Formal spec at docs/architecture/line-pool-format.md defining YAML structure for dialogue and monologue content files. Covers tag enums, 4-layer filtering pipeline, prerequisite-to-KG mapping, ID format, validation rules, and Rust loader interface. Fixes monologue schema: adds required constraint on relationship prerequisite target/state fields. Ref: D-028, D-032, D-035, D-041 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
120 lines
3.6 KiB
JSON
120 lines
3.6 KiB
JSON
{
|
|
"$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).",
|
|
"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)"
|
|
},
|
|
"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", "trigger"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"id": {
|
|
"type": "string",
|
|
"pattern": "^[a-z][a-z0-9-]*_m_[sd]_[0-9]{3}$",
|
|
"description": "Stable line ID: {location_slug}_m_{s|d}_{###}"
|
|
},
|
|
"text": {
|
|
"type": "string",
|
|
"minLength": 1,
|
|
"maxLength": 160,
|
|
"description": "Line text — 160 char max to fit monologue display without scrolling"
|
|
},
|
|
"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"
|
|
},
|
|
"prerequisites": {
|
|
"type": "object",
|
|
"description": "AND-only prerequisite conditions",
|
|
"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)"
|
|
},
|
|
"cooldown": {
|
|
"type": "integer",
|
|
"minimum": 0,
|
|
"description": "Minimum ticks before this line can fire again"
|
|
},
|
|
"tags": {
|
|
"type": "array",
|
|
"items": { "type": "string" }
|
|
}
|
|
}
|
|
},
|
|
"fact_prerequisite": {
|
|
"type": "object",
|
|
"required": ["fact_id", "min_confidence"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"fact_id": { "type": "string" },
|
|
"min_confidence": {
|
|
"type": "string",
|
|
"enum": ["suspects", "knows_of", "knows_details", "direct"]
|
|
}
|
|
}
|
|
},
|
|
"attribute_prerequisite": {
|
|
"type": "object",
|
|
"required": ["entity", "key", "value"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"entity": { "type": "string" },
|
|
"key": { "type": "string" },
|
|
"value": { "type": "string" }
|
|
}
|
|
}
|
|
}
|
|
}
|