Commit Graph
47 Commits
Author SHA1 Message Date
jpmschweitzerandClaude Sonnet 4.6 aa0d8ced37 feat(simulation): NPC-to-NPC conversation system (#247, D-078)
Implements server-authoritative per-word occlusion for NPC conversations.
ConversationEventBuffer drains into ObserverSnapshot each tick so the client
receives only words audible from the player's position. Updates test fixtures
to include the new conversation_events and conversation_ended fields.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-20 18:41:44 +01:00
jpmschweitzerandClaude Opus 4.6 dd1dd0feec fix(simulation): address PR #46 review — zone tests, doc accuracy, TBD comment
Add 3 zone enrichment tests to observer pipeline (tile inside zone,
tile outside zone, absent ZoneMap resource). Fix misleading Decay
Observatory doc comment that claimed Direct start when test starts at
KnowsDetails. Add production population TBD note on ZoneMap.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 18:22:48 +01:00
jpmschweitzerandClaude Opus 4.6 51abc3e3c1 feat(simulation): #523 add zone_id to ObserverSnapshot (D-077, protocol v11)
Server-tracked zone_id on VisibleTile for D-073 zone crossfade and
D-059 deep fog temperature tint. ZoneMap resource backed by BTreeMap,
observer enrichment in snapshot assembly. Backwards-compatible: v10
payloads deserialize with zone_id: None.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 18:10:06 +01:00
jpmschweitzer 4bdcc8c3fa Merge remote-tracking branch 'origin/ci'
# Conflicts:
#	client/tests/fixtures/msgpack/snapshot_boundary_tick_0.msgpack
#	client/tests/fixtures/msgpack/snapshot_boundary_tick_127.msgpack
#	client/tests/fixtures/msgpack/snapshot_boundary_tick_2b31m1.msgpack
#	client/tests/fixtures/msgpack/snapshot_boundary_tick_2b32.msgpack
#	client/tests/fixtures/msgpack/snapshot_boundary_tick_32767.msgpack
#	client/tests/fixtures/msgpack/snapshot_empty.msgpack
#	client/tests/fixtures/msgpack/snapshot_multi_entity.msgpack
#	client/tests/fixtures/msgpack/snapshot_one_npc.msgpack
#	client/tests/fixtures/msgpack/snapshot_player.msgpack
#	client/tests/fixtures/msgpack/snapshot_v2_full.msgpack
#	server/Cargo.toml
#	server/src/bridge/text_renderer.rs
#	server/src/bridge/types.rs
#	server/src/perception/observer/mod.rs
#	server/src/simulation/path_follow.rs
#	server/tests/bridge_ipc.rs
#	server/tests/bridge_tcp.rs
#	server/tests/gen_fixtures.rs
#	server/tests/serialization.rs
2026-02-19 15:35:56 +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 Opus 4.6 3d306b8a2b feat(ci): add tracing::instrument to heavy per-tick systems, fix stale protocol comment (#344, #527)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 14:55:00 +01:00
jpmschweitzerandClaude Sonnet 4.6 6a7dc915de feat(bridge): add rng_seed to ObserverSnapshot for deterministic replay (#527)
Adds rng_seed: Option<u64> to ObserverSnapshot. The WRONG button (#507) captures
inputs.jsonl and seed.txt for replay, but seed.txt was writing "unavailable"
because the server did not include the RNG seed in ObserverSnapshot.

Changes:
- bridge/types.rs: PROTOCOL_VERSION 9→10, rng_seed field with serde(default,
  skip_serializing_if = "Option::is_none") for backward compatibility
- perception/observer/mod.rs: inject Res<SimRng> into compute_observer_snapshot,
  populate rng_seed: Some(rng.seed()) each tick
- All test files: add rng_seed: None to ObserverSnapshot constructors
- tests/serialization.rs: bump protocol_version_constant assertion 9→10
- Regenerate msgpack fixtures and golden file for protocol v10

Completes the WRONG button capture loop: replays can now fully reproduce
observed bugs with the exact RNG seed from the capture.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19 14:15:34 +01:00
jpmschweitzerandClaude Sonnet 4.6 3248603838 feat(simulation): ban HashMap via clippy disallowed_types, fix violations (#343)
Adds server/.clippy.toml with disallowed-types for std::collections::HashMap
and std::collections::HashSet. HashMap iteration order is non-deterministic
and breaks deterministic simulation replay (D-030).

Changes:
- server/.clippy.toml: disallow HashMap and HashSet crate-wide
- simulation/movement.rs: WalkabilityMap.chunks and occupied map → BTreeMap;
  add PartialOrd+Ord to ChunkCoord, TilePosition, TilePresence
- simulation/monologue.rs: MonologueState.shown_ids → BTreeSet (simulation state)
- perception/shadowcast.rs: #![allow] — per-frame FOV scratch, iteration irrelevant
- perception/interpretation.rs: #![allow] — per-frame lookup table, key-only access
- perception/query.rs: #![allow] — sector_lookup is a per-frame read-only cache

Also applies cargo fmt to pre-existing format drift in contraband.rs,
dialogue.rs, test_world/mod.rs, and several integration tests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19 14:14:07 +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 9ea9fd2a74 feat(engine): add rng_seed to ObserverSnapshot for deterministic replay (#527)
Add rng_seed: Option<u64> to ObserverSnapshot (protocol v10). Populated
from SimRng state each tick. Completes the WRONG button capture loop —
seed.txt now writes a valid u64 instead of "unavailable", enabling
deterministic replay from bug reports.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 13:34:14 +01:00
jpmschweitzerandClaude Opus 4.6 0f5a990f82 feat(ci): ban HashMap in simulation crate via clippy (#343)
Add clippy::disallowed_types for std::collections::HashMap scoped to
the simulation crate. Replace HashMap with BTreeMap in movement.rs for
deterministic iteration order. Allow exception in perception/query.rs
where iteration order is irrelevant (per-frame scratch buffer).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 13:34:04 +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 Sonnet 4.6 d103e445e7 feat(simulation): contraband detection + dialogue confidence gate (D-075) (#425, #524)
Contraband detection (Task #425, D-065):
- New module: simulation/contraband.rs — NPC scan checks carried items
  against the KnowledgeGraph confidence gate. NPCs with Authority access
  can initiate a scan; scan outcome depends on item CarriedBy + KG entry.
- Adds ContrabandScanResult event type and ContrabanEntry component.
- Wired into simulation/mod.rs module list.

Dialogue confidence gate (Task #524, D-075 — OQ-18 resolution):
- relationship_to_trust() gains confidence parameter (KnowledgeConfidence).
- Trust tier mapping: (Friendly, KnowsDetails+)→Secret, (Friendly|Known,
  KnowsOf+)→Real, otherwise Surface. Access tier (Layer 1) unchanged.
- Caller process_talk_interaction passes observer KG confidence_of target.
- Resolves OQ-18: confidence co-gates TrustTier, not AccessTier.

Supporting changes:
- decisions/content.md: add D-075 (16 decisions, dated 2026-02-19)
- knowledge/types.rs: expose KnowledgeConfidence comparison helpers
- knowledge/registry.rs: minor API polish
- bridge/types.rs: ContrabandScanResult wire type
- bridge/text_renderer.rs: render contraband scan status
- perception/observer: include carried item count in snapshot
- npc/mod.rs: NPC scan range constant, authority flag

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19 11:12:24 +01:00
jpmschweitzerandClaude Opus 4.6 6c62e2228f test(simulation): sprint 10 — replay loading, content scaling, serialization v9, observer tests
#483: Replay loading in test-client — JSONL file loading, tick-scheduled
PlayerInput sending, 13 unit tests, 3 sample replay files.
#500: Content scaling test — baseline + extra NPC comparative, tick budget
assertion (D-026), determinism check across content packs.
#514: Serialization tests for protocol v9 — blocked_entities roundtrip,
backward compat (v5→v9, v8→v9), regenerated msgpack fixtures.
Observer perception tests for confrontation + walk-away mechanics.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 12:58:27 +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 d5a1f6dadb refactor(simulation): apply rustfmt formatting
Formatting-only changes across server source and test files.
No logic changes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 01:39:44 +01:00
jpmschweitzerandClaude Opus 4.6 b1fdeabb7c test(simulation): sprint 8 test suite — pause guards, registry, boundary, determinism
Add 50+ tests: pause guard suite (movement, unpause, roundtrip, stance,
interact, batch, tick_rate), EntityRegistry lifecycle (stale mapping,
re-register, unknown unregister), boundary value encode/roundtrip (41
values), encoding asymmetry (GDScript signed→Rust unsigned), malformed
batch rejection, determinism gauntlet (20-tick replay), per-fix
determinism unit tests, and recognition monologue integration tests.
Fix pause guard to block all actions except Pause/Unpause while paused.
Fixes #461-463, #466-469, #471-473, #479.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 17:41:33 +01:00
jpmschweitzerandClaude Opus 4.6 695d2ac843 feat(perception): anomaly detection and recognition monologue during delay
Add AnomalyMarker component and detect_anomalies() system that flags
entities with KG relationship PersonOfInterest or Contradicted state
for urgent cognitive delay (0.3s vs 0.6s normal). Add
trigger_recognition_monologue() that fires monologue at delay START
(when grey blob appears), not at completion — the monologue IS the
recognition process per D-060. Includes v0.1 fallback recognition
lines and cooldown tracking. Fixes #450, #451.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 17:41:14 +01:00
jpmschweitzerandClaude Opus 4.6 af8e20ab9a fix(simulation): determinism fixes — BTreeSet ordering, entity sort, mover sort
Replace HashSet with BTreeSet for visible_ids, sort visible_tiles by
coordinates, sort visible entities in snapshot by entity_id, and sort
movers by Entity bits in validate_movement. Required by D-010 principle 4
(deterministic simulation). Fixes #456, #457, #458.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 17:40:57 +01:00
jpmschweitzerandClaude Opus 4.6 d1aba3d554 fix(simulation): use non-blocking TCP to prevent game loop stall
read_framed() called read_exact() which blocked the entire bevy Update
schedule waiting for client input — no systems ran until a keystroke
arrived. Switch TcpStream to non-blocking mode so receive_inputs()
returns Ok(vec![]) on WouldBlock instead of blocking. Toggle to
blocking for snapshot writes (reliable delivery). Add 50ms frame
throttle (~20 ticks/sec) since the non-blocking loop would otherwise
spin. Downgrade input receive logging to trace, add error logging for
missing bridge resource and failed observer queries.

Fixes bug #1 (server never sends snapshots) and #2 (camera doesn't
center until first keystroke).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 23:25:45 +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 4d8fe996fc feat(perception): add cognitive delay system for fog recognition (#423)
New CognitiveDelay component buffers perception events before emitting
KnowledgeEvents. Normal delay: 6 ticks (0.6s), urgent: 3 ticks (0.3s).
Drain system runs after emit_observation_events, before process_knowledge_events.

Adds pending_recognitions to ObserverSnapshot (protocol v7) for client
fog entity visualization. Includes cancellation when entity leaves LOS.

Monologue fires during delay (not after) per D-060 — cross-system
wiring deferred to follow-up ticket #451.

Ref: D-060 (cognitive delay), D-031 (10 tps), D-059 (fog layers)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 00:41:08 +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 3d63a4f9f6 test(simulation): QA coverage for Phase 2 verbs, sprint suppression, occupancy, inventory
Add comprehensive test suites across sprint 6 systems:
- Phase 2 observer filter: Confront injection, archetype label relabeling,
  contradiction marking, POI priority ordering (12 tests)
- Sprint anomaly: detection during sprint, queue semantics, delay timing,
  D-055 visible-but-suppressed integration (7 tests)
- Wire format: Confront and CharacterArchetype msgpack roundtrip (4 tests)
- TilePresence: 4-layer coexistence on same tile (1 test)
- Inventory: Take/Place full roundtrip, capacity enforcement (3 tests)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 16:00:32 +01:00
jpmschweitzerandClaude Opus 4.6 df81b24cd1 feat(simulation): sprint anomaly double-take monologue (#428, D-055)
When sprinting past a Contradicted entity, queue a delayed retroactive
monologue that fires after ~1.5s: "Wait — something wasn't right back
there." SprintAnomalyQueue component with first-in-wins semantics.
Detection in observer pipeline, processing in monologue system.
Wire MovementProfile, Stance, and SprintAnomalyQueue into player spawn.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 16:00:20 +01:00
jpmschweitzerandClaude Opus 4.6 6ef7029707 feat(simulation): smuggler inventory — CarriedBy, Take/Place verbs (#424)
Implement physical inventory system per D-065:

- CarriedBy(StableId) component marks items as carried by an entity
- ItemName and InventorySlot components for display and slot assignment
- Take verb: removes TilePosition, adds CarriedBy + InventorySlot
- Place verb: removes CarriedBy + InventorySlot, adds TilePosition
- Observer snapshot populates player_inventory from carried items query
- Info boundary: carried items lack TilePosition, naturally excluded
  from all spatial queries (visibility, interactions) for other entities
- 9-slot capacity (3x3 grid per OQ-24), auto-assigns first free slot
- 8 new tests covering take, place, sequential slots, full rejection

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 15:44:37 +01:00
jpmschweitzerandClaude Opus 4.6 98f4cedc03 feat(simulation): Sprint 6 Touch — stance, tile presence, verbs, protocol v6
Implements the core Sprint 6: Touch systems across 5 tickets:

- #449 ObserverSnapshot v6: add player_stance (MovementStance) and
  player_inventory (Vec<InventoryItem>) wire fields with serde defaults
  for backward compatibility. Bump PROTOCOL_VERSION 5→6.

- #417 Stance system: Sprint/Walk/Careful/Crouch movement stance with
  tick-based speed (1/2/3/4 ticks per move), monologue rate multipliers,
  and PlayerMoveCooldown component. ToggleStanceUp/Down player actions.

- #420 TilePresence: posture-layer collision system allowing same-tile
  occupancy for different layers (Standing/Prone/Seated/Fixture).
  Layer-based collision in validate_movement.

- #421 ObjectType component: Readable/Container/Terminal/Door/Pickup/
  Furniture types with Phase 1 verb sets computed from type + proximity.

- #422 Phase 2 verb filter: KG-gated observer-side verb processing —
  POI priority flips, Confront injection at KnowsDetails+, contradiction
  marking, archetype-specific label relabeling (Smuggler/Detective).

217 unit tests + 17 integration tests passing. All MessagePack fixtures
regenerated for v6 wire format.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 15:38:59 +01:00
jpmschweitzerandClaude Opus 4.6 3c106aa2d0 feat(simulation): complete interaction and monologue pipelines (#413, #414, #415)
Three fixes to make the gameplay loop functional end-to-end:

- Add Interactable component to NPC spawn so E-prompt detection works
- Build monologue trigger system (enter_location + time_idle) with
  MonologueBuffer/MonologueState components, wire through ObserverSnapshot
  as current_monologue field, decode on client and display via HUD
- Change PlayerAction::Interact from unit to struct variant carrying
  optional target_entity_id and verb fields

Bumps protocol version from 4 to 5. Regenerates MessagePack fixtures.
All 200 tests pass (170 unit + 30 integration).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 19:23:47 +01:00
jpmschweitzerandClaude Opus 4.6 29c5003403 fix(simulation): add TileKind to VisibleTile wire protocol (#412)
Server was sending visible_tiles without tile type data, so the client
could not distinguish floor from wall in live mode. Add TileKind enum
(Floor/Wall/Door/Object) to VisibleTile, populated from WalkabilityMap
in the NaturalVision perception query. Update test fixtures to include
the new field. Uses #[serde(default)] for backward compatibility.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 02:07:19 +01:00
jpmschweitzerandClaude Opus 4.6 18d8253bfe refactor(server): decompose observer pipeline and fix interaction boundary
Extract visibility geometry into a separate system behind a
PerceptionQuery trait, enabling D-017 perception mode swapping.
Two-stage pipeline: compute_visibility_geometry writes to
VisibilityGeometry resource, compute_observer_snapshot reads it.

Remove KnowledgeGraph from compute_nearby_interactions (simulation
phase boundary violation). Verb availability stays in simulation;
POI-based priority adjustment moves to observer via
apply_poi_verb_priority helper.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 23:32:41 +01:00
jpmschweitzerandClaude Opus 4.6 02fa89b1d7 refactor(server): extract observer tests to separate file
Split observer/mod.rs (820 lines) into production code (244 lines) and
tests (480 lines). Reduces module size per Hoshe #3 review item.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 22:52:52 +01:00
jpmschweitzerandClaude Opus 4.6 6f9537fff3 refactor(server): NearbyInteractionBuffer from Resource to Component
Per-entity Component attached to PlayerCharacter instead of global
Resource. Makes the interaction buffer multiplayer-ready (D-009) —
each observer gets their own buffer without pipeline refactoring.

Updated all 8 files touching the buffer: system signatures, player
spawn bundles, and ~30 test spawn sites.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 22:52:47 +01:00
jpmschweitzerandClaude Opus 4.6 ba867564a8 fix(server): add error logging, protocol version, and architecture docs
- Replace silent Entity::to_bits() fallbacks with tracing::error in
  observer.rs and interaction.rs (makes unregistered entities loud)
- Add PROTOCOL_VERSION constant to types.rs, use in observer snapshot
- Document single-observer assumption on NearbyInteractionBuffer
- Document proximity-only (no LOS) limitation on compute_nearby_interactions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 21:22:34 +01:00
jpmschweitzerandClaude Opus 4.6 9943684f2c refactor(server): address PR #16 review feedback
Hoshe + Tyre review items:
- Use StableId consistently for wire entity_id (H4) across observer,
  observation, interpretation, and interaction systems
- Make NearbyInteractionBuffer.interactions private with take() (H1/H20)
- Add system ordering constraint for compute_nearby_interactions (H5)
- Panic on missing PlayerCharacter in input processing (H2)
- Remove redundant paused field from GameTime (Tyre8)
- Remove #[serde(default)] from nearby_interactions (H3)
- Change NearbyInteraction.distance from f32 to u32 (H8)
- Add sort stability for equal verb priorities (H6)
- Scope constants to pub(crate) (H7)
- Add debug_assert for last_observed_tick ordering (H10)
- Strengthen unregistered entity handling to debug_assert + error (H11)
- Document fractional tick accumulation (Tyre9)
- Extract collect_remembered_entities helper (Tyre2/H17)
- Add half_rate_no_drift_over_10000_frames test (H14)
- Add mid-range and deterministic sort tests (H15)
- Add fixture version assertion (H16)
- Regenerate msgpack fixtures for wire format changes

146 unit + 19 integration tests pass, zero clippy warnings.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 20:14:35 +01:00
jpmschweitzerandClaude Opus 4.6 2de413dd87 feat(simulation): add proximity detection and interaction verbs
Implement compute_nearby_interactions system that detects entities
within close (≤2) and mid (≤5) Manhattan distance, computes
available verbs per D-060 spec. NPCs get Talk+Observe at close
range, Observe-only at mid range; PersonOfInterest flips priority.
Objects get Examine. Results populate nearby_interactions[] on
ObserverSnapshot v4. Bump protocol version 3→4. Implements #404.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 19:48:55 +01:00
jpmschweitzerandClaude Opus 4.6 ad653cffc3 refactor(server): fix clippy warnings from Rust 1.93
- Use #[derive(Default)] + #[default] instead of manual Default impls
  for FacingDirection, KnowledgeState, RelationshipState, EntityVisibility
- Replace manual modulo check with .is_multiple_of()
- Collapse nested if in shadowcast symmetry check

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 18:18:04 +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 9c3c32e854 feat(perception): add observation event generator
Implements ticket #239 for Sprint 3:
- ObservationTrigger enum: RoutineDeviation (NPC not at expected
  routine location), Absence (expected location visible but NPC
  missing), NewEntity (unknown entity in LOS)
- ObservationEventQueue resource with push/drain/len/is_empty
- generate_observation_events system runs after emit_observation_events
  but before process_knowledge_events so it can compare current
  snapshot against previous-tick knowledge state
- Populate PerceptionPlugin with ObservationEventQueue resource and
  system registration with correct ordering constraints

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 17:52:02 +01:00
jpmschweitzerandClaude Opus 4.6 0b599ed662 feat(simulation): spawn 3 NPCs with full component bundles
Implements ticket #84 for Sprint 3:
- Replace single bare NPC with 3 distinct NPCs: dock worker (16,13)
  with full 4-phase routine and MovementSpeed(2), field tech (14,18)
  with partial routine, stationary guard (18,14) with no routine
- Register all entities (player + 3 NPCs) in EntityRegistry
- Populate RelationshipGraph with colleague and rival edges
- Add NpcPlugin to app for routine system registration
- Add multi-entity visibility tests: 3 NPCs in LOS all visible,
  NPC behind wall excluded from snapshot

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 17:51:50 +01:00
jpmschweitzerandClaude Opus 4.6 22de6c714f fix(simulation): address PR #12 review — z-level filter, visible tile dedup, version bump
- Filter remembered entities by z-level (Hoshe + Tyre warning)
- Skip remembered ghosts on currently visible tiles (Hoshe warning)
- Bump ObserverSnapshot version to 3 (Tyre suggestion)
- Add edge case tests: visible tile collision, different z-level,
  knowledge without position (Hoshe suggestion)
- Regenerate msgpack fixtures for v3

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 01:47:35 +01:00
jpmschweitzerandClaude Opus 4.6 9c0190c7c2 feat(simulation): integrate knowledge graph into observer snapshot (#366)
VisibleEntity now carries relationship state (D-033 entity color) and
observation type (Visible vs Remembered). compute_observer_snapshot
queries the player's KnowledgeGraph to overlay relationship data on
visible entities and include remembered (not-in-LOS) entities as fog
ghosts at their last known position. Regenerated msgpack fixtures.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 01:28:53 +01:00
jpmschweitzerandClaude Opus 4.6 3115c7a84c fix(simulation): address PR #10 review — plugin wiring, stale reset, warnings
- Register KnowledgePlugin in main.rs and game_loop test (Tyre critical)
- Add KnowledgeGraph component to player spawn (Tyre critical)
- Reset Stale -> Active on fresh direct observation (Hoshe warning)
- Make registry/queue non-optional in emit_observation_events (Tyre/Hoshe)
- Add tracing::warn for missing EntityRegistry entries (Hoshe warning)
- Replace HashSet with Vec for small entity ID lookups (Hoshe suggestion)
- Add const static assertion for KnowledgeConfidence ordering (Hoshe)
- Add is_empty() and known_facts_iter() to KnowledgeGraph (Tyre)
- Add decay_skips_non_minute_ticks and observe_resets_stale tests (Hoshe)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 01:06:33 +01:00
jpmschweitzerandClaude Opus 4.6 804379dee2 feat(simulation): wire direct observation to knowledge graph (#364, #367)
Perception system emits DirectObservation/LeftLOS knowledge events
based on snapshot visibility. Entities entering LOS get Direct
confidence; leaving LOS downgrades to KnowsDetails. System params
are optional for backward compatibility when KnowledgePlugin is not
registered. 28 knowledge graph unit tests included.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 00:48:51 +01:00
jpmschweitzerandClaude Opus 4.6 e205b38938 feat(simulation): integrate observer visibility query (#112)
Replace unfiltered generate_snapshot with compute_observer_snapshot
that combines shadowcasting + vision cone to send only visible
entities and tiles. Enforces information asymmetry (D-011): NPCs
behind walls or in the blind spot are excluded from the snapshot.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 00:21:07 +01:00
jpmschweitzerandClaude Opus 4.6 f760624967 feat(simulation): add vision cone with forward/peripheral/blind sectors (#111)
Implement direction-dependent visibility modulation per D-015.
Forward cone (~120 deg) at full range, peripheral (~180 deg each side)
at reduced range, blind spot (~60 deg behind) excluded. Facing component
updated on player movement via facing_from_delta.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 00:21:01 +01:00
jpmschweitzerandClaude Opus 4.6 3323678ddf feat(simulation): implement symmetric shadowcasting for LOS (#359, #110)
Add Albert Ford's symmetric shadowcasting algorithm using rational
fraction slopes. Benchmarked 1.2-10.5x faster than recursive with
guaranteed symmetry (if A sees B, B sees A). Resolves Q-018 as D-035.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 00:20:54 +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