# 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. - **`consumed_files` (RPT-0006):** when present on a module, a consumer that has not read those paths is in a **detectable** incomplete state — not silence. Freshness/edition-check should fail or warn if a listed file is unread or undigested. Modules without the field still work; new modules should list it. --- ## 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///` 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 aspect’s 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` |