docs(design): add content directory structure, update entity attributes, stub Nils Davan

Wave 1 critical blockers for Sprint 3:
- #384: Content directory structure design doc (10 sections + 2 appendices,
  defines canonical IDs, 8 JSON schemas, 3-tier validation pipeline, migration path)
- #374: Update entity-attributes.md (14→16 keys, secret→leverage rename,
  add 4 role-perspective keys, archetype interpretation note)
- #376: Nils Davan off-stage NPC stub (GHOST+HANDLER pattern, lattice messages,
  Triangle 1 role, relationship to Kael)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-12 17:45:16 +01:00
co-authored by Claude Opus 4.6
parent 64fea5139a
commit 5fdb7f9c53
3 changed files with 848 additions and 30 deletions
+133 -30
View File
@@ -12,7 +12,8 @@ The knowledge graph uses these attributes to determine:
- What the observer's monologue says about the target
- Which dialogue lines are available
- How the target renders in the observer snapshot (name vs. description)
- Whether secrets or contradictions are discovered
- Whether leverage or contradictions are discovered
- How role-perspective assessments shape the observer's internal narrative
---
@@ -83,7 +84,7 @@ The knowledge graph uses these attributes to determine:
- `"friend"` — Sera to detective
- `"authority figure"` — Voss to subordinates
- `"suspect"` — Kael to detective (post-discovery)
- `"partner"` — Hael to Kael
- `"partner"` — Naia to Kael
- `"stranger"` — new NPCs
**Usage**: Drives `RelationshipState` calculation (Unknown/Known/Friendly/PersonOfInterest/Hostile). Determines emotional tone of monologue.
@@ -92,16 +93,18 @@ The knowledge graph uses these attributes to determine:
### `trust_level`
**Value format**: Trust assessment (subjective, observer's judgment).
**Value format**: Trust assessment (subjective, observer's judgment). This key encompasses both the read action (what the observer can observe about trust dynamics) and the state (what level of trust currently exists between observer and target). There is no separate `trust_read` key — the observation and the conclusion are stored together as a single assessment.
**Values**: `trusted`, `reliable`, `uncertain`, `suspicious`, `compromised`.
**Examples**:
- `"trusted"` — high trust, shares sensitive information
- `"reliable"` — professional trust
- `"uncertain"` — cautiously neutral
- `"suspicious"` — flagged for observation
- `"reliable"` — professional trust, predictable behavior
- `"uncertain"` — cautiously neutral, still reading the relationship
- `"suspicious"` — flagged for observation, inconsistencies detected
- `"compromised"` — known to be under pressure or bought
**Usage**: Gates trust-tier dialogue (surface/real/secret). Detective tracking trust levels determines which NPCs can be turned.
**Usage**: Gates trust-tier dialogue (surface/real/secret). Detective tracking trust levels determines which NPCs can be turned. Smuggler uses trust levels to gauge operational reliability. The trust read (what the observer notices) and the trust state (what the observer concludes) are one assessment — the observer watches, interprets, and assigns a level in the same cognitive step.
---
@@ -134,40 +137,42 @@ The knowledge graph uses these attributes to determine:
---
## Secret Attributes
## Leverage Attributes
### `secret_held`
### `leverage_held`
**Value format**: What the observer believes this entity is hiding.
**Value format**: What the observer believes gives them (or could give them) power over this entity. This covers secrets, debts, promises, obligations, and compromising positions — not just secrets. Any information or relationship that creates asymmetric power over the target qualifies as leverage.
**Examples**:
- `"ring membership"` — detective's suspicion about Kael
- `"unreported evidence"` — smuggler's read on Sera (if observant)
- `"gambling debt"` — if Drin's vulnerability is discovered
- `"exit attempt"` — if Kael's unauthorized contact is discovered
- `"ring membership"` — detective's suspicion about Kael (secret)
- `"unreported evidence"` — smuggler's read on Sera (concealed information)
- `"gambling debt"` — if Drin's vulnerability is discovered (financial obligation)
- `"exit attempt"` — if Kael's unauthorized contact is discovered (betrayal)
- `"owes favor to Voss"` — social obligation
- `"witnessed the handoff"` — compromising position
**Usage**: Drives PersonOfInterest state. Gates confrontation dialogue. Smuggler and detective track different secrets about the same NPCs.
**Usage**: Drives PersonOfInterest state. Gates confrontation dialogue. Smuggler and detective track different leverage about the same NPCs. The broader scope (beyond secrets) allows content authors to capture debts, promises, and obligations that create power dynamics without requiring additional keys.
---
### `secret_confidence`
### `leverage_confidence`
**Value format**: How certain the observer is about the secret.
**Value format**: How certain the observer is about the leverage.
**Examples**:
- `"suspected"` — behavioral flags suggest something, no proof
- `"likely"` — multiple indicators align
- `"confirmed"` — direct evidence or confession
**Usage**: Dialogue tone. "Suspected" secrets allow fishing questions. "Confirmed" secrets enable direct confrontation.
**Usage**: Dialogue tone. "Suspected" leverage allows fishing questions. "Confirmed" leverage enables direct confrontation or exploitation.
---
## Investigation Attributes (Detective-Specific)
## Investigation Attributes
### `tell_observed`
**Value format**: Specific tell noted by the detective.
**Value format**: Specific tell noted by the observer.
**Examples**:
- `"looks left when lying"` — Kael's tell
@@ -177,6 +182,8 @@ The knowledge graph uses these attributes to determine:
**Usage**: Behavioral profiling. Accumulated tells build case strength. Monologue references specific tells when they recur.
> **Implementation note**: The server may track tells via `behavior_flags` internally, since tells are a subset of behavioral observations. `tell_observed` is retained as a documented content-authoring key because it serves a distinct narrative purpose: `behavior_flags` accumulates raw observations ("nervous,lattice_checking"), while `tell_observed` captures the observer's interpretive conclusion ("looks left when lying"). Content authors reference `tell_observed` for monologue prerequisites that require the observer to have formed a specific read on the target. The server implementation may store both, or derive `tell_observed` from `behavior_flags` pattern matching.
---
### `contradiction_flagged`
@@ -190,6 +197,87 @@ The knowledge graph uses these attributes to determine:
**Usage**: THE FRIEND arc trigger. When this attribute is set, monologue tone shifts. Dialogue options change. RelationshipState moves toward PersonOfInterest.
> **Implementation note**: Like `tell_observed`, the server may track contradictions via `behavior_flags` (e.g., a flag with a `contradiction:` prefix). `contradiction_flagged` is retained as a documented key because it serves as a distinct narrative trigger — content authors check for its presence to gate arc transitions and monologue shifts. The separation keeps the content authoring interface clean even if the server implementation unifies storage.
---
## Role-Perspective Attributes
These four keys capture the observer's subjective assessment of the target through the lens of their own role, goals, and ethical framework. The same key with the same value reads differently depending on the observer's archetype — interpretation lives in the content layer (monologue pools, voice registers, archetype briefs), not in the schema. See [Archetype Interpretation Note](#archetype-interpretation-note) below.
### `risk_assessment`
**Value format**: Observer's assessment of how much danger this entity poses or attracts.
**Values**: `none`, `low`, `moderate`, `high`, `critical`.
**Examples**:
- Smuggler's assessment of Pell (wavering member) = `"high"` (unpredictable, could expose the ring)
- Detective's assessment of Voss = `"moderate"` (obstructive but not directly dangerous)
- Smuggler's assessment of Naia = `"low"` (uninvolved, unlikely to cause exposure)
**Usage**: Gates operational monologue. High-risk targets trigger cautionary internal dialogue. Critical-risk targets may trigger evasion or preemptive action. The nature of "risk" depends on the archetype (see interpretation note).
---
### `loyalty_assessment`
**Value format**: Observer's assessment of this entity's reliability and loyalty.
**Values**: `solid`, `dependable`, `uncertain`, `wavering`, `hostile`.
**Examples**:
- Smuggler's assessment of Renn (courier) = `"dependable"` (reliable, follows instructions)
- Smuggler's assessment of Kael (mid-game) = `"wavering"` (showing signs of doubt)
- Detective's assessment of Sera = `"solid"` (committed to the investigation)
**Usage**: Determines how much the observer relies on or confides in the target. Wavering loyalty triggers monitoring behavior. Hostile loyalty triggers defensive or adversarial posture.
---
### `position_integrity`
**Value format**: Observer's assessment of this entity's cover, position stability, or facade status.
**Values**: `solid`, `thin`, `cracking`, `blown`, `N/A`.
**Examples**:
- Ring member's assessment of Kael = `"thin"` (behavior changes are visible to anyone watching)
- Smuggler's self-assessment near the detective = `"cracking"` (too many close calls)
- Detective's assessment of a civilian witness = `"N/A"` (no cover to assess)
**Usage**: Tracks active deception status. When position_integrity degrades, the observer's monologue reflects increasing anxiety or strategic recalculation. `N/A` is used when the concept of cover/facade does not apply to the target.
---
### `moral_weight`
**Value format**: Observer's assessment of this entity's moral involvement in the situation.
**Values**: `innocent`, `peripheral`, `complicit`, `compromised`, `willing`.
**Examples**:
- Detective's assessment of Naia = `"innocent"` (uninvolved partner caught in the fallout)
- Smuggler's assessment of Drin = `"compromised"` (dragged in by debt, not by choice)
- Smuggler's assessment of Torek = `"willing"` (fully aware, actively participating)
**Usage**: Shapes the observer's moral arc and internal conflict. Monologue tone shifts when the observer assigns moral weight — guilt, justification, and rationalization are driven by this key. The Comfort-Doubt-Reckoning-Compromise arc references `moral_weight` to determine which phase the observer occupies relative to specific NPCs.
---
### Archetype Interpretation Note
Role-perspective keys use the same value enums across all archetypes, but their meaning is archetype-dependent. The schema stores data; the content layer provides interpretation.
| Key | Smuggler reads as... | Detective reads as... |
|-----|---------------------|----------------------|
| `risk_assessment` | Operational risk to the ring (exposure, interdiction, betrayal) | Threat to public safety or obstruction of the investigation |
| `loyalty_assessment` | Loyalty to the smuggling operation | Cooperation with the investigation or institutional loyalty |
| `position_integrity` | Cover identity stability (can I still pass as legitimate?) | Authority and credibility (does my badge still open doors here?) |
| `moral_weight` | Complicity in the ring's operations (how dirty are their hands?) | Culpability in the crime (how responsible are they?) |
This pattern scales to all 8 planned archetypes without schema modification. An administrator reads `risk_assessment` as political liability; a newcomer reads it as personal vulnerability; a merchant reads it as commercial exposure. Same keys, same enums, different meaning — the archetype brief and voice register provide the lens.
---
## Examples: Full EntityKnowledge Entries
@@ -214,6 +302,10 @@ EntityKnowledge {
("trust_level".to_string(), "trusted".to_string()),
("routine_pattern".to_string(), "morning shift 06:00-14:00, bar after shift".to_string()),
("behavior_flags".to_string(), "reliable,punctual".to_string()),
("risk_assessment".to_string(), "low".to_string()), // Kael is reliable, no exposure concern
("loyalty_assessment".to_string(), "solid".to_string()), // loyal to the ring
("position_integrity".to_string(), "solid".to_string()), // cover is intact
("moral_weight".to_string(), "willing".to_string()), // fully aware, active participant
]),
}
```
@@ -244,9 +336,13 @@ EntityKnowledge {
("routine_pattern".to_string(), "morning shift, frequent late departures".to_string()),
("behavior_flags".to_string(), "nervous,lattice_checking,evasive".to_string()),
("tell_observed".to_string(), "looks left when lying".to_string()),
("secret_held".to_string(), "unauthorized meetings".to_string()),
("secret_confidence".to_string(), "confirmed".to_string()),
("leverage_held".to_string(), "unauthorized meetings".to_string()),
("leverage_confidence".to_string(), "confirmed".to_string()),
("contradiction_flagged".to_string(), "meeting_unknown_contact".to_string()),
("risk_assessment".to_string(), "high".to_string()), // obstructing investigation, potential flight risk
("loyalty_assessment".to_string(), "hostile".to_string()), // uncooperative, evasive
("position_integrity".to_string(), "cracking".to_string()), // his story is falling apart
("moral_weight".to_string(), "complicit".to_string()), // involved, degree of responsibility unclear
]),
}
```
@@ -271,8 +367,12 @@ EntityKnowledge {
("trust_level".to_string(), "uncertain".to_string()),
("routine_pattern".to_string(), "bar regular, off-duty evenings".to_string()),
("behavior_flags".to_string(), "observant,avoidance_pattern".to_string()),
("secret_held".to_string(), "knows something about Torek or Hael".to_string()),
("secret_confidence".to_string(), "suspected".to_string()),
("leverage_held".to_string(), "knows something about Torek or Naia".to_string()),
("leverage_confidence".to_string(), "suspected".to_string()),
("risk_assessment".to_string(), "moderate".to_string()), // Commission presence is inherently risky
("loyalty_assessment".to_string(), "uncertain".to_string()), // unknown allegiance
("position_integrity".to_string(), "N/A".to_string()), // Sera isn't maintaining a cover
("moral_weight".to_string(), "peripheral".to_string()), // not involved in ring, but near it
]),
}
```
@@ -282,20 +382,23 @@ EntityKnowledge {
## Attribute Lifecycle
1. **Initial state** (Unknown NPC): No attributes. EntityKnowledge doesn't exist yet.
2. **First observation** (Direct confidence): `name` (if visible via lattice query or introduction), `role` (inferred from context), `species`, `routine_pattern` starts accumulating.
3. **Repeated interaction** (KnowsOf): `relationship_type` evolves, `trust_level` set, `behavior_flags` accumulate.
4. **Investigation depth** (KnowsDetails): `secret_held`, `tell_observed`, `contradiction_flagged` added by detective. Smuggler gains `faction` clarity.
5. **Knowledge decay**: Attributes persist even as confidence decays. A KnowsOf entry retains all attributes; only positional certainty degrades.
2. **First observation** (Direct confidence): `name` (if visible via lattice query or introduction), `role` (inferred from context), `species`, `routine_pattern` starts accumulating. Initial `risk_assessment` and `moral_weight` may be set to defaults (`none` and `innocent` respectively) or left absent until the observer forms an opinion.
3. **Repeated interaction** (KnowsOf): `relationship_type` evolves, `trust_level` set, `behavior_flags` accumulate. `loyalty_assessment` and `position_integrity` become meaningful as the observer builds a model of the target's reliability and stability.
4. **Investigation depth** (KnowsDetails): `leverage_held`, `tell_observed`, `contradiction_flagged` added by detective. Smuggler gains `faction` clarity. Role-perspective keys (`risk_assessment`, `loyalty_assessment`, `position_integrity`, `moral_weight`) shift as the observer's understanding deepens — a target initially assessed as `risk_assessment: "low"` may escalate to `"high"` after contradictions surface.
5. **Knowledge decay**: Attributes persist even as confidence decays. A KnowsOf entry retains all attributes; only positional certainty degrades. Role-perspective assessments are particularly sticky — once the observer has formed a judgment, it takes strong counter-evidence to revise it.
---
## Content Authoring Guidance
- **Monologue prerequisites** can reference specific attributes: `known_attributes["secret_held"] == "ring membership"`.
- **Monologue prerequisites** can reference specific attributes: `known_attributes["leverage_held"] == "ring membership"`.
- **Dialogue access tiers** can check `faction` or `relationship_type`.
- **Tell system observations** append to `behavior_flags` as comma-separated values.
- **THE FRIEND contradiction** is triggered by setting `contradiction_flagged`.
- **Role-perspective prerequisites** can gate monologue lines by assessment: `known_attributes["risk_assessment"] == "high"` triggers different monologue pools depending on the observer's archetype (smuggler hears operational caution; detective hears investigative urgency).
- **Leverage-based confrontation** uses `leverage_held` + `leverage_confidence` together: a "suspected" leverage allows indirect probing dialogue, while "confirmed" leverage enables direct confrontation or exploitation moves.
- **Moral arc tracking** uses `moral_weight` to determine which phase of the observer's arc (Comfort/Doubt/Reckoning/Compromise) is active relative to each NPC.
---
**Total canonical keys**: 14 (4 identity, 2 social, 2 behavioral, 2 secret, 2 investigation, 2 detective-specific). Additional keys can be added as needed, but these 14 cover v0.1 requirements.
**Total canonical keys**: 16 (4 identity, 2 social, 2 behavioral, 2 leverage, 2 investigation, 4 role-perspective). The 12 shared keys cover entity facts and relational dynamics; the 4 role-perspective keys capture the observer's subjective assessment. This schema scales to all 8 planned archetypes without modification — interpretation lives in content (monologue pools, voice registers, archetype briefs), not in the key definitions.
+110
View File
@@ -0,0 +1,110 @@
# Nils Davan
**Off-Stage NPC** | Smuggling Ring | Entangled
---
## Core Identity
**Name**: Nils Davan
**Age**: ~38
**Role**: Ring Coordinator (upstream authority) — strategic direction, personnel decisions, volume targets
**System Origin**: Krenn System (same as Kael — siblings)
**Current Location**: Off-station (exact location unknown to most ring members)
**Lattice Tier**: Unknown (operates through lattice messages; communication protocols managed by Devra)
**Employer**: The Arrangement (ring leadership, operational)
---
## Essential Function
Nils is the **off-stage authority figure** in the smuggling ring. He does not appear physically in any v0.1 scene. His presence is felt entirely through:
- **Lattice messages to Kael** (~5-8 authored lines): operational instructions, volume pressure, occasional personal/familial notes
- **References in NPC dialogue**: ring members mention Nils by name or by implication ("the coordinator", "your brother", "someone above Devra")
- **Reputation and operational pressure**: the escalation that drives Triangle 1 originates with Nils
Nils is the **escalation pressure source**. He pushes for higher volume, tighter schedules, more throughput. This pressure cascades down through Devra (who executes), Kael (who handles dock-side operations), and Voss (who adjusts shift schedules to create coverage windows). Every character in the ring feels Nils's influence without seeing him.
---
## Relationships
### Kael Davan (younger sibling, ring member)
- **Type**: Blood loyalty, complicated by power dynamic
- **History**: Nils recruited Kael into the ring. "It's just moving containers. You're good at logistics. We take care of our own."
- **Current dynamic**: Genuine familial bond, but Nils puts the operation first. Pushes Kael for higher volume. Doesn't know Kael is trying to exit the ring.
- **Mechanical relevance**: If Kael's exit attempt is discovered, Nils is the primary threat. Nils's reaction — family loyalty vs. operational security — is undefined in v0.1 but implied to be dangerous.
### Devra Talsen (on-station coordinator)
- **Type**: Professional respect, operational partnership
- **Dynamic**: Nils gives strategic direction; Devra handles execution. They respect each other's competence but disagree on risk tolerance — Devra favors steady volume, Nils pushes for escalation.
- **Communication**: Lattice messages, operational protocols. Devra is Nils's primary on-station voice.
### Arvo Voss (shift supervisor)
- **Type**: Resource exploitation, no personal relationship
- **Dynamic**: Nils exploits Voss's schedule authority to create coverage windows for ring operations. Voss resents the invisible hand above him — has positional authority on the floor, but the ring's needs override his scheduling decisions. Voss complies because the money is good and because refusing Nils has consequences he doesn't want to test.
- **Nils's view**: Voss is a resource, not a person. Functional, replaceable.
### The Smuggler (PC, if ring-member path)
- **Type**: Unseen boss
- **Dynamic**: If the smuggler is a ring member, Nils is the authority known by reputation and felt through operational pressure. The smuggler has never met Nils but follows orders relayed through Devra and Kael.
---
## Known Attributes by Other NPCs
| NPC | What They Know About Nils |
|-----|---------------------------|
| **Kael** | Sibling, ring leader, pushing for higher volume, cares about family but puts operation first. Recruited Kael personally. |
| **Devra** | Full operational picture. Communication protocols. Nils's identity, strategic priorities, risk tolerance. Primary on-station contact. |
| **Voss** | "Someone above Devra" giving orders. Never met Nils. Resents the pressure. Knows consequences of refusal exist. |
| **Renn** | Ring coordinator exists. Follows orders relayed through Devra. Minimal direct knowledge. |
| **Pell** | Knows the ring has leadership above local operations. No personal details. |
| **Smuggler (if ring)** | Nils exists, gives orders, is Kael's older sibling. Known by reputation. |
| **Nobody in Sova** | Nils's exact location, the full supply chain above Nils, Nils's broader network. |
---
## Pattern / Motivation
**GHOST + HANDLER**
- **GHOST**: Physically absent from Sova Transit District. Power felt exclusively through intermediaries — lattice messages, relayed orders, operational pressure. No one outside the ring's inner circle (Kael, Devra) has met Nils in person.
- **HANDLER**: Manages ring operations from above. Sets volume targets, applies escalation pressure, makes personnel decisions. The ring's strategic direction comes from Nils; execution is delegated.
**Core motivation**: Growth. Nils wants the operation to scale. More volume, more profit, more reach. This puts him in tension with every on-station operator who prefers stability (Devra, Voss, Kael). Nils either doesn't see or doesn't care that escalation increases risk for people on the ground.
---
## v0.1 Presence
Nils is **never physically present** in any v0.1 game scene. His entire existence in the vertical slice is mediated:
### Lattice Messages (~5-8 authored lines)
Operational instructions to Kael. Pressure to increase volume. Occasional personal/familial note that humanizes the authority figure. These messages are a plot device — the player (as smuggler) may see or hear about them through Kael.
### Dialogue References
NPCs mention Nils by name or by implication:
- Kael: references "my brother" or "Nils" in ring contexts
- Voss: "another adjustment" from above, resentment toward unseen authority
- Devra: operational coordination, professional references
- Generic ring dialogue: "Nils says to push through more this cycle"
### Triangle 1 Volume Escalation Fork (Ticket #377)
Nils's transmitted message serves as a **plot device** — the escalation order that forces Triangle 1 (Voss - Kael - Nils) into active tension. The fork is triggered by Nils's demand for higher volume, which Kael must relay to Voss, who must adjust schedules, creating observable disruption.
---
## Cross-References
- [Kael Davan](kael-davan.md) — younger sibling, ring member, dock-side operator
- [Devra Talsen](devra.md) — on-station coordinator, executes Nils's strategic direction
- [Arvo Voss](voss.md) — shift supervisor, resents Nils's influence over his scheduling authority