clay-borg/workplans/CB-WP-0048-a-configuration-not-a-variant.md

255 lines
11 KiB
Markdown
Raw Normal View History

ADR-0022 + CB-WP-0048 T00: the selector decision, and the mirror held The maintainer's observation decided the design: aspects partition the GAME, strata partition our apparatus, and they are orthogonal. A module is one coordinate change in aspect space with an obligation in every stratum. So aspect identity must NOT be Rust types -- an aspect ground-game adds would make clay-borg fail to parse a configuration rather than fail to run it, welding the two coordinate systems at the one place they must stay independent. Chosen: identity as data (Configuration round-trips anything the catalog names), behaviour exhaustive (Rules, no catch-all), resolve() between. Decisive argument: the catalog ALREADY ships modules with a rules_delta and status: proposed, so a per-aspect enum would report them as "unknown module" -- indistinguishable from a typo, a false statement about the edition, and this project's signature failure shape. Two facts need two errors. Federating design authority is permanent, so the representation must outlive the implementation. Legacy ids alias forever through the catalog's own legacy_experiment_id, on the standard-Np precedent: 26 recordings name them and the expansion is exact, so there is nothing to deprecate. T00 done: the schema-2 mirror had arrived with no digests (19 files) and edition-check was red. Digests are now generated by WALKING editions/, not typed -- two reviews already found hand-written lists that made their own controls vacuous, and a mirror that grows a directory is what breaks a maintained list. PROVENANCE-catalog.md was a file inside the mirrored tree that upstream does not have; folded into our own PROVENANCE.md, since provenance about the mirror does not belong inside the thing it describes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 22:07:57 +02:00
---
id: CB-WP-0048
kind: product
title: "A configuration, not a variant"
CB-WP-0049 T04: a seat that attends to the modules in play 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>
2026-08-09 01:25:22 +02:00
status: done
state_hub_workstream_id: "44ceb8d8-e6e2-46d6-a694-fd275804b771"
ADR-0022 + CB-WP-0048 T00: the selector decision, and the mirror held The maintainer's observation decided the design: aspects partition the GAME, strata partition our apparatus, and they are orthogonal. A module is one coordinate change in aspect space with an obligation in every stratum. So aspect identity must NOT be Rust types -- an aspect ground-game adds would make clay-borg fail to parse a configuration rather than fail to run it, welding the two coordinate systems at the one place they must stay independent. Chosen: identity as data (Configuration round-trips anything the catalog names), behaviour exhaustive (Rules, no catch-all), resolve() between. Decisive argument: the catalog ALREADY ships modules with a rules_delta and status: proposed, so a per-aspect enum would report them as "unknown module" -- indistinguishable from a typo, a false statement about the edition, and this project's signature failure shape. Two facts need two errors. Federating design authority is permanent, so the representation must outlive the implementation. Legacy ids alias forever through the catalog's own legacy_experiment_id, on the standard-Np precedent: 26 recordings name them and the expansion is exact, so there is nothing to deprecate. T00 done: the schema-2 mirror had arrived with no digests (19 files) and edition-check was red. Digests are now generated by WALKING editions/, not typed -- two reviews already found hand-written lists that made their own controls vacuous, and a mirror that grows a directory is what breaks a maintained list. PROVENANCE-catalog.md was a file inside the mirrored tree that upstream does not have; folded into our own PROVENANCE.md, since provenance about the mirror does not belong inside the thing it describes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 22:07:57 +02:00
---
# Purpose
```
structural tier M (changes the state and therefore the recording, and
replaces the selector every consumer names)
declared tier M
```
Implements [ADR-0022](../decisions/ADR-0022-a-configuration-is-a-point-in-aspect-space.md),
adopting ground-game catalog **schema 2** per
[CB-RES-0010](../research/CB-RES-0010-game-aspects-and-design-space.md).
## The gap, stated exactly
`scoped_plus_attack_soothe` is a profile in the vendored catalog **today**.
clay-borg cannot name it — not "has not implemented", *cannot express*.
`Variant` has three arms; H1 bundles flat pressure with self-soothe and
cannot be taken apart, H2 gives scoping alone, and their product has no
arm. Every future combination has the same problem.
The kernel is not the obstacle: **four sites branch on the variant and
each belongs to exactly one aspect** (ADR-0022 Context). The selector is
the blob.
## Task: the mirror is held by the gate
ADR-0022 + CB-WP-0048 T00: the selector decision, and the mirror held The maintainer's observation decided the design: aspects partition the GAME, strata partition our apparatus, and they are orthogonal. A module is one coordinate change in aspect space with an obligation in every stratum. So aspect identity must NOT be Rust types -- an aspect ground-game adds would make clay-borg fail to parse a configuration rather than fail to run it, welding the two coordinate systems at the one place they must stay independent. Chosen: identity as data (Configuration round-trips anything the catalog names), behaviour exhaustive (Rules, no catch-all), resolve() between. Decisive argument: the catalog ALREADY ships modules with a rules_delta and status: proposed, so a per-aspect enum would report them as "unknown module" -- indistinguishable from a typo, a false statement about the edition, and this project's signature failure shape. Two facts need two errors. Federating design authority is permanent, so the representation must outlive the implementation. Legacy ids alias forever through the catalog's own legacy_experiment_id, on the standard-Np precedent: 26 recordings name them and the expansion is exact, so there is nothing to deprecate. T00 done: the schema-2 mirror had arrived with no digests (19 files) and edition-check was red. Digests are now generated by WALKING editions/, not typed -- two reviews already found hand-written lists that made their own controls vacuous, and a mirror that grows a directory is what breaks a maintained list. PROVENANCE-catalog.md was a file inside the mirrored tree that upstream does not have; folded into our own PROVENANCE.md, since provenance about the mirror does not belong inside the thing it describes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 22:07:57 +02:00
```task
id: CB-WP-0048-T00
status: done
priority: high
state_hub_task_id: "fe1a39f4-d123-4c83-be64-35901603edcd"
ADR-0022 + CB-WP-0048 T00: the selector decision, and the mirror held The maintainer's observation decided the design: aspects partition the GAME, strata partition our apparatus, and they are orthogonal. A module is one coordinate change in aspect space with an obligation in every stratum. So aspect identity must NOT be Rust types -- an aspect ground-game adds would make clay-borg fail to parse a configuration rather than fail to run it, welding the two coordinate systems at the one place they must stay independent. Chosen: identity as data (Configuration round-trips anything the catalog names), behaviour exhaustive (Rules, no catch-all), resolve() between. Decisive argument: the catalog ALREADY ships modules with a rules_delta and status: proposed, so a per-aspect enum would report them as "unknown module" -- indistinguishable from a typo, a false statement about the edition, and this project's signature failure shape. Two facts need two errors. Federating design authority is permanent, so the representation must outlive the implementation. Legacy ids alias forever through the catalog's own legacy_experiment_id, on the standard-Np precedent: 26 recordings name them and the expansion is exact, so there is nothing to deprecate. T00 done: the schema-2 mirror had arrived with no digests (19 files) and edition-check was red. Digests are now generated by WALKING editions/, not typed -- two reviews already found hand-written lists that made their own controls vacuous, and a mirror that grows a directory is what breaks a maintained list. PROVENANCE-catalog.md was a file inside the mirrored tree that upstream does not have; folded into our own PROVENANCE.md, since provenance about the mirror does not belong inside the thing it describes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 22:07:57 +02:00
```
**Done 2026-08-08.** The schema-2 mirror (`catalog.yaml`, `ASPECTS.md`,
`CATALOG.md`, `modules/`) arrived vendored with **no recorded digests**
19 files — and `make edition-check` was red on the working tree.
- Digests are now **generated by walking `editions/`**, not typed. Two
reviews (CB-REV-0002 #8, CB-REV-0003 #8) already found hand-written
lists that made their own controls vacuous; a mirror that grows a
*directory* is precisely the case a maintained list loses.
- `editions/PROVENANCE-catalog.md` was a file **inside the mirrored tree
that upstream does not have**, which the gate correctly refused as
unexplained. Folded into `editions/ground-darvo-r0/PROVENANCE.md`
provenance *about* the mirror is ours, so it does not live inside the
thing it describes.
**Noted, not fixed:** `vendored_files()` matches only `.csv` inside the
edition directory, so a non-CSV added *there* is invisible to both the
digest and the freshness check. The sibling walk has no such hole. The
exposure is one file today (`PROVENANCE.md`, ours) — but this is F26's
shape again and should be closed on its own terms.
## Task: `Configuration` and `Rules`
ADR-0022 + CB-WP-0048 T00: the selector decision, and the mirror held The maintainer's observation decided the design: aspects partition the GAME, strata partition our apparatus, and they are orthogonal. A module is one coordinate change in aspect space with an obligation in every stratum. So aspect identity must NOT be Rust types -- an aspect ground-game adds would make clay-borg fail to parse a configuration rather than fail to run it, welding the two coordinate systems at the one place they must stay independent. Chosen: identity as data (Configuration round-trips anything the catalog names), behaviour exhaustive (Rules, no catch-all), resolve() between. Decisive argument: the catalog ALREADY ships modules with a rules_delta and status: proposed, so a per-aspect enum would report them as "unknown module" -- indistinguishable from a typo, a false statement about the edition, and this project's signature failure shape. Two facts need two errors. Federating design authority is permanent, so the representation must outlive the implementation. Legacy ids alias forever through the catalog's own legacy_experiment_id, on the standard-Np precedent: 26 recordings name them and the expansion is exact, so there is nothing to deprecate. T00 done: the schema-2 mirror had arrived with no digests (19 files) and edition-check was red. Digests are now generated by WALKING editions/, not typed -- two reviews already found hand-written lists that made their own controls vacuous, and a mirror that grows a directory is what breaks a maintained list. PROVENANCE-catalog.md was a file inside the mirrored tree that upstream does not have; folded into our own PROVENANCE.md, since provenance about the mirror does not belong inside the thing it describes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 22:07:57 +02:00
```task
id: CB-WP-0048-T01
status: done
ADR-0022 + CB-WP-0048 T00: the selector decision, and the mirror held The maintainer's observation decided the design: aspects partition the GAME, strata partition our apparatus, and they are orthogonal. A module is one coordinate change in aspect space with an obligation in every stratum. So aspect identity must NOT be Rust types -- an aspect ground-game adds would make clay-borg fail to parse a configuration rather than fail to run it, welding the two coordinate systems at the one place they must stay independent. Chosen: identity as data (Configuration round-trips anything the catalog names), behaviour exhaustive (Rules, no catch-all), resolve() between. Decisive argument: the catalog ALREADY ships modules with a rules_delta and status: proposed, so a per-aspect enum would report them as "unknown module" -- indistinguishable from a typo, a false statement about the edition, and this project's signature failure shape. Two facts need two errors. Federating design authority is permanent, so the representation must outlive the implementation. Legacy ids alias forever through the catalog's own legacy_experiment_id, on the standard-Np precedent: 26 recordings name them and the expansion is exact, so there is nothing to deprecate. T00 done: the schema-2 mirror had arrived with no digests (19 files) and edition-check was red. Digests are now generated by WALKING editions/, not typed -- two reviews already found hand-written lists that made their own controls vacuous, and a mirror that grows a directory is what breaks a maintained list. PROVENANCE-catalog.md was a file inside the mirrored tree that upstream does not have; folded into our own PROVENANCE.md, since provenance about the mirror does not belong inside the thing it describes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 22:07:57 +02:00
priority: high
state_hub_task_id: "4b8bfc25-0e4d-4fdc-9dad-5cdb66798207"
ADR-0022 + CB-WP-0048 T00: the selector decision, and the mirror held The maintainer's observation decided the design: aspects partition the GAME, strata partition our apparatus, and they are orthogonal. A module is one coordinate change in aspect space with an obligation in every stratum. So aspect identity must NOT be Rust types -- an aspect ground-game adds would make clay-borg fail to parse a configuration rather than fail to run it, welding the two coordinate systems at the one place they must stay independent. Chosen: identity as data (Configuration round-trips anything the catalog names), behaviour exhaustive (Rules, no catch-all), resolve() between. Decisive argument: the catalog ALREADY ships modules with a rules_delta and status: proposed, so a per-aspect enum would report them as "unknown module" -- indistinguishable from a typo, a false statement about the edition, and this project's signature failure shape. Two facts need two errors. Federating design authority is permanent, so the representation must outlive the implementation. Legacy ids alias forever through the catalog's own legacy_experiment_id, on the standard-Np precedent: 26 recordings name them and the expansion is exact, so there is nothing to deprecate. T00 done: the schema-2 mirror had arrived with no digests (19 files) and edition-check was red. Digests are now generated by WALKING editions/, not typed -- two reviews already found hand-written lists that made their own controls vacuous, and a mirror that grows a directory is what breaks a maintained list. PROVENANCE-catalog.md was a file inside the mirrored tree that upstream does not have; folded into our own PROVENANCE.md, since provenance about the mirror does not belong inside the thing it describes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 22:07:57 +02:00
```
Per ADR-0022 D1. Identity as data, behaviour exhaustive, `resolve()`
between them.
**Done 2026-08-08.** `catalog.rs` reads schema 2 (aspects, modules,
profiles) and **refuses a schema it does not understand by name** — a
reader that silently accepted schema 1 would answer questions about
aspects over a file that has none. `config.rs` holds `Configuration`
(identity), `Rules` (behaviour) and `resolve()`.
Nothing about the aspect list, the defaults, or which modules are
proposed is written in our source; all of it is read. The tests locate
the proposed module **by searching the catalog for `status: proposed`**,
so if ground-game implements it upstream the test looks elsewhere rather
than going stale.
| mutation | what went red |
|---|---|
| the two errors become one sentence | *"a module the catalog HAS was reported as unknown"* |
| one-per-aspect check removed | *"two modules on one aspect must be refused"* |
| identity refuses what it cannot run | *"selecting a catalog module must NAME a configuration"* |
| legacy lookup stops reading the catalog | *"h2 and profile h2 are not the same point in aspect space"* |
`scoped_plus_attack_soothe` now resolves — `problem_stress.scoped` ×
`attack_relief.self_soothe_ge4`, the combination the three-armed enum
could not express.
ADR-0022 + CB-WP-0048 T00: the selector decision, and the mirror held The maintainer's observation decided the design: aspects partition the GAME, strata partition our apparatus, and they are orthogonal. A module is one coordinate change in aspect space with an obligation in every stratum. So aspect identity must NOT be Rust types -- an aspect ground-game adds would make clay-borg fail to parse a configuration rather than fail to run it, welding the two coordinate systems at the one place they must stay independent. Chosen: identity as data (Configuration round-trips anything the catalog names), behaviour exhaustive (Rules, no catch-all), resolve() between. Decisive argument: the catalog ALREADY ships modules with a rules_delta and status: proposed, so a per-aspect enum would report them as "unknown module" -- indistinguishable from a typo, a false statement about the edition, and this project's signature failure shape. Two facts need two errors. Federating design authority is permanent, so the representation must outlive the implementation. Legacy ids alias forever through the catalog's own legacy_experiment_id, on the standard-Np precedent: 26 recordings name them and the expansion is exact, so there is nothing to deprecate. T00 done: the schema-2 mirror had arrived with no digests (19 files) and edition-check was red. Digests are now generated by WALKING editions/, not typed -- two reviews already found hand-written lists that made their own controls vacuous, and a mirror that grows a directory is what breaks a maintained list. PROVENANCE-catalog.md was a file inside the mirrored tree that upstream does not have; folded into our own PROVENANCE.md, since provenance about the mirror does not belong inside the thing it describes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 22:07:57 +02:00
**Controls:**
- **a proposed module is refused BY NAME**, distinguishably from a typo —
the two-error requirement is the reason this shape was chosen, so it is
the first test;
- **two modules on one aspect are refused** (GAME↔MODEL validation);
- **an aspect the catalog has and the kernel does not know still parses**,
because a configuration must be nameable before it is runnable;
- **`Rules` has no catch-all arm**, so a new module cannot fall through
silently (CB-WP-0034's exhaustiveness, which caught two commands before
any test ran);
- mutation-proven, each control against its own defect.
## Task: legacy ids alias forever
ADR-0022 + CB-WP-0048 T00: the selector decision, and the mirror held The maintainer's observation decided the design: aspects partition the GAME, strata partition our apparatus, and they are orthogonal. A module is one coordinate change in aspect space with an obligation in every stratum. So aspect identity must NOT be Rust types -- an aspect ground-game adds would make clay-borg fail to parse a configuration rather than fail to run it, welding the two coordinate systems at the one place they must stay independent. Chosen: identity as data (Configuration round-trips anything the catalog names), behaviour exhaustive (Rules, no catch-all), resolve() between. Decisive argument: the catalog ALREADY ships modules with a rules_delta and status: proposed, so a per-aspect enum would report them as "unknown module" -- indistinguishable from a typo, a false statement about the edition, and this project's signature failure shape. Two facts need two errors. Federating design authority is permanent, so the representation must outlive the implementation. Legacy ids alias forever through the catalog's own legacy_experiment_id, on the standard-Np precedent: 26 recordings name them and the expansion is exact, so there is nothing to deprecate. T00 done: the schema-2 mirror had arrived with no digests (19 files) and edition-check was red. Digests are now generated by WALKING editions/, not typed -- two reviews already found hand-written lists that made their own controls vacuous, and a mirror that grows a directory is what breaks a maintained list. PROVENANCE-catalog.md was a file inside the mirrored tree that upstream does not have; folded into our own PROVENANCE.md, since provenance about the mirror does not belong inside the thing it describes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 22:07:57 +02:00
```task
id: CB-WP-0048-T02
CB-WP-0048 T02/T03/T04: Configuration replaces Variant in the state The three-armed enum could not express a configuration carrying two modules. It does now: --variant h1 expands to problem_stress.flat_any_open AND attack_relief.self_soothe_ge4, and scoped_plus_attack_soothe plays. Legacy names alias forever via serde(alias="variant") plus a scalar-or-map deserialiser. serde(default) alone would have been a silent migration bug -- every H1/H2 recording would have come back as baseline. All 26 scenarios pass unchanged; none pins a state hash. Three things shipped broken first, all caught by gates rather than by reading: 1. `profile` was in the state hash. with_config(select("ground-darvo-r0")) sets profile=Some("baseline") where setup alone leaves None, so two states at THE SAME POINT IN ASPECT SPACE hashed differently and a replay bundle stopped reproducing its own initial state. Now serde(skip): a hash covers what determines play. This was the open judgement from T01 and it did not survive contact with the replay path. 2. A YAML parse inside the event loop. rules() -> resolve() -> catalog() re-parsed catalog.yaml per rule check; AM-6 fell to 9,345 events/s against a 100,000 target. OnceLock, and aspect validation moved to where a configuration is BUILT. Then I nearly optimised a phantom: 470k still looked like a 3x regression against the "~1.7M on bnt-lap001" reference in the gate's own message. Making rules() free measured 491k -- this machine's ceiling. Before optimising against a reference, measure the ceiling with the suspect code removed. 3. The refusal did not fire on the path a player takes. `--module problem_deal.pressure_deck` played a full baseline game and reported success, because with_config is a builder and fell back to the printed rules -- the silent no-op ADR-0022 exists to refuse. Every unit test of resolve() passed. The helper was tested and the driver was not, which is CB-WP-0033's finding verbatim. The new test asserts refusal BY NAME and that no game was played. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 00:54:34 +02:00
status: done
ADR-0022 + CB-WP-0048 T00: the selector decision, and the mirror held The maintainer's observation decided the design: aspects partition the GAME, strata partition our apparatus, and they are orthogonal. A module is one coordinate change in aspect space with an obligation in every stratum. So aspect identity must NOT be Rust types -- an aspect ground-game adds would make clay-borg fail to parse a configuration rather than fail to run it, welding the two coordinate systems at the one place they must stay independent. Chosen: identity as data (Configuration round-trips anything the catalog names), behaviour exhaustive (Rules, no catch-all), resolve() between. Decisive argument: the catalog ALREADY ships modules with a rules_delta and status: proposed, so a per-aspect enum would report them as "unknown module" -- indistinguishable from a typo, a false statement about the edition, and this project's signature failure shape. Two facts need two errors. Federating design authority is permanent, so the representation must outlive the implementation. Legacy ids alias forever through the catalog's own legacy_experiment_id, on the standard-Np precedent: 26 recordings name them and the expansion is exact, so there is nothing to deprecate. T00 done: the schema-2 mirror had arrived with no digests (19 files) and edition-check was red. Digests are now generated by WALKING editions/, not typed -- two reviews already found hand-written lists that made their own controls vacuous, and a mirror that grows a directory is what breaks a maintained list. PROVENANCE-catalog.md was a file inside the mirrored tree that upstream does not have; folded into our own PROVENANCE.md, since provenance about the mirror does not belong inside the thing it describes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 22:07:57 +02:00
priority: high
state_hub_task_id: "3232a451-b60a-42f6-8200-b8115d4b35b9"
ADR-0022 + CB-WP-0048 T00: the selector decision, and the mirror held The maintainer's observation decided the design: aspects partition the GAME, strata partition our apparatus, and they are orthogonal. A module is one coordinate change in aspect space with an obligation in every stratum. So aspect identity must NOT be Rust types -- an aspect ground-game adds would make clay-borg fail to parse a configuration rather than fail to run it, welding the two coordinate systems at the one place they must stay independent. Chosen: identity as data (Configuration round-trips anything the catalog names), behaviour exhaustive (Rules, no catch-all), resolve() between. Decisive argument: the catalog ALREADY ships modules with a rules_delta and status: proposed, so a per-aspect enum would report them as "unknown module" -- indistinguishable from a typo, a false statement about the edition, and this project's signature failure shape. Two facts need two errors. Federating design authority is permanent, so the representation must outlive the implementation. Legacy ids alias forever through the catalog's own legacy_experiment_id, on the standard-Np precedent: 26 recordings name them and the expansion is exact, so there is nothing to deprecate. T00 done: the schema-2 mirror had arrived with no digests (19 files) and edition-check was red. Digests are now generated by WALKING editions/, not typed -- two reviews already found hand-written lists that made their own controls vacuous, and a mirror that grows a directory is what breaks a maintained list. PROVENANCE-catalog.md was a file inside the mirrored tree that upstream does not have; folded into our own PROVENANCE.md, since provenance about the mirror does not belong inside the thing it describes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 22:07:57 +02:00
```
Per ADR-0022 D2, through the catalog's own `legacy_experiment_id`.
**Controls:**
- **all 26 recordings replay byte-identically**, which is the whole
constraint — `make sim` is the authority;
- **`--variant h2` and `--profile h2` produce the same resolved
configuration**, asserted on the resolved object rather than on
behaviour, so the equivalence is exact and not a coincidence of
outcomes;
- **the expansion comes from the catalog**, not a table in our source: a
second copy of ground-game's mapping is F25's shape.
CB-WP-0048 T02/T03/T04: Configuration replaces Variant in the state The three-armed enum could not express a configuration carrying two modules. It does now: --variant h1 expands to problem_stress.flat_any_open AND attack_relief.self_soothe_ge4, and scoped_plus_attack_soothe plays. Legacy names alias forever via serde(alias="variant") plus a scalar-or-map deserialiser. serde(default) alone would have been a silent migration bug -- every H1/H2 recording would have come back as baseline. All 26 scenarios pass unchanged; none pins a state hash. Three things shipped broken first, all caught by gates rather than by reading: 1. `profile` was in the state hash. with_config(select("ground-darvo-r0")) sets profile=Some("baseline") where setup alone leaves None, so two states at THE SAME POINT IN ASPECT SPACE hashed differently and a replay bundle stopped reproducing its own initial state. Now serde(skip): a hash covers what determines play. This was the open judgement from T01 and it did not survive contact with the replay path. 2. A YAML parse inside the event loop. rules() -> resolve() -> catalog() re-parsed catalog.yaml per rule check; AM-6 fell to 9,345 events/s against a 100,000 target. OnceLock, and aspect validation moved to where a configuration is BUILT. Then I nearly optimised a phantom: 470k still looked like a 3x regression against the "~1.7M on bnt-lap001" reference in the gate's own message. Making rules() free measured 491k -- this machine's ceiling. Before optimising against a reference, measure the ceiling with the suspect code removed. 3. The refusal did not fire on the path a player takes. `--module problem_deal.pressure_deck` played a full baseline game and reported success, because with_config is a builder and fell back to the printed rules -- the silent no-op ADR-0022 exists to refuse. Every unit test of resolve() passed. The helper was tested and the driver was not, which is CB-WP-0033's finding verbatim. The new test asserts refusal BY NAME and that no game was played. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 00:54:34 +02:00
**Done 2026-08-08.** `GroundState.variant: Variant` became
`config: Configuration`, with `#[serde(alias = "variant")]` plus a
scalar-or-map deserialiser so a recording written before this loads by
its old name and old spelling. **`serde(default)` alone would have been a
silent migration bug**: every recording played under H1 or H2 would have
come back as the baseline.
All 26 scenarios pass unchanged — none pins a state hash. `--variant h2`,
`--profile h2` and `--module problem_stress.scoped` all resolve to the
same point in aspect space, and `--variant h1` expands to **two** modules
on two aspects, which is the decomposition schema 2 exists for.
## Task: the resolved configuration is recorded
ADR-0022 + CB-WP-0048 T00: the selector decision, and the mirror held The maintainer's observation decided the design: aspects partition the GAME, strata partition our apparatus, and they are orthogonal. A module is one coordinate change in aspect space with an obligation in every stratum. So aspect identity must NOT be Rust types -- an aspect ground-game adds would make clay-borg fail to parse a configuration rather than fail to run it, welding the two coordinate systems at the one place they must stay independent. Chosen: identity as data (Configuration round-trips anything the catalog names), behaviour exhaustive (Rules, no catch-all), resolve() between. Decisive argument: the catalog ALREADY ships modules with a rules_delta and status: proposed, so a per-aspect enum would report them as "unknown module" -- indistinguishable from a typo, a false statement about the edition, and this project's signature failure shape. Two facts need two errors. Federating design authority is permanent, so the representation must outlive the implementation. Legacy ids alias forever through the catalog's own legacy_experiment_id, on the standard-Np precedent: 26 recordings name them and the expansion is exact, so there is nothing to deprecate. T00 done: the schema-2 mirror had arrived with no digests (19 files) and edition-check was red. Digests are now generated by WALKING editions/, not typed -- two reviews already found hand-written lists that made their own controls vacuous, and a mirror that grows a directory is what breaks a maintained list. PROVENANCE-catalog.md was a file inside the mirrored tree that upstream does not have; folded into our own PROVENANCE.md, since provenance about the mirror does not belong inside the thing it describes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 22:07:57 +02:00
```task
id: CB-WP-0048-T03
CB-WP-0048 T02/T03/T04: Configuration replaces Variant in the state The three-armed enum could not express a configuration carrying two modules. It does now: --variant h1 expands to problem_stress.flat_any_open AND attack_relief.self_soothe_ge4, and scoped_plus_attack_soothe plays. Legacy names alias forever via serde(alias="variant") plus a scalar-or-map deserialiser. serde(default) alone would have been a silent migration bug -- every H1/H2 recording would have come back as baseline. All 26 scenarios pass unchanged; none pins a state hash. Three things shipped broken first, all caught by gates rather than by reading: 1. `profile` was in the state hash. with_config(select("ground-darvo-r0")) sets profile=Some("baseline") where setup alone leaves None, so two states at THE SAME POINT IN ASPECT SPACE hashed differently and a replay bundle stopped reproducing its own initial state. Now serde(skip): a hash covers what determines play. This was the open judgement from T01 and it did not survive contact with the replay path. 2. A YAML parse inside the event loop. rules() -> resolve() -> catalog() re-parsed catalog.yaml per rule check; AM-6 fell to 9,345 events/s against a 100,000 target. OnceLock, and aspect validation moved to where a configuration is BUILT. Then I nearly optimised a phantom: 470k still looked like a 3x regression against the "~1.7M on bnt-lap001" reference in the gate's own message. Making rules() free measured 491k -- this machine's ceiling. Before optimising against a reference, measure the ceiling with the suspect code removed. 3. The refusal did not fire on the path a player takes. `--module problem_deal.pressure_deck` played a full baseline game and reported success, because with_config is a builder and fell back to the printed rules -- the silent no-op ADR-0022 exists to refuse. Every unit test of resolve() passed. The helper was tested and the driver was not, which is CB-WP-0033's finding verbatim. The new test asserts refusal BY NAME and that no game was played. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 00:54:34 +02:00
status: done
ADR-0022 + CB-WP-0048 T00: the selector decision, and the mirror held The maintainer's observation decided the design: aspects partition the GAME, strata partition our apparatus, and they are orthogonal. A module is one coordinate change in aspect space with an obligation in every stratum. So aspect identity must NOT be Rust types -- an aspect ground-game adds would make clay-borg fail to parse a configuration rather than fail to run it, welding the two coordinate systems at the one place they must stay independent. Chosen: identity as data (Configuration round-trips anything the catalog names), behaviour exhaustive (Rules, no catch-all), resolve() between. Decisive argument: the catalog ALREADY ships modules with a rules_delta and status: proposed, so a per-aspect enum would report them as "unknown module" -- indistinguishable from a typo, a false statement about the edition, and this project's signature failure shape. Two facts need two errors. Federating design authority is permanent, so the representation must outlive the implementation. Legacy ids alias forever through the catalog's own legacy_experiment_id, on the standard-Np precedent: 26 recordings name them and the expansion is exact, so there is nothing to deprecate. T00 done: the schema-2 mirror had arrived with no digests (19 files) and edition-check was red. Digests are now generated by WALKING editions/, not typed -- two reviews already found hand-written lists that made their own controls vacuous, and a mirror that grows a directory is what breaks a maintained list. PROVENANCE-catalog.md was a file inside the mirrored tree that upstream does not have; folded into our own PROVENANCE.md, since provenance about the mirror does not belong inside the thing it describes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 22:07:57 +02:00
priority: high
state_hub_task_id: "5be13b74-bcc9-4697-96bb-91f1966c760b"
ADR-0022 + CB-WP-0048 T00: the selector decision, and the mirror held The maintainer's observation decided the design: aspects partition the GAME, strata partition our apparatus, and they are orthogonal. A module is one coordinate change in aspect space with an obligation in every stratum. So aspect identity must NOT be Rust types -- an aspect ground-game adds would make clay-borg fail to parse a configuration rather than fail to run it, welding the two coordinate systems at the one place they must stay independent. Chosen: identity as data (Configuration round-trips anything the catalog names), behaviour exhaustive (Rules, no catch-all), resolve() between. Decisive argument: the catalog ALREADY ships modules with a rules_delta and status: proposed, so a per-aspect enum would report them as "unknown module" -- indistinguishable from a typo, a false statement about the edition, and this project's signature failure shape. Two facts need two errors. Federating design authority is permanent, so the representation must outlive the implementation. Legacy ids alias forever through the catalog's own legacy_experiment_id, on the standard-Np precedent: 26 recordings name them and the expansion is exact, so there is nothing to deprecate. T00 done: the schema-2 mirror had arrived with no digests (19 files) and edition-check was red. Digests are now generated by WALKING editions/, not typed -- two reviews already found hand-written lists that made their own controls vacuous, and a mirror that grows a directory is what breaks a maintained list. PROVENANCE-catalog.md was a file inside the mirrored tree that upstream does not have; folded into our own PROVENANCE.md, since provenance about the mirror does not belong inside the thing it describes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 22:07:57 +02:00
```
Per ADR-0022 D3 and CB-RES-0010 §5.3: `cb-play` sessions, replays, trial
logs and panel cells carry the **resolved** module list.
**Controls:**
- **the recorded configuration is the applied one**, proven the way
CB-WP-0046 proved the trial-log stamp — from the state, not the flag;
- **the trial-log marker carries the configuration**, closing the gap
CB-WP-0047 left open (variant stamped, scenario and mode not);
- **a bare field write cannot leave a module inert** — the H2 defect had
three call sites and this is the generalisation of it.
CB-WP-0048 T02/T03/T04: Configuration replaces Variant in the state The three-armed enum could not express a configuration carrying two modules. It does now: --variant h1 expands to problem_stress.flat_any_open AND attack_relief.self_soothe_ge4, and scoped_plus_attack_soothe plays. Legacy names alias forever via serde(alias="variant") plus a scalar-or-map deserialiser. serde(default) alone would have been a silent migration bug -- every H1/H2 recording would have come back as baseline. All 26 scenarios pass unchanged; none pins a state hash. Three things shipped broken first, all caught by gates rather than by reading: 1. `profile` was in the state hash. with_config(select("ground-darvo-r0")) sets profile=Some("baseline") where setup alone leaves None, so two states at THE SAME POINT IN ASPECT SPACE hashed differently and a replay bundle stopped reproducing its own initial state. Now serde(skip): a hash covers what determines play. This was the open judgement from T01 and it did not survive contact with the replay path. 2. A YAML parse inside the event loop. rules() -> resolve() -> catalog() re-parsed catalog.yaml per rule check; AM-6 fell to 9,345 events/s against a 100,000 target. OnceLock, and aspect validation moved to where a configuration is BUILT. Then I nearly optimised a phantom: 470k still looked like a 3x regression against the "~1.7M on bnt-lap001" reference in the gate's own message. Making rules() free measured 491k -- this machine's ceiling. Before optimising against a reference, measure the ceiling with the suspect code removed. 3. The refusal did not fire on the path a player takes. `--module problem_deal.pressure_deck` played a full baseline game and reported success, because with_config is a builder and fell back to the printed rules -- the silent no-op ADR-0022 exists to refuse. Every unit test of resolve() passed. The helper was tested and the driver was not, which is CB-WP-0033's finding verbatim. The new test asserts refusal BY NAME and that no game was played. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 00:54:34 +02:00
**Done 2026-08-08**, and the interesting part is what shipped broken
first.
### `profile` was in the hash, and it should not have been
The replay walk caught it within the hour: `with_config(select("ground-darvo-r0"))`
sets `profile = Some("baseline")` while `setup` alone leaves it `None`,
so **two states at the same point in aspect space hashed differently** and
a bundle stopped reproducing its own initial state. `profile` is now
`#[serde(skip)]`. A state hash should cover what determines play;
provenance of what was *requested* belongs in the recording's manifest.
This was the open judgement flagged when T01 landed. It did not survive
contact with the replay path, which is the right way for it to have been
settled.
### A YAML parse inside the event loop
`rules()` called `resolve()` called `catalog()`, which re-parsed
`catalog.yaml` **per rule check**. AM-6 throughput fell to **9,345
events/s** against a 100,000 target — a spec gate, caught the same run.
The catalog is an `include_str!` constant, so parsing it more than once
was never doing anything but work; it is a `OnceLock` now, and the aspect
validation moved out of `resolve` to where a configuration is *built*.
**And then I nearly optimised a phantom.** 470k events/s still looked
like a 3x regression against the *"~1.7M on bnt-lap001"* reference in the
gate's own message. Making `rules()` free and re-measuring gave **491k**
— this machine's ceiling. The reference is another machine, and the only
real regression was the one already fixed. The control is cheap and worth
naming: **before optimising against a reference, measure the ceiling with
the suspect code removed.**
### The refusal did not fire on the path a player takes
`--module problem_deal.pressure_deck` **played a full baseline game and
reported success.** `with_config` is a builder, cannot return an error,
and fell back to the printed rules — the silent no-op ADR-0022 exists to
refuse. Every unit test of `resolve()` passed throughout.
**The helper was tested and the driver was not**, which is exactly
CB-WP-0033's finding: *"the unit test proves the helper; only the
integration test proves the driver, and the driver was where the data
loss lived."* The driver resolves before dealing now, and the new test
asserts both that it refuses **by name** and that **no game was played**
a refusal that still deals is the same no-op wearing an error message.
## Task: the page and the panels speak aspects
ADR-0022 + CB-WP-0048 T00: the selector decision, and the mirror held The maintainer's observation decided the design: aspects partition the GAME, strata partition our apparatus, and they are orthogonal. A module is one coordinate change in aspect space with an obligation in every stratum. So aspect identity must NOT be Rust types -- an aspect ground-game adds would make clay-borg fail to parse a configuration rather than fail to run it, welding the two coordinate systems at the one place they must stay independent. Chosen: identity as data (Configuration round-trips anything the catalog names), behaviour exhaustive (Rules, no catch-all), resolve() between. Decisive argument: the catalog ALREADY ships modules with a rules_delta and status: proposed, so a per-aspect enum would report them as "unknown module" -- indistinguishable from a typo, a false statement about the edition, and this project's signature failure shape. Two facts need two errors. Federating design authority is permanent, so the representation must outlive the implementation. Legacy ids alias forever through the catalog's own legacy_experiment_id, on the standard-Np precedent: 26 recordings name them and the expansion is exact, so there is nothing to deprecate. T00 done: the schema-2 mirror had arrived with no digests (19 files) and edition-check was red. Digests are now generated by WALKING editions/, not typed -- two reviews already found hand-written lists that made their own controls vacuous, and a mirror that grows a directory is what breaks a maintained list. PROVENANCE-catalog.md was a file inside the mirrored tree that upstream does not have; folded into our own PROVENANCE.md, since provenance about the mirror does not belong inside the thing it describes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 22:07:57 +02:00
```task
id: CB-WP-0048-T04
CB-WP-0048 T02/T03/T04: Configuration replaces Variant in the state The three-armed enum could not express a configuration carrying two modules. It does now: --variant h1 expands to problem_stress.flat_any_open AND attack_relief.self_soothe_ge4, and scoped_plus_attack_soothe plays. Legacy names alias forever via serde(alias="variant") plus a scalar-or-map deserialiser. serde(default) alone would have been a silent migration bug -- every H1/H2 recording would have come back as baseline. All 26 scenarios pass unchanged; none pins a state hash. Three things shipped broken first, all caught by gates rather than by reading: 1. `profile` was in the state hash. with_config(select("ground-darvo-r0")) sets profile=Some("baseline") where setup alone leaves None, so two states at THE SAME POINT IN ASPECT SPACE hashed differently and a replay bundle stopped reproducing its own initial state. Now serde(skip): a hash covers what determines play. This was the open judgement from T01 and it did not survive contact with the replay path. 2. A YAML parse inside the event loop. rules() -> resolve() -> catalog() re-parsed catalog.yaml per rule check; AM-6 fell to 9,345 events/s against a 100,000 target. OnceLock, and aspect validation moved to where a configuration is BUILT. Then I nearly optimised a phantom: 470k still looked like a 3x regression against the "~1.7M on bnt-lap001" reference in the gate's own message. Making rules() free measured 491k -- this machine's ceiling. Before optimising against a reference, measure the ceiling with the suspect code removed. 3. The refusal did not fire on the path a player takes. `--module problem_deal.pressure_deck` played a full baseline game and reported success, because with_config is a builder and fell back to the printed rules -- the silent no-op ADR-0022 exists to refuse. Every unit test of resolve() passed. The helper was tested and the driver was not, which is CB-WP-0033's finding verbatim. The new test asserts refusal BY NAME and that no game was played. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 00:54:34 +02:00
status: done
ADR-0022 + CB-WP-0048 T00: the selector decision, and the mirror held The maintainer's observation decided the design: aspects partition the GAME, strata partition our apparatus, and they are orthogonal. A module is one coordinate change in aspect space with an obligation in every stratum. So aspect identity must NOT be Rust types -- an aspect ground-game adds would make clay-borg fail to parse a configuration rather than fail to run it, welding the two coordinate systems at the one place they must stay independent. Chosen: identity as data (Configuration round-trips anything the catalog names), behaviour exhaustive (Rules, no catch-all), resolve() between. Decisive argument: the catalog ALREADY ships modules with a rules_delta and status: proposed, so a per-aspect enum would report them as "unknown module" -- indistinguishable from a typo, a false statement about the edition, and this project's signature failure shape. Two facts need two errors. Federating design authority is permanent, so the representation must outlive the implementation. Legacy ids alias forever through the catalog's own legacy_experiment_id, on the standard-Np precedent: 26 recordings name them and the expansion is exact, so there is nothing to deprecate. T00 done: the schema-2 mirror had arrived with no digests (19 files) and edition-check was red. Digests are now generated by WALKING editions/, not typed -- two reviews already found hand-written lists that made their own controls vacuous, and a mirror that grows a directory is what breaks a maintained list. PROVENANCE-catalog.md was a file inside the mirrored tree that upstream does not have; folded into our own PROVENANCE.md, since provenance about the mirror does not belong inside the thing it describes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 22:07:57 +02:00
priority: normal
state_hub_task_id: "ff135f86-2265-4db5-b412-23fcb68df489"
ADR-0022 + CB-WP-0048 T00: the selector decision, and the mirror held The maintainer's observation decided the design: aspects partition the GAME, strata partition our apparatus, and they are orthogonal. A module is one coordinate change in aspect space with an obligation in every stratum. So aspect identity must NOT be Rust types -- an aspect ground-game adds would make clay-borg fail to parse a configuration rather than fail to run it, welding the two coordinate systems at the one place they must stay independent. Chosen: identity as data (Configuration round-trips anything the catalog names), behaviour exhaustive (Rules, no catch-all), resolve() between. Decisive argument: the catalog ALREADY ships modules with a rules_delta and status: proposed, so a per-aspect enum would report them as "unknown module" -- indistinguishable from a typo, a false statement about the edition, and this project's signature failure shape. Two facts need two errors. Federating design authority is permanent, so the representation must outlive the implementation. Legacy ids alias forever through the catalog's own legacy_experiment_id, on the standard-Np precedent: 26 recordings name them and the expansion is exact, so there is nothing to deprecate. T00 done: the schema-2 mirror had arrived with no digests (19 files) and edition-check was red. Digests are now generated by WALKING editions/, not typed -- two reviews already found hand-written lists that made their own controls vacuous, and a mirror that grows a directory is what breaks a maintained list. PROVENANCE-catalog.md was a file inside the mirrored tree that upstream does not have; folded into our own PROVENANCE.md, since provenance about the mirror does not belong inside the thing it describes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 22:07:57 +02:00
```
**Controls:**
- **the table names every live module**, not a legacy id — the CB-WP-0044
family: a rules change the page cannot name is reported as "no changes";
- **panels facet by aspect** (CB-RES-0010 §5.4), so "hold all aspects
fixed, vary one" is what the harness does rather than what a reader
reconstructs;
- **a module nothing measured is reported unmeasured**, not absent.
CB-WP-0048 T02/T03/T04: Configuration replaces Variant in the state The three-armed enum could not express a configuration carrying two modules. It does now: --variant h1 expands to problem_stress.flat_any_open AND attack_relief.self_soothe_ge4, and scoped_plus_attack_soothe plays. Legacy names alias forever via serde(alias="variant") plus a scalar-or-map deserialiser. serde(default) alone would have been a silent migration bug -- every H1/H2 recording would have come back as baseline. All 26 scenarios pass unchanged; none pins a state hash. Three things shipped broken first, all caught by gates rather than by reading: 1. `profile` was in the state hash. with_config(select("ground-darvo-r0")) sets profile=Some("baseline") where setup alone leaves None, so two states at THE SAME POINT IN ASPECT SPACE hashed differently and a replay bundle stopped reproducing its own initial state. Now serde(skip): a hash covers what determines play. This was the open judgement from T01 and it did not survive contact with the replay path. 2. A YAML parse inside the event loop. rules() -> resolve() -> catalog() re-parsed catalog.yaml per rule check; AM-6 fell to 9,345 events/s against a 100,000 target. OnceLock, and aspect validation moved to where a configuration is BUILT. Then I nearly optimised a phantom: 470k still looked like a 3x regression against the "~1.7M on bnt-lap001" reference in the gate's own message. Making rules() free measured 491k -- this machine's ceiling. Before optimising against a reference, measure the ceiling with the suspect code removed. 3. The refusal did not fire on the path a player takes. `--module problem_deal.pressure_deck` played a full baseline game and reported success, because with_config is a builder and fell back to the printed rules -- the silent no-op ADR-0022 exists to refuse. Every unit test of resolve() passed. The helper was tested and the driver was not, which is CB-WP-0033's finding verbatim. The new test asserts refusal BY NAME and that no game was played. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 00:54:34 +02:00
**Done 2026-08-08.** The page names every live module —
`attack_relief.self_soothe_ge4 + problem_stress.scoped` where `h2` could
only ever have said one thing — and names the baseline by id when none
are live, because "no modules" and "we could not read the catalog" must
not look the same on the line a player uses to tell rules sets apart.
The four aspects sitting at their defaults are **declared omitted** from
the player page with a reason: an aspect at its default *is* the printed
game, and naming all four on every page is the wall of rules a player
stops reading. `cb-play inspect` prints all four, because a maintainer
diffing two states is asking a different question (ADR-0022 D3).
ADR-0022 + CB-WP-0048 T00: the selector decision, and the mirror held The maintainer's observation decided the design: aspects partition the GAME, strata partition our apparatus, and they are orthogonal. A module is one coordinate change in aspect space with an obligation in every stratum. So aspect identity must NOT be Rust types -- an aspect ground-game adds would make clay-borg fail to parse a configuration rather than fail to run it, welding the two coordinate systems at the one place they must stay independent. Chosen: identity as data (Configuration round-trips anything the catalog names), behaviour exhaustive (Rules, no catch-all), resolve() between. Decisive argument: the catalog ALREADY ships modules with a rules_delta and status: proposed, so a per-aspect enum would report them as "unknown module" -- indistinguishable from a typo, a false statement about the edition, and this project's signature failure shape. Two facts need two errors. Federating design authority is permanent, so the representation must outlive the implementation. Legacy ids alias forever through the catalog's own legacy_experiment_id, on the standard-Np precedent: 26 recordings name them and the expansion is exact, so there is nothing to deprecate. T00 done: the schema-2 mirror had arrived with no digests (19 files) and edition-check was red. Digests are now generated by WALKING editions/, not typed -- two reviews already found hand-written lists that made their own controls vacuous, and a mirror that grows a directory is what breaks a maintained list. PROVENANCE-catalog.md was a file inside the mirrored tree that upstream does not have; folded into our own PROVENANCE.md, since provenance about the mirror does not belong inside the thing it describes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 22:07:57 +02:00
## Not done here
- **No policy reads the configuration.** F27 already records that the
three scoring modes produce identical play because `GreedyPolicy` never
consults `state.mode`; the same will be true of every aspect. Selection
without aspect-aware policies gives configurations we can run and cannot
evaluate — CB-RES-0010 §5.4's last bullet is F27 restated. **This is the
next pass, and it is a prerequisite for measuring any new module**, not
a nicety.
- **`end_condition` and `problem_deal` get no kernel path here.** Both
their non-default modules are `status: proposed`; T01 makes them
nameable and refusable, which is what ADR-0022 asks for and all it asks
for.
- **`specs/Taxonomy.md` does not yet distinguish aspect from stratum.**
ADR-0022 D0 states the distinction; the taxonomy is where it belongs,
and without it the two vocabularies will be crossed in exactly the way
the taxonomy exists to prevent.