Two-round workshop producing D-041 (Knowledge Graph Data Model): - Round 1: independent analyses from Dudley, Gestalt, SI, Tyre, Paula - Round 2: synthesis resolving debates + Gestalt mechanics validation Key decisions: - 4-level confidence hierarchy (Suspects < KnowsOf < KnowsDetails < Direct) - BTreeMap for deterministic iteration (D-010 principle 4) - Per-entity Component model, not centralized Resource - StableEntityId + EntityRegistry for save/load stability (partial Q-019) - Sprint 2 stub: structs + direct observation + basic decay (~6.5 dev-days) Resolved Q-016 (knowledge hierarchy), raised Q-024/Q-025/Q-026. Created tickets #361-#368 under epic #351, reconciled #49 children. Updated sprint 2 briefings, agent briefings, and decision files. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
26 KiB
Knowledge Graph & Information Boundaries — Round 1 (Gestalt)
Role: Mechanics Specialist Focus: How knowledge creates gameplay decisions, system interactions, and emergent fun
Executive Summary
The knowledge graph is the ENGINE that makes asymmetric information playable rather than bookkeeping. Here's what actually matters mechanically:
What makes this fun:
- Knowledge GATES player actions (can't ask about what you don't know exists)
- Knowledge CREATES opportunities (exploit what NPCs don't know)
- Knowledge DEGRADES (fog returns, what you learned becomes outdated)
- Knowledge PROPAGATES through NPCs (gossip you can observe and exploit)
The aha moments:
- Realizing an NPC just lied to you (you have contradictory knowledge)
- Discovering two NPCs both know something you just learned (they've been talking)
- Exploiting an NPC's ignorance (they don't know you know)
- Getting caught in the web of your own misinformation
The failure modes:
- Knowledge as inventory management (collect facts like Pokemon)
- Perfect memory (no decay or challenge)
- NPC knowledge invisible (can't exploit information asymmetry)
- Binary knowledge (either you know or you don't — no gradient of confidence)
1. Knowledge as Gameplay Mechanic (Questions 5-8)
1.1 How Knowledge Enters the Graph
Knowledge should come from four mechanically distinct sources, each with different gameplay implications:
| Source | How You Get It | Trust Level | Mechanical Consequence |
|---|---|---|---|
| Direct Observation | You see it happen in your LOS | HIGH (but interpretation can be wrong) | Certain knowledge, adds to your graph immediately. Can trigger monologue. |
| NPC Tells You | Dialogue, unprompted disclosure | VARIABLE (depends on NPC trust + mood) | Confidence tied to relationship. Can be lies. Gossip chains visible. |
| Physical Evidence | Documents, terminals, manifest logs | MEDIUM-HIGH (can be forged/outdated) | Bypasses social access tiers. Can contradict NPC statements. |
| Inference/Analysis | Player connects two facts, or character's insert flags pattern | LOW-MEDIUM (you might be wrong) | Generates suspects level knowledge. Needs confirmation. |
Key mechanic: The SOURCE must be tracked per knowledge node. This creates:
- "I saw Kael in the corridor" (direct) vs "Sera told me Kael was in the corridor" (told) — mechanically different
- If Sera lied, the lie is IN YOUR KNOWLEDGE GRAPH until contradicted
- Monologue can flag contradictions: "Wait, Sera said Kael was at the dock, but I just saw him here. She lied."
Implementation proposal:
pub enum KnowledgeSource {
DirectObservation { tick: u64, location: TileCoord },
ToldByNPC { npc_id: u64, tick: u64, trust_at_time: f32 },
PhysicalEvidence { evidence_id: String, location: TileCoord },
Inference { based_on: Vec<KnowledgeNodeId> },
}
1.2 Can Knowledge Be Wrong? (Misinformation Mechanic)
YES. This is load-bearing.
The graph must support:
- Lies from NPCs — THE FRIEND tells you they were somewhere, but you later observe contradictory evidence
- Outdated information — "Kael works at the Terminal" (true yesterday, false today after reassignment)
- Partial information — "Two people in that room" but you couldn't see who
- False inferences — Player assumes X based on incomplete data
Mechanical consequence: Knowledge needs a KnowledgeState enum:
pub enum KnowledgeState {
Active, // Currently believed true
Contradicted, // You have conflicting information (monologue fires)
Outdated, // Information age threshold passed
Superseded(KnowledgeNodeId), // Replaced by newer knowledge
}
When you discover contradictory knowledge:
- Both nodes remain in the graph
- Internal monologue fires: "Sera told me Kael was at the dock, but I just saw him in the corridor. Why did she lie?"
- THE FRIEND's color shifts (green → amber) — this IS the emotional gut-punch
This is emergent detective gameplay. The graph structure CREATES the story beat.
1.3 How NPCs Share Knowledge (Gossip System)
NPCs must have their own knowledge graphs. D-010 principle 2 is non-negotiable here.
Gossip propagation rules:
- NPCs share knowledge during conversations (visible or invisible to player)
- What gets shared depends on:
- Relationship trust level
- Secret/vulnerability axis (some facts are suppressed)
- Tolerance threshold (stressed NPCs overshare)
- Triangle pressure (gossip escalates triangle conflicts)
Observable mechanic:
- Player sees two NPCs talking
- Later, NPC B mentions something only NPC A would know
- Player realizes: "They talked. Information propagates. I need to control what people know."
Gameplay loop:
1. Player learns secret about Kael
2. Player tells Sera (dialogue choice)
3. Sera gossips to Hael (background simulation)
4. Hael confronts Kael (triangle pressure threshold crossed)
5. Player observes the consequence of information propagation
Anti-pattern: NPCs all share knowledge instantly (breaks mystery). Correct pattern: Gossip propagates at routine intersections + trust thresholds. Visible if you're watching. Invisible if you're not.
2. Q-016: Knowledge Hierarchy (Suspects < Knows_Of < Knows_Details)
Let me break down what this actually means mechanically.
2.1 The Three Levels
| Level | What It Means | How You Get It | What It Gates |
|---|---|---|---|
| Suspects | "Something's weird about X" | Observation triggers (tell fired, routine deviation, monologue hint) | Can investigate. Can't ask direct questions. Monologue says "seems off." |
| Knows_Of | "X is involved in Y" | Confirmed connection (saw them at location, told by trusted source, found evidence) | Can ask surface-level questions. NPC deflects if trust < threshold. Access tier: insider/peer. |
| Knows_Details | "X is doing Y because Z" | Deep evidence or full disclosure | Can confront. Can exploit. Can make informed choices. Access tier: real/secret. |
2.2 Mechanical Consequences
Monologue prerequisites (resolves Q-016):
# Smuggler entering The Terminal
- id: terminal_m_001
text: "Another day at the office. Keep your head down, Kael."
character: smuggler
trigger: enter_location
prerequisite: null # Always fires
- id: terminal_m_023
text: "Sera's avoiding Torek again. What's she hiding?"
character: smuggler
trigger: observe_npc
prerequisite:
knows_of: ["sera_avoiding_torek"]
- id: terminal_m_047
text: "She's protecting Hael. The manifest discrepancies. It all connects."
character: smuggler
trigger: discover_evidence
prerequisite:
knows_details: ["sera_manifest_cover", "hael_kael_partnership"]
Dialogue access tiers (D-028 Layer 1):
# Talking to Sera
- id: sera_d_012
text: "Busy day at the scanners?"
access: [public]
trust: surface
prerequisite: null
- id: sera_d_089
text: "I noticed you've been avoiding Torek. Everything okay?"
access: [peer]
trust: real
prerequisite:
knows_of: ["sera_avoiding_torek"]
- id: sera_d_134
text: "You're covering for Hael, aren't you? The manifest logs."
access: [insider]
trust: secret
prerequisite:
knows_details: ["sera_manifest_cover"]
Key insight: The hierarchy creates a PROGRESSION SYSTEM for investigation. You're not grinding XP — you're grinding knowledge confidence.
2.3 How You Advance Through The Hierarchy
This is the core gameplay loop:
SUSPECTS → KNOWS_OF:
- Observe NPC in wrong place (direct observation)
- Multiple tells fire (pattern emerges)
- Trusted NPC mentions connection (told by high-trust source)
- Find physical evidence (document, terminal log)
KNOWS_OF → KNOWS_DETAILS:
- Confront NPC and they confess (relationship trust + pressure)
- Gather 2+ pieces of corroborating evidence
- Witness the action directly (catch them in the act)
- Trusted source gives full disclosure (unprompted at high trust)
Mechanical weight: Advancing a knowledge node should require PLAYER ACTION. You don't automatically go from suspects → knows_of just by waiting. You have to investigate.
3. Game Mechanics Integration (Questions 12-14)
3.1 Knowledge Graph → Monologue Pipeline (D-019, Tickets #119-122)
How this works:
- Simulation detects trigger condition (enter location, observe NPC, time idle)
- Query knowledge graph: What does the player character know about this location/NPC?
- Filter monologue pool by:
- Character (hard partition per D-032)
- Trigger type
- Knowledge prerequisites (suspects/knows_of/knows_details)
- Situation tags (first_visit, return_visit, after_confrontation, etc.)
- Select weighted by mood + recent topics
- Emit MonologueEvent to client
Example system logic:
fn trigger_observation_monologue(
query: Query<(&PlayerCharacter, &Position, &KnowledgeGraph)>,
observed: Query<(Entity, &Position), With<Npc>>,
monologue_pool: Res<MonologuePool>,
) {
for (character, player_pos, knowledge) in &query {
for (npc_entity, npc_pos) in &observed {
if in_line_of_sight(player_pos, npc_pos) {
// Check knowledge state
let knowledge_level = knowledge.get_confidence(npc_entity);
// Query monologue pool with filters
let candidates = monologue_pool.query(MonologueQuery {
character: character.archetype, // smuggler/detective
trigger: TriggerType::ObserveNpc,
npc_role: npc_role_mapping(npc_entity),
prerequisite: knowledge_level,
});
if let Some(line) = weighted_select(candidates, character.mood) {
events.send(MonologueEvent { line });
}
}
}
}
}
Key insight: Knowledge prerequisites make monologue REACTIVE to investigation progress. Early game monologue is vague ("Something's off"). Late game monologue is specific ("She's lying to protect Hael").
3.2 Knowledge Graph → Dialogue Access (D-028 Layer 1)
The hard gate mechanic:
You literally cannot SELECT a dialogue line if you don't meet the knowledge prerequisite.
Player clicks NPC → Open dialogue UI
↓
Query available lines:
- Filter by access tier (player's relationship to NPC)
- Filter by knowledge prerequisites
- Weight by mood + situation
↓
Present 3-5 dialogue options to player
↓
Player selects one → conversation continues
Example interaction:
Early game (knows_of: null):
- "Hi Sera, how's it going?" [public]
- "Seen anything unusual today?" [public]
- "Where's Kael?" [peer, if relationship ≥ 0.3]
Mid game (knows_of: ["sera_avoiding_torek"]):
- "Hi Sera, how's it going?" [public]
- "I noticed you've been avoiding Torek. Want to talk?" [peer]
- "Where's Kael?" [peer]
Late game (knows_details: ["sera_manifest_cover"]):
- "Hi Sera, how's it going?" [public]
- "You're covering for Hael, aren't you?" [insider, trust: secret]
- "I found the manifest logs, Sera." [insider, trust: secret]
This is emergent gating. The player doesn't hit a script flag. The knowledge graph unlocks dialogue naturally.
3.3 Knowledge + Social Triangles (D-024, Q-017)
Triangle pressure as knowledge-driven mechanic:
Social triangles have a pressure value that increases based on:
- Knowledge propagation (A learns about B's secret via gossip)
- Player action (player tells C about A-B conflict)
- Time + mood (tolerance threshold erosion)
When pressure crosses threshold:
if triangle.pressure > triangle.confrontation_threshold {
// Activate confrontation situation
mark_npcs_as_in_conflict(&triangle.members);
// Dialogue lines tagged situation:confrontation become available
// Monologue observing these NPCs fires urgent variant
// If player knows_details about the triangle, they get context monologue
}
Q-017 proposal: Triangle pressure threshold should be ~60-80 (out of 100 scale).
Events that increase pressure:
- NPC discovers contradiction (+15)
- Gossip reaches third party (+10)
- Player confronts one member (+20)
- Routine conflict (wants collide) (+5 per day)
Player knowledge interaction:
- If player knows_details about triangle, monologue explains what's happening
- If player only suspects, monologue is vague: "Tension between these two."
- Player can INTENTIONALLY escalate by sharing information
This is SYSTEMS DESIGN. Knowledge graph + gossip propagation + triangle pressure = emergent drama without scripts.
4. Data Structure Design (Questions 1-4)
Let me map that to mechanics.
4.1 What "Entity A Knows About Entity B" Looks Like
pub struct KnowledgeGraph {
/// All knowledge nodes this entity has
nodes: HashMap<KnowledgeNodeId, KnowledgeNode>,
/// Quick lookup: what do I know about entity X?
entity_knowledge: HashMap<u64, Vec<KnowledgeNodeId>>,
/// Quick lookup: what facts do I know about location X?
location_knowledge: HashMap<TileCoord, Vec<KnowledgeNodeId>>,
/// Gossip propagation queue (for background NPCs)
pending_gossip: Vec<GossipEvent>,
}
pub struct KnowledgeNode {
pub id: KnowledgeNodeId,
pub content: KnowledgeContent,
pub source: KnowledgeSource,
pub confidence: KnowledgeConfidence,
pub state: KnowledgeState,
pub timestamp: u64, // When learned
pub last_confirmed: u64, // When last verified (decay mechanic)
}
pub enum KnowledgeContent {
EntityAtLocation { entity_id: u64, location: TileCoord },
EntityRelationship { entity_a: u64, entity_b: u64, relationship: String },
EntityProperty { entity_id: u64, property: String, value: String },
WorldFact { fact_id: String, data: String },
TriangleMembership { triangle_id: String, members: Vec<u64> },
}
pub enum KnowledgeConfidence {
Suspects, // ~20-40% confidence
KnowsOf, // ~60-75% confidence
KnowsDetails, // ~85-95% confidence
}
4.2 Knowledge Decay (D-011: "Fog Returns When You Leave")
Mechanical implementation:
pub fn update_knowledge_decay(
time: Res<SimulationTime>,
mut query: Query<(&mut KnowledgeGraph, &Position)>,
) {
for (mut knowledge, pos) in &mut query {
for (id, node) in &mut knowledge.nodes {
let age = time.current_tick - node.last_confirmed;
// Decay rules based on content type
let decay_threshold = match node.content {
KnowledgeContent::EntityAtLocation { .. } => 600, // 60 game-minutes
KnowledgeContent::EntityRelationship { .. } => 14400, // 24 game-hours
KnowledgeContent::EntityProperty { .. } => u64::MAX, // Never decays
_ => 3600, // 6 game-hours
};
if age > decay_threshold {
node.state = KnowledgeState::Outdated;
// Trigger monologue if player returns
if player_at_location(pos, node.content.location()) {
emit_monologue_event("I wonder if X is still here...");
}
}
}
}
}
Why this is fun:
- Knowledge isn't perfect memory
- Revisiting locations creates "is this still true?" tension
- NPCs move, situations change
- Player has to MAINTAIN their knowledge through repeated observation
Anti-pattern: Knowledge never decays (player becomes omniscient over time).
4.3 Non-Entity Facts
Handled via KnowledgeContent::WorldFact:
// Examples
KnowledgeContent::WorldFact {
fact_id: "smuggling_ring_exists",
data: "terminal_district",
}
KnowledgeContent::WorldFact {
fact_id: "manifest_discrepancy",
data: "cargo_batch_47_alpha",
}
KnowledgeContent::WorldFact {
fact_id: "code_word",
data: "nightingale",
}
These gate:
- Monologue ("I need to find out more about nightingale")
- Dialogue options ("Have you heard the word 'nightingale'?")
- Access to restricted areas (code word at door)
5. Performance (Questions 9-11)
Let me reality-check this against D-026 simulation tiers.
5.1 Memory Budget at 80 Active NPCs
Per NPC knowledge graph estimate:
Average knowledge nodes per NPC: 50-100
Average node size: ~200 bytes (with enums, IDs, metadata)
Per-NPC graph size: 10-20 KB
80 Active NPCs = 800 KB - 1.6 MB total
+ 500 Background NPCs (smaller graphs) = +2-5 MB
Total: ~3-7 MB for all knowledge graphs
This is CHEAP. For context, a single high-res texture is 4-16 MB. Knowledge graphs are not the bottleneck.
5.2 Observer Snapshot Query Efficiency
The critical query:
"What does Player A know about the entities currently in their LOS?"
fn generate_observer_snapshot(
player: &Player,
knowledge: &KnowledgeGraph,
visible_entities: &[u64],
) -> ObserverSnapshot {
let mut snapshot = ObserverSnapshot::new();
for entity_id in visible_entities {
// O(1) lookup via entity_knowledge HashMap
if let Some(node_ids) = knowledge.entity_knowledge.get(entity_id) {
let confidence = highest_confidence(node_ids, knowledge);
let last_seen = most_recent_observation(node_ids, knowledge);
snapshot.add_entity(VisibleEntity {
entity_id: *entity_id,
known_confidence: confidence,
relationship_color: derive_color(entity_id, knowledge),
});
} else {
// Unknown entity - teal color, minimal info
snapshot.add_entity(VisibleEntity {
entity_id: *entity_id,
known_confidence: None,
relationship_color: Color::UNKNOWN_TEAL,
});
}
}
snapshot
}
Performance: ~10-50 entities in LOS × O(1) lookup = negligible overhead.
5.3 Spatial Partitioning for Knowledge Updates
Do we need it? NO, not for v0.1.
Why:
- Active tier is only 80 NPCs
- Knowledge updates happen on discrete events (observation, conversation, evidence discovery)
- Not every tick — only when something HAPPENS
Future optimization: If we hit 500+ active NPCs, add spatial partitioning so gossip propagation only checks nearby entities. But that's a milestone 3+ problem.
6. The Fun Question (Critical Evaluation)
6.1 What Makes This Interesting vs Bookkeeping?
Interesting mechanics (keep these):
- Knowledge gates meaningful choices — "Should I confront Sera now, or gather more evidence?" depends on confidence level
- Asymmetry creates exploitation — "Kael doesn't know I know" enables social manipulation
- Contradictions create story beats — Discovering THE FRIEND lied IS the emotional punch
- Gossip propagates observably — You see NPCs talking, you see consequences later
- Knowledge decays — Revisiting locations has tension ("Is this still true?")
Bookkeeping mechanics (avoid these):
- Binary knowledge — Either you know or you don't (no gradient, no stakes)
- Perfect memory — Once you know, you always know (no decay, no challenge)
- Hidden NPC knowledge — Can't see what NPCs know (can't exploit information asymmetry)
- No propagation — Knowledge is static (no emergent social dynamics)
- No consequences — Knowing something doesn't change options (why track it?)
Our design scores:
- Knowledge gates choices: YES (dialogue access, monologue prerequisites)
- Asymmetry exploitable: YES (NPC knowledge graphs separate from player)
- Contradictions visible: YES (knowledge state tracking, monologue triggers)
- Gossip observable: YES (routine intersections, visible conversations)
- Knowledge decays: YES (timestamp + decay thresholds)
Verdict: This is mechanically sound. The knowledge graph creates DECISIONS, not just RECORDS.
6.2 Where Are The Aha Moments?
Moment 1: The Contradiction
You: "Where were you last night?"
Sera: "Working late at the scanners."
[Later, you check terminal logs]
Monologue: "Sera wasn't at the scanners. She lied to me. Why?"
[Sera's color shifts: green → amber]
This works because:
- Two knowledge nodes with conflicting sources
- System detects contradiction
- Monologue fires
- Visual feedback (color change)
- Player realizes: "Information is unreliable. I need to verify."
Moment 2: The Gossip Chain
[You tell Voss about Kael's smuggling]
[Hours later, you observe Voss and Maret talking]
[Next day, Maret confronts Kael]
Monologue: "Voss told Maret. Information spreads. I started this."
This works because:
- Gossip propagation system
- Observable routine intersections
- Triangle pressure increases
- Player sees CONSEQUENCE of their choices
Moment 3: The Exploitation
[You know Kael is in corridor B, but Torek doesn't]
Torek: "Have you seen Kael?"
You: [Lie] "I think he's at the dock."
[Torek leaves, you slip into corridor B unobserved]
This works because:
- Player knowledge ≠ NPC knowledge
- Dialogue options gated by what you know
- Can deliberately misinform
- Consequences are mechanical (NPC goes wrong place)
6.3 Failure Modes to Avoid
Failure Mode 1: Pokemon Knowledge
"Collect all 47 facts about the smuggling ring!"
How we avoid it:
- Knowledge isn't completionist (no "you've discovered 23/47 facts" UI)
- Confidence gradients mean there's no "done" state
- Multiple valid investigation paths (not checklist)
Failure Mode 2: Information Overload
Journal has 300 entries, player drowns in text.
How we avoid it:
- Knowledge graph is BACKEND (no giant journal UI)
- Player experiences knowledge through GATES (dialogue options, monologue context)
- "What do I know?" expressed through what actions are available
Failure Mode 3: NPC Knowledge Invisible
"I have no idea what anyone else knows."
How we avoid it:
- Observable gossip (NPCs talk, you see it)
- Tell system (NPCs react to what they know)
- Confrontation situations (knowledge triggers visible behavior change)
7. Mechanical Recommendations
7.1 Knowledge Graph Core Features (Must Have)
- Per-entity knowledge graphs — Player + all Active/Background NPCs
- Knowledge confidence hierarchy — Suspects < KnowsOf < KnowsDetails
- Knowledge source tracking — Direct/Told/Evidence/Inference
- Knowledge state — Active/Contradicted/Outdated/Superseded
- Timestamp + decay — Old knowledge becomes unreliable
- Entity knowledge lookup — O(1) "what do I know about X?"
- Gossip propagation — NPCs share knowledge at routine intersections
7.2 Integration Points
Monologue system (#119-122):
- Query knowledge graph for prerequisites
- Filter pool by confidence level
- Fire contradicted state as urgent monologue
Dialogue system (D-028):
- Gate access by knowledge prerequisites
- "Ask about X" only appears if you know_of X
- Confrontation lines require knows_details
Social triangles (D-024):
- Knowledge propagation increases triangle pressure
- Pressure threshold triggers confrontation situation
- Player knowledge gates context monologue
Entity color (D-033):
- Derive relationship color from knowledge + relationship state
- Color shifts when knowledge state changes (contradicted → amber)
7.3 V0.1 Minimum Viable Implementation
Phase 1 (Sprint 2):
KnowledgeGraphcomponent with node storage- Three confidence levels (enum)
- Direct observation source only
- Basic entity knowledge lookup
- Monologue prerequisite gating
Phase 2 (Sprint 3):
- Add ToldByNPC source
- Contradiction detection
- Gossip propagation (simple: share on conversation)
- Dialogue access gating
Phase 3 (Sprint 4):
- Knowledge decay system
- Evidence source
- Triangle pressure integration
- Full source tracking
8. Open Question Resolutions
Q-016 (Knowledge hierarchy):
- RESOLVED: Three levels (Suspects / KnowsOf / KnowsDetails) with mechanical consequences as specified above
- Confidence values: Suspects ~30%, KnowsOf ~70%, KnowsDetails ~90%
- Advancement requires player investigation action, not automatic
Q-017 (Triangle pressure threshold):
- PROPOSED: Threshold = 70 (out of 100)
- Events increase pressure: contradiction +15, gossip +10, confrontation +20, routine conflict +5/day
- When crossed, situation:confrontation activates, NPCs get observable tells
New question raised:
- Q-024: Gossip propagation timing — Do NPCs gossip immediately during conversation, or queued for next routine intersection? Immediate = more reactive, queued = more predictable for player exploitation.
9. Risk Assessment
High risk:
- Performance if we naively iterate all NPCs for gossip (mitigation: event-driven, not tick-driven)
- UI complexity if we expose too much graph state (mitigation: knowledge expressed through gates, not journal)
Medium risk:
- Knowledge decay tuning (mitigation: conservative defaults, playtesting)
- Contradiction detection false positives (mitigation: tight content authoring, source metadata)
Low risk:
- Memory overhead (justified by budget analysis)
- Query performance (O(1) lookups via HashMap)
10. Conclusion
The knowledge graph is not just a data structure — it's the MECHANIC that makes asymmetric information playable.
What this enables:
- Investigation as progression system (suspects → knows_of → knows_details)
- Social manipulation (exploit what NPCs don't know)
- Emergent drama (gossip propagates, triangles escalate)
- Genuine detective moments (contradictions, aha realizations)
What makes it fun:
- Knowledge creates CHOICES (dialogue gates, action opportunities)
- Knowledge creates TENSION (decay, unreliable sources)
- Knowledge creates STORY (THE FRIEND's lie, gossip consequences)
Bottom line: This is interesting-complex, not annoying-complex. The player never manages the graph directly — they experience it through monologue, dialogue options, and NPC behavior. That's the sweet spot.
Let's build this.
Files referenced:
/var/home/jeroenschweitzer/Projects/settled-reach/planning/decisions/perception.md(D-011, D-015-D-019)/var/home/jeroenschweitzer/Projects/settled-reach/planning/decisions/architecture.md(D-010, D-026)/var/home/jeroenschweitzer/Projects/settled-reach/planning/decisions/content.md(D-024, D-028, D-033)/var/home/jeroenschweitzer/Projects/settled-reach/planning/decisions/questions.md(Q-016, Q-017)/var/home/jeroenschweitzer/Projects/settled-reach/planning/server/src/npc/mod.rs(current NPC model)