## T-1153 (D-226 T-1143-rulings amendment): tests for the continuous ## cursor-anchored zoom ladder — enter_orbital() (the canonical planetary ## frame), progressive refinement (held composite survives a rung-crossing ## request), the full-zoom-out reset (Jeroen's HARD condition), rung ## reselection on zoom, and E/W wrap + pole-wall clamps at Region ## granularity. Split out of test_atlas_window_viewer.gd (which owns the ## pre-T-1153 window-viewer behavior — entry, cache reuse, WASD/edge-scroll, ## fit-and-center) purely for file-length reasons (gdlint max-file-lines); ## same instantiation/mock-response conventions as that file, not a ## different testing philosophy. class_name TestAtlasZoomLadder extends GdUnitTestSuite const AtlasWindowRequest := preload("res://ui/implant/apps/atlas/atlas_window_request.gd") const AtlasDescendGeometry := preload("res://ui/implant/apps/atlas/atlas_descend_geometry.gd") const AtlasWindowGeometry := preload("res://ui/implant/apps/atlas/atlas_window_geometry.gd") ## Dudley's WINDOW_GRANULARITY_REGION_KEY (server/src/atlas/layer_proxy.rs) — ## `u32::MAX`, a RESERVED KEY-SPACE TAG the real server ALWAYS puts in the ## legacy `granularity` slot for every Region response (never a real ## multiplier — District=1/Quarter=4 are the only legal wire multipliers). ## Do NOT "fix" this to 1 — that would silently un-repro the live-round bug ## this constant exists to guard against (a real server's actual wire byte, ## not a convenient test value). See _echoed_granularity_matches()'s own doc ## (atlas_window_request.gd) for why this value can NEVER equal a client's ## stored `_granularity` (which stays pinned at DISTRICT_GRANULARITY=1 for ## every rung a T-1152-aware client requests) — that mismatch is exactly ## what silently dropped every Region response before the v2-authoritative ## fix. const SERVER_LEGACY_GRANULARITY_REGION_SENTINEL: int = 4294967295 ## Build a hand-authored DistrictWindowLayer dict (n=2 by default) — mirrors ## test_atlas_window_viewer.gd's own _mock_window(). static func _mock_window(center: Vector2i, n: int = 2) -> Dictionary: return { "center": [center.x, center.y], "n": n, "morphology": PackedByteArray([8, 14, 0, 1]), "elev_q": PackedByteArray([40, 90, 5, 60]), "temp_dc": [120, 95, -32768, 60], "moisture_q": PackedByteArray([50, 30, 90, 20]), "vegetation": PackedByteArray([2, 1, 6, 3]), "glaciation": PackedByteArray([0, 0, 1, 2]), } static func _mock_response(body_id: String, window: Variant) -> Dictionary: return {"body_id": body_id, "status": "Ready", "district_window": window} # ============================================================================= # T-1153: enter_orbital() — the canonical planetary frame, the ladder's TOP # REST STATE (Jeroen's HARD condition, D-226 T-1143-rulings amendment). # ============================================================================= ## enter_orbital() must center on district (0,0) — "district (0,0) sits at ## lon 0 / the equator" (AtlasDescendGeometry's own doc). func test_enter_orbital_centers_on_the_canonical_origin() -> void: var v: AtlasWindowViewer = auto_free(AtlasWindowViewer.new()) add_child(v) v.enter_orbital({"body_id": "GJ380c", "body_radius_km": 6238.4}, {}) assert_that(v._held_center).is_equal(Vector2i.ZERO) ## enter_orbital() must request at Region granularity — the orbital view IS ## the Region rung at high n, not a separate screen/mode (the ticket's own ## framing). func test_enter_orbital_requests_region_granularity() -> void: var v: AtlasWindowViewer = auto_free(AtlasWindowViewer.new()) add_child(v) v.enter_orbital({"body_id": "GJ380c", "body_radius_km": 6238.4}, {}) assert_str(v._held_granularity_v2).is_equal("Region") ## **Superseded by live round 3's tiling fix — retargeted, not deleted.** ## GJ380c/Lendel (radius 6238.4 km) was the ORIGINAL single-window C1 repro ## (raw cols ~19,139 vs. the 6,400 clamp ceiling) — but that SAME threshold ## (`DISTRICT_WINDOW_MAX_N_REGION * DISTRICT_M` = the coverage ceiling ## `compute_tile_grid()` tiles past) means any body needing the n-clamp ALSO ## needs tiling: there is no real body where enter_orbital() takes the ## single-window path with a raw `n` big enough to require clamping. ## GJ380c now correctly enters TILE mode (test_enter_orbital_n_is_the_clamped_value_not_raw_circumference's ## old assertion on a single clamped `_held_n` no longer applies — see ## test_enter_orbital_tile_mode_held_n_is_the_whole_body_extent below for ## what `_held_n` means in tile mode instead). The single-window clamp-mirror ## fix itself remains covered: `_enter_at_rung()`'s own doc/the clamp ## mirror's unit tests (test_atlas_window_request.gd) pin the formula ## directly, and test_zoom_crossing_fires_request_and_accepts_wire_accurate_refinement ## exercises the SAME clamp-mirror lesson at the reselect (not entry) ## boundary, which single-window mode still reaches on the way DOWN from a ## tile-mode zoom-in. func test_enter_orbital_tile_mode_held_n_is_the_whole_body_extent() -> void: var v: AtlasWindowViewer = auto_free(AtlasWindowViewer.new()) add_child(v) var radius_km := 6238.4 # GJ380c (Lendel) var extent: Dictionary = AtlasDescendGeometry.district_extent(radius_km) var raw_cols: int = int(extent["cols"]) v.enter_orbital({"body_id": "GJ380c", "body_radius_km": radius_km}, {}) assert_bool(v.is_tile_mode()).override_failure_message( "GJ380c/Lendel needs tiling — enter_orbital() must have entered tile mode" ).is_true() # In TILE mode, _held_n is the WHOLE body's extent (unclamped) — each # TILE clamps its own request independently inside AtlasWindowTileSet # (see that file's own tests), so _held_n here is NOT expected to equal # any single clamped value the way single-window mode's is. assert_int(v._held_n).is_equal(raw_cols) ## Coordinator live-eyeball dossier (2026-07-23, suspect 2 — DIAGNOSED FALSE ## but pinned as a regression guard anyway per the coordinator's own ## instruction): AtlasWindowNatureOverlay's _draw() reads ## viewer.get_held_granularity_v2() to key its per-rung policy tables ## (RIVER_CLASS_VISIBLE_BY_RUNG etc.) — if that accessor returned anything ## other than the EXACT string "Region" while is_tile_mode() is true (an ## empty string, a stale District default, a different-cased tag...), the ## visibility tables would silently return their empty/default disposition ## and NOTHING would draw, indistinguishable from the live captures' ## "literally zero river dots" symptom. Live drive-script evidence ## (NATURE_DEBUG print, since removed) confirmed this was NOT the actual bug ## — get_held_granularity_v2() already correctly returns "Region" in tile ## mode — but this test makes that fact load-bearing instead of merely ## observed once, so a future refactor of _enter_tile_mode()'s ## _held_granularity_v2 assignment trips a named failure here. func test_get_held_granularity_v2_is_exactly_region_string_in_tile_mode() -> void: var v: AtlasWindowViewer = auto_free(AtlasWindowViewer.new()) add_child(v) var radius_km := 6238.4 # GJ380c (Lendel) — needs tiling v.enter_orbital({"body_id": "GJ380c", "body_radius_km": radius_km}, {}) assert_bool(v.is_tile_mode()).override_failure_message( "this test's premise requires tile mode — Lendel must still need tiling" ).is_true() assert_str(v.get_held_granularity_v2()).override_failure_message( "AtlasWindowNatureOverlay's _draw() keys its ENTIRE per-rung policy off" + " this exact string — anything other than the literal 'Region' silently" + " empties every visibility table and draws nothing, indistinguishable" + " from the live-capture symptom (zero river dots at the orbital rest state)" ).is_equal("Region") ## **The live-round-3 regression, end to end for TILE mode:** enter_orbital() ## on GJ380c/Lendel followed by delivering ONE tile's wire-accurate response ## (clamped n=6,400, "Region" granularity_v2, the legacy sentinel in the old ## granularity slot — exactly what a real server sends) must be ACCEPTED ## into that tile's own slot — not silently dropped. This exercises BOTH ## live-round fixes (the v2-authoritative precedence AND per-tile clamping) ## through the tile-set path specifically, complementing ## test_atlas_window_tile_set.gd's own more granular orchestration tests. func test_enter_orbital_tile_mode_accepts_a_wire_accurate_tile_response() -> void: var v: AtlasWindowViewer = auto_free(AtlasWindowViewer.new()) add_child(v) var radius_km := 6238.4 # GJ380c (Lendel) — the live-repro body v.enter_orbital({"body_id": "GJ380c", "body_radius_km": radius_km}, {}) assert_bool(v.is_tile_mode()).is_true() var tile_set = v.get_tile_set() var tiles: Array = tile_set.get_tiles() assert_int(tiles.size()).is_greater(1) var first_tile_center: Vector2i = tiles[0]["center"] var tile_window: Dictionary = { "center": [first_tile_center.x, first_tile_center.y], "n": AtlasWindowRequest.SERVER_DISTRICT_WINDOW_MAX_N_REGION, "granularity": SERVER_LEGACY_GRANULARITY_REGION_SENTINEL, "granularity_v2": "Region", "morphology": PackedByteArray([8, 14, 0, 1]), "elev_q": PackedByteArray([40, 90, 5, 60]), "temp_dc": [120, 95, -32768, 60], "moisture_q": PackedByteArray([50, 30, 90, 20]), "vegetation": PackedByteArray([2, 1, 6, 3]), "glaciation": PackedByteArray([0, 0, 1, 2]), } SimBridge.atlas_layers_received.emit(_mock_response("GJ380c", tile_window)) assert_that(tile_set.get_tiles()[0]["window"]).override_failure_message( "a wire-accurate response (clamped n, Region granularity_v2, the legacy" + " sentinel) for the first tile must be ACCEPTED into that tile's slot" ).is_equal(tile_window) ## A no-radius body (tiny test body) has no circumference concept — ## enter_orbital() falls back to the District-rung default window rather ## than crashing or deriving a degenerate n. func test_enter_orbital_no_radius_body_falls_back_to_district() -> void: var v: AtlasWindowViewer = auto_free(AtlasWindowViewer.new()) add_child(v) v.enter_orbital({"body_id": "GJ380c"}, {}) assert_str(v._held_granularity_v2).is_equal("District") assert_int(v._held_n).is_equal(AtlasWindowRequest.DISTRICT_WINDOW_DEFAULT_N) # ============================================================================= # T-1153: progressive refinement — the held composite survives until the # replacement arrives (§6 "no mode flip": never a blank frame, never a # clear-then-redraw). # ============================================================================= ## The core acceptance test: once a window is held, a request for a ## DIFFERENT rung being in-flight must NOT clear `_window` — the old ## composite stays exactly what get_district_window() returns until the new ## rung's response actually arrives and is adopted. func test_held_window_survives_while_a_different_rung_request_is_in_flight() -> void: var v: AtlasWindowViewer = auto_free(AtlasWindowViewer.new()) add_child(v) v.enter({"body_id": "GJ380c"}, {}, Vector2i(10, 20), 2) var district_window: Dictionary = _mock_window(Vector2i(10, 20), 2) SimBridge.atlas_layers_received.emit(_mock_response("GJ380c", district_window)) assert_that(v.get_district_window()).is_equal(district_window) # Simulate a rung-reselect firing a NEW (Region) request without the # response having arrived yet — direct call, mirroring what # _maybe_reselect_rung() does internally. v._window_request.request_debounced("GJ380c", Vector2i(10, 20), 2, "Region") assert_that(v.get_district_window()).override_failure_message( "the OLD composite must survive while a different-rung request is in" + " flight — no blank frame, no premature clear" ).is_equal(district_window) ## Once the new rung's response actually arrives (matching the CURRENTLY ## in-flight request's granularity_v2), it swaps in — the composite reference ## changes from the old rung's window to the new one. func test_new_rung_window_swaps_in_once_it_arrives() -> void: var v: AtlasWindowViewer = auto_free(AtlasWindowViewer.new()) add_child(v) v.enter({"body_id": "GJ380c"}, {}, Vector2i(10, 20), 2) var district_window: Dictionary = _mock_window(Vector2i(10, 20), 2) SimBridge.atlas_layers_received.emit(_mock_response("GJ380c", district_window)) v._window_request.request_debounced("GJ380c", Vector2i(10, 20), 2, "Region") var region_window: Dictionary = { "center": [10, 20], "n": 2, "granularity_v2": "Region", "morphology": PackedByteArray([1, 2, 3, 4]), "elev_q": PackedByteArray([10, 20, 30, 40]), "temp_dc": [0, 0, 0, 0], "moisture_q": PackedByteArray([0, 0, 0, 0]), "vegetation": PackedByteArray([0, 0, 0, 0]), "glaciation": PackedByteArray([0, 0, 0, 0]), } SimBridge.atlas_layers_received.emit(_mock_response("GJ380c", region_window)) assert_that(v.get_district_window()).override_failure_message( "once the new rung's matching response arrives, it must swap in" ).is_equal(region_window) assert_str(v._held_granularity_v2).is_equal("Region") ## refresh() clear()s via queue_free() (deferred, not synchronous) — a legend ## that has refreshed more than once in the same frame (build-time refresh at ## _ready(), then an entry-time refresh) can have STALE not-yet-freed ## children still parented alongside the new ones. add_component() always ## APPENDS, so the current ImplantHeader is the LAST one in the list, never ## assumed to be [0]. static func _current_legend_header(legend_panel) -> ImplantHeader: var children: Array = legend_panel.get_implant_children() for i in range(children.size() - 1, -1, -1): if children[i] is ImplantHeader: return children[i] return null ## PR #192 review (Araminta, BLOCKING): the legend subtitle used to hardcode ## District's own "2.048 km/cell" — a 100x lie whenever the viewer actually ## holds Region (204.8 km/cell). While in the orbital tile-mode rest state ## (Region granularity), the legend must read Region's real spacing, not the ## stale District literal. func test_legend_subtitle_reflects_region_spacing_in_tile_mode() -> void: var v: AtlasWindowViewer = auto_free(AtlasWindowViewer.new()) add_child(v) var radius_km := 6238.4 # GJ380c (Lendel) — needs tiling, so enters at Region v.enter_orbital({"body_id": "GJ380c", "body_radius_km": radius_km}, {}) assert_bool(v.is_tile_mode()).is_true() assert_str(v._held_granularity_v2).is_equal("Region") var header: ImplantHeader = _current_legend_header(v._legend_panel) assert_str(header._subtitle_label.text).override_failure_message( "legend subtitle must reflect Region's real 204.800 km/cell spacing while" + " the viewer holds Region granularity, not a hardcoded District figure" ).contains("204.800 km/cell") ## Same bug, the other direction: after crossing INTO a single-window District ## rung, the legend must re-render with District's own spacing — proving the ## legend actually refreshes on a rung change rather than being stuck at ## whatever it showed on the FIRST refresh() call (T-1153's _build_legend_panel() ## fires one at _ready() time, before any real rung is held). func test_legend_subtitle_reflects_district_spacing_after_crossing_in() -> void: var v: AtlasWindowViewer = auto_free(AtlasWindowViewer.new()) add_child(v) v.enter({"body_id": "GJ380c"}, {}, Vector2i(10, 20), 2) assert_str(v._held_granularity_v2).is_equal("District") var header: ImplantHeader = _current_legend_header(v._legend_panel) assert_str(header._subtitle_label.text).override_failure_message( "legend subtitle must re-render at District's own 2.048 km/cell spacing" + " once the viewer holds a District-rung window — proving refresh() is" + " actually wired to the rung change, not just called once at build time" ).contains("2.048 km/cell") ## A response for a rung OTHER than what's currently requested (e.g. a ## District response arriving after the viewer has already moved on to a ## Region request — a rapid wheel-zoom race) must be discarded as stale, the ## held composite untouched. func test_stale_rung_response_after_moving_on_is_discarded() -> void: var v: AtlasWindowViewer = auto_free(AtlasWindowViewer.new()) add_child(v) v.enter({"body_id": "GJ380c"}, {}, Vector2i(10, 20), 2) var district_window: Dictionary = _mock_window(Vector2i(10, 20), 2) SimBridge.atlas_layers_received.emit(_mock_response("GJ380c", district_window)) v._window_request.request_debounced("GJ380c", Vector2i(10, 20), 2, "Region") # A LATE district-rung response for the same (center, n) arrives after the # viewer has already moved on to requesting Region — must be dropped. var late_district_window: Dictionary = _mock_window(Vector2i(10, 20), 2) late_district_window["morphology"] = PackedByteArray([9, 9, 9, 9]) # distinguishable payload SimBridge.atlas_layers_received.emit(_mock_response("GJ380c", late_district_window)) assert_that(v.get_district_window()).override_failure_message( "a stale response for a rung the viewer has since moved on from must be discarded" ).is_equal(district_window) # ============================================================================= # T-1153: full-zoom-out reset (Jeroen's HARD condition). # ============================================================================= ## Directly at the canonical frame already (center (0,0), Region granularity) ## must be a no-op — never re-fights a player zooming back IN from the top. func test_reset_to_canonical_frame_is_noop_when_already_there() -> void: var v: AtlasWindowViewer = auto_free(AtlasWindowViewer.new()) add_child(v) v.enter_orbital({"body_id": "GJ380c", "body_radius_km": 6238.4}, {}) v._held_center = Vector2i.ZERO v._held_granularity_v2 = "Region" var fired: bool = v._maybe_reset_to_canonical_frame() assert_bool(fired).override_failure_message( "already at the canonical frame — the reset must not re-fire" ).is_false() ## A no-radius body must never trigger the reset (no circumference concept — ## matches enter_orbital()'s own guard). func test_reset_to_canonical_frame_never_fires_for_no_radius_body() -> void: var v: AtlasWindowViewer = auto_free(AtlasWindowViewer.new()) add_child(v) v.enter({"body_id": "GJ380c"}, {}, Vector2i(5, 5), 2) var fired: bool = v._maybe_reset_to_canonical_frame() assert_bool(fired).is_false() ## Away from the canonical frame (a drifted District-rung pan/zoom state) ## with a fully-zoomed-out world extent must reset — the direct wiring test ## for Jeroen's HARD condition: enter() at a far-off center, then force the ## view zoom low enough that the displayed extent covers the whole body. func test_reset_to_canonical_frame_fires_and_re_centers_when_fully_zoomed_out() -> void: var v: AtlasWindowViewer = auto_free(AtlasWindowViewer.new()) add_child(v) var radius_km := 50.0 # tiny synthetic body — small circumference, reachable by a modest zoom-out v.enter({"body_id": "GJ380c", "body_radius_km": radius_km}, {}, Vector2i(500, 10), 32) # Force a very low zoom — a huge displayed world extent, comfortably over # this tiny body's whole circumference. v._view_zoom = AtlasWindowViewer.MIN_ZOOM var fired: bool = v._maybe_reset_to_canonical_frame() assert_bool(fired).override_failure_message( "a fully-zoomed-out view on a real-radius body must trigger the reset" ).is_true() assert_that(v._held_center).override_failure_message( "the reset must re-center on the canonical origin (0,0)" ).is_equal(Vector2i.ZERO) assert_str(v._held_granularity_v2).override_failure_message( "the reset must land on the Region rung — the ladder's top rest state" ).is_equal("Region") ## Live round 5's OWN repro, end to end: enter a TILING body's canonical ## frame, wheel-zoom IN far enough to cross out of tile mode (leaving ## `_held_granularity_v2` STALE at "Region" — a real, expected lag per ## `_maybe_reselect_rung()`'s own "does NOT touch _held_granularity_v2" ## doc, not a bug in that function), then wheel-zoom back OUT past the ## fully-zoomed-out threshold. The reset must fire and land EXACTLY on ## enter_orbital()'s own fit zoom for this body/viewport — not merely ## re-center while leaving `_view_zoom` wherever continued `_zoom_at()` ## scaling left it. Before the fix, the stale "Region" granularity ## satisfied the guard's OLD (center + granularity only) check forever, ## so the reset never fired again and `_view_zoom` kept shrinking via ## plain multiplication all the way to MIN_ZOOM. func test_reset_after_crossing_out_and_back_snaps_to_the_canonical_fit_zoom() -> void: var v: AtlasWindowViewer = auto_free(AtlasWindowViewer.new()) add_child(v) v.size = Vector2(1600.0, 900.0) var radius_km := 6238.4 # GJ380c (Lendel) — a tiling body, the live-repro shape v.enter_orbital({"body_id": "GJ380c", "body_radius_km": radius_km}, {}) assert_bool(v.is_tile_mode()).override_failure_message( "sanity: Lendel must enter tile mode — this repro needs a TILING body," + " since that's where _held_granularity_v2 can lag is_tile_mode()" ).is_true() # Zoom IN far enough to cross out of tile mode (matching # test_zoom_crossing_recomputes_view_offset_so_the_new_window_is_on_screen's # own gesture shape). var cursor_pos := Vector2(800.0, 450.0) for _i in range(60): v._zoom_at(cursor_pos, 1.15) if not v.is_tile_mode(): break assert_bool(v.is_tile_mode()).override_failure_message( "sanity: this test needs to actually leave tile mode before zooming back out" ).is_false() assert_str(v._held_granularity_v2).override_failure_message( "sanity: _held_granularity_v2 must be STALE at Region here (no mock response" + " ever adopted a new value) — this is the exact lagging-field condition" + " the guard fix targets, not an artificial setup" ).is_equal("Region") # Zoom back OUT past the fully-zoomed-out threshold — the reset must fire # (possibly after a few more _zoom_at() ticks, matching a real wheel # gesture rather than asserting it fires on the very first step back). for _i in range(200): v._zoom_at(cursor_pos, 1.0 / 1.05) if v.is_tile_mode(): break assert_bool(v.is_tile_mode()).override_failure_message( "zooming back out past the threshold must re-fire the reset and land back" + " in tile mode — the stale-granularity guard bug left this permanently false" ).is_true() assert_that(v._held_center).is_equal(Vector2i.ZERO) var extent: Dictionary = AtlasDescendGeometry.district_extent(radius_km) var n: int = int(extent["cols"]) var expected_fit: Dictionary = AtlasWindowGeometry.fit_window_view( v.size, n, AtlasWindowViewer.CELL_PIXEL_SIZE, AtlasWindowViewer.MIN_ZOOM, AtlasWindowViewer.MAX_ZOOM ) assert_float(v._view_zoom).override_failure_message( ( "post-reset _view_zoom (%.6f) must equal enter_orbital()'s own fit zoom" + " (%.6f) for this body/viewport — Jeroen's condition is the ORIGINAL" + " frame (center AND offset AND fit zoom), not merely re-centered at" + " whatever zoom continued _zoom_at() scaling left behind" ) % [v._view_zoom, expected_fit["zoom"]] ).is_equal_approx(float(expected_fit["zoom"]), 0.000001) ## Live round 5's OWN live-drive repro, exactly: a REAL wheel gesture does ## NOT stop the instant the reset first fires — the coordinator's own ## tmp_drive_ladder.gd keeps sending wheel-down ticks toward a fixed target ## zoom (0.004, chosen below the fit zoom) regardless of the reset. This ## test reproduces that shape directly: continue zooming out PAST the point ## where the reset first re-enters tile mode, all the way to a target zoom ## BELOW the fit value. Before the round-5 fix, `_view_zoom` drifted back ## down from the fit value on every subsequent `_zoom_at()` tick while the ## mode/center/granularity guard read "already canonical" and silently let ## it drift, landing on whatever the LOOP's target zoom happened to be ## instead of the fit value. **Live round 6 update:** the MECHANISM that ## now holds this assertion changed — `_zoom_at()`'s own zoom FLOOR (not a ## re-firing reset) is what keeps `_view_zoom` pinned at fit through ## continued zoom-out ticks; see `_maybe_reset_to_canonical_frame()`'s own ## doc for why re-firing on every tick caused a request storm. This test's ## own assertions are unchanged — only the doc below was updated to match. func test_reset_resnaps_even_after_continued_zoom_out_past_the_first_reset() -> void: var v: AtlasWindowViewer = auto_free(AtlasWindowViewer.new()) add_child(v) v.size = Vector2(1600.0, 900.0) var radius_km := 6238.4 # GJ380c (Lendel) — the live-repro body v.enter_orbital({"body_id": "GJ380c", "body_radius_km": radius_km}, {}) var extent: Dictionary = AtlasDescendGeometry.district_extent(radius_km) var n: int = int(extent["cols"]) var expected_fit: Dictionary = AtlasWindowGeometry.fit_window_view( v.size, n, AtlasWindowViewer.CELL_PIXEL_SIZE, AtlasWindowViewer.MIN_ZOOM, AtlasWindowViewer.MAX_ZOOM ) var fit_zoom: float = float(expected_fit["zoom"]) # Zoom IN far enough to leave tile mode (same shape as the test above). var cursor_pos := Vector2(1100.0, 300.0) # matches tmp_drive_ladder.gd's own aim point for _i in range(60): v._zoom_at(cursor_pos, 1.15) if not v.is_tile_mode(): break assert_bool(v.is_tile_mode()).is_false() # Zoom back OUT toward a target BELOW the fit zoom — matching # tmp_drive_ladder.gd's own `_zoom_until(wv, 0.004, false)` exactly # (Lendel's own fit zoom is ~0.00627, comfortably above this target), # WITHOUT stopping early the moment tile mode is first regained. A real # wheel gesture has no way to know when the reset internally fires. var target_zoom := 0.004 for _i in range(200): if v._view_zoom <= target_zoom: break v._zoom_at(cursor_pos, 1.0 / 1.05) assert_bool(v.is_tile_mode()).override_failure_message( "after continued zoom-out past the reset point, the view must settle back" + " into tile mode — a genuinely re-snapped canonical frame can't have zoomed" + " OUT further than the fit value in the first place" ).is_true() assert_float(v._view_zoom).override_failure_message( ( "post-reset _view_zoom (%.6f) must equal the canonical fit zoom (%.6f) even" + " though the wheel gesture continued past the point where the reset first" + " fired (target was %.6f, BELOW the fit zoom) — _zoom_at()'s own zoom floor" + " must keep pinning it at fit through every subsequent tick, not just once" ) % [v._view_zoom, fit_zoom, target_zoom] ).is_equal_approx(fit_zoom, 0.000001) ## Live round 6's ANTI-STORM test — the exact repro the coordinator's live ## drive caught: drive a REAL continued zoom-out gesture (via `_zoom_at()`, ## the same call path the live drive uses — NOT calling ## `_maybe_reset_to_canonical_frame()` directly with unchanged state, which ## trivially can't reproduce the drift the storm depends on) many ticks past ## the point where the reset first fires — asserts ZERO additional tile-set ## entries occur across the WHOLE gesture. Spies on `AtlasWindowTileSet`'s ## own child `AtlasWindowRequest` node INSTANCES (captured right after the ## FIRST reset) — a fresh `enter_orbital()` call tears down (`queue_free()`s) ## every one of them and creates BRAND NEW ones, so "the same node ## instances are still alive and still the tile set's children after 100 ## more ticks" is a direct, non-invasive proxy for "the reset never fired ## again" — no new production instrumentation needed. Before the round-6 ## fix, `_zoom_at()`'s continued multiplicative zoom-out drifted `_view_zoom` ## below fit on every subsequent tick, the level-triggered guard read "not ## already there" every time, and `enter_orbital()` fired repeatedly: ## tearing down and recreating the tile set (and its 6 request nodes) every ## tick — exactly the "889 of 897 wire responses arrived during one ## zoom-out phase" storm. func test_reset_evaluated_repeatedly_at_canonical_frame_issues_zero_additional_requests() -> void: var v: AtlasWindowViewer = auto_free(AtlasWindowViewer.new()) add_child(v) v.size = Vector2(1600.0, 900.0) var radius_km := 6238.4 # GJ380c (Lendel) — a tiling body, the live-repro shape v.enter_orbital({"body_id": "GJ380c", "body_radius_km": radius_km}, {}) assert_bool(v.is_tile_mode()).is_true() # Zoom IN far enough to leave tile mode, then zoom back OUT past the # first reset — same shape as the round-5 continued-zoom-out test, but # this time spying on the tile set across the WHOLE remaining gesture # instead of only checking the final zoom value. var cursor_pos := Vector2(1100.0, 300.0) # matches tmp_drive_ladder.gd's own aim point for _i in range(60): v._zoom_at(cursor_pos, 1.15) if not v.is_tile_mode(): break assert_bool(v.is_tile_mode()).is_false() for _i in range(200): v._zoom_at(cursor_pos, 1.0 / 1.05) if v.is_tile_mode(): break assert_bool(v.is_tile_mode()).override_failure_message( "sanity: the first reset must have fired before spying on the tile set" ).is_true() var tile_set = v.get_tile_set() var original_requests: Array = tile_set.get_children() assert_int(original_requests.size()).override_failure_message( "sanity: the first reset must have created real tile-request child nodes to spy on" ).is_greater(0) # Continue the SAME zoom-out gesture 100 MORE ticks past the first # reset — a real wheel gesture has no way to stop exactly at the reset # point, and holding the wheel down (or residual scroll momentum) keeps # sending ticks. None of these must tear down/recreate the tile set. for _i in range(100): v._zoom_at(cursor_pos, 1.0 / 1.05) var current_requests: Array = tile_set.get_children() assert_int(current_requests.size()).override_failure_message( "the tile set's child count must be unchanged after 100 more continued" + " zoom-out ticks — a changed count means teardown/recreate happened" ).is_equal(original_requests.size()) for i in range(original_requests.size()): assert_bool(is_instance_valid(original_requests[i])).override_failure_message( "original tile-request node #%d must still be alive — a storm would have" + " queue_free()'d it and created a fresh one" % i ).is_true() assert_bool(is_same(original_requests[i], current_requests[i])).override_failure_message( ( "tile-request node #%d must be the SAME instance as right after the" + " first reset — a different object at the same index means the tile" + " set was torn down and recreated (a storm), even if the count" + " coincidentally matches" ) % i ).is_true() ## Live round 6's BLACK-ENTRY repro: enter_orbital(), then deliver the six ## wire-accurate tile responses WHILE a REAL continued zoom-out gesture (via ## `_zoom_at()`, matching the live drive's actual input shape — a held ## wheel-down keeps sending ticks concurrently with responses streaming in ## from the server) is in flight — asserts all six are accepted and HELD ## (tile set stable throughout, no teardown between delivery and the final ## assertion). Before the round-6 fix, the level-triggered guard fired on ## every zoom-out tick once `_view_zoom` drifted below fit, tearing down the ## tile set mid-delivery and orphaning responses addressed to now-freed ## request nodes — nothing ever accumulated, and the mosaic stayed black ## even though the server dutifully answered every request. func test_six_tile_responses_survive_concurrent_reset_evaluation_and_are_held() -> void: var v: AtlasWindowViewer = auto_free(AtlasWindowViewer.new()) add_child(v) v.size = Vector2(1600.0, 900.0) var radius_km := 6238.4 # GJ380c (Lendel) — 6 tiles, the live-repro shape v.enter_orbital({"body_id": "GJ380c", "body_radius_km": radius_km}, {}) assert_bool(v.is_tile_mode()).is_true() var tile_set = v.get_tile_set() var tiles: Array = tile_set.get_tiles() assert_int(tiles.size()).override_failure_message( "sanity: Lendel must produce Lendel's own real tile count (6) for this" + " repro to be faithful, not a smaller synthetic count" ).is_equal(6) # Same continued zoom-out gesture as the anti-storm test above — leave # tile mode, cross back into it (the first reset), then KEEP sending # zoom-out ticks (a real held wheel has no way to stop exactly at the # reset point). Responses are delivered interleaved with these ticks, # exactly matching the live drive's concurrent shape. var cursor_pos := Vector2(1100.0, 300.0) for _i in range(60): v._zoom_at(cursor_pos, 1.15) if not v.is_tile_mode(): break assert_bool(v.is_tile_mode()).is_false() for _i in range(200): v._zoom_at(cursor_pos, 1.0 / 1.05) if v.is_tile_mode(): break assert_bool(v.is_tile_mode()).override_failure_message( "sanity: the first reset must have fired before delivering responses" ).is_true() for i in range(tiles.size()): var center: Vector2i = tiles[i]["center"] var tile_window: Dictionary = { "center": [center.x, center.y], "n": AtlasWindowRequest.SERVER_DISTRICT_WINDOW_MAX_N_REGION, "granularity": SERVER_LEGACY_GRANULARITY_REGION_SENTINEL, "granularity_v2": "Region", "morphology": PackedByteArray([8, 14, 0, 1]), "elev_q": PackedByteArray([40, 90, 5, 60]), "temp_dc": [120, 95, -32768, 60], "moisture_q": PackedByteArray([50, 30, 90, 20]), "vegetation": PackedByteArray([2, 1, 6, 3]), "glaciation": PackedByteArray([0, 0, 1, 2]), } SimBridge.atlas_layers_received.emit(_mock_response("GJ380c", tile_window)) # Interleave several MORE continued zoom-out ticks, matching the live # drive's per-frame cadence — none of these must tear anything down. for _tick in range(5): v._zoom_at(cursor_pos, 1.0 / 1.05) var final_tiles: Array = tile_set.get_tiles() assert_int(final_tiles.size()).override_failure_message( "the tile set must still have all 6 tile slots — a storm mid-delivery" + " would have torn it down and rebuilt it with fresh (unfulfilled) slots" ).is_equal(6) for i in range(final_tiles.size()): assert_that(final_tiles[i]["window"]).override_failure_message( ( "tile #%d's window must be HELD (non-null) — all six wire-accurate" + " responses delivered during a concurrent continued zoom-out gesture" + " must survive to be accepted, not be silently dropped by an" + " orphaning teardown" ) % i ).is_not_null() ## Not fully zoomed out (a normal District-rung view) must NOT trigger the ## reset — only reaching the top of the ladder resets, not every zoom step. func test_reset_to_canonical_frame_does_not_fire_when_not_fully_zoomed_out() -> void: var v: AtlasWindowViewer = auto_free(AtlasWindowViewer.new()) add_child(v) v.enter({"body_id": "GJ380c", "body_radius_km": 6238.4}, {}, Vector2i(500, 10), 32) v._view_zoom = 1.0 # a normal, non-extreme zoom — nowhere near full planetary coverage var fired: bool = v._maybe_reset_to_canonical_frame() assert_bool(fired).override_failure_message( "an ordinary District-rung view must not trigger the top-rest-state reset" ).is_false() # ============================================================================= # T-1153: rung reselection — _zoom_at() crossing a rung threshold fires a # new request without touching the held composite. # ============================================================================= ## Zooming OUT far enough from a District-rung window (small n, so a modest ## zoom-out already covers a huge world extent) must fire a coarser-rung ## request — the wheel-zoom-driven wiring test for _maybe_reselect_rung(). func test_zoom_out_past_district_threshold_requests_a_coarser_rung() -> void: var v: AtlasWindowViewer = auto_free(AtlasWindowViewer.new()) add_child(v) v.size = Vector2(800.0, 600.0) v.enter({"body_id": "GJ380c"}, {}, Vector2i(0, 0), 2) # n=2 — a tiny window, easy to overshoot var district_window: Dictionary = _mock_window(Vector2i(0, 0), 2) SimBridge.atlas_layers_received.emit(_mock_response("GJ380c", district_window)) assert_str(v._window_request.get_granularity_v2()).is_equal("District") # A big zoom-OUT factor (well under 1.0) from a tiny n=2 window blows the # displayed world extent WAY past District's threshold. v._zoom_at(Vector2(400.0, 300.0), 0.01) assert_str(v._window_request.get_granularity_v2()).override_failure_message( "zooming out far enough from a small District window must re-request a coarser rung" ).is_not_equal("District") # The OLD composite must still be what's held — progressive refinement, # not a block-on-derive clear. assert_that(v.get_district_window()).is_equal(district_window) ## Zooming IN on a District-rung window (well within its own legal coverage ## band, `(32,768 m, 131,072 m]` per select_rung()'s redesigned per-rung ## ceiling model — viewport-independent since `canvas_px` no longer affects ## selection) must NOT trigger a rung change — this is the "zoom is ## client-side on the already-held composite" case, unchanged for in-rung ## zoom. Sets _view_zoom DIRECTLY to a value inside District's band (rather ## than relying on enter()'s COVER auto-fit, which for a small n can already ## sit right at Quarter's own threshold — a fit's zoom level is a ## display-density choice independent of what rung selection would pick from ## scratch, and this test is specifically about a SINGLE zoom-in STEP not ## crossing a boundary, not about where the auto-fit itself lands). The ## small 100x80 viewport here is incidental (any size works under the new ## viewport-independent model) — kept small only because that's what the ## original version of this test used. func test_zoom_in_within_district_threshold_does_not_change_rung() -> void: var v: AtlasWindowViewer = auto_free(AtlasWindowViewer.new()) add_child(v) v.size = Vector2(100.0, 80.0) v.enter({"body_id": "GJ380c"}, {}, Vector2i(0, 0), 32) var district_window: Dictionary = _mock_window(Vector2i(0, 0), 32) SimBridge.atlas_layers_received.emit(_mock_response("GJ380c", district_window)) v._view_zoom = 0.10666666666666667 # E=120,000m at C=100px — inside District's legal band v._apply_transform() v._zoom_at(Vector2(50.0, 40.0), 1.15) # a single ordinary zoom-in step assert_str(v._window_request.get_granularity_v2()).override_failure_message( "a single ordinary zoom-in step must not cross a rung threshold" ).is_equal("District") ## **Live round 3 regression, the direct end-to-end fix target:** a real ## wheel-zoom gesture (many `_zoom_at()` ticks, matching the shape a ## continuous mouse-wheel scroll actually produces) crossing from the ## Region rest state down through District into Quarter territory must (i) ## fire a request at the NEW granularity — `_window_request.get_granularity_v2()` ## must have changed by the end of the gesture — and (ii) accept a ## WIRE-ACCURATE response for that request: echoing the REQUEST's own ## (already re-centered, already re-clamped) center/n, which the live round ## found DIFFERS from the ORIGINAL held center (screen-center-anchored ## refinement re-centers on wherever the cursor currently maps to, not ## wherever the player started) — this is the "second latent drop" the ## coordinator specifically flagged: comparing the echo against a STALE ## `_held_center` (frozen at the pre-crossing value) rather than the ## request's own center would silently drop this response too. ## **Live round 3 update:** GJ380c/Lendel now enters TILE mode via ## enter_orbital() (bug B's fix), so this test starts from THERE — zooming ## in far enough crosses Region's coverage ceiling and must LEAVE tile mode ## for the single-window path at the new (finer) rung, exactly the ## `_maybe_reselect_rung()` "leaving_tile_mode" branch this test exercises. func test_zoom_crossing_fires_request_and_accepts_wire_accurate_refinement() -> void: var v: AtlasWindowViewer = auto_free(AtlasWindowViewer.new()) add_child(v) v.size = Vector2(1600.0, 900.0) var radius_km := 6238.4 # GJ380c (Lendel) — the live-repro body v.enter_orbital({"body_id": "GJ380c", "body_radius_km": radius_km}, {}) assert_bool(v.is_tile_mode()).override_failure_message( "GJ380c/Lendel must enter tile mode at the orbital rest state (live round 3)" ).is_true() # A real wheel-zoom gesture: many ticks, cursor OFF-CENTER (so cursor- # anchored zoom genuinely drifts the screen-to-district mapping away from # the canonical origin, not just scaling in place) — matching the live # drive's actual input shape, not a single synthetic jump. Zooming in far # enough must cross OUT of Region's coverage ceiling, leaving tile mode. var cursor_pos := Vector2(1100.0, 300.0) # off-center, biased toward one quadrant for _i in range(60): v._zoom_at(cursor_pos, 1.15) if not v.is_tile_mode(): break # (i) Tile mode must have been LEFT, and a request must have gone out at # a NEW (finer) granularity via the single-window path. assert_bool(v.is_tile_mode()).override_failure_message( "zooming in far enough must leave tile mode for the single-window path" ).is_false() var request_granularity: String = v._window_request.get_granularity_v2() assert_str(request_granularity).override_failure_message( "leaving tile mode must fire a request at a new (finer) granularity" ).is_not_equal("Region") # (ii) The request's own center/n — read AFTER leaving tile mode, so this # is whatever _maybe_reselect_rung() actually computed — is what a # wire-accurate response must echo to be accepted. var request_center: Vector2i = v._window_request._center var request_n: int = v._window_request._n var refinement_window: Dictionary = { "center": [request_center.x, request_center.y], "n": request_n, "granularity_v2": request_granularity, "morphology": PackedByteArray([1, 2, 3, 4]), "elev_q": PackedByteArray([10, 20, 30, 40]), "temp_dc": [0, 0, 0, 0], "moisture_q": PackedByteArray([0, 0, 0, 0]), "vegetation": PackedByteArray([0, 0, 0, 0]), "glaciation": PackedByteArray([0, 0, 0, 0]), } SimBridge.atlas_layers_received.emit(_mock_response("GJ380c", refinement_window)) assert_that(v.get_district_window()).override_failure_message( "a wire-accurate refinement response (echoing the REQUEST's own center/n/" + " granularity after leaving tile mode) must be ACCEPTED — comparing" + " against a stale/wrong reference instead of the request's own would" + " silently drop this response forever" ).is_equal(refinement_window) assert_str(v._held_granularity_v2).is_equal(request_granularity) ## Live round 4's SECOND bug, pinned directly: `_maybe_reselect_rung()` must ## recompute `_view_offset` (via AtlasWindowGeometry. ## recompute_offset_for_held_n_change()) the instant `_held_n` changes across ## a rung crossing — leaving it untouched (the round-4 bug) means the single- ## window `Rect2(0,0,extent)` draw call renders at whatever screen position ## the OLD (Region-scale) offset happened to put canvas-local (0,0), which ## for a whole-body `held_n` vs. a 64-district District `held_n` is tens or ## hundreds of thousands of px away from the viewport — the exact "pitch ## black" repro. Asserts the NEW held window's own extent actually overlaps ## the viewport after the crossing, the concrete on-screen consequence a ## stale offset breaks. func test_zoom_crossing_recomputes_view_offset_so_the_new_window_is_on_screen() -> void: var v: AtlasWindowViewer = auto_free(AtlasWindowViewer.new()) add_child(v) v.size = Vector2(1600.0, 900.0) var radius_km := 6238.4 # GJ380c (Lendel) — the live-repro body v.enter_orbital({"body_id": "GJ380c", "body_radius_km": radius_km}, {}) assert_bool(v.is_tile_mode()).is_true() var cursor_pos := Vector2(1100.0, 300.0) for _i in range(60): v._zoom_at(cursor_pos, 1.15) if not v.is_tile_mode(): break assert_bool(v.is_tile_mode()).override_failure_message( "sanity: this test needs to actually cross out of tile mode to exercise" + " the held_n change _maybe_reselect_rung() must react to" ).is_false() # The new (post-crossing) window's screen-space rect, using the SAME # formula the overlay's single-window _draw() itself uses # (Rect2(0,0,extent,extent) in canvas-local space, then _canvas's own # position/scale transform — _view_offset/_view_zoom here mirror that # exactly, since _apply_transform() is what sets _canvas.position/scale). var extent_screen: float = float(v._held_n) * v.CELL_PIXEL_SIZE * v._view_zoom var screen_top_left: Vector2 = v._view_offset var screen_bottom_right: Vector2 = screen_top_left + Vector2(extent_screen, extent_screen) var viewport_rect := Rect2(Vector2.ZERO, v.size) var window_rect := Rect2(screen_top_left, Vector2(extent_screen, extent_screen)) assert_bool(viewport_rect.intersects(window_rect)).override_failure_message( ( "the new (post-crossing) held window's screen rect %s must overlap the" + " viewport %s — a stale _view_offset (never recomputed for the new" + " held_n=%d) is exactly live round 4's 'pitch black' bug: the composite" + " renders somewhere entirely off-canvas despite request/response/data" + " all being individually correct" ) % [window_rect, viewport_rect, v._held_n] ).is_true() # ============================================================================= # T-1153: E/W wrap and pole-wall clamps at EVERY rung — both are extent- # relative (CELL_PIXEL_SIZE-based district-space math, unchanged regardless # of which rung's data is actually held), so they must keep working # unmodified at Region granularity, not just District/Quarter. # ============================================================================= ## The pole wall, wired through the real _apply_pan_delta() path, must still ## clamp at Region granularity — same mechanism as the existing District-rung ## test (test_wasd_pan_is_clamped_by_the_pole_wall_when_wired), just entered ## via enter_orbital() instead of enter(). func test_pole_wall_clamps_at_region_granularity_too() -> void: var v: AtlasWindowViewer = auto_free(AtlasWindowViewer.new()) add_child(v) v.size = Vector2(800.0, 800.0) var radius_km := 50.0 # tiny synthetic body — pole wall reachable by an ordinary tick v.enter_orbital({"body_id": "GJ380c", "body_radius_km": radius_km}, {}) assert_str(v._held_granularity_v2).is_equal("Region") var unclamped_magnitude: float = 500.0 * AtlasWindowViewer.PAN_SPEED_CANVAS_PX_S * v.get_view_zoom() v._apply_pan_delta(Vector2(0.0, -1.0), 500.0) # "W"/north held, an absurdly long tick assert_float(absf(v.get_view_offset().y)).override_failure_message( "the pole wall must still clamp an extreme pan at Region granularity" ).is_less(unclamped_magnitude * 0.5) ## East-west wrap (canonicalize_district_center()) must still apply to the ## pan-edge refloat's resulting center at Region granularity — a pan that ## carries the screen-center column past the body's circumference must wrap ## into [0, cols), never run away to an out-of-range column, exactly as the ## District-rung wrap tests already pin (T-1142 item 6a). At Region's own ## enormous held_n (a whole circumference), an ORDINARY pan tick's ## canvas-space delta is negligible relative to the window's half-extent ## (confirmed: ~0.08 districts per 5-second tick vs. a ~9,772-district ## half-window) — so this drives _maybe_refloat_window() DIRECTLY off a ## manually-set _view_offset large enough to genuinely cross the held ## window's edge, the same "exercise the actual edge-crossing branch, not ## just its no-op early-return" discipline _maybe_refloat_window()'s own ## inside-check comment describes. func test_pan_edge_refloat_wraps_columns_at_region_granularity_too() -> void: var v: AtlasWindowViewer = auto_free(AtlasWindowViewer.new()) add_child(v) v.size = Vector2(800.0, 800.0) var radius_km := 6371.0 var extent: Dictionary = AtlasDescendGeometry.district_extent(radius_km) var cols: int = int(extent["cols"]) v.enter_orbital({"body_id": "GJ380c", "body_radius_km": radius_km}, {}) assert_str(v._held_granularity_v2).is_equal("Region") # Force the held center to sit one column short of the wrap seam, then # shift the CANVAS offset by more than half the window's own on-screen # extent — enough to move the screen-center's mapped column past the # window's far edge (i.e. past `cols`, crossing the seam) regardless of # Region's huge held_n. v._held_center = Vector2i(cols - 1, 0) var half_window_screen_px: float = float(v._held_n) * v.get_cell_pixel_size() * v.get_view_zoom() * 0.5 v._view_offset = v.get_view_offset() - Vector2(half_window_screen_px * 1.5, 0.0) v._maybe_refloat_window() assert_int(v._held_center.x).override_failure_message( "a pan crossing the antimeridian at Region granularity must wrap the" + " resulting center into [0, cols), never run past cols" ).is_less(cols) assert_int(v._held_center.x).is_greater_equal(0)