Files
settled-reach/docs/workshops/knowledge-graph-information-boundaries/round1-gestalt.md
T
jpmschweitzerandClaude Opus 4.6 93abd9b9d0 docs(workshops): complete Knowledge Graph & Information Boundaries workshop
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>
2026-02-11 23:24:37 +01:00

26 KiB
Raw Blame History

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:

  1. Realizing an NPC just lied to you (you have contradictory knowledge)
  2. Discovering two NPCs both know something you just learned (they've been talking)
  3. Exploiting an NPC's ignorance (they don't know you know)
  4. Getting caught in the web of your own misinformation

The failure modes:

  1. Knowledge as inventory management (collect facts like Pokemon)
  2. Perfect memory (no decay or challenge)
  3. NPC knowledge invisible (can't exploit information asymmetry)
  4. 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:

  1. Lies from NPCs — THE FRIEND tells you they were somewhere, but you later observe contradictory evidence
  2. Outdated information — "Kael works at the Terminal" (true yesterday, false today after reassignment)
  3. Partial information — "Two people in that room" but you couldn't see who
  4. 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:

  1. NPCs share knowledge during conversations (visible or invisible to player)
  2. 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:

  1. Simulation detects trigger condition (enter location, observe NPC, time idle)
  2. Query knowledge graph: What does the player character know about this location/NPC?
  3. 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.)
  4. Select weighted by mood + recent topics
  5. 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):

  1. Knowledge gates meaningful choices — "Should I confront Sera now, or gather more evidence?" depends on confidence level
  2. Asymmetry creates exploitation — "Kael doesn't know I know" enables social manipulation
  3. Contradictions create story beats — Discovering THE FRIEND lied IS the emotional punch
  4. Gossip propagates observably — You see NPCs talking, you see consequences later
  5. Knowledge decays — Revisiting locations has tension ("Is this still true?")

Bookkeeping mechanics (avoid these):

  1. Binary knowledge — Either you know or you don't (no gradient, no stakes)
  2. Perfect memory — Once you know, you always know (no decay, no challenge)
  3. Hidden NPC knowledge — Can't see what NPCs know (can't exploit information asymmetry)
  4. No propagation — Knowledge is static (no emergent social dynamics)
  5. 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)

  1. Per-entity knowledge graphs — Player + all Active/Background NPCs
  2. Knowledge confidence hierarchy — Suspects < KnowsOf < KnowsDetails
  3. Knowledge source tracking — Direct/Told/Evidence/Inference
  4. Knowledge state — Active/Contradicted/Outdated/Superseded
  5. Timestamp + decay — Old knowledge becomes unreliable
  6. Entity knowledge lookup — O(1) "what do I know about X?"
  7. 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):

  • KnowledgeGraph component 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)