Money stops being a flat `coin` and becomes copper, stored as a single
int, formatted only at the display edge.
The approved model (1g = 100s = 10,000c, store everything in copper) said
money should stay an inventory item under one `copper` id. It can't. §6 is
what kills it: `give_item(x)` adds exactly 1 and carries no quantity, and
`gifts_given` is a global one-shot keyed by item id — so a single `copper`
id would be givable once, for one copper, for the whole campaign.
So the purse is one int on GameState, and the three denominations are
content items that exist only to let a bounded move name a unit —
give_item(gold) is +10,000c. Three ids, not three buckets: the
change-making problem never arises because there is only ever one number.
A quantity arg on the move was rejected — it hands the model an unbounded
integer to invent, which is the §2 line.
Currency routes to the purse and never enters `inventory`, so it can't
appear in an inventory grid by construction. No filter needed.
Prices remain content and remain M8.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QYa9u7Kdxv5gX4AnwWexy8
Applies the seven-campaign saga direction spec (021c248) to the docs it
was written to protect. No new milestone, no new content, no BOM line.
docs/roadmap.md — a "Guarded direction" section, and a ⛨ saga note on the
four milestones that would otherwise foreclose the shape:
M3 don't hardcode the title flow so a saga entry path can't be added
M4 keep construct()'s `creation` a plain Dictionary; the scene must not
become its only producer
M5 the level curve is no longer open — L20 across 7 tiers; enemy stat
blocks carry tier; no scaling multiplier, ever
M9 the save is two objects (Saga + Campaign); humiliations move to the
Saga or they die with the campaign
races-and-classes spec — the deferred "XP curve → M5" line now inherits the
ceiling rather than choosing one.
canon-roadmap — what the saga asks of content: a tier field when the
item/quest namespaces land, and a fixed-vs-variable mark on each BOM line
when the BOM is written. Tiers 2-7 and the other six kings go to the
Backlog.
Content build --check green; no generated content touched.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A direction spec: one character, seven campaigns (one per demon king),
one saga — then it ends. The character, companions, deeds and level carry
between campaigns; the world does not.
Deliberately adds no milestone and no BOM line. Its real payload is a set
of guardrails on milestones that are about to be built blank and would
otherwise foreclose the shape:
- M5 owes a level curve — design it to a ceiling of 20 across 7 tiers,
with tiered enemy stat blocks and never a scaling multiplier.
- M9 owes a save format — two objects (Saga + Campaign), not one blob.
Humiliations move to the Saga or they die with the campaign.
- M3/M4 — don't foreclose a saga entry path; don't couple construct() to
the creation scene.
- Build tool — add tier:1..7 when the item/quest namespaces land.
Difficulty is fixed at world-construction time from the campaign index,
never during play. That prohibition is the whole design; a world that
re-levels with the player is a treadmill.
The canon-log contract does not change: party[].disposition,
humiliations[] and established_facts[] already exist, and player still
admits no number. The Saga becomes the source; the canon log a projection
of it. The seam is one optional fourth arg to NewGame.construct().
Greywater at tier 1 under Ghaul is, unintentionally, already campaign 1.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Content (lore, economy, items, quests, map) was untracked and unbounded.
Bound it: a second roadmap (content/roadmap.md) with Spine / Bill of
Materials / Backlog, demand-driven by the milestone that consumes it.
- Vertical slice = one town + one dungeon (adopt + deepen Greywater).
- Ghaul the Yoke is the ledger chain's patron, so the quest chain and
the cosmology are one object, not two.
- Economy splits per §18: the loop is code (M8), the numbers are content.
Currency = 1g/100s/10,000c, copper as the stored atom; lands before M7.
- Build tool needs `item` + `quest` namespaces; locations already exist.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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
Adds the FTH-axis calling mapping to the cosmology spec: Bonesetter
channels the Warden, the Bloodsworn (names the [CANON-TBD] warlock
calling) pacts one of the Seven, Hedge-Mage is a pointed outsider,
martials unaligned. Luck-immunity intent kept as flavor and flagged for
the M5/Improviser reconcile (§7-sensitive), not built here.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HuHRPE7VfppUJEaoGBEUqZ
Establishes the good-god/seven-demon-lords cosmology as the game's
overarching content theme, mapped onto the content schema as canon
entities, with the world-building skill updated to reconcile all future
authoring against it. Duncarrow scaffolding decoupled now, purged in a
follow-up.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HuHRPE7VfppUJEaoGBEUqZ
Lock the NPC identifier: full namespaced id (npc.mera-fenn) is canonical
everywhere — stored data, client dict key, and the /npc/speak wire. The API
load_npc changes from a filename lookup to an id-indexed load (matching the
client's ContentDB), reads persona from content/server, and resolves the
client's reveal-set fact_ids to topic bodies. Legacy Fenn keeps working; no
migration required. First task of the runtime-consumption cycle.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HuHRPE7VfppUJEaoGBEUqZ
Schema lock built bottom-up from the Duncarrow specimen (candidate-town.md):
- disposition rungs as bands over the engine integer (code owns numbers)
- town fact = engine reveal-topic (authoring layer over §6, no new runtime)
- MD bible -> build -> JSON; split by role (game vs server), secrecy as lint
- canon home: content/lore (source) -> content/world + content/server (built)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HuHRPE7VfppUJEaoGBEUqZ
Settles the §17 class-name reconcile (charter §8 vs mock callings) in
favor of the gritty callings, and gives every race trait a concrete rule.
Feeds M4 character creation; combat ability kit deferred to M5.
- Resolution model: deterministic value vs DC, LCK selects the borderline
band (§7) — flat mods, no random d20, no advantage.
- 5 saves (LCK owns none); death saves = LCK.
- Races: features only, no stat mods; Nightsight ruling for darkvision.
- 7 callings (charter-7), 2 names [CANON-TBD]; casters=MP, martials=cooldowns.
- Flags two contract migrations for M4: canon-log gains `race`; deserter
origin's allowed_classes migrates to new calling ids.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Editor-first Title screen from mock: warm atmosphere (GPUParticles embers,
AnimationPlayer glow, palette-uniform shader bg), logo block, keyboard/mouse
menu (New Game -> shell, Quit works, rest inert), footer. Plus a single
/VERSION source of truth read by both the API (startup + /version) and the
client (synced into project.godot config/version, read via ProjectSettings).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The exploration HUD frame: two-panel tabletop split, DM narration book
wired to the proven /dm/narrate loop (prose-only + refire), thin tested
ShellState for HUD readouts, inert system dock + command bar as faithful
placeholder. Pure-core/thin-shim per the house pattern.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
First of three M3 cycles (Theme -> shell 2a -> Title). Palette.gd consts
as the single source of truth; game_theme.tres for flat-bordered UI;
shaders for the three signature surfaces. EB Garamond replaces
proprietary Georgia. Proof is a human-eyeballed showcase harness.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Flip considering-state to done+merged+live-confirmed. Strike the streaming
item — the considering-state reframes the wait and is tested/live; real
streaming's transport rework + mid-stream failure surface isn't worth it for
the POC. Streaming spec retained as a record (banner SHELVED). Includes the
human's folded-in further-down roadmap ideas.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
5 TDD tasks: ConsideringPhrases (pure) + authored considering.json;
ProxyConfig.request_timeout_seconds (default 35s, reject <=0); HttpTransport
applies it (closes the infinite-hang gap); ConsideringIndicator node shim
(Timer rotates a Label); wire both harnesses around the await.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Pivot M2 anti-freeze from streaming to a lighter considering-state: a rotating
in-character 'the Master considers…' indicator (authored content, §13 spirit)
on the proven non-streaming loop, plus the HttpTransport request-timeout fix so
a hung call yields to the fallback instead of spinning forever. Meets §14's
anti-freeze goal by reframing the wait; near-zero new failure surface. Streaming
design PARKED (banner + roadmap ○), revisit if playtest shows the wait hurts.
Conscious §14 deviation recorded per §18.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Real token streaming to hide the ~2s call (§14). Proxy emits its own minimal
NDJSON (delta/done/error); /dm/narrate becomes a 200 stream (422 stays sync,
model errors become an in-stream frame). Client reworks to an HTTPClient
poll-loop StreamTransport behind a testable seam; hold-back tag filter;
keep-partial mid-stream degrade; folds in the HttpTransport timeout fix.
Narrator first; NPC fast-follow.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
M2 core experiment. Server owns persona+knowledge (spoilers/IP, no DB);
client owns live state and computes available_moves. Free text straight
to the NPC prompt (no Adjudicator). Sibling NpcService + pure MoveValidator;
moves validated against state, invalid dropped, prose always kept (§6).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
First M2 vertical slice: CanonLog -> HTTP -> /dm/narrate -> prose ->
screen -> fact-harvest, with a §13 degraded-DM fallback on any failure.
Pure DmService core behind an injectable DmTransport seam (headless-
testable); throwaway harness scene; one authored fallback line under
client/content (renderer owns the file's home).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Plan status → COMPLETE, all 8 tasks/44 steps checked. Roadmap: Narrator pipeline
✅, Client HTTP loop promoted to ▶ next.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The client half of the canon log contract: typed RefCounted model with
invariants-in-the-model, Luck-centric game state, new-game construction
from origin+world+creation, turn-to-turn mutators, and a pure regex tag
extractor. Headless GUT-tested logic layer; UI/HTTP/save-load deferred.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Plan A of two: the JSON Schema contract, authored POC fixtures (deserter
origin + minimal world), and the api's runtime validation of every canon log
(422 on invalid, enforcing the §7 luck boundary). Five TDD tasks, all runnable
with pytest + Docker in-repo. Plan B (GDScript client construction/maintenance)
deferred until we're in Godot.
Plan: docs/superpowers/plans/2026-07-09-canon-log-contract-and-api-validation.md
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Design spec for the §11 canon log, plus origin seeds as thin initial-state
overlays over a single static world. Three layers (world content / origin seed /
runtime canon log), the in/out boundary (numeric Luck never enters the AI
payload, §7), field-level schemas, new-game construction order, turn-to-turn
maintenance, and JSON storage validated on both client and api.
Folds content/npcs and content/quests under content/world/; adds
content/world/{locations,items} and content/origins. fallback/ kept outside
world/ (authored prose, not id-referenced).
Spec: docs/superpowers/specs/2026-07-09-canon-log-schema-design.md
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>