diff --git a/docs/architecture/atlas-zoom-ladder-t1143.md b/docs/architecture/atlas-zoom-ladder-t1143.md new file mode 100644 index 000000000..da0ad7c1c --- /dev/null +++ b/docs/architecture/atlas-zoom-ladder-t1143.md @@ -0,0 +1,213 @@ +--- +title: "Atlas Zoom Ladder — T-1143 Design Pass" +description: Continuous-derivation zoom ladder from planetary map to tile scale, per D-166's 2026-07-21 amendment + corollary +type: design +status: draft — pending Jeroen decisions +round: T-1143 +created: 2026-07-21 +--- + +# Atlas Zoom Ladder — T-1143 Design Pass + +Contributors: Tyre (architecture), Dudley (derivation/cost), Araminta (encoding), Troblum (adversarial critique), Qatux (synthesis). Grounded in D-166 (+ 2026-07-21 amendment & corollary), D-226 (+ T-1112/T-1124/T-1145 amendments), D-227 (+ T-1125), D-243, D-201, T-1143 full ticket text. + +--- + +## 1. The mandate + +**D-166, Amendment 2026-07-21 (operative text):** + +> "the Atlas must provide a **continuous zoom ladder from the planetary map down to tile scale**, where every zoom level shows **deterministically calculated information at that level's native granularity** ('LoD on the information in view'), never magnified interpolation of a coarser composite." + +**Corollary, same day:** + +> "the authored heightmap PNGs are thereby demoted to **invisible input to the seed/derivation calculation** — no zoom level displays them directly, *including the orbital/planetary level*, which must itself be **fully derived**. Display at every rung samples the derivation at **canvas resolution** … The `import_heightmaps` bake into systems.db survives as derivation *input* storage only." + +Evidence clause (Lendel, R=6238 km): one heightmap px ≈ 19 districts, so the 16-district window was sub-pixel vs. its source; the real waterline sat ~36 districts from the pixel-edge estimate. All window-scale-and-below information is D-227 invented detail that must be *derived*, not smoothed. + +**Hard gate:** T-750 (Phase 4) does not close until the ladder stands. BHAG unchanged. **This pass is design only** — implementation is follow-up tickets. **The D-226(d) floor question is explicitly not decided here** — presented to Jeroen in §10. + +--- + +## 2. The ladder + +Rungs are a property of **derivation granularity** (the finest classification spacing available at a scale), not display — display always samples at canvas resolution (§5). Region and orbital rows are named for completeness; only district and quarter have committed derivation code paths today. + +| Rung | Spacing | Derivation mode | Per-window cost (release) | Wire shape | Status | +|---|---|---|---|---|---| +| Orbital/planetary | region-band, ≥205 km octaves | `region_baseline_at_district` only — bilinear blend of 4 region baselines, **no** `invent_primitives`, no classification | ~19K cells (Lendel) — **contested, see §4 Risk 1** | unresolved carrier — **open, see §4/§9** | design-only, unresolved | +| Region | 204.8 km | same as above, one bilinear call per cell, cheapest possible rung | not benchmarked | none specified | named, not built | +| District | 2,048 m | full `derive_district`: region baseline + `invent_primitives` + `build_district_profile` classification | n=32 ≈ 1 ms / n=64 ≈ 5 ms | `district_window` (existing) | **shipped** | +| Quarter | 512 m | Option B — full reclassification at 512 m spacing, same pipeline as district, finer step (see §4 for A/B resolution) | n=32-district extent (16,384 cells) ≈ 20–23 ms *uncapped*; capped to 4,096 cells ≈ 5 ms | `district_window` + `granularity` param (proposed) | within D-226(d) ceiling, not built | +| Block / tile | 128 m / 1 m | math exists (`voxel_relief`, `voxel_mosaic`), never Atlas-exposed | not estimated | none | **[FLOOR QUESTION — Jeroen, §10]** | + +**Rung-selection rule** (viewport → rung): for a world extent `E` metres shown across canvas `C` px, sample spacing is `E/C`. Classify at the coarsest rung whose spacing ≤ 2·(E/C) — one tier finer than a screen pixel, never coarser. The continuous primitives (`terrain_detail`, `coast_invention`, `detail_scatter` — all confirmed to take raw f64 world-metres, `detail_scatter.rs:54` `value_noise`) truncate their fixed const octave arrays below the per-pixel Nyquist limit via a `min_wavelength_m` cutoff. + +**Status of the cutoff parameter — corrected per critique.** No cutoff parameter exists in the codebase today. `enveloped_fbm` (`server/src/atlas/detail_scatter.rs:137-176`) takes `(seed, wx, wy, envelope, ruggedness, wavelengths: &[f64])` and unconditionally sums every entry of the fixed `wavelengths` slice; `terrain_detail`/`voxel_relief` hard-code their own const octave arrays with no cutoff argument. **This is buildable, not present** — the release numbers measured this session are for the *existing, unmodified* `derive_district`, not a cutoff-bearing variant. Before this design is implemented, `enveloped_fbm` needs an actual `min_wavelength_m: f64` parameter, prototyped and re-benchmarked; "cheap, same seed stream, fewer terms" is a reasonable expectation, not a measured fact. Dudley's proposed refinement — fading the highest active octave's amplitude toward zero near the cutoff rather than a hard truncate, to avoid a pop as sample density crosses an octave boundary — is a second free parameter on top of an unbuilt one and needs its own validation pass. + +**No `derive_district`-interior extraction exists yet either.** `derive_district` (`server/src/atlas/district_profile.rs:1415`) quantizes to integer `DistrictPos` at its signature but immediately converts to fractional `(px, py, world_x_m, world_y_m, lat_deg)` at `:1426-1451` — confirmed by direct read this session. Extracting that interior into a metres-addressable `derive_at_metres(wx, wy, min_wl)` is the keystone move the whole ladder depends on, and it does not exist today under any name. It is a straightforward extraction (the fractional-metres math is already there, just wrapped by an integer-typed function), but "straightforward" and "built" are different things — §8 step 1 is where this lands. + +--- + +## 3. Serving model + +**Recommendation: generalize the existing `district_window` carrier with a `granularity` parameter. Do not add a second windowed payload.** + +Add to `AtlasLayerRequest`, `#[serde(default)]` (the T-1124 §1 pattern — absent = today's behavior, byte-compatible, no sixth demux shape, no protocol bump): +- `window_granularity: u32` (default 1 = district spacing; 4 = quarter) +- `window_min_wl_m: u32` (default 0 = no cutoff = today's behavior) + +`DistrictWindowLayer`'s echo tuple grows to `(center, n, granularity)`; both server FIFO-256 window cache and the client's 24-entry exact-match LRU key on the full tuple. D-227 "valid forever" still holds — same field, more axes. + +**Windowed-family ceiling (D-226 T-1124 §2, [HARD]):** exactly one windowed-query field on `AtlasLayerResponse`; a second is a mandatory migration to the tagged-envelope framing D-225 deferred. Reusing `district_window` with an additive param avoids triggering that migration for the district/quarter rungs. + +**This is a proposed schema change, not a verified-compatible one — flagged by critique as currently overstated.** `DistrictWindowLayer` today has exactly six dense arrays + `center`/`n` (`layer_proxy.rs:280-306`); the server cache key is `(String, DistrictPos, u32)` (`:308`); the client key builder is a 3-field string (`atlas_window_cache.gd:33-38`); server-side coalescing keys on `(connection, body)` only (`gen_queue.rs:221-224`). Landing `granularity` correctly requires five coordinated touch points — server struct, server cache key, server coalescing key, client request struct, client cache key — and if any one is missed (most dangerously the client cache key), a granularity-4 request silently aliases onto a granularity-1 cache slot with the same `(body, center, n)` and serves wrong data with no error surfaced. **The migration plan (§8) must enumerate all five explicitly and ship a test asserting a granularity-4 and granularity-1 request at identical `(center, n)` produce distinct cache entries** — this test does not exist today. + +**Cell-count cap — needs a concrete formula, not asserted as solved.** The intent (extent shrinks as granularity refines, keeping payload roughly constant) is right, but "4,096 cells regardless of rung" is not yet backed by clamp logic: `handle_atlas_request`'s current clamp (`layer_proxy.rs:40`) is a flat `[1, 64]` on `window_n` alone, with no granularity term, because the field does not exist. The correct clamp is `window_n² × granularity² ≤ WIRE_CAP_CELLS` (proposed `WIRE_CAP_CELLS = 4,096`), enforced server-side and never trusted from the wire. Wire sizes at that cap, MessagePack-realistic (field names on the wire, `Vec` as int arrays, not bin blobs): + +| Request shape | Cells | Wire bytes | +|---|---|---| +| District, n=32 (default) | 1,024 | ~7–9 KB | +| District, n=64 (cap) | 4,096 | ~29–34 KB | +| Quarter, capped to same cell budget (n≈16 districts across) | ≤4,096 | ~29–34 KB (same ceiling, smaller ground extent) | +| Quarter, n=32-district extent *uncapped* | 16,384 | ~115–140 KB — **4–5× over the district ceiling; must not be requested at this extent** | + +**Progressive refinement, not block-on-derive.** On zoom-in: display the resident coarser window from cache immediately (already there), fetch the finer-granularity window at the new center, swap on arrival. This is the existing async contract (`district_window: None` until the Rayon drain populates it, D-225 re-poll loop) applied per rung — no new wire mechanism, just a second in-flight request class. + +**Coalescing** generalizes the existing per-`(connection, body)` mechanism (T-1137) to key on `(connection, body, granularity)` — newest request supersedes an unserved older one at the same granularity. **[SOFT], recommended, not mandated** — extends rather than replaces the shipped debounce (150 ms client-side). + +**Queue discipline unchanged [HARD]:** window derives run on the Rayon background queue via `GenWorkItem::DeriveWindow`, never inline on `PreInput` (`serve_atlas_requests`, `plugin.rs:92`). This applies identically to every rung this pass adds. + +**Rejected:** a dedicated `WindowRequestV2` message (T-1124 §2's option (b)). The additive-param approach fits the existing byte-compatible pattern; a successor message earns nothing here and forces the tagged-envelope migration for zero benefit at the district/quarter rungs. (The planetary rung may force it anyway — see §4.) + +--- + +## 4. The planetary rung + +**This is the single least-resolved part of the pass — flagged prominently, not glossed over.** Two incompatible models were proposed in the same design session and neither survives critique unmodified. + +**Model considered (rejected on inspection): coarse region-grid + client GPU-upsample.** Serve one whole-body raster at region spacing (~195×98 ≈ 19,000 cells on Lendel, ~1.2–1.4 µs/cell ≈ ~20 ms release, well within budget), have the client stretch it to canvas resolution via GPU bilinear filtering. + +**Why this fails the mandate.** At planetary fit-zoom on Lendel (~39,200 km circumference over a 1920 px canvas ≈ 20 km/px), a region cell (204.8 km) spans ~10 screen pixels — that is magnified interpolation of a coarser composite, the literal thing the corollary forbids. The claim that "no finer information exists at planetary scale" is **false**: `invent_primitives`' coast-warp band runs 16–262 km wavelengths (`coast_invention.rs:56`) — finer than region spacing — specifically to produce coastline detail. A region-only sample would show a *coarser* coastline than the authored PNG it replaces (the PNG is 40–78 km/px, 3–5× finer than 204.8 km region spacing), which reproduces the exact Lendel evidence-clause failure (imprecise coastline from a coarse composite, D-166's "~36 districts from the pixel-edge estimate") the whole mandate exists to fix, at a different rung. This model is **rejected**. + +**The mandate-compliant model:** canvas-resolution sampling of the continuous fields, exactly as the rung-selection rule in §2 already specifies for every other rung — no separate rule for planetary. At 1920×1080 (~2.07M samples), the (unbuilt, see §2) `min_wavelength_m` cutoff truncates octaves finer than the per-pixel Nyquist limit, so this is *not* the same cost as a full district-tier derive per pixel — but the actual per-sample cost of a cutoff-bearing derive has never been measured (§2). Extrapolating from the *uncut* per-cell rate (~1.2–1.4 µs), a full-resolution one-shot repaint is ~2.6–3.0 s single-thread, ~0.2–0.3 s across 14 Rayon workers — **but the parallel figure is unmeasured**: `build_district_window_layer`'s loop is confirmed **serial** today (`layer_proxy.rs:388-427`, a plain row/col double loop), and naive `par_iter`-ing a loop whose per-task cost (~1.2 µs) is comparable to Rayon's own task-dispatch overhead needs chunking to avoid the parallelism itself costing more than the work — no chunking strategy is specified. **Before any planetary-rung latency claim is used to plan implementation, both the octave-cutoff cost and the parallel-chunked window-derive throughput must be actually measured, not extrapolated.** + +**Wire carrier — unresolved, not a detail to defer.** A dense per-cell array at planetary sample counts breaks every existing budget figure by two-plus orders of magnitude (Dudley's own quarter-rung table shows even 16,384 cells is already over budget; 2M cells is categorically different). This forces an explicit choice this pass does not make: +- **(a)** An **encoded raster** (PNG/binary blob) response — a genuinely new wire shape, which likely forces the tagged-envelope migration D-225 deferred (the exact migration the §3 serving model was designed to avoid triggering for district/quarter). +- **(b)** A **capped-density tile** response riding the `district_window` family at planetary-appropriate granularity + a client-side progressive tiling scheme (many bounded requests covering the visible extent, each within the existing wire budget), with visible refinement as tiles complete. + +**Recommendation: (b).** It reuses the §3 carrier and progressive-refinement machinery without forcing a protocol migration, and it composes naturally with the existing border-fade UX (§6) — a planetary view built from progressively arriving tiles is the same pattern as a regional window's edge-fade, just covering more tiles. But this is a real open design question, not a footnote — **flagged to Jeroen alongside the D-226(d) floor question in §10**, because it changes what "fully derived, canvas resolution" concretely means for the rung the mandate cares about most. + +**What retires regardless of which carrier wins** (`atlas_viewer.gd:454` `_load_heightmap`, the `reliefmap.png` display path, `COLOR_HEIGHTMAP_TINT`; gen-overlay cell-fill loops `_draw_gen_district`/`_draw_gen_region_grid` stop resampling onto the PNG's pixel frame and draw against a virtual canvas extent instead; marker projection and descend inversion re-key to that virtual extent). **Precompute-at-import-time is not viable** as the primary strategy under D-227 (derive-don't-store) — any caching that helps here is a disposable, evictable raster-tile cache analogous to the existing `TerrainAnalysisCache`/`DistrictWindowCache`, not a stored derivation. + +--- + +## 5. Canvas-resolution sampling model + +Confirmed by direct code inspection (not aspirational): `value_noise`, `terrain_detail`, `voxel_relief`, `voxel_mosaic`, `coast_warp_px`, `character_field` all take raw f64 world-metres, are fully continuous (C¹), deterministic, and position-keyed with no stored state (`detail_scatter.rs`, `coast_invention.rs`). This is the mandate's keystone fact: **the continuous derivation already exists; the ladder extracts and truncates it, it does not reinvent it.** + +**Split:** rungs govern *what classification granularity is available and legal to request* (a policy/cost question, §2/§10); canvas-resolution sampling governs *what density the client actually asks for*, tracking the viewport continuously. The rung-selection rule (§2) is the join: pick the coarsest legal rung whose spacing is ≤2× the current screen sample spacing. + +**Bounded key space, not unbounded.** A continuous field sampled at arbitrary density would give the cache an unbounded key space (client obstacle flagged in the grounding: the 24-entry exact-match LRU would thrash to ~0% hit rate). This is avoided because **requests snap to quantized rung tiers** (granularity ∈ {1, 4, …}) and integer district-aligned centers — only *display* is continuous; every *request* the wire actually carries is one of a small number of discrete shapes. **Gap flagged by critique:** as specified, `window_min_wl_m` is viewport-continuous (`E/C`) while the cache key/echo tuple is `(body, center, n, granularity)` — same key, different `min_wl`, would silently collide. Fix: **quantize `min_wl_m` to a small fixed set of bands per rung** (matching the rung's own octave bands) rather than passing a raw continuous value, and add the quantized band to both the echo and the cache key. This closes the gap without reopening the unbounded-key problem. + +**Region/orbital granularity is unrepresentable in the current sketch.** `window_granularity: u32` with `spacing = DISTRICT_M / granularity` can express district (1) and quarter (4) but not region (coarser than district, i.e. granularity < 1). If the planetary rung's chosen carrier (§4) reuses this same field, the type needs to change to something that can express both directions (e.g. a signed log-scale or an explicit rung enum) — noted for the implementer, not resolved here. + +--- + +## 6. Encoding continuity (Araminta) + +**One colorizer family, no per-rung palettes.** `MORPHOLOGY_COLORS` / `MORPHOLOGY_RGB_OPAQUE` (`atlas_overlay_colors.gd:89-96`) are already declared as deliberate duplicates of the same 17-hue table — the codebase's own precedent for "alpha varies by context, hue never does." This generalizes without exception to every rung the ladder adds: temperature (shared `i16` deci-°C + `REGION_TEMP_NONE_DC` sentinel, [HARD] per D-226 T-1124 §2 — "two independently-chosen quantizations... could paint a visible ramp discontinuity at the zoom-swap threshold"), moisture, vegetation (`Marine=6` [HARD] exhaustive, never omitted), glaciation. **No rung gets its own decision-boundary table.** + +**The average-back rule (hue-continuity requirement):** a coarser cell's color must equal the area-weighted average of the finer cells it aggregates, not an independent reclassification — otherwise the zoom visibly "pops" a hue at the rung boundary. This holds automatically for gates driven by genuinely continuous per-metre fields (elevation, slope). **It does not automatically hold — and was not checked against the actual gate tree — for gates driven by district-granularity categorical inputs.** `derive_morphology_zone`'s gate sequence (`district_profile.rs:515-652`) includes hard thresholds on `GlaciationGrade` and tectonic class, both computed at district granularity rather than sampled continuously per metre. A district classified `FjordWall` by a threshold its centre-sample just crossed has no guarantee that finer quarter-cells near its edge average back to `FjordWall`-dominant, because glaciation grade itself may be flat across the whole district rather than varying continuously beneath it. **This needs an explicit audit** — which of the ~8 morphology gates are continuous-field-driven (likely fine) vs. district-categorical-driven (likely NOT fine) — before "average-back holds" is asserted as a general property rather than a per-gate one. Flagged as a **Risk**, §9. + +**Quarter rung: reclassify at fixed thresholds (Option B), not inherit-district-hue (Option A) — resolved here, was previously left open across sections.** Reclassifying per quarter using the *same* classification thresholds as the district rung (never a second tuned "quarter mode") is what makes the average-back guarantee possible at all for the continuous-field-driven gates; inheriting district hue while sampling finer elevation texture underneath would guarantee a visible mismatch between "shape" (quarter-fine) and "category" (district-coarse) at every district boundary — the opposite of what continuity requires. This closes the design gap the grounding left as "a design call" in two sections and a rule in a third. + +**Window-local elevation contrast-stretch: retired, not carried forward.** The stretch existed to manufacture visible relief from a *sparse* sample (a 32-wide window reading flat unless rescaled). Under canvas-resolution sampling every screen pixel gets its own derived `elev_q` — real per-pixel variance from the detail-scatter octave stack, at every zoom level, including genuinely flat terrain (which should read flat). A per-window stretch would also reintroduce exactly the seam class D-243 §4 forbids ("climate does not change on a line," generalized: lightness must not change on a window boundary either) and breaks the D-227 "valid forever" cache guarantee implicitly (rendering would depend on window-contents-derived normalization the cache key doesn't carry). **Ruling: one fixed global lightness mapping** (`0.7 + 0.3·elev_q/100`), unchanged, everywhere. If native-scale contrast genuinely reads too flat after real derived output exists, the fix is amplitude tuning in `detail_scatter.rs`, not a display-side stretch — a separate, later ticket, not this pass. + +**Acceptance criteria for "seamless" (testable):** +1. Zero hue swap at a rung boundary beyond what the finer classification legitimately resolves (sample both rungs at the same world position; assert same or adjacent-averaging table index). +2. Coastline position stable to within one sample-cell of the coarser rung across a boundary (both rungs read the same coast-warp field) — this is the direct regression test for the Lendel evidence clause. +3. No layout jump on descent — the clicked point stays centered to sub-district precision (existing `canonicalize_district_center()` contract). +4. No lightness-band discontinuity at a pan/window boundary (direct consequence of retiring the contrast stretch). + +**One legend, one scale indicator.** `GENERATION_LEGEND` needs no rung-specific variants since every rung reads the same tables. UI chrome is a continuous metres-per-pixel/extent readout (extending the existing not-to-scale hover reticle, T-1138's open item — resolvable in the same pass once real sampling exists at the boundary), never a discrete "you are now in Quarter Mode" label, matching Jeroen's "no mode transition" ruling. + +--- + +## 7. Costs summary + +Release build, this session, body GJ338Bd, seed "yolo", 16 cores / Rayon pool 14 (`server/target/release/aliveness_probe --render`). No committed release figure existed in governance before this session. + +| Quantity | Debug (cited, D-226 T-1124 §4) | Release | Status | +|---|---|---|---| +| Per district-cell `derive_district` (existing, uncut) | ~6.2 µs | ~1.2–1.4 µs | **MEASURED** | +| n=32 window (1,024 cells) | 6 ms | ~1 ms | **MEASURED** | +| n=64 window (4,096 cells, current cap) | 25–26 ms | 5 ms | **MEASURED** | +| n=256 window (65,536 cells) | — | 81–94 ms | **MEASURED** | +| `run_layer1` cold (512×256 TerrainAnalysis) | ~45 ms | ~8–15 ms | debug **CITED** / release **ESTIMATED** (bounded by full-probe wall time 0.19 s incl. cascade+DB+PNGs) | +| Throughput, single-thread | ~145K cells/s | ~0.7–0.8M cells/s | **MEASURED** | +| Throughput, parallel (14 workers) | — | ~10M cells/s | **ESTIMATED, UNVERIFIED** — window loop is confirmed **serial** today (`layer_proxy.rs:388-427`); no chunked-`par_iter` benchmark has been run; naive per-cell parallelization risks task-dispatch overhead comparable to the per-cell cost itself | +| Quarter, n=32-district extent, uncapped (16,384 cells) | ~115 ms (ticket estimate) | ~20–23 ms | **ESTIMATED** — same per-sample cost × 16, not independently measured | +| Quarter, Option A primitive-only sampling | — | "~2–3 ms, ~1/3–1/2 of full derive" | **RETRACTED as stated** — no profile isolates `invent_primitives` vs. `build_district_profile` cost; this fraction was invented, not measured. (Moot in any case — §6 resolves quarter to Option B.) | +| Octave-cutoff derive (`min_wavelength_m`-bearing) | — | not measured | **UNBUILT, UNMEASURED** — every planetary-rung and canvas-sampling latency claim resting on "cheaper because fewer octaves" is an unmeasured extrapolation on top of code that doesn't exist yet | +| Full-canvas planetary sample, 1920×1080 (~2.07M cells) | — | ~2.6–3.0 s single-thread; ~0.2–0.3 s parallel (claimed) | **ESTIMATED, UNVERIFIED** — depends on both the unbuilt cutoff and the unbenchmarked parallel throughput above; treat as directional only | + +**Interactive-latency verdict:** district and quarter rungs (capped) are comfortably interactive on a warm `TerrainAnalysis` — 1–5 ms per response at current cap sizes. The **only** rung with a real latency question is planetary/canvas-fill, and its numbers are two extrapolation-hops from anything actually measured this session. **No implementation should proceed on the planetary rung's cost story without first (a) prototyping the octave cutoff and re-measuring, and (b) chunked-`par_iter`-ing the window loop and re-measuring** — both are cheap to do (the probe binary already exists) and should happen before, not during, the follow-up ticket. + +--- + +## 8. Migration path + +Each step shippable and independently verifiable; steps 1–3 extend `derive_district`, step 4 is a materially different, currently-unscoped code path. + +1. **Extract `derive_at_metres(seed, body, wx, wy, min_wl)`** from `derive_district`'s interior (`district_profile.rs:1426+`); `derive_district` becomes a thin integer-quantizing wrapper. **Prototype and benchmark the `min_wavelength_m` cutoff in `enveloped_fbm` as part of this step, not after** — per §2/§7, this has not been done and every downstream cost claim depends on it. Default `min_wl=0` preserves today's behavior byte-for-byte. Verify against the believability/derivation golden harnesses. +2. **Chunked `par_iter` the window loop** (`build_district_window_layer`, `layer_proxy.rs:388`). Confirmed serial today; parallelize with row/column chunking (not per-cell) to amortize Rayon dispatch overhead, and **re-measure** before using the parallel throughput number anywhere downstream. Byte-identical output, pure perf change. +3. **`window_granularity` + `window_min_wl_m` (quantized bands, per §5) as `#[serde(default)]` on `AtlasLayerRequest`; `granularity` (+ quantized `min_wl` band) added to `DistrictWindowLayer`'s echo and to both server and client cache keys — all five touch points explicit** (server struct, server cache key, server coalescing key, client request struct, client cache key). Ship a same-`(center,n)`-different-granularity cache-collision test as an acceptance gate. Server-side clamp becomes `window_n² × granularity² ≤ WIRE_CAP_CELLS`. Quarter rung ships; district unchanged by default. **This is the item-(c) floor decision point** — quarter ships within the current ceiling; block/tile stays gated pending §10. +4. **Planetary rung — scoped as its own unit of work, not one sentence.** Requires: (i) resolution of the wire-carrier question (§4 — encoded raster vs. capped-density tiles, a decision, not an assumption); (ii) if tiling, a new `GenWorkItem` variant or a generalized `DistrictWindow` request at planetary-appropriate granularity + extent, its own completion-drain routing, and its own client consumption path in `AtlasViewer`; (iii) retirement of `_load_heightmap` (`atlas_viewer.gd:454`), `reliefmap.png` display, `COLOR_HEIGHTMAP_TINT`; (iv) re-keying of gen-overlay cell-fill loops and descend-geometry math from the PNG's pixel frame to a virtual canvas extent. This step should not be estimated at the same confidence as 1–3 until (i) is resolved. +5. **Client rung-selection + progressive refinement** in `AtlasWindowViewer`: request granularity tracks zoom level; on zoom-in, hold coarse + fetch fine + swap on arrival. Merges the district/quarter screens into one continuum. The click-through seam at planetary→regional (T-1124 §5) is preserved as-is — see §10. +6. **Retire `COMPOSITE_SMOOTH`** (`atlas_window_overlay.gd:60`) once granularity-4 (quarter) windows are the default at close zoom — real classified quarter-cells replace what the linear-filter stretch was compensating for; delete the const and the smoothing branch, leaving the crisp `draw_rect` path as the only path. + +--- + +## 9. Risks + +Findings not folded into the sections above as fixes, carried here as explicit risk. + +- **R1 — Planetary rung is the weakest link in the whole pass.** Its cost story rests on two unmeasured extrapolations stacked on top of each other (unbuilt octave cutoff → unbenchmarked parallel throughput), and its wire carrier is an open question this pass identifies but does not close. Treat "the planetary rung is solved" as false until both are independently verified. See §4, §7. +- **R2 — Temperature (and any district-categorical field) is a stepped field, not a continuous one, at every rung.** `region_baseline_at_district` (`region_profile.rs:367`) keys its climate edge-warp on an exact integer `DistrictPos` via `rem_euclid`. If `derive_at_metres` floor-divides a sub-district sample down to its containing district before calling it (the natural implementation), all quarters inside one district get bit-identical temperature — correct per D-243's design intent (climate is district-tier), but it means "same continuous field, different sample density, bit-for-bit agreement on shared octaves" (the general determinism argument in §5/§6) is **not literally true for temperature** — temperature is a hard step at every district boundary at every rung, forever, by construction. This should be stated plainly in the eventual record, not left implicit, or a reader will expect temperature to refine continuously and be surprised when it visibly steps every 2,048 m even inside a "continuous" ladder. +- **R3 — Average-back is unverified for categorical morphology gates.** See §6 — glaciation- and tectonic-class-driven gates in `derive_morphology_zone` are district-granularity categorical inputs, not continuous per-metre fields; the average-back hue-continuity guarantee likely does not hold for them without a specific audit. Needs a pre-implementation check of which of the ~8 gates are safe. +- **R4 — Region rung is named but unscoped.** No cost number, no serving shape, no migration step. As migrated, the ladder goes district → quarter → planetary, with "region" existing only as a table row. Acceptable if the planetary rung's tiling (§4 option b) effectively subsumes it, but that overlap should be made explicit rather than left as two undifferentiated rungs. +- **R5 — `window_granularity`'s type cannot express coarser-than-district rungs.** Flagged in §5; needs a signed/log-scale or enum redesign if region/planetary reuse the same field. +- **R6 — Border-fade's referent changes underneath it.** The existing `_gen_pending_indicator` border-fade (T-1124 §5) fades to "the underlying whole-body heightmap … real data seen through" — exactly the texture the corollary retires. The mechanism survives; its target must be repointed to "the previous derived composite at this position" before the PNG retires, or the fade quietly starts blending against nothing. + +--- + +## 10. Decisions for Jeroen + +### D-226(d) floor question (the item-(c) question T-1143 was explicitly told to reserve) + +The mandate says "down to tile scale" (D-166); D-226(d)/T-1112 §2 hard-codes: *"If a future ticket wants finer planetary-scale detail than this, the answer is 'no' per item (d), not 'extend this struct' … by construction, not by restraint that could erode."* These two records are in tension and this pass does not resolve it — it presents options: + +- **Option 1 — Stop the Atlas ladder at quarter (512 m).** The quarter rung ships fully within the current ceiling; no supersession needed. Block/tile detail remains Phase-5-only, verified in-world via the believability/derivation harnesses, never Atlas-mapped. **Consequence:** D-166's "down to tile scale" phrasing needs a one-line reading note (or amendment) clarifying it means "down to the Atlas's legal floor," not literal tile scale, to avoid the phrase being read as a standing promise this pass doesn't keep. *Recommended by this pass* — quarter (a settlement-footprint cell) is a natural planetary-map floor, and the anti-erosion clause in D-226(d) was deliberately hard-coded against exactly this kind of gradual descent. +- **Option 2 — Explicitly supersede D-226(d) for the windowed view only**, permitting block (128 m) and/or tile (1 m) rungs on the Atlas, keyed to the same `window_granularity` mechanism. **Consequence:** the D-226(d) ceiling's stated purpose (chunk/tile/voxel fill is verified by harnesses in Phase 5, never mapped) is narrowed to "never mapped *except through the windowed viewport*" — a real scope change to a deliberately-hardened rule, not a mechanical extension. Cost/wire figures for this tier do not exist (§2, §7) and would need their own measurement pass before implementation. +- **Option 3 — other.** Not identified by this pass; open if neither of the above fits. + +### Planetary rung wire carrier (surfaced by this pass, not in the original item list, but blocking §4/§8-step-4) + +- **Option A — encoded raster response** (PNG/binary blob), a new wire shape, likely triggering the tagged-envelope migration D-225 deferred. +- **Option B — progressive capped-density tiling** riding the generalized `district_window` carrier, many bounded requests instead of one dense response. *Recommended by this pass* — avoids forcing the migration, reuses existing progressive-refinement/border-fade UX. + +### Continuity through the planetary→regional seam (not this pass's to decide, flagged only) + +T-1124 §5 (2026-07-21) just ratified a hard click-through cut at planetary→regional entry — fixed planetary canvas, no wheel-zoom, click owns descent. This pass's continuous district↔quarter zoom lives *inside* the regional mode, below that seam; it does not touch the seam itself. If continuous zoom is wanted through the planetary entry point too, that is a **follow-up amendment to the T-1124 §5 ruling**, not part of this design. + +--- + +## 11. Proposed governance record changes + +**Not claimed — text sketches only, pending Jeroen's rulings above.** + +- **D-166 amendment (reading note or wording amendment):** clarify "down to tile scale" against whichever floor option is chosen in §10 — either a one-line note that "tile scale" is read as "the Atlas's legal floor per D-226(d)" (Option 1), or an explicit supersession clause for D-226(d) scoped to the windowed view (Option 2). +- **D-226 amendment (T-1143 landing):** the district/quarter ladder as designed in §2/§3/§6 — `granularity` param on `AtlasLayerRequest`/`DistrictWindowLayer`, the windowed-family ceiling's continued applicability (one field, param-extended, not a second field), the quarter-rung Option B resolution, the retired window-local contrast stretch, the `COMPOSITE_SMOOTH` retirement condition. Cross-references: D-227 (derive-don't-store, shared classification thresholds), D-243 (edge-fuzz/no-grid-seam discipline extended to morphology), D-239 §6 (frozen 17-zone vocabulary, unchanged). +- **D-226 amendment (planetary rung landing, separate from the above — pending §10's wire-carrier decision):** whichever carrier is chosen, plus the `_load_heightmap`/`reliefmap.png`/`COLOR_HEIGHTMAP_TINT` retirement and the border-fade referent repoint (Risk R6). +- **New record or D-227 amendment note:** temperature's stepped-not-continuous status across rungs (Risk R2) — worth stating once, canonically, rather than leaving implicit in code comments. \ No newline at end of file