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
11 KiB
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:
- Hosts
rule.disposition-ladder— required exactly once across all bibles; the build hard-fails without it. - The world-building skill's teaching specimen —
SKILL.md:100("match the voice and structure ofcontent/lore/duncarrow.md— it is the reference specimen");schema.md(organize-like-duncarrow; "the ladder already lives induncarrow.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). - A dedicated build test —
tools/content_build/tests/test_duncarrow.py, plus Duncarrow references intest_model.py. - 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). schema.md's inline worked example tiesperson.old-teaguetotown.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,fennare legacy hand-authored (bare ids);mera-fenn,mayor-oswin-crell,harn-blackwoodare generated fromduncarrow.md'snpc.*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.mdis the permanent neutral home for mechanicalrule.*entries. - The required-once invariant is preserved (moved, not duplicated). The ladder must land in
mechanics.mdbeforeduncarrow.mdis 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 guardedperson, itsnpc.*interactive layer (start_disposition: cold, warms up), and one personalfact(secrecy 2) gated atwarm. 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 thegreywater_docksseed). A header comment states plainly: this file is a format specimen, not game canon. status: candidate— the build validates it (--checkresolves itsrelatedand checks its gate against the ladder) but emits nothing tocontent/world/orcontent/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 inmechanics.md) — resolves because the build parses allcontent/lore/*.mdtogether.
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 ofcontent/lore/duncarrow.md" → point atcontent/lore/specimen.md(structure) and note cosmology for voice.schema.md: "organize a file … likeduncarrow.md" →specimen.md; "the ladder already lives induncarrow.md" → "inmechanics.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'srelated: [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.pyand the Duncarrow references intest_model.pyonto 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 iscandidate(unemitted), routing/emit assertions belong on syntheticcanonfixtures constructed in-test, not on the specimen; the specimen backs validation/resolution assertions. - Evals: rewrite the 3 Duncarrow-based
evals/evals.jsonentries 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.elvesandregion.the-tallow-reachare 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-ladderlives incontent/lore/mechanics.md(verbatim), exactly once across all bibles;content/lore/duncarrow.mdno longer exists.content/lore/specimen.mdexists,status: candidate, synthetic non-canon ids, one place + one guardedperson/npc.*+ onewarm-gatedfact; validated by--checkand emitted nowhere (no specimen JSON undercontent/world/orcontent/server/).- The generated Duncarrow artifacts (
mera-fenn,mayor-oswin-crell,harn-blackwoodacross canon/topics/npcs, client + server; the Crell topic chain) are gone; legacybrannoc/cadwyn/fennnpc 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_buildregenerates cleanly;--checkexits 0 (fresh, valid, no orphans, no secrecy leaks);pytest tools/content_build/tests -qgreen.- Cosmology + the-seven content and the hand-authored POC seed JSON are unchanged.
content/lore/canon-roadmap.mdupdated (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.