Root cause: update_from_state() used visible_tiles (always empty in live
server mode) instead of visible_positions for bounds calculation. Bounds
never grew beyond 64x64, so tiles outside that area rendered as solid
unexplored black.
Fix: new _grow_bounds_from_positions() method reads visible_positions
(always populated from server snapshots). Shader fix: removed the
(explored < 0.01 && vis_raw < 0.01) guard that cut off the Gaussian
gradient at unexplored tile boundaries. Doubled blur step size for
D-066 compliant 6-8 tile soft gradient. Added debug_exploration mode
for diagnostic rendering of the exploration texture.
19 acceptance tests covering exploration persistence, bounds grow-only
invariant, gradient margin, Forward-only visibility writes, and
exploration data surviving texture resize.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implements the StartupMessage protocol: client generates world_seed in
SessionManager.new_game(), sends it after handshake, server uses it to
seed SimRng and sample EntanglementConfig.
EntanglementConfig samples flat ∈ [25,35]%, intrigue ∈ [15,25]%, mundane
as remainder (D-029). Same seed produces identical config (D-010
determinism). Different seeds produce distinct configs in ≥90% of pairs.
Protocol flow: HandshakeMessage (server→client) → StartupMessage with
world_seed (client→server) → SimRng initialization → tick loop.
10 Rust tests (determinism, variation, bounds, sum invariant).
9 GDScript test stubs + 2 encode tests for client-side pipeline.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Solid implementation with good test coverage. Three warnings.
#
File
Severity
Issue
1
session_manager.gd:38
warning
randi() produces u32 only — upper 32 bits of u64 world_seed always zero. Document limitation or widen entropy.
2
entanglement.rs:183-199
warning
mundane_ratio test asserts [40,60] but D-029 specifies [45,55]. Spec divergence shipped as TODO — must resolve or update D-029.
3
fog_state.gd:11
suggestion
VIS_PERIPHERAL = 180 is dead code — no longer written anywhere. Remove it.
4
test_fog_sprint22.gd:16-20
suggestion
Private field access via get() + push_warning silently passes if fields rename. Consider test-only accessors or fail().
5
fog_state.gd:161-187
suggestion
_grow_bounds() is dead code — replaced by _grow_bounds_from_positions(). Remove or document.
6
layer3.rs:88
suggestion
Only tests seed=42 — zero and max-u64 not exercised at integration level.
Tyre (Architecture): REQUEST_CHANGES
Clean architecture, seed IPC is well-designed. Two warnings block merge.
#
File
Severity
Issue
1
entanglement.rs:187-202
warning
mundane_ratio bounds violate D-029 spec [45,55] — test widens to [40,60] with a TODO. Must fix sampling or update D-029.
2
session_manager.gd + main.rs
warning
world_seed not persisted to save file — resume_game() sends seed=0 to server, breaking deterministic replay (D-010 principle 4).
3
fog.gdshader:9,93-96
suggestion
exp_fade comment says "soft transition" but filter_nearest on exploration_tex makes it a hard step. Comment is misleading.
4
entanglement.rs + main.rs
suggestion
EntanglementConfig::from_rng() never called in production — seed plumbing works but config isn't consumed yet. Intentional scope boundary? Needs tracking ticket.
5
session_manager.gd:24-25
suggestion
game_id hex and world_seed are consecutive outputs from same PRNG — correlated. Mild metagaming concern per D-029.
Verdict: CHANGES REQUESTED
Shared concerns across both reviewers:
mundane_ratio spec divergence — both flagged the [40,60] vs D-029's [45,55]. Fix the sampling or update the spec.
world_seed not in save file (Tyre) — loaded sessions always get seed=0, breaking deterministic replay.
u32 seed entropy (Hoshe) — document the limitation or widen to full u64.
The fog fix (#569) is clean. The entanglement plumbing (#175/#178) is architecturally sound but has these two data integrity gaps that need resolution before merge.
## Review: client → main (type: code)
### Hoshe (Code Quality): REQUEST_CHANGES
Solid implementation with good test coverage. Three warnings.
| # | File | Severity | Issue |
|---|------|----------|-------|
| 1 | `session_manager.gd:38` | warning | `randi()` produces u32 only — upper 32 bits of u64 `world_seed` always zero. Document limitation or widen entropy. |
| 2 | `entanglement.rs:183-199` | warning | `mundane_ratio` test asserts [40,60] but D-029 specifies [45,55]. Spec divergence shipped as TODO — must resolve or update D-029. |
| 3 | `fog_state.gd:11` | suggestion | `VIS_PERIPHERAL = 180` is dead code — no longer written anywhere. Remove it. |
| 4 | `test_fog_sprint22.gd:16-20` | suggestion | Private field access via `get()` + `push_warning` silently passes if fields rename. Consider test-only accessors or `fail()`. |
| 5 | `fog_state.gd:161-187` | suggestion | `_grow_bounds()` is dead code — replaced by `_grow_bounds_from_positions()`. Remove or document. |
| 6 | `layer3.rs:88` | suggestion | Only tests seed=42 — zero and max-u64 not exercised at integration level. |
### Tyre (Architecture): REQUEST_CHANGES
Clean architecture, seed IPC is well-designed. Two warnings block merge.
| # | File | Severity | Issue |
|---|------|----------|-------|
| 1 | `entanglement.rs:187-202` | warning | `mundane_ratio` bounds violate D-029 spec [45,55] — test widens to [40,60] with a TODO. Must fix sampling or update D-029. |
| 2 | `session_manager.gd` + `main.rs` | warning | `world_seed` not persisted to save file — `resume_game()` sends seed=0 to server, breaking deterministic replay (D-010 principle 4). |
| 3 | `fog.gdshader:9,93-96` | suggestion | `exp_fade` comment says "soft transition" but `filter_nearest` on `exploration_tex` makes it a hard step. Comment is misleading. |
| 4 | `entanglement.rs` + `main.rs` | suggestion | `EntanglementConfig::from_rng()` never called in production — seed plumbing works but config isn't consumed yet. Intentional scope boundary? Needs tracking ticket. |
| 5 | `session_manager.gd:24-25` | suggestion | `game_id` hex and `world_seed` are consecutive outputs from same PRNG — correlated. Mild metagaming concern per D-029. |
### Verdict: CHANGES REQUESTED
**Shared concerns across both reviewers:**
1. **`mundane_ratio` spec divergence** — both flagged the [40,60] vs D-029's [45,55]. Fix the sampling or update the spec.
2. **`world_seed` not in save file** (Tyre) — loaded sessions always get seed=0, breaking deterministic replay.
3. **u32 seed entropy** (Hoshe) — document the limitation or widen to full u64.
The fog fix (#569) is clean. The entanglement plumbing (#175/#178) is architecturally sound but has these two data integrity gaps that need resolution before merge.
- Widen world_seed entropy from u32 to full u64 by combining two randi()
calls (Hoshe warning #1)
- Persist world_seed to save directory and restore on resume_game() so
loaded sessions maintain D-010 deterministic replay (Tyre warning #2)
- Constrain EntanglementConfig intrigue range based on flat value so
mundane_ratio stays within D-029 spec [45,55]% (both reviewers)
- Remove dead VIS_PERIPHERAL constant and _grow_bounds() method
- Update test_client_p1 peripheral test for forward-only simplification
- Fix misleading exp_fade shader comment (filter_nearest = hard step)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
GDScript int is i64 — when randi() returns a value with bit 31 set,
left-shifting by 32 sets bit 63, producing a negative i64. MessagePack
encodes this as a negative integer, which Rust rmp_serde rejects when
deserializing as u64, causing ~50% startup failure rate.
Fix: mask bit 31 before shifting in new_game() to cap entropy at 63
bits. Also mask the sign bit in _read_seed_file() to handle save files
written before this fix.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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
Sprint 22 client team deliverables:
#569 — Fix fog system: blocky edges and zero visibility in explored areas
update_from_state()usedvisible_tiles(empty in live server mode) instead ofvisible_positionsfor bounds calculationdebug_explorationmode for diagnostic rendering#175 — Entanglement ratio configuration (world_seed IPC)
StartupMessagestruct withworld_seed: u64added to bridge types#178 — Seed-based variation
EntanglementConfigwithfrom_rng()/from_seed()in server/src/content/entanglement.rsTest results
Known items
Decisions referenced
D-059 (fog shader spec), D-015 (vision cone), D-066 (dual-scale grid), D-029 (entanglement ratios), D-010 (deterministic simulation), D-020 (dumb renderer)
Review: client → main (type: code)
Hoshe (Code Quality): REQUEST_CHANGES
Solid implementation with good test coverage. Three warnings.
session_manager.gd:38randi()produces u32 only — upper 32 bits of u64world_seedalways zero. Document limitation or widen entropy.entanglement.rs:183-199mundane_ratiotest asserts [40,60] but D-029 specifies [45,55]. Spec divergence shipped as TODO — must resolve or update D-029.fog_state.gd:11VIS_PERIPHERAL = 180is dead code — no longer written anywhere. Remove it.test_fog_sprint22.gd:16-20get()+push_warningsilently passes if fields rename. Consider test-only accessors orfail().fog_state.gd:161-187_grow_bounds()is dead code — replaced by_grow_bounds_from_positions(). Remove or document.layer3.rs:88Tyre (Architecture): REQUEST_CHANGES
Clean architecture, seed IPC is well-designed. Two warnings block merge.
entanglement.rs:187-202mundane_ratiobounds violate D-029 spec [45,55] — test widens to [40,60] with a TODO. Must fix sampling or update D-029.session_manager.gd+main.rsworld_seednot persisted to save file —resume_game()sends seed=0 to server, breaking deterministic replay (D-010 principle 4).fog.gdshader:9,93-96exp_fadecomment says "soft transition" butfilter_nearestonexploration_texmakes it a hard step. Comment is misleading.entanglement.rs+main.rsEntanglementConfig::from_rng()never called in production — seed plumbing works but config isn't consumed yet. Intentional scope boundary? Needs tracking ticket.session_manager.gd:24-25game_idhex andworld_seedare consecutive outputs from same PRNG — correlated. Mild metagaming concern per D-029.Verdict: CHANGES REQUESTED
Shared concerns across both reviewers:
mundane_ratiospec divergence — both flagged the [40,60] vs D-029's [45,55]. Fix the sampling or update the spec.world_seednot in save file (Tyre) — loaded sessions always get seed=0, breaking deterministic replay.The fog fix (#569) is clean. The entanglement plumbing (#175/#178) is architecturally sound but has these two data integrity gaps that need resolution before merge.
Pull request closed