Commit Graph
21 Commits
Author SHA1 Message Date
jpmschweitzerandClaude Opus 4.6 f31be6f866 feat(simulation): add routine deviation detection (#243)
RoutineDeviationEvent emitted when NPC breaks daily routine: wrong
location for day phase or wrong activity at correct location.
CurrentlyDeviating marker prevents duplicate events per episode.
Respects pathfinding-in-progress (no false positives). Feeds
observation event generator for observe_anomaly monologue triggers.
Primary detective mechanic per D-027 criterion 4.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 14:39:37 +01:00
jpmschweitzerandClaude Opus 4.6 029337a801 feat(simulation): add personality and tell system (#90)
TellCategory enum (Nervous, Angry, Friendly, Guarded, RoutineDeviation)
with DerivedTellState component. derive_tell_state system runs after
update_mood and detect_routine_deviation. Tell state derived from NPC
axis values per D-024: Secret+low Tolerance→Nervous, low Contentment+
Hostile→Angry, high Contentment+Friendly→Friendly, high Secret→Guarded.
v0.1 renderer is monologue text, not visual animation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 14:39:27 +01:00
jpmschweitzerandClaude Opus 4.6 78c43ab802 feat(simulation): add NPC generation pipeline (#92)
RoleDefinition struct + generate_npc() seeds all 10 D-024 axes via
SimRng for deterministic generation. Constraint validation: no duplicate
relationship targets, stress < threshold, one routine entry per phase,
no contradictory personality trait pairs. Spawns fully-populated NPC
entity with 2-3 personality traits for tell system (#90).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 14:39:17 +01:00
jpmschweitzerandClaude Opus 4.6 9a20e4dea9 feat(simulation): add tolerance threshold monitoring system (#105)
ToleranceBreachEvent emitted when NPC stress exceeds per-seed threshold.
ToleranceBreached marker prevents duplicate events per episode, cleared
on recovery. check_tolerance_threshold system runs after update_mood,
integrates with mood FSM to push toward Hostile/Anxious. Background-tier
NPCs excluded. Unblocks #250 (triangle escalation).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 14:39:08 +01:00
jpmschweitzerandClaude Opus 4.6 28e7e6d9ad feat(simulation): add NPC name masking with role labels and color index
Server-side infrastructure for information asymmetry in dialogue.
NPCs display role labels (Worker, Supervisor, Patron) instead of
real names until the player explicitly learns them via KG lookup.
NpcColorIndex (stable_id % 8) persists across name reveal.

ConversationEvent and DialogueResponseEvent carry display names +
color indices on the wire with serde(default) for compat.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 13:42:59 +01:00
jpmschweitzerandClaude Opus 4.6 f0e0673c99 fix(simulation): address PR #50 review — determinism, overflow, invariants
- Sort eligible NPCs by StableId for deterministic conversation pairing (D-010)
- Replace single_mut() with per-observer iteration (D-010 principle 3, D-027)
- Widen current_stress * 100 to i32 in mood derivation to prevent i16 overflow
- Promote line_interval to named constant LINE_INTERVAL_TICKS
- Add 4 Sprint 14 component invariants (MoodState, InteractionMemory,
  ActivityState+PathRequest exclusion, double-tagged tier detection)
- Attach MoodState to content spawn pipeline and gauntlet fixup
- VecDeque for InteractionMemory.notable_events (O(1) pop_front)
- Rename who_knows() to who_knows_full_scan() to communicate O(N) cost
- Add O(N^2) growth limit comment on conversation pair scan
- Document Suspicious/Focused as externally-set moods on enum variants

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 19:18:34 +01:00
jpmschweitzerandClaude Sonnet 4.6 8bd65a5662 feat(simulation): NPC-NPC relationship dynamics with passive decay (#103, D-024)
update_relationship_dynamics runs once per game-minute (10 ticks). Edges
inactive for 1+ game-hours (600 ticks) decay trust 1 point toward 0 per
minute. Creates social texture: NPCs who haven't interacted drift to neutral
without active maintenance. Blocks #249 (social propagation, Sprint 15).

Constants: DECAY_INTERVAL_TICKS=10, DECAY_INACTIVITY_THRESHOLD_TICKS=600,
DECAY_DELTA=1. Integer arithmetic only (D-010 determinism).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-20 18:52:36 +01:00
jpmschweitzerandClaude Sonnet 4.6 bd60b356f8 feat(simulation): routine execution system with ActivityState (#101, D-031)
ActivityState component tracks the activity an NPC is currently performing
at their routine destination (activity name, phase, started_tick). The
enter_activity system runs after movement validation and sets ActivityState
when an NPC has arrived with no active path. Cleared on phase transitions.

Feeds TellTrigger::DuringActivity and D-028 Layer 2 situation matching.
Unit tests verified via shift_change room integration.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-20 18:52:29 +01:00
jpmschweitzerandClaude Sonnet 4.6 dcd15a330f feat(simulation): interaction tracking + trust progression (#325, #324)
InteractionMemory component tracks interaction_count, last_interaction_tick,
and notable_events per NPC. Drives D-028 Layer 2 situation activation:
first_meeting (count==0) and repeated_visit (count>=3). warm_active in mood
system now derives from InteractionMemory within a 300-tick window.

Trust progression wired into dialogue systems: talk completion (+1),
walk-away (-1), confrontation (-2) emit TrustEvents consumed by update_trust.
InteractionEvent (WalkAway, Confrontation) recorded in notable_events for
fast per-pair access.

Adds FirstMeeting and RepeatedVisit Situation variants. 18 unit tests in
interaction.rs. All arithmetic integer-only (D-010 determinism). No HashMap.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-20 18:52:23 +01:00
jpmschweitzerandClaude Sonnet 4.6 9eba259fd5 feat(simulation): NPC mood state machine (#323, D-024, D-035)
8-state NPC mood FSM driven by stress, time of day, and interaction events.
Adds MoodState component, derive_mood() pure function, and update_mood() Bevy
system wired into NpcPlugin. Adds Focused as 9th Mood content tag (D-035
Sprint 8 amendment). Syncs CurrentMood for Layer 4 dialogue selection.

31 unit tests covering priority ordering, boundary conditions, and system
integration. All random values route through SimRng (D-010 determinism).
No floats. No HashMap.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-20 18:41:51 +01:00
jpmschweitzerandClaude Opus 4.6 03c44bebaf fix(simulation): address PR #42 review — 8 items from Hoshe and Tyre
1. Sound producers: document empty v0.1 pipeline explicitly (critical)
2. Routine tests: add ActiveSim to 3 tests that passed trivially
3. Rename _observer_pos → observer_pos (used at line 191)
4. Add FactionOnly positive test case (matching faction_id)
5. Fix stale doc comment "Current: 9" → 10 in ObserverSnapshot
6. Remove orphaned SimulationTier/LastInteraction/ScopeTag types
7. Add tracing::warn on FactionOnly non-numeric parse failure
8. Document Medium-range occlusion gap as TODO in audible_at
9. Insert SoundEventQueue in observer test setup_world

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 15:08:32 +01:00
jpmschweitzerandClaude Sonnet 4.6 8e00db2b2d feat(simulation): #94 #99 active tier filtering and transition system
#94 — Active tier simulation (complete):
- Add ActiveSim marker to all 9 test world room NPC spawns
- Fix test entities in routine.rs and path_follow.rs to include ActiveSim
  so With<ActiveSim> queries match correctly in unit tests

#99 — Tier transition logic (complete):
- Implement update_tier_markers system in tier.rs
- Promotes/demotes tier markers by manhattan distance from PlayerCharacter:
  ≤40 tiles → ActiveSim, ≤120 → BackgroundSim, beyond → StateSaved
- Handles cross-z-level as u32::MAX (effectively unreachable)
- No-op when no PlayerCharacter entity present (headless tests safe)
- 11 new unit tests covering all distance bands and boundary cases
- TierPlugin now registers the system after movement::validate_movement

Also picks up extended test coverage added by hoshe:
- observer/tests.rs — 230 lines of perception observer tests
- sound.rs — additional sound event integration tests

All 548 tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19 13:54:37 +01:00
jpmschweitzerandClaude Opus 4.6 066f8031fd feat(simulation): sprint 12 server — tier system, sound events, KG access, line previewer
Implements 4 completed tickets + partial progress on 2 more:

- #93 Tier marker components (ActiveSim, BackgroundSim, StateSaved + TierPlugin)
- #138 Information tag schema (ObserverAccess enum in knowledge/types.rs)
- #124 Sound event system (SoundEventEmitter, SoundEventQueue, bridge wiring)
- #193 Line previewer CLI (line_preview binary with filter/explain/sequence modes)
- #94 Active tier simulation (in progress — With<ActiveSim> filters)
- #139 Component-level access control (in progress — filter_by_access)

Updates snapshot fixtures and test golden files for new sound_events field.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 13:33:23 +01:00
jpmschweitzerandClaude Opus 4.6 273d29f26f feat(simulation): sprint 10 — hub teleport, confrontation response, walk-away phase 2, gauntlet rooms 4-7, blocked_entities debug field
#491: PlayerAction::TeleportToHub — moves player to hub spawn, clears
dialogue/monologue/interaction buffer, Gauntlet-only with log warning.
#520: ConfrontationDelivered event — Tier 2 animation shift, relationship
state decrement (D-033), monologue spike emission.
#519: Walk-away Phase 2 — NPC animation shift + routine deviation on
dialogue exit (D-064).
#498: Four new Gauntlet rooms — Interaction Gallery, Fog Theater, Crowd
Plaza, Dialogue Room with constants and wiring.
#514: blocked_entities Vec<u64> on ObserverSnapshot, protocol v9.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 12:58:14 +01:00
jpmschweitzerandClaude Opus 4.6 d4fdbf426e fix(server): address PR #23 review — 4 critical bugs, 3 warnings, 11 suggestions
Critical fixes:
- Add PendingRecognitionWire serialization roundtrip test
- Check Option return from delay.cancel() before logging
- InputQueue capacity limit (1000) with drop-oldest and warning
- TODO in observation.rs references ticket #450

Warning fixes:
- Hot-reload guards against invalid/empty content root
- Location header mismatch warning in line pool indexing
- walk_yaml() depth limit (100) against symlink loops
- Consecutive reload failure counter (warns after 5+)

Test additions:
- Negative prerequisite filtering test for monologue lines
- Integration test for pending_recognitions in observer snapshot
- Eavesdrop threshold ordering assertion (Careful < default)

Documentation:
- Playtesting expectation comments on delay constants
- is_pending() scalability note for future NPC cognitive delay
- ID format regex validation in line pool spec
- BTreeMap vs sort() ordering clarification in loader
- Multiplayer TODO in relationships.rs references D-010
- ContentSlug ticket #452 filed for entity slug resolution

394 tests, 0 failures.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 01:03:51 +01:00
jpmschweitzerandClaude Opus 4.6 d0663c4193 refactor(server): apply rustfmt and clippy suggestions
Formatting pass across simulation, perception, knowledge, NPC, and
test modules. Includes two clippy fixes in monologue.rs (.values()
instead of for (_, v) pattern).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 00:40:43 +01:00
jpmschweitzerandClaude Opus 4.6 267d415173 feat(simulation): implement content loader Phase 2 (#408)
Extend content loader to read and instantiate real YAML content into
ECS entities. 2-phase spawn pipeline: Phase 1 creates entities with
core components (Want, Tolerance, Contentment, Personality, Tells,
Skills), Phase 2 resolves cross-references (Relationships, Secrets,
Information via KnowledgeGraph, DailyRoutine).

Loads enums, entity attributes, pools, templates, triangles, and NPC
profiles. Handles stub files gracefully. 7 integration tests against
real content files plus edge case tests for invalid data.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 01:19:29 +01:00
jpmschweitzerandClaude Opus 4.6 2fd16f08b0 fix(server): address PR #14 review — ordering, docs, version pin
- Fix NpcPlugin system ordering: .before(compute_paths) instead of
  .after(advance_tick) so PathRequests are picked up same frame
- Fix stale doc comment in interpretation.rs: system runs BEFORE
  knowledge events, not after
- Add TODO(v0.2) on RelationshipGraph about information boundary
  limitation for multiplayer
- Document cardinal-only movement as deliberate v0.1 choice
- Add comment on manhattan_distance u32::MAX fallback for cross-z
- Pin pathfinding crate to 4.11

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 18:17:55 +01:00
jpmschweitzerandClaude Opus 4.6 3c04a0c568 feat(npc): add structured NPC data model, relationships, and daily routines
Implements tickets #86, #87, #88 for Sprint 3:
- Replace stub string/f32 NPC fields with typed enums and integer
  types for D-010 determinism (WantKind, SecretSeverity, Skill, etc.)
- Add RelationshipGraph global resource with BTreeMap<(StableId,
  StableId), RelationshipEdge> for efficient prefix queries
- Add DailyRoutine with phase-based RoutineEntry and PreviousDayPhase
  resource for detecting day-phase transitions
- Create NpcPlugin that initializes relationship graph, day-phase
  tracking, and registers check_phase_transition system

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 17:51:15 +01:00
jpmschweitzerandClaude Opus 4.6 6bda4a7620 fix(simulation): address PR #2 review findings
- Fix Cargo.toml edition 2024 → 2021 (Hoshe #1)
- Switch test runner to cargo-nextest in Makefile (Hoshe #2, D-030)
- Add debug_assert tick ordering enforcement in InputQueue::push (Hoshe #4)
- Add DayPhase Serialize/Deserialize derives (Tyre #6)
- Add day phase boundary comments clarifying half-open ranges (Hoshe #3)
- Add phase duration adjustability comment (Tyre #5)
- Document ObserverSnapshot planned fields as TODO (Tyre #1)
- Document entity_id as wire-format ID, not ECS Entity (Tyre #2)
- Change Relationship.target_name to target_id: u64 (Tyre #3)
- Clarify single app.update() is intentional boilerplate (Hoshe #8, Tyre #7)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 17:53:01 +01:00
jpmschweitzerandClaude Opus 4.6 f67caf1986 feat(server): initialize Rust/bevy_ecs simulation server
Server boilerplate epic (276) complete. Establishes the Rust simulation
server foundation per D-020 (subprocess/IPC architecture).

Structure:
- bevy_ecs 0.18 + bevy_app 0.18, MessagePack serialization (rmp-serde)
- SimulationPlugin with deterministic resources: SimulationTime (D-031),
  SimRng (D-030), InputQueue (D-010)
- Core IPC types: ObserverSnapshot, PlayerInput, SimBridge trait (D-020)
- CauseChain production component for provenance tracking (D-030)
- SimulationTier types with LRU eviction support (D-026)
- NPC 10-axis model components (D-024)
- 15 tests: inline unit tests + integration smoke/serialization tests
- make ci-server passes (clippy, fmt, build, test)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 16:54:40 +01:00