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
2 changes: 2 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## 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`.
- 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.
- Clarified that canonical Storybeat objects do not expose a `signpost` key; any internal grouping should be derived from structural scope, sequence, and parent relationships.
Expand Down
17 changes: 17 additions & 0 deletions SPECIFICATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,22 @@ For open-source adopters, this creates a shared on-ramp: communities can exchang
```


## Story Settings

NCP supports optional reusable story-level Settings for places or environments that recur across Moments. `story.settings[]` defines the shared setting once, while each Moment keeps its own free-text `setting` and may optionally reference the shared entry with `setting_id`.

This avoids repeating the same place details across multiple Moments without making every producer model setting identity. Producers that only need free-text Moment settings can omit `story.settings[]` and `setting_id`.

```json
"settings": [
{
"id": "setting_precinct_archive",
"name": "Precinct Archive",
"description": "A dimly lit archive room where old case files preserve institutional memory."
}
]
```

## Narrative: Structuring Subtext & Storytelling

A single story may contain one or more narratives (e.g., _The Empire Strikes Back_ has the Luke/Yoda Storyform and the Han/Leia Storyform, _Barbie_ has the Barbie/Ken Storyform and the Barbie/Gloria Storyform). Most stories, however, exhibit a single central narrative (e.g., _Anora_, _Anatomy of a Fall_, etc.).
Expand Down Expand Up @@ -414,6 +430,7 @@ Organizational narrative units—such as Acts, Scenes, Sequences, Chapters, and
"summary": "Infiltrating the neon-lit heart of a dystopian metropolis, Alex plunges into a shadowy realm teeming with digital outlaws.",
"synopsis": "Freshly arrived in the neon chaos of Neo-Tokyo, Alex is swiftly ensnared in a perilous game played by cyber-criminals, underground syndicates, and relentless AI-driven enforcers.",
"setting": "The pulsating streets of Neo-Tokyo, where holographic ads blend with the shadowy back alleys controlled by syndicate bosses.",
"setting_id": "setting_neo_tokyo_streets",
"timing": "Late night, just hours after Alex's first unsettling discovery upon arriving in the city.",
"imperatives": "- Establish the dark, chaotic atmosphere of Neo-Tokyo\n- Introduce key threats: cyber-criminals and AI enforcers\n- Show Alex's initial vulnerabilities and resourcefulness",
"audience_experiential_pov": "third_person_limited",
Expand Down
20 changes: 19 additions & 1 deletion docs/narrative-context-protocol-schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,22 @@ Quick heuristic:
- If it is an event chain or conflict progression, put it in `plot`.
- If it is a framing/experience contract with the audience, put it in `genre`.

## Story Settings

`story.settings[]` is an optional story-level glossary for reusable places or environments. Each setting requires an `id` and `name`, with an optional `description`. Moments may keep their local free-text `setting` prose while also pointing at a shared setting with `setting_id`.

Use this when multiple Moments occur in the same place and producers want a stable reference instead of repeating or string-matching setting descriptions.

```json
"settings": [
{
"id": "setting_precinct_archive",
"name": "Precinct Archive",
"description": "A dimly lit archive room where old case files preserve institutional memory."
}
]
```

## Narrative Layers

Each item in `story.narratives[]` is a Dramatica storyform: a single, complete argument structure within the story, expressed through `subtext` and `storytelling` layers.
Expand Down Expand Up @@ -290,7 +306,9 @@ Required keys per item:

Optional keys:

- `id`, `act`, `order`, `maximum_steps`, `fabric`, `audience_experiential_pov`
- `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:

Expand Down
2 changes: 0 additions & 2 deletions examples/anora.json
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,6 @@
"id": "beat_anora_signpost_1",
"scope": "signpost",
"sequence": 1,
"signpost": 1,
"throughline": "Main Character",
"narrative_function": "Present",
"summary": "Ani experiences the immediate thrill and danger of rapid escalation.",
Expand All @@ -184,7 +183,6 @@
"id": "beat_anora_progression_3",
"scope": "progression",
"sequence": 3,
"signpost": 1,
"throughline": "Objective Story",
"narrative_function": "Learning",
"summary": "The family applies escalating leverage to force compliance.",
Expand Down
16 changes: 0 additions & 16 deletions examples/complete-storyform-template.json
Original file line number Diff line number Diff line change
Expand Up @@ -1191,7 +1191,6 @@
"id": "beat_objective_story_signpost_1",
"scope": "signpost",
"sequence": 1,
"signpost": 1,
"throughline": "Objective Story",
"summary": "",
"storytelling": "",
Expand All @@ -1205,7 +1204,6 @@
"id": "beat_objective_story_signpost_2",
"scope": "signpost",
"sequence": 2,
"signpost": 2,
"throughline": "Objective Story",
"summary": "",
"storytelling": "",
Expand All @@ -1219,7 +1217,6 @@
"id": "beat_objective_story_signpost_3",
"scope": "signpost",
"sequence": 3,
"signpost": 3,
"throughline": "Objective Story",
"summary": "",
"storytelling": "",
Expand All @@ -1233,7 +1230,6 @@
"id": "beat_objective_story_signpost_4",
"scope": "signpost",
"sequence": 4,
"signpost": 4,
"throughline": "Objective Story",
"summary": "",
"storytelling": "",
Expand All @@ -1247,7 +1243,6 @@
"id": "beat_main_character_signpost_1",
"scope": "signpost",
"sequence": 1,
"signpost": 1,
"throughline": "Main Character",
"summary": "",
"storytelling": "",
Expand All @@ -1261,7 +1256,6 @@
"id": "beat_main_character_signpost_2",
"scope": "signpost",
"sequence": 2,
"signpost": 2,
"throughline": "Main Character",
"summary": "",
"storytelling": "",
Expand All @@ -1275,7 +1269,6 @@
"id": "beat_main_character_signpost_3",
"scope": "signpost",
"sequence": 3,
"signpost": 3,
"throughline": "Main Character",
"summary": "",
"storytelling": "",
Expand All @@ -1289,7 +1282,6 @@
"id": "beat_main_character_signpost_4",
"scope": "signpost",
"sequence": 4,
"signpost": 4,
"throughline": "Main Character",
"summary": "",
"storytelling": "",
Expand All @@ -1303,7 +1295,6 @@
"id": "beat_influence_character_signpost_1",
"scope": "signpost",
"sequence": 1,
"signpost": 1,
"throughline": "Influence Character",
"summary": "",
"storytelling": "",
Expand All @@ -1317,7 +1308,6 @@
"id": "beat_influence_character_signpost_2",
"scope": "signpost",
"sequence": 2,
"signpost": 2,
"throughline": "Influence Character",
"summary": "",
"storytelling": "",
Expand All @@ -1331,7 +1321,6 @@
"id": "beat_influence_character_signpost_3",
"scope": "signpost",
"sequence": 3,
"signpost": 3,
"throughline": "Influence Character",
"summary": "",
"storytelling": "",
Expand All @@ -1345,7 +1334,6 @@
"id": "beat_influence_character_signpost_4",
"scope": "signpost",
"sequence": 4,
"signpost": 4,
"throughline": "Influence Character",
"summary": "",
"storytelling": "",
Expand All @@ -1359,7 +1347,6 @@
"id": "beat_relationship_story_signpost_1",
"scope": "signpost",
"sequence": 1,
"signpost": 1,
"throughline": "Relationship Story",
"summary": "",
"storytelling": "",
Expand All @@ -1373,7 +1360,6 @@
"id": "beat_relationship_story_signpost_2",
"scope": "signpost",
"sequence": 2,
"signpost": 2,
"throughline": "Relationship Story",
"summary": "",
"storytelling": "",
Expand All @@ -1387,7 +1373,6 @@
"id": "beat_relationship_story_signpost_3",
"scope": "signpost",
"sequence": 3,
"signpost": 3,
"throughline": "Relationship Story",
"summary": "",
"storytelling": "",
Expand All @@ -1401,7 +1386,6 @@
"id": "beat_relationship_story_signpost_4",
"scope": "signpost",
"sequence": 4,
"signpost": 4,
"throughline": "Relationship Story",
"summary": "",
"storytelling": "",
Expand Down
9 changes: 8 additions & 1 deletion examples/example-story.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@
"genre": "Mystery Thriller",
"logline": "A hardened detective uncovers clues linking a cold case to his own haunting history.",
"created_at": "2025-12-01T12:34:56Z",
"settings": [
{
"id": "setting_precinct_archive",
"name": "Precinct Archive",
"description": "A dimly lit archive room where old case files preserve institutional memory and unresolved history."
}
],
"ideation": {
"character": [
{
Expand Down Expand Up @@ -112,7 +119,6 @@
"id": "beat_001",
"scope": "signpost",
"sequence": 2,
"signpost": 2,
"throughline": "Main Character",
"narrative_function": "Preconscious",
"summary": "A moment where the past resurfaces, influencing his current investigation.",
Expand Down Expand Up @@ -149,6 +155,7 @@
"summary": "The inciting discovery",
"synopsis": "John uncovers an old case file that hints at deeper connections to his own past.",
"setting": "A dimly lit precinct archive room.",
"setting_id": "setting_precinct_archive",
"timing": "Late night, after hours.",
"imperatives": "Investigate the link before the evidence disappears.",
"storybeats": [
Expand Down
44 changes: 44 additions & 0 deletions examples/story-settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"schema_version": "1.3.0",
"story": {
"id": "story_settings_demo",
"title": "Shared Settings Demo",
"logline": "A detective returns to the same archive twice and discovers that the room itself carries meaning.",
"created_at": "2026-05-12T20:10:00Z",
"settings": [
{
"id": "setting_precinct_archive",
"name": "Precinct Archive",
"description": "A dim archive room where unresolved cases gather institutional dust."
}
],
"narratives": [
{
"id": "narrative_settings_demo",
"title": "Central Narrative",
"subtext": {
"perspectives": [],
"players": [],
"dynamics": [],
"storypoints": [],
"storybeats": []
},
"storytelling": {
"overviews": [],
"moments": [
{
"id": "moment_archive_return",
"summary": "The detective returns to the archive.",
"synopsis": "A second visit to the archive reframes the old evidence as a personal warning.",
"setting": "The same archive room, now colder and less familiar.",
"setting_id": "setting_precinct_archive",
"timing": "After midnight.",
"imperatives": "Show that the shared place has taken on new meaning.",
"storybeats": []
}
]
}
}
]
}
}
1 change: 1 addition & 0 deletions examples/storypoint-throughline-both-refs.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"narratives": [
{
"id": "narrative_storypoint_throughline_with_perspective",
"title": "Throughline Perspective Narrative",
"subtext": {
"perspectives": [
{
Expand Down
1 change: 1 addition & 0 deletions examples/storypoint-throughline-empty-perspectives.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"narratives": [
{
"id": "narrative_storypoint_throughline_empty_perspectives",
"title": "Throughline Placeholder Narrative",
"subtext": {
"perspectives": [],
"players": [],
Expand Down
2 changes: 0 additions & 2 deletions examples/the-shawshank-redemption.json
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,6 @@
"id": "beat_shawshank_signpost_1",
"scope": "signpost",
"sequence": 1,
"signpost": 1,
"throughline": "Objective Story",
"narrative_function": "Past",
"summary": "Past convictions and institutional history define present constraints.",
Expand All @@ -194,7 +193,6 @@
"id": "beat_shawshank_progression_6",
"scope": "progression",
"sequence": 6,
"signpost": 2,
"throughline": "Relationship Story",
"narrative_function": "Trust",
"summary": "Red and Andy move from caution toward mutual commitment.",
Expand Down
Loading
Loading