- Write sprint 17 briefings for server, client, copy, visual, joint - Add Knowledge Flow & NPC Boundaries workshop brief - Close Q-025 (KG cap/eviction not needed at current scale) - Assign 9 tickets to Sprint 17: Tell Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
23 KiB
Knowledge Flow & NPC Information Boundaries Workshop Brief
Goal: Design the knowledge grant mechanism, NPC-to-NPC knowledge propagation, unprompted disclosure mechanics, NPC information boundaries, and contradiction detection algorithm -- resolving the functional gap between the mature D-041 data model and the Sprint 17 tickets that depend on it. Sprint context: Between Sprint 16 (closing) and Sprint 17 (planned) Priority: CRITICAL -- Sprint 17 blocker (6 tickets depend on these answers) Participants: Tyre (architecture lead), Gestalt (systems design), Dudley (server implementation), Paula (narrative), Qatux (documenter) Source: Tyre architecture audit 2026-02-23, Sprint 17 planning dependency analysis
Context
The Knowledge Graph data model (D-041) shipped in Sprint 2 and is mature. The Rust types are solid (server/src/knowledge/types.rs), the per-entity KnowledgeGraph component works (server/src/knowledge/graph.rs), the event queue drains correctly (server/src/knowledge/events.rs), and the filter_by_access system is implemented with 14 passing tests. Player-facing information boundaries function.
The NPC-facing side is functionally empty. NPCs run on ground truth, gossip does not transfer knowledge, contradiction detection does not fire, and dialogue cannot grant facts. Sprint 17 introduces tickets that build on this unfinished foundation.
Audit Findings (Tyre, 2026-02-23)
Q-024 (Gossip timing) -- Still open. The ToldBy source variant (KnowledgeSource::ToldBy { source_id: StableId, tick: u64 }, server/src/knowledge/types.rs line 97) is defined but never constructed anywhere in the codebase. NPC conversations (run_npc_conversations in server/src/simulation/conversation.rs, line 278+) are cosmetic -- they emit voice SoundEvents and ConversationEvents for the player's snapshot, but no knowledge flows between the participating NPCs. The conversation system IS the natural "routine intersection" hook the original workshop preferred. It already has proximity detection, cooldown management, and deterministic pairing via StableId sorting (D-010 principle 4).
Q-025 (KG cap/eviction) -- Close. Memory analysis shows ~30KB total at current NPC count. Not needed for v0.1/v0.2. Formal closure recommended.
Q-026 (Contradiction detection) -- Downstream consumers fully built and tested, detection algorithm not implemented. Anomaly marking in server/src/perception/anomaly.rs fires on KnowledgeState::Contradicted. Snapshot flags in server/src/perception/observer/mod.rs propagate it. Sprint double-take monologue in server/src/simulation/monologue.rs handles it. All tests manually set Contradicted on KG entries. The detection algorithm that would SET Contradicted based on comparing sources does not exist. Prerequisite: ToldBy sources must exist, which requires Topics 1 and 2 to be resolved first.
#141 (Player info gating) -- Mostly done. filter_by_access in server/src/knowledge/graph.rs is implemented and tested (14 tests). The dialogue pipeline enforces KG gating (layers 1-3 in server/src/simulation/dialogue.rs). Gap: the knowledge_grant field on IndexedDialogueLine (server/src/content/line_pool.rs line 297) is stubbed -- Option<KnowledgeGrant>, always None. The YAML schema defines KnowledgeGrant { fact_id: String, confidence: String } (server/src/content/types.rs lines 495-498). Dialogue lines cannot currently grant facts to the player's KnowledgeGraph.
#142 (NPC info boundaries) -- Still open. No NPC system queries its own KnowledgeGraph. server/src/npc/tell_state.rs uses axis values directly (Secret, ToleranceThreshold, Contentment, MoodState, Relationships). server/src/npc/routine.rs uses DailyRoutine directly. server/src/simulation/path_follow.rs uses ground truth. server/src/simulation/conversation.rs uses proximity + probability, not knowledge.
Sprint 17 Tickets That Depend on These Answers
| Ticket | Title | Dependency |
|---|---|---|
| #172 | Layer 4: Unprompted disclosure | Knowledge propagation model (what can NPCs share?), NPC KG awareness (what does the NPC know to share?) |
| #173 | Trait modifier system | Do traits reshape WHAT NPCs disclose (filtering) or HOW they say it (delivery)? Or both? |
| #148 | POI data model | How do POIs enter the knowledge graph? New FactId category? Or separate system? |
| #149 | POI discovery system | This IS knowledge flow -- it needs the grant mechanism |
| #141 | Knowledge-based information gating | Wire knowledge_grant, complete the loop |
| #142 | NPC information boundaries | NPCs use own KG for decisions |
Key Code to Reference
Participants should read these files before Round 1:
| File | What to read | Why |
|---|---|---|
server/src/knowledge/types.rs |
Full file | Core types: KnowledgeSource::ToldBy (line 97), KnowledgeConfidence hierarchy, KnowledgeState::Contradicted, EntityKnowledge struct, FactKnowledge struct |
server/src/knowledge/graph.rs |
Full file | KnowledgeGraph component, filter_by_access (14 tests), entity/fact queries, observe_entity, observe_entity_leaving_los |
server/src/knowledge/events.rs |
Full file | KnowledgeEventQueue, KnowledgeEventType variants (currently: DirectObservation, LeftLOS, IncompleteInteraction), process_knowledge_events system |
server/src/knowledge/registry.rs |
Full file | EntityRegistry -- StableId <-> Entity bidirectional mapping |
server/src/simulation/conversation.rs (line 278+) |
run_npc_conversations |
NPC proximity pairing, conversation lifecycle, SoundEvent/ConversationEvent emission -- the hook for knowledge transfer |
server/src/simulation/dialogue.rs |
Full file | D-028 four-layer pipeline: access tier (from KG), situations, trust tier (from KG), topic+mood scoring |
server/src/npc/tell_state.rs |
Full file | TellCategory derivation from axis values -- currently bypasses KG entirely |
server/src/npc/relationships.rs |
Full file | TrustEvent queue, relationship state transitions, trust derivation |
server/src/content/line_pool.rs (line 297) |
IndexedDialogueLine |
knowledge_grant: Option<KnowledgeGrant> stub |
server/src/content/types.rs (lines 495-498) |
KnowledgeGrant |
YAML-parsed schema: { fact_id: String, confidence: String } |
server/src/perception/anomaly.rs |
Full file | detect_anomalies system -- marks entities with AnomalyMarker based on KG Contradicted/PersonOfInterest |
server/src/simulation/monologue.rs |
Lines 1-60, sprint double-take | Anomaly monologue, recognition lines -- downstream consumer of contradiction |
Decisions to Reference
| Decision | Topic | Relevance |
|---|---|---|
| D-010 | Multiplayer-ready info boundaries | Non-negotiable: every design must respect info boundaries, deterministic iteration (BTreeMap), no player-special-casing |
| D-011 | Fog of perception | NPCs use the same LOS/perception system as player -- information boundaries are universal |
| D-024 | NPC 10 axes | Tell system, Secret, Contentment, Tolerance -- the axes that should be KG-aware but currently are not |
| D-028 | Dialogue architecture (four layers) | Layer 4 (unprompted disclosure) is the immediate Sprint 17 target. Knowledge grants must integrate with this pipeline |
| D-033 | Entity color from relationship | Color shifts on RelationshipState change -- downstream of contradiction detection |
| D-034 | THE FRIEND arc | The canonical contradiction sequence that drives the emotional centerpiece of v0.1 |
| D-035 | Tag taxonomy with prerequisites | Monologue prerequisite tags gate on knowledge state -- must align with grant mechanism |
| D-041 | Knowledge graph data model | The foundation -- data model is stable, this workshop fills the behavioral gaps |
| D-071 | Eavesdropping / ListeningFocus | Overheard info enters KG at lower confidence -- informs NPC overhearing rules |
| D-078 | Overheard NPC conversation | Server-authoritative occlusion filter, passive dialogue panel -- player-side of NPC conversations |
Workshop Topics
Topic 1: Knowledge Flow -- The Grant Mechanism
When an NPC tells the player something (dialogue) or the player discovers something (POI, evidence, overheard conversation), how does the knowledge graph get updated?
Sub-questions:
-
Wire
knowledge_granton dialogue lines. The YAML schema exists (KnowledgeGrant { fact_id, confidence }). TheIndexedDialogueLinefield exists but is alwaysNone. What triggers the grant -- line selection? Line display on client? Separate post-dialogue system? Who constructs theKnowledgeEventand whatKnowledgeEventTypevariant does it use? -
Entity knowledge vs fact knowledge in grants. Current
KnowledgeGrantonly hasfact_id(a string). Should grants also updateEntityKnowledgeentries? Example: Sera tells the detective "Kael handles cargo at Dock 7" -- this should create/update anEntityKnowledgeentry for Kael withsource: ToldBy { source_id: sera_sid }, not just a fact. DoesKnowledgeGrantneed anentity_grantvariant? -
POI discovery as knowledge flow.
PointOfInterest(#148) needs to enter the KG. Options: (a) newFactIdcategory "poi.*" (e.g.,FactId("poi.dock_7_restricted")), (b) extendEntityKnowledgeto cover locations, (c) separate POI knowledge type. Which integrates cleanest with existingfilter_by_accessand dialogue prerequisite checks? -
Physical evidence discovery (terminals, documents, cargo manifests). Same grant mechanism as dialogue? Or a separate
KnowledgeEventType::EvidenceDiscovered? -
Content author guardrails. What knowledge should NPCs be ABLE to grant? A content validation rule that prevents authors from accidentally making NPCs omniscient. Example: NPC can only grant facts that exist in their own KG. Authoring-time validation or runtime enforcement?
Feasibility note (Tyre): The event queue architecture (KnowledgeEventQueue) already handles this pattern cleanly. Adding a new KnowledgeEventType::KnowledgeGranted variant and a system that fires it post-dialogue-selection is a ~2-day task. The harder question is the schema design for multi-type grants (entity + fact).
Topic 2: NPC-to-NPC Knowledge Propagation (resolves Q-024)
When NPCs talk to each other, what knowledge transfers?
Sub-questions:
-
Confirm queued approach or revise. Q-024 preferred direction: queued at routine intersections. The conversation system (
run_npc_conversations,server/src/simulation/conversation.rsline 278+) IS a routine intersection -- NPCs start conversations when proximate during their routines. It already has proximity detection, cooldown timers, and deterministic pairing. Does this satisfy "queued at routine intersections" or do we need a separate system? -
Trust-gated filtering. NPC A has trust level T toward NPC B. What knowledge does A share at each trust level? Proposed mapping to D-028 trust tiers:
surfacetrust = share publicly-known facts only,realtrust = share observations and rumors,secrettrust = share sensitive knowledge. How does this map to theKnowledgeConfidencehierarchy? -
Confidence downgrade on transfer. When NPC A tells NPC B something, B's entry should be at a lower confidence than A's. Proposed:
ToldByconfidence =min(source_confidence, KnowsOf). Direct observation downgrades to KnowsOf when transferred.SuspectsstaysSuspects. This prevents gossip chains from producingKnowsDetailsknowledge. -
Rate limiting. How much knowledge per conversation? All eligible entries? Random subset? Fixed cap (e.g., 1-3 facts per conversation)? Cap prevents knowledge-explosion from a single NPC-NPC meeting.
-
Observable by player. If the player overhears an NPC-NPC conversation (D-078, occlusion filter), what do they learn? The player gets per-word-occluded text. Should the grant mechanism fire for the player based on what words survived occlusion? Or is overheard knowledge always at
Suspectsconfidence regardless of fidelity? -
ToldBy source construction. The
KnowledgeSource::ToldBy { source_id: StableId, tick: u64 }variant is defined but never constructed. This topic must produce the system that creates it. The source entity'sStableIdis already available in the conversation system (line 321:sid.map(|s| s.0.0).unwrap_or(u64::MAX)).
Feasibility note (Tyre): Tier 1 difficulty -- the conversation system already does the hard part (pairing, lifecycle, events). Adding a knowledge transfer phase between conversation start and conversation end is architecturally clean. The trust-gated filtering adds a query against both NPCs' KGs, which is O(log N) per entry. At ~50 entries per NPC and 1-3 transfers per conversation, this is sub-microsecond per conversation tick.
Topic 3: Unprompted Disclosure Design (#172)
NPCs volunteer information to the player without being asked. D-028 Layer 4.
Sub-questions:
-
Connection to NPC KG.
tell_state.rscurrently derives tell category from raw axis values (Secret, Tolerance, Contentment, Mood). #172 needs NPCs to volunteer INFORMATION, which requires knowing what they know. How does the tell derivation system connect to the NPC'sKnowledgeGraph? DoesDerivedTellStategain adisclosure_candidates: Vec<FactId>field? -
"Do I know something you don't?" Does the NPC check whether the player already knows a fact before volunteering it? Option A: NPC only checks own KG (simpler, may repeat known info -- but the NPC does not know what the player knows). Option B: NPC checks own KG vs player KG (requires cross-entity KG query, but prevents redundant disclosure). Option A is more realistic (NPCs do not know what you know). Option B is better UX. Which do we choose, or is there a middle ground?
-
Trait filtering (#173). Do personality/culture traits affect WHAT is disclosed (filtering -- a cautious NPC withholds certain facts) or HOW it is delivered (delivery -- same facts, different phrasing)? Or both? If "what": traits become a KG filter. If "how": traits become a line-pool modifier. If both: traits filter candidate facts, then modify the delivery of surviving candidates.
-
Trigger conditions. When does unprompted disclosure fire? Proposed: trust threshold met + mood permits + location appropriate + rate limit not exceeded. Which axes contribute? Contentment, trust toward player, mood state, presence of other NPCs (witnesses)?
-
Rate limiting. How often can an NPC volunteer info? Per-NPC cooldown? Per-fact cooldown (do not repeat the same fact)? Global rate limit across all NPCs (prevent disclosure spam)? Interaction with D-028 Layer 4 line cooldown (
LINE_COOLDOWN_TICKS= 600 ticks inserver/src/simulation/dialogue.rsline 39)?
Feasibility note (Tyre): Tier 2 difficulty. The dialogue pipeline exists and handles line selection well. The challenge is the "what to disclose" derivation -- this is new logic that sits between the KG and the line pool, and it needs to be both mechanically sound and narratively satisfying. Paula and Gestalt need to co-design the disclosure candidate selection before Dudley can implement.
Topic 4: NPC Information Boundaries (#142)
NPCs should use their own KnowledgeGraph for decisions, not ground truth.
Sub-questions:
-
Which NPC systems should be retrofitted? Priority order. Candidates:
npc/tell_state.rs-- tell derivation (currently uses axes directly, not KG)simulation/conversation.rs-- conversation partner selection (currently uses proximity, not knowledge of who is nearby)npc/routine.rs-- routine execution (currently usesDailyRoutinedirectly)simulation/path_follow.rs-- pathfinding (currently uses ground truth walkability)
-
Minimum viable boundary. What is the smallest retrofit that makes a gameplay-visible difference? Proposed: just
tell_state.rs+ unprompted disclosure (#172). An NPC that only reveals what it knows (via KG) is a meaningful boundary even if its pathfinding still uses ground truth. -
Simulation tier interaction (D-026). Background-tier NPCs (500-2000) have minimal KGs. Do they get simplified boundaries? Option: Background NPCs have no KG-based boundaries (they run state machines, not full AI). Only Active-tier NPCs (30-80) get KG-driven behavior. This is consistent with D-026's tiered simulation model.
-
What breaks? If
tell_state.rsreads from KG instead of raw axes: nothing breaks -- KG reflects observed state, which for an NPC's own axes is always up-to-date. Ifpath_follow.rsreads from KG: NPCs might "forget" where things are after decay, leading to stuck NPCs or nonsensical pathfinding. The fallback behavior matters. -
Fallback behavior. When an NPC's KG has no relevant information for a decision, what happens? Options: (a) fall through to ground truth (safe but breaks immersion), (b) use last-known state from KG (realistic but may cause stuck behavior), (c) trigger "ask around" behavior (NPC seeks information, creates emergent scenes). v0.1 recommendation: option (a) with logging, option (c) as future enhancement.
Feasibility note (Tyre): Tier 1 for minimum viable (tell_state + disclosure). Tier 3 for full retrofit (pathfinding + routine). Recommend starting with the MVP and expanding per sprint. The conversation system retrofit is Tier 2 -- it needs to check whether NPC A knows NPC B exists before initiating conversation, which adds a KG query to the pairing loop.
Topic 5: Contradiction Detection Pipeline (resolves Q-026)
The downstream consumers are built and tested. Design the detection algorithm.
Prerequisite: Topics 1 and 2 must produce ToldBy sources. Without ToldBy entries in KGs, there is nothing to contradict.
Sub-questions:
-
Location contradiction (simplest case). NPC says "X was at location A at time T" (
ToldBysource). Player observes X at location B at time T (DirectObservationsource). System detects: same entity, overlapping time window, different locations. Both entries receiveContradictedstate. -
Attribute contradiction. NPC says "X is trustworthy" (attribute in
known_attributes). Player discovers X is a smuggler (different attribute value for same key). How are attribute keys structured to enable comparison? Currentknown_attributes: BTreeMap<String, String>is untyped -- does contradiction detection need typed attribute keys? -
Content-authored vs automatic detection. Which contradictions are hand-authored ("fact A contradicts fact B" in content files) and which are algorithmic (same-subject different-value)? Proposed: location contradictions are automatic (algorithmic, based on position + time). Attribute contradictions are content-authored (explicit contradiction pairs in YAML). Fact contradictions are hybrid (some automatic categories, some authored).
-
Detection timing. When does contradiction detection run? Per-tick (expensive but immediate)? Per-game-minute (matches decay frequency)? On KG write (event-driven, only checks new entries against existing)? The event-driven approach is most efficient -- only fire detection when a
KnowledgeEventmodifies a relevant entry. -
Event emission chain. Detection fires
ContradictionDetectedevent containing: observer entity, contradicting entries (A, B), contradiction type. Downstream: monologue system triggers "Wait -- that does not add up" line. Relationship system shifts toPersonOfInterest. Anomaly marker set. D-033 color transitions amber. What is the exact event flow? -
THE FRIEND arc mechanical sequence. The canonical example from D-034: Sera tells detective "Kael was at the dock during second shift" -> detective observes Kael in corridor B-7 at that time -> location contradiction detected -> both entries Contradicted -> monologue: "Sera said Kael was at the dock. I just saw him in B-7." -> Sera shifts to PersonOfInterest -> amber color. Walk through this sequence and confirm every system fires correctly with the proposed design.
Feasibility note (Tyre): Location contradiction detection is Tier 1 -- BTreeMap lookup by StableId, compare positions within a time window. Attribute contradiction is Tier 2 -- needs typed attribute keys or content-authored pairs. The event-driven approach (check on KG write) keeps it off the per-tick hot path. Estimated: ~3 days for location detection + event chain, ~2 additional days for attribute detection.
What This Workshop Is NOT
- Not redesigning D-041. The data model is stable and works. Types, BTreeMap mandate, event queue, decay -- all ship-tested. This workshop fills behavioral gaps, not structural ones.
- Not full gossip implementation. The propagation design is Sprint 17+ dev work. This workshop produces the specification, not the code.
- Not resolving Q-017 (triangle pressure thresholds). Still deferred -- requires gameplay data.
- Not designing the full FRIEND arc narrative. That is Paula + Mellanie content work. This workshop defines the mechanical sequence that enables the narrative.
- Not addressing Q-025 in depth. Recommendation: close formally (not needed at current scale). If the workshop agrees, Qatux records the closure.
Expected Outputs
- Decision: D-0XX -- Knowledge Flow & NPC Information Boundaries. Comprehensive decision covering: grant mechanism schema, NPC-to-NPC propagation model, NPC boundary scope, contradiction detection algorithm. Resolves Q-024 and Q-026.
- Formal closure of Q-025 (not needed at current scale, re-evaluate at 500+ Active NPCs).
- Implementation scope for #141 -- remaining work list: wire
knowledge_grantfield through dialogue pipeline, constructKnowledgeEventon line selection, verifyfilter_by_accessintegration. - Implementation scope for #142 -- which systems to retrofit, priority order, minimum viable boundary, fallback behavior spec.
- Updated ticket descriptions for #172 and #173 -- mechanical specifications from the workshop: disclosure candidate selection algorithm, trait filter vs modifier decision, trigger conditions, rate limits.
- New tickets as needed -- knowledge propagation system, contradiction detection system, POI-KG integration,
KnowledgeEventTypevariants.
Workshop Format
Two rounds, following project convention:
- Round 1: Each participant independently analyzes all 5 topics from their domain perspective. Reference specific code files and line numbers. Tyre: system architecture, ECS patterns, performance budgets. Gestalt: mechanical interactions, "is this fun?", knowledge as gameplay lever. Dudley: Rust implementation feasibility, integration with existing systems, edge cases. Paula: what NPCs should say/know, THE FRIEND arc sequence, narrative consequences of design choices.
- Round 2: Cross-review, debate, synthesis into concrete decisions. Produce D-record(s), close Q-024/Q-025/Q-026, and generate implementation tickets with mechanical specifications.