CB-WP-0011-T02: cb-play --inspect walks a recorded game
Renders the table after every step of a .cbreplay bundle or a scenario YAML, from any seat's projection or a spectator's. This is the first thing in the project that answers 'what did the table look like when it went wrong?' without adding a dbg! and re-running. INTERFACE CHANGE (flagged per InnerLoop chaos limits -- this is a tier-S pass that touched a runtime crate): cb-game-runtime gains replay::open, extracted out of replay::replay. Dev-only, behind the scenarios feature, no type changed. The point of the extraction is that the inspector and the replay gate share one bundle reader, controls included, so the inspector cannot show a state a replay never reached. Three M-D1-MUT controls, each red for its stated reason. The load-bearing one asserts one rendered table per step: without it, a walk that rendered nothing would still report a matching hash.
This commit is contained in:
parent
d2ca1046c0
commit
b11fc91fd4
4 changed files with 478 additions and 22 deletions
|
|
@ -133,7 +133,7 @@ while writing the gate, before it had ever been committed.
|
|||
|
||||
```task
|
||||
id: CB-WP-0011-T02
|
||||
status: todo
|
||||
status: done
|
||||
priority: high
|
||||
state_hub_task_id: "08f8a9c7-3dfe-4f72-b510-df9efa457370"
|
||||
```
|
||||
|
|
@ -160,6 +160,35 @@ must not show anyone else's. The stage-0 test that checked this was
|
|||
vacuous twice before it held (CB-EV-0007); seat the assertion where the
|
||||
hidden thing is actually hidden.
|
||||
|
||||
**Done 2026-08-02.** `cb-play --inspect PATH [--as SEAT|spectator]`
|
||||
walks a `.cbreplay` bundle or a scenario YAML and renders the table after
|
||||
every step.
|
||||
|
||||
The design decision worth recording: `replay::replay` was split, and its
|
||||
bundle reader extracted as `replay::open`, so **the inspector walks
|
||||
through the same reader the replay gate uses** — including the control
|
||||
that makes the recorded seed load-bearing. A second reader would let the
|
||||
inspector show states a replay never reached, and it would be a
|
||||
duplicated fact in the one place where being wrong is silent. The hash is
|
||||
then asserted anyway, because a structural argument that is never
|
||||
executed is the class of claim this project keeps finding to be wrong.
|
||||
|
||||
The two modes take **disjoint** flags in both directions
|
||||
(`--inspect --seed 9` and a bare `--as 2` are both refused, exit 64): a
|
||||
flag accepted and ignored is how a user comes to believe they inspected
|
||||
seed 9 when they inspected whatever the recording holds.
|
||||
|
||||
Three controls, each red for its stated reason:
|
||||
|
||||
| control | result |
|
||||
|---|---|
|
||||
| the hash comparison removed | `a_walk_that_does_not_reproduce_fails` fails — the tampered bundle walks clean |
|
||||
| `Eyes::Seat` resolved to `Viewer::Spectator` | `P3 shows a hand in every table and nobody else does` |
|
||||
| the per-step render dropped | `one table per step plus the opening one` |
|
||||
|
||||
The third is the one that matters: without it a walk that rendered
|
||||
nothing at all would still have reported a matching hash and passed.
|
||||
|
||||
## Task: evidence, and what the chaos roll cost
|
||||
|
||||
```task
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue