Move wiki from docs/wiki/ to root wiki/. Add 14 category templates with YAML frontmatter, governance model, hierarchical spatial structure (system > station > district > location). Populate Krenn System entry as first concrete star system. Update cross-references in workshop and sprint docs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1362 lines
44 KiB
Markdown
1362 lines
44 KiB
Markdown
---
|
|
title: "Monologue Authoring Guide"
|
|
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](../knowledge/fact-catalog.md) — 24 FactIds with confidence progressions
|
|
- [Entity Attributes](../knowledge/entity-attributes.md) — 14 canonical EntityKnowledge keys
|
|
- [Relationship States](../knowledge/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
|
|
|
|
Canonical shortcodes for v0.1 Sova Transit District. Used in line IDs (`{shortcode}_{type}_{###}`) and file naming.
|
|
|
|
| Shortcode | Location | Full Name | D-036 Reference |
|
|
|-----------|----------|-----------|-----------------|
|
|
| `terminal` | Logistics Hub | The Terminal | Primary workplace social site |
|
|
| `bar` | The Last Shift | Lera's (informal) | Social venue |
|
|
| `corridor` | Maintenance corridors | Corridor B-7 (primary) | Smuggling/service spaces |
|
|
|
|
**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\<enum\> | Hard filter: `public`, `insider`, `authority`, `peer`, `hostile` |
|
|
| `trust` | enum | Hard filter: `surface`, `real`, `secret` |
|
|
| `situation` | list\<enum\> | Context filter (13 situations for v0.1) |
|
|
|
|
### Selection Tags (recommended, defaults apply if empty)
|
|
|
|
| Tag | Type | Purpose |
|
|
|-----|------|---------|
|
|
| `topic` | list\<enum\> | Weighted selection (9 topics for v0.1) |
|
|
| `mood` | list\<enum\> | Weighted selection (8 moods for v0.1) |
|
|
| `tags` | list\<string\> | 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 for v0.1):
|
|
`arrival`, `shift_start`, `shift_end`, `shift_transition`, `bar_evening`, `night_shift`, `investigation`, `confrontation`, `social`, `alone`, `emergency`, `routine`, `observation`
|
|
|
|
**`topic`** (9 for v0.1):
|
|
`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 for v0.1):
|
|
`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: "Kael's here. Good — I was starting to worry."
|
|
character: smuggler
|
|
trigger: observe_npc
|
|
mood: [fond]
|
|
prerequisite:
|
|
relationship_state: Friendly
|
|
subject: kael_davan
|
|
```
|
|
|
|
```yaml
|
|
- id: terminal_m_021
|
|
text: "Dock worker from the case file. Davan, K. 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. Devra's in there. That's not a brokering 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: "Kael's checking his lattice again. Third time in ten minutes. That's not normal."
|
|
character: smuggler
|
|
trigger: observe_anomaly
|
|
mood: [worried]
|
|
prerequisite:
|
|
relationship_state: Friendly
|
|
subject: kael_davan
|
|
```
|
|
|
|
```yaml
|
|
- id: terminal_m_041
|
|
text: "Dock worker Davan — lattice activity spiked. Expecting a message? Or checking for surveillance?"
|
|
character: detective
|
|
trigger: observe_anomaly
|
|
mood: [analytical]
|
|
prerequisite:
|
|
known_attributes:
|
|
subject: kael_davan
|
|
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: "Sera's good to have around. Knows the district, knows the people. Reliable."
|
|
character: detective
|
|
trigger: post_conversation
|
|
mood: [fond]
|
|
prerequisite:
|
|
relationship_state: Friendly
|
|
subject: sera_venn
|
|
```
|
|
|
|
```yaml
|
|
- id: bar_m_051
|
|
text: "She's not lying. But she's not telling me everything. Sera, what do you know?"
|
|
character: detective
|
|
trigger: post_conversation
|
|
mood: [conflicted]
|
|
prerequisite:
|
|
relationship_state: PersonOfInterest
|
|
subject: sera_venn
|
|
```
|
|
|
|
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. Kael routed it 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: "Sera's headed out. Smart — Torek 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. Sera leaves when Torek arrives. Coincidence? Filing it."
|
|
character: detective
|
|
trigger: witness_interaction
|
|
mood: [analytical]
|
|
prerequisite:
|
|
known_attributes:
|
|
subject: sera_venn
|
|
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.corridor_b7_restricted
|
|
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.corridor_b7_restricted
|
|
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 Lera's. Same seats, same faces. Sera's in the corner booth. Good."
|
|
character: detective
|
|
trigger: return_visit
|
|
mood: [comfortable]
|
|
prerequisite:
|
|
relationship_state: Friendly
|
|
subject: sera_venn
|
|
```
|
|
|
|
```yaml
|
|
- id: bar_m_091
|
|
text: "Back again. Same booth. ...Let's see if Sera leaves when Torek shows up."
|
|
character: detective
|
|
trigger: return_visit
|
|
mood: [suspicious]
|
|
prerequisite:
|
|
known_attributes:
|
|
subject: sera_venn
|
|
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](../knowledge/fact-catalog.md) — `"contraband.ring_exists"` not `"Ring Exists"`. The 24 v0.1 FactIds are the only valid values.
|
|
|
|
### Gating on RelationshipState
|
|
|
|
```yaml
|
|
prerequisite:
|
|
relationship_state: PersonOfInterest
|
|
subject: kael_davan
|
|
```
|
|
|
|
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: kael_davan
|
|
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: kael_davan
|
|
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: kael_davan
|
|
- known_attributes:
|
|
subject: kael_davan
|
|
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 Kael transitions from Friendly to PersonOfInterest:
|
|
- `insider` lines disappear. Ring talk stops. Trust-gated confidences lock.
|
|
- `peer` lines disappear. Casual warmth dries up. Kael becomes guarded.
|
|
- `public` lines remain. Kael still greets the smuggler — but the warmth is gone.
|
|
|
|
When Sera 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
|
|
|
|
How each character relates to key NPCs:
|
|
|
|
| NPC | Smuggler Access | Detective Access |
|
|
|-----|----------------|------------------|
|
|
| Kael (THE FRIEND) | `insider`, `peer` | `public` → `authority` (after flagging) |
|
|
| Sera (THE FRIEND) | `public` (Commission, wary) | `peer` → `authority` (post-contradiction) |
|
|
| Voss | `insider` (colleague) | `authority` |
|
|
| Lera | `insider` (bar regular) | `public` → `peer` (repeat visits) |
|
|
| Naia | `peer` (through Kael) | `public` → `peer` (through Sera) |
|
|
| Torek | `insider` or `peer` | `public` |
|
|
| Maret | `insider` (hub colleague) | `authority` |
|
|
| Drin | `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: "Kael keeps checking his lattice. Waiting for something."
|
|
character: smuggler
|
|
trigger: observe_anomaly
|
|
mood: [concerned]
|
|
topic: [colleague]
|
|
prerequisite:
|
|
relationship_state: Friendly
|
|
subject: kael_davan
|
|
notes: "First tell. Updates behavior_flags: lattice_checking. Smuggler notices but doesn't flag yet."
|
|
```
|
|
|
|
```yaml
|
|
- id: terminal_m_101
|
|
text: "Dock worker Davan — 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: kael_davan
|
|
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: kael_davan
|
|
# No behavior_flags gate — this IS the first observation
|
|
```
|
|
|
|
**Tell 2 — pattern forming (first flag set):**
|
|
```yaml
|
|
prerequisite:
|
|
known_attributes:
|
|
subject: kael_davan
|
|
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: kael_davan
|
|
key: behavior_flags
|
|
value_contains: lattice_checking
|
|
- known_attributes:
|
|
subject: kael_davan
|
|
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
|
|
|
|
**Kael (smuggler observes):**
|
|
|
|
| Phase | Tell | Behavior flag | Line tone |
|
|
|-------|------|---------------|-----------|
|
|
| First crack | Increased lattice checking | `lattice_checking` | Concern: "Kael's distracted today." |
|
|
| Pattern | Shortened conversations, evasive | `distracted,evasive` | Worry: "Kael's been quiet lately." |
|
|
| Contradiction | Unauthorized spatial presence | `contradiction_flagged: meeting_unknown_contact` | Alarm: "That wasn't anyone from our rotation." |
|
|
| Confirmation | Looks left when answering | `tell_observed: looks_left_when_lying` | Hurt: "He always looks left when he's making something up." |
|
|
|
|
**Sera (detective observes):**
|
|
|
|
| Phase | Tell | Behavior flag | Line tone |
|
|
|-------|------|---------------|-----------|
|
|
| First departure | Leaves when Torek arrives (once) | `avoidance_pattern` (begins) | Barely noticed: "Sera headed out. Long day." |
|
|
| Second departure | Different excuse, same trigger | `avoidance_pattern` (accumulating) | Noted: "Sera left again. She's been 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: "She's not lying. But she's 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:**
|
|
> "Voss adjusted the night shift again. Two workers short."
|
|
- Smuggler: coverage gap for tonight's run
|
|
- Detective: scheduling irregularity worth tracking
|
|
|
|
**Social warmth / threat assessment:**
|
|
> "Sera left early. Headache, she said."
|
|
- Detective: pattern forming — third time when Torek's here
|
|
- Smuggler: Commission person leaving, less oversight
|
|
|
|
**Emotional resonance / clinical data:**
|
|
> "Kael's been quiet lately. Not like him."
|
|
- 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
|
|
|
|
Three pools, one per v0.1 social site. Each shows file structure, progression through THE FRIEND arc, and full tag usage.
|
|
|
|
### The Terminal (Logistics Hub) — Smuggler Monologue
|
|
|
|
```yaml
|
|
# File: content/terminal/monologue-smuggler.yaml
|
|
# Location: The Terminal (Logistics Hub)
|
|
# Character: Smuggler
|
|
|
|
lines:
|
|
|
|
# --- ARRIVAL ---
|
|
|
|
- id: terminal_m_001
|
|
character: smuggler
|
|
trigger: enter_location
|
|
prerequisite: null
|
|
text: "Morning shift. Recycled air and cargo lubricant. Home sweet home."
|
|
mood: [comfortable]
|
|
topic: [routine]
|
|
situation: [arrival, shift_start]
|
|
access: [insider]
|
|
trust: surface
|
|
tags: [baseline]
|
|
|
|
- id: terminal_m_002
|
|
character: smuggler
|
|
trigger: enter_location
|
|
prerequisite:
|
|
fact: contraband.ring_exists
|
|
confidence: KnowsDetails
|
|
text: "Shift transition in thirty minutes. If Voss kept the schedule thin, the route's clear."
|
|
mood: [analytical]
|
|
topic: [cargo]
|
|
situation: [shift_transition]
|
|
access: [insider]
|
|
trust: real
|
|
tags: [ring, operational]
|
|
|
|
# --- KAEL: THE FRIEND ARC ---
|
|
|
|
# Phase 1: Comfort
|
|
- id: terminal_m_010
|
|
character: smuggler
|
|
trigger: observe_npc
|
|
prerequisite:
|
|
relationship_state: Friendly
|
|
subject: kael_davan
|
|
text: "Kael's already at the dock. Good. The day's better when he's on shift."
|
|
mood: [fond]
|
|
topic: [colleague]
|
|
situation: [shift_start]
|
|
access: [insider, peer]
|
|
trust: surface
|
|
tags: [kael, baseline, pre_contradiction]
|
|
notes: "Phase 1 warmth. Establishes the bond before it gets tested."
|
|
|
|
# Phase 2: First crack
|
|
- id: terminal_m_011
|
|
character: smuggler
|
|
trigger: observe_anomaly
|
|
prerequisite:
|
|
all:
|
|
- relationship_state: Friendly
|
|
subject: kael_davan
|
|
- known_attributes:
|
|
subject: kael_davan
|
|
key: behavior_flags
|
|
value_contains: lattice_checking
|
|
text: "Kael keeps checking his lattice. Waiting for a message? Not like him to be jumpy."
|
|
mood: [concerned]
|
|
topic: [colleague]
|
|
situation: [routine]
|
|
access: [insider]
|
|
trust: real
|
|
tags: [kael, tell, first_crack]
|
|
notes: "Phase 2. Smuggler notices, doesn't flag it. Updates behavior_flags."
|
|
|
|
- id: terminal_m_012
|
|
character: smuggler
|
|
trigger: post_conversation
|
|
prerequisite:
|
|
known_attributes:
|
|
subject: kael_davan
|
|
key: behavior_flags
|
|
value_contains: evasive
|
|
text: "Kael cut lunch short again. 'Things to take care of.' Since when does Kael have things to take care of that don't involve me?"
|
|
mood: [worried]
|
|
topic: [colleague]
|
|
situation: [routine]
|
|
access: [insider]
|
|
trust: real
|
|
tags: [kael, tell, pattern_forming]
|
|
|
|
# Phase 3: The contradiction
|
|
- id: terminal_m_013
|
|
character: smuggler
|
|
trigger: witness_interaction
|
|
prerequisite:
|
|
relationship_state: Friendly
|
|
subject: kael_davan
|
|
text: "Kael? By the service hatch? And that's — I don't know them. Not crew, not ring. Who is that?"
|
|
mood: [concerned]
|
|
topic: [colleague]
|
|
situation: [observation]
|
|
access: [insider]
|
|
trust: real
|
|
tags: [kael, the_friend, contradiction, critical_moment]
|
|
notes: >
|
|
THE CONTRADICTION. Kael in restricted area with unknown contact.
|
|
Sets contradiction_flagged: meeting_unknown_contact.
|
|
RelationshipState: Friendly -> PersonOfInterest. Green -> amber.
|
|
|
|
# Phase 4: Confrontation aftermath
|
|
- id: terminal_m_014
|
|
character: smuggler
|
|
trigger: post_conversation
|
|
prerequisite:
|
|
all:
|
|
- relationship_state: PersonOfInterest
|
|
subject: kael_davan
|
|
- known_attributes:
|
|
subject: kael_davan
|
|
key: tell_observed
|
|
value: looks_left_when_lying
|
|
text: "He looked left. He always looks left when he's making something up. Two years I've known that tell. Kael is lying to me."
|
|
mood: [conflicted]
|
|
topic: [trust]
|
|
situation: [confrontation]
|
|
access: [insider]
|
|
trust: real
|
|
tags: [kael, the_friend, tell_confirmation]
|
|
notes: "The tell pays off. Established early in casual observation, confirmed under pressure."
|
|
|
|
# Phase 5: Contaminated trust
|
|
- id: terminal_m_015
|
|
character: smuggler
|
|
trigger: observe_npc
|
|
prerequisite:
|
|
all:
|
|
- relationship_state: PersonOfInterest
|
|
subject: kael_davan
|
|
- known_attributes:
|
|
subject: kael_davan
|
|
key: contradiction_flagged
|
|
value: meeting_unknown_contact
|
|
text: "Same old Kael. Same jokes, same routine. ...What are you not telling me?"
|
|
mood: [conflicted]
|
|
topic: [colleague]
|
|
situation: [routine]
|
|
access: [insider]
|
|
trust: real
|
|
tags: [kael, the_friend, contaminated_trust]
|
|
notes: "Phase 5. Warmth and doubt simultaneously. Every smile now has a question mark."
|
|
|
|
# --- OPERATIONAL ---
|
|
|
|
- id: terminal_m_020
|
|
character: smuggler
|
|
trigger: observe_anomaly
|
|
prerequisite:
|
|
fact: investigation.cargo_anomaly
|
|
confidence: Suspects
|
|
text: "That container's been in temp since yesterday. Someone forgot to process it, or someone's stalling."
|
|
mood: [concerned]
|
|
topic: [cargo]
|
|
situation: [routine]
|
|
access: [insider]
|
|
trust: real
|
|
tags: [investigation, cargo]
|
|
|
|
- id: terminal_m_021
|
|
character: smuggler
|
|
trigger: time_idle
|
|
prerequisite:
|
|
fact: world.shift_schedule
|
|
confidence: KnowsDetails
|
|
text: "Thirteen-forty. Transition window opens in fifty minutes. After that, twenty minutes of reduced oversight."
|
|
mood: [analytical]
|
|
topic: [routine]
|
|
situation: [routine]
|
|
access: [insider]
|
|
trust: real
|
|
tags: [ring, timing, operational]
|
|
```
|
|
|
|
---
|
|
|
|
### The Last Shift (Bar) — Detective Monologue
|
|
|
|
```yaml
|
|
# File: content/bar/monologue-detective.yaml
|
|
# Location: The Last Shift (Bar)
|
|
# Character: Detective
|
|
|
|
lines:
|
|
|
|
# --- ARRIVAL ---
|
|
|
|
- id: bar_m_001
|
|
character: detective
|
|
trigger: enter_location
|
|
prerequisite: null
|
|
text: "The Last Shift. Grain spirit and low conversation. Only place in this district that doesn't smell like freight lubricant."
|
|
mood: [comfortable]
|
|
topic: [routine]
|
|
situation: [arrival, bar_evening]
|
|
access: [public]
|
|
trust: surface
|
|
tags: [baseline, atmosphere]
|
|
|
|
- id: bar_m_002
|
|
character: detective
|
|
trigger: return_visit
|
|
prerequisite:
|
|
fact: progress.initial_suspicion
|
|
confidence: KnowsOf
|
|
text: "Back again. People talk here. And people who don't talk are talking too — just not out loud."
|
|
mood: [analytical]
|
|
topic: [investigation]
|
|
situation: [bar_evening]
|
|
access: [authority]
|
|
trust: real
|
|
tags: [investigation, atmosphere]
|
|
|
|
# --- SERA: THE FRIEND ARC ---
|
|
|
|
# Phase 1: Trust
|
|
- id: bar_m_010
|
|
character: detective
|
|
trigger: observe_npc
|
|
prerequisite:
|
|
relationship_state: Friendly
|
|
subject: sera_venn
|
|
text: "Sera's in her usual booth. Good. One familiar face in a district that doesn't want me here."
|
|
mood: [relieved]
|
|
topic: [colleague]
|
|
situation: [bar_evening]
|
|
access: [peer]
|
|
trust: surface
|
|
tags: [sera, baseline, trust]
|
|
notes: "Phase 1. Sera is the detective's anchor. Establish this warmth — it has to hurt later."
|
|
|
|
# Phase 2: Background
|
|
- id: bar_m_011
|
|
character: detective
|
|
trigger: post_conversation
|
|
prerequisite:
|
|
relationship_state: Friendly
|
|
subject: sera_venn
|
|
text: "Sera's connected here. Knows the regulars, knows the routines. And she's got diagnostic access. Useful."
|
|
mood: [comfortable]
|
|
topic: [colleague]
|
|
situation: [social]
|
|
access: [peer]
|
|
trust: surface
|
|
tags: [sera, background, pre_contradiction]
|
|
notes: "Phase 2. The detective notes Sera's access level without realizing it's the source of the conflict."
|
|
|
|
# Phase 3: Pattern — first departure
|
|
- id: bar_m_012
|
|
character: detective
|
|
trigger: witness_interaction
|
|
prerequisite:
|
|
relationship_state: Friendly
|
|
subject: sera_venn
|
|
text: "Sera headed out. Early shift tomorrow, she said. Fair enough."
|
|
mood: [comfortable]
|
|
topic: [colleague]
|
|
situation: [bar_evening]
|
|
access: [peer]
|
|
trust: surface
|
|
tags: [sera, avoidance, departure_1]
|
|
notes: "First Torek departure. Detective barely notices."
|
|
|
|
# Phase 3: Pattern — second departure
|
|
- id: bar_m_013
|
|
character: detective
|
|
trigger: witness_interaction
|
|
prerequisite:
|
|
known_attributes:
|
|
subject: sera_venn
|
|
key: behavior_flags
|
|
value_contains: avoidance_pattern
|
|
text: "Sera left again. Headache. Right after Torek walked in. ...Noted."
|
|
mood: [suspicious]
|
|
topic: [colleague]
|
|
situation: [bar_evening]
|
|
access: [peer]
|
|
trust: real
|
|
tags: [sera, avoidance, departure_2]
|
|
notes: "Second departure. Detective notes it. Not yet a pattern."
|
|
|
|
# Phase 3: Pattern — the third (contradiction)
|
|
- id: bar_m_014
|
|
character: detective
|
|
trigger: witness_interaction
|
|
prerequisite:
|
|
known_attributes:
|
|
subject: sera_venn
|
|
key: contradiction_flagged
|
|
value: avoidance_inconsistency
|
|
text: "That's the third time. Early shift, headache, kiosk check. Three excuses, one result. Sera leaves when Torek arrives. That's not coincidence."
|
|
mood: [analytical]
|
|
topic: [colleague]
|
|
situation: [bar_evening, observation]
|
|
access: [peer]
|
|
trust: real
|
|
tags: [sera, the_friend, contradiction_discovery]
|
|
notes: >
|
|
THE CONTRADICTION. Three data points make a conclusion.
|
|
Sets contradiction_flagged: avoidance_inconsistency.
|
|
RelationshipState: Friendly -> PersonOfInterest. Green -> amber.
|
|
Different from Kael's — cumulative, not sudden.
|
|
|
|
# Phase 4: The question asked
|
|
- id: bar_m_015
|
|
character: detective
|
|
trigger: post_conversation
|
|
prerequisite:
|
|
all:
|
|
- relationship_state: PersonOfInterest
|
|
subject: sera_venn
|
|
- known_attributes:
|
|
subject: sera_venn
|
|
key: tell_observed
|
|
value: controlled_deflection,topic_change
|
|
text: "She deflected. Smooth — 'he's just loud.' Technically true. But her shoulders shifted. Sera, what do you know about Torek?"
|
|
mood: [conflicted]
|
|
topic: [trust]
|
|
situation: [confrontation]
|
|
access: [authority]
|
|
trust: real
|
|
tags: [sera, the_friend, post_confrontation]
|
|
notes: "Phase 4. The detective hears the non-lie. Deflection IS the tell."
|
|
|
|
# Phase 5: Contaminated trust
|
|
- id: bar_m_016
|
|
character: detective
|
|
trigger: return_visit
|
|
prerequisite:
|
|
relationship_state: PersonOfInterest
|
|
subject: sera_venn
|
|
text: "Same booth. Same warm smile. Same offer to buy me a drink. ...Everything except whatever she's not saying."
|
|
mood: [conflicted]
|
|
topic: [trust]
|
|
situation: [bar_evening]
|
|
access: [authority]
|
|
trust: real
|
|
tags: [sera, the_friend, contaminated_trust]
|
|
notes: "Phase 5. Every kindness now has a question mark. The past is retroactively contaminated."
|
|
|
|
# --- TOREK ---
|
|
|
|
- id: bar_m_020
|
|
character: detective
|
|
trigger: observe_npc
|
|
prerequisite:
|
|
relationship_state: Unknown
|
|
subject: torek_lintar
|
|
text: "Loud one at the bar. Buying rounds he probably can't afford. Worth watching."
|
|
mood: [analytical]
|
|
topic: [money]
|
|
situation: [bar_evening]
|
|
access: [public]
|
|
trust: surface
|
|
tags: [torek, first_observation, spending]
|
|
|
|
# --- ATMOSPHERE ---
|
|
|
|
- id: bar_m_030
|
|
character: detective
|
|
trigger: time_idle
|
|
prerequisite:
|
|
fact: progress.initial_suspicion
|
|
confidence: KnowsOf
|
|
text: "Everyone's friendly enough. Drinks, jokes, the usual complaints about shift schedules. But friendly and honest aren't the same thing."
|
|
mood: [suspicious]
|
|
topic: [routine]
|
|
situation: [bar_evening]
|
|
access: [public]
|
|
trust: real
|
|
tags: [atmosphere, investigation, early_game]
|
|
```
|
|
|
|
---
|
|
|
|
### Corridor B-7 — Smuggler Monologue
|
|
|
|
```yaml
|
|
# File: content/corridor/monologue-smuggler.yaml
|
|
# Location: Corridor B-7 (Maintenance / Smuggling Route)
|
|
# Character: Smuggler
|
|
|
|
lines:
|
|
|
|
# --- ENTRY ---
|
|
|
|
- id: corridor_m_001
|
|
character: smuggler
|
|
trigger: enter_location
|
|
prerequisite:
|
|
fact: location.corridor_b7_restricted
|
|
confidence: KnowsDetails
|
|
text: "B-7. Old prefab, minimal coverage. The route works because nobody updated the surveillance map."
|
|
mood: [analytical]
|
|
topic: [routine]
|
|
situation: [night_shift]
|
|
access: [insider]
|
|
trust: real
|
|
tags: [ring, operational, spatial]
|
|
|
|
- id: corridor_m_002
|
|
character: smuggler
|
|
trigger: enter_location
|
|
prerequisite:
|
|
fact: location.corridor_b7_restricted
|
|
confidence: Suspects
|
|
text: "Maintenance corridor. Quiet. Shouldn't be this quiet during shift change."
|
|
mood: [suspicious]
|
|
topic: [routine]
|
|
situation: [shift_transition]
|
|
access: [public]
|
|
trust: surface
|
|
tags: [exploration, spatial]
|
|
notes: "Lower confidence — smuggler who doesn't know B-7's significance yet."
|
|
|
|
# --- ENVIRONMENTAL ---
|
|
|
|
- id: corridor_m_003
|
|
character: smuggler
|
|
trigger: hear_sound
|
|
prerequisite:
|
|
fact: location.corridor_b7_restricted
|
|
confidence: KnowsOf
|
|
text: "Footsteps. Wrong cadence for maintenance crew. Someone's being careful."
|
|
mood: [concerned]
|
|
topic: [danger]
|
|
situation: [night_shift]
|
|
access: [insider]
|
|
trust: real
|
|
tags: [tension, spatial_awareness]
|
|
|
|
- id: corridor_m_004
|
|
character: smuggler
|
|
trigger: time_idle
|
|
prerequisite:
|
|
fact: location.surveillance_gaps
|
|
confidence: KnowsDetails
|
|
text: "No Meridian signal down here. No eyes, no ears. Whatever happens in B-7 stays in B-7."
|
|
mood: [relieved]
|
|
topic: [routine]
|
|
situation: [alone]
|
|
access: [insider]
|
|
trust: real
|
|
tags: [ring, surveillance, operational]
|
|
|
|
# --- THE CONTRADICTION ---
|
|
|
|
- id: corridor_m_010
|
|
character: smuggler
|
|
trigger: witness_interaction
|
|
prerequisite:
|
|
relationship_state: Friendly
|
|
subject: kael_davan
|
|
text: "Kael? Down here? And that's — I don't know them. Not crew, not ring. Who the hell is that?"
|
|
mood: [concerned]
|
|
topic: [colleague]
|
|
situation: [observation]
|
|
access: [insider]
|
|
trust: real
|
|
tags: [the_friend, contradiction, kael, critical_moment]
|
|
notes: >
|
|
THE CONTRADICTION. The moment the smuggler's world shifts.
|
|
Kael in a restricted corridor with an unknown contact.
|
|
Sets contradiction_flagged: meeting_unknown_contact.
|
|
RelationshipState: Friendly -> PersonOfInterest.
|
|
Color: green -> amber. This moment is the emotional core of the arc.
|
|
|
|
- id: corridor_m_011
|
|
character: smuggler
|
|
trigger: post_conversation
|
|
prerequisite:
|
|
all:
|
|
- relationship_state: PersonOfInterest
|
|
subject: kael_davan
|
|
- known_attributes:
|
|
subject: kael_davan
|
|
key: tell_observed
|
|
value: looks_left_when_lying
|
|
text: "He looked left. Always looks left when he's making something up. Two years, Kael. I know your tells."
|
|
mood: [conflicted]
|
|
topic: [trust]
|
|
situation: [confrontation]
|
|
access: [insider]
|
|
trust: real
|
|
tags: [the_friend, kael, tell_confirmation]
|
|
notes: "Tell payoff. Established early in casual dialogue, confirmed here under pressure."
|
|
|
|
# --- EVIDENCE ---
|
|
|
|
- id: corridor_m_020
|
|
character: smuggler
|
|
trigger: discover_evidence
|
|
prerequisite:
|
|
fact: location.dead_drop_location
|
|
confidence: Direct
|
|
text: "Locker 47. Registered to someone who transferred out eighteen months ago. Convenient."
|
|
mood: [analytical]
|
|
topic: [cargo]
|
|
situation: [investigation]
|
|
access: [insider]
|
|
trust: real
|
|
tags: [dead_drop, evidence]
|
|
|
|
- id: corridor_m_021
|
|
character: smuggler
|
|
trigger: observe_anomaly
|
|
prerequisite:
|
|
fact: location.smuggling_route
|
|
confidence: KnowsDetails
|
|
text: "Fresh marks on the service hatch. Kosse's been through here. Right on schedule."
|
|
mood: [comfortable]
|
|
topic: [cargo]
|
|
situation: [night_shift]
|
|
access: [insider]
|
|
trust: real
|
|
tags: [ring, route, operational]
|
|
|
|
# --- RETURN ---
|
|
|
|
- id: corridor_m_030
|
|
character: smuggler
|
|
trigger: return_visit
|
|
prerequisite:
|
|
all:
|
|
- fact: location.corridor_b7_restricted
|
|
confidence: KnowsDetails
|
|
- relationship_state: PersonOfInterest
|
|
subject: kael_davan
|
|
text: "B-7 again. Last time I was here, Kael was talking to someone he shouldn't have been. The corridor feels different now."
|
|
mood: [suspicious]
|
|
topic: [colleague]
|
|
situation: [alone]
|
|
access: [insider]
|
|
trust: real
|
|
tags: [kael, the_friend, post_contradiction, return]
|
|
notes: "The space is contaminated by what happened here. Location memory."
|
|
```
|
|
|
|
---
|
|
|
|
## 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](../../../decisions/content.md#d-028-dialogue-architecture--tagged-line-pools-with-four-relational-layers): Dialogue architecture, four relational layers
|
|
- [D-032](../../../decisions/content.md#d-032-separate-monologue-pools-per-character): Separate monologue pools per character
|
|
- [D-035](../../../decisions/content.md#d-035-converged-tag-taxonomy-for-dialogue-and-monologue-line-pools): Converged tag taxonomy
|
|
- [Fact Catalog](../knowledge/fact-catalog.md): All 24 FactIds for prerequisites
|
|
- [Entity Attributes](../knowledge/entity-attributes.md): 14 canonical known_attributes keys
|
|
- [Relationship States](../knowledge/relationship-states.md): 5 states, transitions, access tier mapping
|
|
|
|
*If this guide contradicts a decision file, the decision file wins.*
|