Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions COPYRIGHT.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,29 @@ diff --git a/insider-threat-ncp.json b/insider-threat-ncp.json
index c4e7f2a..a6b8d3f 100644
--- a/insider-threat-ncp.json
+++ b/insider-threat-ncp.json
@@ -32,6 +32,14 @@
@@ -32,6 +32,22 @@
"moments": [
+ {
+ "id": "fe8a8863-866d-411d-8d2d-8fb30876abfc",
+ "summary": "Alex is urgently summoned by Miriam, whose paranoia about an internal leak is escalating.",
+ "synopsis": "Alex meets Miriam, visibly distressed and accusing her staff of betrayal. Alex remains tight-lipped.",
+ "setting": "Miriam’s private office, late evening.",
+ "timing": "After hours, amid rising company tensions.",
+ "audience_experiential_pov": "third-person limited",
+ "audience_experiential_pov": "third_person_limited",
+ "storybeats": [
+ {
+ "sequence": 0,
+ "narrative_id": "narrative_insider_threat",
+ "storybeat_id": "beat_ceo_confrontation"
+ }
+ ],
+ "storypoints": [
+ {
+ "sequence": 0,
+ "narrative_id": "narrative_insider_threat",
+ "storypoint_id": "storypoint_objective_story_symptom"
+ }
+ ]
+ }
]
```
Expand Down
5 changes: 4 additions & 1 deletion HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

## Recent Schema Updates

- Added optional `story.settings[]` entries for reusable story-level Settings and optional `narratives[].storytelling.moments[].setting_id` references so Moments can point at a shared Setting while preserving free-text `setting`.
- Moved canonical Moments to required `story.moments[]` so storytelling units belong to the story and can reference Storybeats and Storypoints across multiple narratives.
- Added narrative-qualified `story.moments[].storybeats[]` and `story.moments[].storypoints[]` references, requiring `narrative_id` on each referenced structural element.
- Removed `narratives[].storytelling.moments[]` so canonical payloads have one unambiguous Moment home.
- Added optional `story.settings[]` entries for reusable story-level Settings and optional Moment `setting_id` references so Moments can point at a shared Setting while preserving free-text `setting`.
- Added a canonical story settings example and refreshed validation fixtures so canonical Storybeats omit legacy `signpost` keys.
- Added optional `subtext.storybeats[].appreciation` as a derived interoperability field based on `throughline + scope + sequence`.
- Clarified that Storybeat importers should derive the appreciation identity when the field is omitted so lighter-weight payloads remain compatible.
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ By clearly delineating narrative structure (Subtext) from presentation (Storytel

NCP also includes an optional `story.ideation` layer (`character`, `theme`, `plot`, `genre`) so creators can capture early concepts before committing to full storyform structure.

Storytelling Moments live at `story.moments[]` so scenes, chapters, sequences, and levels can reference Storybeats and Storypoints across multiple narratives without duplicating the storytelling unit.

---

### Authorship, AI, and Creative Intent
Expand Down Expand Up @@ -67,6 +69,7 @@ Use [/VALIDATION.md](/VALIDATION.md) for validating your own NCP files and CI se
## Templates

- [Complete Storyform template](/examples/complete-storyform-template.json): blank-slate NCP fixture with canonical Storypoint Appreciations excluding `Event` and `Progression` labels, plus Signpost-only Storybeats (no Progression/Event Storybeats). `narrative_function` is intentionally omitted so teams can fill in only what they need.
- [Cross-narrative Moments](/examples/cross-narrative-moments.json): story-level Moment fixture showing one scene referencing Storybeats and Storypoints from two different narratives.

## For Adopters (Self-Serve)

Expand Down
101 changes: 90 additions & 11 deletions SPECIFICATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ This clear distinction encourages narrative depth alongside flexibility, allowin
"plot": [],
"genre": []
},
"moments": [],
"narratives": [
{
"id": "narrative_AbnHJ147",
Expand All @@ -31,8 +32,7 @@ This clear distinction encourages narrative depth alongside flexibility, allowin
"dynamics": []
},
"storytelling": {
"overviews": [],
"moments": []
"overviews": []
}
}
]
Expand All @@ -56,6 +56,7 @@ The highest-level object representing the entire story, containing its metadata
"plot": [],
"genre": []
},
"moments": [],
"narratives": [],
"created_at": "2025-02-05T14:30:00Z"
}
Expand All @@ -71,7 +72,7 @@ The highest-level object representing the entire story, containing its metadata
- Each domain is an array of lightweight nodes requiring only `id` and `summary`.
- Nodes remain open/extensible so creators and LLM workflows can attach additional metadata without breaking schema compatibility.

This layer informs narratives as projects mature, while keeping strict structural meaning in `narratives[].subtext` and `narratives[].storytelling`.
This layer informs narratives as projects mature, while keeping strict structural meaning in `narratives[].subtext`, `narratives[].storytelling`, and story-level `story.moments[]`.

For open-source adopters, this creates a shared on-ramp: communities can exchange early creative concepts in a common format without forcing immediate commitment to full Dramatica Storyform structure, while still preserving interoperability with canonical narrative objects.

Expand Down Expand Up @@ -127,6 +128,40 @@ This structure provides both depth (meaning) and flexibility (presentation) with
"story": {
"id": "story_123e4567",
"title": "The Journey Within",
"moments": [
{
"id": "moment_gate_lockdown",
"summary": "The gate locks down.",
"synopsis": "The public evacuation crisis and a private relationship rupture happen in the same audience-facing scene.",
"setting": "The transit gate concourse.",
"timing": "Minutes before the final convoy window closes.",
"imperatives": "Carry both the external evacuation turn and the personal relationship turn.",
"storybeats": [
{
"sequence": 0,
"narrative_id": "narrative_AbnHJ147",
"storybeat_id": "beat_public_crisis"
},
{
"sequence": 1,
"narrative_id": "narrative_MnT90210",
"storybeat_id": "beat_private_rupture"
}
],
"storypoints": [
{
"sequence": 0,
"narrative_id": "narrative_AbnHJ147",
"storypoint_id": "storypoint_public_goal"
},
{
"sequence": 1,
"narrative_id": "narrative_MnT90210",
"storypoint_id": "storypoint_relationship_issue"
}
]
}
],
"narratives": [
{
"id": "narrative_AbnHJ147",
Expand All @@ -140,8 +175,7 @@ This structure provides both depth (meaning) and flexibility (presentation) with
"dynamics": []
},
"storytelling": {
"overviews": [],
"moments": []
"overviews": []
}
}
]
Expand Down Expand Up @@ -194,7 +228,11 @@ Overviews deliver high-level storytelling components, such as Throughline descri
**Why?** Overviews help authors clearly communicate their narrative's essential themes and structural direction, ensuring audiences can effortlessly follow and deeply connect with the story.

## Moments
Moments organize storytelling into narrative units like acts, scenes, chapters, or sequences. Each Moment includes a concise synopsis and structured references linking to associated Storybeats, providing clear narrative structure and aiding audience comprehension and engagement.
Moments organize storytelling into narrative units like acts, scenes, chapters, sequences, or levels. Canonical Moments live on `story.moments[]`, not inside a single narrative, because a storytelling unit belongs to the audience-facing story and can carry material from more than one narrative at the same time. A scene can turn the public Objective Story, illustrate a private Relationship Story issue, and echo a Main Character Storypoint without becoming three separate scenes.

Each story-level Moment includes a concise synopsis and narrative-qualified references to associated Storybeats and Storypoints. The `narrative_id` on each reference preserves which formal narrative owns the structural element while allowing the Moment to gather them into one storytelling unit.

Canonical payloads should not contain `narratives[].storytelling.moments[]`. Moments have one home: `story.moments[]`.

**Why?** Structuring storytelling through Moments ensures narratives are approachable and engaging, helping audiences intuitively grasp story progression and emotional dynamics.

Expand Down Expand Up @@ -423,6 +461,8 @@ Surface-level narrative elements that quickly orient the audience, such as Logli

Organizational narrative units—such as Acts, Scenes, Sequences, Chapters, and Levels—that help structure the narrative temporally. These units can vary in scale and can be flexibly defined to organize narrative flow in any specific context.

Canonical Moments live directly on `story.moments[]`. This makes them story-level storytelling units: they can reference Storybeats and Storypoints from any narrative in the story instead of being trapped inside one narrative's `storytelling` object.

```json
"moments": [
{
Expand All @@ -438,9 +478,33 @@ Organizational narrative units—such as Acts, Scenes, Sequences, Chapters, and
{ "type": "space", "limit": 10 }
],
"storybeats": [
{ "sequence": 0, "storybeat_id": "beat_123456" },
{ "sequence": 1, "storybeat_id": "beat_789012" },
{ "sequence": 2, "storybeat_id": "beat_345678" }
{
"sequence": 0,
"narrative_id": "narrative_public_crisis",
"storybeat_id": "beat_123456"
},
{
"sequence": 1,
"narrative_id": "narrative_private_reckoning",
"storybeat_id": "beat_789012"
},
{
"sequence": 2,
"narrative_id": "narrative_public_crisis",
"storybeat_id": "beat_345678"
}
],
"storypoints": [
{
"sequence": 0,
"narrative_id": "narrative_public_crisis",
"storypoint_id": "storypoint_public_goal"
},
{
"sequence": 1,
"narrative_id": "narrative_private_reckoning",
"storypoint_id": "storypoint_private_issue"
}
]
},
{
Expand All @@ -455,8 +519,23 @@ Organizational narrative units—such as Acts, Scenes, Sequences, Chapters, and
{ "type": "space", "limit": 20 }
],
"storybeats": [
{ "sequence": 0, "storybeat_id": "beat_987654" },
{ "sequence": 1, "storybeat_id": "beat_654321" }
{
"sequence": 0,
"narrative_id": "narrative_public_crisis",
"storybeat_id": "beat_987654"
},
{
"sequence": 1,
"narrative_id": "narrative_public_crisis",
"storybeat_id": "beat_654321"
}
],
"storypoints": [
{
"sequence": 0,
"narrative_id": "narrative_public_crisis",
"storypoint_id": "storypoint_public_revelation"
}
]
}
]
Expand Down
80 changes: 56 additions & 24 deletions docs/narrative-context-protocol-schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Use this page when implementing import/export, validation, and cross-tool interc

- A shared envelope for transporting narrative context (`schema_version` + `story`).
- A consistent separation of `subtext` and `storytelling` per narrative.
- Canonical story-level `moments` that can reference Storybeats and Storypoints across narratives.
- Closed canonical narrative shapes, so extra keys are rejected unless a shape explicitly allows extensions.
- Canonical enums for `appreciation`, `narrative_function`, `dynamic`, and `vector`.
- Optional custom mapping fields that preserve canonical meaning.
Expand Down Expand Up @@ -47,6 +48,7 @@ Legacy exports are not part of canonical validation.
"plot": [],
"genre": []
},
"moments": [],
"narratives": []
}
}
Expand All @@ -59,13 +61,65 @@ Required top-level fields:

Required `story` fields:

- `id`, `title`, `logline`, `created_at`, `narratives`
- `id`, `title`, `logline`, `created_at`, `moments`, `narratives`

Optional `story` fields:

- `genre` (concise story label)
- `ideation` (pre-narrative beginner/exploratory concept threads)

## Story Moments

`story.moments[]` is the canonical home for audience-facing storytelling units such as scenes, acts, chapters, sequences, or levels. Moments belong to the story because storytelling units often carry structural material from more than one formal narrative.

For example, one scene might advance a public evacuation narrative while also turning a mentor-student relationship narrative. Keeping that scene in `story.moments[]` lets the Moment reference both narratives without duplicating the scene or forcing one narrative to own it.

Required keys per item:

- `summary`, `synopsis`, `setting`, `timing`, `imperatives`, `storybeats`, `storypoints`

Optional keys:

- `id`, `setting_id`, `act`, `order`, `maximum_steps`, `fabric`, `audience_experiential_pov`

`storybeats` is an ordered list of narrative-qualified Storybeat references:

```json
"storybeats": [
{
"sequence": 0,
"narrative_id": "narrative_evacuation",
"storybeat_id": "beat_evac_signpost_2"
},
{
"sequence": 1,
"narrative_id": "narrative_mentor_student",
"storybeat_id": "beat_mentor_signpost_2"
}
]
```

`storypoints` is an ordered list of narrative-qualified Storypoint references:

```json
"storypoints": [
{
"sequence": 0,
"narrative_id": "narrative_evacuation",
"storypoint_id": "storypoint_evac_goal"
},
{
"sequence": 1,
"narrative_id": "narrative_mentor_student",
"storypoint_id": "storypoint_mentor_issue"
}
]
```

`setting` remains the Moment-specific free-text description. `setting_id` may reference a `story.settings[]` entry when the Moment occurs in a reusable story-level setting.

Canonical payloads should not contain `narratives[].storytelling.moments[]`. Moments have one home: `story.moments[]`.

## Ideation Model (Optional Beginner Layer)

`story.ideation` is optional. If present, it must contain all four arrays:
Expand Down Expand Up @@ -277,10 +331,9 @@ When `appreciation` is present on a Storybeat, it should restate the structural

## Storytelling Model

`storytelling` contains two required arrays:
`storytelling` contains one required array:

- `overviews`
- `moments`

### Overviews

Expand All @@ -298,27 +351,6 @@ IDs are opaque strings. Plain UUIDs are fine; type prefixes are optional.
Canonical exporters should emit those exact Title Case values.
Importers/normalizers may accept legacy inputs such as `logline`, `genre`, `blended_throughlines`, `Premise Overview`, and `Four Throughlines Extraction`, but they should normalize those values before schema validation or export.

### Moments

Required keys per item:

- `summary`, `synopsis`, `setting`, `timing`, `imperatives`, `storybeats`

Optional keys:

- `id`, `setting_id`, `act`, `order`, `maximum_steps`, `fabric`, `audience_experiential_pov`

`setting` remains the Moment-specific free-text description. `setting_id` may reference a `story.settings[]` entry when the Moment occurs in a reusable story-level setting.

`storybeats` inside a moment is an ordered reference list:

```json
"storybeats": [
{ "sequence": 0, "storybeat_id": "beat_abc123" },
{ "sequence": 1, "storybeat_id": "beat_def456" }
]
```

## Canonical Terminology Sources

Canonical sets are versioned in two places:
Expand Down
Loading
Loading