# Adventure Storyteller Planning Package **Status:** Phase 0 complete; architecture selected; **Milestones M1 and M2 implemented and accepted (2026-09-02)**. **Production coding:** Underway, milestone by milestone. M1 and M2 are done; M3 is the next milestone to brief. This package contains the current product requirements, final Phase 0 architecture decisions, detailed subsystem designs, acceptance tests, research evidence, and the production milestone plan for the local-only interactive-story project. ## Current Decision Phase 0A static research and Phase 0B local validation are complete. The production starting point is: > **Fork AI-DnD at upstream commit `d72f7c1bda0f34fccd84afb7a25c34eb01c901de`.** The selection is based on measured Phase 0B behavior, not feature count. AI-DnD already contains the highest-value structural machinery: browser UI, FastAPI service boundary, SQLite persistence, parent-linked story history, alternate takes, branch-aware state snapshots, local Ollama operation, branch-scoped memory, prompt/context inspection, streaming, export/import, and a substantial automated test suite. The selected composition of ideas is: ```text AI-DnD production base + ai-adventure state/event/commit/checkpoint/privacy patterns + Open Dungeon story-reading and future-media UX patterns + Chronicler memory-authority concepts + Interactive Fiction Framework canon/validation concepts + Gamentic provider-neutral media concepts ``` This is **not** a repository merge. AI-DnD is the ownership center. Other projects are implementation references only unless a later milestone explicitly reimplements a compatible idea. ## Phase 0B Findings That Changed the Plan Phase 0B confirmed the fork choice while correcting several Phase 0A assumptions: - AI-DnD's shipped Undo was destructive and had no Redo. - A disposable spike proved non-destructive head-cursor Undo/Redo in three backend files while preserving branch-scoped memory isolation. - A new continuation written after Undo can fork from the moved-back head while retaining the abandoned future. - AI-DnD's current relative-delta world-state protocol can produce semantically wrong state under realistic context even when the proposal is syntactically valid. - Production narrative state will therefore use explicit typed events/absolute assignments inspired by ai-adventure rather than AI-DnD's relative-delta protocol. - AI-DnD requires offline hardening: `tiktoken` attempts a first-use CDN fetch and the SPA requests Google Fonts at runtime. - AI-DnD's export format must preserve the active head position; otherwise export/import can silently redo an undone story. - AI-DnD Story Cards are not a sufficient imported-knowledge store because they are not designed for the required classification, provenance, chunking, and lineage semantics. - Open Dungeon remains useful for UX/media ideas but is no longer a serious production-fork candidate. - ai-adventure is not the production base but is the strongest implementation reference for authoritative typed state events, head movement, checkpoints, replay, and narrow local-only behavior. See `PHASE-0B-RECOMMENDATION.md` for the coding agent's evidence. That report is retained as research evidence; the planning documents in this package record the decisions made after reviewing it. ## Document Authority Use the documents in this order when requirements appear to conflict: 1. `SPECIFICATION.md` — product requirements and required behavior. 2. Detailed behavior/design documents: - `STORY-BRANCH-SEMANTICS.md` - `CONTEXT-AND-MEMORY.md` - `IMPORTED-KNOWLEDGE-DESIGN.md` - `SECURITY-THREAT-MODEL.md` - `MEDIA-EXTENSION-CONTRACT.md` - `BROWSER-UX-SPEC.md` - `DATA-MODEL.md` 3. `V1-ACCEPTANCE-TESTS.md` — observable pass/fail contract. 4. `TECHNICAL-DESIGN.md` — selected implementation architecture. 5. Foundational ADRs (`001-...md` through the current ADR set). 6. `BUILD-MILESTONES.md` — implementation sequence; it does not override product behavior. 7. Phase 0 research reports — evidence and historical findings. Candidate repositories and research reports are **not** specifications. In particular, ai-adventure is an implementation reference for selected patterns; its behavior does not override this package. ## Foundational Decisions The following are settled for v1: - browser-first UI, - local-only runtime across user-controlled local infrastructure, - Ollama inference with same-host loopback as default and explicitly configured trusted-LAN inference supported, - single-user deployment, - AI-DnD production base at the pinned Phase 0B commit, - application-owned authoritative state, - complete retained transcript/history, - simple user-facing Undo/Redo/Retry/Save Point semantics, - non-destructive head-cursor history internally, - new write after moving backward creates a new continuation while retaining the old future, - abandoned history is retained and marked disposable; **no automatic cleanup is required in v1**, - named checkpoints remain until explicitly deleted, - genre-agnostic core state, - explicit typed narrative-state events/absolute assignments rather than ambiguous relative deltas, - hybrid state model: validated events plus state snapshots/cache, - branch/lineage-safe summaries and memories, - imported knowledge is a separate first-class subsystem rather than an extension of AI-DnD Story Cards, - knowledge classes: Canon / Reference / Inspiration, - local lexical retrieval plus local semantic retrieval where practical, - prompt/context provenance and inspection, - export/import must preserve active branch **and active head position**, including an undone position, - no cloud/Internet inference, telemetry, automatic web retrieval, remote runtime assets, shell/MCP/general plugin execution, - LAN inference is distinct from LAN exposure of the storyteller UI/API; the latter is not required for v1, - future local image/video/audio/TTS/STT support remains optional and decoupled from the story engine. ## Phase 0 Status ### Complete - candidate discovery and triage, - static architecture/privacy/licensing review, - local clone/build/test validation, - real Ollama testing, - offline/network observation, - AI-DnD strip-down/entanglement checks, - Open Dungeon history-retrofit analysis, - ai-adventure Ollama/service-boundary checks, - AI-DnD non-destructive Undo/Redo spike, - referee/state-protocol follow-up, - export/import head-position follow-up, - Story Card lineage review, - Postgres removability review, - production fork decision, - production architecture decision. ### Deferred to implementation/release validation These do not block the architecture decision: - comparative recommendation of narrator/state models for real users, - multi-hour/100-turn long-run behavior, - detailed concurrency behavior beyond the single-user turn lock, - actual future image/video/TTS/STT provider integration, - abandoned-history cleanup UI/policy (not required in v1). ## Recommended Reading Order for the Next Implementation Stage Do not convert this into a coding prompt until the package review is approved. When implementation planning resumes, read: 1. `SPECIFICATION.md` 2. `TECHNICAL-DESIGN.md` 3. `BUILD-MILESTONES.md` 4. `STORY-BRANCH-SEMANTICS.md` 5. `DATA-MODEL.md` 6. `CONTEXT-AND-MEMORY.md` 7. `IMPORTED-KNOWLEDGE-DESIGN.md` 8. `SECURITY-THREAT-MODEL.md` 9. `BROWSER-UX-SPEC.md` 10. `V1-ACCEPTANCE-TESTS.md` 11. ADRs, especially the production-base and narrative-state-event decisions 12. Phase 0B reports only as supporting evidence ## Workflow From Here ```text Phase 0 research and spikes COMPLETE | v Architecture/fork decision COMPLETE | v Planning package revision COMPLETE | v Approve planning package COMPLETE | v Milestone M1 COMPLETE (2026-09-02) fork + offline baseline see planning/reports/M1-*.md | v Milestone M2 COMPLETE (2026-09-02) local-only surface + endpoint see planning/reports/M2-*.md policy | v Milestone M3 NEXT — brief not yet prepared non-destructive undo/redo | v Implement and review milestone-by-milestone ``` ## Stop Rule **One milestone at a time. Do not begin a milestone before its brief exists.** M1 and M2 are complete and accepted; the evidence is in `reports/M1-*.md` and `reports/M2-*.md`. **No M3 brief has been prepared.** The current action is to write one, informed by the post-M2 corrections below and by `reports/M2-IMPLEMENTATION-REPORT.md` §Q, which records that M3's chokepoints were left untouched or simplified by M2 and that the Phase 0B undo/redo spike still applies. ### Post-M2 corrections applied (2026-09-03) M2's review recommended six planning changes and reported rather than applied them. All six are now applied, plus three additions drawn from the same evidence: | Document | Correction | | --- | --- | | `SECURITY-THREAT-MODEL.md` | New §10A records the inference endpoint policy **as implemented** — address allowlist, enforced on save and before every request, TLS never traded against it — with both residual limits stated. §71A item 5 marked resolved; §77 notes the required defaults are now met. | | `TECHNICAL-DESIGN.md` §5.1 | Items 3 and 4 marked done; all five hardening items are now resolved. | | `TECHNICAL-DESIGN.md` §5.2 | New: the M1/M2 production architecture recorded as fact — SQLite, Ollama-only, loopback storyteller, trusted-LAN inference accepted, public endpoints refused. | | `TECHNICAL-DESIGN.md` §18.1 | New wiring rule from the M2 regressions: test a real consumer path when removing a setting, and prove a new setting reaches its component. | | `DECISIONS/011-local-inference-endpoint-policy.md` | **New ADR.** Address-based allowlist over hostname matching, deny by default, checked twice, mandatory TLS — with the `ipaddress`-classification finding as the reason the CIDRs are spelled out. | | `BUILD-MILESTONES.md` M2 | Marked COMPLETE with the capabilities it delivered and the debt it carried forward. | | `BUILD-MILESTONES.md` M5 | Note: eight rollback tests now use the world-state engine as *instrumentation*, not as endorsement; move the instrumentation when M5 replaces the protocol, and rework rather than delete those tests. | | `BUILD-MILESTONES.md` M6 | Note: background memory failure must be observable, at least one real provider-construction path must be tested, and derived-memory failure must not corrupt accepted story state. | | `V1-ACCEPTANCE-TESTS.md` H10 | Strengthened: a wildcard origin must be rejected at startup, and an unknown `/api/...` path must 404 rather than returning the SPA with HTTP 200. | | `V1-ACCEPTANCE-TESTS.md` H12 | **New.** Inference endpoint enforcement, including the defence-in-depth case: a public endpoint written into the database behind the settings API must still be refused at request time. | `SPECIFICATION.md` was deliberately **not** changed. M2 altered no product requirement; it removed capability the specification never asked for. ### Post-M1 corrections applied (2026-09-02) Implementation evidence contradicted or under-specified six places in this package, and a seventh was added on review. All seven are now corrected: | Document | Correction | | --- | --- | | `DECISIONS/002-ollama-only-v1.md` | New section: a trusted-LAN Ollama may be HTTPS with a private CA; verify against the OS trust store; full certificate and hostname checking; no bypass option. | | `DECISIONS/004-local-only-production.md` | New *Testing Consequence*: offline tests need a fresh cache and no route out. Vendored runtime artifacts should be integrity-verifiable. | | `V1-ACCEPTANCE-TESTS.md` A05 | Pass conditions reworded around *accepted* history; explicit note that the user's submitted text is deliberately retained. | | `V1-ACCEPTANCE-TESTS.md` A06 | Now requires a real second machine and an HTTPS endpoint with a locally issued certificate; a plain-HTTP LAN test is no longer sufficient evidence. | | `V1-ACCEPTANCE-TESTS.md` §3 | Record CPU/GPU/RAM: cold model load on a CPU-only host exceeded the inherited 120 s timeout. | | `BUILD-MILESTONES.md` | M1 marked COMPLETE with the capabilities it delivered; M2's endpoint-policy line reframed from inventing trusted-LAN support to narrowing it. | | `TECHNICAL-DESIGN.md` §5 | Runtime boundary restated: the storyteller is loopback-only, inference may be same-host *or* trusted-LAN, and the two are independent. Adds the TLS/private-CA rule. |