Skip to content

Commit 56f4aa8

Browse files
committed
updates: move moments to story level
1 parent c62e0a3 commit 56f4aa8

28 files changed

Lines changed: 1744 additions & 1025 deletions

COPYRIGHT.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,29 @@ diff --git a/insider-threat-ncp.json b/insider-threat-ncp.json
2525
index c4e7f2a..a6b8d3f 100644
2626
--- a/insider-threat-ncp.json
2727
+++ b/insider-threat-ncp.json
28-
@@ -32,6 +32,14 @@
28+
@@ -32,6 +32,22 @@
2929
"moments": [
3030
+ {
3131
+ "id": "fe8a8863-866d-411d-8d2d-8fb30876abfc",
3232
+ "summary": "Alex is urgently summoned by Miriam, whose paranoia about an internal leak is escalating.",
3333
+ "synopsis": "Alex meets Miriam, visibly distressed and accusing her staff of betrayal. Alex remains tight-lipped.",
3434
+ "setting": "Miriam’s private office, late evening.",
3535
+ "timing": "After hours, amid rising company tensions.",
36-
+ "audience_experiential_pov": "third-person limited",
36+
+ "audience_experiential_pov": "third_person_limited",
37+
+ "storybeats": [
38+
+ {
39+
+ "sequence": 0,
40+
+ "narrative_id": "narrative_insider_threat",
41+
+ "storybeat_id": "beat_ceo_confrontation"
42+
+ }
43+
+ ],
44+
+ "storypoints": [
45+
+ {
46+
+ "sequence": 0,
47+
+ "narrative_id": "narrative_insider_threat",
48+
+ "storypoint_id": "storypoint_objective_story_symptom"
49+
+ }
50+
+ ]
3751
+ }
3852
]
3953
```

HISTORY.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22

33
## Recent Schema Updates
44

5-
- 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`.
5+
- Moved canonical Moments to required `story.moments[]` so storytelling units belong to the story and can reference Storybeats and Storypoints across multiple narratives.
6+
- Added narrative-qualified `story.moments[].storybeats[]` and `story.moments[].storypoints[]` references, requiring `narrative_id` on each referenced structural element.
7+
- Removed `narratives[].storytelling.moments[]` so canonical payloads have one unambiguous Moment home.
8+
- 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`.
69
- Added a canonical story settings example and refreshed validation fixtures so canonical Storybeats omit legacy `signpost` keys.
710
- Added optional `subtext.storybeats[].appreciation` as a derived interoperability field based on `throughline + scope + sequence`.
811
- Clarified that Storybeat importers should derive the appreciation identity when the field is omitted so lighter-weight payloads remain compatible.

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ By clearly delineating narrative structure (Subtext) from presentation (Storytel
2424

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

27+
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.
28+
2729
---
2830

2931
### Authorship, AI, and Creative Intent
@@ -67,6 +69,11 @@ Use [/VALIDATION.md](/VALIDATION.md) for validating your own NCP files and CI se
6769
## Templates
6870

6971
- [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.
72+
- [Cross-narrative Moments](/examples/cross-narrative-moments.json): story-level Moment fixture showing one scene referencing Storybeats and Storypoints from two different narratives.
73+
74+
## Integration Notes
75+
76+
- [MovieLabs OMC integration](/docs/omc-integration.md): adapter guidance for using NCP as the authorial-intent layer alongside OMC production-facing narrative entities.
7077

7178
## For Adopters (Self-Serve)
7279

@@ -114,6 +121,7 @@ narrative-context-protocol/
114121
│ │ ├── 04.dynamics.md
115122
│ │ ├── 05.vectors.md
116123
│ │ └── 10.dramatica-translation.md
124+
│ ├── omc-integration.md
117125
│ └── narrative-context-protocol-schema.md
118126
├── tests/
119127
│ └── validate-schema.js

SPECIFICATION.md

Lines changed: 90 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ This clear distinction encourages narrative depth alongside flexibility, allowin
1818
"plot": [],
1919
"genre": []
2020
},
21+
"moments": [],
2122
"narratives": [
2223
{
2324
"id": "narrative_AbnHJ147",
@@ -31,8 +32,7 @@ This clear distinction encourages narrative depth alongside flexibility, allowin
3132
"dynamics": []
3233
},
3334
"storytelling": {
34-
"overviews": [],
35-
"moments": []
35+
"overviews": []
3636
}
3737
}
3838
]
@@ -56,6 +56,7 @@ The highest-level object representing the entire story, containing its metadata
5656
"plot": [],
5757
"genre": []
5858
},
59+
"moments": [],
5960
"narratives": [],
6061
"created_at": "2025-02-05T14:30:00Z"
6162
}
@@ -71,7 +72,7 @@ The highest-level object representing the entire story, containing its metadata
7172
- Each domain is an array of lightweight nodes requiring only `id` and `summary`.
7273
- Nodes remain open/extensible so creators and LLM workflows can attach additional metadata without breaking schema compatibility.
7374

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

7677
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.
7778

@@ -127,6 +128,40 @@ This structure provides both depth (meaning) and flexibility (presentation) with
127128
"story": {
128129
"id": "story_123e4567",
129130
"title": "The Journey Within",
131+
"moments": [
132+
{
133+
"id": "moment_gate_lockdown",
134+
"summary": "The gate locks down.",
135+
"synopsis": "The public evacuation crisis and a private relationship rupture happen in the same audience-facing scene.",
136+
"setting": "The transit gate concourse.",
137+
"timing": "Minutes before the final convoy window closes.",
138+
"imperatives": "Carry both the external evacuation turn and the personal relationship turn.",
139+
"storybeats": [
140+
{
141+
"sequence": 0,
142+
"narrative_id": "narrative_AbnHJ147",
143+
"storybeat_id": "beat_public_crisis"
144+
},
145+
{
146+
"sequence": 1,
147+
"narrative_id": "narrative_MnT90210",
148+
"storybeat_id": "beat_private_rupture"
149+
}
150+
],
151+
"storypoints": [
152+
{
153+
"sequence": 0,
154+
"narrative_id": "narrative_AbnHJ147",
155+
"storypoint_id": "storypoint_public_goal"
156+
},
157+
{
158+
"sequence": 1,
159+
"narrative_id": "narrative_MnT90210",
160+
"storypoint_id": "storypoint_relationship_issue"
161+
}
162+
]
163+
}
164+
],
130165
"narratives": [
131166
{
132167
"id": "narrative_AbnHJ147",
@@ -140,8 +175,7 @@ This structure provides both depth (meaning) and flexibility (presentation) with
140175
"dynamics": []
141176
},
142177
"storytelling": {
143-
"overviews": [],
144-
"moments": []
178+
"overviews": []
145179
}
146180
}
147181
]
@@ -194,7 +228,11 @@ Overviews deliver high-level storytelling components, such as Throughline descri
194228
**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.
195229

196230
## Moments
197-
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.
231+
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.
232+
233+
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.
234+
235+
Canonical payloads should not contain `narratives[].storytelling.moments[]`. Moments have one home: `story.moments[]`.
198236

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

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

424462
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.
425463

464+
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.
465+
426466
```json
427467
"moments": [
428468
{
@@ -438,9 +478,33 @@ Organizational narrative units—such as Acts, Scenes, Sequences, Chapters, and
438478
{ "type": "space", "limit": 10 }
439479
],
440480
"storybeats": [
441-
{ "sequence": 0, "storybeat_id": "beat_123456" },
442-
{ "sequence": 1, "storybeat_id": "beat_789012" },
443-
{ "sequence": 2, "storybeat_id": "beat_345678" }
481+
{
482+
"sequence": 0,
483+
"narrative_id": "narrative_public_crisis",
484+
"storybeat_id": "beat_123456"
485+
},
486+
{
487+
"sequence": 1,
488+
"narrative_id": "narrative_private_reckoning",
489+
"storybeat_id": "beat_789012"
490+
},
491+
{
492+
"sequence": 2,
493+
"narrative_id": "narrative_public_crisis",
494+
"storybeat_id": "beat_345678"
495+
}
496+
],
497+
"storypoints": [
498+
{
499+
"sequence": 0,
500+
"narrative_id": "narrative_public_crisis",
501+
"storypoint_id": "storypoint_public_goal"
502+
},
503+
{
504+
"sequence": 1,
505+
"narrative_id": "narrative_private_reckoning",
506+
"storypoint_id": "storypoint_private_issue"
507+
}
444508
]
445509
},
446510
{
@@ -455,8 +519,23 @@ Organizational narrative units—such as Acts, Scenes, Sequences, Chapters, and
455519
{ "type": "space", "limit": 20 }
456520
],
457521
"storybeats": [
458-
{ "sequence": 0, "storybeat_id": "beat_987654" },
459-
{ "sequence": 1, "storybeat_id": "beat_654321" }
522+
{
523+
"sequence": 0,
524+
"narrative_id": "narrative_public_crisis",
525+
"storybeat_id": "beat_987654"
526+
},
527+
{
528+
"sequence": 1,
529+
"narrative_id": "narrative_public_crisis",
530+
"storybeat_id": "beat_654321"
531+
}
532+
],
533+
"storypoints": [
534+
{
535+
"sequence": 0,
536+
"narrative_id": "narrative_public_crisis",
537+
"storypoint_id": "storypoint_public_revelation"
538+
}
460539
]
461540
}
462541
]

docs/narrative-context-protocol-schema.md

Lines changed: 56 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Use this page when implementing import/export, validation, and cross-tool interc
1212

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

6062
Required `story` fields:
6163

62-
- `id`, `title`, `logline`, `created_at`, `narratives`
64+
- `id`, `title`, `logline`, `created_at`, `moments`, `narratives`
6365

6466
Optional `story` fields:
6567

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

71+
## Story Moments
72+
73+
`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.
74+
75+
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.
76+
77+
Required keys per item:
78+
79+
- `summary`, `synopsis`, `setting`, `timing`, `imperatives`, `storybeats`, `storypoints`
80+
81+
Optional keys:
82+
83+
- `id`, `setting_id`, `act`, `order`, `maximum_steps`, `fabric`, `audience_experiential_pov`
84+
85+
`storybeats` is an ordered list of narrative-qualified Storybeat references:
86+
87+
```json
88+
"storybeats": [
89+
{
90+
"sequence": 0,
91+
"narrative_id": "narrative_evacuation",
92+
"storybeat_id": "beat_evac_signpost_2"
93+
},
94+
{
95+
"sequence": 1,
96+
"narrative_id": "narrative_mentor_student",
97+
"storybeat_id": "beat_mentor_signpost_2"
98+
}
99+
]
100+
```
101+
102+
`storypoints` is an ordered list of narrative-qualified Storypoint references:
103+
104+
```json
105+
"storypoints": [
106+
{
107+
"sequence": 0,
108+
"narrative_id": "narrative_evacuation",
109+
"storypoint_id": "storypoint_evac_goal"
110+
},
111+
{
112+
"sequence": 1,
113+
"narrative_id": "narrative_mentor_student",
114+
"storypoint_id": "storypoint_mentor_issue"
115+
}
116+
]
117+
```
118+
119+
`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.
120+
121+
Canonical payloads should not contain `narratives[].storytelling.moments[]`. Moments have one home: `story.moments[]`.
122+
69123
## Ideation Model (Optional Beginner Layer)
70124

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

278332
## Storytelling Model
279333

280-
`storytelling` contains two required arrays:
334+
`storytelling` contains one required array:
281335

282336
- `overviews`
283-
- `moments`
284337

285338
### Overviews
286339

@@ -298,27 +351,6 @@ IDs are opaque strings. Plain UUIDs are fine; type prefixes are optional.
298351
Canonical exporters should emit those exact Title Case values.
299352
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.
300353

301-
### Moments
302-
303-
Required keys per item:
304-
305-
- `summary`, `synopsis`, `setting`, `timing`, `imperatives`, `storybeats`
306-
307-
Optional keys:
308-
309-
- `id`, `setting_id`, `act`, `order`, `maximum_steps`, `fabric`, `audience_experiential_pov`
310-
311-
`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.
312-
313-
`storybeats` inside a moment is an ordered reference list:
314-
315-
```json
316-
"storybeats": [
317-
{ "sequence": 0, "storybeat_id": "beat_abc123" },
318-
{ "sequence": 1, "storybeat_id": "beat_def456" }
319-
]
320-
```
321-
322354
## Canonical Terminology Sources
323355

324356
Canonical sets are versioned in two places:

0 commit comments

Comments
 (0)