diff --git a/docs/superpowers/specs/2026-07-12-duncarrow-purge-design.md b/docs/superpowers/specs/2026-07-12-duncarrow-purge-design.md new file mode 100644 index 0000000..78036bb --- /dev/null +++ b/docs/superpowers/specs/2026-07-12-duncarrow-purge-design.md @@ -0,0 +1,171 @@ +# Duncarrow purge — decouple scaffolding from infrastructure + +**Status:** approved design, ready for implementation plan +**Date:** 2026-07-12 +**Follows:** `2026-07-12-cosmology-and-worldbuilding-theme-design.md` §6 (which flagged this +purge) and the merged cosmology (dev `df5ed2b`). + +**Scope:** Remove the Duncarrow scaffolding content, preserve the schema/disposition-gate +*infrastructure* it currently carries via a synthetic non-canon specimen, and author +**zero real game content**. Deliberately minimal blast radius: nothing this spec produces +is rebuilt when the NPC model or Margreave lore is later reworked. + +--- + +## 1. Why this is more than a deletion + +`content/lore/duncarrow.md` was authored as scaffolding to build the content schema + the +world-building skill (see the cosmology spec §6). It is **not game story** and is slated +for removal. But it is currently **load-bearing infrastructure** in five places, so a naive +delete breaks the build, the skill, the tests, and the evals: + +1. **Hosts `rule.disposition-ladder`** — required *exactly once* across all bibles; the + build hard-fails without it. +2. **The world-building skill's teaching specimen** — `SKILL.md:100` ("match the voice and + structure of `content/lore/duncarrow.md` — it is the reference specimen"); `schema.md` + (organize-like-duncarrow; "the ladder already lives in `duncarrow.md`"; "mirror the + Crell chain 1→2→2→3→4"; the Mera Fenn reachable-ceiling example); `tone.md` (the + "prosperous and orderly" body quote; "Mera Fenn is the model"; Old Teague). +3. **A dedicated build test** — `tools/content_build/tests/test_duncarrow.py`, plus + Duncarrow references in `test_model.py`. +4. **The eval suite** — 3 of the world-building skill's evals (`evals/evals.json`) are + built on Duncarrow (add-an-NPC-to-Duncarrow; contradict-the-Crell-chain; + elves-beyond-Duncarrow). +5. **`schema.md`'s inline worked example** ties `person.old-teague` to `town.duncarrow`. + +The design separates the two roles Duncarrow conflates — **game story** (delete) and +**schema teaching example** (preserve, synthetically). + +## 2. The deletion is self-contained (verified) + +- The hand-authored POC seed JSON (`content/origins/`, `content/world/quests/`, + `content/world/locations/`, `content/world/items/`) references **none** of Duncarrow's + bible ids (grep clean). It is not touched (see §7). +- The cosmology bibles (`cosmology.md`, `the-seven.md`) reference no Duncarrow id. +- `content/world/npcs/` is a shared dir: `brannoc_thane`, `cadwyn_vell`, `fenn` are legacy + hand-authored (bare ids); `mera-fenn`, `mayor-oswin-crell`, `harn-blackwood` are + **generated** from `duncarrow.md`'s `npc.*` entries. Deleting the source + rebuilding + triggers the build's orphan-cleanup to remove the three generated ones (client + server) + while leaving the three legacy ones. (This is the exact "generated-npc orphan-in-shared- + dir" path the build tool already covers.) + +So deleting `duncarrow.md` dangles no bible reference; the only follow-through is the +build's own orphan cleanup, which is already implemented and tested. + +## 3. Reparent the disposition-ladder → `content/lore/mechanics.md` + +Create `content/lore/mechanics.md` and move `rule.disposition-ladder` into it **verbatim** +(same `id`, `type`, `secrecy: 0`, `rungs: [hostile, cold, neutral, warm, trusted]`, body). + +- **Home choice rationale:** the ladder is a **dialogue mechanic**, not cosmological lore + (so not `cosmology.md`, despite the cosmology spec's loose suggestion) and not the + specimen (which must stay disposable). `mechanics.md` is the permanent neutral home for + mechanical `rule.*` entries. +- The required-once invariant is preserved (moved, not duplicated). The ladder must land in + `mechanics.md` **before** `duncarrow.md` is deleted, or an intermediate build fails. + +## 4. The synthetic specimen → `content/lore/specimen.md` + +Create `content/lore/specimen.md` — the skill's schema/disposition-gate teaching example, +lifted from `schema.md`'s already-written *Old Teague* and cut free of its Duncarrow tie. + +- **Entries:** one generic `place`, one guarded `person`, its `npc.*` interactive layer + (`start_disposition: cold`, warms up), and one personal `fact` (secrecy 2) gated at + `warm`. The Teague shape: guarded-then-warm, one earned personal reveal, no plot weight. +- **Obviously-synthetic, non-Margreave ids** — e.g. `place.specimen-wharf`, + `person.specimen-teague`, `npc.specimen-teague`, `fact.specimen-foreign-coin` (final ids + are the plan's call, but they MUST read as "format example," not real content, and MUST + NOT collide with existing ids like the `greywater_docks` seed). A header comment states + plainly: *this file is a format specimen, not game canon.* +- **`status: candidate`** — the build **validates** it (`--check` resolves its `related` + and checks its gate against the ladder) but **emits nothing** to `content/world/` or + `content/server/`. No synthetic NPC ships in the game bundle. This is the key property: + the specimen teaches humans and stays build-honest, without polluting real content. +- The specimen's gate references a ladder rung, so it depends on `rule.disposition-ladder` + (now in `mechanics.md`) — resolves because the build parses all `content/lore/*.md` + together. + +## 5. Repoint the world-building skill (and improve it) + +Duncarrow played two skill roles; split them across two stable targets: + +- **Schema / disposition-gate STRUCTURE** → the **specimen**: + - `SKILL.md:100` "match the voice and structure of `content/lore/duncarrow.md`" → + point at `content/lore/specimen.md` (structure) and note cosmology for voice. + - `schema.md`: "organize a file … like `duncarrow.md`" → `specimen.md`; "the ladder + already lives in `duncarrow.md`" → "in `mechanics.md`"; "mirror the Crell chain + 1→2→2→3→4" → describe the ascending-secrecy chain generically (the specimen only has a + single fact, so the chain example becomes prose guidance, not a pointer to a deleted + chain); the Mera Fenn reachable-ceiling paragraph → reframe generically or onto the + specimen; the inline worked example's `related: [town.duncarrow]` → the specimen place. +- **Narrator VOICE / tone** → the **cosmology bodies** (permanent canon, strong dry-voice + exemplars): + - `tone.md` "prosperous and orderly place…" quote → a cosmology body quote (e.g. the + Warden's "the oldest argument there is," or the Seven's "Most of the Margreave believes + the Seven are real. Most of the Margreave is right."). + - `tone.md` "Mera Fenn is the model" (fear-as-prickliness, guarded-then-warm) → the + **specimen's** npc as the guarded-then-warm model; keep the mechanic, swap the name. + - `tone.md` "Old Teague's 'dryness turns to something almost fond'" → the specimen npc + (which is Teague) — keep, just ensure it points at the specimen, not Duncarrow. + +Net effect: the skill's **voice** examples now cite real permanent canon and its +**structure** example is a build-validated fixture — both strictly better than pointing at +scaffolding. + +## 6. Tests and evals + +- **Tests:** migrate `test_duncarrow.py` and the Duncarrow references in `test_model.py` + onto the **specimen** and/or **synthetic in-test fixtures**. Preserve the *behaviors* + that mattered — secrecy routing (a secret body never reaches the client), gate/rung + resolution, generated-npc orphan cleanup — but assert them against content that still + exists after the purge. No test may reference a deleted id. Because the specimen is + `candidate` (unemitted), routing/emit assertions belong on synthetic `canon` fixtures + constructed in-test, not on the specimen; the specimen backs validation/resolution + assertions. +- **Evals:** rewrite the 3 Duncarrow-based `evals/evals.json` entries so they target + surviving content: + - add-an-NPC eval → author against the specimen's place / a generic setting. + - contradiction eval → *don't let an NPC reveal the Warden's name* (or otherwise + contradict cosmology canon) — cosmology now provides real canon to reconcile against. + - elves-beyond-Duncarrow eval → a generic "start a new storyline in its own file" prompt + (no Duncarrow dependency). + +## 7. Out of scope (stays intact) + +- Any **real** Margreave town, region, faction, NPC, quest, item, or origin. +- The **NPC-model redesign** the user has flagged as in-flight — this spec must not depend + on or pre-empt it. +- The **hand-authored POC seed JSON** (`content/origins/deserter.json`, + `content/world/quests/find_the_ledger.json`, `content/world/locations/greywater_docks.json`, + `content/world/items/*`): no coupling to Duncarrow bible ids, and editing it pulls in the + runtime/new-game construction surface. Left untouched. (If a later cycle retires the POC + seeds, that is its own spec.) +- **`faction.elves` and `region.the-tallow-reach`** are deleted with the rest (clean slate, + per the design decision) — re-authored as real content later, not preserved as stubs. + +## 8. Acceptance criteria + +- `rule.disposition-ladder` lives in `content/lore/mechanics.md` (verbatim), exactly once + across all bibles; `content/lore/duncarrow.md` no longer exists. +- `content/lore/specimen.md` exists, `status: candidate`, synthetic non-canon ids, one + place + one guarded `person`/`npc.*` + one `warm`-gated `fact`; validated by `--check` + and **emitted nowhere** (no specimen JSON under `content/world/` or `content/server/`). +- The generated Duncarrow artifacts (`mera-fenn`, `mayor-oswin-crell`, `harn-blackwood` + across canon/topics/npcs, client + server; the Crell topic chain) are gone; legacy + `brannoc`/`cadwyn`/`fenn` npc JSON remain. +- No skill file, test, or eval references a deleted id or `duncarrow.md`; the skill's + structure pointers target the specimen and its voice pointers target cosmology. +- `PYTHONPATH=tools python -m content_build` regenerates cleanly; `--check` exits 0 (fresh, + valid, no orphans, no secrecy leaks); `pytest tools/content_build/tests -q` green. +- Cosmology + the-seven content and the hand-authored POC seed JSON are unchanged. +- `content/lore/canon-roadmap.md` updated (Duncarrow removed; ladder → mechanics.md; + specimen established). + +## 9. Blast-radius summary (why this scoping) + +Everything authored here is either permanent infrastructure (`mechanics.md`, the ladder's +home) or an explicitly disposable teaching fixture (`specimen.md`) — plus doc/test/eval +pointer swaps. When the NPC model and real Margreave lore are reworked, **none of this is +rebuilt**. The only thing that would force the specimen to change is a change to the `npc.*` +**schema itself** (a new required field / a changed gate model) — which would ripple through +*all* content regardless, so it is not a blast radius this spec can or should try to avoid.