Claim TODO tasks with [-]; promote mockups to assets/images/ui

- AGENTS.md now requires agents to mark a task [-] while claimed/in progress and
  only use [x] after implementation and verification, with an example
- copied the 21 reference mockups from docs/screens/designs/ into the runtime
  root assets/images/ui/ (byte-identical names); docs/screens/designs/ stays as
  the reference-only copy per ADR-0014
- MEMORY records where the copies live and that screen_designs.py still reads
  the docs tree until the code-path migration

First storage-restructure TODO item completed.
This commit is contained in:
zwitschi committed 2026-11-01 15:47:35 +01:00
1 parent 8f228b0c56
commit f458551594
24 files changed
+79 -24

No files matched your search

+5 -1
View File
@@ -39,6 +39,10 @@ All planned implementation work must be represented in `TODO.md`.
- Use checkbox items for each concrete task. - Use checkbox items for each concrete task.
- Keep tasks small enough to complete and review independently. - Keep tasks small enough to complete and review independently.
- Add new tasks when discoveries expand the scope. - Add new tasks when discoveries expand the scope.
- When starting a task, claim it for the agent workflow by changing `[ ]` to `[-]`. Keep it `[-]`
while implementation or verification is in progress; only change it to `[x]` after the work and
relevant checks are finished. If work is abandoned or blocked, leave a clear note and return the
item to `[ ]` (or add a follow-up task).
- Mark a task complete only after the implementation and relevant verification are finished. - Mark a task complete only after the implementation and relevant verification are finished.
- If any verification check fails, do not mark the task complete. Fix the failure, or if it cannot be fixed, add a follow-up task to `TODO.md`, record the failure in `MEMORY.md`, and report it in the handoff summary. - If any verification check fails, do not mark the task complete. Fix the failure, or if it cannot be fixed, add a follow-up task to `TODO.md`, record the failure in `MEMORY.md`, and report it in the handoff summary.
- Do not use prose status updates as a substitute for checkboxes. - Do not use prose status updates as a substitute for checkboxes.
@@ -52,7 +56,7 @@ Recommended format:
## Core Gameplay ## Core Gameplay
- [ ] Add player movement controls. - [ ] Add player movement controls.
- [ ] Implement NPC approach behavior. - [-] Implement NPC approach behavior. (claimed; implementation/verification in progress)
- [x] Define escalation levels. - [x] Define escalation levels.
## Documentation ## Documentation
+19
View File
@@ -43,6 +43,9 @@ Session memory for durable decisions, state, and gotchas. Keep concise, remove o
`docs/screens/designs/` and `docs/screens/concepts/` stay reference-only; QA captures stay in `docs/screens/designs/` and `docs/screens/concepts/` stay reference-only; QA captures stay in
`docs/screenshots/`. When a mockup becomes runtime art, copy/process it into `assets/images/` `docs/screenshots/`. When a mockup becomes runtime art, copy/process it into `assets/images/`
with a new name (no overwrites) and keep a fallback in code. with a new name (no overwrites) and keep a fallback in code.
**Mockup copies:** 21 design references were copied to `assets/images/ui/` (byte-identical
filenames); `docs/screens/designs/` remains the reference-only copy. `tools/screen_designs.py`
still reads the docs tree until the code-path task moves it; keep the two in sync meanwhile.
## Handoff (read this first) ## Handoff (read this first)
@@ -135,6 +138,22 @@ Session memory for durable decisions, state, and gotchas. Keep concise, remove o
flat plane, so avoidance (not a baked mesh) routes guests around props. Placements live in flat plane, so avoidance (not a baked mesh) routes guests around props. Placements live in
`PROP_PLACEMENTS` with `placement_problems()` validation; variants come from `variant_for(index)`. `PROP_PLACEMENTS` with `placement_problems()` validation; variants come from `variant_for(index)`.
`smoke_props.gd` must be windowed because the guard reads captured-mouse input. `smoke_props.gd` must be windowed because the guard reads captured-mouse input.
- **Realism pass tooling (2026-11-01):** `tools/scene_concepts.py` (`list`/`generate`/`process`/
`audit`/`realism`) never overwrites an image (`next_free_path` adds `-vN`; `process` skips
existing targets). Raw AI output: `assets/textures/ai/v2/raw/` (gitignored). Candidate pool:
`assets/textures/ai/game_ready/v2/` (gitignored except the validated picks un-ignored in
`.gitignore`: skyline day-v4/dusk-v3/night-v4 plus brick/pavers/asphalt/asphalt_wet + normals).
Concepts: `docs/screens/concepts/` (committed, `.gdignore`, targets in its README). Runs:
`docs/screens/realism/<run>/` (PNG captures gitignored; `report*.{json,md}` + `sheet.jpg`
committed). `src/test/capture_realism.gd` swaps textures at runtime by the material's
*original* albedo path (`--swap/--night-swap/--tint/--normal=OLD=NEW`) and writes to
`--out=res://...`. Changing game code is not needed for an A/B test. Gotchas:
gpt-5-image-mini honours `background=transparent` for the 3:2 skyline requests, but it writes
garbled "HOLLYWOOD" lettering unless the prompt forbids signs. Skyline strips are 2:1 to match
one UV repeat of the ring. `elapsed_s = 620` gives the *Evening* phase (pink sky), not night.
The gemini-flash-lite realism scores are noisy (±1–2), and the judge sometimes returns a 400
"API key not valid" from the provider, which the one retry covers. None of the v2 assets are
wired into the game yet.
- **Blender asset library (v0.6.0, integrated 2026-11-01):** - **Blender asset library (v0.6.0, integrated 2026-11-01):**
`tools/blender_assets.py` (`build`/`render` in Blender; `audit`/`sheet`/`list` stdlib) writes `tools/blender_assets.py` (`build`/`render` in Blender; `audit`/`sheet`/`list` stdlib) writes
`assets/models/blender/{npc,npc_gear,props}/*.glb`, `manifest.json` (integration source of `assets/models/blender/{npc,npc_gear,props}/*.glb`, `manifest.json` (integration source of
+55 -23
View File
@@ -1,7 +1,7 @@
# TODO # TODO
Godot 4.3 prototype. Latest release **v0.6.0** (Blender character/gear/prop library, baked AO, environment lift). Godot 4.3 prototype. Latest release **v0.6.0** (Blender character/gear/prop library, baked AO, environment lift).
Headless suite **222/222** plus **69** Python tooling tests; the session, PLAN-verb, crowd, emergency, Headless suite **222/222** plus **81** Python tooling tests; the session, PLAN-verb, crowd, emergency,
timeline, audio, scenario-content, props, NPC-budget, movement, and windowed focus/radial smokes timeline, audio, scenario-content, props, NPC-budget, movement, and windowed focus/radial smokes
pass. Anonymous downloads are enabled on the host. pass. Anonymous downloads are enabled on the host.
@@ -25,7 +25,7 @@ and scene visuals with those mockups — verified with
- [x] Decide the canonical runtime image root (`assets/images/` for UI/scene art): recorded in - [x] Decide the canonical runtime image root (`assets/images/` for UI/scene art): recorded in
`MEMORY.md` and [ADR-0014](docs/adr/0014-runtime-image-root.md). `MEMORY.md` and [ADR-0014](docs/adr/0014-runtime-image-root.md).
- [ ] Move the reference mockups from `docs/screens/designs/` into the runtime root (keep `docs/screens/designs/` as a docs-only copy or replace it with the new path). - [x] Move the reference mockups from `docs/screens/designs/` into the runtime root (keep `docs/screens/designs/` as a docs-only copy or replace it with the new path).
- [ ] Document one convention for game vs reference vs development images across `assets/textures/`, `assets/images/`, `assets/models/generated/`, `docs/screenshots/`, and `docs/screens/designs/`. - [ ] Document one convention for game vs reference vs development images across `assets/textures/`, `assets/images/`, `assets/models/generated/`, `docs/screenshots/`, and `docs/screens/designs/`.
- [ ] Re-run `godot --headless --path . --import` to regenerate `.import` sidecars after any move. - [ ] Re-run `godot --headless --path . --import` to regenerate `.import` sidecars after any move.
- [ ] Confirm `.gitignore` still excludes development-only outputs (concepts, Blender sources, raw AI fabrics) under the new layout. - [ ] Confirm `.gitignore` still excludes development-only outputs (concepts, Blender sources, raw AI fabrics) under the new layout.
@@ -80,77 +80,109 @@ measure the in-game result against that target with the screenshot tools. Plan:
**Rule for every step: never overwrite an existing image.** New outputs get new paths. When a **Rule for every step: never overwrite an existing image.** New outputs get new paths. When a
path is taken, the tools pick the next free `-vN` suffix. Raw AI output stays on disk under path is taken, the tools pick the next free `-vN` suffix. Raw AI output stays on disk under
`assets/textures/ai/v2/raw/` (gitignored like the other raw AI folders). Processed game-ready `assets/textures/ai/v2/raw/` (gitignored like the other raw AI folders). Processed game-ready
candidates go to `assets/textures/ai/game_ready/v2/`, scene references to `docs/screens/concepts/`, candidates go to `assets/textures/ai/game_ready/v2/`, a local pool where only the validated picks
and trial captures and reports to `docs/screens/realism/<run>/`. are tracked (ADR-0014). Scene references go to `docs/screens/concepts/`, and trial captures and
reports to `docs/screens/realism/<run>/`.
### Step 1 — Tooling (`tools/scene_concepts.py`) ### Step 1 — Tooling (`tools/scene_concepts.py`)
- [ ] Add a catalogue of prompts in three groups: `scene` (16:9 example 3D game frames), - [x] Add a catalogue of prompts in three groups: `scene` (16:9 example 3D game frames),
`backdrop` (4:1 skyline panoramas with transparent sky), and `texture` (seamless PBR `backdrop` (4:1 skyline panoramas with transparent sky), and `texture` (seamless PBR
surface tiles). Each entry has a name, prompt, role and target path. surface tiles). Each entry has a name, prompt, role and target path.
- [ ] `generate [--group] [--only] [--variants N]`: call the OpenRouter image API through - [x] `generate [--group] [--only] [--variants N]`: call the OpenRouter image API through
`generate_textures.generate_image` (key from the repo `.env`), save raw output, and never `generate_textures.generate_image` (key from the repo `.env`), save raw output, and never
overwrite (`next_free_path`). Print every file written. overwrite (`next_free_path`). Print every file written.
- [ ] `process`: turn raw backdrops into 2048×512 RGBA strips that tile horizontally (edge - [x] `process`: turn raw backdrops into 2048×512 RGBA strips that tile horizontally (edge
crossfade, sky made fully transparent, hard alpha for the alpha-scissor material). Turn raw crossfade, sky made fully transparent, hard alpha for the alpha-scissor material). Turn raw
textures into seamless 1024² tiles (`asset_pipeline.make_seamless`) plus a normal map textures into seamless 1024² tiles (`asset_pipeline.make_seamless`) plus a normal map
(`make_normal_maps.normal_map`). Skip outputs that already exist. (`make_normal_maps.normal_map`). Skip outputs that already exist.
- [ ] `audit`: run `asset_pipeline.audit_image` on the processed candidates (`backdrop` / - [x] `audit`: run `asset_pipeline.audit_image` on the processed candidates (`backdrop` /
`tile` roles) and fail on any bad result. `tile` roles) and fail on any bad result.
- [ ] `realism`: for each trial capture, report the Pillow detail metrics (edge density, - [x] `realism`: for each trial capture, report the Pillow detail metrics (edge density,
contrast, colour spread, saturation) next to the matching concept image. Optionally ask a contrast, colour spread, saturation) next to the matching concept image. Optionally ask a
vision model (`google/gemini-2.5-flash-lite`) for 0–10 realism scores (lighting, vision model (`google/gemini-2.5-flash-lite`) for 0–10 realism scores (lighting,
materials, texture detail, backdrop, overall) with concrete fixes. Write a new JSON + materials, texture detail, backdrop, overall) with concrete fixes. Write a new JSON +
Markdown report per run. Markdown report per run.
- [ ] Unit tests (`tools/test_scene_concepts.py`): catalogue shape, the no-overwrite path - [x] Unit tests (`tools/test_scene_concepts.py`): catalogue shape, the no-overwrite path
picker, backdrop/tile processing on synthetic images, metrics, and the judge payload/parse picker, backdrop/tile processing on synthetic images, metrics, and the judge payload/parse
(offline, no network). (offline, no network).
### Step 2 — Example 3D scene images ### Step 2 — Example 3D scene images
- [ ] Generate 3D-game-style example frames for every venue and time of day: Hollywood entrance - [x] Generate 3D-game-style example frames for every venue and time of day: Hollywood entrance
(morning, golden hour, rainy night), boulevard skyline view (day, dusk), Joke Shop alley (morning, golden hour, rainy night), boulevard skyline view (day, dusk), Joke Shop alley
(evening, close-up of the door), studio stage door (night arrival), sidewalk material (evening, close-up of the door), studio stage door (night arrival), sidewalk material
close-up, entrance steps and podium, crowd-control barrier line, and a responder arrival close-up, entrance steps and podium, crowd-control barrier line, and a responder arrival
wide shot. wide shot.
- [ ] Review the set and record the visual targets each frame sets (sky, haze, material detail, - [x] Review the set and record the visual targets each frame sets (sky, haze, material detail,
backdrop depth) in the report. backdrop depth) in the report.
### Step 3 — Backgrounds (replace the outdated skyline) ### Step 3 — Backgrounds (replace the outdated skyline)
- [ ] Generate skyline panoramas for day, dusk and night (lit windows): Hollywood/Los Angeles - [x] Generate skyline panoramas for day, dusk and night (lit windows): Hollywood/Los Angeles
mid-rise blocks, palm silhouettes, the hills on the horizon, a transparent sky, and a mid-rise blocks, palm silhouettes, the hills on the horizon, a transparent sky, and a
straight-on view, in several variants each. straight-on view, in several variants each.
- [ ] Process them into `assets/textures/ai/game_ready/v2/skyline_{day,dusk,night}.png`, - [x] Process them into `assets/textures/ai/game_ready/v2/skyline_{day,dusk,night}*.png`,
seamless horizontally for the 3× UV repeat around the backdrop ring. seamless horizontally for the 3× UV repeat around the backdrop ring. Strips are 2048×1024
(2:1, one UV repeat of the 400×60 m ring is about 133×60 m). 12 candidates, 11 audit
clean; `skyline_day-v3` misses the seam limit by 0.6. Variants 1–2 contain garbled
"Hollywood" lettering, so the prompt now forbids signs. Picks: `skyline_day-v4`,
`skyline_dusk-v3`, `skyline_night-v4`.
### Step 4 — Textures ### Step 4 — Textures
- [ ] Generate higher-detail seamless tiles: red brick facade, granite/limestone facade - [x] Generate higher-detail seamless tiles: red brick facade, granite/limestone facade
(studio), sidewalk concrete pavers with joints, asphalt with aggregate, wet night asphalt, (studio), sidewalk concrete pavers with joints, asphalt with aggregate, wet night asphalt,
stone steps, striped awning canvas, and stucco wall. stone steps, striped awning canvas, and stucco wall.
- [ ] Process them into 1024² game-ready tiles plus normal maps in - [x] Process them into 1024² game-ready tiles plus normal maps in
`assets/textures/ai/game_ready/v2/` and audit them. `assets/textures/ai/game_ready/v2/` and audit them (16 tiles + 16 normals, all good). The
`awning_canvas` seam crossfade smears the stripes at the tile edge; it needs a
stripe-aligned crop.
### Step 5 — In-game trial captures (no game-code change) ### Step 5 — In-game trial captures (no game-code change)
- [ ] Add `src/test/capture_realism.gd`. It boots the Hollywood venue, captures a fixed shot - [x] Add `src/test/capture_realism.gd`. It boots the Hollywood venue, captures a fixed shot
list (entrance day, boulevard/skyline day, boulevard night), and can swap textures at list (entrance day, boulevard/skyline day, boulevard night), and can swap textures at
runtime from `--skyline=` / `--brick=` / `--concrete=` / `--asphalt=` user arguments. The runtime from `--skyline=` / `--brick=` / `--concrete=` / `--asphalt=` user arguments. The
swap finds materials by their current texture, so baseline and candidate frames use the swap finds materials by their current texture, so baseline and candidate frames use the
same camera. Writes to `user://screenshots/realism/<tag>/`. same camera. Writes to `user://screenshots/realism/<tag>/`.
- [ ] Capture the baseline (current assets) and the candidate set (v2 skyline + textures), and - [x] Capture the baseline (current assets) and the candidate set (v2 skyline + textures), and
copy them into `docs/screens/realism/<run>/{baseline,candidate}/`. copy them into `docs/screens/realism/<run>/{baseline,candidate}/`.
### Step 6 — Compare against the realistic target ### Step 6 — Compare against the realistic target
- [ ] Run `scene_concepts.py realism` on baseline and candidate. Record the metric deltas and the - [x] Run `scene_concepts.py realism` on baseline and candidate. Record the metric deltas and the
vision scores, and note which candidate textures/backdrops win. vision scores, and note which candidate textures/backdrops win. Run
- [ ] Note the remaining realism gaps (sky/fog, lighting, building geometry, NPC fidelity) as `docs/screens/realism/2026-11-01-v2/` (`report-v2.md`, `sheet.jpg`) gives these mean
judge scores: backdrop 2.6 → 3.6 (v2 day + night skyline) → **4.0** (v2 day + dusk
skyline for the Evening phase), texture detail 1.2 → 1.6–1.75, overall 1.6 → 2.0. Single
scores swing by ±1–2 between runs, so read them as trends. The `characters` score
moved from 3.0 to 1.0 with identical NPCs, which shows the noise.
- [x] Note the remaining realism gaps (sky/fog, lighting, building geometry, NPC fidelity) as
follow-up tasks below. follow-up tasks below.
### Step 6b — Follow-ups from the 2026-11-01 realism report
- [ ] Fix sidewalk overexposure: the concrete reads near-white in every day shot, while the
concepts keep the ground mid-grey. Lower the albedo tint or the sun energy, or add tonemap
exposure in `Materials.configure_environment`.
- [ ] Make the Evening/Late phases darker and lit by practical lights (marquee, lamps,
windows), and add wet-asphalt roughness at night, as in the rain-night concept.
- [ ] Choose the skyline per phase (day → `skyline_day`, Evening → `skyline_dusk`, Late →
`skyline_night`) and lower the fog density on the backdrop so the night windows show.
- [ ] Raise the backdrop plane (60 m → ~90 m) or use 2 UV repeats so the skyline is not a
thin strip at the horizon.
- [ ] Add facade depth (plinth, cornice, window reveals) and replace the blob trees and shrubs
with denser foliage meshes (Blender library follow-up).
- [ ] Re-cut `awning_canvas` so its stripes align at the tile edge.
- [ ] Capture shots from the Joke Shop and the studio too (add them to `capture_realism.gd` /
`SHOTS`).
### Step 7 — Adopt the winners (after the in-flight normal-map/AO work is committed) ### Step 7 — Adopt the winners (after the in-flight normal-map/AO work is committed)
- [x] Track the validated picks in place (ADR-0014). `game_ready/v2/*` is a gitignored local
pool; `.gitignore` un-ignores the skyline picks and the brick/pavers/asphalt (+ wet) tiles
and their normals. Never replace the existing `game_ready/` files.
- [ ] Point `WorldBuilder.T_SKYLINE` at the chosen v2 skyline (separate day/night textures through - [ ] Point `WorldBuilder.T_SKYLINE` at the chosen v2 skyline (separate day/night textures through
`set_night_mode`), and retune `albedo_color` for the realistic strip. `set_night_mode`), and retune `albedo_color` for the realistic strip.
- [ ] Switch `materials.gd` / `world_builder.gd` surface preloads to the chosen v2 tiles + normal - [ ] Switch `materials.gd` / `world_builder.gd` surface preloads to the chosen v2 tiles + normal
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1007 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1004 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1000 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 954 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 910 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 971 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1021 KiB