{ "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "StoryNode", "description": "An immutable branch event with its state delta and player-facing presentation.", "type": "object", "properties": { "action_id": { "type": "string" }, "beats": { "type": "array", "default": [], "items": { "$ref": "#/$defs/PresentationBeat" } }, "branch_id": { "type": "string" }, "can_continue": { "type": "boolean", "default": true }, "character": { "$ref": "#/$defs/PresentationCharacter", "default": { "expression": null, "id": "", "name": "", "pose": null } }, "delta": { "$ref": "#/$defs/StateDelta" }, "id": { "type": "string" }, "parent_id": { "type": [ "string", "null" ] }, "scene": { "$ref": "#/$defs/PresentationScene", "default": { "id": "", "title": "" } }, "state_hash": { "type": "string" }, "story_id": { "type": "string" }, "suggestions": { "type": "array", "default": [], "items": { "$ref": "#/$defs/ActionSuggestion" } }, "user_input": { "type": "string" } }, "required": [ "id", "story_id", "branch_id", "action_id", "user_input", "delta", "state_hash" ], "$defs": { "AcquisitionMode": { "type": "string", "enum": [ "initial", "found", "given", "borrowed", "stolen", "returned" ] }, "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" ] }, "CheckDifficulty": { "type": "string", "enum": [ "regular", "hard", "extreme" ] }, "CheckRecord": { "type": "object", "properties": { "action_id": { "type": "string" }, "actor": { "type": "string" }, "bonus_dice": { "type": "integer", "format": "int8", "maximum": 127, "minimum": -128 }, "difficulty": { "$ref": "#/$defs/CheckDifficulty" }, "id": { "type": "string" }, "node_id": { "type": "string" }, "pushed_from": { "type": [ "string", "null" ] }, "result": { "$ref": "#/$defs/CheckResult" }, "roll": { "type": "integer", "format": "uint8", "maximum": 255, "minimum": 0 }, "skill": { "type": "string" }, "target": { "type": "integer", "format": "uint8", "maximum": 255, "minimum": 0 } }, "required": [ "id", "action_id", "actor", "skill", "target", "difficulty", "bonus_dice", "roll", "result", "node_id" ] }, "CheckResult": { "type": "string", "enum": [ "critical_success", "extreme_success", "hard_success", "success", "failure", "fumble" ] }, "ItemAcquisition": { "type": "object", "properties": { "at_node": { "type": "string" }, "from": { "type": [ "string", "null" ] }, "mode": { "$ref": "#/$defs/AcquisitionMode" } }, "required": [ "mode", "at_node" ] }, "ItemInstance": { "type": "object", "properties": { "acquisition": { "$ref": "#/$defs/ItemAcquisition" }, "condition": { "type": "string" }, "holder": { "type": "string" }, "id": { "type": "string" }, "owner": { "type": "string" }, "placement": { "$ref": "#/$defs/ItemPlacement" }, "quantity": { "type": "integer", "format": "uint32", "minimum": 0 }, "spec_ref": { "type": "string" }, "state_tags": { "type": "array", "default": [], "items": { "type": "string" } } }, "required": [ "id", "spec_ref", "owner", "holder", "placement", "quantity", "condition", "acquisition" ] }, "ItemPlacement": { "type": "string", "enum": [ "bag", "worn", "hand", "scene", "hidden" ] }, "KnowledgeCertainty": { "type": "string", "enum": [ "suspected", "reported", "confirmed" ] }, "KnowledgeRecord": { "type": "object", "properties": { "certainty": { "$ref": "#/$defs/KnowledgeCertainty" }, "fact": { "type": "string" }, "id": { "type": "string" }, "last_verified_at": { "type": [ "string", "null" ] }, "learned_at": { "type": "string" }, "observer": { "type": "string" }, "source": { "type": "string" }, "subject": { "type": [ "string", "null" ] } }, "required": [ "id", "observer", "fact", "certainty", "source", "learned_at" ] }, "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" ] }, "Promise": { "type": "object", "properties": { "accepted_at": { "type": [ "string", "null" ] }, "content": { "type": "string" }, "created_at": { "type": "string" }, "id": { "type": "string" }, "promisee": { "type": "string" }, "promiser": { "type": "string" }, "resolved_at": { "type": [ "string", "null" ] }, "status": { "$ref": "#/$defs/PromiseStatus" }, "weight": { "$ref": "#/$defs/PromiseWeight" } }, "required": [ "id", "promiser", "promisee", "content", "status", "weight", "created_at" ] }, "PromiseStatus": { "type": "string", "enum": [ "proposed", "accepted", "fulfilled", "broken", "released", "impossible" ] }, "PromiseWeight": { "type": "string", "enum": [ "minor", "major" ] }, "RelationshipAdjustment": { "type": "object", "properties": { "cause": { "type": "string" }, "delta": { "type": "integer", "format": "int16", "maximum": 32767, "minimum": -32768 }, "dimension": { "$ref": "#/$defs/RelationshipDimension" }, "judgment_rule": { "type": [ "string", "null" ] } }, "required": [ "dimension", "delta", "cause" ] }, "RelationshipDimension": { "type": "string", "enum": [ "affinity", "trust", "hope", "respect", "intimacy", "attachment" ] }, "StateDelta": { "type": "object", "properties": { "ops": { "type": "array", "default": [], "items": { "$ref": "#/$defs/StateOp" } } } }, "StateOp": { "oneOf": [ { "type": "object", "properties": { "key": { "type": "string" }, "op": { "type": "string", "const": "set_world_flag" }, "value": { "type": "boolean" } }, "required": [ "op", "key", "value" ] }, { "type": "object", "properties": { "adjustment": { "$ref": "#/$defs/RelationshipAdjustment" }, "from": { "type": "string" }, "op": { "type": "string", "const": "adjust_relationship" }, "to": { "type": "string" } }, "required": [ "op", "from", "to", "adjustment" ] }, { "type": "object", "properties": { "op": { "type": "string", "const": "create_promise" }, "promise": { "$ref": "#/$defs/Promise" } }, "required": [ "op", "promise" ] }, { "type": "object", "properties": { "op": { "type": "string", "const": "update_promise" }, "promise_id": { "type": "string" }, "resolved_at": { "type": [ "string", "null" ] }, "status": { "$ref": "#/$defs/PromiseStatus" } }, "required": [ "op", "promise_id", "status" ] }, { "type": "object", "properties": { "op": { "type": "string", "const": "add_knowledge" }, "record": { "$ref": "#/$defs/KnowledgeRecord" } }, "required": [ "op", "record" ] }, { "type": "object", "properties": { "item": { "$ref": "#/$defs/ItemInstance" }, "op": { "type": "string", "const": "add_item" } }, "required": [ "op", "item" ] }, { "type": "object", "properties": { "from": { "type": "string" }, "item_id": { "type": "string" }, "mode": { "$ref": "#/$defs/AcquisitionMode" }, "op": { "type": "string", "const": "transfer_item" }, "placement": { "$ref": "#/$defs/ItemPlacement" }, "to": { "type": "string" } }, "required": [ "op", "item_id", "from", "to", "placement", "mode" ] }, { "type": "object", "properties": { "check": { "$ref": "#/$defs/CheckRecord" }, "op": { "type": "string", "const": "record_check" } }, "required": [ "op", "check" ] }, { "type": "object", "properties": { "clock_id": { "type": "string" }, "delta": { "type": "integer", "format": "uint16", "maximum": 65535, "minimum": 0 }, "op": { "type": "string", "const": "advance_clock" } }, "required": [ "op", "clock_id", "delta" ] } ] }, "VisualDirective": { "type": "object", "properties": { "character": { "type": [ "string", "null" ] }, "expression": { "type": [ "string", "null" ] }, "pose": { "type": [ "string", "null" ] }, "scene": { "type": [ "string", "null" ] } } } } }