ui-coverage.test.ts fails the suite the moment an engine event has no client handling (allowlist entries require a written reason) or a cell/edge-targeting card is missing from the board's aim sets — the one-at-a-time bug reports become a red test instead. The wizwar-audits skill documents the three house audits (UI coverage, ledger inspection by room code, the determinism gate); .claude/skills/ joins the repo so they travel with it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
60 lines
2.8 KiB
Markdown
60 lines
2.8 KiB
Markdown
---
|
|
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/<CODE>.jsonl <scratchpad>/
|
|
|
|
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).
|