Set up the complete Godot 4.6 client foundation as a pure renderer (D-020):
- project.godot with 2D rendering, autoloads, input actions
- Main scene: Game > World (TileMapLayer, Entities, FogOverlay) + Camera2D + UILayer
- Autoloads: SimBridge (connection state machine + test mode), GameState, InputMapper
- Rendering stubs: WorldRenderer, EntityRenderer, FogRenderer
- UI stubs: HUD (health/perception/time), Minimap, MonologueDisplay
- Input mapping: WASD/arrows, E (interact), Tab (perception), Esc (menu), Space (pause)
- gdUnit4 smoke tests: scene loads, autoloads registered (2/2 passing)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix input_mapper double-check bug (redundant InputEventKey + pressed filter)
- Add bounds checking for position arrays in entity_renderer and game_state
- Make test snapshot deterministic (incrementing counter, not wall clock)
- Fix tween overlap in monologue_display (cancel active tween before new one)
- Extract TILE_SIZE constant from magic number 32
- Add 5 D-030 Layer 1 fixture tests for snapshot parsing (7/7 total passing)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Camera2D now tracks player_position from GameState (D-015)
- Add SubViewport child to minimap SubViewportContainer (fixes editor warning)
- Wire MonologueDisplay into main loop for D-016 perception data path
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Dual-Agent Review (Round 3): origin/client -> main
Hoshe (Code Quality): APPROVE
All 3 critical issues from round 2 resolved. SubViewport hierarchy correct, camera tracking implemented with tile-to-pixel scaling, monologue wired into perception data path.
#
File
Severity
Issue
1
scripts/main.gd:25
warning
Missing null check on camera before position assignment (other nodes have null checks)
2
scripts/main.gd:35
warning
No type validation on snapshot.monologue before passing to show_monologue(text: String)
3
scripts/main.gd:24-35
suggestion
Camera updates after world renderer -- one-frame lag likely imperceptible
Tyre (Architecture): APPROVE
All 3 critical fixes satisfy D-015 and D-016 requirements. Camera locked to character, SubViewport properly structured, monologue data path wired. D-020 client-server separation maintained. No new architectural concerns.
Verdict: APPROVED
Both reviewers approve. Merging.
## Dual-Agent Review (Round 3): origin/client -> main
### Hoshe (Code Quality): APPROVE
All 3 critical issues from round 2 resolved. SubViewport hierarchy correct, camera tracking implemented with tile-to-pixel scaling, monologue wired into perception data path.
| # | File | Severity | Issue |
|---|------|----------|-------|
| 1 | scripts/main.gd:25 | warning | Missing null check on camera before position assignment (other nodes have null checks) |
| 2 | scripts/main.gd:35 | warning | No type validation on snapshot.monologue before passing to show_monologue(text: String) |
| 3 | scripts/main.gd:24-35 | suggestion | Camera updates after world renderer -- one-frame lag likely imperceptible |
### Tyre (Architecture): APPROVE
All 3 critical fixes satisfy D-015 and D-016 requirements. Camera locked to character, SubViewport properly structured, monologue data path wired. D-020 client-server separation maintained. No new architectural concerns.
### Verdict: APPROVED
Both reviewers approve. Merging.
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
make ci-clientpipeline functional (lint → build → test)Tickets closed
Epic #277 and stories #287–296 (all 10 child tickets)
Test plan
make ci-clientpasses green (lint, build, test)godot4 --path clientopens without errors🤖 Generated with Claude Code
Dual-Agent Review: origin/client -> main
Hoshe (Code Quality): REQUEST_CHANGES
Summary: Solid foundation but critical bugs and test gaps need fixing before merge.
event.pressedfilter +is_action_pressed()is redundantpos[0]/pos[1]— crashes on malformed snapshot dataVector2(pos[0], pos[1])with no validationTime.get_ticks_msec()makes test snapshot non-deterministic (violates D-010 principle 4)Tyre (Architecture): APPROVE (with suggestions)
Summary: Exactly the right amount of architecture for a first commit. The D-020 contract is correctly implemented: client does zero simulation logic.
addons/gdUnit4/test/directoryRequired before merge:
Dual-Agent Review (Round 2): origin/client -> main
Hoshe (Code Quality): APPROVE
All 8 previous critical/warning issues properly addressed in commit
3368231. Bounds validation added, input bug fixed, test snapshots deterministic, tween cancellation implemented, magic constant extracted, 7 fixture tests covering happy path + edge cases. No new critical issues.Tyre (Architecture): REQUEST_CHANGES
Architecture is 85% solid -- D-020 separation is correct, D-030 testability implemented. But 3 critical wiring gaps remain:
Verdict: CHANGES REQUESTED
Fix the 3 critical wiring issues (camera tracking, SubViewport child, monologue wiring) before merge. Estimated 2-4 hours.
Dual-Agent Review (Round 3): origin/client -> main
Hoshe (Code Quality): APPROVE
All 3 critical issues from round 2 resolved. SubViewport hierarchy correct, camera tracking implemented with tile-to-pixel scaling, monologue wired into perception data path.
Tyre (Architecture): APPROVE
All 3 critical fixes satisfy D-015 and D-016 requirements. Camera locked to character, SubViewport properly structured, monologue data path wired. D-020 client-server separation maintained. No new architectural concerns.
Verdict: APPROVED
Both reviewers approve. Merging.
Pull request closed