Every atlas capture scenario built its body dict without body_radius_km.
Radius is Global's ONLY spacing input (2*pi*R / width), so every Global
golden has been a degenerate block since these scenarios were created — the
map rendered at 0.000 km/gridunit. The fixed rungs were unaffected, since they
derive spacing from the rung's own cell size rather than the body.
That means the "eyeball check against .cache/screenshots baselines"
discipline has been hollow at Global specifically: a baseline that is a solid
rectangle diffs clean against a new solid rectangle. It is how a 2x1 canvas
survived in front of two verification layers.
Adds the real radii to all ten scenarios (Lendel 6238.4, Vethis 6959.3,
Arbour 6711.0, Ferrath 6062.0, Threshold 5503.5), and makes the capture log
course and settlement counts alongside canvas_cells — an empty annotation
layer was previously indistinguishable from a populated one in the log, which
is exactly the signal needed to tell "no rivers" from "rivers not drawn".
Also updates three suites to the corrected Global cache contract: the key now
honours extent (collapsing it meant a resize could never miss), so the shared
_land_global_canvas helper must cache under the extent the viewer will
actually request, and the two make_key tests now assert the real rule —
centre collapsed, extent honoured — instead of the retired sentinel.
Client suite 1830 total / 1804 passed / 0 failed / 26 skipped.
Pair session with Jeroen, 2026-07-27.
Co-Authored-By: Claude <noreply@anthropic.com>
The two-layer client rebuild per D-255(a)(b)(e), replacing the
_canvas.scale continuous-zoom model with one viewer, one path, all six
rungs:
- step_canvas_protocol.gd: StepCanvasRequest/Response codec against
the T-1181 wire contract — incl. the discovered png_bytes subtlety
(rmp_serde without serde_bytes emits a msgpack int-array, not bin;
decode repacks via PackedByteArray before load_png_from_buffer) and
the extent-echo rule (read the server-clamped extent, never assume
the requested one).
- step_canvas/ component: transport (six-rung ladder, cursor-anchored
scroll steps, edge-scroll/WASD pan with re-request on edge crossing,
hard reset-to-Global), RTT terrain layer (Image.set_pixel colorize
per the c1 measured ruling, texture.update reuse on step-cross,
NEAREST coarse / LINEAR fine per rung), unscaled screen-space
annotation sibling (courses + settlement markers at literal px),
in-memory LRU cache (Tier 1; T-1183 layers the disk tiers beneath),
request lifecycle (pending retry, staleness gate, extent echo).
- Full _canvas.scale retirement in the same change: the zoom-scaled
canvas model, the _zs compensation family, select_rung /
MAX_COVERAGE_M / compute_tile_grid, the orbital-mosaic-vs-window
two-path split, _view_zoom/_canonical_fit_zoom — 10 source files
deleted; their 14 test suites deleted with them (T-1157 dead-goldens
rule; replacement visual-capture coverage is re-scoped T-1157).
- Surviving surfaces kept per the ticket: atlas_window_cache.gd's LRU
shape (the ticket's named file atlas_window_tile_set.gd was the
retiring orchestrator; the real LRU shape lives in
atlas_window_cache.gd — cited in step_canvas_cache.gd), overlay
colors, legend/overlay-bar chrome, AtlasViewer descend geometry.
Determinism boundary per D-255(e): the client interpolates only within
the closed server-supplied input set. 7 new gdUnit suites (164 cases)
incl. a real extent-echo bug caught by its own test during
implementation. Full client suite green (exit 0) with the live-gated
suites running against a worktree server build.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>