Narrative Engine

Branching story graph engine with interpolation, effects, and traversal. A zero-runtime-dependency TypeScript library unified from three independently identical graph models in Forge, pseudogen, and gw Idea Evolver.

Overview

@ap/narrative-engine is a shared library that abstracts the directed graph model common to multiple Aloysius Productions apps. It provides the core primitives for building branching narratives: nodes, labeled edges (choices), context-driven interpolation, immutable effect processing, and graph traversal utilities.

The library was extracted after discovery that Quest-Forge, gw, and pseudogen had each independently invented the same graph structure. pseudogen had the richest implementation (effects, interpolation, caching) and served as the base. The API surface was generalized — template/templateAlt instead of codeFragment/codeTemplate — to be domain-agnostic: Tavern uses it for RPG dialogue, Forge uses it for interactive coding tutorials, Muse Studio uses it for creative story building.

Status

Phase: Complete (all 8 implementation phases) — staging evaluation Test coverage: >90%, 110 tests passing API stability: All public APIs marked stable Blockers: None — awaiting first consumer integration validation (Forge)

Tech Stack

TechnologyVersionPurpose
TypeScript^5.6.0Language — strict mode, ESM
Vitest^4.0.18Test runner
fast-check^4.xProperty-based testing (dev-only)

Zero runtime dependencies. Same pattern as eliza-engine.

Key Features

  • Story Graphs — Node-based directed graph structures with labeled edges (choices)
  • Interpolation — ${var} template substitution with cache invalidation
  • Effects — Immutable context transforms (safe for undo/redo)
  • Traversal — Cycle detection, unreachable node detection, branch/merge point finding
  • Graph Builder — Typed helpers for assembling nodes, choices, and graphs immutably
  • Session Serialization — Export/restore engine state (toSession() / fromSession())
  • Progress & Achievements — Optional session state for consumer tracking without external persistence
  • Validation & QA Gate — validate(), validateStrict(), analyze(), assertGraphSafe()
  • Telemetry Hooks — Runtime instrumentation callbacks for consumer observability

Consumer Integration Points

AppUse CaseStatus
ForgeInteractive coding tutorialsPlanned
TavernRPG branching narrativesPlanned
Muse StudioCreative story buildingPlanned
ScribeCollaborative storytellingFuture
WorkshopCode scaffolding narrativesFuture

Key Decisions

DecisionRationale
Unified three models into oneQuest-Forge, gw, pseudogen had structurally identical graph models — single API serves all consumers
template/templateAlt namingDomain-agnostic — not all consumers generate code
Zero runtime depsKeep lightweight for embedding; same pattern as eliza-engine
Immutable effect processingContext transforms return new objects — safe for undo/redo
Include graph traversal utilitiesCycle detection and validation needed by all consumers; prevents runtime errors from broken graphs
Add progress/achievement session stateLightweight tracking for consumers without requiring external persistence
Pre-release checklistReproducible release process enforced before publishing

Patterns Established

  • Telemetry hooks — Runtime instrumentation callbacks (consumer observability without coupling)
  • Metadata schema validation — Enforce allowed keys and depth to prevent unsafe drift
  • Graph health reporting — Summarize errors/warnings/cycles/unreachable for CI gates and dashboards
  • QA gate helper — assertGraphSafe() enforces baseline graph safety; useful for CI and editors
  • Property-based tests — Randomized graph checks via fast-check to find edge cases early
  • Consumer integration smoke test — End-to-end API usage verifying the public API contract

Lessons Learned

  • Three apps independently inventing the same graph model validates the abstraction — extract shared models early
  • pseudogen has the richest implementation and is the best source for a unified engine
  • Tavern tests require Web Audio API shims in Node — use jsdom + AudioContext mocks for audio integrations

CI/CD

CheckStatusNotes
CI workflowConfiguredRuns tests, typecheck, and QA gate on PRs
Securitysecurity.ymlHardened with sanitization and validation helpers
Release readinessPre-release checklistValidates version + QA before tagging
Scale testsPassingDetects performance regressions on large graphs

Commands

npm run build      # tsc
npm run test       # vitest run
npm run typecheck  # tsc --noEmit
npm run qa-gate    # tsc && node scripts/qa-gate.mjs

See Also

  • Forge — first planned consumer; interactive coding tutorials
  • Tavern — RPG companion app using narrative-engine for branching campaigns
  • pseudogen — source of the richest graph implementation
  • eliza-engine — sibling zero-deps shared library pattern
  • gw — one of the three source models