--- name: wizwar-audits description: Run the Wiz-War health audits — UI coverage of engine events/cards (the "telepath audit"), live-game ledger inspection by room code, and the pre-deploy determinism gate. Use when asked to audit, when adding cards or events, or when a player reports "the engine did X but I never saw it". --- # Wiz-War audits Three recurring audits keep the maze honest. The first is self-enforcing; the other two are on-demand. ## 1. UI coverage — "the telepath audit" (automated) `packages/engine/test/ui-coverage.test.ts` runs with every `npm test` and fails when: - a GameEvent type has no client handling (no `humanize` case in `net.svelte.ts`, no fx in `fx.ts`, no modal check in `App.svelte`) and is not in the test's `SILENT_BY_DESIGN` allowlist — each allowlist entry needs a reason for why the player sees the information another way; - a card resolver demanding a cell/edge target is missing from App's `CELL_CARDS` / `EDGE_CARDS` click-targeting sets (an unaimable cast). When adding an **event**: give it a `humanize` line at minimum. Private info (`visibleTo` events carrying cards) deserves the `cardReveal` modal in App.svelte — see `handRevealedPrivate` / `cardsStolenPrivate` / `handTakenPrivate` for the pattern. When adding a **card** with a cell or edge target, add it to the App targeting set; with `params`, wire the named-card picker (`NAMED_CARDS` + suggestions) or a bespoke control. The one axis the test cannot judge: whether a `params`-taking card's input UI actually offers sensible choices. Check that by hand when adding one (thief → target's steallables, deja-vu → discard contents, etc.). ## 2. Live-game audit by room code Fetch and replay production ledgers (details in auto-memory `wizwar-fetch-game-files`): scp root@104.236.96.198:/var/lib/wizwar/rooms/.jsonl / Replay with `createGame({playerIds, seed, sets, colors, deckRev})` + `applyCommand` per command line (see `deploy/replay-verify.mjs`). Stop at any seq to inspect full state. To ask why a bot did something, rebuild the state at its turn and call `automatonCommand(viewFor(state, id), style, tier)` — and if its choice differs from the ledger, the engine refused it and the fallback burned the turn (the X2XN pattern). For "which games are open/stalled" sweeps: fetch all `*.jsonl`, replay each, and report phase / round / humans vs bots / last command's `at`. ## 3. Determinism gate (before deploying engine changes) deploy/verify-ledgers.sh 104.236.96.198 Strict-replays every production ledger against the local engine; one refused command fails. A room whose ledger no longer replays becomes unreachable after restart. Rules changes while games are live need a `deckRev` bump plus an engine gate (the convention survives the 2026-08 reset to rev 1).