clay-borg/editions/CATALOG.md
tegwick 3045eb03f8
Some checks failed
ci / check (push) Has been cancelled
CB-WP-0049 T02/T03: a seat that plays its objective, and F27 splits in two
objective() reads GroundState::score (now public) rather than restating
what winning is; a copy in the bot would disagree with the kernel the
first time ground-game rules on F28.

Working out WHERE the modes can differ was most of the task and it
bounds the result: SOLVE always claims for the actor, so own-score and
group-score want the same SOLVE nearly everywhere. That is a fact about
GROUND's action set, not a shortcoming of the bot. Two real divergences,
both readable off the table: SUPPORT regulates someone else (worth less
against a rival, worth MORE under coalitions where a Bond merges them
into my side), and SOLVE's value is the card's value, which greedy
ignores entirely.

THE RESULT — F27 splits in two:
  group success  UNCHANGED in 34 of 36 cells
  who wins       MOVES: BONDED COALITIONS at 4p goes 2.04 -> 2.98,
                 2.12 -> 3.29, 2.05 -> 3.01 winning seats per game

So "the competitive modes are scoring lenses over cooperative play" was
too strong and is withdrawn. The sharper claim: GROUND's scoring modes
change WHO WINS, not WHETHER THE GROUP SUCCEEDS. And the effect is
seat-band dependent -- 2p none, 4p largest, 6p none under coalitions;
two relation slots capping network growth is a candidate explanation and
is untested.

The panel now prints BOTH policies side by side. That was a correction
mid-task: the first version printed only the new one and I compared it
against a figure remembered from CB-WP-0047 -- a comparison against a
board nobody re-ran.

Control that makes the numbers mean anything: under SHARED GROUND the
two policies agree at all but <=2 decision points across 12 boards, so a
moving column is mode-awareness and not simply a different bot.

Also: two T01 tests keyed on `status: proposed`, which ground-game
renamed to `ready-for-implement` mid-session. They now find the module
by asking resolve() -- the structural property is ours and does not move
when another repo edits its vocabulary.

Also: `make vendor` replaces three hand re-vendors with a tool that
regenerates digests by walking editions/, and reports one-sided files
rather than resolving them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 23:31:11 +02:00

141 lines
6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Edition & rules catalog (schema 2 — composable modules by **aspect**)
**Authority:** this file + [`catalog.yaml`](catalog.yaml) on `main`.
**Aspect map:** [`ASPECTS.md`](ASPECTS.md) — full design-space dimensionality for GROUND.
**Simulator research:** clay-borg `research/CB-RES-0010-game-aspects-and-design-space.md`
**Purpose:** pin **baseline content** and **independent rules modules** so humans and **clay-borg** can run any module alone or in combination, measure, keep, or reject — without silent baseline edits.
---
## Model
```
┌─────────────────────┐
│ baseline content │ editions/ground-darvo-rN/
│ (CSVs, print data) │
└──────────┬──────────┘
┌─────────────────────┼─────────────────────┐
▼ ▼ ▼
problem_stress attack_relief end_condition …
(≤1 module) (≤1 module) (≤1 module)
▲ ▲ ▲
└────────── aspects of the game ────────────┘
```
| Concept | Meaning |
|---------|---------|
| **Aspect** | An orthogonal **design dimension** of the game (how stress is routed, how the game ends, how Problems enter play, …). Full list: [ASPECTS.md](ASPECTS.md). |
| **Baseline** | Edition **data** package (`Problems.csv`, modes, …). Frozen columns still require `rN→rN+1` (GROUND-WP-0002 T01). |
| **Module** | One implementable choice on **one aspect**. Defaults are named modules with no delta. |
| **Profile** | Named list of modules (convenience). **Not** a third rules source — expands to baseline + modules. |
| **Configuration** | Baseline + resolved module list = what is actually played. |
| **Composition** | At most **one module per aspect**. Missing aspects use `default_module`. |
**Independence rule:** a module may only declare rules on its **own aspect**. Cross-aspect effects belong in a **profile** (explicit combo) or a new aspect — never silent coupling inside one module.
**Legacy experiments** (`editions/experiments/h1-…`, `h2-…`) remain on disk as measured packages; they map to **profiles**. Prefer `module_id` / `profile_id` going forward.
**Synonym:** older docs said *axis* for aspect. Machine field is `aspect:`.
---
## Aspects with modules (registered)
| Aspect | Default | Other modules |
|--------|---------|----------------|
| `problem_stress` | `none` | `flat_any_open` (H1-A, reject), `scoped` (H2, keep) |
| `attack_relief` | `none` | `self_soothe_ge4` (H1-B) |
| `end_condition` | `fixed_rounds_5` | `hybrid_clear_collapse` (**ready-for-implement**) |
| `problem_deal` | `fixed_setup` | `pressure_deck` (**ready-for-implement**) |
Many other aspects exist but are **fixed in r0** until a competing design appears (see ASPECTS.md § full map).
---
## Selection (clay-borg / trials)
### Preferred API
```yaml
baseline: ground-darvo-r0
modules:
- problem_stress.scoped
- end_condition.hybrid_clear_collapse # when implemented
# other aspects → defaults
```
Or:
```yaml
profile: h2
# expands to modules: [problem_stress.scoped]
```
Or multi-aspect:
```yaml
profile: scoped_plus_attack_soothe
# problem_stress.scoped + attack_relief.self_soothe_ge4
```
### Validation
1. Every `module_id` exists and `selectable: true`.
2. No two modules share the same **aspect**.
3. `status: proposed` modules may be selected only if the host declares `allow_proposed: true` (kernel may no-op or refuse).
4. State / recordings must store the **resolved module list** (and baseline id), not only a legacy experiment string — so A/B names the **point in design space**.
### Implementation
- Baseline CSVs: vendor as today.
- Each module: apply `rules_delta` + optional `data_overlays` from its `path`.
- Apply modules in **aspect order** listed in `catalog.yaml` `aspects:` (stable, documented).
- Conflict: refuse composition rather than last-write-wins.
---
## Profiles (named combos)
| profile_id | modules | note |
|------------|---------|------|
| `baseline` | (defaults) | Pure r0 |
| `h1` | flat + attack soothe | Legacy H1; reject-as-baseline |
| `h2` | scoped | Legacy H2; keep-as-experiment |
| `scoped_plus_attack_soothe` | scoped + soothe | Unmeasured combo |
| `scoped_plus_hybrid_end` | scoped + hybrid end | Needs kernel for end |
| `scoped_plus_pressure_deck` | scoped + pressure deck | Needs kernel for deal |
---
## Adding a module (checklist)
1. Confirm the **aspect** exists in [ASPECTS.md](ASPECTS.md); add the aspect first if needed.
2. Create `editions/modules/<aspect>/<slug>/` with `MODULE.md` and, if non-default, `rules_delta.yaml` (+ CSV overlays if needed).
3. Register under `modules:` with `aspect`, `path`, `status`, `decision`.
4. Optionally add a **profile** that includes it alone and/or with other modules.
5. Message clay-borg: `module_id`, aspect, delta path, compose examples.
6. Measure **alone** first when possible; then measure interesting **profiles**.
7. Update `utility_estimate` / `decision` per module (and per profile if combo-specific).
### What must not happen
- Silent edit of frozen baseline columns inside `ground-darvo-r0`.
- A new mega-experiment that re-bundles three aspects into one non-decomposable id (use a profile instead).
- Modules that hard-require another aspects module without documenting a profile.
---
## Git
**main + catalog** is discovery; commits pin digests; branches optional for WIP. Modules live as directories on `main`.
---
## Legacy map
| Old experiment | Prefer |
|----------------|--------|
| `h1-problem-stress` | profile `h1` or modules `problem_stress.flat_any_open` + `attack_relief.self_soothe_ge4` |
| `h2-scoped-problem-stress` | profile `h2` or module `problem_stress.scoped` |