Files
security-game/TODO.md
T
zwitschi 988d431da8
Full build / Import + headless tests (push) Successful in 41s
Full build / Full desktop build + optional release (push) Skipped
Generate multi-model anchored concepts, drop old Comedy Store refs, and trim the concept gallery
2026-11-03 17:49:48 +01:00

905 lines
66 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# TODO
Work is grouped by theme. Each item should be small enough to complete and verify on its own;
see `AGENTS.md` for the workflow and `MEMORY.md` for the decisions behind these plans.
**Priority order:** 3D model re-evaluation → character development → local map development →
versioned release milestones (0.10.0) → future/deferred work. See `AGENTS.md` §Priority and
Versioning and §Local Blender skills.
The MIT Blender skill pack lives locally at `.agents/skills/blender-skills/` (gitignored). Every
3D workstream below names the skills to load; they are guidance only, and the project contract,
`blender_assets.py audit`/`fit`/`inspect` and the capture gates stay authoritative.
## 3D model re-evaluation
Goal: re-judge every shipped 3D asset against the newly available Blender skill guidance, rank
the real gaps, and fix only what the rankings justify. Evidence comes from three separate sources:
licensed real-location photos, generated concept boards, and build captures. This is an unversioned development track:
it must not change the `npc_base` contract, the renderer or the 0.10.0 release candidate.
Reference material is collected first (section A): local, gitignored, development-only photo
research may use any source the owner authorises (DuckDuckGo image search, street-view frames,
neighbouring properties, buildings across the street) **without the licence gate**. The licence
and privacy gates still apply the moment a frame is promoted into `docs/screens/refs/` or any
committed asset — local `tmp/research/` is the only licence-free zone.
Scope: 8 library characters (`npc_casual`, `npc_jacket`, `npc_coat`, `npc_vest`, `npc_dress`,
`npc_hoodie`, `npc_firefighter`, `npc_guard`), the frozen `npc_base` fallback, 18 gear pieces,
20 library props, 6 generated props, and the three venue families.
**Exit:** `docs/3d-model-review.md` scores every catalogue asset; every P0/P1 is fixed or
explicitly accepted with a measurement; `inspect`/`audit`/`fit`/proportions, the 24-NPC budget
and the capture gates are green; no runtime contract, dependency or release artifact changed
except the rebuilt assets themselves.
### A. Local reference material collection (development-only, gitignored)
*Owner override (2026-11-03):* for local, development-only photo research the licence gate does
**not** apply. Anything downloaded for this track stays under `tmp/research/` (gitignored) and is
never committed, shipped, or used as a committed asset. The moment a frame is promoted to
`docs/screens/refs/<venue>/` it must pass the sidecar licence + privacy gate; local research is the
licence-free zone only.
- [x] Add a DuckDuckGo image-search fetcher: `tools/refcollect.py search <query> --slug <block>
--limit N` downloads top results into `tmp/research/<block>/` with a source-URL manifest
(no licence filter, marked `local_only`/`unchecked-local`), and `sheet` composes a local
contact sheet. Requests go through a token bucket plus polite jittered backoff that honours
`Retry-After`, and send a full Firefox header set. Tests in
`tools/test_refcollect.py`. **Run note:** DDG rate-limits aggressively; space batches and
run the per-venue collection below when the limit clears.
- [ ] Collect Hollywood block reference: El Capitan facade (day/night/close-up), the El Capitan
Theatre marquee + blade sign neighbour, the east retail neighbour, Ovation Hollywood and
other buildings across the boulevard, the Walk of Fame terrazzo and stars, and the premiere
staging/arrival area.
- [ ] Collect Joke Shop / Comedy Store block reference: the black hall facade and signature
canopy, the side parking lot, the neighbouring hotel building and its parking ramp, the
hillside houses and palms directly behind the roofline, the buildings across Sunset
Boulevard, the entrance recess and door hardware, and any street-level context.
- [ ] Collect street-view frames of both blocks (the owner allows street-view captures for local
reference): save the street-level facades, corners and opposite frontages into the same
`tmp/research/<block>/` folders with a note of the capture viewpoint.
- [ ] Build a local contact sheet per block (`tmp/research/<block>/sheet.jpg`) from the collected
frames so the scorecard and the venue review can cite them; keep it in `tmp/` and never
commit it.
- [ ] Record which local frames actually changed a decision in `docs/3d-model-review.md` or the
venue map doc, with the frame filename, but do not commit the image itself. If a frame is
promoted to the committed board, it goes through the normal sidecar gate and `CREDITS.md`.
### B. Baseline, scorecard and routing
- [x] Load `blender-director` plus the per-family specialists before touching geometry, and
record the skill stack and the advice that changed a decision in `docs/3d-model-review.md`.
(Routing, QA severity/verdict, texel-density tiers, character loop criteria and budget rules
recorded in the review doc; MCP-only steps translated to headless flatpak runs.)
- [x] Re-run the neutral NPC baseline (48 frames), the final-context review (96 frames), the
prop gallery and the 24-NPC budget on the current build; keep raw frames in `tmp/` and do
not replace committed sheets until a fix lands. (48/48 and 96/96 frames captured under
`xvfb-run`, none blank; raw sets in `tmp/model-baseline` and `tmp/model-review`; committed
sheets untouched. 24-NPC smoke still 6.94 ms / 168 meshes / 131,616 triangles.)
- [x] Create `docs/3d-model-review.md` with a per-asset scorecard: silhouette, anatomy/proportion,
topology/edge flow, UV/texel density, textures/materials, rig/weights, LOD/impostor,
collision/grounding, export contract, provenance, skill route, verdict (P0/P1/P2/accept).
(Doc created with character/gear/prop/venue tables, verdict columns and a ranked candidate
list; unmeasured cells are marked `—` instead of being guessed.)
- [x] Collect the baseline measurements in one table: `blender_assets.py inspect`, `audit`, `fit`,
`npc_proportions.py`, texel density, triangles/meshes, 24-NPC frame time. (All seven captured;
`texels` and `inspect --json --out` were added to make the measurements repeatable. All 46
assets audit/inspect clean; texel density 64–122 px/m authored, 287–440 effective fabric.)
- [ ] Review the scorecard with the project owner, rank the P0/P1 gaps and decide fix vs accept
per item; record the decision and the reason in the review document.
### C. Character re-evaluation (8 variants + fallback)
*Skill route: `character-artist`, `retopology`, `rigging`, `uv-workflow`, `texture-workflow`,
`materials`, `hair-groom`, `asset-optimization`, `lookdev`, `qa-review`.*
- [ ] Face/head: review eye/mouth loops, cheek/brow/chin transitions and faceting at the 2 m
portrait distance against `character-artist` and `retopology`; write the concrete edits.
- [ ] Hands/grip: re-check palm, finger segments, thumb and gear contact; decide between a
finger-curl rig or the current open hand plus `HAND_ITEM_FORWARD`, and record the limit.
- [ ] Weights/pose: capture idle, walk, sit and wave; inspect shoulder, hip and neck collapse;
fix the worst offenders using `rigging` practice without changing the 13-bone contract.
**Blocked:** the new `capture_npc_pose.gd` reports the seated/walking pose while the saved
frames still show the rest pose; direct bone writes deform the mesh, so this is a staging/
capture discrepancy that may also affect live venue frames. See
`docs/3d-model-review.md` §"Pose evidence is blocked".
- [ ] Rebuild the pose harness from the verified recipe. Established: the pose reaches proxies
and bones (headless test, 273/273), direct bone rotations deform the mesh, and both window
probes and a `SubViewport` + `RenderingServer.force_draw()` probe render the crouch (offscreen
diff 602 at +2/+6/+12 frames, including a re-created avatar). The current harness still
saves rest frames, so its phase/camera/force-draw ordering is the remaining defect. Rebuild
one pose at a time using the recipe in `docs/3d-model-review.md`, verify each pose visually,
then wire the sheets and fill the weights/pose column.
- [ ] UV/texel density: measure the 256² slot maps; decide whether atlas, UDIM or a resolution
change is justified. Do not change `CHAR_MAX_TRIS`/`CHAR_MAX_VERTS` without re-running the
budget smoke and the Web/Compatibility path.
- [ ] Cloth and hair: re-check coat/dress hem clipping and the hair/beard/headgear meshes against
`hair-groom` guidance; decide explicitly whether cloth simulation stays out of scope.
- [ ] Fix only the ranked P0/P1s, one asset family per commit; refresh the comparison sheet and
re-run `inspect`, `audit`, `fit` and `npc_proportions.py` after each fix.
- [ ] Build a licensed real-photo reference board for crowd variety (ages, builds, hair, outer
layers) and record what was adopted; reference only, never traced or repainted.
- [ ] Generate a face/hand concept board for the highest-ranked P1 and compare it with the 0.9.4
baseline before rebuilding anything; keep it development-only and record model and prompt.
- [ ] After each accepted fix, capture front/three-quarter/profile comparisons, add them to the
review sheet, and refresh the README character row.
- [ ] `qa-review` sign-off: a ship/no-ship verdict per variant with accepted limits recorded.
### D. Gear and prop re-evaluation
*Skill route: `prop-artist`, `hard-surface`, `vegetation-artist`, `materials`, `collision-proxy`,
`lod-pipeline`, `qa-review`.*
- [ ] Gear: review the 18 pieces for silhouette, straps/buckles, helmet and lanyard readability;
verify attach space and body clearance with `fit`; rebuild only what fails the scorecard.
- [ ] Props: review the 20 library props plus the 6 generated props for bevels, chamfers,
silhouette, ground contact and shared material language (`prop-artist`, `hard-surface`);
list the rebuilds that are actually worth the triangle budget.
- [ ] Foliage: replace the flat-shaded `_shrub()`/`_tree()` clumps with `vegetation-artist`-style
carded clusters; measure triangles and keep the 60k `LIBRARY_TRIANGLE_BUDGET`.
- [ ] Materials and emissives: `lookdev` pass on bulbs, signs, lanterns, the marquee and the
sedan at day and late; confirm the flashlight stays a tight spot with no beam geometry.
- [ ] Collision: verify every prop collider and navigation obstacle matches its silhouette and
add the missing `collision-proxy` shapes where walking is blocked.
- [ ] Build a real-photo comparison for street furniture (bollard, bench, bin, hydrant, planter,
lamp) and rank the silhouette and proportion mismatches.
- [ ] Rebuild only the mismatched pieces through the assisted Blender pipeline
(`blender_assets.py inspect` → scripted retopo/UV assist → atlas → `audit`/`fit`); document
the exact commands in `docs/asset-tooling.md`.
- [ ] Refresh `sheet_props.jpg`/`sheet_npc_gear.jpg`, the README asset rows and
`docs/blender_previews/README.md` after the rebuilds.
- [ ] Exit: a prop/gear capture sheet, budgets and collision checks pass with no unreviewed asset.
### E. Venue and camera re-evaluation
*Skill route: `environment-artist`, `archviz`, `set-dressing`, `lighting`, `camera-cinematography`,
`lookdev`, `rendering`, `qa-review`.*
- [ ] Facade/venue review: rank the top five shape-language fixes for Hollywood, the Joke Shop and
the TV Studio (`environment-artist`, `archviz`) and check them against the map-budget tests.
- [ ] Lighting: `lighting`/`lookdev` pass on sconces, canopy, marquee and street lamps with
day/late captures; verify local attenuation stays at 1.0 and no constant-falloff light returns.
- [ ] Set dressing: review entrance and sidewalk prop clusters (`set-dressing`) for occlusion,
navigation obstacles and readable storytelling clusters.
- [ ] Camera height: decide 1.7 m gameplay framing vs the ~1.55 m concept frames using
`camera-cinematography`, and record the decision instead of leaving the mismatch open.
- [x] Build the venue three-up boards (real photo | generated concept | current capture):
`tools/three_up.py compose` renders labelled strips into `docs/screens/boards/` (caption
sidecar per board, `rows` emits README rows). Boards committed: El Capitan day, El Capitan
night, Joke Shop day. Tests in `tools/test_three_up.py`.
- [x] Link each committed board from `docs/hollywood-boulevard-map.md` and
`docs/joke-shop-map.md`.
- [ ] Use the generated concept lighting and palette as the target for the `lighting`/`lookdev`
pass, and record the deviations that stay accepted.
- [ ] After the pass, regenerate the venue captures and update README plus both venue documents.
- [ ] Hooded/winter portrait: close the deferred close-up by staging a types 5–7 capture
(`--portrait-type`) or adding a scenario spawn that provides one.
### F. Reference images, concept boards and screenshots
*Skill route: `lookdev`, `lighting`, `environment-artist`, `qa-review`; tooling:
`tools/scene_concepts.py`, `tools/screen_designs.py`, `tools/asset_pipeline.py`.*
Licensed photos are evidence of what a place looks like, generated boards are art-direction
proposals, and captures are proof that the build matches. Keep the three labelled and separate,
and never ship a generated or downloaded image without provenance.
- [x] Create `docs/screens/refs/` with a README and a sidecar template: source URL, author,
licence/attribution, capture or generation date, what it is evidence for, and whether it is
shipped or development-only. (`docs/screens/refs/README.md` defines the layout, naming,
licence and privacy gates and the three-way separation from concepts and captures;
`SIDECAR-TEMPLATE.md` carries the photo table, redaction/permission notes, derived-decision
log and the generated-board reference table. Linked from `docs/screens/README.md`.)
- [x] Hollywood board: five licence-cleared photos (facade day, blade sign, 1922 elevation,
Ovation across street, premiere staging) with a sidecar and per-image purpose, linked from
`docs/hollywood-boulevard-map.md` and credited in `CREDITS.md`. Cropped the foreground crowd
out of the facade shot; EXIF stripped. (`docs/screens/refs/hollywood/`.)
- [x] Joke Shop board: three licence-cleared photos (hillside/canopy block, frontage with palms,
canopy signature band) with a sidecar, linked from `docs/joke-shop-map.md` and credited in
`CREDITS.md`. The CC BY-SA `The Comedy Store.jpg` from the old link list was deliberately not
used; the public-domain frames cover the same evidence. (`docs/screens/refs/joke-shop/`.)
**Removed 2026-11-03:** the committed Comedy Store photo board was replaced by the local-only
`tmp/research/comedy-store/` research set (owner override; see §3D model re-evaluation → A).
- [ ] Find more pictures from the Comedy Store, the Sunset Boulevard block, collect at least five additional shots for reference; do not care about licensing, these images are only stored locally for reference and inference during development. Find pictures from the neighboring hotel building and the street surroundings.
- [ ] Fill the Joke Shop gaps: better visual representation of actual facade, parking lot to the side, neighboring hotel parking ramp and building, night canopy/sign, entrance recess, south-side neighbours, buildings across the street, hillside behind the building, hill detail.
house detail, neighbouring buildings, and any relevant street-level context.
- [x] TV Studio: no separate board — the venue is the same El Capitan Entertainment Centre block as
the Hollywood day shift, restaged for a late-night arrival. The Hollywood board covers both
venues and the premiere-staging photo is the arrival evidence; the reuse is now stated in
`docs/hollywood-boulevard-map.md`, `docs/gameplay.md`, `PLAN.md` and
`docs/development-status.md`.
- [x] Fill the Hollywood gaps that have a clean licence: El Capitan Theatre neighbour and marquee,
Walk of Fame terrazzo band, star close-up, and a night street-lighting context frame (cropped
to remove people and a plate). The board now has nine photos. (CC BY-SA night frame is
redistributed unmodified for study only; the review is recorded in the sidecar.)
- [ ] Remaining Hollywood gap: a licensed **night photograph of the hero facade and blade sign**
(the night frame on the board is a different block, near Vine), plus a sidewalk-level shot of
the steps/door recess and the east retail neighbour. For the committed board the licence gate
stays (no unlicensed Street View or scraped social media); local-only copies of the same
viewpoints go through section A instead.
- [ ] Generate one concept board per venue with `tools/scene_concepts.py generate` (palette, facade
rhythm, lighting), keep raw output gitignored, commit only the selected board, and record the
model, prompt and spend in the sidecar.
- [x] Build a three-up sheet per venue (real photo | generated concept | current build capture) and
use it as the reference for the character, prop and venue verdicts. (Done for the venue
exteriors via `docs/screens/boards/`; character/prop verdicts still use the Blender
preview sheets.)
- [ ] Apply the screenshot rule to every workstream: each accepted fix updates the relevant row in
`README.md` plus the matching docs page (`docs/blender_previews/README.md`,
`docs/screenshots/README.md`, `docs/3d-model-review.md` or the venue map doc).
- [ ] Re-run `tools/check_screenshots.sh` and `python3 tools/check_docs.py` after gallery changes
and record both results in the handoff.
- [ ] Keep AI-generated images out of `assets/` until they are picked, cropped, credited and (for
textures) audited; `CREDITS.md` and ADR-0015 still govern provenance.
### G. Gates and documentation
- [x] Add the measurable checks the review needs (texel density, weight/pose sanity, collider
coverage, LOD/impostor check) as stdlib or GDScript gates where possible; CI stays offline.
(Texel-density gate in `tools/test_blender_assets.py` checks all five slots per character
and the 40–400 px/m authored band plus the 250 px/m fabric floor; the pose→bone contract is
covered by `test_pose_reaches_the_skeleton_bones`; LOD/impostor already has
`test_avatar_mesh_budget_and_lod_swap`. Collider coverage is still open — split below.)
- [x] Add a collider/proxy check: every library prop that blocks walking has a
`StaticBody3D` + `NavigationObstacle3D`, checked against the catalogue.
(`world_builder.gd` tags every library node with a `library_prop` meta and declares the
non-blocking `marquee`/`handrail`/`lantern`/`door` set; two tests in `test_world.gd`
verify placed props (body + shape + avoidance radius, all three venues) and library
dressing (body unless documented exempt). Mutation-checked: removing `_add_prop_collision`
fails 3 tests, dropping `handrail` from the exemption list fails with the exact node.
Suite is 275/275.)
- [x] Add a coverage test so every catalogue asset has a scorecard row and verdict.
(`tools/test_model_review.py`: every `CHARACTERS`/`GEAR`/`PROPS` entry needs a row in
`docs/3d-model-review.md`, and character rows need a non-empty verdict.)
- [ ] Update `docs/blender-assets.md`, `docs/npc-visual-review.md`, `docs/3d-model-review.md`,
`docs/architecture.md` and `AGENTS.md` with the skill routes and the new gates.
- [ ] Record accepted limits and deferred rebuilds in `docs/known-limitations.md` and `MEMORY.md`.
## Character development
Goal: break the eight-character clone effect with four licence-cleared crowd-variety looks while
keeping the frozen `npc_base` bone, tint-slot and gear-attach contract. The procedural generator is
the primary path; Quaternius is a reviewed reference and MakeHuman is deferred to a separate local
development pipeline.
The roster build is deliberately sequenced **after** the 3D model re-evaluation: the new variants
must inherit the reviewed face/hand/gear baseline instead of multiplying whatever it finds.
*Skill route: `character-artist`, `retopology`, `rigging`, `uv-workflow`, `materials`,
`asset-optimization`, `lowpoly-style`, `godot-export`, `qa-review`.*
### Source review and decision
- [x] Research free/open-source character sources and evaluate at least three downloads against
the existing Blender contract. (Measured Quaternius CC0, Kenney CC0, Khronos
CesiumMan/RiggedFigure CC-BY and the MakeHuman CC0 base mesh; none is a drop-in.
Results, local preview sheet and SHA-256 provenance are in
`docs/npc-model-sourcing.md`.)
- [x] Review the sourcing research with the project owner and choose Option A (procedural),
Option B (Quaternius CC0 intake) or Option C (MakeHuman/MPFB body pipeline); record the
decision in an ADR and in `MEMORY.md`. (2026-11-03: extend the procedural generator as the
primary path, keep Quaternius as a reviewed prototype/reference, defer MakeHuman to a
separate local pipeline. Recorded in ADR-0015 and `MEMORY.md`.)
- [x] Add a source licence allow-list and provenance rule: CC0 preferred, CC-BY only with
attribution in `CREDITS.md`, and no service assets whose terms restrict redistribution.
(ADR-0015; the CC-BY research previews are attributed in `CREDITS.md`.)
- [x] Decide whether the external preview sheet stays local under `tmp/` or is committed with
the required CC-BY attribution. (Committed as
`docs/blender_previews/sheet_npc_sources_research.jpg` with Cesium CC-BY attribution;
the project-owned crowd prototype sheet is also committed.)
### Intake and validation
- [x] Add a Blender `inspect` path that imports a GLB, applies node transforms, reports
tris/verts, bounds, bones, materials, UVs and skinning, and lists contract failures.
(`blender_assets.py inspect --file ...` applies parent/object transforms, converts to
Godot Y-up, ignores the importer's bone-shape helper and prints budgets, bones, slots,
UVs, skinning and animations with issues/warnings; `--json` and `--category` supported.
Seven synthetic contract tests added; all 46 library GLBs inspect clean. `audit` remains
the final gate.)
- [ ] Add an `adapt` path for future external assets: scale/ground, weld seams, decimate, map the
five tint slots, and either rebuild the contract armature or record an explicit second-rig
contract. Use `retopology`/`rigging`/`uv-workflow` guidance for the manual steps, but keep
the Quaternius no-go: a contract rebuild needs a proportion warp, so this is not on the
character critical path.
- [ ] Keep `tools/blender_assets.py audit` as the single final gate; add a regression test for the
intake report/adaptation using a deterministic synthetic or licence-cleared fixture.
- [ ] Document the adapter commands and the go/no-go checks in `docs/asset-tooling.md`.
### Quaternius prototype
- [x] Prototype one Quaternius CC0 variant: weld/decimate to budget and capture Idle/Walk
renders. (12,518 imported verts -> 3,199 after weld -> 2,423 / 4,654 tris after a 0.75
decimate; Idle/Walk quality is good. Preview in
`docs/blender_previews/sheet_npc_sources_research.jpg`.)
- [x] Measure the prototype against the `npc_casual` controls: silhouette, rest pose, body
proportions and gear fit. (No-go for a contract rebuild: T-pose 62-bone realistic rig,
~0.96 m hip, ~1.68 m arm span and ~0.153 m shoulder joint do not match the arm-down
13-bone contract. Keep as reference; a second rig/animation path needs its own ADR.)
- [x] Make a go/no-go decision on Option B. (No-go for the current pass; proceed with the procedural
generator and keep Quaternius as a visual/style reference.)
### Roster and runtime
- [x] Approve four crowd-variety looks (build, head silhouette, hair/beard, outer layer and
accessory; no clothing that labels the NPC's behaviour). (`npc_crowd_a` bun/slim/sunglasses,
`npc_crowd_b` bald/broad/beard/shoulder bag, `npc_crowd_c` coat/umbrella, `npc_crowd_d`
hood/cup; prototype sheet committed.)
- [ ] Re-derive the four approved specs against the re-evaluated character baseline (face, hands,
proportions, gear offsets) so the new variants do not reintroduce the gaps the review found.
- [ ] Generate the four variants through the assisted pipeline (procedural generator → `inspect` →
`audit`/`fit`) and capture the result before committing any of them.
- [ ] Add the four approved specs to `CHARACTERS`, build and commit their GLBs/AO maps, and
update the manifest with roles and tint data. Build only the new assets, never a no-op full
rebuild, and remember that `export_filter="all_resources"` packs committed GLBs into the
next release build: keep this off `main` until after the 0.10.0 tag or accept the size.
- [ ] Replace the fixed `character_model_for()` mapping with deterministic per-role pools and add
tests for repeatability and duplicate avoidance (`godot-export` contract check included).
- [ ] Rebuild and verify gear fit for every new variant (`blender_assets.py fit` plus the runtime
gear checks) and re-run `inspect` on the four new GLBs.
- [ ] Build the crowd-variety reference board (licensed street-crowd photos plus AI proposals) and
compare it with the approved Blender prototypes before building; keep proposals
development-only and record them in `docs/npc-model-sourcing.md`.
- [ ] Capture the four new variants in the neutral baseline and a portrait set, add the rows to
`docs/npc-visual-review.md` and the README character row when they land.
### QA and release
- [ ] Run the 24-NPC budget smoke, portrait baseline, gear fit, headless suite and a release build
with the expanded library.
- [ ] Update `CREDITS.md`, `docs/development-status.md`, `docs/npc-visual-review.md` and
`CHANGELOG.md`; record any accepted visual limits.
- [ ] Exit: a reviewed 12-character library passes contract audit, portrait/gear acceptance,
the 24-NPC budget and licence/provenance review without changing the runtime contract.
### Deferred MakeHuman local pipeline
- [x] Evaluate the MakeHuman CC0 base mesh for a later separate local development pipeline.
(19,158 verts / 36,972 tris; scaled to 1.82 m; decimate 0.35 -> 3,780 verts / 6,468 tris;
UVs present, no normals/material groups/rig. Feasible only with retopology, a custom rig and
project-owned clothing; keep out of CI/build.)
- [ ] Decide whether body-shape diversity still matters after the 12-character library lands; if
yes, prototype the local MPFB/MakeHuman pipeline outside the repo and commit only the final
CC0-derived assets with provenance.
## Local map development
Goal: build a local, data-backed map pipeline that can replace or supplement the stylized venue
geometry with licensed OpenStreetMap footprints, 3D building massing, reference-derived photoreal
facades and AI-assisted composition. This is an unversioned development track, not a release gate.
*Skill route: `environment-artist`, `archviz`, `hard-surface`, `geometry-nodes`,
`procedural-modeling`, `vegetation-artist`, `set-dressing`, `lighting`, `materials`,
`texture-workflow`, `lookdev`, `scene-assembly`, `qa-review`.*
### Data, licensing and scope
- [ ] Define the first target block and whether the result replaces, supplements or only informs
the current stylized venue specs (`docs/hollywood-boulevard-map.md`,
`docs/joke-shop-map.md`).
- [ ] Audit OpenStreetMap's ODbL attribution/share-alike obligations and decide whether derived
geometry ships, stays development-only, or needs a separate data layer.
- [ ] Choose an offline OSM extract workflow (Overpass/Geofabrik) and pin the extract date and
query so the map build is reproducible.
- [ ] Evaluate licence-compatible 3D building datasets (OSM Buildings, Overture, CityGML/LOD1–2
or local authority data); record coverage, accuracy, format and redistribution terms.
- [ ] Add a provenance sidecar for every map source and derived asset, including source URL,
licence, capture/extract date and attribution text.
### Reference imagery
**Recent-photo research (2026-11-03):** Commons geosearch around 34.10118/-118.34009 (500 m) plus
category/date sorting shows usable imagery from the last 12 months: Dolby Theatre billboards
(2026-09-30, CC0, 6 frames), Dolby street level and a fresh Walk of Fame star (2026-07-17, CC0),
a Michael Jackson impersonator at the El Capitan frontage (2026-02-25, CC BY-SA 4.0), the Celia
Cruz Square marker and a 2025-09-28 star series (CC0), and a Thunderbolts premiere (2025-04-28,
CC BY-SA 2.0). No recent frame shoots the El Capitan facade straight-on in daylight; the best
facade evidence is still the 2009 CC BY frame. The 8 downloaded candidates are in
`tmp/research/elcapitan-2026/` (gitignored) with `meta.json`; nothing was committed.
- [x] Wire `tools/refboard.py` (standalone, stdlib-only): `search --source search|geo|category`
lists candidates with ISO date, age-in-months and a commit/review/skip licence gate
(`--allow-ccbysa` after a recorded review); `fetch` downloads usable rows into `tmp/` with
spaced requests and writes `meta.json`; `rows` emits SIDECAR + README table rows from the
manifest. Six recent CC0 photos of the block were re-fetched into
`tmp/research/elcapitan-2026-tool/`. Tests in `tools/test_refboard.py` (licence gate, recent
filter, review-row exclusion, row emission).
- [ ] Add a `--max-age-months` filter (default 12) and a `--must-reuse` mode that matches the
folder's existing sidecar entries so a refresh only reports what changed.
- [ ] Research-diff step: keep the last-12-months board as the "current reality" evidence and the
older photos as the geometry evidence, labelled per photo; no sidecar date field needs to
change, only the purpose column.
- [ ] Write a reference shot list per block: facade materials, windows, signage, rooflines,
street furniture, curb cuts and lighting.
- [ ] Download and catalogue **committed** reference images from Wikimedia Commons, local/own
photography or other clearly licensed sources; record author, licence and attribution with
the §F sidecar template. Local-only research that ignores licence limits (DuckDuckGo,
street-view frames, neighbours, across-street buildings) is collected under §A into
`tmp/research/` and is never committed.
- [ ] Separate development-only references from shipped textures; commit only images with clear
redistribution rights and keep the rest under `tmp/` or the ignored reference folders.
- [ ] Build the per-block real-photo board under `docs/screens/refs/<block>/` using the sidecar
template from the 3D review §E, and link it from the venue map documents.
- [ ] Define the photoreal target and a material-derivation workflow (albedo/normal/roughness,
AO, weathering) that matches the existing Compatibility renderer (`texture-workflow`,
`materials`, `lookdev`), with the recent 2026 street frames as the current-reality reference
and the 2009 facade frame as the geometry reference.
### Geometry and AI-assisted composing
- [ ] Prototype OSM footprint import into Blender at game scale and orientation, then compare it
against the current venue footprint/collider layout.
- [ ] Import 3D building massing for the target block, clean the topology and assign LOD bands;
do not import unbounded city-scale meshes into the runtime (`scene-assembly`,
`asset-optimization`, `lod-pipeline`).
- [ ] Build a reusable photoreal facade kit (window bays, cornices, storefronts, awnings, signage)
with `environment-artist`/`hard-surface`/`geometry-nodes` so buildings share materials and
stay inside the venue triangle/material budgets.
- [ ] Run the assisted Blender pipeline end to end on the first block (OSM import → `inspect` →
retopo/UV assist → atlas → `audit`), and document the exact commands in
`docs/asset-tooling.md`.
- [x] Joke Shop building-appearance pass: `dark_stucco` tile (1024 px) promoted via the picks
pipeline and wired into `_build_comedy_store_building`, replacing the grey paver tile so the
hall reads as flat matte charcoal instead of masonry; photo-anchored day concept generated
from the hillside PD frame (the branded frontage photo trips the model's image-recitation
filter — recorded in the concept README); day capture promoted and the three-up board rebuilt.
Test asserts the hall wall carries `dark_stucco`.
- [x] Building-appearance realism pass, measured against the reference set: bring the masonic
facade's material response (limestone value/roughness, joint lines, weathering streaks),
the banner/canopy and marquee materials, and the night emissive balance to the level of the
2009 facade photo and the 2026 street frames; capture before/after and record each delta.
(Ashlar field: `limestone_ashlar` tile, reference-anchored on the facade photo, 768 px over
~4.6 m of wall = ~167 px/m, promoted via the picks pipeline, warm-shifted tint behind
`VENUE_SPECS`. Banner cloth: warm self-light registered with `_marquee_emissive` (0.14 base;
0.28 night / 0.028 day). Marquee sign face + bulbs: warm-incandescent already in the prop
PALETTE, now test-verified to brighten at night via `_marquee_emissive`. Day and night
captures promoted, both three-up boards rebuilt.)
- [ ] Upgrade the facade from flat material bands to photoreal detail: either texture-projected
detail (Path B below) or AI-generated material tiles derived from the facade photo (with
provenance), then verify texel density, tiling and the night look.
- [ ] Integrate the result behind `WorldBuilder.VENUE_SPECS` with colliders, navigation obstacles,
occlusion and the existing day/night materials.
### Generated location imagery
*Skill route: `lookdev`, `lighting`, `environment-artist`, `texture-workflow`; tooling:
`tools/scene_concepts.py`, `tools/asset_pipeline.py`, `tools/screen_designs.py`.*
**Tool plan for reference-anchored generation (plan first, implement after this section's review):**
- [x] Add `scene_concepts.py generate --reference <photo.png>`: attach a licence-cleared real photo
as a source image to the OpenRouter image request (multimodal chat endpoint with a base64
data URL), with a prompt suffix that preserves the photographed facade geometry. Record the
reference file, its licence and page in the `.refgen.json` provenance sidecar next to the
generated frame.
- [x] Extend `generate_textures.generate_image()` with an optional `reference_path` argument
(base64 data URL of the photo); existing call signatures unchanged, and the path is gated by
`scene_concepts._reference_source` requiring a refs-board `SIDECAR.md` row (or an explicit
`--reference-unchecked`). Verified live on the El Capitan day concept anchored on the CC BY
2.0 2009 facade photo; tests in `ReferenceGateTests`.
- [x] Add a sidecar-driven variant pass: `scene_concepts.py anchor --reference <photo>
--treatments day,night,weathered` generates same-framing variants with treatment clauses,
one `.refgen.json` provenance sidecar per frame. Verified live on the facade photo (night +
overcast frames committed; the weathered treatment reads as mild overcast — noted on the
board). Tests in `AnchorTests`.
- [-] Generate facade, street and signage concept frames for the target block
(`scene_concepts.py generate --reference ...`), commit only the selected frames, and record
model, prompt, spend **and source photo** in the block sidecar. (First frame done:
`hollywood_boulevard_entrance_day-v2`, anchored on the facade photo; remaining framings
pending.)
- [ ] Derive palette, lighting and material targets from the real-photo board and the generated
concepts, and record the deltas the facade kit has to close.
- [ ] Generate signage, awning and poster texture candidates with `asset_pipeline.py`; run the
role audit and the `CREDITS.md` provenance check before anything is used in the kit.
- [ ] Compare generated concepts against the licensed photos: where they disagree, the photos win
for shape and the generated board only informs colour, mood and detail density. Human review
stays the acceptance gate, and AI output is never treated as licensed map data.
### QA and exit
- [ ] Compare the data-backed block against the existing screenshots and map documentation; keep
the stylized fallback available.
- [ ] Run the venue triangle/mesh budget, navigation and collider checks, plus day/night capture
comparisons.
- [ ] Capture day/night gallery frames of the new block and add before/after rows to `README.md`
and the venue map documents.
- [ ] Re-run `tools/check_screenshots.sh` after the map swap so the 21-shot gallery reflects the
new geometry, and refresh the `docs/screens/refs/` three-up sheets.
- [ ] Update `docs/architecture.md`, the venue map documents, `docs/asset-tooling.md`,
`docs/development-status.md` and `CHANGELOG.md` when the pipeline ships or a source is
rejected.
- [ ] Exit: one local block is reconstructed from licensed data with reference-derived photoreal
facades, passes performance/navigation/visual QA and has complete provenance; or the
pipeline is rejected with the findings recorded.
## Maintenance and documentation hygiene
Unversioned housekeeping that keeps the planning sources trustworthy. Do these when they block a
task, not on a schedule.
**Status (2026-11-03):** v0.10.0-rc.1 source; three venues; 276 headless + 143 Python tests; the
Hollywood and Joke Shop facade-realism passes landed (`limestone_ashlar`, `dark_stucco`, banner
night emissive, marquee emissive test); reference boards (`hollywood`, `joke-shop`) with sidecars;
three-up boards; `tools/refboard.py` + reference-anchored generation (`--reference`, `anchor`) +
`tools/three_up.py`. Gaussian splatting is deferred to the end of this file.
### Memory and status accuracy
- [x] Trim `MEMORY.md` from ~1088 lines to the durable set: dropped the superseded 2026-11-01
handoff, the v0.2.x host/disk/NSIS/release anecdotes and duplicated release notes; kept the
gotchas (async/event wiring, import order, colliders, RNG, contracts, Godot `--import` cache,
image-recitation filter, capture-harness windowing, bisect zero-area triangles) and the
easter-egg note. Now ~800 lines.
- [x] Re-check the remaining memory claims against code before deleting them; `MAX_LIVE_NPCS` is
still 16 for gameplay while the separate budget smoke spawns 24, so do not "fix" that.
(Verified phase timing is data-driven via `shift_phases`, fixed the stale `REQUIRE_SIGNIN_VIEW`
contradiction and the old 272/108 counts.)
- [x] Fix stale status claims as they are found; add a documentation check or grep note only if
the same class of drift returns. (Counts and the sign-in state corrected on 2026-11-03.)
- [x] Keep the Gap Analysis baseline and the README status line in sync when a test count, version
or feature milestone changes (the baseline was bumped to 276/143 on 2026-11-03).
### Imagery and provenance upkeep
- [ ] Keep `docs/screens/refs/` sidecars, concept-board records and `CREDITS.md` in sync whenever
an image is added, replaced or dropped; photo-anchored concept frames must keep their
`.refgen.json` provenance sidecar (source photo, licence, page, model) next to the frame.
- [ ] Run `python3 tools/check_docs.py` after any gallery or reference-board edit so every tracked
image stays linked from its folder README.
- [ ] Use `tools/refboard.py search/fetch/rows` for new Commons research instead of ad-hoc API
scripts; downloads stay under `tmp/` and only licence-cleared rows (commit/review gate)
reach a board after a sidecar entry.
- [ ] Delete or ignore development-only photos and raw generations once a board is committed; the
repository carries the picks and their provenance, not the working set.
### Godot import-cache hygiene
- [ ] When a new committed texture (`assets/textures/...`, `picks/`) fails to import under the
existing `.godot/` cache, use the scratch-copy import (`rsync --exclude .godot ...` then
`godot --headless --import` and copy back the `.import` + `.godot/imported/*.ctex/.md5`);
never hand-edit the `uid=` in a copied `.import`. Record any new instance in MEMORY.
- [ ] Prefer `tools/scene_concepts.py promote` (or a manual move into `game_ready/v2/` plus a
`PICKS` entry) so new picks follow the same path as `limestone_ashlar` and `dark_stucco`.
### Blender skills upkeep
- [ ] Re-check the installed Blender pack (`version.json`) when updating it and record the version
in `AGENTS.md` if it changes; keep `.agents/` gitignored and `.agents/.gdignore` in place.
- [ ] Prune the skill routes in `AGENTS.md` if a skill stops matching the project (for example if
a future second-rig path makes `rigging`/`animation` guidance authoritative).
## Gap Analysis and 0.x Roadmap
Baseline: **v0.9.6** (2026-11-03). Three playable venues, tutorial/campaign/checkpoint resume,
difficulty/help, audio/accessibility settings, a 24-NPC budget baseline, a complete
escalation/access/radio loop, shift review, the Blender asset library, 276 headless + 143 Python
tests, a 21/21 clean screen-design judge and an optional Forward+ Desktop HQ build. This is the
baseline; 0.10.0-rc.1 is the current candidate source, with release approvals still open.
### Documentation audit (completed 2026-11-01)
- [x] Make `docs/architecture.md` the single architecture source: asset/content pipeline
contracts, runtime venue-switch/fallback flows, deployment/version constraints, quality
requirements, risk register and documentation ownership map.
- [x] Keep command-heavy operational pages separate but subordinate: `docs/asset-tooling.md`,
`docs/blender-assets.md`, `docs/getting-started.md`, `docs/RELEASING.md` and
`docs/smoke-checklist.md` link to architecture rather than acting as parallel sources.
- [x] Remove the obsolete `docs/plan-graphics-v0.6.md` and its links; completed graphics work is
represented by ADR-0013, the asset pipeline section and the changelog.
- [x] Resolve stale claims: README release version/download row, development status
"Forward+ not implemented", and Blender props "not AO-baked".
- [x] Record the documentation ownership rule in `docs/architecture.md` §12: design intent
(`PLAN.md`), mechanics (`gameplay.md`), system architecture/contracts (`architecture.md`),
decisions (ADRs), status (`development-status.md`), roadmap (`TODO.md`), operations
(tooling/release docs).
### Gap register (remaining roadmap)
| Area | Current baseline | Remaining gap | Risk | Milestone |
| --- | --- | --- | --- | --- |
| 3D model re-evaluation | 8 characters, 18 gear, 20+6 props audited against budgets/proportions; no skill-guided scorecard yet | Scorecard, ranked P0/P1 fixes, texel/weight/collider measurements and accept decisions | Unmeasured drift stays in the shipped library | Unversioned |
| Character development | 8-variant library; source/licence review and Quaternius/MakeHuman evaluation complete | Four crowd variants, role pools, gear fit and runtime integration | Repetition remains or external assets break the contract | Unversioned |
| Local map development | Stylized venue geometry and reference maps | OSM/3D data, photoreal references, AI-assisted composition and splat evaluation | Licensing/provenance or performance failure | Unversioned |
| Content and balance | 3 venues with validated 12+ event matrices, recovery events and contextual dialogue | External playtest evidence, balance/fairness pass, event-weight tuning and final content lock | Repetition or unfair outcomes survive into the release candidate | 0.10.0 |
| Dialog/UI | Audited terminology, copy, button states, focus/navigation, modal close, long strings and all 21 screen captures | Keep the capture/compare/judge gate current as content changes | Low; the remaining risk is drift after new UI is added | Complete (0.9.3) |
| Animation/presentation | Procedural pose layers, portrait captures, reduced hem clipping, 8,000/8,000 NPC cap | Thorough NPC silhouette/face/gear/pose/LOD optimization before visual QA | Close-up jank reduces perceived quality | Complete (0.9.4) |
| Audio/accessibility | Procedural ambience/SFX, volume controls, captions/reduce-motion settings, searchable Help | Full accessibility/localization acceptance review, audio caption coverage and P0/P1 fixes | Public release cannot claim accessible play | 0.10.0 |
| Localization | English JSON table, validation and input-generated Help | Pseudo-locale/layout audit and translator workflow sign-off | Text expansion/clipping at release | 0.10.0 |
| Performance/platform | 24-NPC headless budget (6.94 ms), Compatibility/Web/HQ paths | Target hardware matrix, Web/HQ manual profiling, frame-time/memory evidence | Platform-specific drops or startup failures | 0.9.6 / 0.10.0 |
| Save lifecycle | Settings/campaign/history/checkpoint files, atomic writes | Migration fixtures from 0.8/0.9, fresh-install/upgrade verification, rollback instructions | Player progress loss on upgrade | 0.10.0 |
| QA/CI | Headless suite, smokes, screenshot compare, 21/21 judge | Release-candidate smoke matrix, final gallery and release dry run | Regressions escape the release gate | 0.9.6 / 0.10.0 |
| Release/legal | Unsigned desktop/macOS builds, Web/HQ packages | Signing/notarization decision, checksums, AI-asset provenance, credits, privacy/body-camera and rating review | Public release blocked by trust/policy | 0.10.0 |
| Documentation | Architecture/ADR/status/roadmap ownership established | Final README/changelog/status/TODO/smoke-checklist sign-off and known-limitations page | Docs drift at launch | 0.9.6 / 0.10.0 |
| Future 0.x | Stable 0.x feature set | Live replay, more venues, VO/music, image-to-mesh props and seasonal content | Scope creep before release | Unscheduled |
**Current priority:** the unversioned **3D model re-evaluation** runs first because its findings
gate the crowd-variant roster; **Character development** and **Local map development** follow.
The **0.10.0 release candidate** is the next versioned release; content lock, external playtest,
balance, save migration and release/legal sign-off remain tracked there. The source version is
0.10.0-rc.1; the v0.9.6 release is published. Earlier map/NPC/UI/texture/integration passes are
complete and in `DONE.md`.
## Milestone 0.10.0 — Release candidate
Goal: freeze the feature set, prove it with external players, clear release/legal blockers and
verify every distribution path. This remains the next versioned release after the 0.9.x patch
line, but follows the unversioned 3D re-evaluation, character and local-map tracks in planning
order. Only a release-blocking defect from those tracks may enter this milestone before the tag.
### Content lock and external playtest
- [x] Declare a content/feature freeze for 0.10.0; only release-blocking fixes and balance changes
may land after the freeze. (Frozen 2026-11-03 after the 0.9.6 integration
checkpoint; this pass is limited to release reliability, accessibility,
balance evidence and packaging.)
- [x] Produce a release-candidate build with the tutorial, campaign, all three venues, Help,
accessibility settings and checkpoint/resume enabled. (Clean worktree
`a9658ec` built `0.10.0-rc.1`: Linux 161.5 MB, Windows 197.2 MB, macOS
148.0 MB, Web 97.8 MB and HQ 241.6 MB. The Web/HQ archives include the
credits, privacy, accessibility and known-limitations pages; SHA-256
manifests were written; the Linux and HQ binaries launched headless and the
Web index/wasm/pck/docs returned HTTP 200. Not published because external
playtest and legal approval remain open.)
- [ ] Run at least five first-time-player sessions covering the tutorial and one full venue shift;
record where players get stuck, misunderstand evidence or choose disproportionate escalation.
- [ ] Triage findings by severity (P0/P1/P2) and fix every P0/P1 onboarding/accessibility issue;
keep the rest as explicit known limitations or post-0.10 items.
- [ ] Re-run the affected tutorial/campaign smokes after each fix and capture a fresh first-hour
walkthrough for the release notes.
### Balance and fairness pass
- [x] Define measurable targets for routine compliance, access-decision accuracy, peaceful
resolution, justified emergency calls and false-positive/false-negative rates.
(`docs/balance-acceptance.md` defines cohorts, denominators, 36 matrix cells,
seeds, thresholds and matched emergency-first comparisons. Documentation verified;
targets are not measured results.)
- [ ] Run scripted venue sweeps across easy/normal/hard and all four phases; compare outcomes and
tune event weights, reaction tables, compliance and report strictness where targets fail.
- [ ] Review emergency calls against actual danger: no routine behavior should make emergency the
dominant winning move, and genuine threats must remain answerable. Include the
type-derived `_read_npc_truth()` mismatch with observed threats/forced entry;
use independently labelled behavior evidence, not the helper as its own oracle.
- [ ] Verify the reputation grades, debrief explanations and campaign progression still communicate
the de-escalation-first design after tuning.
- [ ] Record the balance evidence and any deliberate exceptions in `docs/development-status.md`
or `MEMORY.md`.
### Save migration and session reliability
- [x] Add fixtures for a 0.8-era settings/campaign/history save and a 0.9.0 checkpoint; verify
migration/default-filling and a clean first launch with no files. (Committed
fixtures under `src/test/fixtures/saves/`; 9 migration/failure tests cover
old settings/campaign/history, the 0.9.0 checkpoint, all three venue
checkpoint round-trips, clean install, corrupt JSON and a blocked atomic
replace. Suite is now 272 tests.)
- [x] Test fresh install → tutorial → campaign → pause → quit → resume → review → next venue on
an isolated user-data directory. (Tutorial and campaign smokes shared one
isolated `XDG_DATA_HOME`; tutorial completion/replay/skip then campaign
resume/review-continue/help both passed. Pause/menu behavior is covered by
`smoke_session_shell.gd`.)
- [x] Test corrupt JSON, partial temp files, missing optional fields and a failed atomic rename;
confirm fallback behavior never destroys a valid save. (Corrupt/partial files
fall back to defaults; a blocked temp path reports an error and leaves the
prior valid settings intact. `_load_json` now uses the non-logging JSON
instance parser.)
- [x] Verify checkpoint resume after all three venues, after an incident, with NPCs at the door and
with flashlight/body-camera/door state set. (The migration suite round-trips a
checkpoint for Hollywood, the Joke Shop and the TV Studio with an open
incident, one NPC row, flashlight/body-camera/door flags; the campaign smoke
resumes a live checkpoint through the real `GameManager`.)
- [x] Document save locations, schema versions, reset behavior and rollback/export instructions in
`docs/getting-started.md` and the release notes. (`getting-started.md` now
documents the four files, version-1 checkpoint, atomic write/fallback,
clean install, reset and backup/rollback.)
### Release engineering and distribution
- [x] Run `tools/build_releases.sh` from a clean checkout and verify Linux/Windows/macOS/Web/HQ
artifact names, sizes and checksums. (Clean worktree `a9658ec` built the
five artifacts listed above; `PUBLISH_DRY_RUN=1` produced and printed
`build/SHA256SUMS-0.10.0-rc.1.txt` without touching the API.)
- [ ] Smoke-test fresh Linux portable/AppImage, Windows portable/installer, macOS unzip/launch,
Web static hosting and Desktop HQ Vulkan fallback on the target matrix.
(Linux portable and Desktop HQ launched headless; Web files served over a
local static server with HTTP 200. AppImage/installer were not built locally
and Windows/macOS launch testing still needs the target matrix.)
- [x] Add a disk-space preflight and retention policy to the release/publish scripts so a full
Gitea host cannot leave a partially uploaded release. (`publish_release.sh`
checks artifact size/free space, writes SHA-256 checksums, supports
`PUBLISH_DRY_RUN`, rolls back uploaded assets/new releases on failure, and
offers opt-in `RETAIN_RELEASES` pruning; dry-run verified.)
- [x] Verify release metadata, tag/version consistency, asset counts and download links; retain
at least the latest 0.8/0.9 releases and document older-asset pruning.
(Source/version and tag are both 0.9.6; all seven published releases carry
5–7 assets, including the retained v0.8.0/v0.8.1/v0.9.0/v0.9.1 line.
`publish_release.sh` documents opt-in `RETAIN_RELEASES` pruning and
`RELEASING.md` describes the seven-release policy.)
- [x] Decide and document whether macOS signing/notarization is required for 0.10.0 or explicitly
remains a future release blocker; record the quarantine instructions either way.
(0.10.0 ships unsigned with quarantine instructions; signing/notarization
remains an explicit public-release blocker in `RELEASING.md` and
`known-limitations.md`.)
### Legal, credits and platform policy
- [x] Audit AI-assisted asset provenance and licenses; record source/model usage and any
redistribution constraints for textures, characters, props and UI art.
(`CREDITS.md` records the Blender/OpenRouter toolchain, default model slugs,
missing per-file generation metadata and the commercial-rights review as an
explicit release blocker.)
- [x] Audit audio/SFX/music licensing (or confirm everything is procedural) and add a credits file.
(All runtime audio is procedural; no external music/SFX files are bundled.
`CREDITS.md` records this.)
- [x] Review body-camera/privacy language, mental-health-crisis representation, age/content rating
and storefront requirements; fix any release-blocking copy or content.
(`PRIVACY.md` clarifies the simulated body camera/local-only data; the
accessibility and known-limitations pages record the remaining
mental-health/rating/storefront review as a release blocker rather than
claiming approval.)
- [x] Add the player-facing credits, known limitations, accessibility statement and privacy note to
the release package/README. (`README.md` links `CREDITS.md`, `PRIVACY.md`,
`docs/accessibility.md` and `docs/known-limitations.md`; the Web and Desktop
HQ package builders copy those documents into the shipped archives.)
- [ ] Mark external legal/storefront approval as complete or explicitly block the 0.10.0 release on it.
### Documentation and visual sign-off
- [ ] Update `README.md`, `PLAN.md`, `docs/architecture.md`, ADRs, `docs/development-status.md`,
`docs/getting-started.md`, `docs/smoke-checklist.md`, `CHANGELOG.md` and this roadmap.
- [ ] Regenerate the full screenshot gallery and realism baselines from the release-candidate
build (not the dev tree) after content lock; run `check_screenshots.sh` and the pinned vision
judge, recording model/spend/verdicts, and refresh the README and venue-doc images.
- [ ] Include the reference/concept boards and the updated asset sheets in the release docs, and
verify every README and docs-page image resolves from the tagged build.
- [ ] Run the manual smoke checklist on every target and attach/link the release-candidate evidence.
- [ ] Verify the tutorial/campaign/help text at maximum font scale and with the longest strings.
- [x] Remove or archive stale plans/notes and confirm no contradictory version/status claims remain.
- [x] Document the character development toolchain in `docs/architecture.md`: base vs library
sources, tool/artifact/gate table, runtime attach/animation contracts and rebuild discipline.
(Added §5 "Character development tooling" plus risk and ownership-map updates;
documentation check passed.)
### Release-candidate QA and exit
- [ ] Run the complete headless suite, Python tooling, tutorial/campaign/session/scenario smokes,
24-NPC budget smoke and release build from a clean checkout.
- [ ] Run the manual QA matrix: fresh install, upgrade, offline launch, gamepad, accessibility
settings, pause/resume, all venues and Desktop HQ fallback.
- [ ] Confirm no P0/P1 defects remain; P2 items must be documented as known limitations or
post-0.10 work.
- [ ] Create the `v0.10.0` version bump, changelog entry and tag; build/publish the release and
verify all assets and download links.
- [ ] Exit: the release candidate is content-locked, externally played, legally reviewed,
documented, reproducibly built, and approved as the 0.10.0 release candidate.
## Roadmap dependencies and risks
- Content volume is the largest schedule risk; tutorial and campaign work must not outrun the
event/dialogue matrix.
- The vision judge is a dev-time aid with an external key/budget; CI must never make it a hard gate.
- Godot version changes can alter lighting/imports; do not combine an engine baseline move with a
content/feature milestone.
- Signed macOS builds and legal/AI provenance are release blockers, not polish.
- Photo-derived map assets add a second provenance risk: downloaded or user-supplied photos can
carry unclear licences, identifiable people, plates and property restrictions. No photo or
splat-derived asset ships without a completed sidecar, consent/licence review and redaction.
- Gaussian-splat training is GPU/disk-heavy and the toolchain churns quickly; keep it offline,
version-pinned and outside CI, and never make a runtime splat renderer a release dependency.
- Keep the de-escalation-first rules and rare-emergency design unchanged while adding progression,
difficulty and feedback.
- The Blender skill pack is local, unversioned guidance; it can drift from the project contract or
assume Blender MCP. Re-verify every adopted technique with `inspect`/`audit`/`fit` and never
make a skill, asset pack or tool version a build or CI dependency.
- The 3D re-evaluation can expand without bound (retopo every head, rig every finger). Cap it with
the scorecard ranking: P0/P1 only, one asset family per commit, and an explicit accept for
everything else.
## Future / deferred (not scheduled)
- [ ] Live 3D body-camera replay; the timeline is text-only today.
- [ ] Additional venues or seasonal events authored from the `content/venues/` resources.
- [ ] Real voice/dialogue audio; ambience, cues and radio crackle are procedural.
- [ ] Swap the primitive prop builder for an image-to-mesh model API behind the same
`assets/models/generated/<prop>.glb` contract.
- [ ] Rare easter eggs/cameos (e.g. Bob Dobbs) only after core content and QA are stable.
## Gaussian splatting evaluation (deferred)
Postponed for further development on 2026-11-03. The local-map track ships the facade kit and
reference-anchored material passes first; this photo-driven pipeline stays an unversioned,
offline study with no runtime or release dependency until an ADR closes it. All licence and
privacy gates below remain in force whenever the track resumes.
### Photo intake and provenance
Gaussian splatting is evaluated as a photo-driven pipeline: licensed or permissioned photos
become a reference, texture source, mesh proxy or distant backdrop. It is an unversioned local
track with no runtime dependency or release gate until the ADR closes it, and it extends the
reference-image licence and privacy gates above rather than replacing them.
- [ ] Define the accepted photo channels: project/team captures, volunteer or user-supplied
photos with written permission, and downloaded images from clearly licensed archives
(Wikimedia Commons, Openverse, Mapillary and similar). Record which channel produced
each reconstruction.
- [ ] Write a one-page capture brief for user-supplied photos: overlapping arc or orbit around
the facade, 60–80% view overlap, 12 MP+ originals, fixed exposure/white balance, HDR and
filters off, no motion blur, no people or plates in frame where avoidable, overcast or
even light, and the facade height/doors/steps included in several frames.
- [ ] Build an intake checklist and provenance sidecar per photo set: contributor, consent or
property permission, licence and attribution text, source URL, capture date, camera/lens,
location, faces/plates/interiors present, redactions applied, file hashes and whether the
set is shipped or development-only.
- [ ] Set the licence gate: own photos need an explicit contributor licence; CC0/CC BY are
preferred; CC BY-SA triggers a share-alike review for derived textures and meshes; reject
Street View, social-media scrapes, unlicensed commercial imagery and AI-upscaled copies of
unknown originals. Attribution must be feasible in `CREDITS.md` before use.
- [ ] Set the privacy gate: blur or remove faces, minors, licence plates, screens, private
interiors and anything behind a closed door; obtain property permission where required;
keep a redacted copy as the reconstruction input and never commit the originals.
- [ ] Treat downloaded photo sets as sparse and of unknown intrinsics. Use them for reference,
palette and texture study, or as extra training views; do not expect a usable splat from
10–30 casual web photos of a facade.
- [ ] Keep photos, masks, COLMAP databases, checkpoints and splats outside git; commit only
derived, licensed, provenance-stamped assets that pass the review gate.
### Reconstruction and alignment
- [ ] Pin a reproducible offline toolchain (for example COLMAP or GLOMAP for camera poses plus
gsplat, OpenSplat, Nerfstudio or Brush for training), with exact versions, GPU/VRAM/disk
needs and known failure modes recorded in the sidecar.
- [ ] Reconstruct two quality tiers: a dense 100–400-photo arc/orbit capture and a sparse
10–30-photo downloaded set. Record camera-registration rate, training time, splat count,
file size and held-out PSNR/SSIM/LPIPS for both.
- [ ] Mask sky, people, vehicles and moving foliage before training; verify the masks do not
erase facade edges, signage or window detail, and keep the redacted input variant.
- [ ] Align the splat to game coordinates from the OSM footprint plus surveyed points (door
width, column spacing, step rise, storefront height) and record alignment residuals in a
Blender scene containing both the splat and the current venue geometry (`scene-assembly`).
- [ ] Judge quality from held-out views and a render from the game's day/night camera poses
(`camera-cinematography`, `lookdev`, `qa-review`), not from training views alone; reject
splats that only look correct from the capture path.
- [ ] Maintain a coverage map per block: which facades, corners and rooflines have usable views,
and which areas must fall back to the facade kit or stylized geometry.
### Map enhancement paths
- [ ] **Path A — Reference and QA (lowest risk):** render the splat from game camera poses and
compare it with the realism captures; derive dimensions, signage placement, facade rhythm
and material colours. No splat data reaches the runtime.
- [ ] **Path B — Texture derivation:** project splat renders **or reference photos** onto the
facade kit to produce albedo, normal, roughness and AO candidates; de-light and bake them
(`texture-workflow`), then verify UV scale, tiling and readability under the Compatibility
renderer. Deriving directly from a committed reference photo requires its licence to allow
derived works and a `CREDITS.md` entry; CC BY-SA sources stay out unless reviewed.
- [ ] **Path C — Mesh proxy:** extract a mesh from the splat or dense reconstruction, retopo and
dress it in Blender (`retopology`, `prop-artist`), assign LODs (`lod-pipeline`), and keep it
inside the venue triangle/material budgets with mesh-based colliders (`collision-proxy`).
- [ ] **Path D — Distant backdrop:** test a baked panorama, impostor or billboard generated from
the splat for skyline and opposite-street depth where the player cannot walk; measure file
size, loading and visible pop at the venue boundary.
- [ ] **Path E — User-photo supplement:** let a small supplied photo set improve one facade or
landmark (a signage patch, colour reference or hero detail) without rebuilding the venue;
define the minimum evidence and the same licence/privacy/review gate as a full capture.
- [ ] For every path record quality gain versus effort, licence compatibility of the derived
output, and whether the result may ship or stays development-only. Prefer the cheapest
path that closes the visible gap.
### Runtime evaluation and decision
- [ ] Probe Godot 4.7.2 Compatibility and Web support for splat rendering in a throwaway scene:
addon or importer availability, shader/sort cost, memory, load time and fallback behaviour.
Do not add a splat dependency to the release project during evaluation.
- [ ] Set hard limits before any runtime experiment: maximum per-splat file size and total
memory, allowed frame-time delta on the 24-NPC budget scene, acceptable Web load time, and
no compute-shader requirement for the Compatibility/Web path.
- [ ] Keep collision and navigation mesh-based even if a splat is displayed; a splat must never
become the playable floor or the access/occlusion authority.
- [ ] Write the ADR with a per-path go/no-go, the accepted licence/provenance rules, whether each
result ships or stays development-only, rejected alternatives and the evidence bundle.
- [ ] Exit: one licensed photo capture measurably improves a venue through a documented path and
passes visual, performance and provenance review; or the approach is rejected with
reproducible findings and removed from the release path.