Scaffold project and author 14-phase roadmap

Browser co-op kitchen game: FastAPI + native WebSockets, server-authoritative
20 Hz simulation, in-memory anonymous lobbies, data-driven YAML levels, Canvas 2D
vanilla ES-module client with locally authored SVG art and no external CDNs.

.agents/PLAN.md records the LOCKED decisions; .agents/user_stories/ holds the 12
flow contracts; .agents/phases/todo/ breaks them into 14 sequential, test-gated
phases (71 task files), each leaving the app launchable and the suite green.

LLM-Generated: true
This commit is contained in:
2026-10-05 17:05:56 -04:00
commit f84c6ebaef
105 changed files with 5752 additions and 0 deletions
@@ -0,0 +1,29 @@
# US-09 — Drop out and come back mid-round
**As a** player on flaky Wi-Fi (or a locked laptop),
**I want to** reconnect and land back in the same kitchen mid-round,
**so that** one dropped socket does not ruin the group's game.
## Acceptance criteria
1. Losing the socket keeps the player's seat for `GUEST_IDLE_TIMEOUT_S` (default 45 s);
the cook stays in the kitchen and, after 3 s idle, parks and drops what they carried.
2. The other players see a "Cookie disconnected" label, not a vanished cook.
3. Reconnecting with the same token + code mid-round restores the seat and resumes
snapshots; time-to-playable ≤ 3 s after page load.
4. The client shows a "reconnecting…" overlay with exponential backoff (0.5 s → 8 s cap,
jittered) and never spams the server.
5. Reconnecting after the grace window releases the seat and the player re-enters as a
spectator (or joins the lobby if one exists).
6. The server never leaves a ghost connection: a second socket for a token evicts the
first, and closed rooms reject stale tokens with a clean error.
7. A room whose last seat is gone is closed and its resources freed within one GC cycle.
8. A mid-round server-side room exception aborts only that room and tells its players.
## E2E suite
`tests/e2e/test_us09_disconnect_rejoin.py` — kill the socket (context.close of page B /
server-side `kill_connection` test hook), assert ghost label, reload and rejoin mid-round,
assert playable ≤ 3 s and identical score. Integration: seat grace, GC, stale-token paths.
## Phases
`06_realtime_websocket_protocol`, `08_client_prediction_and_touch`,
`12_reconnect_resilience_and_scale`