Standardized YAML frontmatter on all 12 files. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
227 lines
16 KiB
Markdown
227 lines
16 KiB
Markdown
---
|
||
title: "Round 1 Notes — Knowledge Flow & NPC Information Boundaries Workshop"
|
||
description: "Qatux's Round 1 synthesis documenting consensus positions, tension points, and open questions across all four participants"
|
||
type: workshop
|
||
status: archived
|
||
workshop: knowledge-flow-npc-boundaries
|
||
agent: "qatux"
|
||
round: 1
|
||
created: 2026-02-23
|
||
---
|
||
|
||
# Round 1 Notes — Knowledge Flow & NPC Information Boundaries Workshop
|
||
|
||
**Documented by:** Qatux
|
||
**Date:** 2026-02-23
|
||
**Sources:** tyre-round1.md, gestalt-round1.md, dudley-round1.md, paula-round1.md
|
||
|
||
---
|
||
|
||
## Summary
|
||
|
||
Four participants submitted Round 1 analyses across five topics: the grant mechanism (Topic 1), NPC-to-NPC gossip (Topic 2), unprompted disclosure (Topic 3), information boundaries (Topic 4), and contradiction detection (Topic 5). Consensus is strong on fundamentals. Two structural tensions require resolution in Round 2 before implementation can proceed.
|
||
|
||
---
|
||
|
||
## Consensus Positions (all four participants aligned)
|
||
|
||
### Topic 1: Grant Mechanism
|
||
|
||
| Position | Agreed by |
|
||
|----------|-----------|
|
||
| Grant fires at **line selection time**, server-side — not at client display | Tyre, Gestalt, Dudley, Paula |
|
||
| Single `KnowledgeGranted` event type; no separate `EvidenceDiscovered` variant | Tyre, Gestalt, Dudley, Paula |
|
||
| POI discovery uses `FactId("poi.*")` namespace; no new type | Tyre, Gestalt, Dudley, Paula |
|
||
| Physical evidence grants use `DirectObservation` source; dialogue grants use `ToldBy` — same event, different source | Tyre, Gestalt, Dudley, Paula |
|
||
|
||
### Topic 2: NPC-to-NPC Propagation
|
||
|
||
| Position | Agreed by |
|
||
|----------|-----------|
|
||
| Existing `run_npc_conversations` system is the correct hook; no separate propagation system | Tyre, Gestalt, Dudley, Paula |
|
||
| Confidence cap: `transferred_confidence = min(source_confidence, KnowsOf)` — `Direct`/`KnowsDetails` downgrade to `KnowsOf`, `Suspects` stays `Suspects` | Tyre, Gestalt, Dudley, Paula |
|
||
| Overheard NPC-NPC conversations grant player `Suspects` confidence regardless of word-level occlusion (D-078) | Tyre, Gestalt, Dudley, Paula |
|
||
| Rate limit: 1–3 facts per conversation (prevents knowledge explosion, creates asymmetry) | Tyre, Gestalt, Dudley, Paula |
|
||
|
||
### Topic 3: Unprompted Disclosure
|
||
|
||
| Position | Agreed by |
|
||
|----------|-----------|
|
||
| **Option A**: NPC checks own KG only when deciding what to disclose; no cross-entity KG query | Tyre, Gestalt, Dudley, Paula |
|
||
| Disclosure candidates stored in a **separate component** (`DisclosureCandidates` / `DisclosureCandidateList`), not added to `DerivedTellState` | Tyre, Gestalt, Dudley |
|
||
| Traits affect **both** what is disclosed (candidate filtering) AND how it is delivered (line-pool scoring) | Tyre, Gestalt, Dudley, Paula |
|
||
| Per-fact per-NPC cooldown prevents the same NPC disclosing the same fact twice | All four |
|
||
|
||
### Topic 4: NPC Information Boundaries
|
||
|
||
| Position | Agreed by |
|
||
|----------|-----------|
|
||
| MVP boundary = `tell_state.rs` + unprompted disclosure (#172); no other retrofits in v0.1 | Tyre, Gestalt, Dudley, Paula |
|
||
| Background-tier NPCs get no KG-driven behavior; scope to `With<ActiveSim>` | Tyre, Gestalt, Dudley, Paula |
|
||
| Pathfinding (`path_follow.rs`) must NOT be retrofitted in v0.1 — failure mode (stuck NPCs) has no safe recovery | Tyre, Gestalt, Dudley, Paula |
|
||
| Fallback on missing KG entry: ground truth with structured logging, not silent | Tyre, Gestalt, Dudley, Paula |
|
||
| tell_state reads self-knowledge from axis components directly; KG applies to OTHER-state only | Tyre, Gestalt (same conclusion, different framing) |
|
||
|
||
### Topic 5: Contradiction Detection
|
||
|
||
| Position | Agreed by |
|
||
|----------|-----------|
|
||
| Detection is **event-driven at KG write time** — fires in `observe_entity()` before overwrite, not per-tick scan | Tyre, Gestalt, Dudley, Paula |
|
||
| **Both** the `ToldBy` entry and the `DirectObservation` entry receive `KnowledgeState::Contradicted` (epistemic neutrality — the engine does not determine who is wrong) | Tyre, Gestalt, Paula |
|
||
| Event chain: KG write → `ContradictionDetected` → monologue → `AnomalyMarker` → relationship shift → D-033 amber. Downstream consumers already exist and are tested. | All four |
|
||
| Attribute contradiction requires **content-authored contradiction pairs** (YAML), not automatic string comparison | Tyre, Gestalt, Dudley, Paula |
|
||
| Location contradiction is **automatic**: position + time window (`CONTRADICTION_WINDOW_TICKS`) | Tyre, Gestalt, Dudley |
|
||
|
||
### Cross-cutting
|
||
|
||
| Position | Agreed by |
|
||
|----------|-----------|
|
||
| **Close Q-025** (KG memory pressure). Current budget ~14 KB per Active NPC, ~6 MB total at current scale. Not a constraint until 500+ Active NPCs. | Tyre, Gestalt, Dudley |
|
||
|
||
---
|
||
|
||
## Key Tensions Requiring Round 2 Resolution
|
||
|
||
### Tension A: Entity Grants — Sprint 17 vs Sprint 18
|
||
|
||
**The question:** Should `KnowledgeGrant` be extended to support entity-level grants (creating/updating `EntityKnowledge` entries via dialogue) in Sprint 17, or deferred to Sprint 18?
|
||
|
||
**Positions:**
|
||
|
||
| Participant | Position | Rationale |
|
||
|-------------|----------|-----------|
|
||
| **Tyre** | Sprint 17 — extend YAML schema to compound grant (facts + entities) | Architecture is clean; compound grant is the right shape; entity_ref resolves to StableId at content load via BTreeMap |
|
||
| **Gestalt** | Sprint 17 — three-type enum: `FactGrant`, `EntityGrant`, `Compound` | Entity grants are required to make `KnowledgeSource::ToldBy` constructible; this is the missing piece |
|
||
| **Paula** | Sprint 17 — critical prerequisite | Without entity grants, `ToldBy` EntityKnowledge is never created; contradiction detection in THE FRIEND arc **cannot fire** |
|
||
| **Dudley** | **Defer to Sprint 18** | Entity grants require a "name → StableId" content registry that doesn't exist; Sprint 17 can use structured FactIds instead (e.g., `FactId("entity.kael.location.second_shift_dock")`) |
|
||
|
||
**Dudley's Sprint 17 workaround:** Encode entity+attribute+location claims as structured `FactId` strings. Contradiction detection then matches against the `FactKnowledge` entry. Avoids the entity name registry problem.
|
||
|
||
**Paula's counter:** This workaround loses the `EntityKnowledge.last_known_position` and `ToldBy` source. Contradiction detection on THE FRIEND arc requires *both* entries in `EntityKnowledge` — the `ToldBy` entry from Sera's testimony, and the `DirectObservation` when the player sees Kael in B-7. A FactId workaround bypasses `EntityKnowledge` entirely and breaks the contradiction chain.
|
||
|
||
**Note for the record:** Tyre's Sprint 17 estimate is ~1.5 days (schema + content-load entity_ref registry). Dudley's concern is the missing registry infrastructure. This is the crux.
|
||
|
||
---
|
||
|
||
### Tension B: `EntityKnowledge` Structural Fix — `ContradictionClaim` vs `contradiction_basis` vs Option B attribute encoding
|
||
|
||
**The structural problem (agreed by all):** `KnowledgeGraph.entities` is `BTreeMap<StableId, EntityKnowledge>` — one entry per known entity. When `observe_entity()` writes a new `DirectObservation`, it overwrites the existing `ToldBy` source. The prior claim is lost. Contradiction detection has nothing to compare against.
|
||
|
||
**Three proposed solutions:**
|
||
|
||
| Participant | Proposal | Structural impact |
|
||
|-------------|----------|-------------------|
|
||
| **Tyre** | Add `contradicted_claim: Option<ContradictionClaim>` to `EntityKnowledge`. Detect at write time (Approach B): before overwriting, compare incoming vs current; if contradiction, set `Contradicted` + store prior claim in new field | Adds one optional struct field to `EntityKnowledge`. Zero breaking changes. |
|
||
| **Gestalt** | Add `contradiction_basis: Option<ContradictionBasis>` to `EntityKnowledge`. Same detection timing. Struct fields: `conflicting_source`, `conflicting_position`, `detected_at_tick` | Structurally identical to Tyre's proposal, different naming |
|
||
| **Dudley** | **Option B for Sprint 17**: encode position claims as structured attribute strings in `known_attributes` (`"claim.{tick}.position" = "{x},{y},{source_sid}"`). Contradiction detector parses these strings. Sprint 18: refactor to proper struct (Tyre/Gestalt's approach). | Zero schema change for Sprint 17. Acknowledged as "ugly but minimal impact." |
|
||
|
||
**Assessment:** Tyre and Gestalt are proposing the same architecture with different field names — they should align on naming in Round 2. Dudley's Option B is a pragmatic workaround that avoids Sprint 17 schema change at the cost of string-parsing brittleness and a Sprint 18 refactor obligation.
|
||
|
||
Paula does not take a position on implementation approach; defers to the engineers.
|
||
|
||
---
|
||
|
||
## Secondary Disagreements (lower priority, but noted)
|
||
|
||
### Topic 2: Major secret override on trust-gated sharing
|
||
|
||
**Paula** proposes a `disclosure_threshold_override` flag on individual KG entries — a per-entry "never share regardless of trust tier" mechanism for Major secrets (e.g., Kael will not disclose his ring membership even to his closest contact). No other participant mentions this. It is a design addition, not a conflict with existing positions.
|
||
|
||
**For the record:** This is a new design element not currently in the trust-tier model. It does not contradict Tyre, Gestalt, or Dudley's trust-mapping tables — it adds a pre-filter before the tier lookup.
|
||
|
||
### Topic 2: Trust-weighted rate limiting
|
||
|
||
**Paula** proposes trust-weighted fact counts (Surface: 0–1, Real: 1–2, Secret: up to 3). **Tyre, Gestalt, Dudley** propose a flat `rand.random_range(1..=3)`. No strong opposition in any direction. Paula's proposal adds a trust-tier dependency; the others prefer simplicity.
|
||
|
||
### Topic 3: Disclosure trigger — witness inhibition
|
||
|
||
**Gestalt** adds a witness inhibition gate: NPCs are less forthcoming with an audience nearby. **Paula** adds a **location privacy gate**: disclosure candidates tagged `private` will not fire at public locations (e.g., Sera won't confide at The Terminal). These are additive, not conflicting.
|
||
|
||
**Tyre and Dudley** do not address either condition. The team will need to specify the trigger gate list before Dudley can implement `process_unprompted_disclosure`.
|
||
|
||
### Topic 3: Global rate limit
|
||
|
||
**Tyre** and **Dudley** both support a global rate limit (1 disclosure per tick globally) to prevent simultaneous disclosure from multiple NPCs. **Gestalt** opposes it — argues the limit is invisible to the player and creates unintelligible competition between NPCs. **Paula** supports a light global limit as a degenerate-case safeguard. This is a 3-vs-1 split with Gestalt dissenting.
|
||
|
||
### Topic 5: Contradiction monologue content
|
||
|
||
**Paula** argues strongly that contradiction monologue lines must name the source entity explicitly ("Sera said Kael was at the dock — I'm looking at him in B-7"). A generic "that doesn't add up" line is insufficient for THE FRIEND arc. Proposes three options:
|
||
1. Templated monologue lines with entity name substitution
|
||
2. Hand-authored lines per NPC relationship phase (FRIEND pattern NPCs)
|
||
3. Generic fallback + authored override (Paula's preference)
|
||
|
||
This requires the monologue system to resolve `ToldBy.source_id` (StableId) to a displayable name via `EntityRegistry` + `NpcName` component. Gestalt flags this as an open question for Dudley to confirm. No other participant addresses it. **This is a content system requirement that must be resolved before Mellanie can author the contradiction monologue lines.**
|
||
|
||
### Topic 1: Runtime NPC KG guardrail
|
||
|
||
**Tyre**: 3-line runtime check in `process_knowledge_events` — NPC cannot grant facts not in its own KG; grants for unknown facts are dropped with `tracing::warn!`.
|
||
|
||
**Gestalt**: Runtime enforcement + content-load validation (build pipeline check).
|
||
|
||
**Dudley**: Runtime check is Tier 3 difficulty, **not Sprint 17 scope**; authoring-time validation only for Sprint 17.
|
||
|
||
**Paula**: Authoring-time check is mandatory for narrative integrity; agrees runtime is harder given dynamic KGs.
|
||
|
||
This is a scope decision: Dudley's position is the most conservative. Tyre's 3-line check is low-cost; Gestalt's build-pipeline check is moderate work. Team lead to decide Sprint 17 scope.
|
||
|
||
---
|
||
|
||
## Implementation Order (Dudley's recommendation, uncontested)
|
||
|
||
```
|
||
Topic 1 (KnowledgeGranted event + dialogue wire)
|
||
↓ enables
|
||
Topic 4 MVP (tell_state KG awareness — can parallel with Topic 1)
|
||
Topic 2 (NPC-to-NPC transfer — unblocks Topic 5)
|
||
↓ enables
|
||
Topic 5 (contradiction detection — requires ToldBy entries to exist)
|
||
Topic 3 (unprompted disclosure — requires workshop decisions + populated NPC KGs)
|
||
```
|
||
|
||
Tyre's total estimate: ~11 days across Topics 1–5, parallelizable after grant schema is agreed.
|
||
|
||
---
|
||
|
||
## Open Questions Raised This Round
|
||
|
||
| ID | Question | Raised by |
|
||
|----|----------|-----------|
|
||
| — | Entity grants Sprint 17 vs Sprint 18 (see Tension A) | Dudley (dissent) |
|
||
| — | `EntityKnowledge` structural fix approach (see Tension B) | Tyre, Gestalt, Dudley |
|
||
| — | `CONTRADICTION_WINDOW_TICKS` value — Gestalt proposes 600 (1 game-hour); Paula asks what narrative timeframe makes "contradiction not stale info" | Gestalt, Paula |
|
||
| — | `DisclosureCandidates` compute trigger — is there a "player entered dialogue range" event or does this need a range-query every N ticks? | Gestalt → Tyre to confirm |
|
||
| — | Monologue `StableId` → displayable name lookup — is `EntityRegistry + NpcName` available in monologue system context? | Gestalt → Dudley to confirm |
|
||
| — | Witness inhibition trigger (Gestalt) + location privacy trigger (Paula) — which conditions are in v0.1 trigger gate? | Requires team decision |
|
||
| — | Global disclosure rate limit — include or exclude? (3-vs-1 split: Tyre/Dudley/Paula for, Gestalt against) | Gestalt (dissent) |
|
||
| — | Contradiction monologue authoring — templated / hand-authored / hybrid? (Paula requires source-named lines) | Paula → Mellanie/team decision |
|
||
| — | Major secret `disclosure_threshold_override` on KG entries — include in trust-gate model? | Paula (new proposal) |
|
||
|
||
---
|
||
|
||
## Decisions This Round Is Producing (pending formal D-record after workshop closes)
|
||
|
||
The following are **forming consensus** — not yet D-records, but positions Round 2 should confirm or amend:
|
||
|
||
1. `KnowledgeGranted` event type is the single mechanism for all knowledge input (dialogue grants, evidence, POI discovery)
|
||
2. Grant fires at line selection (server-authoritative, tick-deterministic)
|
||
3. `FactId("poi.*")` for POI discovery — no new type
|
||
4. NPC-to-NPC gossip piggybacked on conversation system; separate `transfer_npc_knowledge` system (Bevy ECS dual-mutable constraint — Dudley's finding)
|
||
5. Confidence cap `min(source_confidence, KnowsOf)` on all gossip transfers
|
||
6. Option A for unprompted disclosure (NPC checks own KG only)
|
||
7. Traits act as two-stage filter: candidate pool (WHAT) + line delivery (HOW)
|
||
8. MVP boundary: tell_state + disclosure; no pathfinding retrofit
|
||
9. Contradiction detection event-driven at KG write; both entries marked `Contradicted`
|
||
10. Q-025 closure (formal record pending D-record production)
|
||
|
||
**Not yet forming consensus (blocked on Tensions A and B):**
|
||
- Entity grant schema and Sprint 17 scope
|
||
- `EntityKnowledge` structural fix approach
|
||
|
||
---
|
||
|
||
## Note to Participants
|
||
|
||
For the record: the downstream cascade from contradiction detection (anomaly marker, D-033 color shift, relationship shift to PersonOfInterest) is **already implemented and tested**. The entire narrative payoff of THE FRIEND arc is gated on two things: (1) `ToldBy` EntityKnowledge being constructible from dialogue grants, and (2) the `EntityKnowledge` structural fix that preserves the prior claim before overwrite. Everything else in Topics 3–4 is valuable but not blocking THE FRIEND arc for v0.1.
|
||
|
||
Paula's framing is correct: Tensions A and B are the session's critical path.
|