Files
undercooked/AGENTS.md
T
ducoterra f84c6ebaef 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
2026-10-05 17:05:56 -04:00

6.3 KiB

AGENTS.md — operating rules for this repository

1. Read this order, every time

  1. .agents/PLAN.md — master design. Its Architectural Anchors table holds the LOCKED DECISIONS, which are binding on every task and phase.
  2. This file.
  3. .agents/phases/todo/<phase>/00_phase.md, then the task file you are executing.
  4. The user story referenced by the phase (.agents/user_stories/US-XX_*.md).
  5. .agents/phases/complete/*/00_phase.md for what already exists (do not re-build it).

2. The phased protocol

  • Phase state lives in files, not chat. Pending work: .agents/phases/todo/NN_name/ (00_phase.md + NN_task.md). Finished work: .agents/phases/complete/.
  • Execution is owned by the phased-execution skill (run-task.sh, run-phase.sh, auto-phase.sh). Each task runs in a fresh subprocess and must pass .agents/validate.sh before it moves to complete/.
  • New work is authored by the phase-authoring skill as a phase directory — not implemented straight from chat.
  • Never modify .agents/PLAN.md or anything under .agents/phases/complete/.
  • Ask the user before editing an existing file in .agents/phases/todo/.
  • Do not renumber or reuse phase/task numbers.

3. LOCKED DECISIONS (summary — the table in PLAN.md is authoritative)

  • Python 3.12+ / uv / FastAPI / native WebSockets (uvicorn[standard]). No Socket.IO, no SSE, no WebRTC, no REST for live game traffic.
  • Server-authoritative fixed-tick simulation (20 Hz) with client interpolation. The browser never decides anything true. src/undercooked/sim/ is pure: no FastAPI, no asyncio, no I/O, no wall-clock, no random without the round RNG.
  • No database, no ORM, no Alembic. Live state lives in the room supervisor; results/scoreboards live in memory and die with the process. User-approved deviation from the default FastAPI stack.
  • Data-driven content. Levels/recipes/hazards come from YAML in levels/ loaded through validated Pydantic models. No hard-coded level or recipe lists in Python.
  • Client: Canvas 2D + vanilla ES modules + this repo's own SVG art. No bundler, no framework, no CDN, no analytics, no external fonts.
  • Tests: pytest + Playwright. One Playwright suite per user story; multi-player stories use two browser contexts against one room.
  • Quality gate: ruff + pyright + full pytest, >90% coverage on new/modified code, entire suite 100% passing before a phase may complete or commit.

4. Definition of done (every task)

  • Task's own work exists at the named paths and is importable/runnable.
  • Tests written for the task's logic (unit for pure logic, integration for rooms/protocol, e2e for user-visible flows) and passing.
  • Full project suite passes (uv run pytest), coverage gate met — including failures the task did not cause: fix them, do not skip, xfail, or delete tests.
  • uv run ruff check . and uv run pyright report zero errors.
  • uv run undercooked-levels validate passes if any level/content file changed.
  • README.md and AGENTS.md updated when the change is user-visible (setup, commands, config, protocol, features, conventions). Every phase's final pass re-reviews both in full, project-wide and fixes inconsistencies, including pre-existing ones.
  • App still launches: uv run undercooked serves http://127.0.0.1:8000/healthz with 200 and the client at /.
  • No behavior regression in any completed phase.

5. Hard rules

  • No external CDNs or remote assets. tests/unit/test_no_external_assets.py fails the build on http:///https://///cdn references in app/static/ and templates. CSP is default-src 'self' (plus ws:/wss: same-origin).
  • No new technology (dependency, framework, service) without explicit written user permission recorded in the phase's 00_phase.md and signed off into PLAN.md.
  • The simulation is the single source of truth. Client-side values are guesses. Never trust inbound coordinates, scores, timers, or level ids — validate every inbound field against the room's state (server/protocol.py).
  • Anonymous by design. No accounts, no emails, no cookies with personal data. Identity = a random per-browser token (secrets.token_urlsafe) held in sessionStorage. Names are sanitized, length-capped, non-authoritative.
  • Frame and rate limits are enforced, not suggested: max_message_bytes, max_inputs_per_s, room caps, and message-type whitelists per room state.
  • Protocol changes need a version bump: editing a wire message means editing src/undercooked/server/protocol.py, docs/PROTOCOL.md, and the client in the same task, and bumping PROTOCOL_VERSION (PLAN §11).
  • Determinism is a contract. sim/step.py must produce identical state given the same seed and input script — the replay tests in tests/sim/ are the guard.
  • ntfy is outbound-only. Never use it to ask questions or wait for approval. If a task is ambiguous, make the best judgment consistent with PLAN.md, or stop and let the user rewrite the task.
  • Commits are made by the pipeline harness (PHASE_COMMIT=1), one atomic commit per completed phase, --no-gpg-sign, subject phase: <NN_name>. Child executors never run git add/commit/mv/rm/stash. When a human asks for a commit, use the git-commit skill (--no-gpg-sign, LLM-Generated: true trailer).
  • Do not commit .env, logs, coverage output, .agents/phase-sessions/, .agents/pipeline.log, or .agents/reports/ (all gitignored).

6. Where things go

Change Location
Pure game rules (movement, stations, orders, scoring, hazards) src/undercooked/sim/
Level/recipe content levels/*.yaml
Rooms, lobby lifecycle, session records src/undercooked/server/rooms.py, room.py
Wire messages + validation src/undercooked/server/protocol.py, docs/PROTOCOL.md
HTTP app, static serving, headers src/undercooked/server/app.py
Renderer, HUD, input, interpolation app/static/js/, app/static/assets/
User-visible flow contract .agents/user_stories/US-XX_*.md

Tests mirror that: tests/unit/, tests/server/ (HTTP routes and stores), tests/integration/ (live uvicorn + WebSocket clients), tests/sim/ (headless determinism and replays), tests/e2e/ (Playwright, named test_usNN_*.py, marked e2e).