clay-borg/workplans/CB-WP-0042-h2-scoped-problem-stress.md
tegwick 04e26b3077
Some checks failed
ci / check (push) Failing after 4s
CB-WP-0042 T01-T04: H2's scoped stress, with the named defects caught
H2 is ground-game's answer to our H1 reading — that a flat +1 to every
seat is a solve-rate tax scaling with the number of Problems. Unclaimed
Problems now tick only the seats in scope: global (all), personal (the
owner), bond (the owner's Bond network over Bond edges only, degree 0
falling back to personal), assigned by hidden priority so 2p never has the
bond card in play.

T01: the package is vendored with digests, and H2's Problems.csv is r0's
with one column added and NOTHING else changed — checked, not assumed,
because the delta claims deal_and_thresholds unchanged and a silent
difference would make every H2-vs-baseline comparison a comparison of two
boards as well as two rule sets. Scopes are read from the column, not
derived from the priority in Rust: F25 exists because we hardcoded numbers
the edition already carried.

T02: owner and scope are new ProblemState fields, both Option and both
skipped when None, so a baseline state serialises without them and every
recorded scenario's hash is untouched — asserted on the JSON, not assumed.
with_variant() replaces the bare field write, because state.variant = v
would leave owners unassigned: a silently wrong game rather than a failing
one.

T03: every named defect is mutation-proven — traversing Rivalry edges,
applying stacking once, a degree-0 owner ticking everyone, personal
hitting everyone. The degree-0 mutation MISSED first: the fallback lives
inside bond_network and the mutation broke the None-owner arm instead, a
different branch. It stayed green until aimed at the path the test
exercises. A mutation that misses is not evidence the test works.

T04: ownership is not a permission. Filtering SOLVE to the owner turns it
red, which is the regression this task exists for — the engine had no
owner concept before T02 added one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 16:06:21 +02:00

7.8 KiB

id kind title status state_hub_workstream_id
CB-WP-0042 product H2 — scoped problem stress active 8f11d55b-3452-49f3-9857-d0bf06752f68

Purpose

structural tier  M   (touches a canonical interface: edition loading
                      becomes variant-parameterised, and the kernel gains
                      per-Problem state)
chaos            d8 = 4  → no override
declared tier    M

Declaration 2 of chaos window 4.

Why, and it is a direct answer to ours

We reported that H1-A behaves as a solve-rate tax: a flat +1 to every seat while any Problem is unclaimed, so the pressure scales with the number of Problems while the intended effect does not.

ground-game responded with H2 — scoped problem stress. Unclaimed Problems now tick only the seats in their scope:

scope who takes the +1
global all seats
personal the Problem's owner
bond the owner's Bond network — owner plus every seat reachable over Bond edges only, never Rivalry; degree 0 falls back to personal

Assigned by hidden priority: 0 (Surface) global, 1 personal, 2 personal, 3 bond, 4 personal — which is a seat-band dial without a difficulty card, since 2p never has the bond card in play.

It does not stack with H1. replaces_experiments: [h1-problem-stress], base is ground-darvo-r0, and there is no ATTACK self-soothe.

Why this is bigger than H1 was

H1 was two arithmetic deltas on existing state. H2 needs three things we do not have:

  1. Variant-scoped edition data. H2 overrides Problems.csv with a new stress_scope column. edition.rs include_str!s r0's copy at compile time — the data is currently a constant, not a parameter.
  2. Per-Problem ownership, assigned at setup. That is new state, so it reaches the state hash and every recording.
  3. Bond-network reachability — a graph traversal over Bond edges only, with a degree-0 fallback.

Task: variant-scoped edition data

id: CB-WP-0042-T01
status: done
priority: high
state_hub_task_id: "37f9bc34-05d1-4a12-9a98-6c61ab3ec23f"

Controls:

  • the baseline's data is bit-for-bit what it was, and its state hashes do not move — the control that protected CB-WP-0038 and the one that invalidates every prior measurement if it fails;
  • the H2 package is vendored with digests like every other borrowed file, and edition-check covers it — sibling discovery walks the disk now, so an undigested file fails (CB-REV-0003 #8);
  • stress_scope's assignment is read from the file, not hardcoded. The delta states the priority→scope mapping; it is the edition's to state and ours to read, and F25 exists because we hardcoded numbers the edition already carried.

Done 2026-08-08. Package vendored with digests; edition-check walks it. StressScope and stress_scopes() read the column.

H2's Problems.csv is r0's with one column added and nothing else changed — same rows, values, suits, visibilities and priorities. That is checked, not assumed: the delta claims deal_and_thresholds unchanged, and a silent difference would make every H2-vs-baseline comparison a comparison of two boards as well as two rule sets.

Task: ownership at setup

id: CB-WP-0042-T02
status: done
priority: high
state_hub_task_id: "65b9b2b8-8160-488f-8cd4-b7f734d03b22"

H2-OWN: ascending hidden priority among in-play non-global Problems, starting at Lead, stepping clockwise. Global Problems have no owner.

Controls:

  • deterministic, and asserted so — the delta says "deterministic for sims" and a seeded-but-unstated order would be untestable;
  • the baseline carries no owners and its hash does not move. New state that is None under baseline must serialise as it did before, or every recorded scenario breaks;
  • exactly one owner per eligible Problem, checked at every seat count, because the assignment walks two sequences at once and off-by-one is the obvious failure.

Done 2026-08-08. owner and scope on ProblemState, both Option, both skip_serializing_if = "Option::is_none" — so a baseline state serialises without them and every recorded scenario's hash is untouched. Asserted directly, on the JSON.

with_variant() replaces the bare field write. state.variant = v would leave owners unassigned — a silently wrong game rather than a failing one — so the builder applies the variant's setup and every driver path goes through it.

Task: scoped pressure

id: CB-WP-0042-T03
status: done
priority: high
state_hub_task_id: "8426e79c-579e-4aba-a695-381020016206"

H2-A, at Round End, before the clamp and the DARVO arm check — the same ordering H1-A needed, and the same trap.

Controls:

  • each scope fails on its own, by mutation: global hitting only the owner, personal hitting everyone, bond stopping at the owner;
  • stacking: true is tested — two open bond Problems must tick the network twice, and a careless implementation applies it once;
  • Rivalry edges are not traversed. The delta says Bond only, and a traversal that follows any relation is the single most likely defect;
  • degree 0 falls back to personal, which is the branch a test forgets;
  • ordering asserted as in CB-WP-0038: pressure before the arm check.

Done 2026-08-08. All four named defects mutation-proven:

mutation caught by
traverse Rivalry edges too h2_bond_scope_does_not_traverse_rivalry
stacking applied once h2_pressure_stacks_per_problem
degree-0 owner ticks everyone h2_a_bond_problem_with_no_bonds_is_personal
personal hits everyone h2_pressure_reaches_only_the_scope

The degree-0 mutation missed first, and that is worth recording: the fallback lives inside bond_network, and the first mutation broke the None-owner arm instead — a different branch. It stayed green until the mutation was aimed at the path the test actually exercises. A mutation that misses is not evidence the test works.

Task: SOLVE is not restricted by scope

id: CB-WP-0042-T04
status: done
priority: medium
state_hub_task_id: "6606cb3b-733d-486c-9e46-37a2a2b0c2c9"

H2-SOLVE: any seat with a matching suit may claim; the owner need not be the solver, and altruistic clearing is intended.

Control: our engine has no owner concept today, so this is already true — which makes it a regression test, not a feature. T02 adds ownership, and the risk is that ownership silently becomes a permission. The test must fail if it does.

Done 2026-08-08, and it does: filtering SOLVE to the owner in legal_commands turns it red.

Task: measure, and report what fails

id: CB-WP-0042-T05
status: todo
priority: high
state_hub_task_id: "0bcd97da-60b8-46b2-ae86-7a94f6af8dd5"

Same instrument as H1, same panel, both variants in one run.

Controls:

  • greedy and reactive both, because H1's whole verdict turned on which policy was asked (CB-EV-0031);
  • report against ground-game's own criteria for H2, from their design note — read it, do not reuse H1's §3.2 from memory;
  • the bond-scope hypothesis is the interesting one and must be measured directly: their claim is that a shared tick makes a Bond network jointly motivated to solve that card. Whether a policy that does not model other seats can express that at all is an open question, and the honest answer may be "our panel cannot test this hypothesis";
  • make panels runs it, or the figures come from an ungated binary again (CB-REV-0002 #7).

Not in this workplan

  • No stacking with H1. The package forbids it explicitly.
  • No felt-play. H2's central claim is about motivation — a bonded pair caring about each other's card — and 200-game aggregates measure dynamics, not that (Taxonomy.md §4).