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`.
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
// Undercooked — the wire enums (phase 07 task 03).
|
||||
//
|
||||
// The client's vocabulary for the sim's StrEnums (src/undercooked/sim/model.py)
|
||||
// and the protocol's `ErrorCode` (src/undercooked/server/protocol.py). The
|
||||
// wire carries the *string values* (a StrEnum's `.value`); these frozen sets
|
||||
// are what `net/decode.js` maps against and what a frame's values are
|
||||
// checked against.
|
||||
//
|
||||
// Drift is a build failure, not a surprise: `tests/unit/test_client_enum_parity.py`
|
||||
// reads this file and asserts each set is set-equal to the Python enum, in
|
||||
// both directions (the same guard pattern as `test_protocol_doc_sync.py`).
|
||||
// Add a value to the sim and forget it here (or vice versa) and the gate
|
||||
// fails, naming the missing value.
|
||||
|
||||
/** The terrain under a grid cell (`TileKind`). */
|
||||
export const TILE_KIND = Object.freeze([
|
||||
"floor",
|
||||
"counter",
|
||||
"wall",
|
||||
"void",
|
||||
]);
|
||||
|
||||
/** The kitchen fixture types (`StationKind`). */
|
||||
export const STATION_KIND = Object.freeze([
|
||||
"spawn_shelf",
|
||||
"chop_board",
|
||||
"stove",
|
||||
"prep",
|
||||
"serve",
|
||||
"sink",
|
||||
"trash",
|
||||
]);
|
||||
|
||||
/** Ingredient / dish types (`ItemKind`). */
|
||||
export const ITEM_KIND = Object.freeze([
|
||||
"tomato",
|
||||
"onion",
|
||||
"lettuce",
|
||||
"dough",
|
||||
"patty",
|
||||
"rice",
|
||||
"fish",
|
||||
"plate",
|
||||
]);
|
||||
|
||||
/** The preparation stage of an item (`ItemForm`). */
|
||||
export const ITEM_FORM = Object.freeze([
|
||||
"raw",
|
||||
"chopped",
|
||||
"cooking",
|
||||
"cooked",
|
||||
"burnt",
|
||||
"plated",
|
||||
"dirty",
|
||||
]);
|
||||
|
||||
/** The four directions; the wire's `f` is an index into this list (PLAN §4: 0-3). */
|
||||
export const FACING = Object.freeze(["up", "right", "down", "left"]);
|
||||
|
||||
/** The transient FX/log event kinds (`EventKind`; `encode_events`' `k`). */
|
||||
export const EVENT_KIND = Object.freeze([
|
||||
"chopped",
|
||||
"cooked",
|
||||
"ready",
|
||||
"served",
|
||||
"burnt",
|
||||
"order_missed",
|
||||
"fire_started",
|
||||
"denied",
|
||||
"score",
|
||||
"stunned",
|
||||
"washed",
|
||||
"trashed",
|
||||
"round_end",
|
||||
"wasted",
|
||||
"picked",
|
||||
"dropped",
|
||||
"handed_off",
|
||||
"trashed_already_empty",
|
||||
"tick_slow",
|
||||
"err",
|
||||
"resync",
|
||||
"ghost_on",
|
||||
"ghost_off",
|
||||
"ghost_park",
|
||||
]);
|
||||
|
||||
/** The stable rejection codes (`ErrorCode`, docs/PROTOCOL.md "Error codes"). */
|
||||
export const ERROR_CODE = Object.freeze([
|
||||
"unknown_type",
|
||||
"bad_json",
|
||||
"bad_field",
|
||||
"too_big",
|
||||
"rate_limited",
|
||||
"not_seated",
|
||||
"not_host",
|
||||
"level_locked",
|
||||
"wrong_state",
|
||||
"room_full",
|
||||
"room_gone",
|
||||
"protocol_mismatch",
|
||||
"evicted",
|
||||
"internal",
|
||||
]);
|
||||
|
||||
// The extras the renderer (task 04) needs. Not in the parity gate's
|
||||
// seven, but the same discipline applies: the wire's short strings.
|
||||
|
||||
/** What a cook is doing this tick (`PlayerState`; the wire's `s`). */
|
||||
export const PLAYER_STATE = Object.freeze([
|
||||
"idle",
|
||||
"moving",
|
||||
"using",
|
||||
"stunned",
|
||||
"disconnected",
|
||||
]);
|
||||
|
||||
/** A station's lifecycle (`StationState`; the wire's `s`). */
|
||||
export const STATION_STATE = Object.freeze([
|
||||
"idle",
|
||||
"working",
|
||||
"ready",
|
||||
"busy",
|
||||
"dirty",
|
||||
"blocked",
|
||||
]);
|
||||
|
||||
/** The hazard families (`HazardKind`; the wire's `t`). */
|
||||
export const HAZARD_KIND = Object.freeze([
|
||||
"fire",
|
||||
"spill",
|
||||
"moving_obstacle",
|
||||
"rush",
|
||||
]);
|
||||
|
||||
/** The terminal outcome of a round (`RoundResult`). */
|
||||
export const ROUND_RESULT = Object.freeze(["won", "lost", "aborted"]);
|
||||
Reference in New Issue
Block a user