Files
undercooked/.agents/phases/complete/06_realtime_websocket_protocol/00_phase.md
T
ducoterra f26849c1f3 phase: 06_realtime_websocket_protocol
All green. Final verification complete — writing the report.

**Final pass report — phase 06 `realtime_websocket_protocol`**

- Verified: all 6 task files present in `complete/`; this was the final verification pass (no implementation work outstanding)
- `uv run ruff check .` → all checks passed; `uv run pyright` → 0 errors
- `uv run undercooked-levels validate` → content OK; `uv run pytest` (full suite) → **1751 passed, 0 failed, coverage 97.30% (>90% floor)**; slow sim stage (`-m slow tests/sim --no-cov`) → 2 passed; repo hygiene clean
- App launches: `/healthz` 200, `/` 200, `/api/levels`, `/api/config`, `POST /api/rooms` (201), `/api/stats` all verified live on an ephemeral port (server cleaned up)
- Criteria: scripted client room→hello→ready→start→countdown→≥20 snaps→round — PASS (`test_ws_round_two_clients.py`); identical `round` payloads both clients — PASS (`round_a == round_b`); version mismatch → `err protocol_mismatch` + close `4400` — PASS; 64 KB refused / 4 KB boundary, 500-burst → `rate_limited` → `4404` with bounded queue, 2000 malformed + 200 handshakes within memory bound — PASS; snap ≤ 1.5 KB (4p/4o/3h) and 64×64 ≤ 4 KB, downlink ≤ 60 KB/s over 100 ticks — PASS; `docs/PROTOCOL.md` model-sync test-enforced in both directions + full-round sequence diagram present — PASS
- Docs: README.md had 3 stale spots — status section (claimed 01–05 complete, 06 pending → now 01–06 complete, 07 pending), "until phases 06/07 wire the transport" wording, and the `PROTOCOL.md` layout note ("phase 06 completes it"). All fixed. AGENTS.md verified consistent — no changes needed
- No defects found in completed phases; no live infrastructure touched

Next pending phase: `07_canvas_client_and_hud`.
2026-10-09 11:13:25 -04:00

3.9 KiB

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