transfer_npc_knowledge system runs after conversations with trust-gated
fact exchange, confidence capping at KnowsOf, ToldBy source construction.
POI data model with PointOfInterest component and proximity-based discovery
via KnowledgeGranted events. Implements D-080. Closes Q-024.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
tell_state reads KG for other-entity relationship state (MVP boundary
per D-082). Contradiction monologue fires with pre-resolved entity names,
shifts ToldBy source to PersonOfInterest. Full THE FRIEND arc event chain.
Implements D-082 step 1, D-083 event chain.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Version field round-trip, mismatch detection, serde_default migration
pattern, all TellCategory and VerbKind variant coverage.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Heartbeat rule for agent spawn prompts (15-min progress check) and
team lead proactive checks (bottleneck detection pattern).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reviews must run from main. Added step 0 hard stop if current branch
is not main, preventing repeated misuse from team branches.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Well-structured 4700-line implementation. Knowledge graph core, contradiction detection, NPC-to-NPC transfer, POI discovery, and disclosure pipeline are all architecturally sound. Test coverage is thorough for happy paths and most edge cases. Two warning-level issues found.
#
File
Severity
Issue
1
server/src/knowledge/graph.rs:206-218
warning
record_incomplete_interaction creates new entries with KnowledgeSource::DirectObservation — walk-away from dialogue is not direct observation. Falsely inoculates entries against future contradiction detection (pre-overwrite check only fires when existing.source is ToldBy).
2
server/src/npc/disclosure.rs:123-199
warning
exclude_high_trust_entities (Loyal trait) is defined, configured, and tested via any_excludes_high_trust, but derive_disclosure_candidates never calls the filter. Loyal trait silently has no effect on disclosure.
3
server/src/simulation/monologue.rs:453-464
suggestion
Wildcard arm _ => OBSERVE_NPC_LINES silently returns wrong lines for unknown trigger strings. Add tracing::warn! on the default arm.
4
server/src/npc/disclosure.rs:394-397
suggestion
process_unprompted_disclosure re-queries npc_query mutably after read pass. Pattern is fragile — consider extracting mutable cooldown update or adding explicit borrow-sequencing comment.
5
server/src/npc/trait_modifiers.rs:192-203
suggestion
parse_confidence duplicates KnowledgeConfidence::try_from but only accepts underscore forms. Should delegate to try_from instead.
Comment says "draw 1–3 entries randomly" but implementation always takes top-N by recency. Either update comment or implement random sampling.
Tyre (Architecture): APPROVE
Substantial, well-executed sprint implementing D-079 through D-083. Information boundaries are first-class, BTreeMaps used correctly for determinism, D-010 principles consistently upheld. Contradiction detection, NPC-to-NPC transfer, unprompted disclosure, and POI discovery all integrate cleanly without violating multiplayer-readiness baseline.
Dual-mutable KG access is correct, but one-directional transfer (A→B only) emergent behavior if conversations fire on both participants should be documented.
2
server/src/knowledge/graph.rs:171-177
suggestion
After contradiction, source rewritten to DirectObservation means subsequent observations don't re-trigger — intentional but undocumented. Add comment to prevent future "fix."
3
server/src/npc/disclosure.rs:~283
suggestion
candidates.first() always picks highest-priority fact — known simplification, worth a comment flagging it for Layer 4 line selection (#172).
4
server/src/simulation/dialogue.rs:677-709
suggestion
Entity grants have no NPC-knows-this-entity guardrail (unlike Fact grants). Correct per D-079 spec, but comment should explain why the asymmetry exists.
5
server/src/knowledge/mod.rs:40-44
suggestion
process_knowledge_events runs after snapshot → contradiction monologue lags by one tick (~0.1s). Not a bug, but worth a comment on ordering.
6
server/src/simulation/poi_discovery.rs:84-93
suggestion
Direct KG write bypasses event queue — justified for LOS discovery but breaks the unified KnowledgeGranted path from D-079. Document the carve-out.
Wildcard arm in select_hardcoded_fallback silently uses wrong lines for unrecognized triggers. Add tracing::warn!.
Verdict: CHANGES REQUESTED
Fixes needed:
record_incomplete_interaction — use a correct KnowledgeSource variant (not DirectObservation) for walk-away entries
Wire up exclude_high_trust_entities filter in derive_disclosure_candidates, or remove/stub it with a TODO if it's deferred
## Review: server → main (#63) — type: code
### Hoshe (Code Quality): REQUEST_CHANGES
Well-structured 4700-line implementation. Knowledge graph core, contradiction detection, NPC-to-NPC transfer, POI discovery, and disclosure pipeline are all architecturally sound. Test coverage is thorough for happy paths and most edge cases. Two warning-level issues found.
| # | File | Severity | Issue |
|---|------|----------|-------|
| 1 | `server/src/knowledge/graph.rs`:206-218 | warning | `record_incomplete_interaction` creates new entries with `KnowledgeSource::DirectObservation` — walk-away from dialogue is not direct observation. Falsely inoculates entries against future contradiction detection (pre-overwrite check only fires when `existing.source` is `ToldBy`). |
| 2 | `server/src/npc/disclosure.rs`:123-199 | warning | `exclude_high_trust_entities` (Loyal trait) is defined, configured, and tested via `any_excludes_high_trust`, but `derive_disclosure_candidates` never calls the filter. Loyal trait silently has no effect on disclosure. |
| 3 | `server/src/simulation/monologue.rs`:453-464 | suggestion | Wildcard arm `_ => OBSERVE_NPC_LINES` silently returns wrong lines for unknown trigger strings. Add `tracing::warn!` on the default arm. |
| 4 | `server/src/npc/disclosure.rs`:394-397 | suggestion | `process_unprompted_disclosure` re-queries `npc_query` mutably after read pass. Pattern is fragile — consider extracting mutable cooldown update or adding explicit borrow-sequencing comment. |
| 5 | `server/src/npc/trait_modifiers.rs`:192-203 | suggestion | `parse_confidence` duplicates `KnowledgeConfidence::try_from` but only accepts underscore forms. Should delegate to `try_from` instead. |
| 6 | `server/src/simulation/npc_knowledge_transfer.rs`:265-270 | suggestion | Comment says "draw 1–3 entries randomly" but implementation always takes top-N by recency. Either update comment or implement random sampling. |
### Tyre (Architecture): APPROVE
Substantial, well-executed sprint implementing D-079 through D-083. Information boundaries are first-class, BTreeMaps used correctly for determinism, D-010 principles consistently upheld. Contradiction detection, NPC-to-NPC transfer, unprompted disclosure, and POI discovery all integrate cleanly without violating multiplayer-readiness baseline.
| # | File | Severity | Issue |
|---|------|----------|-------|
| 1 | `server/src/simulation/npc_knowledge_transfer.rs`:199-210 | suggestion | Dual-mutable KG access is correct, but one-directional transfer (A→B only) emergent behavior if conversations fire on both participants should be documented. |
| 2 | `server/src/knowledge/graph.rs`:171-177 | suggestion | After contradiction, source rewritten to `DirectObservation` means subsequent observations don't re-trigger — intentional but undocumented. Add comment to prevent future "fix." |
| 3 | `server/src/npc/disclosure.rs`:~283 | suggestion | `candidates.first()` always picks highest-priority fact — known simplification, worth a comment flagging it for Layer 4 line selection (#172). |
| 4 | `server/src/simulation/dialogue.rs`:677-709 | suggestion | Entity grants have no NPC-knows-this-entity guardrail (unlike Fact grants). Correct per D-079 spec, but comment should explain *why* the asymmetry exists. |
| 5 | `server/src/knowledge/mod.rs`:40-44 | suggestion | `process_knowledge_events` runs after snapshot → contradiction monologue lags by one tick (~0.1s). Not a bug, but worth a comment on ordering. |
| 6 | `server/src/simulation/poi_discovery.rs`:84-93 | suggestion | Direct KG write bypasses event queue — justified for LOS discovery but breaks the unified `KnowledgeGranted` path from D-079. Document the carve-out. |
| 7 | `server/src/simulation/monologue.rs` (fallback lines) | suggestion | Wildcard arm in `select_hardcoded_fallback` silently uses wrong lines for unrecognized triggers. Add `tracing::warn!`. |
### Verdict: CHANGES REQUESTED
**Fixes needed:**
1. `record_incomplete_interaction` — use a correct `KnowledgeSource` variant (not `DirectObservation`) for walk-away entries
2. Wire up `exclude_high_trust_entities` filter in `derive_disclosure_candidates`, or remove/stub it with a TODO if it's deferred
record_incomplete_interaction now uses Heard/Close source instead of
DirectObservation, preventing false inoculation against contradiction
detection. Wired exclude_high_trust_entities (Loyal trait) filter into
derive_disclosure_candidates — facts from Friendly-relationship source
entities are excluded from disclosure pool.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- monologue.rs: tracing::warn on unrecognized trigger in fallback arm
- disclosure.rs: borrow-sequencing comment, first() simplification note
- trait_modifiers.rs: delegate parse_confidence to KnowledgeConfidence::try_from
- npc_knowledge_transfer.rs: fix misleading "draw randomly" comment,
document one-directional transfer behavior
- graph.rs: document intentional no-retrigger after contradiction
- dialogue.rs: explain entity grant guardrail asymmetry (D-079)
- knowledge/mod.rs: document one-tick monologue lag from system ordering
- poi_discovery.rs: document D-079 carve-out for direct KG write
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Sprint 17 server delivery — knowledge graph becomes a live system:
KnowledgeGrantuntagged enum (Fact + Entity),ContentEntityRegistry,KnowledgeGrantedevent processing at line selection time (D-079)ContradictionClaimstruct with 600-tick window inobserve_entity, epistemic neutrality (D-083)ToldBysource construction (D-080)868 tests passing, 0 failures. +4,699 lines across 26 files.
Tickets
#545, #546, #547, #548, #549, #550, #551, #148, #149, #173, #232
Decisions implemented
D-079 (grant architecture), D-080 (NPC propagation), D-081 (unprompted disclosure), D-082 (NPC boundaries MVP), D-083 (contradiction pipeline)
Test plan
Review: server → main (#63) — type: code
Hoshe (Code Quality): REQUEST_CHANGES
Well-structured 4700-line implementation. Knowledge graph core, contradiction detection, NPC-to-NPC transfer, POI discovery, and disclosure pipeline are all architecturally sound. Test coverage is thorough for happy paths and most edge cases. Two warning-level issues found.
server/src/knowledge/graph.rs:206-218record_incomplete_interactioncreates new entries withKnowledgeSource::DirectObservation— walk-away from dialogue is not direct observation. Falsely inoculates entries against future contradiction detection (pre-overwrite check only fires whenexisting.sourceisToldBy).server/src/npc/disclosure.rs:123-199exclude_high_trust_entities(Loyal trait) is defined, configured, and tested viaany_excludes_high_trust, butderive_disclosure_candidatesnever calls the filter. Loyal trait silently has no effect on disclosure.server/src/simulation/monologue.rs:453-464_ => OBSERVE_NPC_LINESsilently returns wrong lines for unknown trigger strings. Addtracing::warn!on the default arm.server/src/npc/disclosure.rs:394-397process_unprompted_disclosurere-queriesnpc_querymutably after read pass. Pattern is fragile — consider extracting mutable cooldown update or adding explicit borrow-sequencing comment.server/src/npc/trait_modifiers.rs:192-203parse_confidenceduplicatesKnowledgeConfidence::try_frombut only accepts underscore forms. Should delegate totry_frominstead.server/src/simulation/npc_knowledge_transfer.rs:265-270Tyre (Architecture): APPROVE
Substantial, well-executed sprint implementing D-079 through D-083. Information boundaries are first-class, BTreeMaps used correctly for determinism, D-010 principles consistently upheld. Contradiction detection, NPC-to-NPC transfer, unprompted disclosure, and POI discovery all integrate cleanly without violating multiplayer-readiness baseline.
server/src/simulation/npc_knowledge_transfer.rs:199-210server/src/knowledge/graph.rs:171-177DirectObservationmeans subsequent observations don't re-trigger — intentional but undocumented. Add comment to prevent future "fix."server/src/npc/disclosure.rs:~283candidates.first()always picks highest-priority fact — known simplification, worth a comment flagging it for Layer 4 line selection (#172).server/src/simulation/dialogue.rs:677-709server/src/knowledge/mod.rs:40-44process_knowledge_eventsruns after snapshot → contradiction monologue lags by one tick (~0.1s). Not a bug, but worth a comment on ordering.server/src/simulation/poi_discovery.rs:84-93KnowledgeGrantedpath from D-079. Document the carve-out.server/src/simulation/monologue.rs(fallback lines)select_hardcoded_fallbacksilently uses wrong lines for unrecognized triggers. Addtracing::warn!.Verdict: CHANGES REQUESTED
Fixes needed:
record_incomplete_interaction— use a correctKnowledgeSourcevariant (notDirectObservation) for walk-away entriesexclude_high_trust_entitiesfilter inderive_disclosure_candidates, or remove/stub it with a TODO if it's deferredRe-Review: server → main (#63) — Round 2
Hoshe (Code Quality): APPROVE
Both warning-level issues fixed. All 4 suggestions addressed. No new issues.
record_incomplete_interactionwrong sourceKnowledgeSource::Heard { Close }derive_disclosure_candidatestracing::warn!addedparse_confidenceduplicationtry_fromTyre (Architecture): APPROVE
All 7 suggestions addressed with inline comments and decision references. Fix commits architecturally sound.
Verdict: APPROVED
Pull request closed