# Phase 06 — Realtime WebSocket protocol **Story:** `US-02_join_by_code`, `US-03_ready_up_and_start`, `US-05_orders_score_and_result` (delivery), `US-09_disconnect_and_rejoin` (partial) **Context:** `.agents/PLAN.md` §7 (protocol), §4 (data flow, snapshot), A3, A4, A14 ## Objective Put the tested room core on the wire: `/ws/{code}` with a versioned JSON protocol, strict inbound validation (shape, size, rate, per-state legality), input ingestion with sequence numbers, and snapshot/event broadcasting at the configured rate — so two browsers can already play a round. This is the last phase before the game becomes visible. ## Dependencies - `05_anonymous_lobbies_and_room_lifecycle` (complete) — supervisor, `Room`, lobby payloads, session store - `04_kitchen_pipeline_and_scoring` (complete) — sim state and result payloads to encode ## Tasks 1. `01_protocol_models_and_wire_contract.md` — `server/protocol.py`, message models, `docs/PROTOCOL.md`, protocol version 2. `02_ws_endpoint_and_handshake.md` — `/ws/{code}`, origin/token checks, caps, error codes, single-socket-per-token 3. `03_input_ingestion_and_validation.md` — `input` handling, seq discipline, clamping, per-state whitelist 4. `04_snapshot_and_event_encoding.md` — `server/encoding.py`, quantized snapshots, event batching, `SNAPSHOT_HZ` pacing, size budget 5. `05_heartbeat_disconnect_and_seat_grace.md` — heartbeats, seat grace on drop, ghost parking, rejoin within the window 6. `06_websocket_integration_suite.md` — two-socket full round, malformed flood, rate limit, size cap, latency injection flag ## Testing & Quality - Unit: every protocol model's accept/reject surface; encoder quantization and size; whitelist per room state; seq stale/rollback rules. - Integration (real WebSockets via `TestClient`/`websockets` against a live uvicorn on an ephemeral port): handshake, welcome shape, `ready`→`start`→`countdown`→`snap` stream, two clients both reach the same `round` payload, unknown message types, oversized frame, message flood, wrong protocol version close code `4400`, second socket evicts first, abrupt close keeps the seat for the grace window and a reconnect resumes snapshots. - Budget tests: encoded snapshot ≤ 1.5 KB for a 4-player level-1 state; downlink ≤ 60 KB/s per player over a measured 5 s window. - Coverage: **>90%** on new/modified code; `server/protocol.py`, `server/encoding.py` ≥ 95%. - The phase is "Complete" only when the **entire** project test suite passes 100%. ## Documentation & Consistency - The final pass reviews `README.md` and `AGENTS.md` in full against the project as it stands after this phase — fixing every inconsistency found, **including pre-existing ones not caused by this phase**. - `docs/PROTOCOL.md` is the deliverable contract: message tables, close codes, error codes, size/rate limits, versioning policy, and a sequence diagram of a full round. Every field in code must appear in the doc (a test compares model field sets to the doc tables). ## Completion Criteria - [ ] a Python `websockets` client can: create room over HTTP → connect `/ws/{code}` → `hello` → `ready` → host `start` → receive `countdown` then ≥ 20 `snap` frames → drive a scripted input to `round` - [ ] two clients in one room receive identical `round` payloads - [ ] protocol version mismatch closes with code `4400` and a clean client message - [ ] oversized (> `max_message_bytes`) and flood (> `max_inputs_per_s`) cases are refused with the documented error/close codes and no memory growth - [ ] snapshot ≤ 1.5 KB and downlink ≤ 60 KB/s measured by tests - [ ] `docs/PROTOCOL.md` matches the implemented models (test-enforced) and includes the round sequence diagram - [ ] full test suite **100% passing**, coverage >90% - [ ] README.md and AGENTS.md are accurate and consistent with the whole project (verified in the final pass) - [ ] no behavior change in completed phases