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`.
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user