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>
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>
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>
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>
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>
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>
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>
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>
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>
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>