# Narrative
Reusable branching-story package for Zero: data-defined progression and dialogue, multi-file content authoring, a registered agent toolbox, history inspection, and persistent local/player save slots. Game-specific content lives outside the package.
Version 0.1.0. Stored in this private world. Committing and pushing syncs the work; making the world public is a separate owner-controlled visibility change.
## Start here
Agents: inspect `tools.list().value.story`, then read the requested tool with `describe_tool({tool:"story.condition"})`. Unpushed tools are not yet in the semantic index. Push the world changes and allow indexing; direct registry discovery and calls also work before pushing. The package asset identity is `Narrative.story`; the registered callable toolbox namespace is **`story`**, so calls are `story.create`, `story.condition`, etc., not `Narrative.story.create`.
Read `guides({path:"Narrative.package/authoring"})` or [the authoring guide](authoring.guide/guide.md) for the complete workflow and [the runtime contract](Runtime.module/README.md) for the expression language. The package includes JSON Schemas under `schemas/` for editor association; runtime validation additionally checks references and graph integrity.
## What installs
| Asset | Responsibility |
|---|---|
| `Narrative.Runtime` | Pure state, history, condition evaluation, dialogue graphs and snapshots |
| `Narrative.Projects` | Manifest loading, separate content records, validation and revision-checked edits |
| `Narrative.Sessions` | Named sessions; persistent local/player save/load; previous checkpoint |
| `Narrative.Fingerprint` | SHA-256 definition/content compatibility fingerprints |
| `Narrative.story` toolbox | 24 discoverable tools for authoring, simulation, inspection and persistence |
| `Narrative.authoring` guide | Setup, storage locations, examples and integration requirements |
| `examples/harbor/` | Complete unrelated RPG example split into records |
| `schemas/` and `tests/` | Machine-readable formats and regression suites |
Package-internal imports use `~.` so the implementation does not depend on the host world's name. The only external module dependency is the engine's builtin JSON codec. Runtime storage adapters use documented VFS and player-data APIs.
The old world-level `BranchingStory` module is a compatibility bridge to this package and is not a dependency of it.
## Storage
Authored content: a caller-chosen JSON manifest plus relative record files. Neither its filename nor its directory is hardcoded. Tools return each record's path and the project revision. Updating one condition does not rewrite every conversation.
Live state: an isolated session in memory.
Local save: `/zero/source/local/narrative/<encoded-game-id>/<encoded-slot>.json`. This is per world/user/device, durable, and excluded from published world content.
Player save: `runtime_data.player(runtime_data.localId())`, under `narrative/<encoded-game-id>/<encoded-slot>`. This is per signed-in player and follows the player's replicated store. IDs are UTF-8 bytes encoded as hex to avoid path collisions/traversal. `story.slots` and `story.save` report actual paths.
Player saves are divided into bounded chunks to respect the store's 256 KB per-value limit. Chunks are written and confirmed before replacing the slot pointer. Hash/length are checked on load. A previous checkpoint is retained. Old chunk generations are retired after a later successful commit; failed writes can leave unreachable chunks but do not intentionally advance the slot.
Authored JSON is never used as a player save. Save format 2 contains a compact definition fingerprint and accepted-event journal, not a copy of every authored dialogue line. Exact-compatible legacy format-1 runtime snapshots can still load.
## Scope
This package supplies runtime APIs and agent authoring tools. It does not contain a graphical dialogue editor or a game-specific dialogue HUD. Games report real events, run their minigames, apply pending gameplay effects idempotently, and supply/restore physical checkpoint data alongside the story state.
The save revision check rejects stale writes within the calling workflow; local concurrent saves are serialized by slot. A game must designate one writer per player slot across devices: the underlying store is not a distributed compare-and-swap service.
No campaign content or public installation is implied by these tools. SPITE's data project stays at `/zero/source/narrative/spite-shift/manifest.json`.
## Verification
Execute `tests/runtime.luau` (19 runtime checks) and `tests/integration.luau` (12 package/tool/storage checks) through the engine. Integration tests create uniquely named scratch projects and private save slots, then remove their test saves. They include 120 NPC fate records, 200 quest-stage records, an eight-layer dialogue gate, SHA-256 vectors, previous-checkpoint recovery and a player save larger than one store leaf. The separate SPITE consequence suite contains 15 checks.
These tests do not claim that 120 fully authored NPCs or 200 actual quests exist, and are not a complete campaign performance benchmark.
# story shared helpers
Standard success/failure result envelopes shared by the story tools. Per-tool workflows live in each tool's init.luau; runtime, project and persistence APIs live in the package's separate modules.
# Narrative.Projects
Multi-file story project authoring and assembly. Public methods create, load, get, put, remove, importDefinition and references operate on caller-chosen manifest paths. Mutations require the observed revision and validate before publishing a new manifest. Relative record paths stay inside the project. See the package authoring guide for the schema and examples.
# story — Narrative authoring and progression
Manage multi-file RPG/story definitions, reusable conditions, dialogue option gates, event histories and persistent local/player save slots. Registered tools are `story.<name>`, and the package asset is `Narrative.story`.
- **create**: Create an empty multi-file narrative project at any chosen manifest JSON path; refuses overwrites.
- **list**: List narrative content IDs and source files, without dumping every NPC or conversation.
- **get**: Read one fact, condition, rule or dialogue graph with its editable data and current project revision.
- **put**: Create or replace one data record. Validates the assembled project and rejects stale revisions; value is the section-specific declarative record.
- **remove**: Remove a narrative record only when it has no known structural references and the remaining definition validates.
- **validate**: Assemble every narrative content file, validate conditions and graph links, and report definition identity, record counts and fingerprint.
- **references**: Find authored references to a named fact, set, event, condition or graph; returns record paths for impact review.
- **condition**: Add or update a reusable named condition from a declarative expression (all/any/not, facts, history, membership, comparisons); validates every reference.
- **gate**: Attach a named availability condition to an exact dialogue option at any depth, without rewriting the graph manually.
- **importDefinition**: Split an existing complete definition JSON into records in an empty narrative project, preserving rule order.
- **open**: Open a fresh isolated narrative session from a project manifest; does not overwrite existing sessions or saves.
- **event**: Submit one declared gameplay event to a narrative session, deduplicating its occurrence ID and validating fields.
- **begin**: Begin an authored conversation after checking entry conditions; returns its current presentation token.
- **advance**: Advance one dialogue line using its graph/node/run token. Cannot skip a choice or minigame.
- **choose**: Choose an available dialogue option by stable ID; rejects stale tokens and locked choices.
- **resolve**: Commit an authored minigame outcome to a test session; caller supplies the actual verified outcome and optional performance.
- **abort**: Abort active dialogue without implicitly treating it as a failed romance or granting rewards.
- **inspect**: Inspect current narrative state, pending game effects, eligible endings and a paginated event history.
- **save**: Persist narrative plus caller-supplied physical checkpoint data in a named local-device or current-player slot. Use revision 0 for a new slot.
- **load**: Load a persistent slot into a fresh session, checking content compatibility and returning physical checkpoint data for the game to apply.
- **slots**: List persistent save slots for a project, or inspect one named slot and its previous-checkpoint availability.
- **explain**: Explain why a named condition passes or fails against a live or loaded session, including evaluated operands.
- **close**: Close an isolated in-memory story session; does not remove saves or authored content.
- **ack**: Acknowledge a pending effect only after its gameplay consumer has applied it using the stable effect ID.
Start with the package's Narrative.authoring guide. Use describe_tool for each live signature. Authored data, live test sessions and persistent player saves are separate. Nothing publishes the world.