183 lines
4.0 KiB
JSON
183 lines
4.0 KiB
JSON
{
|
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
"title": "PresentationSnapshot",
|
|
"description": "Player-authorized presentation output committed with a [`StoryNode`].\n\nThe snapshot deliberately contains no runtime facts. Exact relationships,\nhidden checks, NPC knowledge and private inventory remain in `RuntimeState`\nand must pass through the normal `PlayerView` projection boundary.",
|
|
"type": "object",
|
|
"properties": {
|
|
"beats": {
|
|
"type": "array",
|
|
"default": [],
|
|
"items": {
|
|
"$ref": "#/$defs/PresentationBeat"
|
|
}
|
|
},
|
|
"can_continue": {
|
|
"type": "boolean",
|
|
"default": true
|
|
},
|
|
"character": {
|
|
"$ref": "#/$defs/PresentationCharacter",
|
|
"default": {
|
|
"expression": null,
|
|
"id": "",
|
|
"name": "",
|
|
"pose": null
|
|
}
|
|
},
|
|
"scene": {
|
|
"$ref": "#/$defs/PresentationScene",
|
|
"default": {
|
|
"id": "",
|
|
"title": ""
|
|
}
|
|
},
|
|
"suggestions": {
|
|
"type": "array",
|
|
"default": [],
|
|
"items": {
|
|
"$ref": "#/$defs/ActionSuggestion"
|
|
}
|
|
}
|
|
},
|
|
"$defs": {
|
|
"ActionSuggestion": {
|
|
"type": "object",
|
|
"properties": {
|
|
"draft": {
|
|
"type": "string"
|
|
},
|
|
"id": {
|
|
"type": "string"
|
|
},
|
|
"label": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"id",
|
|
"label",
|
|
"draft"
|
|
]
|
|
},
|
|
"BeatKind": {
|
|
"type": "string",
|
|
"enum": [
|
|
"narration",
|
|
"dialogue",
|
|
"action",
|
|
"system"
|
|
]
|
|
},
|
|
"PresentationBeat": {
|
|
"type": "object",
|
|
"properties": {
|
|
"id": {
|
|
"type": "string"
|
|
},
|
|
"kind": {
|
|
"$ref": "#/$defs/BeatKind"
|
|
},
|
|
"speaker": {
|
|
"type": [
|
|
"string",
|
|
"null"
|
|
]
|
|
},
|
|
"text": {
|
|
"type": "string"
|
|
},
|
|
"visual": {
|
|
"anyOf": [
|
|
{
|
|
"$ref": "#/$defs/VisualDirective"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"required": [
|
|
"id",
|
|
"kind",
|
|
"text"
|
|
]
|
|
},
|
|
"PresentationCharacter": {
|
|
"description": "Resolved public visual state for the primary character at a committed node.\n\n`expression` and `pose` are the final values after the node's beats have\nplayed. Persisting the resolved values means restoring a node does not need\nto replay an earlier branch to reconstruct the current portrait.",
|
|
"type": "object",
|
|
"properties": {
|
|
"expression": {
|
|
"type": [
|
|
"string",
|
|
"null"
|
|
],
|
|
"default": null
|
|
},
|
|
"id": {
|
|
"type": "string"
|
|
},
|
|
"name": {
|
|
"type": "string"
|
|
},
|
|
"pose": {
|
|
"type": [
|
|
"string",
|
|
"null"
|
|
],
|
|
"default": null
|
|
}
|
|
},
|
|
"required": [
|
|
"id",
|
|
"name"
|
|
]
|
|
},
|
|
"PresentationScene": {
|
|
"description": "Public scene identity frozen at a committed story node.\n\nThis is presentation data, not authoritative world state. In particular it\nmust never contain unrevealed scene facts or trigger conditions.",
|
|
"type": "object",
|
|
"properties": {
|
|
"id": {
|
|
"type": "string"
|
|
},
|
|
"title": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"id",
|
|
"title"
|
|
]
|
|
},
|
|
"VisualDirective": {
|
|
"type": "object",
|
|
"properties": {
|
|
"character": {
|
|
"type": [
|
|
"string",
|
|
"null"
|
|
]
|
|
},
|
|
"expression": {
|
|
"type": [
|
|
"string",
|
|
"null"
|
|
]
|
|
},
|
|
"pose": {
|
|
"type": [
|
|
"string",
|
|
"null"
|
|
]
|
|
},
|
|
"scene": {
|
|
"type": [
|
|
"string",
|
|
"null"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|