Running games always continue; new work is refused when there is no
capacity; abuse is rejected immediately.
- Docker: CPU/memory/pids caps per container (overridable in .env);
uvicorn message size, queue and concurrency limits
- Server abuse limits: connections total/per IP (close 1013), message
rate per connection (token bucket, close 1008 on floods), lobby
creation rate per IP
- Load monitor: event loop lag, CPU of the own cgroup quota and
throttling, with hysteresis (normal/busy/overloaded, severe lag
overloads immediately)
- Admission control: create_lobby and start_game refused while
overloaded or MAX_ACTIVE_GAMES are running; server_status message
broadcast on changes; /health reports load but stays ok
- AI bridge: timeout sent with requests, in-flight cap, circuit breaker
- AI service: bounded workers and queue ("overloaded"), drops expired
requests, degrades to the heuristic agent when busy or too slow
- Website: busy notices, Create/Start disabled when not accepting
games, slow retry when the server is full
- Tests for limiters, load levels, admission control and AI service
limits; docs updated
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Wizard — developer documentation
This folder explains the whole codebase: what each part does, how the parts talk to each other, and why things are built the way they are. It is written to be read top to bottom the first time and used as a reference afterwards.
Reading order
| # | Document | What you learn |
|---|---|---|
| 1 | Architecture overview | The four components, how a move travels through the system, repository layout, key design decisions |
| 2 | Game rules as implemented | Every rule of Wizard as the code implements it, with the exact function that enforces it |
| 3 | Game engine (wizard_game) |
The rules package: cards, the WizardGame state machine, observations, actions, events |
| 4 | Game server (wizard_server/app) |
Sessions, reconnects, lobbies, running games, AI turns, broadcasting, configuration |
| 5 | Protocol reference | Every websocket message between browser ↔ server and server ↔ AI, with examples |
| 6 | Frontend (wizard_website) |
The React app: connection hook, screens, components, styling, build |
| 7 | AI player (wizard_ai) |
Agents, feature encoding, policy interface, training, evaluation, production service — and how to plug in a real model |
| 8 | Deployment, development & operations | Docker, networks, Caddy, environment variables, local setup, tests, troubleshooting, how-to recipes |
The system in one paragraph
A React website lets players create or join a lobby and play. It talks to
the Python game server over one websocket per browser tab. The server keeps
all lobbies and games in memory and uses the game engine (wizard_game, a
dependency-free Python package) to enforce the rules. For every AI seat, the
server asks the AI service over an internal websocket which move to make;
the AI service answers using an Agent (today a heuristic, later a
reinforcement-learning model trained with the same game engine).
flowchart LR
B["Browser<br/>React app"] -- "wss /wizard/api/ws" --> C[Caddy]
B -- "https /wizard/website/" --> C
C -- "/ws, /health" --> S["wizard_server<br/>FastAPI :8083"]
C -- "/assets, /index.html" --> W["wizard_website<br/>nginx :8082"]
A["wizard_ai<br/>AI service"] -- "ws /internal/ai" --> S
S -. uses .-> G[("wizard_game<br/>rules engine")]
A -. uses .-> G
Conventions used in these docs
- File references are relative to the repository root, e.g.
wizard_server/app/lobby.py. - "Seat" or "player index" means the position
0 … n-1of a player at the table. The game engine only knows indices; names and ids live in the server. - Code excerpts are shortened; the source files are the final truth.