GD-0001: group success is unreachable below 5 seats, with its reproduction

The maintainer played several 3-player games on 2026-08-03 and could not
win any. This says why, from the engine's own constants rather than my
arithmetic: claim every Problem the deal puts in play, concede nothing,
and the total still falls short of GR-E01's threshold at 2, 3 and 4
seats.

  2p: 2 problems worth 3  vs threshold 5 — UNREACHABLE
  3p: 3 problems worth 6  vs threshold 7 — UNREACHABLE
  4p: 3 problems worth 6  vs threshold 7 — UNREACHABLE
  5p: 4 problems worth 10 vs threshold 9 — reachable
  6p: 4 problems worth 10 vs threshold 9 — reachable

The test reads problem_priorities (GR-S01's deal) and threshold (GR-E01)
out of the engine, so it cannot drift from the rules it tests, and it
holds for either dataset -- the stand-in gives 3/6/10 and Problems.csv
gives 4/6/9 against the same 5/7/9.

It ASSERTS THE DEFECT and is expected to keep passing until ground-game
rules, then be inverted. This is CB-WP-0022's reproduction rule applied
before the register exists, because delivering feedback should not block
on building the tool that tracks it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
tegwick 2026-08-03 23:49:49 +02:00
parent a86efba4c3
commit b513209acf

View file

@ -2162,6 +2162,19 @@ mod replay_probe {
use cb_kernel::EventSeq;
use std::time::Instant;
/// A fresh game at `seats` players, for the seat-count sweep.
fn fresh_n(seats: u8) -> GroundState {
GroundState::setup(
&Setup {
players: seats,
preset: format!("standard-{seats}p"),
patch: BTreeMap::new(),
},
42,
)
.expect("a standard deal")
}
fn fresh(seed: u64) -> GroundState {
GroundState::setup(
&Setup {
@ -2441,6 +2454,56 @@ mod replay_probe {
}
}
/// **GD-0001: group success is arithmetically unreachable below 5
/// seats**, and this is the reproduction rather than an argument.
///
/// The maintainer played several 3-player games on 2026-08-03 and
/// could not win any of them. This says why: claim *every* Problem
/// the deal puts in play, concede nothing, and the total still falls
/// short of GR-E01's threshold at 2, 3 and 4 seats.
///
/// It reads both numbers out of the engine — `problem_priorities`
/// (GR-S01's deal) and `threshold` (GR-E01) — so it cannot drift from
/// the rules it is testing, and it holds for **either dataset**: the
/// stand-in gives 3/6/10 and `Problems.csv` gives 4/6/9, against the
/// same 5/7/9.
///
/// **This test asserts the defect.** It is expected to keep passing
/// until ground-game rules, and to be inverted when it does — either
/// the deal count rises or the thresholds fall.
#[test]
fn gd0001_group_success_is_unreachable_below_five_seats() {
let mut verdicts = Vec::new();
for seats in 2..=6u8 {
let state = fresh_n(seats);
let best: u32 = state.problems.values().map(|p| u32::from(p.value)).sum();
let need = state.threshold();
verdicts.push((seats, state.problems.len(), best, need, best >= need));
println!(
" {seats}p: {} problem(s) worth {best} against a threshold of {need} \u{2014} {}",
state.problems.len(),
if best >= need { "reachable" } else { "UNREACHABLE" }
);
}
let unreachable: Vec<u8> = verdicts
.iter()
.filter(|(_, _, _, _, ok)| !ok)
.map(|(s, _, _, _, _)| *s)
.collect();
// Positive control: a run where everything is reachable would
// report a clean sheet and prove nothing.
assert!(
!verdicts.is_empty() && verdicts.iter().any(|(_, _, _, _, ok)| *ok),
"no seat count was reachable; the harness measured nothing useful"
);
assert_eq!(
unreachable,
vec![2, 3, 4],
"GD-0001 has changed: ground-game may have ruled. Re-read the \
finding before editing this test."
);
}
/// AM-7 scaling floor from GameKernel §5: fold throughput at 100k
/// events must be at least this fraction of throughput at 5k.
///