fix(simulation): PR #191 review round — n-clamp mirror, min_wl band quantization, coalescing coverage, fixture consumer
All seven Hoshe/Tyre findings addressed, none retracted:
- n-clamp/echo/staleness triangle (Tyre C1): client _clamp_window_n_mirror
(bit-for-bit twin of the server clamp, canonicalize_district_center
precedent) applied before _n is stored/sent; server test pins the
quarter n=32 -> echo 16 contract.
- min_wl band quantization (Hoshe 1/Tyre C3): quantize_min_wl_m snaps to
MIN_WL_BANDS_M {0, 32768, 16384, 8192, 4096} before cache key and echo
(design doc §5's unbounded-key fix), reusing the one true
OCTAVE_WAVELENGTHS_M array; docstrings now state the server-quantizes/
client-sends-raw split; same-band cache-sharing test.
- coalescing granularity axis (Hoshe 2): two tests pin different-
granularity requests as separate in-flight slots and same-granularity
coalescing unchanged.
- orphaned fixture (Hoshe 3): test_protocol.gd consumer decodes
atlas_response_ready_with_window.msgpack through the real IPC path and
asserts the new fields.
- atlas_window_request coverage (Hoshe 4): new test file — stale-drop on
granularity mismatch, old-server-shape defaults accepted, clamp mirror
formula + wiring. First draft's quarter-via-request_now test would have
passed for the wrong reason (request_now resets granularity by design
until T-1153) — split into formula pin + reachable-path wiring proof.
- granularity type seam (Tyre C2): field + resolver docstrings state
finer-only integer multiples with resolve_window_granularity as the
single widening point; matching contract note added to the D-226
T-1143-rulings amendment.
cargo --lib 1807/1807; goldens bit-identical; gdlint clean.
This commit is contained in:
@@ -48,6 +48,15 @@ const MAX_RETRIES: int = 20 # ~10s ceiling, matches atlas_generation_proxy.gd's
|
||||
const DEFAULT_GRANULARITY: int = AtlasWindowCache.DISTRICT_GRANULARITY
|
||||
const DEFAULT_MIN_WL_M: int = 0
|
||||
|
||||
## Mirrors server/src/atlas/layer_proxy.rs's DISTRICT_WINDOW_MAX_N /
|
||||
## WIRE_CAP_CELLS exactly (PR #191 review, Tyre C1). `_clamp_window_n_mirror()`
|
||||
## below reproduces `clamp_window_n()` bit-for-bit — the load-bearing-mirror
|
||||
## pattern `AtlasDescendGeometry.canonicalize_district_center()` already uses
|
||||
## for the server's `normalize_window_center()`. Keep both numbers in sync
|
||||
## with the server constants of the same name if either ever changes.
|
||||
const SERVER_DISTRICT_WINDOW_MAX_N: int = 64
|
||||
const SERVER_WIRE_CAP_CELLS: int = 4_096
|
||||
|
||||
var _owner = null # AtlasWindowViewer (untyped to avoid cyclic ref)
|
||||
var _cache = null # AtlasWindowCache
|
||||
var _body_id: String = ""
|
||||
@@ -86,6 +95,38 @@ func reset() -> void:
|
||||
_debounce_timer.stop()
|
||||
|
||||
|
||||
## Mirrors server/src/atlas/layer_proxy.rs's `clamp_window_n(raw_n,
|
||||
## granularity)` EXACTLY (PR #191 review, Tyre C1 — "the sharpest" finding):
|
||||
## `serve_district_window` echoes the CLAMPED `n` back in
|
||||
## `DistrictWindowLayer.n`, but `on_response()`'s staleness guard compares the
|
||||
## echo against `_n`. Without this mirror, `_n` would hold the RAW requested
|
||||
## value while the server echoes the CLAMPED one — the moment a caller
|
||||
## requests quarter (granularity=4) at n=32, the server clamps to n=16 and
|
||||
## echoes THAT, `on_response()` sees `echoed_n=16 != _n=32`, decides the
|
||||
## response is stale, and the window silently never loads (no error, no log
|
||||
## on this side — just an eternally-pending request).
|
||||
##
|
||||
## Clamping HERE, before `_n` is ever stored or sent, means `_n` already
|
||||
## equals what the server will echo — no drift between the two sides, the
|
||||
## SAME load-bearing-mirror pattern `AtlasDescendGeometry.
|
||||
## canonicalize_district_center()` uses for the server's
|
||||
## `normalize_window_center()` (see that function's docstring for the general
|
||||
## rationale: canonicalizing before the request is sent means the client's
|
||||
## held state already equals what the server will echo back).
|
||||
##
|
||||
## Formula, bit-for-bit: `n = raw_n.clamp(1, SERVER_DISTRICT_WINDOW_MAX_N)`,
|
||||
## then `n = min(n, floor(sqrt(SERVER_WIRE_CAP_CELLS) / max(granularity, 1)))`
|
||||
## — applied in that order (per-axis cap first, then the granularity-aware
|
||||
## wire-size ceiling), matching `clamp_window_n`'s own comment ("Applied AFTER
|
||||
## the per-axis clamp so a request that already satisfies
|
||||
## DISTRICT_WINDOW_MAX_N still shrinks further at granularity 4").
|
||||
static func _clamp_window_n_mirror(raw_n: int, granularity: int) -> int:
|
||||
var n: int = clampi(raw_n, 1, SERVER_DISTRICT_WINDOW_MAX_N)
|
||||
var g: int = maxi(granularity, 1)
|
||||
var cap_n: int = int(floor(sqrt(float(SERVER_WIRE_CAP_CELLS)) / float(g)))
|
||||
return mini(n, maxi(cap_n, 1))
|
||||
|
||||
|
||||
## Entry point + pan re-request: request the window centered on `center`
|
||||
## (a DistrictPos-equivalent Vector2i) for `body_id`. Cache hit -> immediate
|
||||
## synchronous window_ready emit, no network traffic at all. Cache miss ->
|
||||
@@ -97,12 +138,12 @@ func reset() -> void:
|
||||
func request_now(body_id: String, center: Vector2i, n: int = DISTRICT_WINDOW_DEFAULT_N) -> void:
|
||||
_body_id = body_id
|
||||
_center = center
|
||||
_n = n
|
||||
_granularity = DEFAULT_GRANULARITY
|
||||
_min_wl_m = DEFAULT_MIN_WL_M
|
||||
_n = _clamp_window_n_mirror(n, _granularity) # Tyre C1 — mirror BEFORE storing/requesting
|
||||
_debounce_timer.stop() # a direct request supersedes any pending debounced one
|
||||
|
||||
var cached: Variant = _cache.get_window(body_id, center, n, _granularity, _min_wl_m)
|
||||
var cached: Variant = _cache.get_window(body_id, center, _n, _granularity, _min_wl_m)
|
||||
if cached != null:
|
||||
_pending = false
|
||||
_retries = 0
|
||||
@@ -111,7 +152,7 @@ func request_now(body_id: String, center: Vector2i, n: int = DISTRICT_WINDOW_DEF
|
||||
|
||||
_pending = true
|
||||
_retries = 0
|
||||
SimBridge.request_atlas_layers(body_id, "Topography", center, n, _granularity, _min_wl_m)
|
||||
SimBridge.request_atlas_layers(body_id, "Topography", center, _n, _granularity, _min_wl_m)
|
||||
|
||||
|
||||
## Pan-triggered re-request (§4/§5: "150ms after the last drag-release, not
|
||||
@@ -122,9 +163,9 @@ func request_now(body_id: String, center: Vector2i, n: int = DISTRICT_WINDOW_DEF
|
||||
func request_debounced(body_id: String, center: Vector2i, n: int = DISTRICT_WINDOW_DEFAULT_N) -> void:
|
||||
_body_id = body_id
|
||||
_center = center
|
||||
_n = n
|
||||
_granularity = DEFAULT_GRANULARITY
|
||||
_min_wl_m = DEFAULT_MIN_WL_M
|
||||
_n = _clamp_window_n_mirror(n, _granularity) # Tyre C1 — mirror BEFORE storing/requesting
|
||||
_debounce_timer.start()
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user