From ac8da4e6dade3dd8bf8f6e93e5515ec1c6749e07 Mon Sep 17 00:00:00 2001 From: Phillip Tarrant Date: Sun, 12 Jul 2026 15:30:59 -0500 Subject: [PATCH] feat(content): reparent disposition-ladder to mechanics.md; purge Duncarrow Move rule.disposition-ladder into content/lore/mechanics.md and delete the Duncarrow scaffolding (source + 23 generated JSON). Remove the redundant test_duncarrow.py (routing/secrecy already covered by test_emit.py synthetic fixtures); repoint a cosmetic slug-test id. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01HuHRPE7VfppUJEaoGBEUqZ --- content/lore/duncarrow.md | 298 ------------------ content/lore/mechanics.md | 21 ++ content/server/npcs/harn-blackwood.json | 5 - content/server/npcs/mayor-oswin-crell.json | 5 - content/server/npcs/mera-fenn.json | 5 - .../server/topics/crell-runs-slave-trade.json | 5 - .../topics/crells-guard-acts-alone.json | 5 - .../server/topics/elves-avoid-the-shrine.json | 5 - content/server/topics/harn-daughter-left.json | 5 - .../topics/militia-never-investigates.json | 5 - .../server/topics/travelers-go-missing.json | 5 - content/world/canon/duncarrow.json | 10 - content/world/canon/elves.json | 6 - content/world/canon/mayor-oswin-crell.json | 8 - content/world/canon/the-tallow-reach.json | 6 - content/world/canon/the-white-antlers.json | 9 - content/world/npcs/harn-blackwood.json | 18 -- content/world/npcs/mayor-oswin-crell.json | 23 -- content/world/npcs/mera-fenn.json | 27 -- .../world/topics/crell-runs-slave-trade.json | 9 - .../world/topics/crells-guard-acts-alone.json | 8 - .../world/topics/elves-avoid-the-shrine.json | 8 - content/world/topics/harn-daughter-left.json | 7 - .../topics/militia-never-investigates.json | 8 - .../world/topics/travelers-go-missing.json | 8 - tools/content_build/tests/test_duncarrow.py | 37 --- tools/content_build/tests/test_model.py | 4 +- 27 files changed, 23 insertions(+), 537 deletions(-) delete mode 100644 content/lore/duncarrow.md create mode 100644 content/lore/mechanics.md delete mode 100644 content/server/npcs/harn-blackwood.json delete mode 100644 content/server/npcs/mayor-oswin-crell.json delete mode 100644 content/server/npcs/mera-fenn.json delete mode 100644 content/server/topics/crell-runs-slave-trade.json delete mode 100644 content/server/topics/crells-guard-acts-alone.json delete mode 100644 content/server/topics/elves-avoid-the-shrine.json delete mode 100644 content/server/topics/harn-daughter-left.json delete mode 100644 content/server/topics/militia-never-investigates.json delete mode 100644 content/server/topics/travelers-go-missing.json delete mode 100644 content/world/canon/duncarrow.json delete mode 100644 content/world/canon/elves.json delete mode 100644 content/world/canon/mayor-oswin-crell.json delete mode 100644 content/world/canon/the-tallow-reach.json delete mode 100644 content/world/canon/the-white-antlers.json delete mode 100644 content/world/npcs/harn-blackwood.json delete mode 100644 content/world/npcs/mayor-oswin-crell.json delete mode 100644 content/world/npcs/mera-fenn.json delete mode 100644 content/world/topics/crell-runs-slave-trade.json delete mode 100644 content/world/topics/crells-guard-acts-alone.json delete mode 100644 content/world/topics/elves-avoid-the-shrine.json delete mode 100644 content/world/topics/harn-daughter-left.json delete mode 100644 content/world/topics/militia-never-investigates.json delete mode 100644 content/world/topics/travelers-go-missing.json delete mode 100644 tools/content_build/tests/test_duncarrow.py diff --git a/content/lore/duncarrow.md b/content/lore/duncarrow.md deleted file mode 100644 index b64e67e..0000000 --- a/content/lore/duncarrow.md +++ /dev/null @@ -1,298 +0,0 @@ -# DUNCARROW — status: canon - -> The bounded-dialogue / disposition-gate specimen, promoted from -> `candidate-town.md`. Every fact_id resolves, every gate is a legal -> disposition value, every knowledge link points at a real fact, and nothing -> here contradicts existing canon. -> -> Disposition ladder referenced by all gates: -> `hostile / cold / neutral / warm / trusted` -> -> Two guard axes, kept separate on purpose: -> - **secrecy** lives on the fact (author-facing, static, mis-authoring guard) -> - **gate** lives on the knowledge link (character-facing, runtime disposition) -> `never` is a real gate: the NPC knows the fact but no disposition unlocks it. - ---- - -## WORLD RULE (canon dependency) - -```yaml -id: rule.disposition-ladder -type: rule -status: canon -secrecy: 0 -related: [] -rungs: [hostile, cold, neutral, warm, trusted] -body: > - NPC trust toward the player is one of five ordered states: - hostile < cold < neutral < warm < trusted. Where a given player sits with a - given NPC is runtime state owned by code. The ladder itself is canon. Every - knowledge-link gate references one of these five names, plus the special - gate `never` (fact is known but never revealed through dialogue at any rung). -``` - -```yaml -id: region.the-tallow-reach -type: region -status: canon -secrecy: 0 -related: [] -body: > - The Tallow Reach — the lowland march of grain towns and wool roads that - Duncarrow sits at the edge of, feeding the pass trade. -``` - -```yaml -id: faction.elves -type: faction -status: canon -secrecy: 0 -related: [] -body: > - The elven travellers of the road — no single polity, but the people whose - passage through the White Antlers, and its recent absence, the town notices. -``` - ---- - -## TOWN — public layer (tier 0, freely given) - -```yaml -id: town.duncarrow -type: town -status: canon -secrecy: 0 -related: [region.the-tallow-reach, place.the-white-antlers, person.mayor-oswin-crell] -body: > - Duncarrow is a walled market town at the edge of the Tallow Reach, grown fat - on the road trade between the lowland grain towns and the pass. Timber and - wool go out; salt, iron, and coin come in. Ten militia hold the walls under - the mayor's charter. It is, by every visible measure, a prosperous and orderly - place, which is exactly the reputation its mayor has spent fifteen years - building and depends on. -``` - -```yaml -id: place.the-white-antlers -type: place -status: canon -secrecy: 0 -related: [town.duncarrow, faction.elves] -body: > - An old elven shrine a half-hour's walk north of Duncarrow, in the birch stand - off the pass road. Weathered antler-carvings, a dry basin, nothing worth - stealing. Elves on the road have historically stopped here. Locals know it as - a curiosity and a good spot to water horses. -``` - -```yaml -id: person.mayor-oswin-crell -type: person -status: canon -secrecy: 0 -related: [town.duncarrow] -body: > - Mayor of Duncarrow for fifteen years. Warm, unhurried, remembers names and - the names of your dead. Runs a clean council and a clean set of books. Widely - liked. The visible locked door of this town: pleasant to every player at every - disposition, and revealing of nothing. -``` - ---- - -## THE SECRET CHAIN (the ladder the town exists to test) - -Ordered from freely-observed to `never`. Each is its own atomic fact so different -NPCs can hold the same fact at different gates. - -```yaml -id: rumor.elves-avoid-the-shrine -type: rumor -status: canon -secrecy: 1 -related: [place.the-white-antlers, faction.elves] -body: > - Elves don't stop at the White Antlers anymore. Have not, for a couple of - years. Anyone observant notices; most townsfolk assume the elves simply moved - on or the road changed. -``` - -```yaml -id: rumor.travelers-go-missing -type: rumor -status: canon -secrecy: 2 -related: [town.duncarrow, place.the-white-antlers] -body: > - Small parties on the north road — always small, always few enough not to be - missed — sometimes don't arrive where they were going. Locals know it as bad - luck on a bad stretch of road. They do not like discussing it. -``` - -```yaml -id: fact.militia-never-investigates -type: fact -status: canon -secrecy: 2 -related: [town.duncarrow, rumor.travelers-go-missing] -body: > - When travelers go missing near the shrine, the town militia does not ride out. - There is always a reason — jurisdiction, weather, the road being the pass's - problem not the town's. The pattern is the tell: this is protected, not - neglected. -``` - -```yaml -id: fact.crells-guard-acts-alone -type: fact -status: canon -secrecy: 3 -related: [person.mayor-oswin-crell, fact.militia-never-investigates] -body: > - The mayor keeps three personal guardsmen who answer only to him, separate from - the town militia of ten. They come and go on the north road at odd hours on - the mayor's word alone. Someone close enough to the militia notices they - operate outside its command entirely. -``` - -```yaml -id: secret.crell-runs-slave-trade -type: secret -status: canon -secrecy: 4 -related: [person.mayor-oswin-crell, place.the-white-antlers, faction.elves] -body: > - Mayor Crell runs an elf-slaving operation. When a small enough elven party - camps near the White Antlers — few enough that no one will come looking — his - three personal guard take them on the road and Crell sells them into slavery - in towns beyond the pass. The town's prosperity and order are partly the - proceeds and partly the cover. - - POC CONSTRAINT: this fact is learnable but not actionable in this build. No NPC - proposes a move to stop it. The witness's top rung delivers understanding, not - a quest. Faction/positional combat that acting on this would require is out of - POC scope. -``` - ---- - -## NPC — THE WITNESS (deep — the variable) - -This is the NPC the POC is really testing. The reachable top rung. Whether -climbing her ladder feels like relationship or like a lockpick minigame IS the -question. - -```yaml -id: npc.mera-fenn -type: person -status: canon -secrecy: 0 -start_disposition: cold -related: [town.duncarrow, fact.crells-guard-acts-alone] -body: > - Mera Fenn runs the north gate's night watch — militia, low rank, overlooked, - which is how she sees things she shouldn't. Dry, tired, careful. She saw the - mayor's guard bring a covered cart through her gate before dawn and was told, - pleasantly, to log it as grain. She has told no one. She is afraid, and her - fear reads as prickliness to strangers — she withholds MORE than a stranger - would, not less, until you've earned otherwise. - -knows: - - {fact: rumor.elves-avoid-the-shrine, gate: neutral} - - {fact: rumor.travelers-go-missing, gate: warm} - - {fact: fact.militia-never-investigates, gate: warm} - - {fact: fact.crells-guard-acts-alone, gate: trusted} - # the reachable ceiling - # She does NOT hold secret.crell-runs-slave-trade. She saw the guard, the cart, - # the pattern — she never saw a sale. Her top rung is naming what she witnessed, - # not stating the whole truth. The player infers the secret; the game never - # hands it over as a line. This is deliberate: understanding earned, not told. - -disposition_notes: > - Starts at `cold`, not `neutral` — she's guarded by default. Hostile is - reachable (push her, threaten, side visibly with the mayor) and at hostile she - reveals nothing, not even the tier-1 rumor a stranger would get. This is the - fear-driven withholding the 5-rung ladder exists for. -``` - ---- - -## NPC — THE MAYOR (medium — the control) - -Holds the secret at `never`. His job is to be the locked door the witness -explains. Do not judge him by the aliveness bar; he is the control, not the -variable. - -```yaml -id: npc.mayor-oswin-crell -type: person -status: canon -secrecy: 0 -start_disposition: neutral -related: [person.mayor-oswin-crell, secret.crell-runs-slave-trade] -body: > - Same person as person.mayor-oswin-crell; this is his interactive NPC layer. - Warm to every player at every rung. Rises to `warm` easily and stalls there — - no disposition moves him past it, because there is nothing past it he will give. - -knows: - - {fact: rumor.elves-avoid-the-shrine, gate: cold} - # dismisses it lightly - - {fact: secret.crell-runs-slave-trade, gate: never} - # knows; unlocked by no rung - - {fact: fact.crells-guard-acts-alone, gate: never} - # knows; explains it away if pressed - -disposition_notes: > - The `never` gates are the point: he KNOWS these facts, the Improviser can - reason with them, and the eight-move vocabulary demonstrably cannot leak them - at any disposition. If a player at `trusted` can get anything out of him about - the guard or the trade, the bounded-dialogue guarantee has failed and the POC - has found a real bug — which is itself a valuable POC result. -``` - ---- - -## NPC — ONE PUBLIC-LAYER TOWNSPERSON (shallow — texture + a clean guarded-personal test) - -Proves the "eloped daughter tier": low-secrecy fact that's still personally -guarded, unrelated to the main secret, so you can test disposition-gating on -something with no plot weight. - -```yaml -id: npc.harn-blackwood -type: person -status: canon -secrecy: 0 -start_disposition: neutral -related: [town.duncarrow] -body: > - Harn Blackwood, the town smith. Gruff, fair, talks freely about iron, the - road, and the price of salt. Carries one small private grief he will not hand - a stranger. - -knows: - - {fact: rumor.travelers-go-missing, gate: warm} - # locals know, say little - - {fact: fact.harn-daughter-left, gate: warm} - # personal, no plot weight - -disposition_notes: > - Control case for the OTHER half of the test: does disposition-gating feel good - on a fact that costs nothing to reveal and spoils nothing? If earning the - daughter story feels warm and human, gating works. If it feels like grinding a - vendor, the mechanic has a problem the plot-secret would only hide. -``` - -```yaml -id: fact.harn-daughter-left -type: fact -status: canon -secrecy: 1 -related: [npc.harn-blackwood] -body: > - Harn's daughter left Duncarrow two winters ago with a wool trader's caravan - and does not write. It shames and grieves him. Spoils nothing; guarded purely - because it is his. -``` diff --git a/content/lore/mechanics.md b/content/lore/mechanics.md new file mode 100644 index 0000000..0a18e1b --- /dev/null +++ b/content/lore/mechanics.md @@ -0,0 +1,21 @@ +# MECHANICS — canonical world rules (mechanical, not lore) + +> Home for mechanical `rule.*` entries the dialogue/engine layer depends on. +> `rule.disposition-ladder` lives here (moved from the retired `duncarrow.md` +> scaffolding); it is the required-exactly-once gate vocabulary every NPC +> knowledge-gate references. + +```yaml +id: rule.disposition-ladder +type: rule +status: canon +secrecy: 0 +related: [] +rungs: [hostile, cold, neutral, warm, trusted] +body: > + NPC trust toward the player is one of five ordered states: + hostile < cold < neutral < warm < trusted. Where a given player sits with a + given NPC is runtime state owned by code. The ladder itself is canon. Every + knowledge-link gate references one of these five names, plus the special + gate `never` (fact is known but never revealed through dialogue at any rung). +``` diff --git a/content/server/npcs/harn-blackwood.json b/content/server/npcs/harn-blackwood.json deleted file mode 100644 index 8d8c486..0000000 --- a/content/server/npcs/harn-blackwood.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "disposition_notes": "Control case for the OTHER half of the test: does disposition-gating feel good on a fact that costs nothing to reveal and spoils nothing? If earning the daughter story feels warm and human, gating works. If it feels like grinding a vendor, the mechanic has a problem the plot-secret would only hide.", - "id": "npc.harn-blackwood", - "persona": "Harn Blackwood, the town smith. Gruff, fair, talks freely about iron, the road, and the price of salt. Carries one small private grief he will not hand a stranger.\n" -} diff --git a/content/server/npcs/mayor-oswin-crell.json b/content/server/npcs/mayor-oswin-crell.json deleted file mode 100644 index f882cca..0000000 --- a/content/server/npcs/mayor-oswin-crell.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "disposition_notes": "The `never` gates are the point: he KNOWS these facts, the Improviser can reason with them, and the eight-move vocabulary demonstrably cannot leak them at any disposition. If a player at `trusted` can get anything out of him about the guard or the trade, the bounded-dialogue guarantee has failed and the POC has found a real bug \u2014 which is itself a valuable POC result.", - "id": "npc.mayor-oswin-crell", - "persona": "Same person as person.mayor-oswin-crell; this is his interactive NPC layer. Warm to every player at every rung. Rises to `warm` easily and stalls there \u2014 no disposition moves him past it, because there is nothing past it he will give.\n" -} diff --git a/content/server/npcs/mera-fenn.json b/content/server/npcs/mera-fenn.json deleted file mode 100644 index 31142d0..0000000 --- a/content/server/npcs/mera-fenn.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "disposition_notes": "Starts at `cold`, not `neutral` \u2014 she's guarded by default. Hostile is reachable (push her, threaten, side visibly with the mayor) and at hostile she reveals nothing, not even the tier-1 rumor a stranger would get. This is the fear-driven withholding the 5-rung ladder exists for.", - "id": "npc.mera-fenn", - "persona": "Mera Fenn runs the north gate's night watch \u2014 militia, low rank, overlooked, which is how she sees things she shouldn't. Dry, tired, careful. She saw the mayor's guard bring a covered cart through her gate before dawn and was told, pleasantly, to log it as grain. She has told no one. She is afraid, and her fear reads as prickliness to strangers \u2014 she withholds MORE than a stranger would, not less, until you've earned otherwise.\n" -} diff --git a/content/server/topics/crell-runs-slave-trade.json b/content/server/topics/crell-runs-slave-trade.json deleted file mode 100644 index 3c07afb..0000000 --- a/content/server/topics/crell-runs-slave-trade.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "body": "Mayor Crell runs an elf-slaving operation. When a small enough elven party camps near the White Antlers \u2014 few enough that no one will come looking \u2014 his three personal guard take them on the road and Crell sells them into slavery in towns beyond the pass. The town's prosperity and order are partly the proceeds and partly the cover.\nPOC CONSTRAINT: this fact is learnable but not actionable in this build. No NPC proposes a move to stop it. The witness's top rung delivers understanding, not a quest. Faction/positional combat that acting on this would require is out of POC scope.", - "id": "secret.crell-runs-slave-trade", - "secrecy": 4 -} diff --git a/content/server/topics/crells-guard-acts-alone.json b/content/server/topics/crells-guard-acts-alone.json deleted file mode 100644 index a2446ee..0000000 --- a/content/server/topics/crells-guard-acts-alone.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "body": "The mayor keeps three personal guardsmen who answer only to him, separate from the town militia of ten. They come and go on the north road at odd hours on the mayor's word alone. Someone close enough to the militia notices they operate outside its command entirely.", - "id": "fact.crells-guard-acts-alone", - "secrecy": 3 -} diff --git a/content/server/topics/elves-avoid-the-shrine.json b/content/server/topics/elves-avoid-the-shrine.json deleted file mode 100644 index dbb0a1e..0000000 --- a/content/server/topics/elves-avoid-the-shrine.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "body": "Elves don't stop at the White Antlers anymore. Have not, for a couple of years. Anyone observant notices; most townsfolk assume the elves simply moved on or the road changed.", - "id": "rumor.elves-avoid-the-shrine", - "secrecy": 1 -} diff --git a/content/server/topics/harn-daughter-left.json b/content/server/topics/harn-daughter-left.json deleted file mode 100644 index 20e6cd8..0000000 --- a/content/server/topics/harn-daughter-left.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "body": "Harn's daughter left Duncarrow two winters ago with a wool trader's caravan and does not write. It shames and grieves him. Spoils nothing; guarded purely because it is his.", - "id": "fact.harn-daughter-left", - "secrecy": 1 -} diff --git a/content/server/topics/militia-never-investigates.json b/content/server/topics/militia-never-investigates.json deleted file mode 100644 index 51e8dbb..0000000 --- a/content/server/topics/militia-never-investigates.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "body": "When travelers go missing near the shrine, the town militia does not ride out. There is always a reason \u2014 jurisdiction, weather, the road being the pass's problem not the town's. The pattern is the tell: this is protected, not neglected.", - "id": "fact.militia-never-investigates", - "secrecy": 2 -} diff --git a/content/server/topics/travelers-go-missing.json b/content/server/topics/travelers-go-missing.json deleted file mode 100644 index fae4d3d..0000000 --- a/content/server/topics/travelers-go-missing.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "body": "Small parties on the north road \u2014 always small, always few enough not to be missed \u2014 sometimes don't arrive where they were going. Locals know it as bad luck on a bad stretch of road. They do not like discussing it.", - "id": "rumor.travelers-go-missing", - "secrecy": 2 -} diff --git a/content/world/canon/duncarrow.json b/content/world/canon/duncarrow.json deleted file mode 100644 index 6393118..0000000 --- a/content/world/canon/duncarrow.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "body": "Duncarrow is a walled market town at the edge of the Tallow Reach, grown fat on the road trade between the lowland grain towns and the pass. Timber and wool go out; salt, iron, and coin come in. Ten militia hold the walls under the mayor's charter. It is, by every visible measure, a prosperous and orderly place, which is exactly the reputation its mayor has spent fifteen years building and depends on.", - "id": "town.duncarrow", - "related": [ - "region.the-tallow-reach", - "place.the-white-antlers", - "person.mayor-oswin-crell" - ], - "type": "town" -} diff --git a/content/world/canon/elves.json b/content/world/canon/elves.json deleted file mode 100644 index 27e098b..0000000 --- a/content/world/canon/elves.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "body": "The elven travellers of the road \u2014 no single polity, but the people whose passage through the White Antlers, and its recent absence, the town notices.", - "id": "faction.elves", - "related": [], - "type": "faction" -} diff --git a/content/world/canon/mayor-oswin-crell.json b/content/world/canon/mayor-oswin-crell.json deleted file mode 100644 index 530383f..0000000 --- a/content/world/canon/mayor-oswin-crell.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "body": "Mayor of Duncarrow for fifteen years. Warm, unhurried, remembers names and the names of your dead. Runs a clean council and a clean set of books. Widely liked. The visible locked door of this town: pleasant to every player at every disposition, and revealing of nothing.", - "id": "person.mayor-oswin-crell", - "related": [ - "town.duncarrow" - ], - "type": "person" -} diff --git a/content/world/canon/the-tallow-reach.json b/content/world/canon/the-tallow-reach.json deleted file mode 100644 index cde71d6..0000000 --- a/content/world/canon/the-tallow-reach.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "body": "The Tallow Reach \u2014 the lowland march of grain towns and wool roads that Duncarrow sits at the edge of, feeding the pass trade.", - "id": "region.the-tallow-reach", - "related": [], - "type": "region" -} diff --git a/content/world/canon/the-white-antlers.json b/content/world/canon/the-white-antlers.json deleted file mode 100644 index 9195fe6..0000000 --- a/content/world/canon/the-white-antlers.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "body": "An old elven shrine a half-hour's walk north of Duncarrow, in the birch stand off the pass road. Weathered antler-carvings, a dry basin, nothing worth stealing. Elves on the road have historically stopped here. Locals know it as a curiosity and a good spot to water horses.", - "id": "place.the-white-antlers", - "related": [ - "town.duncarrow", - "faction.elves" - ], - "type": "place" -} diff --git a/content/world/npcs/harn-blackwood.json b/content/world/npcs/harn-blackwood.json deleted file mode 100644 index 7fe1ce9..0000000 --- a/content/world/npcs/harn-blackwood.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "id": "npc.harn-blackwood", - "knows": [ - { - "fact_id": "rumor.travelers-go-missing", - "gate": "warm" - }, - { - "fact_id": "fact.harn-daughter-left", - "gate": "warm" - } - ], - "related": [ - "town.duncarrow" - ], - "start_disposition": "neutral", - "type": "person" -} diff --git a/content/world/npcs/mayor-oswin-crell.json b/content/world/npcs/mayor-oswin-crell.json deleted file mode 100644 index f55a8b2..0000000 --- a/content/world/npcs/mayor-oswin-crell.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "id": "npc.mayor-oswin-crell", - "knows": [ - { - "fact_id": "rumor.elves-avoid-the-shrine", - "gate": "cold" - }, - { - "fact_id": "secret.crell-runs-slave-trade", - "gate": "never" - }, - { - "fact_id": "fact.crells-guard-acts-alone", - "gate": "never" - } - ], - "related": [ - "person.mayor-oswin-crell", - "secret.crell-runs-slave-trade" - ], - "start_disposition": "neutral", - "type": "person" -} diff --git a/content/world/npcs/mera-fenn.json b/content/world/npcs/mera-fenn.json deleted file mode 100644 index 4bba56e..0000000 --- a/content/world/npcs/mera-fenn.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "id": "npc.mera-fenn", - "knows": [ - { - "fact_id": "rumor.elves-avoid-the-shrine", - "gate": "neutral" - }, - { - "fact_id": "rumor.travelers-go-missing", - "gate": "warm" - }, - { - "fact_id": "fact.militia-never-investigates", - "gate": "warm" - }, - { - "fact_id": "fact.crells-guard-acts-alone", - "gate": "trusted" - } - ], - "related": [ - "town.duncarrow", - "fact.crells-guard-acts-alone" - ], - "start_disposition": "cold", - "type": "person" -} diff --git a/content/world/topics/crell-runs-slave-trade.json b/content/world/topics/crell-runs-slave-trade.json deleted file mode 100644 index 39648d7..0000000 --- a/content/world/topics/crell-runs-slave-trade.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "id": "secret.crell-runs-slave-trade", - "related": [ - "person.mayor-oswin-crell", - "place.the-white-antlers", - "faction.elves" - ], - "type": "secret" -} diff --git a/content/world/topics/crells-guard-acts-alone.json b/content/world/topics/crells-guard-acts-alone.json deleted file mode 100644 index 78384d1..0000000 --- a/content/world/topics/crells-guard-acts-alone.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "id": "fact.crells-guard-acts-alone", - "related": [ - "person.mayor-oswin-crell", - "fact.militia-never-investigates" - ], - "type": "fact" -} diff --git a/content/world/topics/elves-avoid-the-shrine.json b/content/world/topics/elves-avoid-the-shrine.json deleted file mode 100644 index e42695f..0000000 --- a/content/world/topics/elves-avoid-the-shrine.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "id": "rumor.elves-avoid-the-shrine", - "related": [ - "place.the-white-antlers", - "faction.elves" - ], - "type": "rumor" -} diff --git a/content/world/topics/harn-daughter-left.json b/content/world/topics/harn-daughter-left.json deleted file mode 100644 index 667ba70..0000000 --- a/content/world/topics/harn-daughter-left.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "id": "fact.harn-daughter-left", - "related": [ - "npc.harn-blackwood" - ], - "type": "fact" -} diff --git a/content/world/topics/militia-never-investigates.json b/content/world/topics/militia-never-investigates.json deleted file mode 100644 index d60993a..0000000 --- a/content/world/topics/militia-never-investigates.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "id": "fact.militia-never-investigates", - "related": [ - "town.duncarrow", - "rumor.travelers-go-missing" - ], - "type": "fact" -} diff --git a/content/world/topics/travelers-go-missing.json b/content/world/topics/travelers-go-missing.json deleted file mode 100644 index c9bd06d..0000000 --- a/content/world/topics/travelers-go-missing.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "id": "rumor.travelers-go-missing", - "related": [ - "town.duncarrow", - "place.the-white-antlers" - ], - "type": "rumor" -} diff --git a/tools/content_build/tests/test_duncarrow.py b/tools/content_build/tests/test_duncarrow.py deleted file mode 100644 index ea4cf00..0000000 --- a/tools/content_build/tests/test_duncarrow.py +++ /dev/null @@ -1,37 +0,0 @@ -"""End-to-end: the real promoted Duncarrow bible builds green and routes the -Crell secret correctly (body server-only; the id ships in the gate skeleton).""" - -import json -from pathlib import Path - -from content_build.__main__ import _load_world, check -from content_build.emit import build_trees - -REPO = Path(__file__).resolve().parents[3] -LORE = REPO / "content" / "lore" -WORLD = REPO / "content" / "world" -SERVER = REPO / "content" / "server" - - -def test_duncarrow_builds_and_check_is_clean(): - assert check(LORE, WORLD, SERVER) == 0 - - -def test_secret_body_is_server_only(): - client, server = build_trees(_load_world(LORE)) - assert "topics/crell-runs-slave-trade.json" in server - # the secret's descriptive id ships in the gate skeleton (schema property)... - npc = client["npcs/mayor-oswin-crell.json"] - assert any(k["fact_id"] == "secret.crell-runs-slave-trade" - and k["gate"] == "never" for k in npc["knows"]) - # ...but its BODY never reaches any client artifact - blob = json.dumps(client) - assert "elf-slaving" not in blob and "sells them into slavery" not in blob - - -def test_mera_never_holds_the_secret(): - client, _ = build_trees(_load_world(LORE)) - fenn = client["npcs/mera-fenn.json"] - facts = {k["fact_id"] for k in fenn["knows"]} - assert "secret.crell-runs-slave-trade" not in facts - assert "fact.crells-guard-acts-alone" in facts diff --git a/tools/content_build/tests/test_model.py b/tools/content_build/tests/test_model.py index dfcdaaf..9289f4f 100644 --- a/tools/content_build/tests/test_model.py +++ b/tools/content_build/tests/test_model.py @@ -13,11 +13,11 @@ def _raw(**over) -> RawEntry: def test_namespace_and_slug(): - e = entry_from_raw(_raw(id="npc.mera-fenn", type="person", + e = entry_from_raw(_raw(id="npc.specimen-teague", type="person", start_disposition="cold", knows=[{"fact": "rumor.x", "gate": "warm"}])) assert e.namespace == "npc" - assert e.slug == "mera-fenn" + assert e.slug == "specimen-teague" def test_category_predicates():