Files
settled-reach/docs/workshops/knowledge-flow-npc-boundaries/round-1-notes.md
T
jpmschweitzerandClaude Opus 4.6 60ffe2e02a docs(docs): add frontmatter to knowledge-flow-npc-boundaries workshop
Standardized YAML frontmatter on all 12 files.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 23:40:44 +01:00

16 KiB
Raw Blame History

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: 13 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: 01, Real: 12, 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 15, 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 34 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.