CB-WP-0049 T04: a seat that attends to the modules in play
Some checks are pending
ci / check (push) Waiting to run

ModuleAwarePolicy reads the RESOLVED Rules -- one policy, not one per
module. H2AwarePolicy would have been the blob schema 2 exists to
retire, rebuilt a layer up; reading Rules means a two-module
configuration gets both terms and a future module is one arm here rather
than a new policy per combination.

Two terms, both reading the table: prefer the Problem whose Stress falls
on me (problem_stress.scoped), and treat ATTACK as a Stress tool at the
gate (attack_relief.self_soothe_ge4). stress_scope and the owner marker
are public regardless of the card's face -- the H2 rules place the
marker ON the card -- so it is blind by construction.

THE CONTROL I CLAIMED WAS REAL WAS VACUOUS, AND MUTATION SAID SO.
"Under the baseline the two must be identical" swept fresh deals across
36 combinations, and forcing the scope term to fire regardless of
configuration left it GREEN. At a fresh deal only the Surface Problem is
face up, so exactly one SOLVE is legal and no ranking term can move the
argmax. The control could not distinguish the property from its
negation.

Both tests now use a BUILT position -- two face-up, unclaimed, equally
valuable Problems differing only in scope -- under H2 for divergence and
under the baseline for the control. The mutation goes red there.

That is also a finding about the module: the scope term is INERT at
round-one positions, so anything measuring H2 with round-one-heavy play
is measuring a mechanism that has not started. Recorded, not tuned away.

Also: CB-WP-0048 was `active` with every task closed; loop-lint's
lifecycle rule caught it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
tegwick 2026-08-09 01:25:22 +02:00
parent d713fbc1bc
commit 8ae68195b8
4 changed files with 379 additions and 3 deletions

View file

@ -2,7 +2,7 @@
id: CB-WP-0048
kind: product
title: "A configuration, not a variant"
status: active
status: done
state_hub_workstream_id: "44ceb8d8-e6e2-46d6-a694-fd275804b771"
---

View file

@ -214,7 +214,7 @@ mode-aware.
```task
id: CB-WP-0049-T04
status: todo
status: done
priority: normal
state_hub_task_id: "1b26c7e9-e049-49d0-aecd-63830c7c8a37"
```
@ -236,6 +236,48 @@ achievable cheaply, the honest move is one policy that reads the resolved
control that separates "attends to the module" from "plays differently";
- **blind** (T01).
**Done 2026-08-08.** `ModuleAwarePolicy` reads the resolved `Rules`
**one policy, not one per module.** `H2AwarePolicy` would have been the
blob schema 2 exists to retire, rebuilt a layer up; reading `Rules` means
a configuration carrying two modules gets both terms and a module the
kernel gains later is one arm here rather than a new policy for every
combination it appears in.
It delegates to `ObjectivePolicy::rank`, which delegates to
`GreedyPolicy::rank`, so it differs in exactly two arms:
| module | term |
|---|---|
| `problem_stress.scoped` | prefer the Problem whose Stress falls **on me** — two equally valuable cards are not equally urgent, which is the module's whole point |
| `attack_relief.self_soothe_ge4` | at the gate, ATTACK is a Stress tool; greedy ranks it 10 in every position because under the printed rules it does nothing for the attacker |
Both read the table: `stress_scope` and the owner marker are public
regardless of the card's face, because the H2 rules say to place the
marker **on the card** and at a table everyone can see it. So it is blind
(ADR-0023) by construction, and the T01 sweep now covers it.
### The control I claimed was real was vacuous, and mutation said so
*"Under the baseline the two must be identical"* swept fresh deals across
four seeds × three seat bands × three modes — and **forcing the scope
term to fire regardless of configuration left it green.**
At a fresh deal only the Surface Problem is face up, so exactly one SOLVE
is legal and **no ranking term can move the argmax**. The control could
not distinguish the property from its negation, which is the definition
of decoration (ADR-0006 D3).
Both tests now use a **built** position — two face-up, unclaimed, equally
valuable Problems the seat can solve either of, differing only in scope —
played under H2 for the divergence and under the baseline for the
control. The mutation goes red there.
**This is also a finding about the module, not only about the test.** The
scope term is **inert at round-one positions**: the module cannot reach a
decision until more than one Problem is solvable, so anything measuring
H2 with round-one-heavy play is measuring a mechanism that has not
started. Recorded rather than tuned away.
## Two things this pass fixed that were not the task
**A test keyed on a word another repo owns.** T01's controls found their