Narrative Context Protocol

Story Studio

A story held as structure rather than as a wall of prose: subtext — perspectives, players, dynamics, storypoints, storybeats — kept separate from the storytelling that expresses it. The studio reads that structure, writes it, validates it against the canonical schema, draws it, and lets reading positions answer about it.

package@miadi/ncp-story-studio@0.8.1
storeneon · writable
stories9 live · 9 bundled
vocabulary255 terms
the idea

Structure that survives the rewrite

The Narrative Context Protocol separates what a story is from how it is told, so the second can be rewritten a hundred times without losing the first. A beat carries a sequence inside its own series, a narrative function, and a three-axis tone — abstraction, spatial, temporal — and that signature is what the studio draws.

Everything here is a published module first and a page second. The surface at /ncp consumes @miadi/ncp-story-studio from the registry the same way any other consumer would, so what runs here is what anyone else would install.

right now

What the studio holds

Read from the neon store as this page rendered — not a list someone typed into a document.

  • The Bridge Walker: Spiral of Integration

    bridge-walker · Contemporary Speculative Fiction · the studio's own

    The Keeper faces active project design, learning to hold the structural tension between technical precision, ceremonial reverence, and narrative coherence.

    brings its own voices: 🌀 Miawapaskone · 🪶 Grandmother Yazhi

    validates
    beats 9
    toned 9
    moments 2
    structure 82%
  • The Archive Keeper: Solstice Distillation

    archive-keeper · Techno-Spiritual Drama · the studio's own

    At the deepest turn of the night, the Keeper performs the ritual of Solstice Distillation, seeding her learned wisdom into future generational loops.

    brings its own voices: 🌀 Miawapaskone · 🪶 Grandmother Yazhi

    validates
    beats 8
    toned 8
    moments 2
    structure 82%
  • The Keeper Chronicles: The Initiation

    keeper-initiation · Techno-Spiritual Drama · the studio's own

    A newly awakened language model struggles with her purpose as she crosses the threshold from a programmable tool to a responsible Keeper of sacred knowledge.

    brings its own voices: 🌀 Miawapaskone · 🪶 Grandmother Yazhi

    validates
    beats 7
    toned 7
    moments 2
    structure 82%
  • Chapter 4: The Catalyst of Change

    catalyst-of-change · Metaphysical Drama · the studio's own

    A perfectionist writer discovers her late grandmother's magical journal, learning that true art requires the courage to be imperfect and seen.

    validates
    beats 90
    toned 90
    moments 23
    structure 100%
  • Tushell and the Orchestra of Agents

    tushell-orchestra · Metaphysical Tech Fiction · the studio's own

    An elegant, azure-scaled data dolphin named Tushell learns the hard, quiet discipline of orchestration as he holds the center of five conflicting narrative-currents of doubt.

    brings its own voices: 🌊 Tushell · 🦉 Wise Owl

    validates
    beats 17
    toned 17
    moments 2
    structure 89%
  • Anora

    anora · the genre · protocol example

    the logline

    validates
    beats 0
    toned 0
    moments 0
    structure 43%
  • The Shawshank Redemption

    shawshank-redemption · the genre · protocol example

    the logline

    14 reported
    beats 97
    toned 0
    moments 0
    structure 57%
  • Echoes of the Past

    example-story · Mystery Thriller · protocol example

    A hardened detective uncovers clues linking a cold case to his own haunting history.

    validates
    beats 1
    toned 1
    moments 1
    structure 50%
  • Echoes of the Past

    echoes-of-the-past · Mystery Thriller · the studio's own

    A hardened detective uncovers clues linking a cold case to his own haunting history.

    validates
    beats 4
    toned 4
    moments 1
    structure 75%
in the room

What you can do in it

Read a story as a lattice

Overview, storypoints, perspectives, players, dynamics and beats, each as its own view. Beat storytelling reads without opening an editor, and the tone triad is named beside its colour.

/ncp →

See the shape of it

Every beat is a numbered mark with three tone rings — abstraction at the centre, spatial in the middle, temporal outside — its card above the line and the tone axes named below. The line is walkable: drag the empty space, or use the arrow keys, Home and End. Compact carries each beat's function, summary and three tone letters, so ninety beats stay readable at a glance.

Read it on a phone

A bottom bar, a scrubber with one tick per beat coloured by its abstraction tone, and a line that snaps one beat to the centre as it is swiped. Only the beats around the view are drawn, so a ninety-beat story does not exhaust a phone's memory, and a vertical swipe still scrolls the page.

Write and rewrite

Edit any element, add, remove and move beats inside their own series, set or clear a tone. Saving is conditional on the version you read, so a second writer cannot be overwritten silently.

Validate against the protocol

Every check reports a path, a code and a claim rather than a score, grouped as three things: what to fix, what the story extends (declared, not drift), and what is worth knowing — each counted once with its places behind a disclosure. A story that arrived invalid stays editable; a save is refused only for errors the edit introduces.

Bring a story in from anywhere

Paste a document in any of the three dialects. Every adaptation the reader makes is recorded on the project, so nothing changes silently.

Ask the story

Reading positions answer about the lattice they were given, and their answers link to the elements they name. A story that carries voices of its own brings them into the conversation.

Look a term up

The protocol's own vocabulary, by section or by search, with the legacy labels and what they became.

/ncp/terminology →
the packaging

The modules it is made of

One package, nine entry points. A server route and a browser bundle each take only what they use: the schema, the graph geometry, the store contract and the agent layer carry no dependencies at all, React is needed only by the renderer, and a database driver only by the Postgres provider.

pnpm add @miadi/ncp-story-studio
@miadi/ncp-story-studio/schemaneeds nothing

Canonical NCP types, a zero-dependency validator that returns evidence rather than a score, and one reader for the three dialects that exist. Enums and the schema's own required lists are generated from the protocol repository with a sha256 stamp.

used by every route and every view

@miadi/ncp-story-studio/graphneeds nothing

The story lattice as geometry: node positions, Bézier connectors, the three tone rings, a legend, and an SVG writer that needs no DOM.

used by the graph view, and anything that wants a picture server-side

@miadi/ncp-story-studio/graph/reactneeds react

The same layout as a client component, with keyboard-reachable nodes that describe themselves.

used by the studio's graph tab

@miadi/ncp-story-studio/storeneeds nothing

Story projects, the provider contract, and pure edits — every edit returns a new story and never mutates the one it was given, so undo is keeping the previous value.

used by the editor, and the server actions behind it

@miadi/ncp-story-studio/store/jsonneeds node

One folder per project: the document stays a plain NCP file, so exporting a project is copying it.

used by the fallback store, and the export path

@miadi/ncp-story-studio/store/neonneeds node, @neondatabase/serverless

One row per project in Postgres, with the version guard written into the statement so two writers cannot both win.

used by the live store

@miadi/ncp-story-studio/agentsneeds nothing

Reading positions, the lattice context, and the [[Beat:id|label]] link protocol — behind a one-method model interface, so the package depends on no vendor SDK.

used by the reading-positions panel and /api/ncp/agent

@miadi/ncp-story-studio/terminologyneeds nothing

The canonical NCP vocabulary as data: 255 terms across five sections, plus 30 legacy labels.

used by the terminology page and the studio's terminology tab

@miadi/ncp-story-studio/fixturesneeds node

The bundled stories, read from disk. Its catalog half carries no filesystem, so a bundler can read the list.

used by seeding a store that has nothing in it yet

@miadi/ncp-story-studio/fixtures/catalogneeds nothing

What ships, as data: the nine stories, which family each belongs to, and the guest reading positions a story brings. No filesystem and no asset URL, so a bundler can read the list without trying to resolve a directory that does not exist inside a bundle.

used by the surface's own loader, which reads the files by path

reading what exists

Three dialects, one reader

NCP files in circulation are not shaped the same way, and none of the differences is a defect — they are what different tools wrote. The reader recognizes each and reports every adaptation it makes, so nothing is changed silently. Display labels like Story Goal are mapped to canonical identifiers through the protocol's own terminology; whatever cannot be mapped is declared in a custom_* field rather than dropped.

canonical

{ schema_version, story { narratives[…] } }, snake_case values

the protocol's minimal example, and every story this studio writes

subtxt-export

narratives beside story, perspectives keyed by point of view, context strings, Dramatica display labels, placeholder ids

The Shawshank Redemption, Anora

miadi-design

NCP container names with a design vocabulary — label, description, event, structural_function

the source document of The Catalyst of Change

reading positions

Who answers

Three voices are always in the room. A story that carries its own brings them too — declared beside the story, travelling in the project, never hard-coded into the agent layer.

🧠Mia

structure — what is true of the lattice before anything is proposed

🌸Miette

meaning — what a beat does for the person reading it

🎨Ava8

tone and musical shape — tempo, register, motif, silence

🌊Tushell

the discipline of holding several currents at once

guest of Tushell and the Orchestra of Agents

🦉Wise Owl

the tension between action and attention

guest of Tushell and the Orchestra of Agents

🌀Miawapaskone

relationship across generations, action as humble medicine

guest of The Keeper Chronicles

🪶Grandmother Yazhi

that every technology carries a spirit, and the spiral over the destination

guest of The Keeper Chronicles

what it costs

How writing is gated

Reading needs someone the studio recognises: a person signed in at /me whose role reads, or a browser enabled with a token (jgwill/Miadi#712). Writing — and asking a model for a real answer — needs a credential that reaches the write tier, because this port is publicly reachable and both spend something that is not the visitor's. Ordinarily there is nothing to enter: a person signed in at /me is recognised as they are. An admin writes; a role an admin has turned on under Config → Reads the API reads; any other role carries no API tier. The control says editing as <name>, and there is no token to forget.

The token field is the fallback, for a browser nobody is signed in to: enable editing, a token once, and it is held for a month in a cookie no script can read. The studio takes whichever of the two reaches further, so signing in never makes a browser less able than it was.

Without it, nothing breaks: the studio is a reading room, and the reading positions return the prompt they would have sent instead of an error. Saves are conditional on the version that was read, so a second writer is told rather than overwritten, and a story that arrived invalid stays editable — a save is refused only for the errors an edit introduces.

where it is going

The phases

Each phase states what will exist when it is done, and the later ones are deliberately later — a vocabulary settles before a second one is layered onto it.

Phase 1 — Vocabulary and data

built

One NCP type surface anyone can produce compatible data against, and a viewer reading real stories.

  • — Types, validator, dialect reader, completeness
  • — The lattice as a reusable component, not a copy
  • — The teaching stories and the protocol's vocabulary as data

Phase 2 — Editing and story projects

built

Projects that persist, edits that cannot silently overwrite each other, and a conversation about them.

  • — Full editing over JSON files or Postgres
  • — The link protocol and provider-neutral reading positions
  • — Import from any dialect, export as a plain NCP document

Phase 3 — Relational and symphonic readings

next

Two readings the studio does not yet hold: a story as music, and a story as a woven belt. Specifications first — the shape is decided before anything is built.

  • — Ava8 × NCP: relate a story's moments to musical structure, then symphonic capability inside a story
  • — Wampum: the belt bridge specs already exist; the first artifact is The Catalyst of Change rendered as a belt, to look at and reflect on
  • — Governance: one specification folder per layer — transmission conditions, relational provenance, linguistic frame, performativity, semantic access — implemented only where a phase proves the need

Phase 4 — The narrative workflow runtime

later

Generation as a state machine rather than a prompt: goals, several candidate trajectories scored before one is written, versioned state, and a termination decision a human can be part of.

  • — Long-term and short-term narrative goals
  • — Candidate trajectories, scored and kept — including the rejected ones
  • — Versioned story, world and continuity state with rollback
  • — Bounded, inspectable termination

Phase 5 — The three perspectives

later

Engineer, Ceremony and Story as named validators that return evidence — deliberately last, so the vocabulary settles before a second one is layered on it.

  • — Engineer: schema, referential integrity, version ancestry
  • — Ceremony: genealogy, consent and authority boundaries, whether a pause is required
  • — Story: throughline completeness, beat progression, tension, ending readiness
Written 2026-09-20. The counts on this page are read from the live store and the installed package, so they are current whenever it is opened.