2026-08-02 02:33:39 +02:00
|
|
|
|
---
|
|
|
|
|
|
id: CB-WP-0011
|
|
|
|
|
|
kind: product
|
|
|
|
|
|
title: "Stage 1, first slice: an inspector that shows everything"
|
2026-08-02 02:48:51 +02:00
|
|
|
|
status: done
|
CB-WP-0011-T01: the inspector shows everything, and a gate says so
The renderer moves out of the play loop into inspect.rs and grows from
24 to 42 of the 43 leaf paths a populated GroundView carries. What it
had been dropping was the whole DARVO state machine, the whole GROUND
practice, the scoring mode, Focus tokens, the discard pile, per-seat
protection, and every part of the outcome except the headline.
The load-bearing half is every_view_field_is_classified, which walks
the serialized view for leaf paths and requires each to be listed as
rendered (with a token the output must contain) or omitted (with a
reason). Paths rather than keys: 'problem' occurs under a DARVO target,
a GROUND choice and a Selection, and a key-set walk would let one of
the three vouch for the other two.
Four M-D1-MUT controls, each red for its stated reason. The
unclassified-field control fired for real on the first run --
players.*.hand, a field the gate's own author had missed.
2026-08-02 02:38:38 +02:00
|
|
|
|
state_hub_workstream_id: "1142442a-65f1-483a-800d-6ca8490c5f1a"
|
2026-08-02 02:33:39 +02:00
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
# Purpose
|
|
|
|
|
|
|
|
|
|
|
|
Tier **S** — and this is the **first time the chaos roll has changed
|
|
|
|
|
|
anything** in six declarations.
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
structural tier L (INTENT stage 1 creates a new capability port)
|
|
|
|
|
|
chaos d4 = 4 → override
|
|
|
|
|
|
override roll shuf -e S M L → S
|
|
|
|
|
|
declared tier S (structural L, chaos 4 → S)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Declaration 6 of 12 in the calibration window. The `CHAOS` gate in
|
|
|
|
|
|
`gates.toml` has `caught = []` and a `review_by` of 2026-09-30; this pass
|
|
|
|
|
|
is the first entry it can earn, whichever way the outcome falls.
|
|
|
|
|
|
|
|
|
|
|
|
## What tier S is allowed to mean here
|
|
|
|
|
|
|
|
|
|
|
|
A rolled-down tier relaxes *process weight*. It does not relax the hard
|
|
|
|
|
|
gate — **no implementation code for a capability exists before its ADR is
|
|
|
|
|
|
committed** — because that gate is stated unconditionally and the tier
|
|
|
|
|
|
table governs only "weight of steps 1–3", not whether step 3 happens.
|
|
|
|
|
|
|
|
|
|
|
|
The two rules meet head-on: stage 1's headline deliverable is a rendering
|
|
|
|
|
|
port (`cb-render-api` / `-null` / `-wgpu`, ArchitectureBlueprint §Port
|
|
|
|
|
|
pattern), a port needs an ADR, and tier S has no ADR.
|
|
|
|
|
|
|
|
|
|
|
|
**Resolution: split the declaration rather than lawyer either rule.**
|
|
|
|
|
|
This packet is the part of stage 1 that creates no port, adds no
|
|
|
|
|
|
dependency, and therefore trips no ADR gate. The GUI half gets its own
|
|
|
|
|
|
tier declaration and its own chaos roll later, informed by what this pass
|
|
|
|
|
|
learns. Two facts make that ordering the right one anyway:
|
|
|
|
|
|
|
|
|
|
|
|
- **AM-4a has 3,750 lines of headroom** (246,250 of 250,000 measured by
|
|
|
|
|
|
`make dep-weight`). Any 2D toolkit is a five- to six-figure line count.
|
|
|
|
|
|
The dependency decision needs a survey, and the roll just deleted the
|
|
|
|
|
|
survey — so the honest move is to not make the decision this pass.
|
|
|
|
|
|
- The second-use rule cuts the same way. A renderer that has never had to
|
|
|
|
|
|
show the whole of `GroundView` does not yet know what a view needs.
|
|
|
|
|
|
|
|
|
|
|
|
## The finding this packet acts on
|
|
|
|
|
|
|
|
|
|
|
|
`tools/cb-play/src/table.rs:113` already has
|
|
|
|
|
|
`render(view: &GroundView) -> String`. It is stage 1's renderer, written
|
|
|
|
|
|
in stage 0 to prompt a human, and **it drops roughly a third of what the
|
|
|
|
|
|
projection carries**:
|
|
|
|
|
|
|
|
|
|
|
|
| in `GroundView` | in `render` |
|
|
|
|
|
|
|---|---|
|
|
|
|
|
|
| `mode`, `focus`, `solution_discard` | absent |
|
|
|
|
|
|
| `ground_modes`, `ground_choices` | absent |
|
|
|
|
|
|
| `support_responses`, `darvo_targets` | absent |
|
|
|
|
|
|
| `protection`, `freedom_gate_lifted` | absent |
|
|
|
|
|
|
| `protected_this_round` on a Problem | absent |
|
|
|
|
|
|
| `personal`, `coalitions`, `mastery` on the outcome | absent |
|
|
|
|
|
|
|
|
|
|
|
|
Nothing is wrong: it was written to show a human their legal moves, and
|
|
|
|
|
|
it does. But "inspectable" is the word INTENT uses for stage 1, and an
|
|
|
|
|
|
inspector that silently omits the DARVO state machine and the GROUND
|
|
|
|
|
|
practice — the two mechanics this game exists to model — is not one.
|
|
|
|
|
|
|
|
|
|
|
|
The interesting part is that **no test could have caught this**, because
|
|
|
|
|
|
every assertion a renderer test naturally makes is satisfied by any
|
|
|
|
|
|
render. That is the harness-does-nothing class again, in its presentation
|
|
|
|
|
|
form.
|
|
|
|
|
|
|
|
|
|
|
|
## Task: the inspector shows everything, and a gate says so
|
|
|
|
|
|
|
|
|
|
|
|
```task
|
|
|
|
|
|
id: CB-WP-0011-T01
|
CB-WP-0011-T01: the inspector shows everything, and a gate says so
The renderer moves out of the play loop into inspect.rs and grows from
24 to 42 of the 43 leaf paths a populated GroundView carries. What it
had been dropping was the whole DARVO state machine, the whole GROUND
practice, the scoring mode, Focus tokens, the discard pile, per-seat
protection, and every part of the outcome except the headline.
The load-bearing half is every_view_field_is_classified, which walks
the serialized view for leaf paths and requires each to be listed as
rendered (with a token the output must contain) or omitted (with a
reason). Paths rather than keys: 'problem' occurs under a DARVO target,
a GROUND choice and a Selection, and a key-set walk would let one of
the three vouch for the other two.
Four M-D1-MUT controls, each red for its stated reason. The
unclassified-field control fired for real on the first run --
players.*.hand, a field the gate's own author had missed.
2026-08-02 02:38:38 +02:00
|
|
|
|
status: done
|
2026-08-02 02:33:39 +02:00
|
|
|
|
priority: high
|
CB-WP-0011-T01: the inspector shows everything, and a gate says so
The renderer moves out of the play loop into inspect.rs and grows from
24 to 42 of the 43 leaf paths a populated GroundView carries. What it
had been dropping was the whole DARVO state machine, the whole GROUND
practice, the scoring mode, Focus tokens, the discard pile, per-seat
protection, and every part of the outcome except the headline.
The load-bearing half is every_view_field_is_classified, which walks
the serialized view for leaf paths and requires each to be listed as
rendered (with a token the output must contain) or omitted (with a
reason). Paths rather than keys: 'problem' occurs under a DARVO target,
a GROUND choice and a Selection, and a key-set walk would let one of
the three vouch for the other two.
Four M-D1-MUT controls, each red for its stated reason. The
unclassified-field control fired for real on the first run --
players.*.hand, a field the gate's own author had missed.
2026-08-02 02:38:38 +02:00
|
|
|
|
state_hub_task_id: "b8cb4c20-9d06-47a4-890c-bf8390015439"
|
2026-08-02 02:33:39 +02:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Extend `render` to cover every field of `GroundView`, and — the load-
|
|
|
|
|
|
bearing half — add the check that keeps it covering them.
|
|
|
|
|
|
|
|
|
|
|
|
**The check.** Serialize the view to `serde_json::Value`, walk it for
|
|
|
|
|
|
every object key reachable in a populated state, and require each key to
|
|
|
|
|
|
be classified in exactly one of two lists in the test:
|
|
|
|
|
|
|
|
|
|
|
|
- `RENDERED` — the inspector shows it, asserted against a state where the
|
|
|
|
|
|
field holds a distinctive value that appears in the output;
|
|
|
|
|
|
- `OMITTED` — with a stated reason per entry (e.g. `hand_size`, which is
|
|
|
|
|
|
redundant when `hand` is shown to its owner).
|
|
|
|
|
|
|
|
|
|
|
|
A new field on `GroundView` that is in neither list **fails the test**.
|
|
|
|
|
|
That is the same shape as `not_control_gates` in `gates.toml`, for the
|
|
|
|
|
|
same reason: silence must cost something.
|
|
|
|
|
|
|
|
|
|
|
|
**Vacuity controls (M-D1-MUT).** The test must go red for a stated reason
|
|
|
|
|
|
when (a) a field is deleted from the render, (b) a field is moved from
|
|
|
|
|
|
`RENDERED` to `OMITTED` while still being rendered, and (c) the walk is
|
|
|
|
|
|
made to return an empty key set — the EXPECT-VACUOUS control, since a
|
|
|
|
|
|
coverage test over zero keys passes trivially and that is precisely how
|
|
|
|
|
|
this check would rot.
|
|
|
|
|
|
|
|
|
|
|
|
Build the fixture from a **mid-DARVO, mid-GROUND** state, not a fresh
|
|
|
|
|
|
deal: most of the missing fields are empty at deal time, and a coverage
|
|
|
|
|
|
test run against a state where the fields are absent is the same lie in a
|
|
|
|
|
|
different costume.
|
|
|
|
|
|
|
CB-WP-0011-T01: the inspector shows everything, and a gate says so
The renderer moves out of the play loop into inspect.rs and grows from
24 to 42 of the 43 leaf paths a populated GroundView carries. What it
had been dropping was the whole DARVO state machine, the whole GROUND
practice, the scoring mode, Focus tokens, the discard pile, per-seat
protection, and every part of the outcome except the headline.
The load-bearing half is every_view_field_is_classified, which walks
the serialized view for leaf paths and requires each to be listed as
rendered (with a token the output must contain) or omitted (with a
reason). Paths rather than keys: 'problem' occurs under a DARVO target,
a GROUND choice and a Selection, and a key-set walk would let one of
the three vouch for the other two.
Four M-D1-MUT controls, each red for its stated reason. The
unclassified-field control fired for real on the first run --
players.*.hand, a field the gate's own author had missed.
2026-08-02 02:38:38 +02:00
|
|
|
|
**Done 2026-08-02.** The renderer moved to `tools/cb-play/src/inspect.rs`
|
2026-08-02 02:48:51 +02:00
|
|
|
|
and now covers **41 of the 42 leaf paths** in a populated `GroundView`.
|
|
|
|
|
|
The one omission is `players.*.hand` — `null` for a non-viewer seat,
|
|
|
|
|
|
where the absence is what `hand N card(s)` renders.
|
|
|
|
|
|
|
|
|
|
|
|
**Measured, not counted** (T03): the old renderer produced 24 of the 41
|
|
|
|
|
|
tokens. One of the 17 it missed, `outcome.winners.*`, it did in fact
|
|
|
|
|
|
show — in a different format (`["P1", "P2"]` rather than `winners P1,
|
|
|
|
|
|
P2`), so the token misses it. **16 fields were genuinely absent**, and
|
|
|
|
|
|
that is the number to quote. The commit message for this task says
|
|
|
|
|
|
"42 of 43, up from 24"; both figures were counted by hand before the
|
|
|
|
|
|
measurement and both were wrong.
|
CB-WP-0011-T01: the inspector shows everything, and a gate says so
The renderer moves out of the play loop into inspect.rs and grows from
24 to 42 of the 43 leaf paths a populated GroundView carries. What it
had been dropping was the whole DARVO state machine, the whole GROUND
practice, the scoring mode, Focus tokens, the discard pile, per-seat
protection, and every part of the outcome except the headline.
The load-bearing half is every_view_field_is_classified, which walks
the serialized view for leaf paths and requires each to be listed as
rendered (with a token the output must contain) or omitted (with a
reason). Paths rather than keys: 'problem' occurs under a DARVO target,
a GROUND choice and a Selection, and a key-set walk would let one of
the three vouch for the other two.
Four M-D1-MUT controls, each red for its stated reason. The
unclassified-field control fired for real on the first run --
players.*.hand, a field the gate's own author had missed.
2026-08-02 02:38:38 +02:00
|
|
|
|
|
|
|
|
|
|
`every_view_field_is_classified` walks the serialized view for leaf
|
|
|
|
|
|
*paths* (not keys — `problem` occurs under a DARVO target, a GROUND
|
|
|
|
|
|
choice and a Selection, and a key-set walk would let one vouch for the
|
|
|
|
|
|
other two). Four controls, each run and each red for its stated reason:
|
|
|
|
|
|
|
|
|
|
|
|
| control | result |
|
|
|
|
|
|
|---|---|
|
|
|
|
|
|
| a field deleted from `render` | `players.*.protection is claimed rendered, but the output has no "protect 2"` |
|
|
|
|
|
|
| a field present in neither list | fired **for real on the first run** — `players.*.hand` |
|
|
|
|
|
|
| the walk returns no paths (EXPECT-VACUOUS) | `the walk found 0 leaf path(s) — it is not walking the view` |
|
|
|
|
|
|
| a classified path that no longer exists | `classified path(s) no longer exist in GroundView: ["outcome.nonexistent"]` |
|
|
|
|
|
|
|
|
|
|
|
|
The second is the one worth keeping: the gate caught a field I had missed
|
|
|
|
|
|
while writing the gate, before it had ever been committed.
|
|
|
|
|
|
|
2026-08-02 02:33:39 +02:00
|
|
|
|
## Task: `cb-play --inspect` walks a recorded game
|
|
|
|
|
|
|
|
|
|
|
|
```task
|
|
|
|
|
|
id: CB-WP-0011-T02
|
2026-08-02 02:45:55 +02:00
|
|
|
|
status: done
|
2026-08-02 02:33:39 +02:00
|
|
|
|
priority: high
|
CB-WP-0011-T01: the inspector shows everything, and a gate says so
The renderer moves out of the play loop into inspect.rs and grows from
24 to 42 of the 43 leaf paths a populated GroundView carries. What it
had been dropping was the whole DARVO state machine, the whole GROUND
practice, the scoring mode, Focus tokens, the discard pile, per-seat
protection, and every part of the outcome except the headline.
The load-bearing half is every_view_field_is_classified, which walks
the serialized view for leaf paths and requires each to be listed as
rendered (with a token the output must contain) or omitted (with a
reason). Paths rather than keys: 'problem' occurs under a DARVO target,
a GROUND choice and a Selection, and a key-set walk would let one of
the three vouch for the other two.
Four M-D1-MUT controls, each red for its stated reason. The
unclassified-field control fired for real on the first run --
players.*.hand, a field the gate's own author had missed.
2026-08-02 02:38:38 +02:00
|
|
|
|
state_hub_task_id: "08f8a9c7-3dfe-4f72-b510-df9efa457370"
|
2026-08-02 02:33:39 +02:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Stage 1 asks for a *debug inspector*. The inspector above renders one
|
|
|
|
|
|
state; this makes it walk a game.
|
|
|
|
|
|
|
|
|
|
|
|
Deliver `cb-play --inspect <bundle-or-scenario> [--as SEAT|spectator]`:
|
|
|
|
|
|
replay the recorded commands and print the full table after each step,
|
|
|
|
|
|
from the chosen viewpoint. A `.cbreplay` bundle and a scenario YAML are
|
|
|
|
|
|
both accepted — both already reconstruct a command sequence.
|
|
|
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
It costs no dependency: replay, projection and render all exist.
|
|
|
|
|
|
|
|
|
|
|
|
**Acceptance.** Inspecting a recorded game must reproduce the end-state
|
|
|
|
|
|
hash the bundle records — an inspector that shows a state the replay did
|
|
|
|
|
|
not reach is worse than none. Assert the hash, and mutate the replay to
|
|
|
|
|
|
prove the assertion fires.
|
|
|
|
|
|
|
|
|
|
|
|
**Projection is not optional here.** `--as 2` must show P3's hand and
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
2026-08-02 02:45:55 +02:00
|
|
|
|
**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.
|
|
|
|
|
|
|
2026-08-02 02:33:39 +02:00
|
|
|
|
## Task: evidence, and what the chaos roll cost
|
|
|
|
|
|
|
|
|
|
|
|
```task
|
|
|
|
|
|
id: CB-WP-0011-T03
|
2026-08-02 02:48:51 +02:00
|
|
|
|
status: done
|
2026-08-02 02:33:39 +02:00
|
|
|
|
priority: medium
|
CB-WP-0011-T01: the inspector shows everything, and a gate says so
The renderer moves out of the play loop into inspect.rs and grows from
24 to 42 of the 43 leaf paths a populated GroundView carries. What it
had been dropping was the whole DARVO state machine, the whole GROUND
practice, the scoring mode, Focus tokens, the discard pile, per-seat
protection, and every part of the outcome except the headline.
The load-bearing half is every_view_field_is_classified, which walks
the serialized view for leaf paths and requires each to be listed as
rendered (with a token the output must contain) or omitted (with a
reason). Paths rather than keys: 'problem' occurs under a DARVO target,
a GROUND choice and a Selection, and a key-set walk would let one of
the three vouch for the other two.
Four M-D1-MUT controls, each red for its stated reason. The
unclassified-field control fired for real on the first run --
players.*.hand, a field the gate's own author had missed.
2026-08-02 02:38:38 +02:00
|
|
|
|
state_hub_task_id: "db722865-1233-4918-952d-0bf4761199e4"
|
2026-08-02 02:33:39 +02:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Write `evidence/CB-EV-0009-inspectable-table.md` covering:
|
|
|
|
|
|
|
|
|
|
|
|
1. **Did tier S produce a worse outcome than tier L would have?** The
|
|
|
|
|
|
only honest way to answer is to name what the deleted survey would
|
|
|
|
|
|
have decided and check whether this pass needed it. State the answer
|
|
|
|
|
|
even if it is "no, and that is one data point against the tier table",
|
|
|
|
|
|
because that is the finding the calibration window is for.
|
|
|
|
|
|
2. The field-coverage gap as measured before and after T01.
|
|
|
|
|
|
3. Cost and session shape for the pass, per `make status`. The previous
|
|
|
|
|
|
pass opened at a **HARD** session-shape breach (338,852 mean context
|
|
|
|
|
|
against a 300,000 ceiling) and a **45%** trailing-3 meta share against
|
|
|
|
|
|
a soft 25%. This pass is `product`; report where both land.
|
|
|
|
|
|
4. Update `gates.toml`: `CHAOS` gets its first `caught` entry — the roll
|
|
|
|
|
|
fired, and what it changed.
|
|
|
|
|
|
|
|
|
|
|
|
**Do not update the ADR or INTENT.** Stage 1 is not shipped when this
|
|
|
|
|
|
lands; the port half is untouched and INTENT's stage-1 line stays open.
|
|
|
|
|
|
Marking a stage complete because part of it works is the failure mode
|
|
|
|
|
|
stage 0 avoided by leaving the CLI player open for three passes.
|
2026-08-02 02:48:51 +02:00
|
|
|
|
|
|
|
|
|
|
**Done 2026-08-02.** [CB-EV-0009](../evidence/CB-EV-0009-inspectable-table.md).
|
|
|
|
|
|
The headline: tier S did **not** produce a worse outcome, and the reason
|
|
|
|
|
|
is not that tier L was unnecessary — the roll forced a decomposition that
|
|
|
|
|
|
found a defect the survey would have walked past. Recorded as the CHAOS
|
|
|
|
|
|
gate's first `caught` entry, with the window left open.
|
|
|
|
|
|
|
|
|
|
|
|
Also on record, against my own prior: I recommended tier L in the turn
|
|
|
|
|
|
before the roll, and the roll was right.
|