Skip to content

Commit ec099bd

Browse files
committed
Tighten schema enums and docs
1 parent b9fb13e commit ec099bd

14 files changed

+369
-190
lines changed

HISTORY.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## Recent Schema Updates
44

5+
- Closed the primary canonical narrative shapes so unexpected keys now fail validation unless a shape explicitly supports extension metadata.
6+
- Clarified that Perspective, Player, and Overview IDs are opaque strings. Plain UUIDs are acceptable and type prefixes are optional.
7+
- Canonicalized overview labels to the exact Title Case enum values `Logline`, `Genre`, and `Blended Throughlines`.
8+
- Clarified that import/normalization layers may still accept legacy overview labels such as `logline`, `genre`, `blended_throughlines`, `Premise Overview`, and `Four Throughlines Extraction`, but canonical export/validation now requires the Title Case enum.
59
- Added an optional `story.ideation` object for pre-narrative concept development, with required domains `character`, `theme`, `plot`, and `genre` whenever `ideation` is present.
610
- Added lightweight shared ideation node validation requiring `id` and `summary`, with open metadata for beginner and LLM-assisted workflows.
711
- Added optional `narratives[].status` with canonical values `candidate`, `draft`, and `complete` to represent potential or in-progress narratives without splitting data into separate arrays.

SPECIFICATION.md

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,8 @@ In this section, we'll explore examples of each narrative aspect, offering a bri
262262

263263
Perspectives are where the author positions the source of conflict to communicate the story’s intended meaning, independent of first- or third-person narrative style (those refer to storytelling, not subtext). These Perspectives shape how thematic conflicts are revealed, deepening the story by re-inforcing the author's intended message.
264264

265+
Perspectives are closed authorial POV records. They do not carry character identity, role, or conflict metadata; those belong on Players, Storypoints, and Storybeats.
266+
265267
For example, in _A Christmas Carol_, each of the four ghosts (Marley included) functions thematically as an Influence Character for Scrooge, sequentially handing off their unique perspectives from one ghost to another. While each ghost brings a distinct angle—progress, past, present, and future—their collective thematic role remains consistent: to provoke Scrooge’s transformation. Each ghost provides a unique lens on his life, amplifying narrative resonance by exploring different facets of the same thematic conflict.
266268

267269
Another example can be seen in *Inside Out 2*. Unlike the original *Inside Out*, where Joy alone carries the perspective of the Main Character, the sequel has both Joy and Riley sharing the same thematic perspective of Main Character. They seamlessly pass this viewpoint back and forth, allowing the audience to explore identical thematic issues through two distinct yet interconnected lenses. This shared perspective enriches the narrative by demonstrating how the same thematic conflicts can manifest uniquely in different characters, amplifying emotional resonance.
@@ -271,7 +273,7 @@ The implications for interactive narratives are significant. In interactive stor
271273
```json
272274
"perspectives": [
273275
{
274-
"id": "perspective_ab12cd34",
276+
"id": "123e4567-e89b-12d3-a456-426614174000",
275277
"author_structural_pov": "i",
276278
"summary": "Michael Radford",
277279
"storytelling": "Michael Radford has spent his life convincing himself that control is the key to survival, but every step forward only tightens the noose around him. When his instincts betray him at the worst possible moment, he’s forced to confront the truth—his carefully built defenses aren’t protecting him, they’re suffocating him."
@@ -281,28 +283,21 @@ The implications for interactive narratives are significant. In interactive stor
281283

282284
### Players
283285

284-
Characters whose actions and motivations reveal deeper thematic layers (subtext), moving beyond superficial characterization. Each Player should be linked to one or more relevant Perspectives to maintain narrative coherence.
286+
Players own character identity within the narrative. They carry names, roles, sensory characterization, summaries, and the links to any Perspectives they express in the story.
285287

286288
```json
287289
"players": [
288290
{
289-
"id": "player_def456",
291+
"id": "123e4567-e89b-12d3-a456-426614174001",
290292
"name": "Dr. Michael Hayes",
291-
"role": "the world's leading psychologist",
293+
"role": "Main Character",
292294
"visual": "A distinguished man in his late 50s, with silver-streaked hair and piercing blue eyes. He wears a well-tailored suit but often appears slightly disheveled, as if sleep eludes him.",
293295
"audio": "His voice is calm and measured, carrying the weight of experience but occasionally betraying a hint of hesitation when discussing personal matters.",
294-
"bio": "Dr. Michael Hayes is a renowned psychologist known for his groundbreaking research on trauma and memory. Despite his professional success, he struggles with the ghosts of his past—mistakes he can never take back and patients he couldn’t save. As he delves deeper into the minds of others, he finds himself unable to escape his own unresolved grief.",
295-
"storytelling": "A psychologist haunted by his past.",
296-
"motivations": [
297-
{
298-
"narrative_function": "Avoid",
299-
"illustration": "avoiding confronting past failures",
300-
"storytelling": "In therapy sessions, he changes topics when pressed."
301-
}
302-
],
296+
"summary": "A celebrated trauma specialist whose command over others cannot protect him from unresolved grief.",
297+
"storytelling": "Michael presents authority and polish, but every personal question exposes how fragile that control really is.",
303298
"perspectives": [
304299
{
305-
"perspective_id": "persp_def456"
300+
"perspective_id": "123e4567-e89b-12d3-a456-426614174000"
306301
}
307302
]
308303
}
@@ -324,7 +319,7 @@ Defined structural elements representing spatial aspects of a narrative. They es
324319
"storytelling": "Michael takes charge, justifying his actions as necessary in order to take care of the family.",
325320
"perspectives": [
326321
{
327-
"perspective_id": "persp_def456"
322+
"perspective_id": "123e4567-e89b-12d3-a456-426614174000"
328323
}
329324
]
330325
}
@@ -348,7 +343,7 @@ Temporal elements that demonstrate how the narrative unfolds over time. Each bea
348343
"storytelling": "Michael has spent years outrunning his past, but in an instant, it catches up to him. His patient’s words land like a ghostly echo, dredging up memories he’s tried to bury, his composure cracking under the weight of old wounds. For the first time, he isn’t just remembering—he’s reliving it, trapped in a moment he thought he’d left behind.",
349344
"perspectives": [
350345
{
351-
"perspective_id": "perspective_ab12cd34"
346+
"perspective_id": "123e4567-e89b-12d3-a456-426614174000"
352347
}
353348
]
354349
}
@@ -378,16 +373,22 @@ Surface-level narrative elements that quickly orient the audience, such as Logli
378373
```json
379374
"overviews": [
380375
{
381-
"id": "overview_12345abc",
382-
"label": "logline",
376+
"id": "123e4567-e89b-12d3-a456-426614174010",
377+
"label": "Logline",
383378
"storytelling": "In a neon-lit cyberpunk metropolis, a determined detective races to outsmart a rogue AI before it reshapes humanity's future.",
384379
"summary": "A cyberpunk crime thriller about a rogue AI and the detective trying to stop it."
385380
},
386381
{
387-
"id": "overview_67890def",
388-
"label": "genre_dynamics",
382+
"id": "123e4567-e89b-12d3-a456-426614174011",
383+
"label": "Genre",
389384
"storytelling": "Cyber Noir: Merging shadowy detective intrigue with dystopian futurism to subvert classic crime narratives.",
390385
"summary": "A fusion of cyberpunk and detective noir."
386+
},
387+
{
388+
"id": "123e4567-e89b-12d3-a456-426614174012",
389+
"label": "Blended Throughlines",
390+
"storytelling": "The detective's private guilt, the rogue AI's challenge, the city's institutional corruption, and the unstable alliance between hunter and hunted all converge into one unified audience-facing summary of the argument.",
391+
"summary": "A single overview blending Main Character, Influence Character, Objective Story, and Relationship Story tensions."
391392
}
392393
]
393394
```

docs/narrative-context-protocol-schema.md

Lines changed: 18 additions & 4 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+
- Closed canonical narrative shapes, so extra keys are rejected unless a shape explicitly allows extensions.
1516
- Canonical enums for `appreciation`, `narrative_function`, `dynamic`, and `vector`.
1617
- Optional custom mapping fields that preserve canonical meaning.
1718

@@ -24,7 +25,7 @@ node tests/validate-schema.js
2425

2526
The test runner validates:
2627

27-
- Valid fixtures: `/examples/example-story.json`, `/examples/ideation-beginner.json`, `/examples/anora.json`, `/examples/the-shawshank-redemption.json`
28+
- Valid fixtures: `/examples/example-story.json`, `/examples/ideation-beginner.json`, `/examples/anora.json`, `/examples/the-shawshank-redemption.json`, `/examples/complete-storyform-template.json`
2829
- Invalid fixtures: `/examples/invalid/*.json`
2930

3031
Legacy exports are kept in `/examples/legacy/` for migration reference only.
@@ -137,13 +138,18 @@ Required keys per item:
137138
- `summary`
138139
- `storytelling`
139140

141+
IDs are opaque strings. Plain UUIDs are fine; type prefixes are optional.
142+
Perspectives are closed authorial POV records; do not place role, conflict, or character identity fields here.
143+
140144
### Players
141145

142146
Required keys per item:
143147

144148
- `id`, `name`, `role`, `visual`, `audio`, `summary`, `storytelling`, `perspectives`
145149

146150
`perspectives` must be an array of objects, each with required `perspective_id`.
151+
Player identity belongs here, not on `perspectives`.
152+
IDs are opaque strings. Plain UUIDs are fine; type prefixes are optional.
147153

148154
### Dynamics
149155

@@ -224,9 +230,17 @@ Optional keys:
224230

225231
Required keys per item:
226232

227-
- `label`, `summary`, `storytelling`
233+
- `id`, `label`, `summary`, `storytelling`
234+
235+
IDs are opaque strings. Plain UUIDs are fine; type prefixes are optional.
236+
`label` must be exactly one of:
237+
238+
- `Logline`
239+
- `Genre`
240+
- `Blended Throughlines`
228241

229-
`label` must be normalized snake_case (`^[a-z][a-z0-9_]*$`), e.g. `logline`, `genre_dynamics`.
242+
Canonical exporters should emit those exact Title Case values.
243+
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.
230244

231245
### Moments
232246

@@ -279,7 +293,7 @@ Example (storypoint):
279293
"summary": "A recurring refusal to accept what is in front of them.",
280294
"storytelling": "The protagonist keeps dismissing direct warnings.",
281295
"perspectives": [
282-
{ "perspective_id": "perspective_ab12cd34" }
296+
{ "perspective_id": "123e4567-e89b-12d3-a456-426614174000" }
283297
]
284298
}
285299
```

examples/anora.json

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,25 @@
1313
"subtext": {
1414
"perspectives": [
1515
{
16-
"id": "perspective_anora_mc",
16+
"id": "persp_anora_mc",
1717
"author_structural_pov": "i",
1818
"summary": "Ani",
1919
"storytelling": "Ani fights to preserve dignity and agency while others attempt to define her future."
2020
},
2121
{
22-
"id": "perspective_anora_ic",
22+
"id": "persp_anora_ic",
2323
"author_structural_pov": "you",
2424
"summary": "Igor",
2525
"storytelling": "Igor pressures Ani to accept a pragmatic view of survival inside a coercive system."
2626
},
2727
{
28-
"id": "perspective_anora_os",
28+
"id": "persp_anora_os",
2929
"author_structural_pov": "they",
3030
"summary": "Zakharov family conflict",
3131
"storytelling": "Competing interests collide around money, image, and control of the marriage."
3232
},
3333
{
34-
"id": "perspective_anora_rs",
34+
"id": "persp_anora_rs",
3535
"author_structural_pov": "we",
3636
"summary": "Ani and Igor",
3737
"storytelling": "Their relationship shifts from antagonism to uneasy mutual recognition."
@@ -48,7 +48,7 @@
4848
"storytelling": "Ani resists being reduced to a bargaining chip.",
4949
"perspectives": [
5050
{
51-
"perspective_id": "perspective_anora_mc"
51+
"perspective_id": "persp_anora_mc"
5252
}
5353
]
5454
},
@@ -62,7 +62,7 @@
6262
"storytelling": "Igor challenges Ani's assumptions about freedom and safety.",
6363
"perspectives": [
6464
{
65-
"perspective_id": "perspective_anora_ic"
65+
"perspective_id": "persp_anora_ic"
6666
}
6767
]
6868
}
@@ -93,7 +93,7 @@
9393
"storytelling": "Ani's conflict focuses on tangible autonomy and legal freedom.",
9494
"perspectives": [
9595
{
96-
"perspective_id": "perspective_anora_os"
96+
"perspective_id": "persp_anora_os"
9797
}
9898
]
9999
},
@@ -106,7 +106,7 @@
106106
"storytelling": "Her defensive control tactics escalate pressure and conflict.",
107107
"perspectives": [
108108
{
109-
"perspective_id": "perspective_anora_mc"
109+
"perspective_id": "persp_anora_mc"
110110
}
111111
]
112112
}
@@ -123,7 +123,7 @@
123123
"storytelling": "The marriage appears to offer escape but quickly reveals hidden constraints.",
124124
"perspectives": [
125125
{
126-
"perspective_id": "perspective_anora_mc"
126+
"perspective_id": "persp_anora_mc"
127127
}
128128
]
129129
},
@@ -138,7 +138,7 @@
138138
"storytelling": "Each negotiation reveals deeper asymmetries in power and intent.",
139139
"perspectives": [
140140
{
141-
"perspective_id": "perspective_anora_os"
141+
"perspective_id": "persp_anora_os"
142142
}
143143
]
144144
}
@@ -147,14 +147,14 @@
147147
"storytelling": {
148148
"overviews": [
149149
{
150-
"id": "overview_anora_logline",
151-
"label": "logline",
150+
"id": "over_anora_logline",
151+
"label": "Logline",
152152
"summary": "A fast-moving relationship drama about power, class, and agency.",
153153
"storytelling": "A character-driven narrative where each turning point reframes who has leverage."
154154
},
155155
{
156-
"id": "overview_anora_genre",
157-
"label": "genre_dynamics",
156+
"id": "over_anora_genre",
157+
"label": "Genre",
158158
"summary": "Romantic drama with pressure-cooker social conflict.",
159159
"storytelling": "The tone shifts from impulsive romance to coercive family confrontation."
160160
}

0 commit comments

Comments
 (0)