Commit Graph
32 Commits
Author SHA1 Message Date
jpmschweitzerandClaude Opus 4.6 a7e2c8fbf4 feat(simulation): add proof room with wall and NPC (#357)
Wall at (16,14) and NPC at (16,13) for Sprint 2 fog-of-perception
proof. Player starts at (16,16) — NPC hidden behind wall until
player moves around it.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 01:45:47 +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 e733a4c223 feat(simulation): add knowledge graph system per D-041 (#361, #362, #363, #365)
Implement per-entity KnowledgeGraph component with BTreeMap storage
for deterministic iteration (D-010). StableEntityId + EntityRegistry
for entity identity across save/load. KnowledgeEventQueue + processing
system for decoupled knowledge updates. Decay system runs once per
game-minute. All types conform to D-041 canonical structs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 00:48:43 +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 bb6bc287e9 feat(simulation): add ObserverSnapshot v2 schema with visibility types (#358, #25)
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>
2026-02-12 00:20:46 +01:00
jpmschweitzerandClaude Opus 4.6 beee44b3c8 feat(client): add batch fixture, fixture smoke test, decode_errors test
Tyre #1: Added Rust-generated input_batch_two.msgpack fixture for
bidirectional D-030 Layer 1 symmetry (Vec<PlayerInput>).
Tyre #2: Added all_fixtures_deserialize Rust test that reads every
.msgpack fixture and verifies it deserializes (corruption guard).
Hoshe #3: Added test_decode_snapshot_malformed_entities_counted test
verifying the decode_errors counter on D-010 boundary violations.
45 client tests, 54 server tests pass.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 21:57:18 +01:00
jpmschweitzerandClaude Opus 4.6 e1e4e346c7 feat(client): add EntityKind::Player fixture and update multi-entity fixture
Server team added EntityKind::Player variant. Added snapshot_player
fixture and updated snapshot_multi_entity to include all 4 entity kinds
(Player, Npc, Object, Terrain) for complete D-030 Layer 1 coverage.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 21:44:20 +01:00
jpmschweitzerandClaude Opus 4.6 b9a3d8efea Merge branch 'server' into main (PR #6)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 21:26:48 +01:00
jpmschweitzerandClaude Opus 4.6 3f4c663242 fix(bridge): improve accept error reporting with address context
Replace expect() with unwrap_or_else that logs the bind address
and error via tracing before exiting.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 21:16:08 +01:00
jpmschweitzerandClaude Opus 4.6 b9af725b02 fix(simulation): correct tick synchronization in snapshot generation
Snapshot for tick N should show state at END of tick N. Reorder systems
so generate_snapshot runs after validate_movement but before
advance_tick. Previously snapshot.tick was the incremented tick,
not the tick whose inputs were processed. Also fix main.rs accept
error to log address context before exiting.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 21:16:04 +01:00
jpmschweitzerandClaude Opus 4.6 2cd8786036 fix(bridge): add Disconnected error variant, fix test race condition
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>
2026-02-11 21:15:56 +01:00
jpmschweitzerandClaude Opus 4.6 a5b88cb735 chore(bridge): format gen_fixtures.rs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 21:01:31 +01:00
jpmschweitzerandClaude Opus 4.6 7864bfdf7d feat(simulation): add input processing, snapshot gen, and game loop
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>
2026-02-11 21:01:28 +01:00
jpmschweitzerandClaude Opus 4.6 1b0e514560 feat(bridge): add TCP transport for Godot client connection
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>
2026-02-11 21:01:20 +01:00
jpmschweitzerandClaude Opus 4.6 f6ce7d4046 fix(bridge): use named MessagePack format for wire compatibility
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>
2026-02-11 21:01:15 +01:00
jpmschweitzerandClaude Opus 4.6 0f75c3194d feat(client): add LocalBridge framing tests and diagonal fixtures
12 new tests covering framing roundtrips, cross-layer Protocol+framing
integration, and diagonal wire mapping. 4 new diagonal movement
fixtures generated from Rust for D-030 Layer 1 cross-language
verification. 33/33 tests pass.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 20:59:46 +01:00
jpmschweitzer 56ee8305ae Merge origin/client into main 2026-02-11 20:26:17 +01:00
jpmschweitzerandClaude Opus 4.6 f87bd2b0e5 feat(simulation): add entity-entity collision
validate_movement now checks both terrain walkability AND tile
occupancy. Builds a spatial index of occupied tiles from stationary
entities, then resolves movers in order — first valid claim wins.

Same spatial pattern needed for D-026 simulation tiers (30-80 active
NPCs) and future pathfinding occupied-tile awareness.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 20:15:24 +01:00
jpmschweitzerandClaude Opus 4.6 bef4383196 feat(simulation): add 8-directional movement
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>
2026-02-11 20:15:18 +01:00
jpmschweitzerandClaude Opus 4.6 bc9a691bc1 fix(client): address PR #4 review feedback
Hoshe critical fixes:
- _action_enum_to_wire uses InputMapper.Action constants instead of
  fragile integer literals; OPEN_MENU explicitly handled as client-only
- Remove int() coercion on tick/entity_id — use direct assignment since
  GDScript int is signed 64-bit (safe for realistic tick values)
- Check encode result before buffering in send_input() — reject empty
  bytes instead of corrupting the outbound stream
- Test snapshot now uses Protocol format {tick, entities} instead of
  legacy schema; GameState updated to derive player position from
  entity data; main.gd and world_renderer.gd updated accordingly

Hoshe warnings:
- 5 negative tests added (truncated bytes, wrong type, missing fields,
  empty bytes, encode validation) — 20/20 tests pass
- receive_bytes signal is emitted at consume time in poll_snapshot by
  design (documented in code)

Tyre suggestions:
- Remove duplicated root-level fixtures — single source of truth in
  client/tests/fixtures/msgpack/
- gen_fixtures.rs writes directly to client/ directory
- Add `make fixtures` target for regeneration

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 19:32:49 +01:00
jpmschweitzerandClaude Opus 4.6 9860fc0857 fix(simulation): address bridge review feedback
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>
2026-02-11 19:32:35 +01:00
jpmschweitzerandClaude Opus 4.6 78e0c71c6d refactor(simulation): chunk-based walkability map per D-012
Rewrites WalkabilityMap from flat Vec<bool> to HashMap<ChunkCoord, ChunkData>
with 32x32 tile chunks. Supports chunk load/unload for future borderless
generation. Unloaded chunks treated as unwalkable.

Adds TilePosition ↔ f32 render coordinate conversion (to_render_coords,
from_render_coords) bridging i32 simulation coords and f32 wire format.

Addresses Tyre PR review: D-012 chunk architecture compatibility and
VisibleEntity coordinate mismatch.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 19:32:29 +01:00
jpmschweitzerandClaude Opus 4.6 84e34f61bd feat(client): add MessagePack library and cross-language fixtures
Install Godot4MessagePack (pure GDScript) for MessagePack encode/decode.
Add Rust fixture generator (gen_fixtures.rs) that produces canonical
.msgpack files using rmp_serde::to_vec_named for cross-language testing.

Fixtures cover: snapshots (empty, one NPC, multi-entity with all
EntityKind variants) and player inputs (unit + data enum variants).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 19:16:43 +01:00
jpmschweitzerandClaude Opus 4.6 862ab9099f feat(simulation): add tile collision system (#236)
TilePosition component with discrete grid coordinates, flat-storage
WalkabilityMap resource with O(1) can_move_to() lookup, MoveIntent
component and validate_movement system. Movement validated against
walkability map each tick, blocking all NPC and player movement
through unwalkable tiles. 11 unit tests + 1 integration test.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 19:07:53 +01:00
jpmschweitzerandClaude Opus 4.6 4ed15c1a38 feat(simulation): add LocalBridge IPC over Unix socket (#78)
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>
2026-02-11 19:07:47 +01:00
jpmschweitzerandClaude Opus 4.6 112910df9b test(simulation): expand test coverage per PR #2 review
- Add roundtrip tests for all PlayerAction variants (Hoshe #6)
- Add roundtrip tests for all EntityKind variants (Hoshe #6)
- Add day wraparound at midnight edge case test (Hoshe #7)
- Add day() calculation test (Hoshe #7)
- Add out-of-order input rejection test (Hoshe #7)
- Total: 15 → 20 tests

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 17:53:16 +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
jpmschweitzerandClaude Opus 4.6 38ded93a5b chore(meta): add project directory scaffold
Create client/, server/, tooling/, tests/, .config/ (tracked) and
.cache/ (gitignored). Update CLAUDE.md project structure to reflect
the new layout including workshops directory.

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