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:
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user