Standardized YAML frontmatter on all 12 files. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
16 KiB
title, description, type, status, workshop, agent, round, created
| title | description | type | status | workshop | agent | round | created |
|---|---|---|---|---|---|---|---|
| Round 1 Notes — Knowledge Flow & NPC Information Boundaries Workshop | Qatux's Round 1 synthesis documenting consensus positions, tension points, and open questions across all four participants | workshop | archived | knowledge-flow-npc-boundaries | qatux | 1 | 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:
- Templated monologue lines with entity name substitution
- Hand-authored lines per NPC relationship phase (FRIEND pattern NPCs)
- 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:
KnowledgeGrantedevent type is the single mechanism for all knowledge input (dialogue grants, evidence, POI discovery)- Grant fires at line selection (server-authoritative, tick-deterministic)
FactId("poi.*")for POI discovery — no new type- NPC-to-NPC gossip piggybacked on conversation system; separate
transfer_npc_knowledgesystem (Bevy ECS dual-mutable constraint — Dudley's finding) - Confidence cap
min(source_confidence, KnowsOf)on all gossip transfers - Option A for unprompted disclosure (NPC checks own KG only)
- Traits act as two-stage filter: candidate pool (WHAT) + line delivery (HOW)
- MVP boundary: tell_state + disclosure; no pathfinding retrofit
- Contradiction detection event-driven at KG write; both entries marked
Contradicted - 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
EntityKnowledgestructural 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.