--- title: "Monologue Authoring Guide" description: "How to write tagged monologue and dialogue content — tag taxonomy, prerequisite format, situation overlap rules, and voice discipline" slug: monologue-guide category: authoring-guide status: canonical created: 2026-02-12 updated: 2026-02-13 tags: [] decision_refs: [D-032, D-035] cross_refs: [] --- # Monologue and Dialogue Authoring Guide How to write tagged monologue and dialogue content for The Settled Reach. Read the knowledge system docs first — this guide assumes you know what a FactId is and how RelationshipState works. **Prerequisites:** - [Fact Catalog](../concepts/fact-catalog.md) — 24 FactIds with confidence progressions - [Entity Attributes](../concepts/entity-attributes.md) — 14 canonical EntityKnowledge keys - [Relationship States](../concepts/relationship-states.md) — 5 states, transitions, dialogue access tiers **Canonical sources:** D-028 (dialogue architecture), D-032 (separate monologue pools), D-035 (tag taxonomy) --- ## Location Shortcodes Location shortcodes are defined per district. Used in line IDs (`{shortcode}_{type}_{###}`) and file naming. Author per-district shortcode tables in the district wiki entry. | Shortcode | Location Type | Notes | |-----------|-------------|-------| | `terminal` | Primary workplace (logistics hub, factory floor, etc.) | Assign per district | | `bar` | Social venue (bar, canteen, commons) | Assign per district | | `corridor` | Service / restricted spaces | Assign per district | **File naming convention:** `{shortcode}-{character}.yaml` (e.g., `terminal-smuggler.yaml`, `bar-detective.yaml`) **Line ID format:** `{shortcode}_{d|m|e}_{###}` where `d`=dialogue, `m`=monologue, `e`=environmental --- ## Situation Overlap Rules A line can have multiple situations in its `situation` list. These rules define valid combinations. **Mutually exclusive** (never co-occur): - `arrival` and `shift_end` — you can't be both arriving and leaving - `alone` and `social` — by definition - `emergency` and `routine` — emergency overrides routine - `confrontation` and `social` — confrontation replaces social context **Common valid overlaps:** - `shift_start` + `routine` — beginning-of-shift routine observations - `bar_evening` + `social` — social interaction at the bar - `observation` + any non-exclusive situation — observation layers on top of context - `investigation` + `observation` — investigating by watching **Default if empty:** `routine` (engine assumes routine context) --- ## Mood Exclusivity Rules A line can have multiple moods, but some combinations are contradictory. **Mutually exclusive** (never co-occur): - `fond` and `suspicious` — these are opposing orientations toward someone - `comfortable` and `worried` — opposing emotional states - `relieved` and `concerned` — resolved vs. unresolved tension **Common valid overlaps:** - `analytical` + any mood — analytical is a cognitive mode that coexists with emotion - `conflicted` + `fond` or `concerned` — conflicted implies mixed feelings - `worried` + `suspicious` — worry about someone's behavior shading into suspicion **Default if empty:** `comfortable` (engine assumes neutral emotional baseline) --- ## Core Principle Internal monologue is **hard-partitioned by playable character** (D-032). The smuggler and detective have completely separate monologue pools. No shared lines. Same trigger, different pool. This is how mirror moments work without either pool knowing about the other. Dialogue lines are shared — NPCs say the same words regardless of who's listening. The access tier system filters which lines each character can hear at runtime. --- ## D-035 Tag Taxonomy Reference Every line carries structural tags, selection tags, and (for monologue) character-specific tags. Here's the full schema. ### Structural Tags (required on every dialogue line) | Tag | Type | Purpose | |-----|------|---------| | `id` | string | `{location}_{d\|m\|e}_{###}` — stable, machine-parseable | | `text` | string | The authored line | | `role` | enum | Template-defined role, not NPC name (NPC assignment is runtime) | | `access` | list\ | Hard filter: `public`, `insider`, `authority`, `peer`, `hostile` | | `trust` | enum | Hard filter: `surface`, `real`, `secret` | | `situation` | list\ | Context filter (13 situations) | ### Selection Tags (recommended, defaults apply if empty) | Tag | Type | Purpose | |-----|------|---------| | `topic` | list\ | Weighted selection (9 topics) | | `mood` | list\ | Weighted selection (8 moods) | | `tags` | list\ | Freeform escape hatch for author intent | ### Monologue-Specific Tags (added to structural + selection) | Tag | Type | Purpose | |-----|------|---------| | `character` | enum | `smuggler` or `detective` — hard partition (D-032) | | `trigger` | enum | What fires this line (9 types — see next section) | | `prerequisite` | map or null | Knowledge state gate | ### Authoring-Only Tags (not consumed by engine) | Tag | Type | Purpose | |-----|------|---------| | `dual_lens` | map | Per-character notes on how the line reads differently | | `notes` | string | Author intent, context for future editors | ### Enum Values **`situation`** (13): `arrival`, `shift_start`, `shift_end`, `shift_transition`, `bar_evening`, `night_shift`, `investigation`, `confrontation`, `social`, `alone`, `emergency`, `routine`, `observation` **`topic`** (9): `colleague`, `routine`, `cargo`, `money`, `trust`, `danger`, `institution`, `personal`, `investigation` Note: no `crime` or `smuggling` topic. NPCs think of it as `cargo` or `money`. The detective uses `investigation`. **`mood`** (8): `fond`, `comfortable`, `worried`, `suspicious`, `analytical`, `conflicted`, `concerned`, `relieved` --- ## Monologue Trigger Types (9) The `trigger` tag determines WHEN a monologue line fires. Each type maps to a game event. ### 1. `enter_location` Fires when the player enters a named area. ```yaml - id: terminal_m_010 text: "Morning shift. Recycled air and cargo lubricant. Home sweet home." character: smuggler trigger: enter_location situation: [arrival] mood: [comfortable] prerequisite: null ``` ```yaml - id: terminal_m_011 text: "Logistics hub. Standard prefab, heavy foot traffic. Let's see what the shift change tells me." character: detective trigger: enter_location situation: [arrival] mood: [analytical] prerequisite: null ``` **Mirror moment**: Same entry, different register. Smuggler sees home; detective sees a crime scene. Use for first impressions, atmosphere, returning-to-familiar-ground observations. Keep short — the player is moving. --- ### 2. `observe_npc` Fires when a known entity enters the player's line of sight. ```yaml - id: terminal_m_020 text: "{THE FRIEND}'s here. Good — I was starting to worry." character: smuggler trigger: observe_npc mood: [fond] prerequisite: relationship_state: Friendly subject: {friend_npc_slug} ``` ```yaml - id: terminal_m_021 text: "Dock worker from the case file. {Surname}, {initial}. Unremarkable on paper." character: detective trigger: observe_npc mood: [analytical] prerequisite: fact: investigation.manifest_discrepancy confidence: Suspects ``` Use for identification, behavioral observations, emotional reactions. The prerequisite controls which version fires — same NPC, different line depending on knowledge. --- ### 3. `hear_sound` Fires on audio events — ambient, diegetic, or anomalous. ```yaml - id: bar_m_030 text: "Raised voices from the back room. That's not a routine call." character: smuggler trigger: hear_sound mood: [concerned] prerequisite: fact: contraband.ring_exists confidence: KnowsDetails ``` ```yaml - id: bar_m_031 text: "Arguing behind that door. The bartender didn't flinch. Either she's used to it or she knows what it is." character: detective trigger: hear_sound mood: [suspicious] prerequisite: null ``` Audio triggers fire less frequently than visual ones. Make them count. --- ### 4. `observe_anomaly` Fires when the player observes something that contradicts expected state — a container in the wrong place, an NPC where they shouldn't be, a door that should be locked. ```yaml - id: terminal_m_040 text: "{THE FRIEND}'s checking their lattice again. Third time in ten minutes. That's not normal." character: smuggler trigger: observe_anomaly mood: [worried] prerequisite: relationship_state: Friendly subject: {friend_npc_slug} ``` ```yaml - id: terminal_m_041 text: "Dock worker {Surname} — lattice activity spiked. Expecting a message? Or checking for surveillance?" character: detective trigger: observe_anomaly mood: [analytical] prerequisite: known_attributes: subject: {friend_npc_slug} key: behavior_flags value_contains: lattice_checking ``` This is the detective's bread and butter: the gap between expected and observed. --- ### 5. `post_conversation` Fires after a dialogue exchange ends. Internal reaction to what just happened. ```yaml - id: bar_m_050 text: "{THE FRIEND}'s good to have around. Knows the district, knows the people. Reliable." character: detective trigger: post_conversation mood: [fond] prerequisite: relationship_state: Friendly subject: {friend_npc_slug} ``` ```yaml - id: bar_m_051 text: "Not lying. But not telling me everything. {THE FRIEND}, what do you know?" character: detective trigger: post_conversation mood: [conflicted] prerequisite: relationship_state: PersonOfInterest subject: {friend_npc_slug} ``` This is where character voice shines — the detective analyzes, the smuggler worries about people. --- ### 6. `discover_evidence` Fires when the player finds physical evidence — a document, object, or data point. ```yaml - id: terminal_m_060 text: "Container 4471. Manifest says 240 kilos. That crate is closer to 310." character: detective trigger: discover_evidence mood: [analytical] prerequisite: fact: investigation.manifest_discrepancy confidence: Suspects ``` ```yaml - id: terminal_m_061 text: "4471's still in temp. Routed there during transition. Standard. Nothing to worry about." character: smuggler trigger: discover_evidence mood: [relieved] prerequisite: fact: contraband.ring_exists confidence: KnowsDetails ``` Brief, observational. The fact system handles what the player now knows — the monologue handles what they feel about it. --- ### 7. `witness_interaction` Fires when the player observes two NPCs interacting. ```yaml - id: bar_m_070 text: "{THE FRIEND}'s headed out. Smart — {NPC} gets loud after three drinks. Nobody wants to deal with that." character: smuggler trigger: witness_interaction mood: [comfortable] prerequisite: null ``` ```yaml - id: bar_m_071 text: "That's twice now. {THE FRIEND} leaves when {NPC} arrives. Coincidence? Filing it." character: detective trigger: witness_interaction mood: [analytical] prerequisite: known_attributes: subject: {friend_npc_slug} key: behavior_flags value_contains: avoidance_pattern ``` **Mirror moment**: Same event. Smuggler has the innocent explanation. Detective has the investigative read. On replay: "Wait — WAS it just the noise?" --- ### 8. `time_idle` Fires after inactivity — the player is standing still, watching, waiting. The character's mind wanders. ```yaml - id: corr_m_080 text: "Quiet tonight. Good. Nobody using the south access." character: smuggler trigger: time_idle mood: [relieved] prerequisite: fact: location.restricted_corridor confidence: KnowsDetails ``` ```yaml - id: corr_m_081 text: "This corridor should see foot traffic during shift change. It's empty. Why?" character: detective trigger: time_idle mood: [suspicious] prerequisite: fact: location.restricted_corridor confidence: Suspects ``` Idle lines reveal what the character cares about when nothing demands attention. The smuggler thinks about the operation; the detective thinks about the case. --- ### 9. `return_visit` Fires when the player returns to a location they've visited before. Distinct from `enter_location` — gates on prior visit history. ```yaml - id: bar_m_090 text: "Back at the bar. Same seats, same faces. {THE FRIEND}'s in the corner booth. Good." character: detective trigger: return_visit mood: [comfortable] prerequisite: relationship_state: Friendly subject: {friend_npc_slug} ``` ```yaml - id: bar_m_091 text: "Back again. Same booth. ...Let's see if {THE FRIEND} leaves when {NPC} shows up." character: detective trigger: return_visit mood: [suspicious] prerequisite: known_attributes: subject: {friend_npc_slug} key: behavior_flags value_contains: avoidance_pattern ``` Return visits build investigation momentum. This is where the detective's pattern recognition fires. --- ## YAML Prerequisite Format Prerequisites gate monologue lines on knowledge state. A line only fires if the player's knowledge meets the conditions. ### No prerequisite (always eligible) ```yaml prerequisite: null ``` Still filtered by trigger type, character, and location. Use for baseline observations that don't depend on knowledge. ### Gating on FactId + confidence ```yaml prerequisite: fact: contraband.ring_exists confidence: KnowsOf ``` Fires only if the active character knows the named fact at the specified confidence **or higher**. Confidence levels ordered: `Suspects` < `KnowsOf` < `KnowsDetails` < `Direct`. Use exact FactId strings from the [Fact Catalog](../concepts/fact-catalog.md) — `"contraband.ring_exists"` not `"Ring Exists"`. The 24 canonical FactIds are the only valid values. ### Gating on RelationshipState ```yaml prerequisite: relationship_state: PersonOfInterest subject: {npc_slug} ``` Fires only if the active character's relationship with the named entity is the specified state. States: `Unknown`, `Known`, `Friendly`, `PersonOfInterest`, `Hostile`. ### Gating on EntityKnowledge attributes **Exact match:** ```yaml prerequisite: known_attributes: subject: {npc_slug} key: contradiction_flagged value: meeting_unknown_contact ``` Fires if the active character's `EntityKnowledge` for the target has the exact key-value pair. **Partial match** (for comma-separated fields like `behavior_flags`): ```yaml prerequisite: known_attributes: subject: {npc_slug} key: behavior_flags value_contains: lattice_checking ``` Matches if `behavior_flags` contains `lattice_checking` anywhere in the comma-separated list. ### Compound prerequisites Combine conditions with `all` (AND) or `any` (OR): ```yaml prerequisite: all: - fact: contraband.ring_exists confidence: KnowsDetails - relationship_state: Friendly subject: {friend_npc_slug} - known_attributes: subject: {friend_npc_slug} key: behavior_flags value_contains: lattice_checking ``` All three must be true. Swap `all` for `any` for OR logic. Keep compound prerequisites to 2-3 conditions. If you need more, the line is too narrowly targeted — split it. ### Character-specific gating The `character` tag on monologue lines is already a hard partition. You don't need to gate on character inside `prerequisite`. But some facts are character-specific in practice: ```yaml # Detective-only fact — smuggler never reaches this prerequisite: fact: investigation.evidence_collected confidence: KnowsOf ``` ```yaml # Both characters can reach this, but from different starting points prerequisite: fact: contraband.ring_exists confidence: KnowsOf # Smuggler starts here. Detective earns it through investigation. ``` --- ## Access Tier Mapping The `access` tag on dialogue lines determines who can hear what. Access is derived from `RelationshipState` plus character type (smuggler/detective). ### RelationshipState to dialogue access | `access` tag | Unknown | Known | Friendly | PersonOfInterest | Hostile | |--------------|---------|-------|----------|------------------|---------| | `public` | yes | yes | yes | yes | yes | | `peer` | -- | yes | yes | -- | -- | | `insider` | -- | -- | yes | -- | -- | | `authority` | detective | detective | -- | detective | -- | | `hostile` | -- | -- | -- | -- | yes | **Key rules:** - **`public`**: Anyone can hear it. Greetings, small talk, general information. - **`peer`**: Requires Known or Friendly. Coworker talk, casual gossip. **Locks out at PersonOfInterest** — when trust breaks, peers stop sharing. - **`insider`**: Requires Friendly only. Ring operations talk, close confidences. The content that vanishes when THE FRIEND turns amber. - **`authority`**: Detective-only, works at Unknown, Known, and PersonOfInterest. Institutional leverage. Doesn't work on Friendly (too personal) or Hostile (they've stopped cooperating). - **`hostile`**: Only at Hostile. Threats, demands, final warnings. ### What this means for THE FRIEND When THE FRIEND (smuggler's) transitions from Friendly to PersonOfInterest: - `insider` lines disappear. Ring talk stops. Trust-gated confidences lock. - `peer` lines disappear. Casual warmth dries up. THE FRIEND becomes guarded. - `public` lines remain. THE FRIEND still greets the smuggler — but the warmth is gone. When THE FRIEND (detective's) transitions from Friendly to PersonOfInterest: - `insider` lines disappear. Institutional background sharing stops. - `peer` lines disappear. Bar conversation becomes stilted. - `authority` lines unlock for the detective. Pressing questions become available. This is the mechanical expression of the emotional arc. The content doesn't change — the **filter** changes. Lines that existed before are now locked. That absence IS the narrative. ### Trust sublayers Within each access tier, `trust` further filters content: | `trust` | What it gates | |---------|--------------| | `surface` | Safe topics, social norms, what anyone would say | | `real` | Honest opinions, unguarded speech, actual feelings | | `secret` | Dangerous knowledge, confessions, things that create leverage | Trust is orthogonal to access. A `peer` + `surface` line is casual coworker talk. A `peer` + `real` line is a coworker dropping the mask. A `peer` + `secret` line is a coworker confessing something risky. ### Per-NPC access mapping *v0.1 named-NPC access table removed — cited NPCs no longer in v0.2 pipeline (D-122). Author per-district access mapping tables against the active NPC roster. Pattern for the standard cast:* | NPC Role | Smuggler Access | Detective Access | |----------|----------------|------------------| | THE FRIEND (smuggler's) | `insider`, `peer` | `public` → `authority` (after flagging) | | THE FRIEND (detective's) | `public` (Commission, wary) | `peer` → `authority` (post-contradiction) | | Supervisor | `insider` (colleague) | `authority` | | Bar owner | `insider` (bar regular) | `public` → `peer` (repeat visits) | | MIRROR NPC | `peer` (through FRIEND) | `public` → `peer` (through FRIEND B) | | Ring-adjacent NPC | `insider` or `peer` | `public` | | Hub scheduler | `insider` (hub colleague) | `authority` | | Compromised inspector | `insider` (hub colleague) | `authority` | --- ## Tell Observation Format Tells are behavioral signals that update `EntityKnowledge.known_attributes`. When observed, two things happen: the attribute updates in the knowledge graph, and a monologue line fires. ### Structure A tell observation monologue line should: 1. **Name the behavior** — what the player sees 2. **Interpret through character lens** — what it means to THIS character 3. **Map to an attribute** — note in `notes` which `known_attributes` key updates ```yaml - id: terminal_m_100 text: "{THE FRIEND} keeps checking their lattice. Waiting for something." character: smuggler trigger: observe_anomaly mood: [concerned] topic: [colleague] prerequisite: relationship_state: Friendly subject: {friend_npc_slug} notes: "First tell. Updates behavior_flags: lattice_checking. Smuggler notices but doesn't flag yet." ``` ```yaml - id: terminal_m_101 text: "Dock worker {Surname} — lattice activity spiked. Three pings in two minutes. Expecting a message? Or checking for surveillance?" character: detective trigger: observe_anomaly mood: [analytical] topic: [investigation] prerequisite: relationship_state: Known subject: {friend_npc_slug} notes: "Same tell, different read. Updates behavior_flags: lattice_checking." ``` ### Tell progression Tells accumulate. Write them as a sequence, each gated on increasing knowledge: **Tell 1 — first observation (no prior flags):** ```yaml prerequisite: relationship_state: Friendly subject: {friend_npc_slug} # No behavior_flags gate — this IS the first observation ``` **Tell 2 — pattern forming (first flag set):** ```yaml prerequisite: known_attributes: subject: {friend_npc_slug} key: behavior_flags value_contains: lattice_checking # Requires tell 1 to have fired and set the attribute ``` **Tell 3 — conclusion (multiple flags):** ```yaml prerequisite: all: - known_attributes: subject: {friend_npc_slug} key: behavior_flags value_contains: lattice_checking - known_attributes: subject: {friend_npc_slug} key: behavior_flags value_contains: evasive ``` Each tell should feel like a natural observation, not a checklist. The player doesn't know they're accumulating evidence. ### Canonical tell attributes | Attribute key | What it captures | Example values | |--------------|-----------------|----------------| | `behavior_flags` | Comma-separated observations | `"nervous,lattice_checking"`, `"avoidance_pattern,evasive"` | | `tell_observed` | Specific personal tell | `"looks_left_when_lying"`, `"leaves_when_torek_arrives"` | | `contradiction_flagged` | THE FRIEND arc trigger | `"meeting_unknown_contact"`, `"avoidance_inconsistency"` | | `secret_held` | What observer believes target hides | `"ring membership"`, `"unreported evidence"` | | `secret_confidence` | Certainty level | `"suspected"`, `"likely"`, `"confirmed"` | ### THE FRIEND tell arcs *Tell arcs are authored per district against the active NPC roster — v0.1 named examples removed (D-122). The pattern structure:* **THE FRIEND A (smuggler observes):** | Phase | Tell | Behavior flag | Line tone | |-------|------|---------------|-----------| | First crack | Increased lattice checking | `lattice_checking` | Concern: "Distracted today." | | Pattern | Shortened conversations, evasive | `distracted,evasive` | Worry: "Been quiet lately." | | Contradiction | Unauthorized spatial presence | `contradiction_flagged: meeting_unknown_contact` | Alarm: "That wasn't anyone from our rotation." | | Confirmation | Personal tell fires under pressure | `tell_observed: {specific_tell}` | Hurt: "That tell. I know that tell. They're lying to me." | **THE FRIEND B (detective observes):** | Phase | Tell | Behavior flag | Line tone | |-------|------|---------------|-----------| | First departure | Leaves when ring-adjacent NPC arrives (once) | `avoidance_pattern` (begins) | Barely noticed: "Headed out. Long day." | | Second departure | Different excuse, same trigger | `avoidance_pattern` (accumulating) | Noted: "Left again. Tired lately." | | Third departure | Pattern confirmed | `contradiction_flagged: avoidance_inconsistency` | Analytical: "Three times. Three excuses. That's data." | | Deflection | Controlled redirect when asked | `tell_observed: controlled_deflection` | Conflicted: "Not lying. But not telling me everything." | --- ## Voice Discipline: Writing for Dual-Lens Every NPC line must work for both character perspectives. Same words, different meaning. ### The rule Monologue pools are separate (D-032). But dialogue is shared — the NPC says the same thing to both characters. The `access` tier filters which lines each character can hear, but `public` and `peer` lines reach both. When an NPC speaks, the words must land differently depending on who's listening. ### How to write dual-lens lines **Step 1: Write the line.** Concrete, in the speaker's voice. The NPC doesn't know who's listening. ```yaml - id: hub_d_044 role: dock_worker text: "Container 4471 sat in temp storage overnight. Scheduling backed up again." access: [public, peer] trust: surface situation: [shift_start] ``` **Step 2: Check both readings.** Document the split. ```yaml dual_lens: smuggler: "Operational context — part of the ring pipeline. 'Backed up' is cover language." detective: "Anomaly — overnight exceeds standard procedure. Flag for investigation." ``` **Step 3: Verify neither reading breaks.** If it only works for one character, use a different `access` tier or rely on character-specific monologue to recontextualize. ### Dual-lens patterns **Innocuous surface / operational subtext:** > "{Supervisor} adjusted the night shift again. Two workers short." - Smuggler: coverage gap for tonight's run - Detective: scheduling irregularity worth tracking **Social warmth / threat assessment:** > "{THE FRIEND} left early. Headache, they said." - Detective: pattern forming — third time when {NPC} is here - Smuggler: Commission person leaving, less oversight **Emotional resonance / clinical data:** > "{THE FRIEND}'s been quiet lately. Not like them." - Smuggler: concern for a friend - Detective: behavioral change in a subject **Casual disclosure / institutional intelligence:** > "I ran the usual calibration checks today." - Detective: routine work, mundane - Smuggler: Commission is still active in the district ### What to avoid - **One-character lines in shared pools.** If only the smuggler gets it, it needs `insider` access, not `public`. - **Telegraphing.** "I'm definitely not doing anything illegal" — nobody talks like that. - **Breaking NPC voice for the lens.** The NPC doesn't know who's listening. They talk like themselves. - **Over-explaining.** If you need a paragraph of `dual_lens` notes to explain the split, the line isn't doing its job. The best dual-lens lines work on surface for one character and subtext for the other. --- ## Concrete Examples: Full Tagged Pools *v0.1 named-NPC pool examples removed — cited NPCs no longer in v0.2 pipeline (D-122). Author per-district pools against the active NPC roster using the tag schema and trigger types documented above.* **Structure reference (three pools per district):** ``` content/{district}/ {terminal-slug}/ monologue-smuggler.yaml # Smuggler's FRIEND arc + operational lines monologue-detective.yaml # Detective's investigation lines dialogue.yaml # Shared NPC dialogue (access-tier filtered at runtime) {bar-slug}/ monologue-smuggler.yaml monologue-detective.yaml dialogue.yaml {corridor-slug}/ monologue-smuggler.yaml # Route operational + THE CONTRADICTION scene monologue-detective.yaml dialogue.yaml ``` **Required content per location per character:** - Arrival / enter_location (2-3 lines, baseline + investigation variant) - THE FRIEND arc phases 1-5 (smuggler: Phase 1-5 for FRIEND A; detective: Phase 1-5 for FRIEND B) - Operational / investigative observations (3-5 lines per location) - Return visit variants (1-2 lines per location) - Atmospheric time_idle lines (1-2 per location) --- ## File Naming and Directory Structure Content is organized by location and character. Location is implicit from directory — don't duplicate it in per-line tags. ``` content/ terminal/ monologue-smuggler.yaml monologue-detective.yaml dialogue.yaml bar/ monologue-smuggler.yaml monologue-detective.yaml dialogue.yaml corridor/ monologue-smuggler.yaml monologue-detective.yaml dialogue.yaml ``` Monologue files are hard-partitioned by character (D-032). One file per character per location. Dialogue files are shared — access-tier filtering happens at runtime. ### ID Convention `{location}_{type}_{###}` - **location**: `terminal`, `bar`, `corridor` (or `hub`, `corr` as shorthand) - **type**: `m` (monologue), `d` (dialogue), `e` (environmental) - **number**: Sequential per file, starting at 001 --- ## Authoring Checklist Before submitting a line: 1. **Who is speaking?** Monologue: which character? Dialogue: which role? 2. **What do they know?** Does the prerequisite reference a real FactId, RelationshipState, or attribute key from the catalogs? 3. **What triggers it?** One of 9 types. Does the trigger match the game moment? 4. **Dual-lens check.** If dialogue, does it read differently for smuggler vs detective? Document in `dual_lens`. 5. **Brevity.** Monologue competes with gameplay. If it's longer than one breath, cut it. 6. **Voice.** Does it sound like the character? The detective analyzes. The smuggler worries about people. NPCs talk like themselves, not like game designers. 7. **Show don't tell.** "The lock's been forced" not "Someone has broken into this room." 8. **Access tier.** Is the line available to the right people? Does PersonOfInterest correctly lock out trust content? --- **Cross-References:** - [D-028](../../governance/decisions/content.md#d-028-dialogue-architecture--tagged-line-pools-with-four-relational-layers): Dialogue architecture, four relational layers - [D-032](../../governance/decisions/content.md#d-032-separate-monologue-pools-per-character-superseded--deferred-to-phase-6): Separate monologue pools per character - [D-035](../../governance/decisions/content.md#d-035-converged-tag-taxonomy-for-dialogue-and-monologue-line-pools): Converged tag taxonomy - [Fact Catalog](../concepts/fact-catalog.md): All 24 FactIds for prerequisites - [Entity Attributes](../concepts/entity-attributes.md): 14 canonical known_attributes keys - [Relationship States](../concepts/relationship-states.md): 5 states, transitions, access tier mapping *If this guide contradicts a decision file, the decision file wins.*