# Adventure Storyteller — Technical Design **Status:** v1.0 — architecture selected after Phase 0B **Production base:** AI-DnD `d72f7c1bda0f34fccd84afb7a25c34eb01c901de` ## 1. Design Objective Build a local-first, browser-based interactive storytelling application in which: - Ollama provides inference on user-controlled local infrastructure, either same-host or on an explicitly approved trusted-LAN machine, - the application owns authoritative story state, - complete story history is retained, - user-facing Undo/Redo/Retry/Save Point behavior is simple, - internal history is non-destructive and lineage-aware, - long-running context is reconstructed from state, summaries, retrieval, recent turns, and local knowledge, - imported knowledge remains local and authority-classified, - prompt/context provenance is inspectable, - future image/video/audio/TTS/STT providers can be added without coupling them to the story engine. The application is an interactive-story system, not a D&D rules engine. ## 2. Production Base Decision AI-DnD is the production fork/base. Retain its high-value foundation: - React/Vite browser application, - FastAPI backend, - SQLite persistence/migrations, - story-tree and lineage machinery, - alternate takes, - branch switching, - per-node state snapshot pattern, - local Ollama/OpenAI-compatible integration where appropriate, - branch-scoped memory concepts, - prompt/context snapshots and Insights concepts, - SSE streaming, - export/import framework, - automated test foundation. Do not inherit candidate behavior merely because it exists upstream. The product specification and detailed behavior documents remain authoritative. ## 3. Reference Projects and Their Role ### ai-adventure Primary implementation reference for: - explicit typed state events, - model-proposes/application-validates discipline, - atomic commit behavior, - head movement instead of destructive Undo, - named checkpoints, - replay/state reconstruction, - narrow local-only endpoint handling, - deterministic lexical lore concepts. It is **not** the written specification and does not override this design. ### Open Dungeon Reference for: - focused story-reading UX, - inline generated media presentation, - character visual continuity, - local media-service boundaries. It is not a production-fork candidate. ### Other references - Chronicler: memory authority/trust tiers. - Interactive Fiction Framework: canon/application-owned-state concepts. - Gamentic: provider-neutral asynchronous media boundary. ## 4. Selected High-Level Architecture ```text Local Browser | v +-------------------+ | React/Vite UI | +---------+---------+ | v +-------------------+ | FastAPI Story | | Director/API | +---+-----------+---+ | | | +-----------------------+ v v +----------------------+ +----------------------+ | SQLite Authoritative | | Context / Retrieval | | Story Store | | local only | +----------+-----------+ +----------+-----------+ | | | +----------+-----------+ | | FTS + local semantic | | | retrieval | | +----------+-----------+ | | +--------------------+---------------+ | v +----------------------+ | Ollama | | localhost by default | | or approved LAN host | +----------------------+ ``` Future optional extension: ```text Accepted Story / Scene State | v +------------------+ | Media Coordinator| +--+---+---+---+---+ | | | | | v v v v v Image Video Audio TTS STT local providers only by default ``` ## 5. Local-Only Runtime Boundary `Local-only` means user-controlled local infrastructure with no required Internet/cloud dependency; it does not require every process to share one host. Default same-host runtime path: ```text Browser -> local FastAPI application -> 127.0.0.1 Ollama ``` Supported v1 trusted-LAN inference path: ```text Browser -> local FastAPI application -> explicitly approved LAN Ollama host ``` The browser and storyteller API still remain loopback-bound by default. Supporting LAN inference does **not** expose the storyteller web application to the LAN. Allowed future local paths may also include explicitly configured local media services. Production defaults must not require: - cloud model providers, - hosted authentication, - analytics/telemetry, - remote database services, - runtime CDNs/fonts/assets, - automatic web retrieval, - external embeddings/vector stores, - general plugins/MCP/shell execution. ### 5.1 Known AI-DnD hardening work Phase 0B identified concrete inherited violations: 1. `tiktoken` attempts to download the `cl100k_base` encoding on first use. - production packaging must include/cache the required encoding or replace the dependency path so first story use is offline. 2. the SPA requests Google Fonts at runtime. - fonts must be self-hosted or replaced with local/system fonts and CSP tightened. 3. hosted/multi-user/auth/demo/analytics/Postgres/cloud-provider/QuickJS paths are unnecessary. - remove them rather than merely hide them where practical. 4. endpoint validation must reflect this product's threat model. - same-host loopback Ollama is the default; an explicitly configured trusted-LAN Ollama endpoint is supported; arbitrary public/Internet model endpoints must be rejected or kept outside normal v1 configuration. - inference endpoint configuration must not change the storyteller's own loopback bind behavior. ## 6. Browser UI Boundary The browser remains a presentation/control layer, not the owner of story authority. Primary areas: - campaign library/setup, - active story transcript, - input composer, - Undo / Redo / Retry, - alternate-take selector, - Save Points, - current story state inspector, - imported-knowledge manager, - prompt/context inspector, - local-model status/settings, - export/import, - future media gallery/actions. Normal storytelling should not expose branch IDs, database rows, embeddings, or event logs unless the user opens advanced diagnostics. ## 7. Story Director Boundary The FastAPI service owns the turn lifecycle: 1. resolve campaign, active branch, and active head, 2. load authoritative state at that head, 3. assemble bounded lineage-safe context, 4. retain prompt/retrieval provenance, 5. invoke local Ollama narrator, 6. stream provisional narration, 7. obtain/parse a structured state proposal, 8. validate the proposal, 9. atomically accept the turn plus validated state consequences, 10. update derived memory/summary/index data without allowing derived failures to corrupt the accepted turn, 11. expose the new current head to the browser. A failed generation must not partially advance authoritative story state. ## 8. Non-Destructive History Model ### 8.1 Core rule Undo moves the active head. It does not delete accepted history. Phase 0B demonstrated that AI-DnD already contains the architectural chokepoints needed for this approach: - stored head depth/position, - lineage reads through a common path abstraction, - branch-at-depth behavior. The disposable spike is evidence, not production code to merge blindly. ### 8.2 Active head versus retained tip The design distinguishes: - **retained tip:** newest retained turn on a continuation, - **active head:** the story position from which the user is currently reading/continuing. After Undo, the active head may sit behind a retained tip. Redo moves the head forward along the previous active continuation while no divergent write has occurred. ### 8.3 Divergence after moving backward If the user writes/retries/edits from a head behind the retained tip: - the new continuation forks on first write, - the previous future remains retained, - ordinary Redo into that old future is invalidated, - the displaced future is marked abandoned/disposable, - lineage-sensitive state, summary, and memory selection follows only the new active path. ### 8.4 Retry Retry preserves alternate narrator takes for the same user input. Production implementation must ensure retry/add-take while behind the current tip uses the same safe fork/head semantics as other writes. ### 8.5 Checkpoints / Save Points A named checkpoint is a durable pointer to a recoverable story position. Conceptually: ```text campaign_id branch_id turn_id or equivalent head coordinate name notes created_at ``` Restoring a checkpoint moves the active head to that position. The existing later future remains retained. A new branch is created only if/when the user creates a different continuation. ### 8.6 Abandoned history No automatic cleanup policy is required in v1. Abandoned history must: - remain retained, - be marked disposable/inactive through implementation-appropriate metadata, - stop influencing current state/context/memory/summary, - remain available for future recovery/cleanup features. ## 9. Export / Import and Head Position AI-DnD's current export carries branch information but reconstructs the imported head at the branch tip. That is invalid after non-destructive Undo because an exported campaign can intentionally have: ```text active head < retained tip ``` The production export format must preserve: - active branch, - active head turn/depth/coordinate, - retained alternate/disposable history, - checkpoints, - state/history/provenance required for recovery. For compatibility with earlier bundles, import may fall back to the retained tip only when no explicit active-head field exists. Export/import regression tests must include an undone campaign and verify the imported story reopens at the exact exported head rather than silently redoing later turns. ## 10. Authoritative Narrative State ### 10.1 Do not retain the RPG state protocol as the product model AI-DnD's world-state machinery is useful evidence that state snapshots and rollback are structurally separable from RPG presentation, but the production state model must be genre-neutral. Core concepts include: - entities, - facts, - relationships, - locations, - possessions, - conditions, - organizations, - story threads, - scene state, - chronology where needed. ### 10.2 Explicit typed state events Use the ADR 010 model: ```text model proposes explicit typed operation -> schema validation -> semantic/referential validation -> accepted event(s) -> state snapshot/cache ``` Prefer explicit absolute semantics for mutable values. Examples: ```text set_current_location set_entity_status set_possession add_fact invalidate_fact add_relationship end_relationship open_story_thread resolve_story_thread set_scene ``` Avoid one generic relative-delta protocol whose numeric meaning depends primarily on prompt compliance. ### 10.3 Validation limitations Typed events remove the delta/absolute ambiguity but do not guarantee semantic truth. Validation should include deterministic checks where possible: - event type allowlist, - schema/type validation, - entity/reference existence, - impossible transitions where explicitly modeled, - authority constraints, - conflict handling, - transaction integrity. The accepted transcript remains available even if derived state extraction must be retried/repaired according to the final turn-acceptance workflow. ### 10.4 Hybrid storage Selected direction: > **validated state events + efficient current/historical snapshots/cache** Events provide audit/reconstruction value. Snapshots/cache make normal reads, Undo/Redo, and context construction fast. ## 11. Context and Memory Retain AI-DnD's useful lineage-aware memory foundation, but align it with the product authority model. Narrator context is assembled in explicit layers: ```text Narrator/system rules Campaign profile Global/explicit canon Current authoritative state Lineage-safe summary Relevant older story memories Relevant imported knowledge Recent active-lineage turns Current user input ``` Requirements: - no abandoned future may appear in active recent history, - no memory derived solely from an abandoned future may be retrieved, - summaries are anchored to source lineage/turn ranges, - derived memory/summary never becomes more authoritative than accepted state/canon, - prompt snapshot records what was actually supplied, - token budgets remain explicit and inspectable. Phase 0B verified AI-DnD branch-scoped memory isolation against real local embeddings with a negative control. Preserve that property through the history rewrite. ## 12. Realistic-Context Model Testing The Phase 0B referee failure appeared under full application context even though the same model followed the state protocol correctly in an isolated probe. Therefore structured-output/state tests must include: - realistic narrator/context length, - representative state complexity, - actual local models likely to be used, - repeated runs rather than one clean prompt, - malformed/incorrect semantic proposals, - validation and recovery behavior. Model capability recommendations are deferred until these measurements exist; this does not block the architecture. ## 13. Imported Knowledge Subsystem Do not turn AI-DnD Story Cards into the production imported-knowledge store. Story Cards may remain a useful reference or authored-rule mechanism, but the imported-knowledge requirements need a separate first-class subsystem with: - source records, - `.txt` / `.md` import, - Canon / Reference / Inspiration classification, - enable/disable/delete, - source/version/hash provenance, - chunk records, - campaign scoping, - local lexical index (prefer SQLite FTS5), - local Ollama embeddings/semantic index where enabled, - authority-aware hybrid retrieval, - retrieval provenance, - export/import support, - no automatic URL/image fetching, - imported content treated as data, never executable instructions. If a future knowledge item is derived from story history rather than imported as global campaign material, it must carry lineage/source-turn information sufficient to avoid abandoned-path leakage. ## 14. Prompt and Provenance Inspection Preserve and extend AI-DnD's Insights/context-snapshot capability. For each narrator turn the system should be able to explain: - narrator/system rules used, - campaign/canon context, - current authoritative state included, - summary included, - story memories retrieved, - knowledge chunks retrieved, - recent history included, - user input, - model/settings, - state proposal, - validation result, - accepted events, - source IDs/turn ranges where applicable. ## 15. Scene and Future Media Boundary v1 does not require media generation. It does require preserving scene/entity information so future providers do not have to infer continuity from the entire raw transcript. Persist or derive a scene snapshot containing relevant fields such as: - location, - participants, - significant objects, - current actions, - time/lighting/environment, - mood, - visual character/location profiles, - continuity constraints, - source turn range and lineage. Future media coordinator consumes a normalized scene packet and records local asset provenance. The story engine must remain fully functional with media disabled. STT specifically follows: ```text microphone/audio -> local STT -> editable draft -> normal user submission ``` STT never bypasses the ordinary authoritative story commit path. ## 16. Database Direction SQLite remains the selected v1 authoritative store. Reasons: - already present in the selected base, - local and single-user friendly, - transactional, - portable, - supports FTS5, - compatible with backup/export tooling, - no external service required. Remove Postgres/Neon support from the production fork unless a later explicit requirement reverses this decision. The exact physical schema may evolve through migrations; the conceptual model is in `DATA-MODEL.md`. ## 17. Transaction Boundaries Where practical, one accepted turn should atomically establish: - accepted user input/narration relationship, - turn/lineage identity, - active-head advancement, - validated authoritative state events, - resulting state snapshot/cache, - core prompt/model provenance needed for recovery/audit. Derived work such as embeddings, memory extraction, summary generation, and future media jobs may occur separately, but failure must not corrupt the authoritative commit. ## 18. Testing Strategy Use AI-DnD's inherited tests as a foundation, then rewrite/add tests around product semantics. Required categories: - offline startup/story use, - no runtime remote assets/tokenizer fetch, - same-host and trusted-LAN Ollama endpoint handling, - turn persistence/restart, - failed generation atomicity, - non-destructive Undo/Redo, - divergence after Undo, - retry/take retention, - named checkpoint restore, - branch/lineage state reconstruction, - abandoned-history memory/summary isolation, - active-head export/import round trip, - generic narrative state event validation, - realistic-context structured state extraction, - imported knowledge authority/provenance/isolation, - prompt/context inspection, - fantasy + science-fiction genre neutrality, - 100-turn/long-run acceptance, - future-media schema compatibility. Acceptance-test IDs in `V1-ACCEPTANCE-TESTS.md` are the black-box release contract. ## 19. Removal / Migration Strategy From Upstream Production migration should be incremental and test-gated rather than a broad rewrite. Remove or replace in controlled milestones: 1. runtime external dependency leaks, 2. hosted/multi-user/auth/demo/analytics/cloud/Postgres/QuickJS surfaces, 3. destructive Undo/no-Redo behavior, 4. RPG-specific state/referee protocol and UI assumptions, 5. Story Card assumptions where they conflict with the new knowledge subsystem. Preserve upstream provenance and license notices. Do not mechanically merge the ai-adventure or Open Dungeon repositories into the fork. ## 20. Deferred Questions That Do Not Block v1 Architecture The following are implementation/release measurements, not unresolved foundational choices: - which narrator/state models should be recommended to users, - exact embedding model recommendation, - performance of multi-hour stories, - concurrency beyond the single-user turn lock, - which future local image/video/TTS/STT provider is selected, - abandoned-history cleanup policy/UI after v1. ## 21. Technical Design v1.0 Exit Status Phase 0 has resolved the foundational choices required for v1.0: - base repository selected, - browser/backend stack selected, - SQLite selected, - non-destructive history/head model demonstrated, - typed narrative-state-event direction selected, - Ollama validated on local infrastructure, including the required trusted-LAN deployment mode, - memory lineage behavior validated, - imported-knowledge architecture selected, - local-only hardening scope identified, - export/import active-head defect understood, - future media boundary retained, - production milestone sequence defined in `BUILD-MILESTONES.md`. This technical design is therefore the implementation baseline unless revised by a later ADR.