clay-borg/workplans/CB-WP-0048-a-configuration-not-a-variant.md
tegwick 75080beb03
Some checks are pending
ci / check (push) Waiting to run
CB-WP-0048: conform task headings to the parser's shape
status.py resolves `## Task: <text>` immediately above a task block;
`## Task T00:` resolved to nothing and the gate said so.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 22:09:58 +02:00

154 lines
5.7 KiB
Markdown

---
id: CB-WP-0048
kind: product
title: "A configuration, not a variant"
status: in_progress
---
# 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
```task
id: CB-WP-0048-T00
status: done
priority: high
```
**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`
```task
id: CB-WP-0048-T01
status: todo
priority: high
```
Per ADR-0022 D1. Identity as data, behaviour exhaustive, `resolve()`
between them.
**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
```task
id: CB-WP-0048-T02
status: todo
priority: high
```
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.
## Task: the resolved configuration is recorded
```task
id: CB-WP-0048-T03
status: todo
priority: high
```
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.
## Task: the page and the panels speak aspects
```task
id: CB-WP-0048-T04
status: todo
priority: normal
```
**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.
## 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.