{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "monologue-pool.schema.json", "title": "Monologue Line Pool", "description": "Tagged monologue lines, hard-partitioned by character (D-032, D-035). Monologue lines carry all 6 D-035 structural tags for schema compliance, but role/access/trust are fixed constants for player-character internal voice (role=player_character, access=[public], trust=surface). The engine does not gate monologue on access or trust — these tags exist for taxonomy uniformity only.", "type": "object", "required": ["character", "location", "lines"], "additionalProperties": false, "properties": { "character": { "type": "string", "enum": ["smuggler", "detective"], "description": "Playable character this pool belongs to (hard partition per D-032). All lines in this pool belong to this character." }, "location": { "type": "string", "pattern": "^[a-z][a-z0-9-]*$", "description": "Location slug, or 'general' for location-independent lines." }, "lines": { "type": "array", "items": { "$ref": "#/$defs/monologue_line" }, "minItems": 1 } }, "$defs": { "monologue_line": { "type": "object", "required": ["id", "text", "role", "access", "trust", "situation", "trigger"], "additionalProperties": false, "properties": { "id": { "type": "string", "pattern": "^[a-z][a-z0-9-]*_m_[sd]_[0-9]{3}$", "description": "Stable line ID: {npc-slug}_m_{s|d}_{###} (e.g. pc-smuggler_m_s_001, pc-detective_m_d_001). s = smuggler, d = detective. NPC-scoped per D-035 Sprint 15 amendment — each NPC has an independent sequence starting at _001." }, "text": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Line text — 256 char hard cap, aim for ≤160 to avoid line wrap" }, "role": { "type": "string", "const": "player_character", "description": "D-035 structural tag — always player_character for monologue. Monologue is the player character's internal voice." }, "access": { "type": "array", "items": { "const": "public" }, "minItems": 1, "maxItems": 1, "description": "D-035 structural tag — always [public] for monologue. No access gating applies to internal voice." }, "trust": { "type": "string", "const": "surface", "description": "D-035 structural tag — always surface for monologue. No trust gating applies to internal voice." }, "situation": { "type": "array", "items": { "type": "string", "enum": [ "arrival", "shift_start", "shift_end", "shift_transition", "bar_evening", "night_shift", "investigation", "confrontation", "social", "alone", "emergency", "routine", "observation", "greeting" ] }, "minItems": 1, "uniqueItems": true, "description": "D-035 structural tag: situations in which this monologue line is contextually appropriate. 14 v0.1 values. The engine selects using trigger; situation provides additional authoring context for filtering by the caller. NOTE: 'greeting' is not yet in server/src/content/line_pool.rs Situation enum." }, "trigger": { "type": "string", "enum": [ "enter_location", "observe_npc", "hear_sound", "observe_anomaly", "post_conversation", "discover_evidence", "witness_interaction", "time_idle", "return_visit" ], "description": "What causes this line to fire. 9 v0.1 trigger types (D-035 monologue-specific tag)." }, "prerequisites": { "description": "Knowledge state gate (D-035 monologue-specific tag). null or omitted = unconditional. Conditions are AND-evaluated. Uses FactIds from the knowledge vocabulary (#368, D-041).", "oneOf": [ { "type": "null" }, { "type": "object", "additionalProperties": false, "properties": { "facts": { "type": "array", "items": { "$ref": "#/$defs/fact_prerequisite" } }, "entity_attributes": { "type": "array", "items": { "$ref": "#/$defs/attribute_prerequisite" } }, "relationship": { "type": "object", "required": ["target", "state"], "additionalProperties": false, "properties": { "target": { "type": "string" }, "state": { "type": "string", "enum": ["unknown", "known", "friendly", "person_of_interest", "hostile"] } } } } } ] }, "topic": { "type": "array", "items": { "type": "string", "enum": [ "colleague", "routine", "cargo", "money", "trust", "danger", "institution", "personal", "investigation" ] }, "uniqueItems": true, "description": "D-035 selection tag: topic tags for weighted selection. 9 v0.1 values. Optional." }, "mood": { "type": "array", "items": { "type": "string", "enum": [ "anxious", "frustrated", "content", "suspicious", "warm", "hostile", "relieved", "focused" ] }, "uniqueItems": true, "description": "D-035 selection tag: mood tags for weighted selection. 8 v0.1 values, renamed Sprint 14 to match voice guide vocabulary. Neutral = untagged." }, "priority": { "type": "integer", "minimum": 0, "maximum": 10, "default": 5, "description": "Selection priority (higher = more likely to fire when multiple lines are eligible). Default: 5." }, "cooldown": { "type": "integer", "minimum": 0, "default": 0, "description": "Minimum simulation ticks before this line can fire again. Default: 0." }, "tags": { "type": "array", "items": { "type": "string" }, "description": "D-035 selection tag: freeform tags. Not consumed by the selection pipeline." }, "dual_lens": { "type": "object", "description": "Authoring-only: notes on how this line reads differently for smuggler vs detective. NOT consumed by engine.", "additionalProperties": false, "properties": { "smuggler": { "type": "string" }, "detective": { "type": "string" } } }, "notes": { "type": "string", "description": "Authoring-only: freeform author notes. NOT consumed by engine." } } }, "fact_prerequisite": { "type": "object", "required": ["fact_id", "min_confidence"], "additionalProperties": false, "properties": { "fact_id": { "type": "string", "description": "FactId from the knowledge vocabulary (#368, D-041)." }, "min_confidence": { "type": "string", "enum": ["suspects", "knows_of", "knows_details", "direct"], "description": "Minimum D-041 confidence level required." } } }, "attribute_prerequisite": { "type": "object", "required": ["entity", "key", "value"], "additionalProperties": false, "properties": { "entity": { "type": "string" }, "key": { "type": "string" }, "value": { "type": "string" } } } } }