Some checks failed
ci / check (push) Failing after 3s
The spec is explicit: a WORKPLAN is active|done|paused; in_progress is a TASK status. I used the task vocabulary on the workplan frontmatter, and the hub rejected both with a 422 on every sync. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
183 lines
7.2 KiB
Markdown
183 lines
7.2 KiB
Markdown
---
|
||
id: CB-WP-0048
|
||
kind: product
|
||
title: "A configuration, not a variant"
|
||
status: active
|
||
state_hub_workstream_id: "44ceb8d8-e6e2-46d6-a694-fd275804b771"
|
||
---
|
||
|
||
# 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
|
||
state_hub_task_id: "fe1a39f4-d123-4c83-be64-35901603edcd"
|
||
```
|
||
|
||
**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: done
|
||
priority: high
|
||
state_hub_task_id: "4b8bfc25-0e4d-4fdc-9dad-5cdb66798207"
|
||
```
|
||
|
||
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.
|
||
|
||
**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
|
||
state_hub_task_id: "3232a451-b60a-42f6-8200-b8115d4b35b9"
|
||
```
|
||
|
||
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
|
||
state_hub_task_id: "5be13b74-bcc9-4697-96bb-91f1966c760b"
|
||
```
|
||
|
||
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
|
||
state_hub_task_id: "ff135f86-2265-4db5-b412-23fcb68df489"
|
||
```
|
||
|
||
**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.
|