Commit Graph
116 Commits
Author SHA1 Message Date
jpmschweitzerandClaude Opus 4.6 2338941721 fix(client): batch-encode inputs as Vec<PlayerInput> per server wire format
Server expects a MessagePack array of PlayerInput objects in one framed
message per tick, not individual inputs per frame. Added
Protocol.encode_player_inputs() for batch encoding. Changed SimBridge to
buffer raw input dicts and batch-encode in _process(). Also fixed server
port default (9876) and positional arg format to match server CLI.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 21:44:14 +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 3befd2309c fix(client): address PR #5 review — race condition, buffer corruption, input error
Critical fixes from Hoshe review:
1. Race condition: defer TCP connect to _process() with retry logic
   (MAX_CONNECT_RETRIES=20, 100ms interval) so server has time to bind.
2. Buffer corruption: disconnect on oversized message instead of
   clearing valid buffered data (_corrupt flag, fail-safe).
3. Silent input drop: send_input() returns Error so callers can detect
   encode/validation failures.

Warnings addressed:
- ServerProcess validates server_path exists before spawning
- SIGKILL and health check TODOs documented for future work
- Diagonal keybindings documented as intentional deferral
- send_message uses single put_data() call (no partial write risk)
- Static frame helpers documented as D-030 Layer 2 test-only

New tests (36 total, up from 33):
- Partial read scenario (chunked TCP delivery)
- Multi-message sequential decode (exercises buffer corruption fix)
- send_input error return on invalid action

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 21:14:52 +01:00
jpmschweitzerandClaude Opus 4.6 058d0352ab chore(meta): update changelog
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 21:02:00 +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 c4e1b07346 chore(meta): update changelog
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 21:00:04 +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
jpmschweitzerandClaude Opus 4.6 2ecafff2ed feat(client): integrate LocalBridge transport and 8-directional movement
Wire SimBridge to use LocalBridge for TCP transport in non-test mode:
_process() polls for incoming snapshots and flushes outbound inputs.
Add 4 diagonal movement variants (NE, SE, SW, NW) to InputMapper and
wire mapping, ordered clockwise. Register diagonal input actions in
project.godot.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 20:59:40 +01:00
jpmschweitzerandClaude Opus 4.6 6dfaf2831f feat(client): add LocalBridge TCP transport and ServerProcess manager
LocalBridge wraps StreamPeerTCP with 4-byte big-endian length-prefix
framing matching server/src/bridge/framing.rs. ServerProcess manages
the Rust server as a subprocess via OS.create_process(). Together
they form the D-020 IPC transport layer for ticket #79.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 20:59:34 +01:00
jpmschweitzerandClaude Opus 4.6 af4d0d3f26 docs(workshops): complete v0.1 content gap analysis workshop
Workshop produced 42 new tickets (#297-#338) + 6 updated, 9 new
decisions (D-032 through D-040), and 53 dependency links. All 18
agent briefings updated to reflect 40 confirmed decisions.

Key outcomes: Sera Venn as detective's FRIEND, Kael Davan as
smuggler's FRIEND, all 6 wow moments in scope, converged 6+3 tag
taxonomy, wiki taxonomy with 14 categories, 8 audio files via
Stable Audio Open, 4 parallel unblocked work tracks identified.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 20:38:21 +01:00
jpmschweitzerandClaude Opus 4.6 228844fb5d docs(briefings): update Mellanie briefing post-workshop
Workshop outputs unblock content authoring. Updated status,
key decisions, and immediate work items.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 20:28:58 +01:00
jpmschweitzerandClaude Opus 4.6 96087323d4 chore(db): track ticket database updates
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 20:28:43 +01:00
jpmschweitzerandClaude Opus 4.6 36ffd3f6fa docs(decisions): add D-040 wiki taxonomy and Q-012 through Q-017
D-040: hierarchical wiki structure with YAML frontmatter.
6 new open questions from content gap analysis workshop
covering generation expansion, line previewer, audio timing,
FRIEND content authoring, knowledge hierarchy, and triangle
pressure thresholds.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 20:28:17 +01:00
jpmschweitzerandClaude Opus 4.6 17ea8a49a1 chore(meta): update changelog
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 20:28:02 +01:00
jpmschweitzerandClaude Opus 4.6 47585d8107 chore(db): track ticket database updates
Workshop tickets and sprint assignment changes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 20:27:46 +01:00
jpmschweitzerandClaude Opus 4.6 3b6148e56f docs(meta): add PR #4 protocol codec test report
Hoshe's code quality review of client MessagePack codec.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 20:27:42 +01:00
jpmschweitzerandClaude Opus 4.6 745ce01117 docs(decisions): add D-032 through D-039 from content workshop
D-032: separate monologue pools per character
D-033: entity color = relationship to player
D-034: THE FRIEND production-level NPC pattern
D-035: converged tag taxonomy for line pools
D-036: Sova Transit District / Krenn System setting
D-037: contraband specification (unlicensed lattice components)
D-038: audio in v0.1 scope (8 files via Stable Audio Open)
D-039: v0.1 wow moment scope (all 6 moments)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 20:27:37 +01:00
jpmschweitzerandClaude Opus 4.6 e96ec80d9c docs(workshops): archive v0.1 content gap analysis workshop
6 agents × 2 rounds examining 9 content layers. Produced D-032
through D-039, THE FRIEND NPC pattern, converged tag taxonomy,
and Sova Transit District setting.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 20:27:31 +01:00
jpmschweitzer 56ee8305ae Merge origin/client into main 2026-02-11 20:26:17 +01:00
jpmschweitzer 2d97fe74da Merge remote-tracking branch 'origin/server' 2026-02-11 20:25:55 +01:00
jpmschweitzerandClaude Opus 4.6 90edf3fabc chore(meta): update changelog
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 20:15:48 +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 5a539991e4 fix(client): address PR #4 round 2 review feedback
- decode_snapshot() reports dropped entities via push_error and returns
  decode_errors count so callers can detect partial data (D-010
  information boundary compliance)
- receive_bytes() warns when overwriting unconsumed snapshot, documents
  latest-wins semantics
- Rename misleading test to test_encode_produces_nonempty_bytes
- Fix tick rate comment: 10 ticks/game-minute per D-031

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 20:12:39 +01:00
jpmschweitzerandClaude Opus 4.6 0f5f73a927 chore(meta): update changelog
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 19:32:56 +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 91db2f99de docs(sprints): add PR workflow instructions to sprint briefings
All three sprint briefings now include tea CLI PR creation example
with required --login and --repo flags to avoid TTY prompts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 19:26:15 +01:00
jpmschweitzerandClaude Opus 4.6 198749f9c1 docs(workshops): add v0.1 content gap analysis workshop brief
Nine-layer analysis from global (art direction) to specific (audio).
Identifies gaps in content tickets for Mellanie, Paula, and Araminta.
Structured as 2-round workshop with 6 participants to produce missing
tickets, dependency chain, and content team work plan.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 19:18:28 +01:00
jpmschweitzerandClaude Opus 4.6 9af9b3f3aa chore(meta): update changelog
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 19:17:20 +01:00
jpmschweitzerandClaude Opus 4.6 0041e4453f feat(client): wire SimBridge to Protocol codec
SimBridge now encodes player inputs via Protocol.encode_player_input()
and exposes receive_bytes()/drain_outbound() for the transport layer.
Test mode still works unchanged. Transport (ticket #79) will call
these methods to complete the IPC pipeline.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 19:17:05 +01:00
jpmschweitzerandClaude Opus 4.6 b5dd44313e feat(client): add Protocol codec with cross-language tests (#77)
Protocol.gd decodes ObserverSnapshot and PlayerInput from Rust's
rmp_serde wire format, and encodes PlayerInput for sending to server.
Handles rmp_serde enum encoding: unit variants as bare strings,
data variants as single-element maps.

8 fixture-based tests verify decode of Rust-generated fixtures,
GDScript encode/decode roundtrips, and cross-language compatibility.
All 15 tests pass (3 suites).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 19:16:56 +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 e44e90c2cb chore(meta): update changelog
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 19:08:07 +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 0c7d44b265 fix(db): sqlite connector always reads/writes main worktree database
Same fix as the ticket CLI — uses git rev-parse --git-common-dir to
resolve DB path to the main worktree. Prevents WAL/journal pollution
when sqlite-query or sqlite-exec are called from feature branches.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 19:01:26 +01:00
jpmschweitzerandClaude Opus 4.6 70a6f850c6 fix(db): ticket CLI always reads/writes main worktree database
Uses git rev-parse --git-common-dir to find the main worktree root,
then resolves the DB path there. Prevents WAL/journal pollution on
feature branch worktrees that caused merge conflicts on commonwealth.db.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 19:00:16 +01:00
jpmschweitzerandClaude Opus 4.6 039eac608d chore(skills): start-sprint uses current branch as team
No argument needed — the current branch determines the team.
Only asks if on main.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 18:53:16 +01:00
jpmschweitzerandClaude Opus 4.6 0123c5599c chore(skills): add start-sprint skill
Syncs team branch with main, finds the active sprint, reads the sprint
briefing, loads ticket details and key decisions, then presents an
actionable work plan with suggested first task.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 18:52:24 +01:00
jpmschweitzerandClaude Opus 4.6 7f88fa79b7 chore(meta): point agents at sprint briefings in CLAUDE.md
Sprint briefings (docs/sprints/sprint-N/{team}.md) are now the primary
starting point for implementation work. Per-agent briefings remain as
background context.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 18:50:02 +01:00
jpmschweitzerandClaude Opus 4.6 116b6c308c docs(sprints): add Sprint 1 team briefings
Per-team sprint briefings under docs/sprints/sprint-1/ for server,
client, and joint tracks. Each lists assigned tickets, dependencies,
key decisions to read, and implementation notes. Agents use
ticket show <id> for full details.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 18:49:49 +01:00
jpmschweitzerandClaude Opus 4.6 e8f03b4cd8 chore(meta): update changelog
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 18:46:20 +01:00