fix(simulation): address PR #39 review — 3 warnings + 6 suggestions

Warnings fixed:
- contraband.rs: scan event now always emits even when NPC already
  knows (was skipped by early `continue`). Contract matches doc.
- test_world/mod.rs: ScanEventBuffer added to player spawn bundle
  so check_contraband_scan doesn't silently no-op in gauntlet mode.
- npc/mod.rs → simulation/mod.rs: moved check_contraband_scan
  registration to SimulationPlugin (operates on player inventory and
  snapshot pipeline, consistent with process_talk_interaction).

Suggestions addressed:
- cross_room_transitions.rs T1: clarified standalone position vs
  constants.rs observer position in comment.
- dialogue.rs: Vec<&str> dedup replaced with BTreeSet<&str> for
  deterministic iteration (project convention).
- contraband.rs: added test for multiple simultaneous ScanAuthority
  NPCs in range (564 tests total).
- dialogue.rs: doc-comment on relationship_to_trust explaining
  KnowledgeConfidence ordering and Suspects default.
- cross_room_transitions.rs T5: noted direct KG API usage vs full
  perception system.
- sprint_gauntlet.rs: documented intentional Contentment { level: 0 }.
- content_scaling.rs: noted GAUNTLET_NPC_COUNT is manually maintained.
- contraband.rs: doc-comment on cross-plugin registration rationale.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-19 12:23:02 +01:00
co-authored by Claude Opus 4.6
parent bee93963d9
commit 258b266f15
8 changed files with 135 additions and 44 deletions
+20 -4
View File
@@ -15,6 +15,8 @@
//! - Writes DialogueResponseBuffer for snapshot inclusion
//! - Uses SimRng for deterministic weighted random selection
use std::collections::BTreeSet;
use bevy_ecs::prelude::*;
use rand::Rng;
@@ -177,6 +179,19 @@ pub fn available_access_tiers(relationship: RelationshipState) -> Vec<AccessTier
/// - Secret: Friendly + KnowsDetails+ (deep rapport + actionable knowledge)
/// - Real: (Friendly or Known) + KnowsOf+ (rapport + substantive knowledge)
/// - Surface: everything else (baseline, always available)
/// Map relationship + knowledge confidence to trust tier (D-075).
///
/// Trust tier gates which dialogue lines are available. The layered gate
/// requires BOTH sufficient relationship AND sufficient KG confidence:
/// Surface: any relationship, any confidence (baseline)
/// Real: (Friendly|Known) + KnowsOf+ (rapport + substantive knowledge)
/// Secret: Friendly + KnowsDetails+ (deep rapport + actionable knowledge)
///
/// KnowledgeConfidence ordering is load-bearing here — the >= comparison
/// relies on the derive(PartialOrd) order: Suspects < KnowsOf < KnowsDetails < Direct.
///
/// Unknown NPCs (no KG entry) default to Suspects, yielding Surface tier.
/// This is correct: you can't have deep dialogue with someone you know nothing about.
pub fn relationship_to_trust(
relationship: RelationshipState,
confidence: crate::knowledge::types::KnowledgeConfidence,
@@ -383,6 +398,8 @@ pub fn process_talk_interaction(
let situations = derive_situations(time.day_phase(), relationship);
// Layer 3: Trust tier from relationship + confidence (D-075)
// Default to Suspects for unknown NPCs — no KG entry means no basis for
// deeper dialogue, which correctly yields Surface trust tier.
let confidence = target_stable
.and_then(|sid| observer_kg.confidence_of(&sid))
.unwrap_or(crate::knowledge::types::KnowledgeConfidence::Suspects);
@@ -390,7 +407,7 @@ pub fn process_talk_interaction(
// Query Layers 1-3: collect candidates across all available access tiers
let mut candidates: Vec<&IndexedDialogueLine> = Vec::new();
let mut seen_ids: Vec<&str> = Vec::new();
let mut seen_ids: BTreeSet<&str> = BTreeSet::new();
for access in &access_tiers {
let results = line_pool.0.query_dialogue(
@@ -401,9 +418,8 @@ pub fn process_talk_interaction(
trust,
);
for line in results {
// Deduplicate across access tiers
if !seen_ids.contains(&line.id.as_str()) {
seen_ids.push(&line.id);
// Deduplicate across access tiers (BTreeSet for deterministic iteration)
if seen_ids.insert(&line.id) {
candidates.push(line);
}
}