Files
ducoterra 95ca3fd1fa phase: 07_canvas_client_and_hud
**Final report — phase 07 final verification pass**

- **Verified:** all 5 tasks present in `complete/`; app boots (`/healthz` 200, `/` 200, static + atlas + `/api/levels` served); `docs/CLIENT.md` module map matches the on-disk `app/static/` tree; no code defects found.
- **Tests/lint/coverage:** `bash .agents/validate.sh` → ruff clean, pyright 0 errors, `undercooked-levels validate` pass, **full pytest 1838 passed, 97.21% coverage (floor 90%)**, slow sim stage 2 passed, repo hygiene clean. `uv run pytest tests/e2e -q` → **53 passed** (all 8 suites added this phase).
- **Criteria:** (1) two tabs create→join→ready→start→serve one dish, keyboard only — green via `test_us01/02/03/04` ✔; (2) e2e green ✔; (3) canvas non-blank, pixels change after a move — `test_us04_render_smoke` ✔; (4) HUD score within 200 ms of the `served` event — asserted, green ✔; (5) zero console errors + zero off-origin requests — `test_atlas_loads` / `test_us01_landing_surface` ✔; (6) `docs/CLIENT.md` matches layout ✔; (7) 100% suite + 97.21% ✔; (8) docs pass below ✔; (9) no regression in completed phases (all prior suites green) ✔.
- **README.md fixed:** status still said "next pending phase is 07" → now 07 complete, 08 pending; the phase-07 client text buried in the phase-05 bullet → its own "canvas client, art, HUD (phase 07)" bullet; stale "What does not exist yet" (claimed movement/controls missing) → rewritten to phases 08–14; "once the room flow ships" → "live in the browser today"; Layout `app/static/` "renderer arrives with the rest of phase 07" → full shipped-client map; Layout `docs/` "CLIENT lands with phase 07" → `CLIENT.md` listed; added `gen_art_index.py` Layout entry.
- **AGENTS.md fixed:** "the eight screens" (7 listed) → "the seven screens" (+ `dom.js` is the shared builder, not a screen); e2e naming line → notes the non-story guard `test_atlas_loads.py`.
- **Decisions:** no code changes were needed; only the two doc fixes above. Docs re-verified by `test_docs_commands`/`test_docs_index` (44 passed) plus the final full gate.
- **Next pending phase:** `08_client_prediction_and_touch`.
2026-10-10 18:03:52 -04:00

528 lines
8.3 KiB
JSON

{
"cook-1-down-0": {
"file": "cooks.svg",
"h": 32.0,
"w": 32.0
},
"cook-1-down-1": {
"file": "cooks.svg",
"h": 32.0,
"w": 32.0
},
"cook-1-left-0": {
"file": "cooks.svg",
"h": 32.0,
"w": 32.0
},
"cook-1-left-1": {
"file": "cooks.svg",
"h": 32.0,
"w": 32.0
},
"cook-1-right-0": {
"file": "cooks.svg",
"h": 32.0,
"w": 32.0
},
"cook-1-right-1": {
"file": "cooks.svg",
"h": 32.0,
"w": 32.0
},
"cook-1-up-0": {
"file": "cooks.svg",
"h": 32.0,
"w": 32.0
},
"cook-1-up-1": {
"file": "cooks.svg",
"h": 32.0,
"w": 32.0
},
"cook-2-down-0": {
"file": "cooks.svg",
"h": 32.0,
"w": 32.0
},
"cook-2-down-1": {
"file": "cooks.svg",
"h": 32.0,
"w": 32.0
},
"cook-2-left-0": {
"file": "cooks.svg",
"h": 32.0,
"w": 32.0
},
"cook-2-left-1": {
"file": "cooks.svg",
"h": 32.0,
"w": 32.0
},
"cook-2-right-0": {
"file": "cooks.svg",
"h": 32.0,
"w": 32.0
},
"cook-2-right-1": {
"file": "cooks.svg",
"h": 32.0,
"w": 32.0
},
"cook-2-up-0": {
"file": "cooks.svg",
"h": 32.0,
"w": 32.0
},
"cook-2-up-1": {
"file": "cooks.svg",
"h": 32.0,
"w": 32.0
},
"cook-3-down-0": {
"file": "cooks.svg",
"h": 32.0,
"w": 32.0
},
"cook-3-down-1": {
"file": "cooks.svg",
"h": 32.0,
"w": 32.0
},
"cook-3-left-0": {
"file": "cooks.svg",
"h": 32.0,
"w": 32.0
},
"cook-3-left-1": {
"file": "cooks.svg",
"h": 32.0,
"w": 32.0
},
"cook-3-right-0": {
"file": "cooks.svg",
"h": 32.0,
"w": 32.0
},
"cook-3-right-1": {
"file": "cooks.svg",
"h": 32.0,
"w": 32.0
},
"cook-3-up-0": {
"file": "cooks.svg",
"h": 32.0,
"w": 32.0
},
"cook-3-up-1": {
"file": "cooks.svg",
"h": 32.0,
"w": 32.0
},
"cook-4-down-0": {
"file": "cooks.svg",
"h": 32.0,
"w": 32.0
},
"cook-4-down-1": {
"file": "cooks.svg",
"h": 32.0,
"w": 32.0
},
"cook-4-left-0": {
"file": "cooks.svg",
"h": 32.0,
"w": 32.0
},
"cook-4-left-1": {
"file": "cooks.svg",
"h": 32.0,
"w": 32.0
},
"cook-4-right-0": {
"file": "cooks.svg",
"h": 32.0,
"w": 32.0
},
"cook-4-right-1": {
"file": "cooks.svg",
"h": 32.0,
"w": 32.0
},
"cook-4-up-0": {
"file": "cooks.svg",
"h": 32.0,
"w": 32.0
},
"cook-4-up-1": {
"file": "cooks.svg",
"h": 32.0,
"w": 32.0
},
"cook-carry": {
"file": "cooks.svg",
"h": 32.0,
"w": 32.0
},
"cook-stun": {
"file": "cooks.svg",
"h": 32.0,
"w": 32.0
},
"fx-chop": {
"file": "fx.svg",
"h": 32.0,
"w": 32.0
},
"fx-deny": {
"file": "fx.svg",
"h": 32.0,
"w": 32.0
},
"fx-flame": {
"file": "fx.svg",
"h": 32.0,
"w": 32.0
},
"fx-score": {
"file": "fx.svg",
"h": 32.0,
"w": 32.0
},
"fx-serve": {
"file": "fx.svg",
"h": 32.0,
"w": 32.0
},
"fx-splash": {
"file": "fx.svg",
"h": 32.0,
"w": 32.0
},
"fx-steam": {
"file": "fx.svg",
"h": 32.0,
"w": 32.0
},
"item-dough-burnt": {
"file": "items.svg",
"h": 32.0,
"w": 32.0
},
"item-dough-chopped": {
"file": "items.svg",
"h": 32.0,
"w": 32.0
},
"item-dough-cooked": {
"file": "items.svg",
"h": 32.0,
"w": 32.0
},
"item-dough-cooking": {
"file": "items.svg",
"h": 32.0,
"w": 32.0
},
"item-dough-raw": {
"file": "items.svg",
"h": 32.0,
"w": 32.0
},
"item-fish-burnt": {
"file": "items.svg",
"h": 32.0,
"w": 32.0
},
"item-fish-chopped": {
"file": "items.svg",
"h": 32.0,
"w": 32.0
},
"item-fish-cooked": {
"file": "items.svg",
"h": 32.0,
"w": 32.0
},
"item-fish-cooking": {
"file": "items.svg",
"h": 32.0,
"w": 32.0
},
"item-fish-raw": {
"file": "items.svg",
"h": 32.0,
"w": 32.0
},
"item-lettuce-burnt": {
"file": "items.svg",
"h": 32.0,
"w": 32.0
},
"item-lettuce-chopped": {
"file": "items.svg",
"h": 32.0,
"w": 32.0
},
"item-lettuce-cooked": {
"file": "items.svg",
"h": 32.0,
"w": 32.0
},
"item-lettuce-cooking": {
"file": "items.svg",
"h": 32.0,
"w": 32.0
},
"item-lettuce-raw": {
"file": "items.svg",
"h": 32.0,
"w": 32.0
},
"item-onion-burnt": {
"file": "items.svg",
"h": 32.0,
"w": 32.0
},
"item-onion-chopped": {
"file": "items.svg",
"h": 32.0,
"w": 32.0
},
"item-onion-cooked": {
"file": "items.svg",
"h": 32.0,
"w": 32.0
},
"item-onion-cooking": {
"file": "items.svg",
"h": 32.0,
"w": 32.0
},
"item-onion-raw": {
"file": "items.svg",
"h": 32.0,
"w": 32.0
},
"item-patty-burnt": {
"file": "items.svg",
"h": 32.0,
"w": 32.0
},
"item-patty-chopped": {
"file": "items.svg",
"h": 32.0,
"w": 32.0
},
"item-patty-cooked": {
"file": "items.svg",
"h": 32.0,
"w": 32.0
},
"item-patty-cooking": {
"file": "items.svg",
"h": 32.0,
"w": 32.0
},
"item-patty-raw": {
"file": "items.svg",
"h": 32.0,
"w": 32.0
},
"item-plate-dirty": {
"file": "items.svg",
"h": 32.0,
"w": 32.0
},
"item-plate-plated": {
"file": "items.svg",
"h": 32.0,
"w": 32.0
},
"item-plate-raw": {
"file": "items.svg",
"h": 32.0,
"w": 32.0
},
"item-rice-burnt": {
"file": "items.svg",
"h": 32.0,
"w": 32.0
},
"item-rice-cooked": {
"file": "items.svg",
"h": 32.0,
"w": 32.0
},
"item-rice-cooking": {
"file": "items.svg",
"h": 32.0,
"w": 32.0
},
"item-rice-raw": {
"file": "items.svg",
"h": 32.0,
"w": 32.0
},
"item-tomato-burnt": {
"file": "items.svg",
"h": 32.0,
"w": 32.0
},
"item-tomato-chopped": {
"file": "items.svg",
"h": 32.0,
"w": 32.0
},
"item-tomato-cooked": {
"file": "items.svg",
"h": 32.0,
"w": 32.0
},
"item-tomato-cooking": {
"file": "items.svg",
"h": 32.0,
"w": 32.0
},
"item-tomato-raw": {
"file": "items.svg",
"h": 32.0,
"w": 32.0
},
"station-chop_board": {
"file": "stations.svg",
"h": 32.0,
"w": 32.0
},
"station-pan": {
"file": "stations.svg",
"h": 32.0,
"w": 32.0
},
"station-pot": {
"file": "stations.svg",
"h": 32.0,
"w": 32.0
},
"station-prep": {
"file": "stations.svg",
"h": 32.0,
"w": 32.0
},
"station-serve": {
"file": "stations.svg",
"h": 32.0,
"w": 32.0
},
"station-sink": {
"file": "stations.svg",
"h": 32.0,
"w": 32.0
},
"station-spawn_shelf": {
"file": "stations.svg",
"h": 32.0,
"w": 32.0
},
"station-stove": {
"file": "stations.svg",
"h": 32.0,
"w": 32.0
},
"station-stove-burning": {
"file": "stations.svg",
"h": 32.0,
"w": 32.0
},
"station-stove-off": {
"file": "stations.svg",
"h": 32.0,
"w": 32.0
},
"station-stove-ready": {
"file": "stations.svg",
"h": 32.0,
"w": 32.0
},
"station-stove-working": {
"file": "stations.svg",
"h": 32.0,
"w": 32.0
},
"station-trash": {
"file": "stations.svg",
"h": 32.0,
"w": 32.0
},
"tile-counter": {
"file": "tiles.svg",
"h": 32.0,
"w": 32.0
},
"tile-floor": {
"file": "tiles.svg",
"h": 32.0,
"w": 32.0
},
"tile-floor-1": {
"file": "tiles.svg",
"h": 32.0,
"w": 32.0
},
"tile-floor-2": {
"file": "tiles.svg",
"h": 32.0,
"w": 32.0
},
"tile-floor-3": {
"file": "tiles.svg",
"h": 32.0,
"w": 32.0
},
"tile-floor-4": {
"file": "tiles.svg",
"h": 32.0,
"w": 32.0
},
"tile-void": {
"file": "tiles.svg",
"h": 32.0,
"w": 32.0
},
"tile-wall": {
"file": "tiles.svg",
"h": 32.0,
"w": 32.0
},
"ui-crown": {
"file": "ui.svg",
"h": 32.0,
"w": 32.0
},
"ui-ghost": {
"file": "ui.svg",
"h": 32.0,
"w": 32.0
},
"ui-ready": {
"file": "ui.svg",
"h": 32.0,
"w": 32.0
},
"ui-star": {
"file": "ui.svg",
"h": 32.0,
"w": 32.0
},
"ui-streak": {
"file": "ui.svg",
"h": 32.0,
"w": 32.0
},
"ui-ticket": {
"file": "ui.svg",
"h": 32.0,
"w": 32.0
}
}