Fix input encoding to batch Vec per frame matching server wire protocol
Fix SimBridge server args (positional address) and port default (9876)
Add EntityKind::Player fixture and update multi-entity fixture with all 4 entity kinds
Add D-030 Layer 3 E2E test: spawns Rust server, connects via LocalBridge, sends MoveNorth, verifies player movement in snapshot
43/43 client tests pass, 53/53 server tests pass
Test plan
make test-client (43/43 pass including new E2E test)
make test-server (53/53 pass)
E2E test verifies full round-trip: client to server to snapshot with correct player position (16.5, 15.5)
Batch encoding tested with single, multiple, data-variant, and empty input arrays
EntityKind::Player fixture decoded correctly from Rust-generated msgpack
Generated with Claude Code
## Summary
- Fix input encoding to batch Vec<PlayerInput> per frame matching server wire protocol
- Fix SimBridge server args (positional address) and port default (9876)
- Add EntityKind::Player fixture and update multi-entity fixture with all 4 entity kinds
- Add D-030 Layer 3 E2E test: spawns Rust server, connects via LocalBridge, sends MoveNorth, verifies player movement in snapshot
- 43/43 client tests pass, 53/53 server tests pass
## Test plan
- [x] make test-client (43/43 pass including new E2E test)
- [x] make test-server (53/53 pass)
- [x] E2E test verifies full round-trip: client to server to snapshot with correct player position (16.5, 15.5)
- [x] Batch encoding tested with single, multiple, data-variant, and empty input arrays
- [x] EntityKind::Player fixture decoded correctly from Rust-generated msgpack
Generated with Claude Code
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>
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>
D-030 Layer 3: E2E test spawns the Rust server binary, connects via
LocalBridge, sends a batched MoveNorth input, and verifies the player
moved to (16.5, 15.5). Also adds batch encoding roundtrip tests,
framed batch test, and Player entity fixture decode test. 43/43 pass.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Solid implementation with excellent test coverage (43 client tests, 53 server tests). Wire format fix correctly matches server's Vec<PlayerInput> expectations. Three-layer D-030 architecture is well-exercised.
#
File
Severity
Suggestion
1
test_e2e_connection.gd:37
suggestion
Fixed TEST_PORT (19876) could conflict in parallel CI. Consider ephemeral port 0 (like server-side game_loop.rs does with TcpListener::bind("127.0.0.1:0")).
2
sim_bridge.gd:~144
suggestion
Failed batch encoding silently drops inputs after drain_outbound() clears the buffer. Either re-queue failed entries or add a comment explaining that encode failure = corrupt state (drop is intentional).
3
test_protocol.gd
suggestion
Add a test with malformed entities in a snapshot to verify the decode_errors counter increments correctly (exercises the D-010 boundary violation log path).
Tyre (Architecture): APPROVE
Clean D-030 three-layer IPC testing. Batch encoding fix aligns client with server wire format. No D-010/D-012/D-020 violations. Separation of concerns between layers 1/2/3 is correct.
#
File
Severity
Suggestion
1
test_protocol.gd
suggestion
Add a Rust-generated Vec<PlayerInput> fixture (input_batch_two.msgpack) for bidirectional Layer 1 symmetry — currently batch encoding is GDScript-to-server one-way only.
2
gen_fixtures.rs
suggestion
Add a Rust-side deserialization smoke test that reads all .msgpack fixtures back and asserts they round-trip. Guards against fixture corruption during git operations.
Verdict: APPROVED
All suggestions are hardening improvements — no blockers found.
## Dual-Agent Review: `client` -> `main` (PR #7)
### Hoshe (Code Quality): APPROVE
Solid implementation with excellent test coverage (43 client tests, 53 server tests). Wire format fix correctly matches server's `Vec<PlayerInput>` expectations. Three-layer D-030 architecture is well-exercised.
| # | File | Severity | Suggestion |
|---|------|----------|------------|
| 1 | `test_e2e_connection.gd:37` | suggestion | Fixed `TEST_PORT` (19876) could conflict in parallel CI. Consider ephemeral port 0 (like server-side `game_loop.rs` does with `TcpListener::bind("127.0.0.1:0")`). |
| 2 | `sim_bridge.gd:~144` | suggestion | Failed batch encoding silently drops inputs after `drain_outbound()` clears the buffer. Either re-queue failed entries or add a comment explaining that encode failure = corrupt state (drop is intentional). |
| 3 | `test_protocol.gd` | suggestion | Add a test with malformed entities in a snapshot to verify the `decode_errors` counter increments correctly (exercises the D-010 boundary violation log path). |
### Tyre (Architecture): APPROVE
Clean D-030 three-layer IPC testing. Batch encoding fix aligns client with server wire format. No D-010/D-012/D-020 violations. Separation of concerns between layers 1/2/3 is correct.
| # | File | Severity | Suggestion |
|---|------|----------|------------|
| 1 | `test_protocol.gd` | suggestion | Add a Rust-generated `Vec<PlayerInput>` fixture (`input_batch_two.msgpack`) for bidirectional Layer 1 symmetry — currently batch encoding is GDScript-to-server one-way only. |
| 2 | `gen_fixtures.rs` | suggestion | Add a Rust-side deserialization smoke test that reads all `.msgpack` fixtures back and asserts they round-trip. Guards against fixture corruption during git operations. |
### Verdict: APPROVED
All suggestions are hardening improvements — no blockers found.
Hoshe #1: E2E test now uses random ephemeral port (49152-65535) with
port rotation on bind failure, avoiding conflicts in parallel CI.
Hoshe #2: Documented intentional input drop on encode failure in
SimBridge — re-queuing would retry bad data and server tick has
already advanced.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
Rust smoke tests: 6 tests in serialization.rs — round-trips for all 12 PlayerAction + 4 EntityKind variants, plus all_fixtures_deserialize corruption guard over all 11 .msgpack fixtures.
No remaining issues.
Tyre (Architecture): APPROVE
Test layering correct per D-030. No D-010/D-012/D-020 violations. The all_fixtures_deserialize test is an elegant corruption guard that runs on every cargo test.
Verdict: APPROVED — ready to merge.
## Follow-up Review: `client` -> `main` (PR #7)
All 5 suggestions from the initial review have been addressed.
### Hoshe (Code Quality): APPROVE
- **Ephemeral port**: Random port from IANA ephemeral range (49152-65535) with 5-attempt rotation. Correct.
- **Input drop docs**: Comment explains intentional drop — stale inputs invalid after tick advance. Clear.
- **decode_errors test**: 1 valid + 2 malformed entities, asserts `decode_errors == 2`. Covers D-010 boundary path.
- **Batch fixture**: Rust-generated `input_batch_two.msgpack`, GDScript decodes and verifies. Bidirectional Layer 1 complete.
- **Rust smoke tests**: 6 tests in `serialization.rs` — round-trips for all 12 PlayerAction + 4 EntityKind variants, plus `all_fixtures_deserialize` corruption guard over all 11 .msgpack fixtures.
No remaining issues.
### Tyre (Architecture): APPROVE
Test layering correct per D-030. No D-010/D-012/D-020 violations. The `all_fixtures_deserialize` test is an elegant corruption guard that runs on every `cargo test`.
### Verdict: APPROVED — ready to merge.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Test plan
Generated with Claude Code
Dual-Agent Review:
client->main(PR #7)Hoshe (Code Quality): APPROVE
Solid implementation with excellent test coverage (43 client tests, 53 server tests). Wire format fix correctly matches server's
Vec<PlayerInput>expectations. Three-layer D-030 architecture is well-exercised.test_e2e_connection.gd:37TEST_PORT(19876) could conflict in parallel CI. Consider ephemeral port 0 (like server-sidegame_loop.rsdoes withTcpListener::bind("127.0.0.1:0")).sim_bridge.gd:~144drain_outbound()clears the buffer. Either re-queue failed entries or add a comment explaining that encode failure = corrupt state (drop is intentional).test_protocol.gddecode_errorscounter increments correctly (exercises the D-010 boundary violation log path).Tyre (Architecture): APPROVE
Clean D-030 three-layer IPC testing. Batch encoding fix aligns client with server wire format. No D-010/D-012/D-020 violations. Separation of concerns between layers 1/2/3 is correct.
test_protocol.gdVec<PlayerInput>fixture (input_batch_two.msgpack) for bidirectional Layer 1 symmetry — currently batch encoding is GDScript-to-server one-way only.gen_fixtures.rs.msgpackfixtures back and asserts they round-trip. Guards against fixture corruption during git operations.Verdict: APPROVED
All suggestions are hardening improvements — no blockers found.
Follow-up Review:
client->main(PR #7)All 5 suggestions from the initial review have been addressed.
Hoshe (Code Quality): APPROVE
decode_errors == 2. Covers D-010 boundary path.input_batch_two.msgpack, GDScript decodes and verifies. Bidirectional Layer 1 complete.serialization.rs— round-trips for all 12 PlayerAction + 4 EntityKind variants, plusall_fixtures_deserializecorruption guard over all 11 .msgpack fixtures.No remaining issues.
Tyre (Architecture): APPROVE
Test layering correct per D-030. No D-010/D-012/D-020 violations. The
all_fixtures_deserializetest is an elegant corruption guard that runs on everycargo test.Verdict: APPROVED — ready to merge.
Pull request closed