CB-REV-0002: round 2, and the corrections were not approvable either
Some checks failed
ci / check (push) Failing after 4s
Some checks failed
ci / check (push) Failing after 4s
Three FATAL, five SERIOUS. The substance of round 1's corrections held — Reactive is genuinely one arm different, the five replacement controls are non-inert, the inert metric is right, the numbers reproduce. What failed were the CLAIMS about them, and two defects the corrections introduced. FATAL 1: the fix for round 1's #11 did not fix it. The assertion was `games + setup_fails == 200`, and a refused setup increments setup_fails while skipping games — so the sum is invariant under exactly the failure it claimed to catch. Injecting setup failures gave exit 0 over 196-game columns. Now asserts games == GAMES, verified to exit 101. FATAL 2: the correction to the selective-column FATAL was itself selective. "81-1000 per cell, baseline AND H1" and "31-1000" twelve lines apart, both taken from the baseline row; under H1 rank-75 arms are 59/0/0/0. Every cell is now printed rather than summarised, and the corrected verdict is the opposite of the one it replaced: under rank-75, H1 REDUCES DARVO arms to zero at 3p and above. FATAL 3: "DARVO arms 2 per seat per game" is 1 per seat per game, exactly, at every band. SERIOUS: the tiebreak oracle asserted only that the winner set CHANGED, so reversing the tiebreak left it green; the #13 defect's impact was claimed and never measured (72,000 games: zero divergences — real in principle, witnessed only by a constructed board); a 29-of-363 citation pointed at a file that did not contain it (round 1's reviewer did report it, and it was never transcribed — the record was wrong, not the number); the harnesses were run by NO GATE, so every published figure came from a manual run of an ungated binary, including the assertion added for #1; and edition-check's sibling handling — added by the last correction — was self-certifying, crashed instead of failing, and counted Markdown lines as coverage. Now discovered on disk, and it found a real gap on its first run: Rules_Text.csv vendored with no digest. Also: "peak Stress held" was dead code kept quiet by `let _ = held;` — the numbers were right by coincidence. make panels is now a registered gate. Round 3 is owed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
84aa09264c
commit
da58e78e4a
10 changed files with 285 additions and 56 deletions
12
Makefile
12
Makefile
|
|
@ -36,7 +36,7 @@ PORT ?= 0
|
|||
# Every cargo recipe runs at the repo root; the shell does not persist cd.
|
||||
IN_REPO := cd $(REPO) &&
|
||||
|
||||
.PHONY: help ground check test sim bench bench-test coverage dep-weight cost cost-test cost-pin cost-budget shape-budget cost-mix loop-lint self-tests env-test task-done status facts-check facts-gen mutation-check size-metrics runtime-metrics build-time am6 am7 am8 edition-check replay-test loc play gate-review all \
|
||||
.PHONY: help ground check test sim bench bench-test coverage dep-weight cost cost-test cost-pin cost-budget shape-budget cost-mix loop-lint self-tests env-test task-done status facts-check facts-gen mutation-check size-metrics runtime-metrics build-time am6 am7 am8 edition-check replay-test loc play gate-review panels all \
|
||||
design difficulty trials
|
||||
# `design`, `difficulty` and `trials` were added by CB-WP-0022, CB-WP-0025
|
||||
# and CB-WP-0027 and none was declared here. Only `trials` revealed it, by
|
||||
|
|
@ -228,6 +228,16 @@ trials:
|
|||
difficulty:
|
||||
@cargo run --release -q -p games-ground --example difficulty
|
||||
|
||||
# CB-REV-0002 #7: the H1 measurement harnesses were run by NO gate. Every
|
||||
# number in CB-EV-0030 and CB-EV-0031 came from a manual invocation of an
|
||||
# ungated binary -- so the assertion added to catch short cells was
|
||||
# unreachable from `make`, and "what would the harness report if the work
|
||||
# silently stopped" answered: green, and nothing else.
|
||||
## the variant panels: ATTACK's value, and regulation under H1
|
||||
panels:
|
||||
@cargo run --release -q -p games-ground --example attack-value
|
||||
@cargo run --release -q -p games-ground --example regulation
|
||||
|
||||
# CB-WP-0022 T05: the design-finding register, reported over
|
||||
# specs/GroundRules.md. Shows the QUEUE by default; the log of closed
|
||||
# findings is a line, not a listing, because a default view that mixes
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ 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
|
||||
sha256 62785f5e7e245c60171624d15de2f40187a44fec54f93c7d9705cf52584b1078 ../experiments/h1-problem-stress/Rules_Text.csv
|
||||
```
|
||||
|
||||
**`rules_delta.yaml` is the load-bearing one**: it is the executable
|
||||
|
|
|
|||
|
|
@ -20,18 +20,33 @@ 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 31–1000 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.
|
||||
> **CORRECTED TWICE.** Round 1 found criteria 1 and 2 rendered as flat
|
||||
> failures **on the greedy column alone**, while this pass's own harness
|
||||
> printed non-zero DARVO arms in the rank-75 and rank-95 columns — the
|
||||
> selective-column move, in the file that names it.
|
||||
>
|
||||
> **Round 2 found the correction was itself selective, and its numbers
|
||||
> wrong** ([`CB-REV-0002`](../reviews/CB-REV-0002-h1.md) #2): it quoted
|
||||
> "81–1000 per cell … baseline *and* H1" and, twelve lines away,
|
||||
> "31–1000". Both ranges came from the **baseline** rank-75 row. Under
|
||||
> **H1**, rank-75 arms are `2p 59, 3p 0, 4p 0, 6p 0` — three cells at zero
|
||||
> and the fourth below the stated floor.
|
||||
>
|
||||
> **Every cell is now given**, because two attempts at summarising this
|
||||
> into a range have now produced three wrong numbers.
|
||||
|
||||
**DARVO arms per 200-game cell, SHARED GROUND** (all three modes agree on
|
||||
arms; they differ only in who wins):
|
||||
|
||||
| | greedy | rank-75 | rank-95 |
|
||||
|---|---:|---:|---:|
|
||||
| **baseline** 2p / 3p / 4p / 6p | 0 / 0 / 0 / 0 | 81 / 125 / 218 / 31 | 400 / 805 / 1000 / 1000 |
|
||||
| **H1** 2p / 3p / 4p / 6p | 0 / 0 / 0 / 0 | **59 / 0 / 0 / 0** | 600 / 870 / 941 / 970 |
|
||||
|
||||
| # | criterion | verdict |
|
||||
|---|---|---|
|
||||
| 1 | DARVO arm rate non-trivial, "not 0/500" | **not a flat fail.** **0** under greedy; **81–1000 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 |
|
||||
| 1 | DARVO arm rate non-trivial, "not 0/500" | **depends entirely on the policy, and H1 does not improve it for the middle one.** Zero under greedy in both. Under rank-75, H1 **reduces** arms to zero at 3p and above. Only rank-95 — a seat that always attacks — arms freely, and it does so **under the baseline too** |
|
||||
| 2 | ATTACK selection rises for some subpopulation | **no, for the policy the criterion is about.** Greedy attacks 0 times under both. rank-75's attacks fall 604 → 180 at 2p and **592/923/389 → 0** at 3p/4p/6p. Only the deliberately unregulated seat of CB-EV-0031 rises, and it never wins |
|
||||
| 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 |
|
||||
|
||||
|
|
|
|||
|
|
@ -45,9 +45,10 @@ rather than a claim. SHARED GROUND, 200 games per cell, all 200 ran, and
|
|||
| 4p | 0 | 0 | 0 | 4 | 0 | 1600 | 800 | **5** |
|
||||
| 6p | 0 | 0 | 0 | 4 | 0 | 2400 | 1200 | **5** |
|
||||
|
||||
**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.
|
||||
**H1's mechanism does reach the unregulated seat.** DARVO arms **exactly
|
||||
1 per seat per game** — 600/(200×3), 800/(200×4), 1200/(200×6) — and 0.91
|
||||
at 2p. The first correction said **2** per seat per game, which is wrong
|
||||
by a factor of two and was caught by round 2 (#3).
|
||||
|
||||
**Criterion 3's verdict is corrected.** The original said reactive *"wins
|
||||
nothing, at any seat count"*. **False.** At 2p it wins **66 against
|
||||
|
|
@ -95,9 +96,11 @@ and a final-Stress signature of `[5, 5, 4, 4, 4, 4]`.
|
|||
|
||||
**Withdrawn on two independent grounds, both found by the review.**
|
||||
|
||||
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.
|
||||
1. **The constant was the broken policy** — but a constant remains, and
|
||||
saying otherwise was wrong (round 2, #12). With the one-arm-override
|
||||
policy `darvo` is **exactly `seats × games`** at 3p and above. The
|
||||
constant moved from 400 to `n·games`; it did not dissolve, and whatever
|
||||
forces exactly one arm per seat per game is still unexplained.
|
||||
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.
|
||||
|
|
@ -132,13 +135,20 @@ CB-WP-0038 asserted it because the code shares `resolve_attack`; nothing
|
|||
tested it, and the withdrawn §3 ran straight through this path.
|
||||
`h1b_soothes_the_darvo_stage_attack_too` now covers it, mutation-verified.
|
||||
|
||||
**Round-5 pressure did not reach the score — a real defect, not a
|
||||
reporting one.** `end_round_events` scored from `self` while H1-A's
|
||||
pressure went into `work`, and `score` reads Stress for the GR-E03 and
|
||||
GR-E04 tiebreaks. The final round's pressure was invisible to **the two
|
||||
modes CB-EV-0030 reports on**. Fixed, and the test uses the case that
|
||||
actually bites: uniform pressure preserves an ordering, so it takes the
|
||||
**clamp** at 5 to collapse a gap and change who wins.
|
||||
**Round-5 pressure did not reach the score.** `end_round_events` scored
|
||||
from `self` while H1-A's pressure went into `work`, and `score` reads
|
||||
Stress for the GR-E03 and GR-E04 tiebreaks. Fixed, and the test uses the
|
||||
case that actually bites: uniform pressure preserves an ordering, so it
|
||||
takes the **clamp** at 5 to collapse a gap and change who wins.
|
||||
|
||||
**Its impact was claimed and never measured, and the measurement is
|
||||
zero** (round 2, #5). This file said the pressure was invisible to *"the
|
||||
two modes CB-EV-0030 reports on"* without checking. The reviewer ran
|
||||
~72,000 games across all three modes with a divergence detector and found
|
||||
**no divergence at all**; `attack-value`'s output is byte-identical with
|
||||
the fix and without it. **The defect is real in principle and its only
|
||||
witness is a hand-constructed board.** It is worth fixing and it changed
|
||||
nothing that has been reported.
|
||||
|
||||
**Inert arms, and a second wrong-subject error caught on the way.** A
|
||||
DARVO arm at the End of Round 5 can never advance a stage — `GameEnded`
|
||||
|
|
@ -156,8 +166,15 @@ follows immediately — and ground-game's criterion 1 is about DARVO
|
|||
every cell**, because it tested `g.rounds >= 5` — a property of the
|
||||
*game*, not of the *event*. Every arm in every completed game was marked
|
||||
inert, which briefly looked like "criterion 1 is not met after all". An
|
||||
arm is inert when no `RoundEnded` follows it; that figure matches the
|
||||
reviewer's independent 29-of-363.
|
||||
arm is inert when no `RoundEnded` follows it.
|
||||
|
||||
**29-of-363 was independently confirmed twice**, and the citation for it
|
||||
was wrong the first time (round 2, #6): this file credited
|
||||
`CB-REV-0001`, which does not contain the figure. Round 1's reviewer *did*
|
||||
report it — 29 of 363 at 2p, 8% — but only in its message, and it was
|
||||
never transcribed into the review file. **The record is now corrected
|
||||
there.** Round 2 re-derived it independently, by a different definition
|
||||
(no later DARVO event names that player), and agrees in every cell.
|
||||
|
||||
**Criterion 1 stands as met**: 92% of arms at 2p and all of them above are
|
||||
live.
|
||||
|
|
|
|||
|
|
@ -20,9 +20,12 @@ use games_ground::{Action, GroundCommand, GroundState, ScoringMode, Variant};
|
|||
|
||||
/// Greedy, with GROUND demoted below ATTACK. Nothing else differs.
|
||||
///
|
||||
/// **The copy is deliberate.** `GreedyPolicy::rank` is private, and the
|
||||
/// point is to change one line of it while holding the rest identical —
|
||||
/// calling into it would make that impossible to demonstrate.
|
||||
/// **It delegates.** An earlier version re-typed an abridged copy of
|
||||
/// greedy's ranking and called changing one line of the copy "one
|
||||
/// preference"; it differed in five, and the seat burned its Freedom
|
||||
/// token in round one of every game. This comment used to argue for the
|
||||
/// copy, which gave a future maintainer written cover to restore it
|
||||
/// (CB-REV-0002 #11).
|
||||
struct Reactive;
|
||||
|
||||
impl Policy for Reactive {
|
||||
|
|
@ -72,6 +75,10 @@ impl Policy for Reactive {
|
|||
/// inlined so the peak metric cannot silently disagree with setup.
|
||||
const START_STRESS: u8 = 2;
|
||||
|
||||
/// Games per cell. Named once so the assertion and the banner cannot
|
||||
/// disagree — the banner said "200 games per cell" over 196-game columns.
|
||||
const GAMES: u32 = 200;
|
||||
|
||||
struct Cell {
|
||||
games: u32,
|
||||
won: u32,
|
||||
|
|
@ -99,7 +106,7 @@ fn sweep(mode: ScoringMode, variant: Variant, players: u8, reactive: bool) -> Ce
|
|||
setup_fails: 0,
|
||||
inert_arms: 0,
|
||||
};
|
||||
for seed in 0..200u64 {
|
||||
for seed in 0..GAMES as u64 {
|
||||
let Ok(mut st) = GroundState::setup(
|
||||
&Setup {
|
||||
players,
|
||||
|
|
@ -174,20 +181,31 @@ fn sweep(mode: ScoringMode, variant: Variant, players: u8, reactive: bool) -> Ce
|
|||
}
|
||||
if let games_ground::GroundEvent::StressSet { player, stress } = e {
|
||||
held.insert(*player, *stress);
|
||||
c.peak_stress = c.peak_stress.max(*stress);
|
||||
}
|
||||
// Read from `held`, which is the point. The first correction
|
||||
// BUILT `held`, then took the max over event payloads anyway
|
||||
// and silenced the unused binding with `let _ = held;` — so
|
||||
// the comment described code that did not exist (CB-REV-0002
|
||||
// #10). The published figures were right only because the
|
||||
// START_STRESS floor made the two agree.
|
||||
c.peak_stress = c
|
||||
.peak_stress
|
||||
.max(held.values().copied().max().unwrap_or(START_STRESS));
|
||||
}
|
||||
let _ = held;
|
||||
}
|
||||
// Reported as a REFUSAL, not left for a reader to notice a short
|
||||
// column. CB-REV-0001 #11: `games != 200` was printed, never asserted.
|
||||
// **`games`, not `games + setup_fails`** (CB-REV-0002 #1).
|
||||
//
|
||||
// The first version asserted the SUM — and a refused setup increments
|
||||
// `setup_fails` while skipping `games`, so the sum is invariant under
|
||||
// exactly the failure it claimed to catch. It could only ever fire on
|
||||
// a `play` error, the path that was already instrumented. Verified by
|
||||
// injecting setup failures: green, exit 0, and a full table printed
|
||||
// over 196-game columns under a banner reading "200 games per cell".
|
||||
assert_eq!(
|
||||
c.games + c.setup_fails,
|
||||
200,
|
||||
"{players}p {variant:?}: {} games ran and {} setups failed — the cell is short, \
|
||||
so every number in it is over a sample nobody chose",
|
||||
c.games,
|
||||
c.setup_fails
|
||||
c.games, GAMES,
|
||||
"{players}p {variant:?}: only {} of {GAMES} games ran ({} setups refused) — \
|
||||
the cell is short, so every number in it is over a sample nobody chose",
|
||||
c.games, c.setup_fails
|
||||
);
|
||||
if c.setup_fails > 0 {
|
||||
eprintln!(
|
||||
|
|
@ -202,7 +220,7 @@ fn main() {
|
|||
println!("CB-WP-0039 — does H1 reach a seat that does not regulate?\n");
|
||||
println!("`reactive` is greedy with ONE preference changed: GROUND is");
|
||||
println!("demoted below ATTACK, so the seat never grounds to shed Stress.");
|
||||
println!("SHARED GROUND; `won` is group success; 200 games per cell.\n");
|
||||
println!("SHARED GROUND; `won` is group success; {GAMES} games per cell.\n");
|
||||
|
||||
for (vlabel, variant) in [
|
||||
("BASELINE ground-darvo-r0", Variant::Baseline),
|
||||
|
|
|
|||
|
|
@ -2409,12 +2409,21 @@ mod tests {
|
|||
panic!("round 5 did not end the game");
|
||||
};
|
||||
assert!(outcome.group_success, "the fixture must qualify");
|
||||
|
||||
// **The oracle names the expected winners** (CB-REV-0002 #4).
|
||||
// The first version asserted only that the set CHANGED, so
|
||||
// reversing GR-E03's tiebreak — making HIGHER Stress win —
|
||||
// left it green: the set still changed, just wrongly.
|
||||
let pre = s.score();
|
||||
assert_ne!(
|
||||
outcome.winners, pre.winners,
|
||||
"the outcome ignores the final round's pressure — scored from `self`. \
|
||||
pre={:?} post={:?}",
|
||||
pre.winners, outcome.winners
|
||||
assert_eq!(
|
||||
pre.winners,
|
||||
vec![seats[1]],
|
||||
"before the pressure, the seat at Stress 4 wins on the tiebreak"
|
||||
);
|
||||
assert_eq!(
|
||||
outcome.winners,
|
||||
vec![seats[0], seats[1]],
|
||||
"after it both are clamped to 5, so they share"
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
14
gates.toml
14
gates.toml
|
|
@ -163,3 +163,17 @@ caught = [
|
|||
"CB-WP-0013: forced SH-3's re-justification and then its retirement. `make gate-review` had reported SH-3 as a standing breach for seven passes with zero actions taken, which is this registry's own ritual test (ADR-0006 D4); asking what it had ever caught is what exposed that the metric could not read above ~0% in the window it was gated on (ADR-0008 D1)",
|
||||
]
|
||||
retire_if = "it has retired, tightened, or forced the re-justification of nothing by its review date — then it is a ritual, and ADR-0006 D4 says rituals cash out or go"
|
||||
|
||||
[[gate]]
|
||||
id = "CB-REV-0002/7"
|
||||
name = "variant panels"
|
||||
target = "panels"
|
||||
checks = "the H1 measurement harnesses actually run, and a short cell fails rather than printing a number a reader must notice"
|
||||
notes = """
|
||||
Registered because the second adversarial review asked what the harness
|
||||
would report if the work silently stopped, and the answer was "green, and
|
||||
nothing else": `attack-value` and `regulation` were wired into no target,
|
||||
so every figure in CB-EV-0030 and CB-EV-0031 came from a manual run of an
|
||||
ungated binary -- including the assertion added to catch short cells,
|
||||
which was unreachable from `make`.
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -97,7 +97,10 @@ Stress is ever added. ATTACK is the sole inbound pressure.
|
|||
- **11 — `regulation.rs` still skips setup failures silently.** Conceded
|
||||
and **fixed**: counted, and a short cell now fails an assertion rather
|
||||
than printing a number a reader must notice.
|
||||
- **13 — round-5 arms, and scoring from `self`.** Both **fixed**, and the
|
||||
- **13 — round-5 arms, and scoring from `self`.** *(Round 1's reviewer
|
||||
reported the arm figure as **29 of 363 at 2p, 8%**, under its
|
||||
`StrictReactive`. That number was omitted when this file was written and
|
||||
later cited to it — see CB-REV-0002 #6. Recorded here now.)* Both **fixed**, and the
|
||||
second was a real defect rather than a reporting one: `score` reads
|
||||
Stress for the GR-E03/GR-E04 tiebreaks, so the final round's pressure
|
||||
was invisible to the two modes CB-EV-0030 reports on. Inert arms are now
|
||||
|
|
|
|||
120
reviews/CB-REV-0002-h1.md
Normal file
120
reviews/CB-REV-0002-h1.md
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
# CB-REV-0002 — re-review of the H1 corrections
|
||||
|
||||
Round 2 of the tier-L review. A **fresh** agent, not the round-1 reviewer,
|
||||
because a re-review by the same reviewer inherits its own sampling. Run
|
||||
2026-08-08 against the corrections made after
|
||||
[`CB-REV-0001`](CB-REV-0001-h1.md).
|
||||
|
||||
> **Verdict: not approvable.** Three FATAL, five SERIOUS.
|
||||
>
|
||||
> **The substance of round 1's corrections held. The claims about them did
|
||||
> not**, and two of the defects were introduced *by* the corrections.
|
||||
|
||||
The reviewer was briefed on the specific risk — **the author of the
|
||||
corrections is the author of the errors** — and re-derived on five
|
||||
independent seed windows.
|
||||
|
||||
---
|
||||
|
||||
## What it could not break, after trying
|
||||
|
||||
Stated first, because it is what round 1's corrections were for.
|
||||
|
||||
- **`Reactive` is genuinely one arm different.** The reviewer built a
|
||||
`PureDelegate` with the same loop shape and *no* override, hashed every
|
||||
command of every game, and got **identical output to `GreedyPolicy` in
|
||||
8/8 cells over 500 seeds**, both variants. Round 1's worst finding is
|
||||
properly closed. *Residual: nothing asserts it; it is true by
|
||||
construction, not by test.*
|
||||
- **All five replacement controls are non-inert**, re-verified by
|
||||
mutation, and the SOLVE control is red on nine alternate seeds.
|
||||
- **`h1b_soothes_the_darvo_stage_attack_too` really covers that path** —
|
||||
disabling H1-B *only* for the DARVO extra Attack reddens that test alone.
|
||||
- **The inert-arm metric is right**, agreeing exactly with an independent
|
||||
definition in every cell of every window.
|
||||
- **Every number in CB-EV-0031 §1 reproduces** and is stable across five
|
||||
windows.
|
||||
- **`score()` from `work` is correct per the delta and changes no baseline
|
||||
path.**
|
||||
|
||||
## The three fatal ones
|
||||
|
||||
### 1. The fix for round 1's #11 did not fix it
|
||||
|
||||
The assertion was `games + setup_fails == 200`. **A refused setup
|
||||
increments `setup_fails` and skips `games`, so the sum is invariant under
|
||||
exactly the failure it claimed to catch.** Injecting setup failures gave
|
||||
exit 0 and a full table over 196-game columns, under a banner reading
|
||||
"200 games per cell".
|
||||
|
||||
**Conceded.** Now `assert_eq!(c.games, GAMES)`, verified to exit 101 under
|
||||
injected failures, with `GAMES` named once so the banner and the assertion
|
||||
cannot disagree.
|
||||
|
||||
### 2. The correction to the selective-column FATAL was itself selective
|
||||
|
||||
CB-EV-0030's correction quoted *"81–1000 per cell … baseline **and** H1"*
|
||||
and, twelve lines away, *"31–1000"*. **Both came from the baseline
|
||||
rank-75 row.** Under H1, rank-75 arms are `2p 59, 3p 0, 4p 0, 6p 0`.
|
||||
|
||||
**Conceded, and it is the same error twice.** The remedy for choosing a
|
||||
favourable column chose a favourable column. **Every cell is now printed**
|
||||
rather than summarised, because two attempts at a range produced three
|
||||
wrong numbers — and the corrected verdict is the opposite of the one it
|
||||
replaced: under rank-75, **H1 reduces DARVO arms to zero** at 3p and above.
|
||||
|
||||
### 3. "DARVO arms 2 per seat per game" is off by a factor of two
|
||||
|
||||
It is **1 per seat per game**, exactly, at every band: 600/(200×3),
|
||||
800/(200×4), 1200/(200×6). Deterministic across five windows.
|
||||
|
||||
**Conceded.** A headline number, wrong, in a corrected section.
|
||||
|
||||
## The serious ones
|
||||
|
||||
| # | challenge | outcome |
|
||||
|---|---|---|
|
||||
| 4 | the tiebreak test's oracle was `assert_ne!` — "the set changed", not "changed correctly". Reversing GR-E03's tiebreak left it green | **conceded, fixed.** The oracle now names the expected winners before and after; the reviewer's M7 goes red |
|
||||
| 5 | the #13 "real defect" was claimed to affect the reported modes and never measured | **conceded.** ~72,000 games across three modes: **zero divergences**, `attack-value` byte-identical. Real in principle, and its only witness is a constructed board. Now stated |
|
||||
| 6 | "matches the reviewer's independent 29-of-363" cites a file that does not contain it | **conceded, with a correction to the correction.** Round 1's reviewer *did* report 29 of 363 — in its message, never transcribed into the review file. So the figure is real and the **record** was not. Recorded in CB-REV-0001 now |
|
||||
| 7 | `regulation.rs` and `attack-value.rs` are run by **no gate** | **conceded, and it is the sharpest finding.** Every number in both evidence files came from a manual run of an ungated binary — including the assertion added for #1, unreachable from `make`. Now `make panels`, registered in `gates.toml` |
|
||||
| 8 | `edition-check`'s sibling handling was self-certifying: it read the file list *out of PROVENANCE*, crashed instead of failing on an absent file, and "coverage" counted Markdown lines | **conceded — a defect introduced by the correction.** Siblings are now discovered on disk; an absent recorded file FAILs; undocumented siblings FAIL. **It found a real gap on its first run**: `Rules_Text.csv` was vendored with no digest |
|
||||
|
||||
## The minor ones
|
||||
|
||||
- **9 — the CSV falsifier ran over YAML.** Fixed; it now filters to `.csv`.
|
||||
- **10 — "peak Stress held" was dead code.** `held` was built, never read,
|
||||
and `let _ = held;` kept clippy quiet; the metric was still max over
|
||||
payloads plus a floor. **The published numbers were right by
|
||||
coincidence.** Now actually read from `held`, and the figures are
|
||||
unchanged — which is how it stayed hidden.
|
||||
- **11 — `Reactive`'s doc comment still argued for the copy** that round 1
|
||||
ruled fatal, giving cover to restore it. Rewritten.
|
||||
- **12 — §3's withdrawal ground was wrong.** *"There is no constant to
|
||||
explain"* — there is: `darvo == seats × games`, exactly. The constant
|
||||
moved from 400 to `n·games` rather than dissolving, and **what forces
|
||||
exactly one arm per seat per game is still unexplained.**
|
||||
- **13 — assorted**, including that the delta's DARVO clause is
|
||||
conditional (*"if they share the same path"*) where the test's comment
|
||||
says "outright".
|
||||
|
||||
## What the reviewer could not check
|
||||
|
||||
Digest freshness against upstream (`edition-check` reports
|
||||
`upstream not checked out` when the sibling repo is absent — it did not
|
||||
have it); several untouched modules; ground-game's design note; felt-play.
|
||||
|
||||
---
|
||||
|
||||
## The pattern, now visible across two rounds
|
||||
|
||||
Round 1 found five fatal errors of the form *correct computation, wrong
|
||||
subject*. **Round 2 found three more, in the corrections to them** — an
|
||||
assertion invariant under its own target, a selective fix for a selective
|
||||
report, and a rate wrong by a factor of two.
|
||||
|
||||
> **A correction is new work and deserves the scrutiny of new work.** It
|
||||
> arrives feeling like a conclusion, and that is exactly when it is least
|
||||
> examined.
|
||||
|
||||
**Round 3 is owed.** Same reason as round 2.
|
||||
|
|
@ -59,10 +59,27 @@ def vendored_files():
|
|||
# control unverified — correctly. Recorded relative to `editions/`.
|
||||
SIBLINGS = "../"
|
||||
|
||||
# Discovered ON DISK, not read out of PROVENANCE (CB-REV-0002 #8). The
|
||||
# first version listed siblings by reading the digest block, which made
|
||||
# three controls vacuous at once: a recorded-but-absent file could never
|
||||
# be reported missing (it was in `present` by construction), an absent one
|
||||
# raised FileNotFoundError from `digest` instead of failing with the
|
||||
# designed message, and "the sibling packages are covered" counted lines
|
||||
# in a Markdown file -- it passed with all three files deleted.
|
||||
SIBLING_GLOBS = ("catalog.yaml", "experiments/*/rules_delta.yaml", "experiments/*/*.csv")
|
||||
|
||||
|
||||
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))
|
||||
"""Sibling packages that are on disk, as `../`-relative paths."""
|
||||
import glob as _glob
|
||||
|
||||
root = os.path.join(ROOT, EDITION, SIBLINGS)
|
||||
out = []
|
||||
for pattern in SIBLING_GLOBS:
|
||||
for hit in _glob.glob(os.path.join(root, pattern)):
|
||||
rel = os.path.relpath(hit, os.path.join(ROOT, EDITION))
|
||||
out.append(rel.replace(os.sep, "/"))
|
||||
return sorted(out)
|
||||
|
||||
|
||||
def check():
|
||||
|
|
@ -72,7 +89,7 @@ def check():
|
|||
|
||||
siblings = sibling_files()
|
||||
present = vendored_files() + siblings
|
||||
undocumented = [f for f in vendored_files() if f not in want]
|
||||
undocumented = [f for f in vendored_files() + siblings if f not in want]
|
||||
if undocumented:
|
||||
print(f" [FAIL] vendored with no recorded digest: {', '.join(undocumented)}")
|
||||
rc = 1
|
||||
|
|
@ -81,10 +98,15 @@ def check():
|
|||
print(f" [FAIL] a digest is recorded for a file that is not here: {', '.join(missing)}")
|
||||
rc = 1
|
||||
|
||||
for name in present:
|
||||
for name in [f for f in present if f.endswith(".csv")]:
|
||||
if name not in want:
|
||||
continue
|
||||
have = digest(os.path.join(ROOT, EDITION, name))
|
||||
path = os.path.join(ROOT, EDITION, name)
|
||||
if not os.path.exists(path):
|
||||
print(f" [FAIL] {name} is recorded but not on disk")
|
||||
rc = 1
|
||||
continue
|
||||
have = digest(path)
|
||||
# `../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")
|
||||
|
|
@ -96,7 +118,7 @@ def check():
|
|||
# ADR-0015 D3's falsifier, checked rather than asserted: the hand
|
||||
# reader handles commas inside quotes and NOTHING ELSE. A doubled
|
||||
# quote or an embedded newline means `csv` is the answer after all.
|
||||
for name in present:
|
||||
for name in [f for f in present if f.endswith(".csv")]:
|
||||
raw = open(os.path.join(ROOT, EDITION, name), encoding="utf-8-sig").read()
|
||||
if '""' in raw:
|
||||
print(f" [FAIL] {name} contains a doubled quote — ADR-0011's revisit")
|
||||
|
|
@ -116,7 +138,7 @@ def check():
|
|||
print(" [----] upstream not checked out — freshness UNVERIFIED")
|
||||
print(f" expected {UPSTREAM_DIR}")
|
||||
return rc
|
||||
for name in present:
|
||||
for name in [f for f in present if f.endswith(".csv")]:
|
||||
up = os.path.join(UPSTREAM_DIR, name)
|
||||
if not os.path.exists(up):
|
||||
print(f" [FAIL] {name} is not in upstream — where did it come from?")
|
||||
|
|
@ -151,9 +173,9 @@ def self_test():
|
|||
chk("digests match the real files",
|
||||
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")
|
||||
all(f in want for f in sibling_files()) and len(sibling_files()) >= 3,
|
||||
"catalog.yaml and rules_delta.yaml decide WHAT WE MEASURED; the first "
|
||||
"version counted lines in PROVENANCE and passed with the files deleted")
|
||||
|
||||
# The control that matters: a changed byte must be detected.
|
||||
import tempfile
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue