CB-REV-0001: the adversarial review, and it was not approvable
Some checks failed
ci / check (push) Failing after 4s

Thirteen challenges, five FATAL, all five conceded. Nothing had reached
ground-game, which is the only reason this is a correction and not a
retraction.

The worst: `Reactive` was not "greedy with one preference changed". It
differed in five, including SpendFreedom — ranked 95 unconditionally
against greedy's `95 if gated else 0` — so the seat burned its Freedom
token in round one of every game. A second change to the exact mechanism
under study, and every number in CB-EV-0031 was measuring it. The pass
claimed ADR-0018's one-varying-parameter discipline in its own workplan
while violating it. GreedyPolicy::rank is now public and the policy
delegates, overriding one match arm, so the control is structurally true.

Withdrawn entirely: "H1-B suppresses DARVO in the attacker". Disabling
H1-B under the corrected policy changes the arm count by exactly zero.
The pass hedged the wrong variable — it disclaimed "the number 2" and
defended "the direction", and the direction is what failed. The
supporting inference was invalid anyway: final Stress cannot show who
armed, because DarvoEnded resets the stage and REVERSE gives its owner -2.

Corrected: criterion 1 was failed on the greedy column while the pass's
own printed table showed 31-1000 arms in the other columns — the
selective-column move, in the file that names it. "Peak Stress was 1" was
a maximum over StressSet payloads, not held state (true: 2); the baseline
game count was 1,600 not 3,200; and "a reckless policy plays identically
to a careful one" is refuted by this repo's own rank-95 policy.

Inert controls replaced, each verified red against the reviewer's own
mutation: the baseline hash test compared two identically-constructed
states (serde(skip) on variant left 57/57 green); the `unchanged:` test
checked 3 of 7 entries and passed with SOLVE made illegal; H1-A's ordering
and H1-B's OU-cancel path had no test at all.

edition-check now covers catalog.yaml and rules_delta.yaml, whose digests
CB-WP-0038 claimed and never recorded — the review found it and reported
it unverified rather than absent, which was the right call.

Still open: H1-B on the DARVO extra-Attack path is untested, regulation.rs
still skips setup failures silently, and round-5 arms are counted though
they can never act.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
tegwick 2026-08-08 02:02:35 +02:00
parent 38106791a6
commit 041c0e7c3e
9 changed files with 489 additions and 101 deletions

View file

@ -46,6 +46,27 @@ falsifiers rather than merely skipped
the designer placed *outside* the core; importing it would break the claim
that this engine plays the edition as printed (ADR-0015 D2).
## The catalog and the H1 experiment package
Vendored 2026-08-08 from `ground-game` `8886543` (CB-WP-0038). These are
**outside this directory** — `editions/catalog.yaml` and
`editions/experiments/h1-problem-stress/` — because the catalog selects
*between* packages and does not belong inside one.
**Digests were claimed for these by CB-WP-0038 T01 and not recorded**;
the adversarial review ([CB-REV-0001](../../reviews/CB-REV-0001-h1.md))
reported it unverified and it was a real gap.
```
sha256 eb21fa3237637790fef601fe6668a190a549715e9a78b7dfe47b40cd069b648e ../catalog.yaml
sha256 f58e81f84ea2b0d16e39932261eb3f3d9890345cdf37ad6f0b3abc00636840be ../experiments/h1-problem-stress/rules_delta.yaml
sha256 7b1cc0149122b855e827bc930576ed165bf7dd8d62707e845a9e514ce3521f8e ../experiments/h1-problem-stress/Actions.csv
```
**`rules_delta.yaml` is the load-bearing one**: it is the executable
statement of H1, and the kernel implements it. A silent change there is a
silent change to what we measured.
## Digests
```

View file

@ -20,10 +20,18 @@ than trusted, and the ATTACK panel re-run for both rule sets.
`ground-game`'s success criteria (design note §3.2), answered one by one.
**Three of four fail.**
> **CORRECTED 2026-08-08 after adversarial review**
> ([`CB-REV-0001`](../reviews/CB-REV-0001-h1.md)). Criteria 1 and 2 were
> rendered as flat failures **on the strength of the greedy column
> alone**, while this pass's own harness printed 311000 DARVO arms per
> cell in the rank-75 and rank-95 columns. That is the selective-column
> move this project says it exists to prevent, committed in the file that
> says so. The verdicts below are restated per column.
| # | criterion | verdict |
|---|---|---|
| 1 | DARVO arm rate non-trivial, "not 0/500" | **fails** — still **0** under greedy at every seat count |
| 2 | ATTACK selection rises for some subpopulation | **fails** — greedy still attacks **0** times; and for the rank-75 policy ATTACK *fell*, 604 → 180 at 2p |
| 1 | DARVO arm rate non-trivial, "not 0/500" | **not a flat fail.** **0** under greedy; **811000 per cell** under rank-75 and rank-95, baseline *and* H1. It fails for a seat that regulates and passes for one that does not — see [CB-EV-0031](CB-EV-0031-a-seat-that-does-not-regulate.md) |
| 2 | ATTACK selection rises for some subpopulation | **mixed.** Greedy attacks **0** times; rank-75's ATTACK *fell* 604 → 180 at 2p; the unregulated seat's rose 0 → 726 |
| 3 | group success does not collapse | **fails hardest** — greedy's wins go **165 → 0** (3p), **190 → 0** (4p), **200 → 0** (6p) |
| 4 | Bond/GROUND stay better than DARVO | holds, but **vacuously**: DARVO never fires |

View file

@ -4,9 +4,17 @@ CB-WP-0039. Tier M (adds a policy to the panel every future measurement is
reported against; chaos d8 = 2 → no override). **Declaration 11 of chaos
window 3.** Closed 2026-08-08.
> Like [CB-EV-0030](CB-EV-0030-h1-measured.md), **this has not had the
> tier-L adversarial review that pass owes, and none of it may reach
> `ground-game` until that review has run.**
> **CORRECTED 2026-08-08 after adversarial review, and most of the
> original file was wrong.** The review is in
> [`CB-REV-0001`](../reviews/CB-REV-0001-h1.md). The policy this pass
> called *"greedy with one preference changed"* differed in **five**
> places — including `SpendFreedom`, which it ranked 95 unconditionally
> where greedy ranks it 0 unless the gate bites, so the seat burned its
> Freedom token in round one of every game. **Every number below was
> measuring that bug.** They have been re-derived against a policy that
> delegates to `GreedyPolicy::rank` and overrides exactly one arm.
>
> Sections 1 and 2 are rewritten. **Section 3 is withdrawn entirely.**
**Delivered:** the `reactive` policy, and the measurement CB-EV-0030 §4
named as the one it had not run.
@ -24,24 +32,27 @@ unreachable **by construction**. So "H1 does nothing" was really "H1 does
nothing *to a seat that already manages its Stress*" — and H1 was written
for the seat that does not.
`reactive` is greedy with **one preference changed**: GROUND demoted below
ATTACK. SHARED GROUND, 200 games per cell, all 200 ran in every cell:
`reactive` now **delegates to `GreedyPolicy::rank` and overrides one arm**
(`Ground if gated`), so "one preference differs" is structurally true
rather than a claim. SHARED GROUND, 200 games per cell, all 200 ran, and
**`peak` is now Stress held, not Stress assigned** (§2):
| | | greedy | | | | reactive | | |
|---|---:|---:|---:|---:|---:|---:|---:|---:|
| **seats** | won | atk | darvo | peak | won | atk | darvo | peak |
| 2p | 68 | 0 | 0 | 4 | **0** | 1200 | **400** | **5** |
| 3p | 0 | 0 | 0 | 4 | **0** | 1800 | **400** | **5** |
| 4p | 0 | 0 | 0 | 4 | **0** | 2400 | **400** | **5** |
| 6p | 0 | 0 | 0 | 4 | **0** | 3600 | **400** | **5** |
| 2p | 68 | 0 | 0 | 4 | **66** | 726 | 363 | **5** |
| 3p | 0 | 0 | 0 | 4 | 0 | 1200 | 600 | **5** |
| 4p | 0 | 0 | 0 | 4 | 0 | 1600 | 800 | **5** |
| 6p | 0 | 0 | 0 | 4 | 0 | 2400 | 1200 | **5** |
**H1's mechanism works.** Criterion 1 (DARVO arm rate non-trivial) and
criterion 2 (ATTACK selection rises for some subpopulation) are **met**
for the subpopulation H1 was aimed at. CB-EV-0030 reported both as
failures, and that report was about greedy.
**H1's mechanism does reach the unregulated seat.** DARVO arms **2 per
seat per game**, scaling with the table — where the earlier figure was a
flat 400 in every cell, which was an artifact of the broken policy.
**Criterion 3 still fails, and now worse.** Reactive wins **nothing**, at
any seat count, under H1.
**Criterion 3's verdict is corrected.** The original said reactive *"wins
nothing, at any seat count"*. **False.** At 2p it wins **66 against
greedy's 68** — indistinguishable. It wins nothing at 3p and above, which
is also where greedy wins nothing.
## 2. The baseline finding, which is larger than H1
@ -49,40 +60,55 @@ Look at the baseline half of the same run. Greedy and reactive are
**identical** — 132/165/190/200, zero attacks, zero DARVO, in all four
bands.
**Peak Stress across 3,200 baseline games was 1.** Starting Stress is 2,
so no seat's Stress was ever *set* above 1: it only ever went down.
**Peak Stress held across the 1,600 baseline games was 2 — the starting
value, never exceeded.** Stress only ever went down.
> **The baseline's entire Stress economy is unreachable under this panel.**
> The gate at 4, the DARVO arm at 5, the Freedom token that buys past the
> gate — none of it can engage, and a policy built to be reckless with
> Stress plays identically to one built to husband it.
**Three corrections to what this section originally said.**
That is a deeper account of F17 than F17 has. ATTACK is not merely
unrewarding; **the pressure it is supposed to answer never exists.** H1 is
an attempt to fix exactly this, and it is aimed at the right thing.
1. It reported **1**, because `peak` was a maximum over `StressSet` event
*payloads*. Starting Stress is written by `setup`, never by an event,
so a table sitting at 2 all game reported 1 — and a table with no
`StressSet` at all would have reported 0. **Wrong subject**: the metric
answered *"highest value ever assigned"* while the prose claimed
*"highest Stress reached"*.
2. It said **3,200 baseline games**. The run is 3,200 *total*; the
baseline half is **1,600**.
3. It generalised to *"a policy built to be reckless with Stress plays
identically to one built to husband it"*. **False, and refuted by this
repo's own sibling harness**: `attack-value.rs`'s rank-95 policy is
exactly that policy, and under **baseline** it drives Stress to 5 and
arms DARVO 4001000 times per cell.
## 3. What H1-B actually does, which is not what it was for
**What survives, stated narrowly.** Under both policies measured here —
neither of which ever selects ATTACK under baseline — **no Stress is ever
added at all**. The baseline's Stress economy is reachable only through
ATTACK, so a table that does not attack never meets the gate, the arm, or
the Freedom token. That is still a real observation about F17, and it is
**about ATTACK being the sole inbound pressure**, not about the economy
being unreachable in general.
`darvo` is **exactly 400 in every cell** while `atk` scales cleanly with
seats (1200 / 1800 / 2400 / 3600 = 3 per seat per game). A constant across
seat counts is an artifact smell, so it was measured rather than reported.
## 3. WITHDRAWN — "H1-B suppresses DARVO in the attacker"
Six-player final Stress, every seed: **`[5, 5, 4, 4, 4, 4]`**. Exactly two
seats arm, whatever the table size.
The original §3 argued that H1-B holds the attacker at Stress 4, below the
arm, and pushes its targets to 5 — inferred from a constant `darvo = 400`
and a final-Stress signature of `[5, 5, 4, 4, 4, 4]`.
**The self-soothe is doing it.** An attacker at Stress ≥ 4 takes 1 for a
landed Attack, which holds it at 4 — *below the arm* — while its targets
take +1 or +2 and climb to 5. **H1-B suppresses DARVO in the seat that
attacks and concentrates it in the seat attacked.**
**Withdrawn on two independent grounds, both found by the review.**
The hypothesis wanted ATTACK to be rational at high Stress. It is. The
side effect is that the aggressor is the one seat protected from arming.
1. **The constant was the broken policy.** With the one-arm-override
policy, `darvo` scales with seats (363/600/800/1200). There is no
constant to explain.
2. **Disabling H1-B changes the arm count by exactly zero**, in every
cell, under the corrected policy. The effect attributed to H1-B's
arithmetic was an interaction with the undeclared preference deltas.
**Stated as a limitation, not a finding about H1:** `reactive` picks its
Attack target by first-legal, not by any judgement, so the *concentration*
on two seats is partly an artifact of crude targeting. The direction —
attackers held at 4, targets pushed to 5 — follows from H1-B's arithmetic
and does not depend on the targeting. **The number 2 does.**
**And the inference was invalid even where the numbers held.** Final
Stress does not record who armed: `DarvoEnded` resets the stage to `Off`
and REVERSE applies 2 to its owner, so a seat can arm and finish below 5.
The review demonstrated six seats arming behind the same `[5,5,4,4,4,4]`
signature. **The original hedged the wrong variable** — it disclaimed "the
number 2" and defended "the direction", and the direction is the part that
failed.
## 4. What this does not say

View file

@ -40,31 +40,22 @@ impl Policy for Reactive {
.players
.get(&seat)
.is_some_and(|p| p.stress >= 4 && !p.freedom_gate_lifted);
// ONE ARM OVERRIDDEN, THE REST DELEGATED.
//
// The first version re-typed greedy's ranking and changed one
// line of the copy. It differed in five places, and the review
// found it: `SpendFreedom` ranked 95 unconditionally instead of
// greedy's `95 if gated else 0`, so this seat spent its Freedom
// token in round one of every game — a second change to the very
// mechanism under study. Delegating makes "exactly one preference
// differs" structurally true instead of a claim in a comment.
let rank = |c: &GroundCommand| -> i32 {
match c {
GroundCommand::SelectAction {
action, problem, ..
} => match action {
// THE ONE LINE. Greedy has `Ground if gated => 100`.
Action::Ground if gated => 5,
Action::Solve
if problem
.and_then(|p| state.problems.get(&p))
.is_some_and(|p| p.claimed_by.is_some()) =>
{
20
}
Action::Solve => 90,
Action::Investigate => 80,
Action::Support => 70,
Action::Ground => 5,
Action::Attack => 10,
},
GroundCommand::SpendFreedom => 95,
GroundCommand::ChooseGroundMode { .. } => 50,
GroundCommand::RespondToSupport { .. } => 90,
GroundCommand::ChooseDarvoTarget { .. } => 50,
GroundCommand::Reveal | GroundCommand::Resolve | GroundCommand::EndRound => -1,
action: Action::Ground,
..
} if gated => 5,
other => GreedyPolicy::rank(state, seat, other),
}
};
let mut best = 0;
@ -77,6 +68,10 @@ impl Policy for Reactive {
}
}
/// `Scenarios.csv`: "All players start at Stress 2." Named rather than
/// inlined so the peak metric cannot silently disagree with setup.
const START_STRESS: u8 = 2;
struct Cell {
games: u32,
won: u32,
@ -136,17 +131,28 @@ fn sweep(mode: ScoringMode, variant: Variant, players: u8, reactive: bool) -> Ce
c.atk += 1;
}
}
// Peak Stress **held**, not peak Stress *assigned*.
//
// The first version took a maximum over `StressSet` PAYLOADS.
// Starting Stress is 2 and is written by `setup`, never by an
// event, so a table that sat at 2 all game reported **1**, and a
// table with no `StressSet` at all would report 0. CB-EV-0031 §2
// built its headline claim on that number. Wrong subject: the
// metric answered "highest value ever assigned", the prose said
// "highest Stress reached".
let mut held: std::collections::BTreeMap<PlayerId, u8> =
g.state.players.keys().map(|s| (*s, START_STRESS)).collect();
c.peak_stress = c.peak_stress.max(START_STRESS);
for e in &g.events {
if matches!(e, games_ground::GroundEvent::DarvoTriggered { .. }) {
c.darvo += 1;
}
// How close does Stress actually get to the arm at 5? That is
// the number H1's whole mechanism turns on, and CB-EV-0030
// had to infer it from a single game.
if let games_ground::GroundEvent::StressSet { stress, .. } = e {
if let games_ground::GroundEvent::StressSet { player, stress } = e {
held.insert(*player, *stress);
c.peak_stress = c.peak_stress.max(*stress);
}
}
let _ = held;
}
c
}

View file

@ -323,7 +323,20 @@ impl Policy for RandomPolicy {
pub struct GreedyPolicy;
impl GreedyPolicy {
fn rank(state: &GroundState, seat: PlayerId, cmd: &GroundCommand) -> i32 {
/// The ranking, **public so a variant policy can override exactly one
/// arm and inherit the rest** (CB-WP-0039, after review).
///
/// It was private, so `regulation.rs` re-typed an abridged copy and
/// called it "greedy with one preference changed". It differed in
/// five places — including `SpendFreedom`, which the copy ranked 95
/// unconditionally where this ranks it 0 unless the gate is biting,
/// so the "reactive" seat burned its Freedom token in round one of
/// every game. **A second change to the exact mechanism the pass was
/// studying**, and every number in CB-EV-0031 was measuring it.
///
/// Making this callable removes the possibility rather than testing
/// for it: a caller that delegates cannot drift.
pub fn rank(state: &GroundState, seat: PlayerId, cmd: &GroundCommand) -> i32 {
let gated = state
.players
.get(&seat)

View file

@ -2092,14 +2092,40 @@ mod tests {
s
}
/// **The load-bearing control.** A variant system that perturbs
/// the baseline invalidates every measurement this repo has.
/// **The load-bearing control**, rewritten after review found the
/// first version inert.
///
/// It compared two states built by the *same* `setup` call, both
/// then assigned `Variant::Baseline` — bitwise identical by
/// construction, so the assertion could only fail if hashing were
/// nondeterministic. It carried no information about variants at
/// all. Adding `#[serde(skip)]` to `variant` — which is exactly
/// the "a scenario replayed under the wrong variant diverges
/// silently" failure the workplan named — left all 57 tests green.
///
/// This asserts the two properties that were claimed:
/// **the variant reaches the hash**, and **selecting the baseline
/// is not a change**.
#[test]
fn baseline_is_bit_for_bit_what_it_was() {
fn the_variant_reaches_the_hash_and_baseline_is_not_a_change() {
for players in [2u8, 3, 6] {
for seed in 0..8u64 {
let base = setup(players, Variant::Baseline, seed);
let mut default_built = GroundState::setup(
let h1 = setup(players, Variant::H1ProblemStress, seed);
// 1. The variant is IN the hash. `#[serde(skip)]` on
// the field makes these equal, which is the whole
// silent-divergence failure.
assert_ne!(
cb_events::state_hash_hex(&base),
cb_events::state_hash_hex(&h1),
"{players}p seed {seed}: the variant does not reach the state hash, \
so a recording cannot say which rules it was played under"
);
// 2. And selecting the baseline explicitly is not a
// change from selecting nothing.
let untouched = GroundState::setup(
&Setup {
players,
preset: format!("standard-{players}p"),
@ -2108,12 +2134,10 @@ mod tests {
seed,
)
.expect("setup");
// Untouched: whatever `setup` produces IS baseline.
assert_eq!(default_built.variant, Variant::Baseline);
default_built.variant = Variant::Baseline;
assert_eq!(untouched.variant, Variant::Baseline, "the default moved");
assert_eq!(
cb_events::state_hash_hex(&base),
cb_events::state_hash_hex(&default_built),
cb_events::state_hash_hex(&untouched),
"{players}p seed {seed}: selecting the baseline changed it"
);
}
@ -2226,6 +2250,68 @@ mod tests {
);
}
/// **H1-A lands before the DARVO arm check** (review M5).
///
/// The delta orders it "+1 Stress, then clamp, then DARVO arm
/// check as today". CB-WP-0038 claimed this was got right and
/// nothing tested it: moving the pressure after the arm check
/// left every test green.
///
/// A seat at 4 with a Problem unclaimed must arm **in the same
/// round end** — pressure takes it to 5, and the check sees it.
#[test]
fn h1a_pressure_arms_darvo_in_the_same_round_end() {
let mut s = setup(3, Variant::H1ProblemStress, 7);
for p in s.players.values_mut() {
p.stress = 4;
p.darvo = DarvoStage::Off;
}
assert!(s.problems.values().any(|p| p.claimed_by.is_none()));
let events = s.end_round_events();
assert!(
events
.iter()
.any(|e| matches!(e, GroundEvent::DarvoTriggered { .. })),
"pressure took the seat to 5 but the arm check did not see it, \
so H1-A is ordered after it"
);
// And the order is visible in the event stream: the Stress
// must be set before the trigger, not after.
let first_stress = events
.iter()
.position(|e| matches!(e, GroundEvent::StressSet { .. }));
let first_trigger = events
.iter()
.position(|e| matches!(e, GroundEvent::DarvoTriggered { .. }));
assert!(
first_stress < first_trigger,
"the arm check precedes the pressure in the event stream"
);
}
/// **H1-B must not fire on a GROUND—OU cancellation** (review M11).
///
/// `resolve_attack` has two cancel paths and the existing test
/// exercised only Protection — it passed `&Default::default()`
/// for `ou_cancels`, so the other path was never reached.
#[test]
fn h1b_does_not_soothe_an_ou_cancelled_attack() {
let mut s = setup(3, Variant::H1ProblemStress, 3);
let seats: Vec<PlayerId> = s.players.keys().copied().collect();
let (a, t) = (seats[0], seats[1]);
s.players.get_mut(&a).expect("a").stress = 4;
let mut ou = std::collections::BTreeSet::new();
ou.insert((a, t));
let mut events = Vec::new();
s.resolve_attack(a, t, &ou, &mut events);
assert!(
!events
.iter()
.any(|e| matches!(e, GroundEvent::StressSet { player, .. } if *player == a)),
"an Attack cancelled by GROUND—OU still soothed the attacker"
);
}
/// **`rules_delta.yaml`'s `unchanged:` list is ground-game's claim
/// about their own experiment, and it is checkable.**
///
@ -2260,6 +2346,61 @@ mod tests {
base.solution_deck, h1.solution_deck,
"{players}p: deck moved"
);
// solve_legality / support / ground_modes: the SAME menu
// in the SAME position. Comparing setup fields could not
// see a delta that forbids an action -- the review made
// SOLVE illegal under H1 and this test stayed green.
let seats: Vec<PlayerId> = h1.players.keys().copied().collect();
for seat in &seats {
let mut lb: Vec<String> = crate::bot::legal_commands(&base, *seat)
.iter()
.map(|c| format!("{c:?}"))
.collect();
let mut lh: Vec<String> = crate::bot::legal_commands(&h1, *seat)
.iter()
.map(|c| format!("{c:?}"))
.collect();
lb.sort();
lh.sort();
assert_eq!(
lb, lh,
"{players}p {seat}: H1 changed which commands are legal"
);
}
// relation_slots: 2, asserted at the BOUNDARY. The old
// check asked `has_free_slot` of a seat with no relations,
// which holds for any capacity >= 1.
if seats.len() >= 3 {
let mut s = h1.clone();
s.relations
.insert(Pair::new(seats[0], seats[1]), Relation::Bond);
assert!(s.has_free_slot(seats[0]), "one relation leaves a slot");
s.relations
.insert(Pair::new(seats[0], seats[2]), Relation::Bond);
assert!(
!s.has_free_slot(seats[0]),
"{players}p: two relations must fill both slots -- capacity moved"
);
}
// darvo_stage_table: the arm sits at Stress 5. Every
// Problem claimed, so H1-A cannot add pressure and the
// only question is where the threshold is.
let mut s = h1.clone();
for p in s.players.values_mut() {
p.stress = 4;
}
for p in s.problems.values_mut() {
p.claimed_by = Some(seats[0]);
}
assert!(
!s.end_round_events()
.iter()
.any(|e| matches!(e, GroundEvent::DarvoTriggered { .. })),
"{players}p: DARVO armed below Stress 5 -- the stage table moved"
);
}
}
}

129
reviews/CB-REV-0001-h1.md Normal file
View file

@ -0,0 +1,129 @@
# CB-REV-0001 — adversarial review of the H1 measurement
The tier-L review CB-WP-0038 owed (InnerLoop Step 2). One round: challenge,
then response. Run 2026-08-08 by a separate agent against
CB-WP-0038/CB-EV-0030 and CB-WP-0039/CB-EV-0031.
> **Verdict: not approvable as submitted.** Thirteen challenges, five
> rated FATAL. **Every FATAL is conceded.** Nothing from either evidence
> file had reached `ground-game`, which is the only reason this is a
> correction rather than a retraction.
The reviewer reproduced every number, re-derived on **three** samples
(seeds 0..200, 1000..1200, 5000..5500) and ran **14 kernel mutations**.
---
## The five that were fatal
### 1. `Reactive` was not "greedy with one preference changed" — it differed in five
**Conceded, and it is the worst thing in the pass.** The policy re-typed
an abridged copy of greedy's ranking and changed one line *of the copy*,
under a comment reading `// THE ONE LINE`. It also differed in
`SpendFreedom` (95 unconditional against greedy's `95 if gated else 0`),
`Solve` on a claimed Problem, `ChooseGroundMode` and `RespondToSupport`.
**The `SpendFreedom` difference is a second change to the exact mechanism
under study**: the seat burned its Freedom token in round one of every
game, ungated. Measured by the reviewer: 1200 spends against greedy's 0.
**This pass claimed ADR-0018's one-varying-parameter discipline in its own
workplan while violating it.** That is worse than not claiming it.
**Fixed structurally rather than by testing:** `GreedyPolicy::rank` is now
`pub`, and `Reactive` delegates to it and overrides a single match arm. A
caller that delegates cannot drift. The reviewer's `StrictReactive`
numbers reproduce exactly.
### 2. The H1-B suppression mechanism does not survive the corrected policy
**Conceded and withdrawn.** The reviewer disabled H1-B and re-ran:
`darvo` is **identical in every cell**. The effect CB-EV-0031 §3 attributed
to "H1-B's arithmetic" was an interaction with challenge 1's bugs.
**The hedge was on the wrong variable.** §3 disclaimed *"the number 2"*
and defended *"the direction"*. The direction is what failed.
### 3. `[5,5,4,4,4,4]` does not show that two seats armed
**Conceded.** `DarvoEnded` resets the stage and REVERSE gives its owner
2, so a seat can arm and end below 5. The reviewer exhibited **six**
seats arming behind the same signature. A terminal snapshot was used to
prove a path property.
### 4. Criterion 1 was failed on the greedy column alone
**Conceded.** CB-EV-0030 rendered *"DARVO arm rate still 0"* as a flat
failure while **its own printed table** showed 311000 arms per cell in
the rank-75 and rank-95 columns. **The selective-column move, in the file
that names selective reporting as the thing to avoid.** Restated per
column.
### 5. "Peak Stress was 1" was a wrong-subject error, with two more defects
**Conceded, all three.** `peak` maximised over `StressSet` event
*payloads*; starting Stress is written by `setup` and never by an event,
so a table sitting at 2 reported 1. True peak held: **2**. The baseline
game count was **1,600**, not 3,200. And the generalisation — *"a reckless
policy plays identically to a careful one"* — is refuted by this repo's
own rank-95 policy, which under **baseline** drives Stress to 5.
**What survives is narrower and is now stated that way**: under the two
policies measured, neither of which selects ATTACK under baseline, no
Stress is ever added. ATTACK is the sole inbound pressure.
---
## The serious ones
| # | challenge | outcome |
|---|---|---|
| 6 | `baseline_is_bit_for_bit_what_it_was` compared two identically-constructed states — inert against its own threat; `#[serde(skip)]` on `variant` left 57/57 green | **conceded.** Replaced by `the_variant_reaches_the_hash_and_baseline_is_not_a_change`, which asserts baseline and H1 hash **differently**. The reviewer's M6 now goes red |
| 7 | the `unchanged:` test checked **3 of 7** entries; making SOLVE illegal under H1 left it green | **conceded.** Now compares `legal_commands` per seat (catches M9), checks relation slots at the **boundary** rather than on an empty seat, and asserts the DARVO arm is at 5 (catches M7). Both verified red |
| 8 | "criteria met" rests on a forced move — `reactive` ranks ATTACK at 10 and picks it only when the gate leaves nothing else | **conceded as a limitation, recorded, not fixed.** It is true that the instrument cannot show a null result once H1-A reaches Stress 4. That is a real weakness of the measurement and is now stated in CB-EV-0031 §4 |
| 9 | three claimed properties had no failing test: H1-A's ordering, H1-B on the DARVO extra Attack, H1-B on an OU-cancelled Attack | **two fixed**`h1a_pressure_arms_darvo_in_the_same_round_end` and `h1b_does_not_soothe_an_ou_cancelled_attack`, both mutation-verified. **The DARVO extra-Attack path remains untested** and is carried as open |
## The rest
- **10 — H1-B's `after_target_and_relation_effects` ordering is vacuous
here.** Conceded: nothing between the two positions touches the
attacker's Stress, so the clause cannot be checked in this kernel. The
honest statement replaces the claim that it was got right.
- **11 — `regulation.rs` still skips setup failures silently.** Conceded;
the credit CB-EV-0030 §3 took was half-earned. The `play` path was
instrumented, the `setup` path was not.
- **13 — round-5 DARVO arms are counted but can never act**, and
`end_round_events` scores from `self` rather than `work`, so round-5 H1-A
Stress is invisible to the CommonProblem tiebreak. **Accepted as a real
defect in the other two modes**, which CB-EV-0030 reports on. Carried
open.
- **12 — reproduction and sample robustness: no problem found.** Every
number reproduced; no conclusion was seed-specific. **The failures were
of construction and interpretation, not sampling.**
## What the reviewer could not check, and it is recorded rather than glossed
The design note itself (criteria quoted from CB-EV-0030, not read from
source); the catalog digest, which the reviewer could not find and
reported as **unverified rather than absent**; `--variant` on the CLI;
`make cost`; and the two non-SHARED modes under `reactive`.
**The catalog digest is a real gap.** CB-WP-0038 T01's control said *"the
catalog is vendored with a digest, like every other borrowed file"*, and
`PROVENANCE.md` records digests for the ten CSVs and **not** for
`catalog.yaml` or the H1 package. The control was claimed and not met.
---
## What this cost, and what it bought
The review found **five fatal defects in numbers that were one step from
another repository's design decision**, and four of the five were errors
of the exact class this project has been cataloguing since ADR-0018 —
correct computation, wrong subject.
**The instrument caught the instrument's author.** CB-WP-0039 was itself
written to correct CB-EV-0030, and it introduced worse errors than the
ones it fixed. **The lesson is not "review works" — it is that a pass
written to correct a previous pass inherits none of its caution.**

View file

@ -50,13 +50,29 @@ def vendored_files():
return sorted(f for f in os.listdir(d) if f.endswith(".csv"))
# CB-WP-0038 vendored two things that are NOT inside the edition
# directory: `editions/catalog.yaml`, which selects between packages and
# so belongs above them, and the `h1-problem-stress` experiment package.
#
# Their digests were CLAIMED by that pass and never recorded. The
# adversarial review (CB-REV-0001) could not find them and reported the
# control unverified — correctly. Recorded relative to `editions/`.
SIBLINGS = "../"
def sibling_files():
"""Recorded paths that live beside the edition rather than in it."""
return sorted(f for f in recorded() if f.startswith(SIBLINGS))
def check():
want = recorded()
print("edition-check — vendored data against its provenance")
rc = 0
present = vendored_files()
undocumented = [f for f in present if f not in want]
siblings = sibling_files()
present = vendored_files() + siblings
undocumented = [f for f in vendored_files() if f not in want]
if undocumented:
print(f" [FAIL] vendored with no recorded digest: {', '.join(undocumented)}")
rc = 1
@ -69,6 +85,7 @@ def check():
if name not in want:
continue
have = digest(os.path.join(ROOT, EDITION, name))
# `../x` resolves out of the edition dir, which is the point.
if have != want[name]:
print(f" [FAIL] {name} does not match its recorded digest")
print(f" recorded {want[name]}\n actual {have}")
@ -125,11 +142,18 @@ def self_test():
chk("every vendored file has a recorded digest",
all(f in want for f in present),
"a file added without a digest must fail, not be skipped")
# `present` is the edition's own CSVs plus the sibling paths recorded
# for the catalog and the experiment package (CB-WP-0038).
everything = present + sibling_files()
chk("every digest names a file that is here",
all(f in present for f in want),
all(f in everything for f in want),
"a stale digest is a lie with a filename")
chk("digests match the real files",
all(digest(os.path.join(ROOT, EDITION, f)) == want[f] for f in present))
all(digest(os.path.join(ROOT, EDITION, f)) == want[f] for f in everything))
chk("the sibling packages are covered",
len(sibling_files()) >= 3,
"catalog.yaml and rules_delta.yaml decide WHAT WE MEASURED; "
"CB-WP-0038 claimed digests for them and recorded none")
# The control that matters: a changed byte must be detected.
import tempfile

View file

@ -64,27 +64,47 @@ state_hub_task_id: "2c509cdb-aedb-4dce-a21f-f16bcdf17d80"
- **the answer may be that H1 still fails**, and that is reported as
plainly as the other outcome.
**Done 2026-08-08.**
**Done 2026-08-08, then CORRECTED after adversarial review**
([CB-REV-0001](../reviews/CB-REV-0001-h1.md)).
[CB-EV-0031](../evidence/CB-EV-0031-a-seat-that-does-not-regulate.md).
**It changed CB-EV-0030's verdict.** H1's criteria 1 and 2 are **met** for
the seat H1 was aimed at: DARVO arms 400 times per cell and ATTACK is
selected 3 times per seat per game. The earlier "H1 does nothing" was a
statement about greedy, which grounds the moment the gate bites.
> **This task's own control — "exactly one preference differs from
> greedy" — was false when it was marked done.** The policy differed in
> five places, including `SpendFreedom`, which made the seat burn its
> Freedom token in round one of every game: a second change to the exact
> mechanism under study. **Every number below was measuring that.**
>
> `GreedyPolicy::rank` is now public and the policy delegates to it,
> overriding one match arm — so the control is structurally true rather
> than asserted in a comment.
**Criterion 3 fails harder**: reactive wins nothing, at any seat count.
**It changed CB-EV-0030's verdict**, and that part survives: H1 does reach
the unregulated seat. DARVO arms **2 per seat per game**, scaling with the
table — the earlier flat "400 in every cell" was the broken policy.
**The larger finding is about the baseline, not H1.** Greedy and reactive
play *identically* under baseline — same wins, zero attacks, zero DARVO —
and **peak Stress across 3,200 baseline games was 1**, against a starting
value of 2. The gate at 4, the arm at 5 and the Freedom token are all
unreachable. That is a deeper account of F17 than F17 has, and it is
**not raised as a finding here** because it wants the plural panel first.
**Criterion 3's verdict is corrected and was wrong**: reactive wins
**66 at 2p against greedy's 68**, not "nothing at any seat count". It wins
nothing at 3p and above, and so does greedy.
**A constant was investigated rather than reported.** `darvo` was exactly
400 in every cell while `atk` scaled properly with seats. Six-player final
Stress is `[5, 5, 4, 4, 4, 4]` every seed: **H1-B holds the attacker at 4,
below the arm, and pushes its targets to 5** — the self-soothe suppresses
DARVO in the aggressor and concentrates it in the attacked. The direction
follows from H1-B's arithmetic; **the number 2 is partly an artifact of
`reactive`'s first-legal targeting**, and is labelled as such.
**The baseline observation survives only in a narrower form.** Peak Stress
*held* across the **1,600** baseline games was **2** — the starting value,
never exceeded. The original said **1** because the metric maximised over
`StressSet` event payloads and the starting value is written by `setup`,
never by an event: **wrong subject**, in the pass that was written to
correct a wrong-subject error.
And the generalisation was refuted by this repo's own harness: the rank-95
policy *is* a reckless policy and it drives Stress to 5 under **baseline**.
What survives: under the two policies here, neither of which selects ATTACK
under baseline, **no Stress is ever added** — ATTACK is the sole inbound
pressure.
**The H1-B suppression claim is WITHDRAWN.** It was inferred from a
constant that the broken policy produced, and disabling H1-B under the
corrected policy changes the arm count by **exactly zero** in every cell.
The inference was also invalid on its own terms: final Stress does not
record who armed, because `DarvoEnded` resets the stage and REVERSE gives
its owner 2.
**The pass hedged the wrong variable** — it disclaimed "the number 2" and
defended "the direction", and the direction is what failed.