docs(roadmap): considering-state done; shelve streaming for the POC
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>
This commit is contained in:
@@ -49,8 +49,8 @@ The milestones are ordered to reach the POC's one question as early as possible,
|
||||
### M2 — Prove aliveness ◀ *(the POC's one question)*
|
||||
- ✅ **Client HTTP loop** — client posts its canon log to `/dm/narrate`, displays the prose, harvests `[FACT]` via its `TagExtractor` into its own log, and shows the degraded-DM authored fallback (§13) on any non-200. First end-to-end vertical slice: **state → HTTP → model → prose → screen → fact-harvest.** Pure `DmService` core behind an injectable transport seam; throwaway harness scene for the first on-screen prose. **Live-proven** against qwen3.5 through Docker (grounded scene prose, no numbers per §7). 67/67 client tests; merged to `dev` (`b949cd2`). Surfaced + fixed two Docker-dev gaps in M1 (prompts not packaged, no container→host-Ollama route) — M1's live proof had been venv-on-host only. *§2: state (client owns the loop, consumes text) · goal: put the Narrator on screen.*
|
||||
- ✅ **Bounded NPC conversation** — `/npc/speak` with server-owned persona + `knowledge[]` (spoilers stay off the client) and client-computed `available_moves[]`; the client validates each emitted move against live state, applies the valid, silently drops the invalid, and always keeps the prose (§6). Server role is a thin drop-in on the M1 pipeline (`npc.run` mirrors `narrate.py`); the client added a pure `MoveValidator` (membership is the whole test) + a `MoveApplier` that writes town-NPC disposition to `GameState.npc_dispositions` (not the party log), plus `NpcContent.available_moves` as the single legality home. Free text goes straight to the NPC prompt (no Adjudicator needed — the moves are the NPC's). **Live-proven** against qwen3.5: Fenn answered in-voice, grounded strictly in his authored knowledge, no Luck leak (§7), with `reveal`/`offer_quest` moves landing. The live smoke also caught two real tag-format drifts a unit test can't — paren-less zero-arg moves and a dropped `MOVE:` prefix leaking into prose — both fixed by making `TagExtractor` tolerant/scrub-safe (backward-compatible; narrator path unaffected). Built on `feature/npc-conversation`; awaiting the human's `--no-ff` merge to `dev` (§18). *§2: both (text = the NPC's voice · state = the validated moves) · goal: answer the one question.*
|
||||
- ▶ **Considering-state + transport timeout** — while a model call is in flight the client shows a rotating in-character "the Master considers…" indicator (authored content, §13 spirit — even *loading* is content) instead of a frozen surface, and the `HttpTransport` request timeout is set so a hung call gives way 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 essentially no new failure surface. *§2: text/UI · depends on the client loop · goal: the wait is framed (in-character) and bounded (never hangs).*
|
||||
- ○ **Streaming** (§14) — **PARKED** (`specs/2026-07-10-narrator-streaming-design.md`). Server streams Ollama → client to genuinely *hide* the ~2s call. Deferred behind the considering-state: it is the POC's largest transport rework (client `HTTPRequest` → poll-based `HTTPClient`) and adds mid-stream error/tag-boundary failure surface — too much risk for "polish, not proof" while the aliveness question is already answered. **Revisit** only if playtesting shows the wait hurts immersion (long responses or a slow prod model). Conscious deviation from §14's "stream everything," recorded here per §18. *§2: text · goal: polish, not proof.*
|
||||
- ✅ **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 *(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.*
|
||||
@@ -64,3 +64,11 @@ The milestones are ordered to reach the POC's one question as early as possible,
|
||||
|
||||
### 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).
|
||||
|
||||
#### 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.
|
||||
|
||||
- ○ **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.*
|
||||
- ○ **Personality Hexagon persona** — a richer NPC persona schema: six axes (Drive, Diligence, Boldness, Warmth, Empathy, Composure) supplied to the NPC prompt (§6) as structured voice-shaping input, replacing free-form persona blurbs. Server-owned (like `knowledge[]`), so it never ships to the client. Purely additive to the §6 prompt contract — it steers *how* an NPC speaks, not *what* it may do (the move vocabulary is unchanged). *§2: state (the schema) feeding text (the voice) · depends on the NPC role (M2, done) · goal: consistent, distinct NPC voices from data, not prose.*
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
# Narrator streaming (M2) — design
|
||||
|
||||
> **STATUS: PARKED (2026-07-10).** Deferred in favour of a lightweight
|
||||
> considering-state (see `2026-07-10-considering-state-design.md`), which meets
|
||||
> §14's anti-freeze *goal* by reframing the wait in-character rather than hiding
|
||||
> it — for a fraction of the risk (this piece is the POC's largest transport
|
||||
> rework and adds mid-stream error/tag-boundary failure surface that a
|
||||
> "polish, not proof" feature shouldn't). Revisit only if playtesting shows the
|
||||
> wait genuinely hurts immersion (long Narrator responses or a slow prod model).
|
||||
> This design stays ready for that moment.
|
||||
> **STATUS: SHELVED for the POC (2026-07-10).** The considering-state
|
||||
> (`2026-07-10-considering-state-design.md`) shipped and is live-confirmed; it
|
||||
> meets §14's anti-freeze *goal* by reframing the wait in-character rather than
|
||||
> hiding it, for a fraction of the risk. Real streaming is the POC's largest
|
||||
> transport rework (client `HTTPRequest` → poll-based `HTTPClient`) and adds
|
||||
> mid-stream error/tag-boundary failure surface judged not worth it. The roadmap
|
||||
> item is struck. This design is retained only as a record — revive it solely if
|
||||
> playtesting proves the wait genuinely hurts immersion (long Narrator responses
|
||||
> or a slow prod model). Not planned work.
|
||||
|
||||
Date: 2026-07-10
|
||||
Milestone: **M2 — prove aliveness** (roadmap). The third M2 item; **polish, not
|
||||
|
||||
Reference in New Issue
Block a user