docs(charter+roadmap): pivot to the tactical CRPG (the POC is answered)
The aliveness POC (M0-M2) is proven, so redefine the project as the tactical CRPG the /mockups describe. Charter: §1 reframed (Code of Conquest / The Margreave), §10 combat = tactical + action-economy but GRIDLESS (tokens are flavor, no positional rules), §15 = button-driven actions + free-text NPC dialogue (Adjudicator reshaped to the optional free-text escape hatch), §16 adopts /mockups as the UI/systems bible, §17 rewritten to the game's scope. Two conflicts flagged not silently decided (§18): damage determinism (§7 vs mock ranges → M5) and class names (§8 vs mock callings → M4). Roadmap: M0-M2 kept as the built engine; M3-M9 re-sequenced around the mock screens (Theme+shell → creation → combat → dialogue → inventory/sheet → world systems → framing/AI-flavor/persistence). Streaming stays shelved; v2 NPC ideas preserved, re-homed to M6. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,40 +2,40 @@
|
||||
|
||||
Source of truth for scope is [`CLAUDE.md`](../CLAUDE.md). This tracks sequencing.
|
||||
|
||||
## POC — the one question (charter §17)
|
||||
## The game — building the tactical CRPG (charter §17)
|
||||
|
||||
> **Does bounded AI dialogue feel alive, or does it feel like a chatbot in a costume?**
|
||||
> **The POC's one question — *does bounded AI dialogue feel alive?* — is answered.** Bounded NPC dialogue, validated moves, and the DM loop are built and live-proven (M0–M2). We are now building the game the mockups describe (§16, `/mockups`): a tactical CRPG across 11 screens.
|
||||
|
||||
Test that before building anything else. ~30 minutes of play.
|
||||
The engine is done and proven. What's left is the **game on top of it** — recreated screen by screen against the mockups' shared visual system, on the canon log / DM–NPC pipeline / bounded-moves / Luck / character-creation model we already built.
|
||||
|
||||
### POC scope
|
||||
### Reconcile as we build (charter §17)
|
||||
|
||||
- One town, **two NPCs** with authored knowledge lists
|
||||
- One dungeon: **three fights, one boss**
|
||||
- **Two companions:** Cadwyn, Brannoc
|
||||
- **Three playable classes:** Sellsword, Assassin, Priest
|
||||
- Luck fully wired: generation, drift, one shrine, one cursed item
|
||||
- Full proxy, full role split, full canon log
|
||||
- Authored fallback text for every AI surface
|
||||
- **Damage determinism** — §7/§10 (deterministic) vs the Combat HUD mock's damage ranges → combat brainstorm (M5).
|
||||
- **Class names** — §8 names vs the mock's callings (same archetypes) → character-creation brainstorm (M4).
|
||||
|
||||
### Out of scope (charter §17)
|
||||
### Out of scope (never / later)
|
||||
|
||||
AI-generated story skeletons · multiplayer (never) · mobile · credits/payments/auth · companions leaving · positional combat · more than three classes.
|
||||
Multiplayer (never) · mobile (later) · AI-generated story skeletons (v2) · credits/payments/auth (retrofit onto the proxy, §4).
|
||||
|
||||
## Sequencing
|
||||
|
||||
Status: ✅ done · ▶ next · ○ planned. Each item is its own spec → plan → implementation cycle.
|
||||
Each carries its **§2 side** (state = code owns it · text = AI owns it · both = it is two systems), what it **depends on**, and the **milestone goal** it advances.
|
||||
|
||||
The milestones are ordered to reach the POC's one question as early as possible, then build the game around a validated answer:
|
||||
M0–M2 built the **engine** (the contract, the client, the server loop, bounded dialogue) and answered the aliveness question. M3+ build the **game** — the CRPG screens/systems of the mockups, sequenced toward a playable vertical slice first, then breadth:
|
||||
|
||||
| Milestone | Goal it proves |
|
||||
| Milestone | Goal it advances |
|
||||
|---|---|
|
||||
| **M0 — Foundations** ✅ | The contract and the client-side engine exist and are trustworthy. |
|
||||
| **M1 — Prove the server loop** ✅ | A real model sits behind `/dm/narrate` and the pipeline is reusable. |
|
||||
| **M2 — Prove aliveness** ✅ | **Does bounded AI dialogue feel alive?** — the whole POC question (§17). Build complete + live-proven; the *feel* is confirmed in playtest. |
|
||||
| **M3 — Make it a game** ◀ *here* | The dialogue lives inside real stakes: a playable ~30-min dungeon slice. |
|
||||
| **M4 — POC ship-readiness** | Every AI surface degrades with a voice, never an error (§13). |
|
||||
| **M2 — Prove aliveness** ✅ | **Does bounded AI dialogue feel alive?** — answered; bounded NPC dialogue + DM loop live-proven. |
|
||||
| **M3 — Visual foundation & shell** ◀ *here* | The `Theme` + the exploration HUD; every screen inherits the look and lives in the shell. |
|
||||
| **M4 — Character creation** | The player enters the world; the proven stat/Luck model gets its UI. |
|
||||
| **M5 — Tactical combat (gridless)** | Real stakes: the Combat HUD turn manager. |
|
||||
| **M6 — Dialogue screen** | The proven NPC free-text loop inside the mock's conversation UI. |
|
||||
| **M7 — Inventory & character sheet** | State the player can see and manage. |
|
||||
| **M8 — World systems** | World-map travel, a shop economy, the quest log. |
|
||||
| **M9 — Framing, AI-flavor & persistence** | Title/pause, save/load, and the Improviser/Banter/Luck-drift roles + fallback sweep. |
|
||||
|
||||
---
|
||||
|
||||
@@ -52,22 +52,44 @@ The milestones are ordered to reach the POC's one question as early as possible,
|
||||
- ✅ **Considering-state + transport timeout** — while a model call is in flight the client rotates authored in-character "the Master considers…" lines (§13 spirit — even *loading* is content; `ConsideringPhrases` + `ConsideringIndicator`, 3.0s cadence) instead of a frozen surface, and `HttpTransport` sets a request timeout (35s, rejects ≤0) so a hung call degrades to the authored fallback instead of spinning forever. Meets §14's anti-freeze *goal* by **reframing** the wait, on the *proven* non-streaming loop, with no new failure surface. **Human-confirmed live** including the degrade path (API down → fallback). Merged to `dev` (`099714d`); 110/110 client tests. *§2: text/UI · goal: the wait is framed (in-character) and bounded (never hangs).*
|
||||
- ~~**Streaming** (§14)~~ — **SHELVED for the POC.** Real token streaming would genuinely *hide* the ~2s call, but it is the POC's largest transport rework (client `HTTPRequest` → poll-based `HTTPClient`) and adds mid-stream error/tag-boundary failure surface not worth the risk. The considering-state above reframes the wait instead and is tested and live. Design kept as a record (`specs/2026-07-10-narrator-streaming-design.md`, banner SHELVED); revive only if playtest proves the wait genuinely hurts. Conscious deviation from §14's "stream everything," recorded per §18.
|
||||
|
||||
### M3 — Make it a game ◀ *here — (the playable ~30-min slice — dungeon first, per the sequencing call)*
|
||||
- ○ **Adjudicator** — `/dm/adjudicate`: free text → a legal action or an in-world rejection, **strict JSON** (§12), small/fast model, the one-retry-with-error-appended path. Unlocks the hybrid input model (§15) the playable slice needs — the "what do you do?" boundary. *§2: both (text = the in-world reason · state = the chosen action) · depends on the pipeline · goal: free-text world actions.*
|
||||
- ○ **Combat** — deterministic, seeded per encounter from save state (§10); positionless turn-based; resource-management as the one interesting axis; Luck influences only crit thresholds + borderline status checks (§7). The dungeon: **three fights, one boss.** Combat flavor text is async, optional Narrator calls (reuses M1). "Ship the boring one" (§10) — mostly state work, low AI risk. *§2: state (flavor text = a thin AI layer on top) · depends on the pipeline for flavor · goal: real stakes.*
|
||||
- ○ **Luck fully wired** — generation exists (Plan B); this adds **drift events** (sleeping in a real bed, a shrine's blessing, killing something praying), **one shrine**, **one cursed item** (e.g. +STR / −LCK). Visible only in prose, never as a number (§7). Gates the Improviser. *§2: state · depends on the item + event systems · goal: the signature system, live.*
|
||||
- ○ **Improviser** — `/dm/improvise`: minor off-script events, **§7-sandboxed by construction** — output passes a validator that can only apply a whitelisted set of state changes (dignity, never progress; structurally incapable of ending a quest). Fires on Luck; hooks Cadwyn. *§2: both (text = the event · state = the whitelisted change) · depends on Luck being wired · goal: bad luck as a story, not a fine.*
|
||||
- ○ **Banter** — `/party/banter`: companions comment on recent events; low stakes, high charm, **aggressively cacheable**; reads Brannoc's humiliation log (§9), stacking not overwriting. Prose only, no tags. The cheapest role, landed last. *§2: text · depends on the humiliation log (Plan B) + events to comment on · goal: the comedy loop closes.*
|
||||
Each screen is recreated as a Godot 4.7 Control-node scene against the mockups (§16); each `.dc.html`'s `Component` class is the behavior spec. Sequenced toward a playable vertical slice (shell → creation → combat → dialogue) first, then breadth.
|
||||
|
||||
### M4 — POC ship-readiness
|
||||
- ○ **Authored fallback text — full sweep** — every AI-dependent surface has authored fallback *content* (§13), written as writing, not error handling. Each role lands with its own fallback; this is the final pass that guarantees no surface can show the player an error. *§2: text · depends on every surface existing · goal: a degraded DM still has a voice.*
|
||||
### M3 — Visual foundation & shell ◀ *here*
|
||||
- ○ **Shared `Theme`** — palette tokens, the three font families, and reusable styleboxes (parchment card, dark panel, primary CTA, tab, item tile, tag/chip) from the mock README as a Godot `Theme` resource. Every screen pulls from it; build it first so the look is one system. *§2: n/a (presentation) · depends on nothing · goal: one consistent visual identity.*
|
||||
- ○ **Main Window shell (2a)** — the exploration HUD: isometric world-view slot + the permanent DM "narration book" (wired to the proven `/dm/narrate` loop + considering-state), the turn-order rail, minimap slot, the slide-in system dock (Inventory/Character/Quest/Map/Party toggles), and the bottom command bar (HP/MP/gold, consumables, End Turn). The frame everything else lives in. *§2: state (client owns the HUD, consumes DM text) · depends on the DM loop (M2) · goal: the game's main screen, on screen.*
|
||||
- ○ **Title screen** — new game / continue / load / settings; the entry point. *§2: n/a · depends on the Theme · goal: first impression, into the world.*
|
||||
|
||||
### Deferred beyond POC
|
||||
Replicate provider (prod) · auth · metering · credits/payments (§4) — retrofit onto the pipeline later, the game doesn't notice. AI-generated story skeletons (v2 — the seeded story is authored for now).
|
||||
### M4 — Character creation
|
||||
- ○ **Character creation UI** — the mock's screen over our proven model: race + calling cards, six stats with **LCK hidden entirely** (§7), 3d6 floors, the **+3 additive-only spend-up** pool (§8, matches the `character-creation-stats` model), live origin blurb + nameplate. **Reconcile class names** here (§8 vs the mock's callings). Feeds new-game canon-log construction (already built). *§2: state · depends on the creation model (M0) + Theme · goal: build a character.*
|
||||
|
||||
### M5 — Tactical combat (gridless)
|
||||
- ○ **Combat turn manager + HUD** — the Combat HUD `Component` state machine as GDScript: initiative order, the action economy (Action/Bonus/Move), ability resolution, click-to-target, victory/defeat; tokens on the iso board as **flavor only, no movement grid** (§10). Seeded per encounter (§10). **Reconcile damage determinism** here (§7/§10 vs the mock's ranges). Combat flavor is async optional Narrator calls (reuses M1). *§2: state (flavor text a thin AI layer) · depends on the pipeline for flavor · goal: real stakes.*
|
||||
|
||||
### M6 — Dialogue screen
|
||||
- ○ **Dialogue UI + reshaped Adjudicator** — wrap the *proven* NPC free-text loop (`/npc/speak`, M2) in the mock's conversation screen: NPC portrait, live disposition meter, the NPC's spoken line + DM narration beat, and the **hybrid** input (choice chips with skill/approach tags **plus** the free-text line, §15). The **Adjudicator** (`/dm/adjudicate`, strict JSON §12, one-retry) lands here as the interpreter for the free-text "describe your own action" escape hatch — most turns use buttons. *§2: both (text = NPC voice · state = validated moves/actions) · depends on the NPC role (M2) · goal: conversation inside the game's UI.*
|
||||
|
||||
### M7 — Inventory & character sheet
|
||||
- ○ **Inventory & equipment** — the paper-doll (12 slots) + Satchel grid, category tabs, item detail, encumbrance, derived stats; item seed-data from the mock's `items()` map as `Resource`s. *§2: state · depends on the Theme + item model · goal: gear the player manages.*
|
||||
- ○ **Character sheet** — attributes (modifier-forward, LCK still hidden), saving throws, the "in a fight" derived grid, skills, talents, afflictions/conditions, the DM's-notes bio. *§2: state (display) · depends on the stat model · goal: the character, legible.*
|
||||
|
||||
### M8 — World systems
|
||||
- ○ **World-map travel** — region map, location markers (settlement/dungeon/fog), roads + planned route, danger ratings, travel time, set-out. *§2: state · depends on the shell · goal: move between places.*
|
||||
- ○ **Shop economy** — buy/sell with a fence: purses, stock/owned, the ~40%-sell loop, gritty disabled-CTA reasons, merchant reaction lines. *§2: state (merchant reaction = a thin authored/AI layer) · depends on inventory · goal: an economy loop.*
|
||||
- ○ **Quest log** — active/completed/failed tabs, objectives checklists, rewards, tracked quest; reads the canon log's `active_quests` (§11). *§2: state · depends on the quest model · goal: track the story.*
|
||||
|
||||
### M9 — Framing, AI-flavor & persistence
|
||||
- ○ **Save / load + pause / settings** — the pause overlay + data-driven settings; save/load over the canon log + game state (seeds preserved, §10). *§2: state · depends on the systems existing · goal: persistence + framing.*
|
||||
- ○ **Luck fully wired** — generation exists (Plan B); this adds **drift events** (real bed, shrine blessing, killing something praying), **one shrine**, **one cursed item** (+STR / −LCK). Visible only in prose (§7). Gates the Improviser. *§2: state · depends on the item + event systems · goal: the signature system, live.*
|
||||
- ○ **Improviser** — `/dm/improvise`: minor off-script events, **§7-sandboxed by construction** — a validator that only applies whitelisted state changes (dignity, never progress; structurally incapable of ending a quest). Fires on Luck; hooks Cadwyn. *§2: both · depends on Luck being wired · goal: bad luck as a story, not a fine.*
|
||||
- ○ **Banter** — `/party/banter`: companions comment on recent events; low stakes, high charm, **aggressively cacheable**; reads Brannoc's humiliation log (§9), stacking not overwriting. Prose only, no tags. *§2: text · depends on the humiliation log (M0) + events · goal: the comedy loop closes.*
|
||||
- ○ **Authored-fallback sweep** — every AI-dependent surface has authored fallback *content* (§13), written as writing; the final pass so no surface can show the player an error. *§2: text · depends on every surface existing · goal: a degraded DM still has a voice.*
|
||||
|
||||
### Deferred (later / never)
|
||||
Replicate provider (prod) · auth · metering · credits/payments (§4) — retrofit onto the pipeline later, the game doesn't notice. AI-generated story skeletons (v2 — the seeded story is authored for now). Streaming (§14) — SHELVED (`specs/2026-07-10-narrator-streaming-design.md`); the considering-state reframes the wait instead.
|
||||
|
||||
#### NPC & relationship depth (v2)
|
||||
|
||||
Three ideas mined from [NarrativeEngine-P](https://github.com/Sagesheep/NarrativeEngine-P) (MIT) — design borrowed, not code. All three are **§2: state** (code owns them; the AI only voices from what code decides), so they strengthen the §2 boundary rather than loosen it. None is in POC scope (§17); they fold into the NPC role (§6) and canon log (§11) once bounded dialogue is proven alive. Sequence them after M3's Adjudicator, since they enrich the same conversation surface.
|
||||
Three ideas mined from [NarrativeEngine-P](https://github.com/Sagesheep/NarrativeEngine-P) (MIT) — design borrowed, not code. All three are **§2: state** (code owns them; the AI only voices from what code decides), so they strengthen the §2 boundary rather than loosen it. They fold into the NPC role (§6) and canon log (§11); sequence them **with or after the Dialogue screen (M6)**, since they enrich the same conversation surface.
|
||||
|
||||
- ○ **Directional dispositions** — split the single per-pair disposition into two directed fields (A→B and B→A), so liking is asymmetric. Unrequited regard, undisclosed betrayal (player still trusts the captain who already sold them out), and the Cadwyn↔Brannoc mutual-but-differently-flavored dislike (§9) all become expressible. Player→NPC gates dialogue *tone*; NPC→player gates *offered moves* (§6 `available_moves`) — two arrows, two levers. Extends `party[]` in the canon log (§11) and `npc_dispositions` on the client; keep the −100..100 range, just double the field. *§2: state · depends on the disposition model existing (M2, done) · goal: relationships that aren't symmetric.*
|
||||
- ○ **Witness tracking** — every logged event carries a `witnesses: [...]` list; a fact enters an NPC's `knowledge[]` (§6) only if they witnessed it or a witness told them. This is the missing **input-side rule** for the knowledge list — CLAUDE.md §6 says the list is "the entire content the NPC has to draw on" but never says how a fact gets *in*. Structurally prevents the blacksmith spoiling a twist he never saw, gives shady acts real "were you seen?" stakes without a stealth system, and turns rumor spread into a code operation (witness meets NPC → code copies the fact, optionally degraded) rather than AI invention. Adds a field to `recent_events[]`/`established_facts[]` (§11) and a propagation rule on character encounters. *§2: state · depends on the canon log event model (M0, done) + knowledge lists (§6) · goal: NPCs know only what they could plausibly know.*
|
||||
|
||||
Reference in New Issue
Block a user