docs(spec): Duncarrow purge — decouple scaffolding from infrastructure

Delete the Duncarrow scaffolding while preserving the schema/disposition-gate
infrastructure it carries: reparent rule.disposition-ladder into a new
mechanics.md, stand up a synthetic status:candidate specimen (validated but
never emitted), repoint the skill/tests/evals. Zero real game content; the
in-flight NPC redesign and the hand-authored POC seed JSON stay out of scope.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HuHRPE7VfppUJEaoGBEUqZ
This commit is contained in:
2026-07-12 15:11:14 -05:00
parent df5ed2b525
commit 9aa06d59d7

View File

@@ -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.