chore(meta): Sprint 17 planning — briefings, workshop brief, close Q-025

- 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>
This commit is contained in:
2026-02-23 23:25:08 +01:00
co-authored by Claude Opus 4.6
parent 41e3b4a9b3
commit abff69a632
7 changed files with 574 additions and 5 deletions
+4 -5
View File
@@ -139,11 +139,10 @@ Tracked questions awaiting discussion or resolution.
- **Source:** Knowledge Graph & Information Boundaries Workshop (Gestalt Round 1)
### Q-025: Knowledge graph cap and eviction strategy
- **Status:** Open
- **Question:** At what point does an NPC's knowledge graph need entry eviction? What is the eviction policy? Options: MAX_ENTITY_KNOWLEDGE constant (e.g., 100 entities), LRU by `last_observed_tick`, lowest confidence first, hybrid approach. How are evicted entries handled — complete removal, or archival to "forgotten" state that can be refreshed?
- **Context:** Memory budget analysis shows ~14 KB per NPC with 50 entities + 20 facts. At 80 Active NPCs this is ~1.1 MB, well within budget. However, long-running sessions or NPCs with high interaction rates could accumulate entries. Eviction policy affects gameplay: forgetting low-confidence rumors creates natural information decay; forgetting old observations simulates memory limits.
- **Assigned to:** Tyre, Dudley
- **Source:** Knowledge Graph & Information Boundaries Workshop (Dudley Round 1, section 8.3)
- **Status:** Resolved — not needed for v0.1/v0.2. Revisit if gossip propagation (Q-024) causes unbounded growth.
- **Question:** At what point does an NPC's knowledge graph need entry eviction? What is the eviction policy?
- **Resolution (2026-02-23):** The v0.1 Gauntlet has ~16 NPCs. At worst case (every NPC knows every other NPC + 50 facts), total KG memory is ~30 KB. The D-041 workshop estimate of ~1.1 MB for 80 Active NPCs still holds. `ToldBy` source (the only mechanism that could cause unbounded growth via gossip chains) is not yet implemented — NPC-to-NPC knowledge transfer does not exist. The existing decay system (`decay_knowledge` in `knowledge/events.rs`) downgrades confidence and marks entries `Stale` but does not remove them, which is correct behavior (preserves "I used to know X" for narrative). No cap or eviction is needed at current or projected v0.1 scale. If gossip propagation ships (Q-024) and causes growth concerns, the simplest eviction policy is: on each decay pass, if `entities.len() > MAX_ENTITIES`, remove `Stale` entries with lowest `last_updated_tick`. The BTreeMap makes this a clean O(N) scan.
- **Source:** Knowledge Graph & Information Boundaries Workshop (Dudley Round 1, section 8.3). Closed by architecture audit 2026-02-23.
### Q-026: Contradiction detection algorithm
- **Status:** Open
+60
View File
@@ -0,0 +1,60 @@
# Sprint 17: Tell — Client Tasks
**Goal:** NPCs volunteer information unprompted and express personality through delivery; the player can read time and orientation at a glance from the insert HUD; POI infrastructure lands on the server.
**Branch:** `client`
**Agents:** Stig (UI), Tyre (arch), Hoshe (QA)
## Carry-over from Sprint 16
None. Sprint 16 client tickets (#540, #543) will close before Sprint 17.
## New Tickets
| # | Title | Blocked by |
|---|-------|------------|
| #263 | Time display on insert HUD | — |
| #537 | UX: E-Talk overlay improvement | — |
Use `db/connectors/ticket show <id>` for full details.
## Key Decisions
- `decisions/perception.md` — D-019 (camera angle), D-033 (entity color)
- `decisions/architecture.md` — D-020 (Godot client + Rust server via IPC)
- `decisions/scope.md` — D-051 (diegetic insert/minimap)
## Notes
### #263 — Time display on insert HUD
**What exists:** The client has `client/scripts/ui/debug_overlay.gd` for debug display. The insert HUD concept is defined in D-051 but no insert UI code exists yet. `client/scripts/rendering/world_renderer.gd` handles the main rendering pipeline. The server sends `SimulationTime` data in `ObserverSnapshot` (see `server/src/bridge/types.rs`).
**What to deliver:** A diegetic time display on the player's insert/HUD. The player needs to know the current game time for routine-based investigation (NPC schedules, shift changes). Should show time in the station's local format, not abstract tick counts.
**Design dependency:** #314 (visual, this sprint) produces the insert/HUD wireframe. Coordinate with Araminta's output for placement and visual style. Can start with a placeholder layout and refine after the wireframe lands.
**Integration:** Reads `SimulationTime` from the snapshot. No new server work required — time data is already in the protocol.
### #537 — UX: E-Talk overlay improvement
**What exists:** The E-Talk interaction overlay appears when adjacent to an NPC. Playtester feedback says it doesn't communicate enough value — the overlay appears but doesn't convey what talking will accomplish or what access tier is available.
**What to deliver:** Improve the overlay to show: NPC name (if known from KG), relationship state color (from `RelationshipState` in snapshot), and a hint of available dialogue tier (surface/real/secret based on trust level). The goal is to make the player feel informed before committing to a conversation.
**Integration:** All data needed is already in `ObserverSnapshot` — the `VisibleEntity` includes `relationship` state and `known_attributes`. No server changes needed.
## Dependency Chain
```
#263 (Time display) → standalone
#537 (E-Talk UX) → standalone
Both can run in parallel.
```
## PR Workflow
When ready to submit, create a PR with `tea` CLI:
```bash
tea pr create --repo jpmschweitzer/settled-reach --login schweitz --title "feat(client): sprint 17 description" --description "body" --base main --head client
```
+66
View File
@@ -0,0 +1,66 @@
# Sprint 17: Tell — Copy Tasks
**Goal:** NPCs volunteer information unprompted and express personality through delivery; the player can read time and orientation at a glance from the insert HUD; POI infrastructure lands on the server.
**Branch:** `copy`
**Agents:** Mellanie (author), Paula (narrative), Gestalt (systems)
## Carry-over from Sprint 16
None. Sprint 16 copy ticket (#542, line ID migration) will close before Sprint 17.
## New Tickets
| # | Title | Blocked by |
|---|-------|------------|
| #330 | Diegetic tutorial monologue lines — per character | — (blockers #299, #300 done) |
Use `db/connectors/ticket show <id>` for full details.
## Key Decisions
- `decisions/content.md` — D-035 (tag taxonomy, monologue prerequisites), D-028 (dialogue architecture)
- `decisions/perception.md` — D-019 (camera and perception), D-011 (fog of perception)
## Notes
### #330 — Diegetic tutorial monologue lines — per character
**What exists:** Monologue pools at `content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/detective/` and `.../smuggler/` contain character-specific internal monologue. Opening monologue files exist (`opening.yaml` for both characters). The monologue system in `server/src/simulation/monologue.rs` fires lines based on triggers and prerequisites.
**What to deliver:** 8-10 monologue lines per character (smuggler + detective) that teach core mechanics diegetically:
- Movement and exploration ("These corridors all look the same. Mental note: check the signage.")
- Fog of perception ("Can't see past that corner. Might be worth checking.")
- Sound model ("Voices down the hall. Can't make out the words from here.")
- NPC interaction ("Could ask around. People talk if you give them reason to.")
- Insert/HUD usage ("Check the overlay. Should show the time and nearby contacts.")
Lines fire on first-time events (first move, first fog encounter, first sound heard, first NPC proximity, first insert open). Use `trigger: first_time_event` with appropriate event tags.
**Voice consistency:** Smuggler lines should be observational, street-smart, practical. Detective lines should be analytical, procedure-oriented, careful. Both stay in-character — tutorials are disguised as natural inner thoughts, not fourth-wall-breaking instructions.
**Prerequisite format:** Per D-035:
```yaml
- id: pc-smuggler_m_s_tut_001
text: "Voices. Down the corridor. Can't tell how many."
trigger: first_sound_heard
priority: tutorial
cooldown: -1
```
Use `_tut_` in IDs to distinguish tutorial lines from narrative monologue.
**Note on PC monologue ID collision (Q-028):** The review of PR #59 flagged that PC monologue IDs collide across location files. Use the `_tut_` discriminator for tutorial lines. Q-028 will resolve the broader scheme.
## Dependency Chain
```
#330 (Tutorial monologue) → standalone, no deps
```
## PR Workflow
When ready to submit, create a PR with `tea` CLI:
```bash
tea pr create --repo jpmschweitzer/settled-reach --login schweitz --title "feat(content): sprint 17 description" --description "body" --base main --head copy
```
+80
View File
@@ -0,0 +1,80 @@
# Sprint 17: Tell — Joint Tasks
**Goal:** NPCs volunteer information unprompted and express personality through delivery; the player can read time and orientation at a glance from the insert HUD; POI infrastructure lands on the server.
## Pre-Sprint: Knowledge Flow & NPC Boundaries Workshop
**Brief:** `docs/workshops/knowledge-flow-npc-boundaries/workshop-brief.md`
**Participants:** Tyre (arch), Gestalt (mechanics), Dudley (impl), Paula (narrative), Qatux (docs)
**Timing:** After Sprint 16 closes, before Sprint 17 starts
### Topics and Sprint Impact
| Topic | Resolves | Feeds tickets |
|-------|----------|---------------|
| 1. Knowledge grant mechanism | #141 remaining gap | #172, #149 |
| 2. NPC-NPC knowledge propagation | Q-024 | #172 |
| 3. Unprompted disclosure design | — | #172, #173 |
| 4. NPC information boundaries | #142 | #172 |
| 5. Contradiction detection pipeline | Q-026 | Future (THE FRIEND arc) |
### Expected Outputs
- **D-record** resolving Q-024 and Q-026
- Implementation scope for #141 (wire `knowledge_grant`) and #142 (NPC boundary retrofit priority)
- Mechanical spec for #172 unprompted disclosure
- Updated ticket descriptions for #172 and #173
**#172 is blocked until workshop completes.** Other server tickets can start in parallel.
## Pre-Sprint Decisions
| Decision | Who | Blocks |
|----------|-----|--------|
| Workshop Topics 1-5 | Tyre, Gestalt, Dudley, Paula | #172, #173 |
| Q-028: Collision-resistant line IDs | Gestalt, Tyre | Copy authoring conventions |
## Cross-Team Integration Points
| Server ticket | Client ticket | Integration |
|---------------|---------------|-------------|
| #148 POI data model | #263 Time display | POI data feeds future minimap; time data already in snapshot |
| #232 Protocol versioning | All client | Client must handle version field in messages |
| #172 Unprompted disclosure | #537 E-Talk UX | Disclosure lines appear in dialogue UI; E-Talk overlay should hint at NPC willingness |
| Server ticket | Visual ticket | Integration |
|---------------|---------------|-------------|
| #148 POI data model | #314 Insert/HUD wireframe | POI categories must match wireframe's display elements |
## Sprint Completion Proof
Sprint 17 is **DONE** when:
1. **Unprompted disclosure fires** — An NPC with high trust and relevant knowledge volunteers information to the player without being asked. The volunteered line appears in the dialogue UI. The player's KnowledgeGraph gains a new fact via `knowledge_grant`.
2. **Trait modifiers reshape delivery** — Two NPCs with different personality traits deliver the same base information differently (different mood, different wording or selection weight).
3. **Time is visible** — The insert HUD shows current game time in a diegetic format. Time advances visibly as ticks pass.
4. **POIs exist on the map** — Server spawns POI entities with the `PointOfInterest` component. POIs can be discovered via walking into a location (physical discovery).
5. **Protocol version field exists** — All messages include a version field. Client logs a warning on version mismatch.
6. **E-Talk overlay is informative** — The interaction overlay shows NPC name (if known), relationship color, and a dialogue tier hint.
7. **Insert wireframe is specified** — Both smuggler and detective variants are wireframed with layout, colors, and interaction states documented.
8. **Tutorial monologue fires** — First-time events (move, fog, sound, NPC proximity) trigger diegetic tutorial lines for both characters.
## Test Plan (D-030 alignment)
Sprint 17 is in the **integration testing** phase (Sprints 3-4 per D-030):
- **#172 + #173:** Integration test — NPC with specific axis values and KG state triggers unprompted disclosure; trait modifier changes the selected line.
- **#148 + #149:** Unit tests for POI component CRUD; integration test for discovery event → KG update.
- **#232:** Unit test for version serialization roundtrip; integration test for version mismatch handling.
- **#263:** Manual verification — time display updates as simulation advances.
- **#537:** Manual verification — overlay shows correct NPC data.
- **#330:** Line preview test — tutorial lines fire on first-time triggers, respect cooldown -1 (fire once).
## Teams
| Team | Branch | Agents | Tickets |
|------|--------|--------|---------|
| server | `server` | Dudley, Tyre, Hoshe | #172, #173, #232, #148, #149 |
| client | `client` | Stig, Tyre, Hoshe | #263, #537 |
| copy | `copy` | Mellanie, Paula, Gestalt | #330 |
| visual | `visual` | Araminta | #314 |
+103
View File
@@ -0,0 +1,103 @@
# Sprint 17: Tell — Server Tasks
**Goal:** NPCs volunteer information unprompted and express personality through delivery; the player can read time and orientation at a glance from the insert HUD; POI infrastructure lands on the server.
**Branch:** `server`
**Agents:** Dudley (simulation), Tyre (arch), Hoshe (QA)
## Carry-over from Sprint 16
None. Sprint 16 server was 100% complete (4/4 done).
## New Tickets
| # | Title | Blocked by |
|---|-------|------------|
| #172 | Layer 4: Unprompted disclosure | — |
| #173 | Trait modifier system | — |
| #232 | Create protocol versioning scheme | — |
| #148 | POI data model | — |
| #149 | POI discovery system | #148 |
Use `db/connectors/ticket show <id>` for full details.
## Pre-Sprint Workshop
The **Knowledge Flow & NPC Boundaries** workshop runs before this sprint starts. Brief at `docs/workshops/knowledge-flow-npc-boundaries/workshop-brief.md`. Topics 1-3 directly inform #172 and #173:
- **Topic 1:** Knowledge grant mechanism — how dialogue grants facts to player KG
- **Topic 2:** NPC-to-NPC knowledge propagation (resolves Q-024)
- **Topic 3:** Unprompted disclosure design — how `tell_state.rs` connects to NPC KG
Wait for workshop decisions before starting #172. #148, #149, #232, and #173 can start in parallel.
## Key Decisions
- `decisions/content.md` — D-028 (dialogue architecture, four relational layers), D-024 (NPC 10 axes), D-035 (tag taxonomy)
- `decisions/architecture.md` — D-041 (knowledge graph data model), D-010 (information boundaries), D-020 (engine architecture)
- `decisions/perception.md` — D-033 (entity color from relationship)
## Open Questions to Resolve Early
- **Q-024: Gossip propagation timing** — Resolved by workshop. Feeds #172 implementation.
- **Q-026: Contradiction detection** — Resolved by workshop. Not directly Sprint 17, but workshop output constrains #172 design.
## Notes
### #172 — Layer 4: Unprompted disclosure
**What exists:** `server/src/npc/tell_state.rs` derives tell state from NPC axis values (Secret, ToleranceThreshold, Contentment, MoodState, Relationships). The `TellState` component tracks willingness to volunteer info. `server/src/simulation/dialogue.rs` has the D-028 four-layer pipeline (Layer 1: access tier, Layer 2: situation, Layer 3: trust-gated gossip). Layer 4 is unimplemented.
**What to deliver:** A system that checks NPC `TellState` + `KnowledgeGraph` to select information the NPC wants to volunteer. This is NOT player-initiated — the NPC decides to speak based on mood, trust, and what they know. Workshop Topic 3 will define the trigger conditions and candidate selection algorithm.
**Key gap from audit:** `tell_state.rs` does NOT query the NPC's own `KnowledgeGraph`. NPCs currently operate on ground truth. Workshop Topic 4 (NPC boundaries) will determine the minimum retrofit scope. At minimum, #172 needs `tell_state.rs` to read `&KnowledgeGraph` to know what the NPC can share.
**Integration:** Uses `knowledge_grant` on dialogue lines to give player new facts. Workshop Topic 1 defines the grant schema.
### #173 — Trait modifier system
**What exists:** `server/src/npc/mod.rs` defines NPC components including personality axes per D-024. `server/src/content/line_pool.rs` has the `IndexedDialogueLine` struct with mood and tag fields. No trait-based line transformation exists.
**What to deliver:** A system where NPC personality traits reshape HOW lines are delivered, not per-trait scripts. Base lines exist in the pool; traits modify selection weight, delivery mood, or text variants. Workshop Topic 3 will clarify whether traits also affect WHAT is disclosed (filtering) or just delivery.
**Gotcha:** This must compose with Layer 3 (trust-gated, shipped Sprint 16) and Layer 4 (#172). Trait modifiers should operate as a scoring pass on the already-filtered candidate set, not as a separate filtering stage.
### #232 — Create protocol versioning scheme
**What exists:** `server/src/bridge/types.rs` defines `ObserverSnapshot` and all message types. `client/scripts/protocol/protocol.gd` deserializes them. No version field exists on any message. MessagePack encoding per D-020.
**What to deliver:** Version field in protocol messages, compatibility checking, migration strategy. This is infrastructure — no gameplay change.
**Standalone:** No dependencies on other sprint tickets or workshop output.
### #148 — POI data model
**What exists:** No POI system exists. The `KnowledgeGraph` has `BTreeMap<FactId, FactKnowledge>` for non-entity facts, but POIs are a new domain combining spatial position + knowledge.
**What to deliver:** `PointOfInterest` component with name, location, category, discovery source, visibility rules. This is an ECS component on map entities (bars, terminals, corridors, etc.). POIs feed into the minimap (#151, future) and insert HUD (#263, client Sprint 17).
**Design question:** Do POIs integrate with the knowledge graph as `FactId` entries (e.g., `poi.the_last_shift`), as entity knowledge via `StableId`, or as a separate system? Workshop Topic 1 touches this — POI discovery as knowledge flow.
### #149 — POI discovery system
**What exists:** Nothing. Depends on #148 POI data model.
**What to deliver:** System for learning POIs via: character background (starting knowledge), NPC tips (dialogue grants), research (terminal interaction), physical discovery (walking into a location). Each discovery source maps to a `KnowledgeSource` variant and confidence level.
**Integration:** This IS knowledge flow — uses the same `KnowledgeEventQueue` pattern. New `KnowledgeEventType` variant for POI discovery. Connects to the grant mechanism (Workshop Topic 1).
## Dependency Chain
```
#148 (POI data model) → #149 (POI discovery)
#172 (Unprompted disclosure) → blocked by workshop output
#173 (Trait modifiers) → standalone, parallel
#232 (Protocol versioning) → standalone, parallel
```
## PR Workflow
When ready to submit, create a PR with `tea` CLI:
```bash
tea pr create --repo jpmschweitzer/settled-reach --login schweitz --title "feat(server): sprint 17 description" --description "body" --base main --head server
```
+61
View File
@@ -0,0 +1,61 @@
# Sprint 17: Tell — Visual Tasks
**Goal:** NPCs volunteer information unprompted and express personality through delivery; the player can read time and orientation at a glance from the insert HUD; POI infrastructure lands on the server.
**Branch:** `visual`
**Agents:** Araminta (art direction)
## Carry-over from Sprint 16
None. Sprint 16 visual ticket (#540, sprite camera angle) will close before Sprint 17.
## New Tickets
| # | Title | Blocked by |
|---|-------|------------|
| #314 | Insert/HUD wireframe and spec — dual character variants | — (blocker #303 done) |
Use `db/connectors/ticket show <id>` for full details.
## Key Decisions
- `decisions/perception.md` — D-019 (camera and perception), D-033 (entity color palette)
- `decisions/scope.md` — D-051 (diegetic insert/minimap)
- `decisions/content.md` — D-024 (NPC 10 axes, relationship display)
## Notes
### #314 — Insert/HUD wireframe and spec — dual character variants
**What exists:** D-051 defines the diegetic insert/minimap concept. D-033 defines the entity color palette (Unknown teal, Known green, PersonOfInterest amber, Hostile red). No wireframe or visual spec exists yet for the insert overlay.
**What to deliver:** Wireframe and visual specification for the lattice overlay HUD with dual-character variants:
**Smuggler variant:**
- Social contacts displayed as dots using D-033 relationship colors
- Casual labels ("The Last Shift", "Kael's usual spot")
- Time display (feeds #263 client implementation)
- Informal, street-level aesthetic — the smuggler's network view
**Detective variant:**
- POIs as amber diamonds with formal labels
- Commission-style grid overlay
- Time display with shift indicators
- Analytical, procedural aesthetic — the detective's investigation tool
**Output format:** Wireframe images (PNG) + written spec document describing layout, color usage, typography, and interaction states. Use `/frame0-wireframe` if Frame0 is available, otherwise produce annotated mockups.
**Integration:** This spec directly feeds #263 (client, time display) and future #151 (minimap rendering). The client team needs placement coordinates and visual hierarchy from this spec.
## Dependency Chain
```
#314 (Insert/HUD wireframe) → standalone, informs #263 (client)
```
## PR Workflow
When ready to submit, create a PR with `tea` CLI:
```bash
tea pr create --repo jpmschweitzer/settled-reach --login schweitz --title "feat(visual): sprint 17 description" --description "body" --base main --head visual
```
@@ -0,0 +1,200 @@
# 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 `SoundEvent`s and `ConversationEvent`s 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:**
1. **Wire `knowledge_grant` on dialogue lines.** The YAML schema exists (`KnowledgeGrant { fact_id, confidence }`). The `IndexedDialogueLine` field exists but is always `None`. What triggers the grant -- line selection? Line display on client? Separate post-dialogue system? Who constructs the `KnowledgeEvent` and what `KnowledgeEventType` variant does it use?
2. **Entity knowledge vs fact knowledge in grants.** Current `KnowledgeGrant` only has `fact_id` (a string). Should grants also update `EntityKnowledge` entries? Example: Sera tells the detective "Kael handles cargo at Dock 7" -- this should create/update an `EntityKnowledge` entry for Kael with `source: ToldBy { source_id: sera_sid }`, not just a fact. Does `KnowledgeGrant` need an `entity_grant` variant?
3. **POI discovery as knowledge flow.** `PointOfInterest` (#148) needs to enter the KG. Options: (a) new `FactId` category "poi.*" (e.g., `FactId("poi.dock_7_restricted")`), (b) extend `EntityKnowledge` to cover locations, (c) separate POI knowledge type. Which integrates cleanest with existing `filter_by_access` and dialogue prerequisite checks?
4. **Physical evidence discovery** (terminals, documents, cargo manifests). Same grant mechanism as dialogue? Or a separate `KnowledgeEventType::EvidenceDiscovered`?
5. **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:**
1. **Confirm queued approach or revise.** Q-024 preferred direction: queued at routine intersections. The conversation system (`run_npc_conversations`, `server/src/simulation/conversation.rs` line 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?
2. **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: `surface` trust = share publicly-known facts only, `real` trust = share observations and rumors, `secret` trust = share sensitive knowledge. How does this map to the `KnowledgeConfidence` hierarchy?
3. **Confidence downgrade on transfer.** When NPC A tells NPC B something, B's entry should be at a lower confidence than A's. Proposed: `ToldBy` confidence = `min(source_confidence, KnowsOf)`. Direct observation downgrades to KnowsOf when transferred. `Suspects` stays `Suspects`. This prevents gossip chains from producing `KnowsDetails` knowledge.
4. **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.
5. **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 `Suspects` confidence regardless of fidelity?
6. **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's `StableId` is 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:**
1. **Connection to NPC KG.** `tell_state.rs` currently 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's `KnowledgeGraph`? Does `DerivedTellState` gain a `disclosure_candidates: Vec<FactId>` field?
2. **"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?
3. **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.
4. **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)?
5. **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 in `server/src/simulation/dialogue.rs` line 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:**
1. **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 uses `DailyRoutine` directly)
- `simulation/path_follow.rs` -- pathfinding (currently uses ground truth walkability)
2. **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.
3. **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.
4. **What breaks?** If `tell_state.rs` reads from KG instead of raw axes: nothing breaks -- KG reflects observed state, which for an NPC's own axes is always up-to-date. If `path_follow.rs` reads from KG: NPCs might "forget" where things are after decay, leading to stuck NPCs or nonsensical pathfinding. The fallback behavior matters.
5. **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:**
1. **Location contradiction (simplest case).** NPC says "X was at location A at time T" (`ToldBy` source). Player observes X at location B at time T (`DirectObservation` source). System detects: same entity, overlapping time window, different locations. Both entries receive `Contradicted` state.
2. **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? Current `known_attributes: BTreeMap<String, String>` is untyped -- does contradiction detection need typed attribute keys?
3. **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).
4. **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 `KnowledgeEvent` modifies a relevant entry.
5. **Event emission chain.** Detection fires `ContradictionDetected` event containing: observer entity, contradicting entries (A, B), contradiction type. Downstream: monologue system triggers "Wait -- that does not add up" line. Relationship system shifts to `PersonOfInterest`. Anomaly marker set. D-033 color transitions amber. What is the exact event flow?
6. **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
1. **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.
2. **Formal closure of Q-025** (not needed at current scale, re-evaluate at 500+ Active NPCs).
3. **Implementation scope for #141** -- remaining work list: wire `knowledge_grant` field through dialogue pipeline, construct `KnowledgeEvent` on line selection, verify `filter_by_access` integration.
4. **Implementation scope for #142** -- which systems to retrofit, priority order, minimum viable boundary, fallback behavior spec.
5. **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.
6. **New tickets as needed** -- knowledge propagation system, contradiction detection system, POI-KG integration, `KnowledgeEventType` variants.
## 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.