--- title: "Sprint 17 — Server Briefing" description: "Knowledge grant architecture, NPC-to-NPC propagation, unprompted disclosure, POI infrastructure" type: sprint status: archived sprint: 17 team: "server" --- # Sprint 17: Tell — Server Tasks **Goal:** NPCs volunteer information unprompted and express personality through delivery; the knowledge graph becomes a live system with grants, propagation, contradiction detection, and NPC information boundaries; POI infrastructure lands; protocol versioning ships. **Branch:** `server` **Agents:** Dudley (simulation), Tyre (arch), Hoshe (QA) ## Carry-over from Sprint 16 None. Sprint 16 server was 100% complete (4/4 done). ## Workshop Output The **Knowledge Flow & NPC Boundaries** workshop completed before this sprint. Outcomes at `docs/workshops/knowledge-flow-npc-boundaries/workshop-outcomes.md`. **Decisions registered:** D-079 (Grant Architecture), D-080 (NPC-to-NPC Propagation), D-081 (Unprompted Disclosure), D-082 (NPC Information Boundaries MVP), D-083 (Contradiction Detection Pipeline) **Questions closed:** Q-024 (gossip timing — conversation system hook), Q-025 (KG memory — not a concern at current scale), Q-026 (contradiction detection — event-driven at KG write time) **Team lead decision:** Entity grants ship in Sprint 17 (compound `KnowledgeGrant` enum with `Entity` variant, `ContentEntityRegistry` at NPC spawn). ## Tickets ### Knowledge Graph Infrastructure (Workshop Tickets) | # | Title | Priority | Blocked by | Est. lines | |---|-------|----------|------------|------------| | **#545** | KnowledgeGrant schema + ContentEntityRegistry | critical | — | ~120 | | **#546** | KnowledgeGranted event + handler | high | #545 | ~150 | | **#547** | ContradictionClaim struct + detection in observe_entity | high | #545 | ~160 + tests | | **#548** | NPC-to-NPC knowledge transfer system | high | #545, #546 | ~160 | | **#549** | tell_state.rs KG awareness — MVP boundary (#142) | high | #545 | ~35 | | **#550** | Contradiction monologue + event chain | high | #545, #546, #547, #548, #552 | ~90 | | **#551** | DisclosureCandidates + unprompted disclosure | high | #545, #546, #548 | ~220 | ### Stories (Acceptance Gates) | # | Title | Priority | Blocked by | |---|-------|----------|------------| | **#141** | Knowledge-based information gating | high | #546 | | **#142** | NPC information boundaries | high | #546, #548, #549 | | **#172** | Layer 4: Unprompted disclosure | high | #551 | | **#173** | Trait modifier system | high | — | ### Standalone | # | Title | Priority | Blocked by | |---|-------|----------|------------| | **#148** | POI data model | high | — | | **#149** | POI discovery system | high | #148 | | **#232** | Create protocol versioning scheme | high | — | Use `db/connectors/ticket show ` for full details. ## Dependency Chain ``` #545 (KnowledgeGrant schema) ─ CRITICAL ROOT ├─→ #546 (event + handler) │ ├─→ #548 (NPC-to-NPC transfer) │ │ ├─→ #551 (disclosure) → #172 (story gate) │ │ ├─→ #550 (contradiction monologue) ← also needs #547, #552 │ │ └─→ #142 (story gate) │ └─→ #141 (story gate) ├─→ #547 (ContradictionClaim) → #550 ├─→ #549 (tell_state KG) → #142 (story gate) │ Parallel tracks (no KG deps): #148 → #149 (POI) #173 (trait modifiers) #232 (protocol versioning) ``` **Critical path:** #545 → #546 → #548 → #551 → #172 **Parallel from day 1:** #547 (with #545), #549 (after #545), #148, #173, #232 ## Key Decisions - `decisions/perception.md` — D-079 (grant architecture), D-080 (NPC-to-NPC propagation), D-081 (unprompted disclosure), D-082 (NPC boundaries MVP), D-083 (contradiction detection) - `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) ## Implementation Notes ### #545 — KnowledgeGrant schema + ContentEntityRegistry **D-079.** Compound `KnowledgeGrant` enum with `Fact` and `Entity` variants via `#[serde(untagged)]`. `ContentEntityRegistry` resource (`BTreeMap`) populated at NPC spawn time. ~0.5 day infrastructure. This is the critical root — everything else depends on it. ### #546 — KnowledgeGranted event + handler **D-079.** New `KnowledgeEventType::KnowledgeGranted` variant. Fires at line selection time in `server/src/simulation/dialogue.rs`. Wires the `knowledge_grant` field on `IndexedDialogueLine` (`server/src/content/line_pool.rs` line 297) — currently `Option`, always `None`. ### #547 — ContradictionClaim struct + detection **D-083.** Add `contradicted_claim: Option` to `EntityKnowledge`. Detection fires in `observe_entity()` when: existing entry has `source: ToldBy`, position differs, and `|current_tick - told_tick| < CONTRADICTION_WINDOW_TICKS` (600 ticks). Parallel with #546. ### #548 — NPC-to-NPC knowledge transfer **D-080.** Separate `transfer_npc_knowledge` system (ECS borrow constraint — can't hold two mutable KGs in same system). Runs after `run_npc_conversations`. Trust-gated: Surface 0-1, Real 1-2, Secret 2-3 facts. Confidence capped at `KnowsOf`. Constructs `ToldBy` source. ### #549 — tell_state.rs KG awareness **D-082.** MVP information boundary. Add `Option<&KnowledgeGraph>` to tell_state query. NPC relationship reads come from KG (other-entity knowledge), self-knowledge stays on axes (always ground truth). ~35 lines, standalone after #545. ### #550 — Contradiction monologue + event chain **D-083.** `ContradictionDetected` event → monologue system triggers source-named line → relationship shifts to `PersonOfInterest` → `AnomalyMarker` set → D-033 amber color. Pre-resolve `source_display_name` into event payload. Depends on #552 (copy team authors the lines). ### #551 — DisclosureCandidates + unprompted disclosure **D-081.** `DisclosureCandidates` component (separate from `DerivedTellState`). Trigger gates: trust >= Surface, mood != Hostile, contentment >= -10, witness inhibition, location privacy. Three rate-limit layers: per-fact history, per-NPC 300-tick cooldown, global 1/10-tick StableId-ordered cap. Trait-based two-stage filter (what + how). ### #172 — Layer 4: Unprompted disclosure (story) Acceptance gate for #551. Verify: NPC with high trust and relevant knowledge volunteers information unprompted. Player's KG gains a new fact via `knowledge_grant`. ### #173 — Trait modifier system **D-081 two-stage design.** Stage 1: traits filter WHAT is disclosed (Cautious → KnowsDetails minimum, Gossipy → Suspects minimum). Stage 2: traits modify HOW (delivery mood, line selection weight). Composes with Layer 3 (trust-gated) and Layer 4 (#551). ### #148 / #149 — POI data model + discovery POIs enter KG as `FactId("poi.*")` namespace per D-079. `PointOfInterest` component with name, location, category, discovery source, visibility rules. Discovery via `KnowledgeEventType::KnowledgeGranted` with `Fact` variant. ### #232 — Protocol versioning Standalone infrastructure. Version field in protocol messages, compatibility checking, migration strategy. No gameplay change. ## 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 ```