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>
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>
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>
No expansion hooks for future D-020 fields (fog, sound, monologue, HUD)
Verdict: CHANGES REQUESTED
Hoshe's critical issues need fixing: silent data loss on skipped enum variant, encode error not checked before buffering, test snapshot schema mismatch.
Note: Please use all required tea CLI flags (--login schweitz --repo jpmschweitzer/settled-reach) when creating PRs to avoid TTY prompts.
## Dual-Agent Review: origin/client → main (PR #4)
### Hoshe (Code Quality): REQUEST_CHANGES
| # | File | Severity | Issue |
|---|------|----------|-------|
| 1 | sim_bridge.gd:97-105 | critical | _action_enum_to_wire() skips action 6 (OPEN_MENU) silently — silent data loss |
| 2 | protocol.gd:26 | critical | int(raw["tick"]) coerces Rust u64 to GDScript signed int — overflow at 2^63 violates D-010 determinism |
| 3 | protocol.gd + sim_bridge.gd | critical | Inconsistent error handling — decode returns null, encode returns empty bytes. send_input() doesn't check encode result, empty bytes corrupt stream |
| 4 | sim_bridge.gd:114-128 | warning | _test_snapshot() returns wrong schema — doesn't match Protocol's expected {tick, entities} format |
| 5 | test_protocol.gd | warning | No negative tests — zero tests for malformed/truncated MessagePack |
| 6 | sim_bridge.gd:74 | warning | receive_bytes() stores snapshot but doesn't emit snapshot_received signal |
### Tyre (Architecture): APPROVE
D-020 IPC protocol compliance confirmed. Cross-language fixture approach is sound per D-030 Layer 1. rmp_serde encoding patterns verified. Clean separation for future NetworkBridge swap.
| # | File | Severity | Issue |
|---|------|----------|-------|
| 1 | tests/fixtures/msgpack/ | warning | Fixtures duplicated in tests/ and client/tests/ — sync risk, should symlink or add make fixtures target |
| 2 | sim_bridge.gd:86-97 | suggestion | Action enum mapping uses integer literals instead of InputMapper.Action constants — fragile coupling |
| 3 | protocol.gd | suggestion | No expansion hooks for future D-020 fields (fog, sound, monologue, HUD) |
### Verdict: CHANGES REQUESTED
Hoshe's critical issues need fixing: silent data loss on skipped enum variant, encode error not checked before buffering, test snapshot schema mismatch.
Note: Please use all required tea CLI flags (--login schweitz --repo jpmschweitzer/settled-reach) when creating PRs to avoid TTY prompts.
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>
Dual-Agent Review Round 2: origin/client → main (PR #4)
Round 1 Issue Resolution: ALL FIXED
Issue
Status
OPEN_MENU skipped silently (CRITICAL)
FIXED — explicit handling with push_warning
u64→i64 tick overflow (CRITICAL)
ACKNOWLEDGED — documented as safe (29B year margin)
Inconsistent error handling (CRITICAL)
FIXED — send_input() checks encode result
Test snapshot wrong schema (WARNING)
FIXED — matches Protocol format
No negative tests (WARNING)
FIXED — 5 negative tests added
receive_bytes() no signal (WARNING)
BY DESIGN — signal emitted at consume time
Fixture duplication (WARNING)
FIXED — single source in client/tests/fixtures/
Integer literals in enum mapping (SUGGESTION)
FIXED — InputMapper.Action constants
Hoshe (Code Quality): REQUEST_CHANGES
All 6 round 1 issues properly addressed. New issues found in round 2:
#
File
Severity
Issue
1
protocol.gd
critical
Silent entity filtering in decode_snapshot() — failed entities dropped with push_warning only, caller gets partial snapshot with no indication of data loss. Violates D-010 information boundary. Add filtered entity count as push_error and/or return decode_errors field so caller can detect corruption. ~5 line fix.
2
sim_bridge.gd
warning
receive_bytes() overwrites unconsumed snapshot silently. Add push_warning when overwriting so assumption violations are visible. ~3 line fix. Full queue can be a follow-up ticket.
3
test_protocol.gd
warning
test_encode_returns_empty_on_failure is actually a positive test — rename to test_encode_produces_nonempty_bytes
Revised from round 2 APPROVE. Silent partial data in decode_snapshot() violates D-010 information boundaries — the client must know what it knows. When future D-020 fields (fog, sound, monologue) arrive, this silent-drop pattern multiplies and becomes undebuggable.
#
File
Severity
Issue
1
protocol.gd
critical
Silent entity filtering is a D-010 principle 2 violation — information boundary is corrupted when client doesn't know it received partial data. Pattern error, not missing feature.
2
sim_bridge.gd
warning
Snapshot overwrite: add warning log + document "latest wins" semantics. Upgrade to queue when multi-server design arrives.
Verdict: CHANGES REQUESTED
Both reviewers agree: silent entity filtering must be fixed (D-010 violation). Snapshot overwrite needs a warning. Test naming cleanup. All small fixes — estimated 15 minutes.
## Dual-Agent Review Round 2: origin/client → main (PR #4)
### Round 1 Issue Resolution: ALL FIXED
| Issue | Status |
|-------|--------|
| OPEN_MENU skipped silently (CRITICAL) | FIXED — explicit handling with push_warning |
| u64→i64 tick overflow (CRITICAL) | ACKNOWLEDGED — documented as safe (29B year margin) |
| Inconsistent error handling (CRITICAL) | FIXED — send_input() checks encode result |
| Test snapshot wrong schema (WARNING) | FIXED — matches Protocol format |
| No negative tests (WARNING) | FIXED — 5 negative tests added |
| receive_bytes() no signal (WARNING) | BY DESIGN — signal emitted at consume time |
| Fixture duplication (WARNING) | FIXED — single source in client/tests/fixtures/ |
| Integer literals in enum mapping (SUGGESTION) | FIXED — InputMapper.Action constants |
### Hoshe (Code Quality): REQUEST_CHANGES
All 6 round 1 issues properly addressed. New issues found in round 2:
| # | File | Severity | Issue |
|---|------|----------|-------|
| 1 | protocol.gd | critical | Silent entity filtering in decode_snapshot() — failed entities dropped with push_warning only, caller gets partial snapshot with no indication of data loss. Violates D-010 information boundary. Add filtered entity count as push_error and/or return decode_errors field so caller can detect corruption. ~5 line fix. |
| 2 | sim_bridge.gd | warning | receive_bytes() overwrites unconsumed snapshot silently. Add push_warning when overwriting so assumption violations are visible. ~3 line fix. Full queue can be a follow-up ticket. |
| 3 | test_protocol.gd | warning | test_encode_returns_empty_on_failure is actually a positive test — rename to test_encode_produces_nonempty_bytes |
| 4 | protocol.gd | suggestion | Tick overflow comment says "10 ticks/min" — verify intended tick rate (likely 10 ticks/sec) |
### Tyre (Architecture): REQUEST_CHANGES
Revised from round 2 APPROVE. Silent partial data in decode_snapshot() violates D-010 information boundaries — the client must know what it knows. When future D-020 fields (fog, sound, monologue) arrive, this silent-drop pattern multiplies and becomes undebuggable.
| # | File | Severity | Issue |
|---|------|----------|-------|
| 1 | protocol.gd | critical | Silent entity filtering is a D-010 principle 2 violation — information boundary is corrupted when client doesn't know it received partial data. Pattern error, not missing feature. |
| 2 | sim_bridge.gd | warning | Snapshot overwrite: add warning log + document "latest wins" semantics. Upgrade to queue when multi-server design arrives. |
### Verdict: CHANGES REQUESTED
Both reviewers agree: silent entity filtering must be fixed (D-010 violation). Snapshot overwrite needs a warning. Test naming cleanup. All small fixes — estimated 15 minutes.
- 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>
Dual-Agent Review Round 3: origin/client → main (PR #4)
Hoshe (Code Quality): APPROVE
All 3 round 2 fixes verified: decode_snapshot() now reports filtered entity count via push_error + decode_errors field, receive_bytes() warns on unconsumed snapshot overwrite, test renamed to test_encode_produces_nonempty_bytes. Clean, minimal changes.
Tyre (Architecture): APPROVE
D-010 information boundary restored. D-030 Layer 1 complete with 14 tests. Architecture expansion-ready for future D-020 fields.
Verdict: APPROVED
## Dual-Agent Review Round 3: origin/client → main (PR #4)
### Hoshe (Code Quality): APPROVE
All 3 round 2 fixes verified: decode_snapshot() now reports filtered entity count via push_error + decode_errors field, receive_bytes() warns on unconsumed snapshot overwrite, test renamed to test_encode_produces_nonempty_bytes. Clean, minimal changes.
### Tyre (Architecture): APPROVE
D-010 information boundary restored. D-030 Layer 1 complete with 14 tests. Architecture expansion-ready for future D-020 fields.
### Verdict: APPROVED
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
Dual-Agent Review: origin/client → main (PR #4)
Hoshe (Code Quality): REQUEST_CHANGES
Tyre (Architecture): APPROVE
D-020 IPC protocol compliance confirmed. Cross-language fixture approach is sound per D-030 Layer 1. rmp_serde encoding patterns verified. Clean separation for future NetworkBridge swap.
Verdict: CHANGES REQUESTED
Hoshe's critical issues need fixing: silent data loss on skipped enum variant, encode error not checked before buffering, test snapshot schema mismatch.
Note: Please use all required tea CLI flags (--login schweitz --repo jpmschweitzer/settled-reach) when creating PRs to avoid TTY prompts.
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>Dual-Agent Review Round 2: origin/client → main (PR #4)
Round 1 Issue Resolution: ALL FIXED
Hoshe (Code Quality): REQUEST_CHANGES
All 6 round 1 issues properly addressed. New issues found in round 2:
Tyre (Architecture): REQUEST_CHANGES
Revised from round 2 APPROVE. Silent partial data in decode_snapshot() violates D-010 information boundaries — the client must know what it knows. When future D-020 fields (fog, sound, monologue) arrive, this silent-drop pattern multiplies and becomes undebuggable.
Verdict: CHANGES REQUESTED
Both reviewers agree: silent entity filtering must be fixed (D-010 violation). Snapshot overwrite needs a warning. Test naming cleanup. All small fixes — estimated 15 minutes.
Dual-Agent Review Round 3: origin/client → main (PR #4)
Hoshe (Code Quality): APPROVE
All 3 round 2 fixes verified: decode_snapshot() now reports filtered entity count via push_error + decode_errors field, receive_bytes() warns on unconsumed snapshot overwrite, test renamed to test_encode_produces_nonempty_bytes. Clean, minimal changes.
Tyre (Architecture): APPROVE
D-010 information boundary restored. D-030 Layer 1 complete with 14 tests. Architecture expansion-ready for future D-020 fields.
Verdict: APPROVED
Pull request closed