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>
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>
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>
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>
format_snapshot_text(&ObserverSnapshot) -> String pub-exported from
server crate. Entity labels as kind:entity_id sorted by distance,
room name stubbed as (unknown) until Gauntlet constants land.
10 unit tests. Consumed by tooling/test-client for --text mode.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implement full dialogue selection pipeline (D-028): 4-layer filtering
engine with access tier, situation derivation, trust tier, and weighted
topic+mood scoring via SimRng. Add ContentSlug component for stable
content identity across save/load. Add walk-away KG recording with
IncompleteInteraction events per D-064 three-phase consequences. Bump
protocol to v8 with DialogueResponseEvent. Fixes#305, #427, #452.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
process_player_input processed movement commands regardless of tick
rate, causing the camera to drift from the player when the game was
paused and the player held direction keys. Add PlayerAction::is_movement()
helper and a paused guard that skips movement actions while TickRate is
Paused. Pause/Unpause commands still process normally.
Fixes bug #3 (player moves while game is paused).
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>
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>
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>
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>
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>
Log each received player input at DEBUG level with tick and action,
useful for diagnosing input pipeline issues during live testing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
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>
- 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>
Delete generate_snapshot from bridge/mod.rs — superseded by
perception::observer::compute_observer_snapshot. Not referenced
in any schedule or test.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
- 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>
Implements ticket #341 for Sprint 3:
- Add DeserializationWithDump and MutexPoisoned variants to BridgeError
- Replace .expect("mutex poisoned") with graceful error propagation
in LocalBridge and TcpBridge (4 locations)
- Log first 256 bytes as hex dump on deserialization failure for
debugging malformed payloads
- Classify errors in receive_bridge_inputs: BrokenPipe/ConnectionReset
→ clean shutdown, MutexPoisoned → shutdown, DeserializationWithDump
→ skip frame (recoverable)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- 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>
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>
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>
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>
Expand wire protocol with version field, GameTime (day/phase/paused),
FacingDirection (8-directional), VisibleTile, VisibilitySector
(Forward/Peripheral), and visibility tag on VisibleEntity.
Regenerate all msgpack fixtures for client compatibility.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace string-matching disconnect detection with explicit
BridgeError::Disconnected variant. Add TcpBridge::accept_on(listener)
that takes a pre-bound TcpListener, eliminating the 100ms sleep hack
in TCP tests. Send errors now also trigger ServerRunning=false.
Add trace logging to generate_snapshot for entity count visibility.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implements the full server-side tick pipeline:
- process_player_input drains InputQueue, converts PlayerActions to
MoveIntent components or pause/unpause toggles
- generate_snapshot builds ObserverSnapshot from ECS state with
render coordinate conversion
- receive_bridge_inputs/send_bridge_snapshot handle bridge I/O with
graceful disconnect detection via ServerRunning resource
- main.rs now accepts TCP connections and runs a proper game loop
- PlayerCharacter marker, Player EntityKind, SnapshotBuffer resource
Closes server side of #81, #82, #83.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Godot has no Unix socket API, so TCP localhost is required for
client-server IPC. TcpBridge implements SimBridge with the same
framing protocol as LocalBridge. Includes accept/connect methods
and three integration tests over TCP.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Client-side Protocol.gd expects rmp_serde::to_vec_named() (maps with
string keys), but LocalBridge was using to_vec() (compact positional
arrays). Fix send_snapshot and update all test serialization calls to
match actual wire format. Also change EOF from Ok(vec![]) to
BridgeError::Transport so bridge systems can detect disconnects.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add diagonal PlayerAction variants (MoveNortheast, MoveNorthwest,
MoveSoutheast, MoveSouthwest) and TilePosition::all_neighbors()
returning all 8 surrounding tiles. Genre-expected for immersive sim.
Establishes the movement pattern before pathfinding is built on top.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace .lock().unwrap() with .expect("mutex poisoned") in LocalBridge
for clearer panic messages. Document 16MB MAX_MESSAGE_SIZE rationale
in framing.rs with entity count sizing analysis.
Addresses Hoshe PR review suggestions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Length-prefixed MessagePack framing (4-byte BE length + payload),
LocalBridge struct implementing SimBridge trait over Unix domain
sockets, BridgeResource wrapper for ECS integration. Adds Io
error variant to BridgeError. Two integration tests verify
snapshot and input round-trips over real sockets.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>