clay-borg/games/ground/examples/module-panel.rs

312 lines
12 KiB
Rust
Raw Normal View History

CB-WP-0050: every configuration, faceted by aspect — and F31 module-panel sweeps points in aspect space the way scenario-panel sweeps boards: one module at a time with every other aspect held, then the profiles where an interaction is the hypothesis. F31: attack_relief.self_soothe_ge4 HAS NEVER FIRED. Zero ATTACKs in every cell, every seat band, both bots. The module acts only on an uncancelled ATTACK by a seat at Stress >= 4, and greedy ranks Ground 100 at the gate against Attack's 10 -- so at exactly the position where self-soothe would pay, GROUND wins. ModuleAwarePolicy adds 55 and that is still not enough. `unplayed`, not `inert`: the kernel implements it correctly and nothing has ever given it an opportunity. This reaches backwards: CB-EV-0030's H1 verdict rests on its flat-pressure half alone, because H1's other half never had an opportunity in those games either. Also: problem_stress.scoped is the only module with a measured effect (3p 85->60 greedy, 86->63 module-aware, peak Stress 2->4); flat_any_open drives group success to 0 at every band, reproducing the H1 rejection from the module side; and scoped_plus_attack_soothe is EXACTLY scoped alone -- necessarily, given F31 -- so the catalog's first intentional multi-aspect combination cannot currently be evaluated as a combination. THE PANEL'S OWN DEFECT, first run: it printed 85/86 for a module that never fired -- real-looking numbers inviting "measured, no effect" when no seat ever created the precondition. Its docstring already said it would not do that; the claim was written before the behaviour was. First fix marked whole rows unmeasured, which threw away h1's real flat-pressure result; the shipped fix names the specific module and keeps the row's numbers, which are real for the modules that did fire. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 01:45:53 +02:00
//! Every configuration the catalog offers, faceted by aspect
//! (CB-WP-0050, CB-RES-0010 §5.4).
//!
//! `scenario-panel` sweeps boards. This sweeps **points in aspect
//! space**: each aspect held at its default while one module varies, then
//! the profiles where the hypothesis is an interaction.
//!
//! ## What it will not do
//!
//! **It does not omit what it cannot run.** A module with no kernel path
//! is printed as `no kernel path` rather than left out — a panel whose
//! absences are invisible is how `end_condition` and `problem_deal` would
//! quietly stop being questions. CB-RES-0010 §5.6.
//!
//! **It does not report a module as failed when nothing could have
//! tested it.** Both policies are named per row, and the honest reading
//! of a flat row under `greedy` is that greedy cannot see the module —
//! F27's shape, and the reason `ModuleAwarePolicy` exists.
use cb_game_runtime::{ScenarioGame, Setup};
use cb_kernel::PlayerId;
CB-WP-0050 T02: F31 falsified — the module is unreachable, then real GateAttackPolicy ranks ATTACK above GROUND at the stress gate and delegates everything else. A PROBE, not a better bot: it wins 12/100 where greedy wins 60/100 under the same module, and the panel's banner says so, because a column that looks like a policy comparison will be read as one. (a) THE MODULE IS UNREACHABLE IN THE PRINTED GAME. Selected alone it still never fires: peak Stress never exceeds 2, so the gate never bites and no ATTACK is ever gated. A module can be unreachable because of an aspect it does not name -- attack_relief needs a problem_stress module before it can act at all, and nothing in its own declaration says so. (b) ONCE REACHABLE IT IS REAL. Holding the probe fixed and varying only the module: group wins 12->21, 19->28, 50->57 at 3/4/6p, and DARVO arms 299->221, 294->213, 334->164. Under flat pressure the same shape appears in DARVO alone: h1 arms 200 against flat_any_open's 300/400/600. Stated as the conditional it is: GIVEN seats that attack at the gate. Not advice to attack, and not evidence against F17. AND IT CHANGES WHAT WE TOLD GROUND-GAME. CB-EV-0030 rejected H1 with policies that never attacked, so H1-B was inert for every game behind that verdict. The rejection stands on flat pressure alone -- wins are 0 either way -- but "H1-B does nothing" was never established and is now known to be false. We owe them that correction. Sensitivity: vary only the ATTACK rank. At 10 (greedy) and +55 (module-aware) the module never fires; at 110 it fires in every game. Nothing about the module changed -- only whether any seat gave it a turn. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 02:30:08 +02:00
use games_ground::bot::{play, GateAttackPolicy, GreedyPolicy, ModuleAwarePolicy, Policy};
CB-WP-0050: every configuration, faceted by aspect — and F31 module-panel sweeps points in aspect space the way scenario-panel sweeps boards: one module at a time with every other aspect held, then the profiles where an interaction is the hypothesis. F31: attack_relief.self_soothe_ge4 HAS NEVER FIRED. Zero ATTACKs in every cell, every seat band, both bots. The module acts only on an uncancelled ATTACK by a seat at Stress >= 4, and greedy ranks Ground 100 at the gate against Attack's 10 -- so at exactly the position where self-soothe would pay, GROUND wins. ModuleAwarePolicy adds 55 and that is still not enough. `unplayed`, not `inert`: the kernel implements it correctly and nothing has ever given it an opportunity. This reaches backwards: CB-EV-0030's H1 verdict rests on its flat-pressure half alone, because H1's other half never had an opportunity in those games either. Also: problem_stress.scoped is the only module with a measured effect (3p 85->60 greedy, 86->63 module-aware, peak Stress 2->4); flat_any_open drives group success to 0 at every band, reproducing the H1 rejection from the module side; and scoped_plus_attack_soothe is EXACTLY scoped alone -- necessarily, given F31 -- so the catalog's first intentional multi-aspect combination cannot currently be evaluated as a combination. THE PANEL'S OWN DEFECT, first run: it printed 85/86 for a module that never fired -- real-looking numbers inviting "measured, no effect" when no seat ever created the precondition. Its docstring already said it would not do that; the claim was written before the behaviour was. First fix marked whole rows unmeasured, which threw away h1's real flat-pressure result; the shipped fix names the specific module and keeps the row's numbers, which are real for the modules that did fire. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 01:45:53 +02:00
use games_ground::config::Configuration;
use games_ground::{GroundState, ScoringMode};
/// Games per cell. Named once so the banner and the assertion cannot
/// disagree (CB-REV-0002 #1).
const GAMES: u32 = 100;
#[derive(Default)]
struct Cell {
games: u32,
played: u32,
won: u32,
/// Peak Stress **held**, not assigned — a table that sat at 2 all
/// game reported 1 when this was a max over event payloads
/// (CB-REV-0003 #5).
peak_stress: u8,
darvo: u32,
attacks: u32,
setup_fails: u32,
/// Games in which **every active module actually acted**.
///
/// A module that never fires has not been measured, and printing a
/// group-success number for it is worse than printing nothing: 85 vs
/// 86 reads as "measured, no effect" when the truth is that no seat
/// ever created the precondition. `attack_relief.self_soothe_ge4`
/// showed exactly this on the panel's first run — zero ATTACKs in
/// every cell, because GROUND outranks ATTACK at the stress gate, so
/// the module could not fire and its row looked like a null result.
unfired: std::collections::BTreeMap<String, u32>,
}
/// Did every non-default module in `cfg` actually act in this game?
///
/// Matched per module rather than inferred, for the same reason `Rules`
/// is exhaustive: a module added later must be a compile error here, not
/// a silent "fired" that turns an untested row into a measured one.
fn unfired_modules(cfg: &Configuration, g: &games_ground::bot::BotGame) -> Vec<String> {
cfg.active_modules()
.into_iter()
.filter(|m| !fired(m, g))
.collect()
}
/// Did this one module act in this game?
///
/// **Per module, not inferred.** Same reason `Rules` is exhaustive: a
/// module added later must be a compile error here rather than a silent
/// "fired" that turns an untested row into a measured one.
fn fired(m: &str, g: &games_ground::bot::BotGame) -> bool {
match m {
// Its Stress tick happens at Round End; the ledger moves.
"problem_stress.flat_any_open" | "problem_stress.scoped" => g
.events
.iter()
.any(|e| matches!(e, games_ground::GroundEvent::StressSet { .. })),
// It only acts on an uncancelled ATTACK by a seat at Stress >= 4.
"attack_relief.self_soothe_ge4" => g.steps.iter().any(|(_, c)| {
matches!(
c,
games_ground::GroundCommand::SelectAction {
action: games_ground::Action::Attack,
..
}
)
}),
// Anything else has no kernel path, so the row never gets here.
_ => false,
}
}
#[derive(Clone, Copy, PartialEq)]
enum Seat {
Greedy,
ModuleAware,
CB-WP-0050 T02: F31 falsified — the module is unreachable, then real GateAttackPolicy ranks ATTACK above GROUND at the stress gate and delegates everything else. A PROBE, not a better bot: it wins 12/100 where greedy wins 60/100 under the same module, and the panel's banner says so, because a column that looks like a policy comparison will be read as one. (a) THE MODULE IS UNREACHABLE IN THE PRINTED GAME. Selected alone it still never fires: peak Stress never exceeds 2, so the gate never bites and no ATTACK is ever gated. A module can be unreachable because of an aspect it does not name -- attack_relief needs a problem_stress module before it can act at all, and nothing in its own declaration says so. (b) ONCE REACHABLE IT IS REAL. Holding the probe fixed and varying only the module: group wins 12->21, 19->28, 50->57 at 3/4/6p, and DARVO arms 299->221, 294->213, 334->164. Under flat pressure the same shape appears in DARVO alone: h1 arms 200 against flat_any_open's 300/400/600. Stated as the conditional it is: GIVEN seats that attack at the gate. Not advice to attack, and not evidence against F17. AND IT CHANGES WHAT WE TOLD GROUND-GAME. CB-EV-0030 rejected H1 with policies that never attacked, so H1-B was inert for every game behind that verdict. The rejection stands on flat pressure alone -- wins are 0 either way -- but "H1-B does nothing" was never established and is now known to be false. We owe them that correction. Sensitivity: vary only the ATTACK rank. At 10 (greedy) and +55 (module-aware) the module never fires; at 110 it fires in every game. Nothing about the module changed -- only whether any seat gave it a turn. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 02:30:08 +02:00
/// F31's falsifier: a seat that attacks at the stress gate, so
/// `attack_relief.self_soothe_ge4` gets an opportunity at all. **A
/// probe, not a recommendation** — its win rate is not advice.
GateAttack,
CB-WP-0050: every configuration, faceted by aspect — and F31 module-panel sweeps points in aspect space the way scenario-panel sweeps boards: one module at a time with every other aspect held, then the profiles where an interaction is the hypothesis. F31: attack_relief.self_soothe_ge4 HAS NEVER FIRED. Zero ATTACKs in every cell, every seat band, both bots. The module acts only on an uncancelled ATTACK by a seat at Stress >= 4, and greedy ranks Ground 100 at the gate against Attack's 10 -- so at exactly the position where self-soothe would pay, GROUND wins. ModuleAwarePolicy adds 55 and that is still not enough. `unplayed`, not `inert`: the kernel implements it correctly and nothing has ever given it an opportunity. This reaches backwards: CB-EV-0030's H1 verdict rests on its flat-pressure half alone, because H1's other half never had an opportunity in those games either. Also: problem_stress.scoped is the only module with a measured effect (3p 85->60 greedy, 86->63 module-aware, peak Stress 2->4); flat_any_open drives group success to 0 at every band, reproducing the H1 rejection from the module side; and scoped_plus_attack_soothe is EXACTLY scoped alone -- necessarily, given F31 -- so the catalog's first intentional multi-aspect combination cannot currently be evaluated as a combination. THE PANEL'S OWN DEFECT, first run: it printed 85/86 for a module that never fired -- real-looking numbers inviting "measured, no effect" when no seat ever created the precondition. Its docstring already said it would not do that; the claim was written before the behaviour was. First fix marked whole rows unmeasured, which threw away h1's real flat-pressure result; the shipped fix names the specific module and keeps the row's numbers, which are real for the modules that did fire. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 01:45:53 +02:00
}
fn sweep(cfg: &Configuration, players: u8, who: Seat) -> Cell {
let mut c = Cell::default();
for seed in 0..GAMES as u64 {
let Ok(st) = GroundState::setup(
&Setup {
players,
preset: format!("standard-{players}p"),
patch: Default::default(),
},
seed,
) else {
c.setup_fails += 1;
continue;
};
// `with_config`, never a field write: problem_stress.scoped
// assigns owners at setup and a bare write leaves the module
// inert (ADR-0022 D3).
let mut st = st.with_config(cfg.clone());
st.mode = ScoringMode::SharedGround;
let start = st.players.values().map(|p| p.stress).max().unwrap_or(0);
let mut ps: Vec<Box<dyn Policy>> = (0..players)
.map(|_| match who {
Seat::Greedy => Box::new(GreedyPolicy) as Box<dyn Policy>,
Seat::ModuleAware => Box::new(ModuleAwarePolicy) as Box<dyn Policy>,
CB-WP-0050 T02: F31 falsified — the module is unreachable, then real GateAttackPolicy ranks ATTACK above GROUND at the stress gate and delegates everything else. A PROBE, not a better bot: it wins 12/100 where greedy wins 60/100 under the same module, and the panel's banner says so, because a column that looks like a policy comparison will be read as one. (a) THE MODULE IS UNREACHABLE IN THE PRINTED GAME. Selected alone it still never fires: peak Stress never exceeds 2, so the gate never bites and no ATTACK is ever gated. A module can be unreachable because of an aspect it does not name -- attack_relief needs a problem_stress module before it can act at all, and nothing in its own declaration says so. (b) ONCE REACHABLE IT IS REAL. Holding the probe fixed and varying only the module: group wins 12->21, 19->28, 50->57 at 3/4/6p, and DARVO arms 299->221, 294->213, 334->164. Under flat pressure the same shape appears in DARVO alone: h1 arms 200 against flat_any_open's 300/400/600. Stated as the conditional it is: GIVEN seats that attack at the gate. Not advice to attack, and not evidence against F17. AND IT CHANGES WHAT WE TOLD GROUND-GAME. CB-EV-0030 rejected H1 with policies that never attacked, so H1-B was inert for every game behind that verdict. The rejection stands on flat pressure alone -- wins are 0 either way -- but "H1-B does nothing" was never established and is now known to be false. We owe them that correction. Sensitivity: vary only the ATTACK rank. At 10 (greedy) and +55 (module-aware) the module never fires; at 110 it fires in every game. Nothing about the module changed -- only whether any seat gave it a turn. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 02:30:08 +02:00
Seat::GateAttack => Box::new(GateAttackPolicy) as Box<dyn Policy>,
CB-WP-0050: every configuration, faceted by aspect — and F31 module-panel sweeps points in aspect space the way scenario-panel sweeps boards: one module at a time with every other aspect held, then the profiles where an interaction is the hypothesis. F31: attack_relief.self_soothe_ge4 HAS NEVER FIRED. Zero ATTACKs in every cell, every seat band, both bots. The module acts only on an uncancelled ATTACK by a seat at Stress >= 4, and greedy ranks Ground 100 at the gate against Attack's 10 -- so at exactly the position where self-soothe would pay, GROUND wins. ModuleAwarePolicy adds 55 and that is still not enough. `unplayed`, not `inert`: the kernel implements it correctly and nothing has ever given it an opportunity. This reaches backwards: CB-EV-0030's H1 verdict rests on its flat-pressure half alone, because H1's other half never had an opportunity in those games either. Also: problem_stress.scoped is the only module with a measured effect (3p 85->60 greedy, 86->63 module-aware, peak Stress 2->4); flat_any_open drives group success to 0 at every band, reproducing the H1 rejection from the module side; and scoped_plus_attack_soothe is EXACTLY scoped alone -- necessarily, given F31 -- so the catalog's first intentional multi-aspect combination cannot currently be evaluated as a combination. THE PANEL'S OWN DEFECT, first run: it printed 85/86 for a module that never fired -- real-looking numbers inviting "measured, no effect" when no seat ever created the precondition. Its docstring already said it would not do that; the claim was written before the behaviour was. First fix marked whole rows unmeasured, which threw away h1's real flat-pressure result; the shipped fix names the specific module and keeps the row's numbers, which are real for the modules that did fire. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 01:45:53 +02:00
})
.collect();
let g = match play(st, &mut ps) {
Ok(g) => g,
Err(e) => {
eprintln!(" !! {players}p seed {seed}: {e:?}");
continue;
}
};
c.games += 1;
if g.state.outcome.is_some() && g.rounds == 5 {
c.played += 1;
}
if g.state.outcome.as_ref().is_some_and(|o| o.group_success) {
c.won += 1;
}
let mut held: std::collections::BTreeMap<PlayerId, u8> =
g.state.players.keys().map(|s| (*s, start)).collect();
c.peak_stress = c.peak_stress.max(start);
for e in &g.events {
match e {
games_ground::GroundEvent::StressSet { player, stress } => {
held.insert(*player, *stress);
c.peak_stress = c.peak_stress.max(held.values().copied().max().unwrap_or(0));
}
games_ground::GroundEvent::DarvoTriggered { .. } => c.darvo += 1,
_ => {}
}
}
for m in unfired_modules(cfg, &g) {
*c.unfired.entry(m).or_insert(0) += 1;
}
for (_, cmd) in &g.steps {
if let games_ground::GroundCommand::SelectAction {
action: games_ground::Action::Attack,
..
} = cmd
{
c.attacks += 1;
}
}
}
assert_eq!(
c.games, GAMES,
"{players}p: only {} of {GAMES} games ran ({} setups refused)",
c.games, c.setup_fails
);
assert_eq!(
c.played, GAMES,
"{players}p: {} of {} games reached an outcome over five rounds",
c.played, c.games
);
c
}
/// Every point worth measuring, in the order a reader should read them.
fn points() -> Vec<(String, String, Result<Configuration, String>)> {
let cat = games_ground::catalog::catalog().expect("catalog.yaml");
let mut out = vec![(
"".to_string(),
"baseline (every aspect at its default)".to_string(),
Configuration::select("ground-darvo-r0"),
)];
// ONE MODULE AT A TIME, grouped by aspect: "hold all aspects fixed,
// vary one" is what makes a row a measurement of that module rather
// than of a bundle (CB-RES-0010 §5.4).
for aspect in &cat.aspects {
for m in cat.modules.iter().filter(|m| m.aspect == aspect.id) {
if m.is_default || m.module_id == aspect.default_module {
continue;
}
out.push((
aspect.id.clone(),
m.module_id.clone(),
Configuration::from_modules(
&cat.default_baseline,
std::slice::from_ref(&m.module_id),
),
));
}
}
// Then the profiles, which are where an INTERACTION is the
// hypothesis. A single-module profile is skipped: it is the row above.
for p in &cat.profiles {
if p.modules.len() < 2 {
continue;
}
out.push((
"(interaction)".to_string(),
p.profile_id.clone(),
Configuration::from_profile(&p.profile_id),
));
}
out
}
fn main() {
println!("CB-WP-0050 — every configuration, faceted by aspect\n");
println!("SHARED GROUND; {GAMES} games per cell; seeds 0..{GAMES}.");
println!("One module at a time first, holding every other aspect at its");
println!("default; then the profiles, where an interaction is the point.\n");
println!("`grdy` is GreedyPolicy, which reads no module at all. `mod` is");
println!("ModuleAwarePolicy. A row flat under `grdy` and moving under");
println!("`mod` is a module that needs a seat able to see it — not a");
println!("module that does nothing (F27's distinction).\n");
CB-WP-0050 T02: F31 falsified — the module is unreachable, then real GateAttackPolicy ranks ATTACK above GROUND at the stress gate and delegates everything else. A PROBE, not a better bot: it wins 12/100 where greedy wins 60/100 under the same module, and the panel's banner says so, because a column that looks like a policy comparison will be read as one. (a) THE MODULE IS UNREACHABLE IN THE PRINTED GAME. Selected alone it still never fires: peak Stress never exceeds 2, so the gate never bites and no ATTACK is ever gated. A module can be unreachable because of an aspect it does not name -- attack_relief needs a problem_stress module before it can act at all, and nothing in its own declaration says so. (b) ONCE REACHABLE IT IS REAL. Holding the probe fixed and varying only the module: group wins 12->21, 19->28, 50->57 at 3/4/6p, and DARVO arms 299->221, 294->213, 334->164. Under flat pressure the same shape appears in DARVO alone: h1 arms 200 against flat_any_open's 300/400/600. Stated as the conditional it is: GIVEN seats that attack at the gate. Not advice to attack, and not evidence against F17. AND IT CHANGES WHAT WE TOLD GROUND-GAME. CB-EV-0030 rejected H1 with policies that never attacked, so H1-B was inert for every game behind that verdict. The rejection stands on flat pressure alone -- wins are 0 either way -- but "H1-B does nothing" was never established and is now known to be false. We owe them that correction. Sensitivity: vary only the ATTACK rank. At 10 (greedy) and +55 (module-aware) the module never fires; at 110 it fires in every game. Nothing about the module changed -- only whether any seat gave it a turn. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 02:30:08 +02:00
println!("`atk!` is GateAttackPolicy, which attacks at the stress gate so");
println!("attack_relief gets an opportunity at all (F31). It is a PROBE:");
println!("its win rate is not a recommendation. The peak/darvo/atk columns");
println!("are its games, because they are the only ones where ATTACK");
println!("happens.\n");
CB-WP-0050: every configuration, faceted by aspect — and F31 module-panel sweeps points in aspect space the way scenario-panel sweeps boards: one module at a time with every other aspect held, then the profiles where an interaction is the hypothesis. F31: attack_relief.self_soothe_ge4 HAS NEVER FIRED. Zero ATTACKs in every cell, every seat band, both bots. The module acts only on an uncancelled ATTACK by a seat at Stress >= 4, and greedy ranks Ground 100 at the gate against Attack's 10 -- so at exactly the position where self-soothe would pay, GROUND wins. ModuleAwarePolicy adds 55 and that is still not enough. `unplayed`, not `inert`: the kernel implements it correctly and nothing has ever given it an opportunity. This reaches backwards: CB-EV-0030's H1 verdict rests on its flat-pressure half alone, because H1's other half never had an opportunity in those games either. Also: problem_stress.scoped is the only module with a measured effect (3p 85->60 greedy, 86->63 module-aware, peak Stress 2->4); flat_any_open drives group success to 0 at every band, reproducing the H1 rejection from the module side; and scoped_plus_attack_soothe is EXACTLY scoped alone -- necessarily, given F31 -- so the catalog's first intentional multi-aspect combination cannot currently be evaluated as a combination. THE PANEL'S OWN DEFECT, first run: it printed 85/86 for a module that never fired -- real-looking numbers inviting "measured, no effect" when no seat ever created the precondition. Its docstring already said it would not do that; the claim was written before the behaviour was. First fix marked whole rows unmeasured, which threw away h1's real flat-pressure result; the shipped fix names the specific module and keeps the row's numbers, which are real for the modules that did fire. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 01:45:53 +02:00
println!("`never fired: UNMEASURED` means no seat created that module's");
println!("precondition in any game, so its contribution to the row is not");
println!("a null result — it is an absence of evidence. The other numbers");
println!("in such a row are still real for the modules that DID fire.\n");
for players in [3u8, 4, 6] {
println!("{players} players");
println!(
CB-WP-0050 T02: F31 falsified — the module is unreachable, then real GateAttackPolicy ranks ATTACK above GROUND at the stress gate and delegates everything else. A PROBE, not a better bot: it wins 12/100 where greedy wins 60/100 under the same module, and the panel's banner says so, because a column that looks like a policy comparison will be read as one. (a) THE MODULE IS UNREACHABLE IN THE PRINTED GAME. Selected alone it still never fires: peak Stress never exceeds 2, so the gate never bites and no ATTACK is ever gated. A module can be unreachable because of an aspect it does not name -- attack_relief needs a problem_stress module before it can act at all, and nothing in its own declaration says so. (b) ONCE REACHABLE IT IS REAL. Holding the probe fixed and varying only the module: group wins 12->21, 19->28, 50->57 at 3/4/6p, and DARVO arms 299->221, 294->213, 334->164. Under flat pressure the same shape appears in DARVO alone: h1 arms 200 against flat_any_open's 300/400/600. Stated as the conditional it is: GIVEN seats that attack at the gate. Not advice to attack, and not evidence against F17. AND IT CHANGES WHAT WE TOLD GROUND-GAME. CB-EV-0030 rejected H1 with policies that never attacked, so H1-B was inert for every game behind that verdict. The rejection stands on flat pressure alone -- wins are 0 either way -- but "H1-B does nothing" was never established and is now known to be false. We owe them that correction. Sensitivity: vary only the ATTACK rank. At 10 (greedy) and +55 (module-aware) the module never fires; at 110 it fires in every game. Nothing about the module changed -- only whether any seat gave it a turn. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 02:30:08 +02:00
" {:<18} {:<38} {:>5} {:>5} {:>5} {:>6} {:>6} {:>6}",
"aspect", "module / profile", "grdy", "mod", "atk!", "peak", "darvo", "atk"
CB-WP-0050: every configuration, faceted by aspect — and F31 module-panel sweeps points in aspect space the way scenario-panel sweeps boards: one module at a time with every other aspect held, then the profiles where an interaction is the hypothesis. F31: attack_relief.self_soothe_ge4 HAS NEVER FIRED. Zero ATTACKs in every cell, every seat band, both bots. The module acts only on an uncancelled ATTACK by a seat at Stress >= 4, and greedy ranks Ground 100 at the gate against Attack's 10 -- so at exactly the position where self-soothe would pay, GROUND wins. ModuleAwarePolicy adds 55 and that is still not enough. `unplayed`, not `inert`: the kernel implements it correctly and nothing has ever given it an opportunity. This reaches backwards: CB-EV-0030's H1 verdict rests on its flat-pressure half alone, because H1's other half never had an opportunity in those games either. Also: problem_stress.scoped is the only module with a measured effect (3p 85->60 greedy, 86->63 module-aware, peak Stress 2->4); flat_any_open drives group success to 0 at every band, reproducing the H1 rejection from the module side; and scoped_plus_attack_soothe is EXACTLY scoped alone -- necessarily, given F31 -- so the catalog's first intentional multi-aspect combination cannot currently be evaluated as a combination. THE PANEL'S OWN DEFECT, first run: it printed 85/86 for a module that never fired -- real-looking numbers inviting "measured, no effect" when no seat ever created the precondition. Its docstring already said it would not do that; the claim was written before the behaviour was. First fix marked whole rows unmeasured, which threw away h1's real flat-pressure result; the shipped fix names the specific module and keeps the row's numbers, which are real for the modules that did fire. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 01:45:53 +02:00
);
for (aspect, name, cfg) in points() {
let cfg = match cfg {
Ok(c) => c,
Err(e) => {
println!(" {aspect:<18} {name:<38} — — {e}");
continue;
}
};
// **Named, never omitted.** A module the kernel cannot run is
// a question that stays open, and a blank row is how it would
// stop being one.
if let Err(e) = cfg.resolve() {
let why = e.split(" (catalog status").next().unwrap_or(&e).to_string();
let why = why.replace(&format!("{name} is a known module with "), "");
println!(" {aspect:<18} {name:<38} {:>5} {:>5} {why}", "", "");
continue;
}
let g = sweep(&cfg, players, Seat::Greedy);
let m = sweep(&cfg, players, Seat::ModuleAware);
CB-WP-0050 T02: F31 falsified — the module is unreachable, then real GateAttackPolicy ranks ATTACK above GROUND at the stress gate and delegates everything else. A PROBE, not a better bot: it wins 12/100 where greedy wins 60/100 under the same module, and the panel's banner says so, because a column that looks like a policy comparison will be read as one. (a) THE MODULE IS UNREACHABLE IN THE PRINTED GAME. Selected alone it still never fires: peak Stress never exceeds 2, so the gate never bites and no ATTACK is ever gated. A module can be unreachable because of an aspect it does not name -- attack_relief needs a problem_stress module before it can act at all, and nothing in its own declaration says so. (b) ONCE REACHABLE IT IS REAL. Holding the probe fixed and varying only the module: group wins 12->21, 19->28, 50->57 at 3/4/6p, and DARVO arms 299->221, 294->213, 334->164. Under flat pressure the same shape appears in DARVO alone: h1 arms 200 against flat_any_open's 300/400/600. Stated as the conditional it is: GIVEN seats that attack at the gate. Not advice to attack, and not evidence against F17. AND IT CHANGES WHAT WE TOLD GROUND-GAME. CB-EV-0030 rejected H1 with policies that never attacked, so H1-B was inert for every game behind that verdict. The rejection stands on flat pressure alone -- wins are 0 either way -- but "H1-B does nothing" was never established and is now known to be false. We owe them that correction. Sensitivity: vary only the ATTACK rank. At 10 (greedy) and +55 (module-aware) the module never fires; at 110 it fires in every game. Nothing about the module changed -- only whether any seat gave it a turn. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 02:30:08 +02:00
let a = sweep(&cfg, players, Seat::GateAttack);
CB-WP-0050: every configuration, faceted by aspect — and F31 module-panel sweeps points in aspect space the way scenario-panel sweeps boards: one module at a time with every other aspect held, then the profiles where an interaction is the hypothesis. F31: attack_relief.self_soothe_ge4 HAS NEVER FIRED. Zero ATTACKs in every cell, every seat band, both bots. The module acts only on an uncancelled ATTACK by a seat at Stress >= 4, and greedy ranks Ground 100 at the gate against Attack's 10 -- so at exactly the position where self-soothe would pay, GROUND wins. ModuleAwarePolicy adds 55 and that is still not enough. `unplayed`, not `inert`: the kernel implements it correctly and nothing has ever given it an opportunity. This reaches backwards: CB-EV-0030's H1 verdict rests on its flat-pressure half alone, because H1's other half never had an opportunity in those games either. Also: problem_stress.scoped is the only module with a measured effect (3p 85->60 greedy, 86->63 module-aware, peak Stress 2->4); flat_any_open drives group success to 0 at every band, reproducing the H1 rejection from the module side; and scoped_plus_attack_soothe is EXACTLY scoped alone -- necessarily, given F31 -- so the catalog's first intentional multi-aspect combination cannot currently be evaluated as a combination. THE PANEL'S OWN DEFECT, first run: it printed 85/86 for a module that never fired -- real-looking numbers inviting "measured, no effect" when no seat ever created the precondition. Its docstring already said it would not do that; the claim was written before the behaviour was. First fix marked whole rows unmeasured, which threw away h1's real flat-pressure result; the shipped fix names the specific module and keeps the row's numbers, which are real for the modules that did fire. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 01:45:53 +02:00
// **A module that never acted is UNMEASURED, not null.**
// Printing win counts for it invites the reading that it does
// nothing, when what happened is that no seat ever created
// the precondition. CB-RES-0010 §5.4's last bullet, one level
// deeper than F27: not "the bot cannot see the module" but
// "the bot never gives the module anything to see".
// **Name the module that never acted, not the whole row.**
// Reporting a two-module profile as wholly unmeasured throws
// away the half that did fire: h1's flat pressure reaches
// every game and drives group success to 0, which is a real
// result about that module even though its ATTACK half never
// gets an opportunity.
CB-WP-0050 T02: F31 falsified — the module is unreachable, then real GateAttackPolicy ranks ATTACK above GROUND at the stress gate and delegates everything else. A PROBE, not a better bot: it wins 12/100 where greedy wins 60/100 under the same module, and the panel's banner says so, because a column that looks like a policy comparison will be read as one. (a) THE MODULE IS UNREACHABLE IN THE PRINTED GAME. Selected alone it still never fires: peak Stress never exceeds 2, so the gate never bites and no ATTACK is ever gated. A module can be unreachable because of an aspect it does not name -- attack_relief needs a problem_stress module before it can act at all, and nothing in its own declaration says so. (b) ONCE REACHABLE IT IS REAL. Holding the probe fixed and varying only the module: group wins 12->21, 19->28, 50->57 at 3/4/6p, and DARVO arms 299->221, 294->213, 334->164. Under flat pressure the same shape appears in DARVO alone: h1 arms 200 against flat_any_open's 300/400/600. Stated as the conditional it is: GIVEN seats that attack at the gate. Not advice to attack, and not evidence against F17. AND IT CHANGES WHAT WE TOLD GROUND-GAME. CB-EV-0030 rejected H1 with policies that never attacked, so H1-B was inert for every game behind that verdict. The rejection stands on flat pressure alone -- wins are 0 either way -- but "H1-B does nothing" was never established and is now known to be false. We owe them that correction. Sensitivity: vary only the ATTACK rank. At 10 (greedy) and +55 (module-aware) the module never fires; at 110 it fires in every game. Nothing about the module changed -- only whether any seat gave it a turn. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 02:30:08 +02:00
// **The probe's row decides "never fired", not the others.**
// A module is unreachable only if the seat built to reach it
// could not either.
let never: Vec<&String> = a
CB-WP-0050: every configuration, faceted by aspect — and F31 module-panel sweeps points in aspect space the way scenario-panel sweeps boards: one module at a time with every other aspect held, then the profiles where an interaction is the hypothesis. F31: attack_relief.self_soothe_ge4 HAS NEVER FIRED. Zero ATTACKs in every cell, every seat band, both bots. The module acts only on an uncancelled ATTACK by a seat at Stress >= 4, and greedy ranks Ground 100 at the gate against Attack's 10 -- so at exactly the position where self-soothe would pay, GROUND wins. ModuleAwarePolicy adds 55 and that is still not enough. `unplayed`, not `inert`: the kernel implements it correctly and nothing has ever given it an opportunity. This reaches backwards: CB-EV-0030's H1 verdict rests on its flat-pressure half alone, because H1's other half never had an opportunity in those games either. Also: problem_stress.scoped is the only module with a measured effect (3p 85->60 greedy, 86->63 module-aware, peak Stress 2->4); flat_any_open drives group success to 0 at every band, reproducing the H1 rejection from the module side; and scoped_plus_attack_soothe is EXACTLY scoped alone -- necessarily, given F31 -- so the catalog's first intentional multi-aspect combination cannot currently be evaluated as a combination. THE PANEL'S OWN DEFECT, first run: it printed 85/86 for a module that never fired -- real-looking numbers inviting "measured, no effect" when no seat ever created the precondition. Its docstring already said it would not do that; the claim was written before the behaviour was. First fix marked whole rows unmeasured, which threw away h1's real flat-pressure result; the shipped fix names the specific module and keeps the row's numbers, which are real for the modules that did fire. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 01:45:53 +02:00
.unfired
.iter()
.filter(|(_, n)| **n == GAMES)
.map(|(k, _)| k)
.collect();
let note = if never.is_empty() {
String::new()
} else {
format!(
" \u{2190} {} never fired: UNMEASURED",
never
.iter()
.map(|s| s.as_str())
.collect::<Vec<_>>()
.join(", ")
)
};
println!(
CB-WP-0050 T02: F31 falsified — the module is unreachable, then real GateAttackPolicy ranks ATTACK above GROUND at the stress gate and delegates everything else. A PROBE, not a better bot: it wins 12/100 where greedy wins 60/100 under the same module, and the panel's banner says so, because a column that looks like a policy comparison will be read as one. (a) THE MODULE IS UNREACHABLE IN THE PRINTED GAME. Selected alone it still never fires: peak Stress never exceeds 2, so the gate never bites and no ATTACK is ever gated. A module can be unreachable because of an aspect it does not name -- attack_relief needs a problem_stress module before it can act at all, and nothing in its own declaration says so. (b) ONCE REACHABLE IT IS REAL. Holding the probe fixed and varying only the module: group wins 12->21, 19->28, 50->57 at 3/4/6p, and DARVO arms 299->221, 294->213, 334->164. Under flat pressure the same shape appears in DARVO alone: h1 arms 200 against flat_any_open's 300/400/600. Stated as the conditional it is: GIVEN seats that attack at the gate. Not advice to attack, and not evidence against F17. AND IT CHANGES WHAT WE TOLD GROUND-GAME. CB-EV-0030 rejected H1 with policies that never attacked, so H1-B was inert for every game behind that verdict. The rejection stands on flat pressure alone -- wins are 0 either way -- but "H1-B does nothing" was never established and is now known to be false. We owe them that correction. Sensitivity: vary only the ATTACK rank. At 10 (greedy) and +55 (module-aware) the module never fires; at 110 it fires in every game. Nothing about the module changed -- only whether any seat gave it a turn. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 02:30:08 +02:00
" {aspect:<18} {name:<38} {:>5} {:>5} {:>5} {:>6} {:>6} {:>6}{note}",
g.won, m.won, a.won, a.peak_stress, a.darvo, a.attacks
CB-WP-0050: every configuration, faceted by aspect — and F31 module-panel sweeps points in aspect space the way scenario-panel sweeps boards: one module at a time with every other aspect held, then the profiles where an interaction is the hypothesis. F31: attack_relief.self_soothe_ge4 HAS NEVER FIRED. Zero ATTACKs in every cell, every seat band, both bots. The module acts only on an uncancelled ATTACK by a seat at Stress >= 4, and greedy ranks Ground 100 at the gate against Attack's 10 -- so at exactly the position where self-soothe would pay, GROUND wins. ModuleAwarePolicy adds 55 and that is still not enough. `unplayed`, not `inert`: the kernel implements it correctly and nothing has ever given it an opportunity. This reaches backwards: CB-EV-0030's H1 verdict rests on its flat-pressure half alone, because H1's other half never had an opportunity in those games either. Also: problem_stress.scoped is the only module with a measured effect (3p 85->60 greedy, 86->63 module-aware, peak Stress 2->4); flat_any_open drives group success to 0 at every band, reproducing the H1 rejection from the module side; and scoped_plus_attack_soothe is EXACTLY scoped alone -- necessarily, given F31 -- so the catalog's first intentional multi-aspect combination cannot currently be evaluated as a combination. THE PANEL'S OWN DEFECT, first run: it printed 85/86 for a module that never fired -- real-looking numbers inviting "measured, no effect" when no seat ever created the precondition. Its docstring already said it would not do that; the claim was written before the behaviour was. First fix marked whole rows unmeasured, which threw away h1's real flat-pressure result; the shipped fix names the specific module and keeps the row's numbers, which are real for the modules that did fire. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 01:45:53 +02:00
);
}
println!();
}
}