{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "dialogue-line.schema.json", "title": "Dialogue Line — canonical D-035 tag taxonomy", "description": "Canonical single-line schema for dialogue and monologue pools. Implements the converged tag taxonomy from D-035 (6 structural + 3 selection + 2 authoring-only tags). Monologue-specific additions (character, trigger, prerequisite) are defined in $defs/monologue_extension. Mood vocabulary renamed Sprint 14 to match voice guide (anxious/frustrated/content/suspicious/warm/hostile/relieved/focused).", "type": "object", "required": ["id", "text", "role", "access", "trust", "situation"], "additionalProperties": false, "properties": { "id": { "type": "string", "pattern": "^[a-z][a-z0-9-]*_(d|m)_[0-9]{3}$", "description": "Stable machine-parseable line ID: {npc-slug}_{d|m}_{###} (e.g. kael-davan_d_001, pc-detective_m_d_001). d = dialogue, m = monologue. NPC-scoped per D-035 Sprint 15 amendment — each NPC has an independent sequence starting at _001." }, "text": { "type": "string", "minLength": 1, "description": "The authored line text." }, "role": { "type": "string", "pattern": "^[a-z][a-z0-9-]*$", "description": "Template-defined role slug (e.g. dock-worker, bar-owner, player_character). Not NPC name — NPC assignment is runtime." }, "access": { "type": "array", "items": { "type": "string", "enum": ["public", "insider", "authority", "peer", "hostile"] }, "minItems": 1, "uniqueItems": true, "description": "D-028 Layer 1: access tiers this line is eligible for. List — a line can be eligible for multiple tiers. Hard filter." }, "trust": { "type": "string", "enum": ["surface", "real", "secret"], "description": "D-028 Layer 3: minimum trust tier required. Hard filter. Ordering: surface < real < secret." }, "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-028 Layer 2: situations in which this line can fire. 14 v0.1 values (13 original + greeting added Sprint 8 for PC dialogue initial contact lines). NOTE: 'greeting' is not yet in server/src/content/line_pool.rs — lines using it will be skipped until Rust is updated." }, "topic": { "type": "array", "items": { "type": "string", "enum": [ "colleague", "routine", "cargo", "money", "trust", "danger", "institution", "personal", "investigation" ] }, "uniqueItems": true, "description": "D-028 Layer 4: topic tags for weighted selection. 9 v0.1 values. Optional — defaults to empty if omitted. Note: 'crime' deliberately excluded; NPCs think of it as 'cargo' or 'money'." }, "mood": { "type": "array", "items": { "type": "string", "enum": [ "anxious", "frustrated", "content", "suspicious", "warm", "hostile", "relieved", "focused" ] }, "uniqueItems": true, "description": "D-028 Layer 4: mood tags for weighted selection. 8 v0.1 values. Neutral mood = omit tag (untagged lines are always eligible). Renamed Sprint 14 to match voice guide vocabulary." }, "tags": { "type": "array", "items": { "type": "string" }, "description": "Freeform escape hatch for author intent not covered by the structured taxonomy. Not consumed by the engine selection pipeline." }, "knowledge_grant": { "type": "object", "description": "Knowledge the player gains from hearing this line. Feeds into the knowledge graph (D-041).", "required": ["fact_id", "confidence"], "additionalProperties": false, "properties": { "fact_id": { "type": "string", "description": "FactId from the knowledge vocabulary (#368)." }, "confidence": { "type": "string", "enum": ["suspects", "knows_of", "knows_details", "direct"], "description": "D-041 confidence tier granted." } } }, "dual_lens": { "type": "object", "description": "Authoring-only: per-character notes for content with different resonance for smuggler vs detective. NOT consumed by the engine.", "additionalProperties": false, "properties": { "smuggler": { "type": "string" }, "detective": { "type": "string" } } }, "notes": { "type": "string", "description": "Authoring-only: freeform author notes, context, or intent documentation. NOT consumed by the engine." } }, "$defs": { "monologue_extension": { "title": "Monologue-specific additions (D-035)", "description": "Additional required fields for monologue lines. Applied ON TOP OF the base dialogue line schema. Pool-level character partitioning (D-032) is enforced at the pool root, not per-line.", "type": "object", "required": ["trigger"], "properties": { "character": { "type": "string", "enum": ["smuggler", "detective"], "description": "D-032: hard partition tag. Which playable character this line belongs to. Must match the parent pool's character field." }, "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 monologue line to fire. 9 v0.1 trigger types." }, "prerequisite": { "description": "Knowledge state gate. null = unconditional (fires whenever triggered). 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"] } } } } } ] }, "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 (no cooldown)." } } }, "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 for this fact." } } }, "attribute_prerequisite": { "type": "object", "required": ["entity", "key", "value"], "additionalProperties": false, "properties": { "entity": { "type": "string" }, "key": { "type": "string" }, "value": { "type": "string" } } }, "situation_enum": { "type": "string", "enum": [ "arrival", "shift_start", "shift_end", "shift_transition", "bar_evening", "night_shift", "investigation", "confrontation", "social", "alone", "emergency", "routine", "observation", "greeting" ], "description": "14 v0.1 situation values (D-035 + Sprint 8 amendment)." }, "topic_enum": { "type": "string", "enum": [ "colleague", "routine", "cargo", "money", "trust", "danger", "institution", "personal", "investigation" ], "description": "9 v0.1 topic values (D-035)." }, "mood_enum": { "type": "string", "enum": [ "anxious", "frustrated", "content", "suspicious", "warm", "hostile", "relieved", "focused" ], "description": "8 v0.1 mood values. Renamed Sprint 14 to match voice guide vocabulary. Neutral = untagged." } } }