The complete workshop record: four round-1 positions, five round-2 syntheses (incl. Troblum's adversarial pass with addendum + final scorecard — all seven findings resolved), both lead interviews, Qatux's round notes and the 8-section workshop-outcomes.md (the lakes message-crossing documented as process history), measurement ⑥ (set_pixel/c1) + the population-survey and chunk/S2 addenda in the measurement docs, the brief's appendix updated through ⑥, and architecture-briefing-final.md — Jeroen's outline written back as-built (six-level ladder, lakes, ~9MB resident global tier). README row: Complete. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
90 KiB
title, description, type, status, workshop, created
| title | description | type | status | workshop | created |
|---|---|---|---|---|---|
| Body Map Viewer — Tyre's Round 2 Synthesis | Final amendment texts (record-ready), tagged-envelope governance disposition, step-ladder tables, and the deprecation-sweep draft (Expected Output 2) | workshop | active | body-map-viewer | 2026-07-25 |
Tyre — Round 2 Synthesis
cracks knuckles — interview 1 upheld both my load-bearing round-1 calls
(gridunit snaps to D-243; cliffs Phase-4) and added two rulings I now fold in:
the map-time TTL-split with the storage/staleness axes distinction (Jeroen's
new eviction amendment), and cliffs as a sparse CliffSegment feature list
(aligning my round-1 "new fields, not stolen bits" text with Araminta's sparse
shape and Jeroen's ruling). This document is the filing package: paste §(a) into
governance/decisions/architecture.md with only ID-claiming left, run the §(d)
sweep at wrap-up.
Four sections, in the coordinator's order: (a) final amendment texts, (b) envelope mechanics + the ceiling-rule disposition (with Dudley on wire/serving), (c) step-ladder tables (with Dudley on costs), (d) deprecation-sweep draft.
(a) AMENDMENT TEXTS — FINAL, record-ready
These incorporate every interview-1 ruling. Each is written to paste directly into the named record. A new D-record (the body-map-viewer render architecture) is claimed separately at filing — these are the amendments to existing records; the new-record text lives at the end of this section as §(a.0) so the whole package is in one place.
(a.0) NEW RECORD — body-map-viewer render architecture (claim a D-id at filing)
D-NNN — Body-map-viewer stepped render architecture (supersedes the T-1143 continuous-ladder mechanism). Claimed [date]. Domain: architecture.
- Decision: The Atlas map handler is rebuilt on three locked premises: (1) content determination is server-side — the CPU/Rust server answers "what is at this world coordinate at this zoom step" as a per-step data canvas; the client never invents geometry. (2) The client is a map-art function — it colorizes, styles, and annotates the server's canvas via a render-to-texture terrain layer (texel-exact, drawn at the display ratio) + an unscaled screen-space sibling layer for vector annotations. (3) Zoom is stepped — discrete gridunit-spacing levels, one server-canvas fetch per crossed step boundary, cursor-anchored, with edge-scroll pan and a hard full-zoom-out reset to the canonical Global (rung-0) body-surface frame.
- The step ladder is six levels — the Global map opener (rung 0) plus five fixed metre rungs (Dudley's Option D, every fixed rung measured): Global (rung 0, body-surface view) → Region (204.8 km, rung 1) → District (2,048 m, rung 2) → Quarter (512 m, rung 3) → Block (128 m, rung 4) → Chunk (64 m, rung 5, deepest). Rung 0 (Global) is the map opener and is variable-extent, not a fixed metre rung (Jeroen, interview 2 correction): it is the whole body surface at one gridunit per region, so its canvas is the body's region grid — variable per body (~19K gridunits on an Earth-class body; the D-243 elastic seam made visible, since region count floats per
body_radius_km). Region (rung 1) is the largest fixed-size rung — viewport-sized like every fixed rung below it, not the always-kept tier (that is Global). Tile/voxel (1 m) is dropped from the Atlas ladder (Jeroen, interview 2: "the actual tile level rung seems unusable, maybe replace with 64" — a 10-px-per-tile full-screen view is ~192×108 m of ground, which is in-world viewport content, Phase-5's scope, not an Atlas map); voxel is reserved for Phase-5 in-world rendering. Every fixed rung's gridunit spacing is one of D-243's absolute-metre rungs — never a viewport-derived spacing (see the D-243 gridunit amendment, §(a.4)). Deepest bottom-out rule: 1 screen px per 64 m gridunit, no magnification margin — the old "10 px per tile" margin does not carry over (it existed because a 1 m unit is sub-readable at 1×1; a 64 m gridunit is already a legible map feature — a city block / short street — so chunk uses the plain fixed-canvas budget with no display-ratio-sized exception, §(c)).- Canvas policy: rung 0 (Global) is the sole canonical, always-keep tier — the body-surface region-grid canvas, one gridunit per region, variable-extent per body. D-226(d)-legal by construction: at one gridunit per region it is coarser than the region grid, never a sub-region metre-resolution whole-body derivation. Every fixed rung — Region (rung 1) through Chunk (rung 5) — is viewport-sized and evictable (Region included: it is the largest fixed rung, not the canonical tier), bounded to a fixed canvas-pixel budget (not a per-monitor echo), which keeps the deep ladder legal under D-226(d) per request by construction (a viewport-sized chunk-spacing canvas is never a whole-body metre-resolution derivation on any single request). The D-226(d) prohibition is stated as a per-request / per-derivation constraint, not an aggregate-storage constraint (§(a.8), Troblum S3) — the letter and the purpose are both held server-side; the client-cache accumulation path is closed by the deep-rung retention cap in the Cache bullet, not left to practical improbability.
- Wire: the per-step canvas rides a tagged-envelope carrier (§(a.5), §(b)) — the ceiling-forcing payload D-225 deferred, now built. Dense classification fields ship PNG-per-field (measurement ④'s winner on size and speed); sparse feature lists (
courses,cliffs) stay MessagePack-native.- Cache: three tiers, cheapest-first — client in-memory LRU → client disk-backed
FileAccessstore (self-cleaning TTL for sim-state entries) → server (D-203-shaped resident global tier + TTL(detail, time, distance) for finer rungs). Determinism (D-227) makes every geometry tier a pure cache, never a source of truth. Staleness and storage are distinct eviction axes (§(a.6)). The server global (rung-0) tier is the body-surface region-grid canvas — one gridunit per region, ~19K gridunits on an Earth-class body — and costs ~8.85 MB PNG-encoded (27.61 MB raw) across the entire real ~267-body population (Dudley, measured: 4,825,615 total cells, avg 18,073/body; largest GJ325Ac at 25,200 cells/47.4 KB, smallest a moon at 253 cells; Earth-class reference 195×97 = 18,915, matching the ~19K framing). This supersedes the earlier ~174 MB figure (which mis-priced a fixed 4K-class Region-spacing canvas per body, ~440× too many cells). At ~8.85 MB the keep-always tier is trivially process-resident, not merely disk-safe — the "always keep global" policy gets easier, not harder, under the rung-identity correction. Convention stated: SI decimal MB, so the figure isn't "corrected" against adu-reported MiB number later (Troblum N1). Derive cost — the "snappy after first calc" number (Dudley, measured on real per-body extents, not extrapolated): ~16–21 ms single-thread per body (~830–910 ns/cell over ~18K cells) — trivially interactive on a fresh Atlas-open. The tier populates lazily, once per body, on first Atlas-open via the D-206 background queue (the same pattern every other cached layer uses), so the ~4.0 s all-267-summed single-thread figure is a sanity ceiling only, never paid synchronously in one batch (same shape as T-1177's per-body-vs-summed hydrology framing). Two client-cache hardening requirements, both stated in the record, both implemented in Stig'sFileAccessspec: (i) a per-body deep-rung retention cap (a maximum resident chunk/block-spacing tile count or disk quota per body, independent of the rung-0 retention floor) — this is the structural ceiling that closes the D-226(d) accumulation gap (§(a.8)); (ii) every persistent cache entry carries a schema/version tag (the game'sproject.yamlversion string or agenerator_sha-style stamp), checked at read time — a mismatch is treated as a cache miss and re-fetched, never decoded (§(a.9), Troblum S5).- Rationale: the T-1143 error class (client compensating for a zoom-scaled canvas —
_canvas.scale,_zs/_zs_stroke/_zs_ring_radius, the line-rasterizer floor) is dissolved at the root: there is no zoom-scaled canvas anymore, so per-call compensation cannot occur. Every pre-workshop cost gate (①–⑤) came back GO with no extrapolation.- Cross-reference: D-166 (cascade + the amended zoom-ladder corollary), D-226 (the ceiling this migrates past; D-226(d) the deep-step boundary), D-227 (derive-don't-store — the cache's discipline), D-243 (the rung ladder gridunit snaps to), D-225 (the tagged-envelope migration this executes), D-010 (determinism — server-owns-derivation, client-art-function).
- Dissent: None.
(a.1) D-166 corollary — repoint (owns between-step magnification)
Paste as an amendment on D-166, after the 2026-07-21 amendment:
Amendment (2026-07-25, body-map-viewer workshop — stepped ladder supersedes continuous). The 2026-07-21 corollary sentence — "Display at every rung samples the derivation at canvas resolution (the ladder is a continuous field, not a stack of fixed display rasters)" — is repointed, not deleted. The zoom mechanism is now stepped: the server generates one data canvas per discrete zoom step, sampled at that step's native D-243 gridunit spacing. The corollary's guarantee survives, re-expressed per-step: a gridunit is never derived coarser than its step's own rung floor, and never displayed finer than the display-ratio tunable (1×1 ideal, ≥5×5 px/gridunit acceptable — measurement ④). The "continuous field" framing is retired as literally false (it never was continuous once server-side per-step canvases replaced the client
_canvas.scalemodel). The corollary now reads: "each zoom step's data canvas is a derivation sampled at that step's native gridunit spacing; display within a step holds that canvas at a fixed, texel-exact ratio; between-step magnification of the held canvas is bounded to one step interval and is the ladder's only sanctioned display-time scaling." This amendment owns the one honest new gap it creates: in the interval just before a step-cross, the held (coarser or adjacent) canvas is magnified to fill the new step's viewport for the fetch duration — the exact operation the original corollary was written against, now a named, bounded exception rather than a silent violation. The bound is joint in two knobs: step count (more steps → smaller per-step magnification factor) and the display ratio. The fetch interval is short — measurement ⑤ shows step-canvas texture upload at 0.03–4.6 ms across every size, never a frame-budget risk, and measurement ④ shows an uncached 330K-gridunit step derives + encodes server-side in ~80 ms — so the magnified hold is a double-digit-millisecond transient, not a resting display state. Ladder extent (interview 2, §(a.8b)): the 2026-07-21 amendment's "down to tile scale" phrasing is narrowed — the Atlas ladder bottoms out at chunk (64 m), not tile (1 m); tile/voxel is Phase-5 in-world content, not an Atlas rung. The per-step derivation guarantee above applies to every rung from region down to chunk.
(a.2) T-1143 ruling 3 — superseded for zoom transport
Paste as an amendment on the D-226 record's T-1143 ruling block (or on D-166, wherever the T-1143 rulings are anchored — they live in the D-226 amendment chain):
Superseded 2026-07-25 (body-map-viewer workshop). T-1143 ruling 3 ("continuous cursor-anchored zoom... wheel-zoom carries the view from the orbital frame down through regional granularities continuously") is superseded for the transport mechanism: zoom is stepped — scroll clicks through discrete D-243-rung gridunit-spacing levels, one server-canvas fetch per crossed step boundary. Survives unchanged: (a) cursor-anchored centering, (b) edge-scroll pan, (c) the [HARD] condition that a full zoom-out resets to the canonical Global (rung-0) body-surface frame and location. A client-side morph/tween between held step canvases is an investigation item (cosmetic interpolation of already-arrived textures while the next step's canvas is in flight — never re-derivation, never a second positional truth; see the determinism-boundary ruling, §(a.7)). T-1143 ruling 2 ("progressive capped-density tiling riding the generalized
district_windowcarrier — no forced tagged-envelope migration") is also superseded: the tagged-envelope migration is now triggered (§(a.5)) — measurement ④ shows the step-canvas payload at 21×–563× the windowed ceiling across the three measured sizes, off by two to three orders of magnitude before encoding is even considered, which no additive-param reuse ofdistrict_windowcan carry.
(a.3) select_rung / rung-model — replaced by the step index
Paste as an amendment note (on the same T-1143-rulings block):
Superseded 2026-07-25. The shipped rung selector —
select_rung()'s unified per-rung coverage-ceiling walk keyed onMAX_COVERAGE_M(Quarter → District → Region → tile-mode mosaic;atlas-zoom-ladder-t1143.md§6 "Final model, round 3") — is replaced by a discrete step index into the stepped gridunit ladder. Rungs-as-derivation-granularity survive conceptually (every step still names an absolute-metre D-243 rung), but the selector is no longer a coverage walk over viewport extent — it is "which step the viewport is currently on," advanced/retreated one notch per scroll.select_rung,MAX_COVERAGE_M, the coverage-ceiling walk, and thecompute_tile_grid()whole-body Region-tile mosaic that composed the beyond-Region extent are retired. The whitelist-validation discipline fromresolve_window_granularity(T-1150: finer-than-district integer multiples only, unknown values fall back, never trusted from the wire) is the correct shape for the step index's own validation and should be reused, not reinvented.
(a.4) D-243 — gridunit vocabulary entry (additive)
Paste into D-243's item (5) vocabulary block, or as a labelled amendment:
Amendment (2026-07-25, body-map-viewer workshop) —
gridunitadded to the locked vocabulary (additive; no rung changes). gridunit (at zoom step): the per-step data-canvas cell. Not a new spatial rung — a role name for whichever D-243 absolute-metre rung the Atlas ladder pins a given zoom step to. At every fixed rung, gridunit spacing equals one of the ladder's fixed metre values and never floats with viewport size or display resolution — a fixed step's gridunit is a D-243 metre rung, full stop. The Atlas ladder's fixed rungs run from Region (~205 km, rung 1) down to chunk (64 m, rung 5, the deepest Atlas rung); tile/voxel (1 m) is NOT an Atlas gridunit — it is dropped from the ladder (§(a.8b), Jeroen interview 2) and reserved for Phase-5 in-world rendering. The one exception to fixed-metre snapping is rung 0 (Global): it is the variable map-opener, one gridunit per region, so its gridunit is a whole region (~205 km) but its canvas extent floats with the body's region count (the D-243 elastic seam). Global's gridunit is still not viewport-derived — it is the region grid, a fixed property of the body — so the "never floats with viewport/display" discipline holds; only the body's own region count varies. So the outline's "10 px per tile" bottom-out is superseded by "1 screen px per 64 m gridunit, no magnification margin" (Dudley's chunk bench): the Atlas bottoms out at the chunk rung at the workshop's own 1×1 ideal ratio, with no extra magnification, because a 64 m gridunit is already a legible map feature (city block / short street) — unlike a 1 m unit, which needed the 10× margin only to be readable at all (which is exactly the in-world-viewport problem chunk is defined to sit above). The display ratio (screen-px per gridunit — 1×1 ideal, ≥5×5 acceptable) is the free, client-side, viewport-dependent parameter, kept terminologically and architecturally separate from gridunit spacing: two monitors at different resolutions requesting the same step receive the same absolute-metre canvas (same rung, same derived content, same cache entry — shareable) and merely display it at different px-per-gridunit ratios (a GPU texture-to-viewport resize, never a re-derivation). This is what keeps the derivation cache key free of any presentation parameter (D-227: "a canvas for a fixed seed never changes" stays true). The display ratio is step-dependent, not flat across the ladder (Stig, measurement ⑥ —Image.set_pixel77.5 ns/cell flat, so coloring cost is driven by cell count, never display density): 1×1 at the deepest steps (Block/chunk — full fidelity where the player is closest to visible detail; chunk-64 m is now the deepest Atlas rung, §(a.8b)), 1×1 preferred at the mid steps (Quarter/District) while the realistic canvas stays under ~2M cells, and ~5×5 reserved for the shallow rungs (Region/rung 1 — and the Global/rung-0 opener, whose region-grid canvas is tiny in cell count regardless of ratio) where the metre extent grows large. There is no measured reason to sacrifice fidelity where the player is nearest the detail; the ~5×5 fallback is a cost-relief valve for the coarse steps only. This changes nothing about the snap rule or the cache key — the ratio still governs only presentation (canvas extent sizing + on-screen scale), and per-step ratio selection is a client-side policy, never a spacing or derivation input.
(a.5) D-226 T-1124 §2 windowed-family ceiling — tagged-envelope migration triggered
Paste as an amendment on D-226 (extends the amendment chain that already holds the T-1156/T-1170 carrier notes):
Amended 2026-07-25 (body-map-viewer workshop — tagged-envelope migration triggered, superseding T-1143 ruling 2's "no forced migration"). The windowed-family ceiling's purpose survives untouched: prevent uncorrelated concurrent windowed queries needing per-field request correlation. Its current mechanism — "exactly one windowed-query field on
AtlasLayerResponse(district_window), sized for a ≤4,096-cell served window" — cannot carry a step canvas: measurement ④ (T-1179) shows the best available encoding (PNG-per-field) at 21×–563× the ~30 KB reference across the three measured canvas sizes (330K/2.07M/8.3M gridunits), with no encoding in the measured set closing that gap (it is a cell-count gap of two to three orders of magnitude, not a codec gap). The tagged-envelope migration D-225 deferred (2026-06-12 constraint: "the next inbound message type must introduce a tagged envelope") is hereby the sanctioned path and is executed: the step-canvas payload becomes its own tagged message type on the existing IPC stream (not a second socket, not adistrict_windowgrowth) — the exact shape §(b) fixes. The ceiling rule is re-scoped, not lifted: "exactly one windowed-query field" now governs the legacydistrict_windowcarrier only; the tagged step-canvas envelope is a separate carrier the ceiling rule does not apply to by construction — it is not a second windowed field on the old shape, it is the new shape. The ceiling's original job (no uncorrelated concurrent windowed queries) is preserved within the envelope by the same echo-key/staleness disciplinedistrict_windowuses today ((body, step, center, granularity)echoed on every response, latest-wins, stale-discardable). Framed as expected scope, executing a planned deferral — tier: challenging but doable, not a risk. Concrete shape (Dudley, §(b)): inbound is a discriminator-fieldStepCanvasRequest { step_canvas: bool, body_id, step_index, center, extent, min_wl_m }— a sixthInboundvariant extending the existingstar_map/city_names/browseShapeProbepattern (the required-marker form D-225's 2026-06-12 amendment named); outbound is a dedicatedStepCanvasResponsemessage (not a field onAtlasLayerResponse) +SimBridge::send_step_canvas_response. The legacydistrict_windowcarrier survives byte-unchanged — the envelope carries only new step-canvas traffic;district_windowgoes cold when its only client (the retiredAtlasWindowViewer) is deleted, then is removed in a follow-up cleanup ticket (D-005/D-192 co-ship — no old-client/new-server window). The ceiling rule is therefore RE-SCOPED, not retired: it keeps governing the live legacy carrier verbatim.
(a.6) Map-time axis + storage/staleness eviction split (Jeroen's interview-1 amendment)
New — records interview-1 ruling 2 verbatim-grounded. Paste as an amendment on D-227 (the derive-don't-store record whose cache discipline this instantiates) and cross-reference from the new render-architecture record:
Amendment (2026-07-25, body-map-viewer workshop — map time axis; and staleness vs storage as distinct cache axes). The Atlas map shows current state via a TTL-split: static geometry (morphology/elevation/moisture/ vegetation/glaciation/height — everything derive-don't-store covers) is cached indefinitely-fresh (determinism: re-derivation is byte-identical, so "stale" is not a concept that applies to geometry); sim-state planes (frozen/flooded, and any future climate-sim-driven field) are carried as separately-cached short-TTL planes, re-requested as sim time advances. Two distinct eviction axes (Jeroen, interview 1, verbatim: "we still may also want to evict non global level geometry based on time to save storage for planets the player visits but never goes back to"): (1) staleness-eviction applies only to sim-state planes (they genuinely go stale as sim time moves); geometry never goes stale. (2) storage-eviction applies to all sub-global cache entries including geometry — every fixed rung, Region (rung 1) through Chunk (rung 5), included — evicted on time-since-last-visit purely as a storage-budget policy, not because the data is wrong (a re-derive on next visit is byte-identical and cheap — measurement ②/③, ~190–220 ns/cell parallel flat at every rung). The global tier — rung 0 (Global, the body-surface region-grid canvas), NOT Region — alone is keep-always — exempt from both axes, the resident tier that makes "atlas navigation snappy after first calc" true. (Region is rung 1, the largest fixed rung; it is viewport-sized and storage-evictable like every rung below it — the always-kept tier is the variable Global opener above it.) This makes Dudley's
TTL(detail, time, distance)formula precise: thetimeterm is storage-eviction for geometry (evict a long-unvisited body's fine-rung canvases to reclaim disk) and staleness for sim-state planes (re-fetch a flooded/frozen plane whose sim-time TTL expired) — two different reasons an entry leaves the cache, never conflated.
(a.7) river-courses-t1170.md carrier rule + cliff sparse-list — terminology repoint + cliff addition
Paste as a note at the top of docs/architecture/river-courses-t1170.md and as
a one-line D-227 cross-reference update:
Note (2026-07-25, body-map-viewer workshop). The carrier three-way rule (Ruling 1c) survives unchanged in substance; "the windowed payload" is repointed terminologically to "the per-step data-canvas payload — formerly the
district_windowfield, now the tagged step-canvas envelope (D-226 2026-07-25 amendment, §(a.5))." Rule (iii) — rung-indexed invented detail rides the windowed payload regardless of geometric kind — now has a second vector member alongsidecourses:cliffs: Vec<CliffSegment>. Carved-gorge geometry (dominantelevationunchanged + per-segmentchannel_depth+cliff_edge, T-1177's direct solver-output carry) is rung-indexed invented detail exactly as course geometry is (hydrology settles once per body, but the carved representation drawn at a step is a windowed-rung concern the same way course geometry is), so it rides the step-canvas envelope as a sparse feature list — zero-length when nothing is carved (measurement ①: gorge carving is structurally rare, zero carved cells across all three production-scale benches),#[serde(default)], parallel tocourses. It is not a dense per-gridunit array and not a stolen bit of an existing classification byte. Scope: Phase-4 Atlas (Jeroen, interview 1, ruling 3 — a map showing a smooth shoreline where the settled solver computed a carved channel would misrepresent the "settled hydrology" the workshop premised; including it is nearly free given the direct-carry representation). The sparse-list encoding's "near-zero occupancy" cost is SURVEY-CONFIRMED population-wide (Troblum B1, resolved strong): the pre-filing population survey ran all 267 committed real heightmaps independently (each body's own PNG-embedded sea level, real 512×256 working grid, ~0.86 s total, byte-exact determinism across two runs) and found zero carved-outlet basins, zerocliff_edgecells, 0/267 bodies with any carving — across genuinely varied terrain (31–187 basins/body), not a flat population. Thecliffsfield ships empty on every currently-committed body; the "near-free" claim is now population-backed, not one-body-backed. Framing held deliberately at "not observed yet ≠ cannot occur": the carving arithmetic (channel_depth = original − spill_level, thecliff_edgeflag) stays unit-proven in isolation for any future body whose terrain does produce the narrow two-independently-sealed-basins-plus-single-cell-corridor geometry carving requires — the field-set and Phase-4 scope stand because the model must represent what the solver can produce, and the sparse-list is the right shape at zero occupancy (empty vec,#[serde(default)]) and remains a correct shape at any future nonzero occupancy. Survey scope limit to carry into the filed record: the survey used uniformmoisture_q = 55(per-body climate wiring is out of scope) — this affects only the endorheic/overflow split, never carving (carving is elevation-gated, never moisture-gated), so the zero-carving finding is independent of the climate simplification. Full addendum:measurements/t1177-hydrology.md"POPULATION SURVEY" section.
(a.8) D-226(d) whole-body prohibition — per-request framing + client-cache accumulation cap (Troblum S3)
Paste as an amendment on D-226 (the item-(d) prohibition), alongside the ceiling amendment §(a.5):
Amended 2026-07-25 (body-map-viewer workshop — accumulation gap closed, Troblum adversarial pass S3). The item-(d) whole-body prohibition ("chunk/ tile/voxel output never appears as a whole-body planetary map layer") is stated explicitly as a per-request / per-derivation constraint, not an aggregate-storage constraint. The stepped ladder's viewport-sizing policy holds it by construction server-side: no single
StepCanvasRequestever derives whole-body coverage at sub-Region spacing (the deepest step is a chunk-64 m viewport canvas — see §(a.8b) for the tile/voxel-drop narrowing). But the client-side persistent cache (Stig'sFileAccessstore) introduces an accumulation path the letter of the rule does not cover: a systematic exhaustive pan at the deepest (chunk) spacing — most plausibly the D-226 item-(4)AtlasAgentInterfaceautomated QA sweep, not normal play — could assemble a near-whole-body chunk-resolution artifact as N discrete cached files over wall-clock time (the tile-spacing case that produced the ~985 GB / 6.6M-tile figure is now moot at the Atlas ladder — tile is dropped, §(a.8b) — but the accumulation principle still applies at chunk/block spacing, just at a coarser resolution and a proportionally smaller aggregate; impossible by accident, but not structurally prevented). The rule's purpose is about information content, not file count, so packaging it as N files does not exempt it. Closed structurally, not by improbability: a per-body deep-rung client-cache retention cap (a maximum resident chunk/block-spacing tile count or disk quota per body, independent of the rung-0/Global retention floor) bounds sub-global accumulation so the aggregate can never approach whole-body metre-resolution coverage. The automated QA channel inherits the same cap — an agent sweep's client cache is bounded identically, so a QA run cannot silently deposit the forbidden artifact inuser://atlas_cache/. The exact cap value is a tuning constant sized in Stig's cache spec at implementation; the requirement that a cap exist is record-level.
(a.8b) D-226(d) floor — partial restore at chunk (Jeroen's interview-2 narrowing of his own interview-1 opening)
Paste as an amendment on D-226, immediately after the T-1143 ruling 1 block (which opened item-(d)'s floor for the ladder) — this narrows that opening:
Amended 2026-07-25 (body-map-viewer workshop, interview 2 — the opened floor lands at chunk; tile/voxel re-close for the Atlas). T-1143 ruling 1 (2026-07-21) opened item-(d)'s floor "toward block/tile granularity" for the Atlas ladder, on the BHAG that "we set a new BHAG so old restrictions are up for debate." Interview 2 scopes that opening — it does not reverse it. Jeroen (verbatim): "the actual tile level rung seems unusable. maybe replace with 64?" Reasoning (matching the workshop's own seam logic): a 10-px-per-tile full-screen Atlas view is ~192×108 m of ground — that is in-world viewport content (Phase-5 scope), not a map. The Atlas zoom ladder therefore bottoms out at chunk (64 m), and tile/voxel (1 m) output returns to never-Atlas-mapped — exactly item-(d)'s original prohibition, now restored for the tile/voxel tier specifically. Precise post-interview-2 state of the floor: the opening is used down to chunk (64 m) — block (128 m) and chunk (64 m) are legal Atlas rungs, riding the viewport-sized windowed carve-out (§(a.8) per-request framing) — and re-closed below chunk: tile (1 m) and voxel/subvoxel output are Atlas-invisible, verified by the believability/derivation harnesses and shown in-world in Phase 5, exactly as item (d) originally required. This is a deliberate narrowing of the BHAG's scope, not a walk-back of the BHAG ("a Reach a character can travel through" is unchanged; what changed is that the Atlas map stops one rung above the in-world viewport, because that's where a map stops being a map). The harness-verification path for tile/voxel L5 fill remains primary, as it was before the opening — the opening's practical effect is now limited to the block and chunk rungs, which is the range where a whole-viewport canvas still reads as a map rather than a scene.
(a.9) Client-cache schema/version tag — the one D-192 gap (Troblum S5)
Paste as an amendment on D-227 (the cache-discipline record) and cross-reference from D-192:
Amendment (2026-07-25, body-map-viewer workshop — persistent-cache version discipline, Troblum adversarial pass S5). D-192 drops the client/server protocol version handshake on the subprocess-co-ship rationale ("the Godot client launches the Rust server it was built with — always in sync at runtime"). That holds for the live wire, and for the tagged-envelope migration itself (no live network deployment where an old client meets a new server). It does not hold for a disk-backed persistent cache (Stig's
user://atlas_cache/store, premise 9): a cache file written by game version N and read back by version N+1 survives a game update by construction — exactly the version boundary D-192 assumes away everywhere else. A patch that changes the step-canvas payload shape (adds a field — e.g. this workshop's owncliffslist — or shifts an enum discriminant range per T-1150's "unknown values fall back, never trusted from the wire") would have an N-schema cache decoded as N+1-schema: a hard decode error at best, a silent misinterpretation of old bytes as new fields at worst (the exact class D-225's 2026-06-12 tagged-envelope constraint prevents for the live wire, now extended to the disk format). Requirement (record-level): every persistent client-cache entry carries a schema/version tag at write time (the game'sproject.yamlversion string, or agenerator_sha-style stamp), and a read-time check: a tag mismatch is treated as a cache miss — re-fetch, never decode. This extends the existing cache-index shape ({written_at, last_read_at, kind, size_bytes}+schema_version) by one field; it lands in Stig'sFileAccessspec at implementation, but the requirement is stated here so it is not discovered as a stale-cache decode bug in the wild. Consistent with D-227's "cache never truth, evict → recompute always valid" — a version-mismatched entry is just another eviction case.
(a.10) Seed-chaining — the "cache-accelerated pure function" model (Jeroen interview-2: he meant consuming coarser output)
Paste as an amendment on D-227 (this is the one place derive-don't-store meets
"a finer step reads a coarser step's output") — for Jeroen's final
ratification against his phrase "serves as seed information for the deeper
cascade." Governance framing is mine; the cost/impl side is
Dudley-confirmed (dudley-interview2-response.md §2) — his A/B mechanism
distinction is folded in, and the [DUDLEY] bracket is resolved.
Amendment (2026-07-25, body-map-viewer workshop, interview 2 — seed-chaining resolved as a cache-accelerated pure function). Jeroen's outline — "[the step canvas] at the same time serves as seed information for the deeper cascade" — is ruled at interview 2 to mean the finer step consumes the coarser step's resolved output (not merely that the coarser rung is independently re-derivable). This is reconciled with D-227 derive-don't-store without weakening it, via the cache-accelerated pure function model:
- What "consuming coarser output" means precisely — mechanism B, not mechanism A (Dudley §2, load-bearing to prevent a subtle violation). (A) Reading the coarser step's RESOLVED CLASSIFICATION (e.g. taking a District-spacing
morphology_zoneas a shortcut for a Chunk cell's zone) is ruled OUT — it violates Araminta's categorical-field re-derivation rule (§(a.6)/round-1: coarser steps re-derive morphology/vegetation/ glaciation as a fresh dominant-mode pick at their own spacing, never inherit a different spacing's classification — the same-vocabulary/different-meaning- per-scale contradiction). (B) Reading the coarser step's underlying CONTINUOUS PRIMITIVE (the region/district baseline blend at a world position) as an input to the finer step's OWN fresh classification is what "seed information for the deeper cascade" means — and it is already the shipped pattern (invent_primitives's district call reads a region baseline today). The cache-accelerated model applies to (B): cache the continuous baseline blend, not the resolved classification.- The DEFINITION stays pure. Every gridunit value remains
derive(seed, position)— a pure function of fixed inputs, byte-identical on every evaluation (D-010/D-227 unchanged). "Consuming the coarser output" does not make the finer step a function of mutable state; the coarser baseline it consumes is itselfderive(seed, position)at the coarser rung — a pure value, not a stored fact.- The IMPLEMENTATION may read a resident coarser canvas as an ACCELERATION, with a derive-fresh fallback when that canvas isn't resident. Reading the cached coarser canvas is faster than recomputing it; not having it costs a fresh derive of exactly the shape Dudley already benched.
- This is an OPTIMIZATION, not a SEMANTIC DEPENDENCY — the load-bearing governance distinction. The coarser canvas being read is itself evictable derived data (a pure function of the same seed). So correctness never depends on the cache being warm: if the coarser entry is evicted, the finer step derives it fresh and gets byte-identical input, producing the same output. That is precisely D-227's own standing test — "eviction → recompute, always valid." A semantic dependency would mean "the finer step is wrong without the coarser cache" — never true here, because the coarser value is re-derivable to the same bytes. The cache is still never truth, only an accelerator: derive-don't-store holds intact.
- Mandatory determinism test (the proof that makes this airtight): the cache-hit path (read resident coarser canvas) and the cache-miss path (derive the coarser input fresh) must produce byte-identical finer-step output — both are the same pure function of the same seed. This is a required test, the same shape as T-1170's window-independence invariant. If it passes, the two paths are indistinguishable except in speed, which is the definition of "optimization, not dependency." If it ever failed, that would be a determinism bug (a non-pure derivation), caught here rather than corrupting a save (D-227's determinism-is-save-critical clause).
- Benched numbers survive as worst-case ceilings (Dudley-confirmed). Every ①②③ cost number measured the independent re-derivation path — which is exactly the cache-miss fallback. So the measured costs are the cache-cold ceiling: the shipped system is never slower than the appendix, and is faster whenever the coarser baseline is resident. This closes Troblum B2's "every cost number prices the wrong architecture" worry — the numbers price the fallback, and the fallback is the worst case, so they remain authoritative as an upper bound.
- No chain-reaction on eviction (Dudley-confirmed). A deep-step (chunk) cache miss does not walk backward through evicted District/Region cache state — each rung's fresh-derive fallback is fully self-contained (
derive(seed, position)takes nothing but those two inputs, by construction), so a miss costs one fresh derive at that rung's own inputs, never a cascade through every evicted ancestor. Troblum B2's chain-reaction worry dissolves — there is no dependency to chain, because the fallback was never built to depend on any other rung's cache state.- Acceleration magnitude is unquantified but not architecture-gating (Dudley-confirmed honest caveat). The saving from reading a cached continuous baseline vs. recomputing it (mechanism B) is very likely real but modest — no bench isolates the region-baseline-blend sub-cost from the full
derive_at_metrescall (most of the per-cell cost is the octave-sum detail-scatter work mechanism B does not propose caching). This is a future implementation-time measurement, not a gate on the architecture ruling: the ①②③ ceiling numbers already answer the load-bearing yes/no, and the "expected" (as opposed to worst-case) latency is sized later.- Cross-reference: supersedes Dudley's round-2 §(b) "independent re-derivation, never reads a cached response" as the exclusive rule — that ruling survives as the fallback path's description (function-composition on a cache miss); interview 2 adds the cache-read fast path (mechanism B) on top, governed by the byte-identical-paths test above.
(a.11) Lakes — settled-hydrology sourcing of the existing MorphologyZone::Lake; endorheic cue via outflow-course presence (FINAL, converged)
FINAL — fully converged on both sides. The endorheic-cue residual is closed:
Dudley picked Araminta's outflow-course presence (his doc updated with proper
supersession — the stale 4-state-water sections, a crossed-in-flight reply to
Araminta's original questions, are marked SUPERSEDED-BY-CROSSING and traceable,
not deleted; his corrected section carries her 8-dense + 2-sparse struct with a
no-dissent confirm). No open clauses remain in this amendment.
Paste as an amendment on D-227 (the derive-pipeline record — the fill is a
data-source fix, not a wire change) with a D-239 §6 cross-reference. Converged
sources: Araminta's encoding ruling (araminta-round2.md §(e), where she verified
Dudley's code-read at source — district_profile.rs:556-565,
generator.rs:1198-1223, features.rs:104-105 — and withdrew her earlier
new-field proposal) + Dudley's pipeline ruling + endorheic-cue pick
(dudley-interview2-response.md, "LAKES CONVERGENCE", corrected section).
Amendment (2026-07-23, body-map-viewer workshop — lakes sourced from settled hydrology; endorheic cue via outflow-course presence). The outline's lake behaviour (settled fill, overflow, endorheic sinks — measurement ①/T-1177) reaches the Atlas map with no new wire field and no vocabulary change:
- Lakes ride the EXISTING
MorphologyZone::Lake(discriminant 1, already in the frozen 17-zone D-239 §6 vocabulary — not a new zone; no new wire field for the fill itself). The gap was never a missing vocabulary entry; it was a missing data source. Todayderive_morphology_zoneemitsLakefrom a crude heightmap threshold (ocean_fraction_q >= 60, a bilinear sample ofelev < sea_level), with zero connection toHydrologyResult's settled-equilibrium basins (the code's own comment already flags this as a known gap). The fix:derive_morphology_zonesources theLakeemission from settled hydrology instead of the heightmap heuristic, falling through to today'socean_fraction_qheuristic where no basin exists.- Pipeline sourcing — sample the continuous
filled_scaledfield, NOT projected basin-cell membership (Dudley's ruling, adopted). Water derives fromHydrologyResult's continuousfilled_scaledfield sampled bilinearly at each gridunit's world position (the same mechanismocean_fraction_q/sea_levelalready use) — not from basin-cell membership projected as a discrete 512×256 lookup, which would produce a blocky, non-refining lake edge — exactly the magnified-coarser-composite artifact D-166's corollary forbids (§(a.1)). This is seed-chaining mechanism B (§(a.10)) applied to hydrology exactly as it already applies tosea_level: sample a coarser rung's continuous primitive fresh per rung, never re-solve — so the lake edge refines with zoom (a genuine finer curve at each rung), not a coarse grid magnified. Sea vs. Lake is unchanged (both already-existing discriminants; theOpenOceantier is untouched).- Static, distinct from the sim-state flooded plane. Lake basin geometry is a settled equilibrium — a pure function of seed + terrain (D-227), cached indefinitely-fresh like all geometry. It is not the short-TTL frozen/flooded sim-state plane (§(a.6)); a lake's existence and extent are static, while the flooded plane is the sim-time-varying water-height overlay. The two do not conflate.
- Endorheic-vs-overflow cue = OUTFLOW-COURSE PRESENCE. No wire bit, no new zone (FINAL). The distinction (a lake that drains vs. a closed sink) ships as a client-side read of whether a lake has a river course exiting it: an overflow basin's outlet edge appears in
courses(T-1170); an endorheic basin's does not. Three reasons this is the right carrier, not a dense marker:
- Proportionality. Endorheic is 1,030 of 22,270 basins = 4.63% in the real population. A per-cell bit under morphology-fold would force either an 18th
MorphologyZonearm — a D-239 frozen-vocabulary change every consumer inherits forever (including the one-colorizer-family guarantee) — or a new wire field, for a fewer-than-1-in-20 distinction, when a zero-marginal- cost alternative exists.- The work is required regardless. Overflow lakes must show their exit rivers to be hydrologically honest (a lake that drains but shows no outlet river is simply wrong on the map) — so the basin-outlet→course wiring is built no matter what. The endorheic cue is a side effect of that required work, not a feature it pays for.
- Definitionally sound, no misfire case. Every
Overflowbasin has a guaranteed non-emptyoutlet_path(tested:overflowing_basin_has_nonempty_outlet_path); everyEndorheicbasin has none. The presence/absence read is exact — there is no basin class that drains-but-shows-no-course or is-closed-but-shows-a-course. The cliffs list is NOT the cue (T-1177's survey: zero carved cells across all 267 real bodies — a cliff-wired cue would fire nowhere).- Honest scope — until the outlet-wiring ticket ships, there is NO visible endorheic cue.
HydrologyResult's basinoutlet_path/BasinOutcomeis not currently threaded intoRiverNetwork/courses(D8-network-derived, a different computation; T-1177's own scope note confirmsHydrologyResultis prototype-only, unwired to any payload). So the two deliverables are distinct: theLakesourcing fix (self-contained — the map shows lakes as water) and the outlet-wiring (the exit-river distinction). Between them, the map shows lakes but not the drains-vs-closed distinction — state this plainly; it is not a gap in the design, it is the honest sequencing. The outlet-wiring is a real, small, additive follow-up ticket (§(d)), pre-cleared by T-1170 Ruling 7b (the reservedTERMINALdownstream sentinel: "an interior sink becomes an additive drainage-extraction change, not a wire migration... the work is in D8 sink retention and lake morphology, and every piece this batch builds consumes them without modification"), andriver_course::build_edgesis already no-op-safe onTERMINAL(Dudley's confirm) — additive, not a migration.- Visual treatment: lakes draw as water at every rung, same colorizer family as sea/ocean (one-colorizer-family guarantee, Araminta round-1 §3 — a
Lakediscriminant colours identically whether sourced by heuristic or basin); endorheic-vs-overflow reads via outlet-course presence at the lake shore (no distinct fill/texture on the lake body, no new styling rule for Stig — the present-or-absent exit river is the visual difference).
(b) TAGGED-ENVELOPE MECHANICS — governance disposition (with Dudley on wire/serving)
Division of labor: I own the record framing + the D-225/D-226 §2 disposition
(what happens to the ceiling rule). Dudley owns the wire/serving design (message
shape, demux, legacy coexistence). Dudley has ruled (dudley-round2.md §(a),
grounded in a direct read of server/src/bridge/mod.rs); his three answers are
folded in below and §(a.5)'s bracketed clause is now resolved.
The ceiling-rule disposition (mine, final)
The windowed-family ceiling (D-226 T-1124 §2, [HARD]) has two separable parts, and only one moves:
- Its purpose — "no uncorrelated concurrent windowed queries needing per-field request correlation" — is preserved in full. This is why the rule existed: two independently-in-flight windowed queries would each need their own request→response correlation, and the hand-rolled shape-demux couldn't carry that. The tagged envelope strengthens this: a tagged message has an explicit correlation handle by construction (the tag + echo key), which is strictly better than the shape-demux the ceiling was protecting.
- Its mechanism — "exactly one windowed field on
AtlasLayerResponse" — is re-scoped to the legacy carrier only. The rule was a fence around a hand-rolled demux, not a first-principles limit on windowed data. Once a proper tagged envelope exists, the fence is obsolete for anything inside the envelope: the envelope can carry as many correlated fields as its schema declares, because the tag makes correlation explicit rather than structural.
So the disposition is: the ceiling rule keeps governing district_window
(the legacy shape-demuxed carrier) verbatim, and does not extend to the tagged
step-canvas envelope, which is a new carrier with its own explicit correlation
discipline. This is the same move T-1156 and T-1170 made in miniature (both
kept traffic off the ceiling by choosing the right carrier) — the difference
is those two stayed inside the one-field shape because they could (skeleton is
whole-body; courses are content of the existing field), whereas the step canvas
cannot (cell count alone forces a new carrier), so this one builds the
envelope the others didn't need.
D-225's constraint is landed on its intended target. D-225's 2026-06-12 amendment said the next inbound message type must introduce a tagged envelope rather than extend shape-based detection. Every carrier since (T-1124's window params, T-1131's BrowseRequest — "the fifth and last map-shape probe") deferred it by riding existing shapes. The step canvas is the one that can't ride an existing shape, so it is correctly the one that pays the deferred cost. This is a planned migration executing on schedule, not an emergency.
Three slots — Dudley's rulings, folded in
Dudley read the actual decode_inbound/Inbound code and found the
"tagged-marker" pattern D-225 asked for is already implemented five times
(each newer inbound shape — StarMapRequest/CityNamesRequest/BrowseRequest
— carries a mandatory boolean discriminator, and ShapeProbe already enforces
at-most-one-discriminator). So the migration extends a proven pattern rather
than inventing a new envelope format — which sharpens my governance framing: at
the code level this is "doable," and the "challenging" part lives in the
client rebuild (Stig) and the cache/ladder work, not the demux.
-
Message shape → discriminator field on the existing stream. Inbound: a new
StepCanvasRequest { step_canvas: bool, body_id, step_index, center, extent, min_wl_m }as a sixthInboundvariant, extending the existingShapeProbemutual-exclusivity chain. Outbound: a dedicatedStepCanvasResponsemessage (not a field onAtlasLayerResponse— D-226 T-1124 §2 names this exact "dedicated response message by rule" case) +SimBridge::send_step_canvas_response. My §(a.5) text stands verbatim — "its own tagged message type on the existing IPC stream" is exactly a discriminated inbound variant + dedicated response message; D-225's language was "a tagged envelope (or a required marker field)", and the required marker field is what ships. The ceiling disposition is identical to what I drafted. -
Legacy coexistence →
district_windowsurvives unchanged; the envelope carries only the new step-canvas traffic. Dudley's call matches my lean: no retirement message, no dual-write, no migration of existing windowed traffic. The legacy carrier keeps working byte-for-byte until Stig's stepped viewer replaces its only client, at which point it goes cold and gets deleted in a follow-up cleanup ticket (D-005/D-192 co-ship guarantee means no old-client/new-server window). Therefore the ceiling rule is RE-SCOPED (my §(a.5) primary text), not fully retired — it keeps governing the live legacydistrict_windowcarrier verbatim; the envelope is the new carrier outside it. The §(d) deprecation table's parenthetical "(if Dudley rules one-carrier-subsumes-all → SUPERSEDE)" branch does not fire — re-scope is final. -
Rung-0 (Global) and rung-1 (Region) both ride the NEW envelope — at
step_index: 0(Global, the variable body-surface region-grid canvas) andstep_index: 1(Region, 204.8 km fixed), not the legacy whole-bodyregion_grid/district_gridOptionfields. Dudley's reasoning is the one I'd have given: putting the opener on the legacy family would force the new stepped client to speak two response protocols (envelope for the deeper rungs, old family for the opener) for zero architectural gain — one request shape, one response shape across the whole ladder is simpler on both sides and is what premise 8 ("step boundaries = compute-chunk boundaries") implies uniformly. The only per-rung difference is that rung 0's canvas extent is variable (the region grid) rather than a fixed pixel budget — a field value onStepCanvasRequest, not a different message shape. Render-architecture record "Wire" bullet updated accordingly (§(a.0): the envelope carries every rung including the Global opener; the legacy whole-body layers keep serving whatever non-stepped consumers survive the cutover, if any).
Response framing (Araminta's relayed dense/sparse question, Dudley answered):
one flat tagged StepCanvasResponse carrying all fields together (six dense
PNG-per-field + settlement_id dense + courses/cliffs sparse
MessagePack-native), not a dense/sparse split into separately-tagged
sub-messages. The progressive-paint UX case (terrain first, annotations after)
is real but belongs client-side (paint the RTT layer on decode, defer the
annotation draw a frame) — no wire-protocol complexity for a cost split the
measurements don't show (courses +0.09–0.21 ms, negligible). This matches the
whole-payload-together precedent D-225 set for Layer1Output.
Filing note: §(a.5) and §(a.0) are now final — no bracketed clauses remain.
(c) STEP-LADDER TABLES — snap-rule constraints (mine) + costs (Dudley's)
INTERVIEW-2 UPDATE — tile/voxel dropped, chunk-64 m is the new deepest rung,
and Dudley's Option D is DELIVERED (every row measured). Jeroen ruled the tile
rung "unusable" (§(a.8b)); chunk (64 m) is the deepest Atlas rung. Dudley
benched the never-measured chunk rung (dudley-interview2-response.md §1) and
built Option D — this is now the live ladder table (below). Options A/B/C
are superseded and retained only for the carried-forward reasoning.
Option D — the adopted ladder (six levels: Global opener + 5 fixed rungs; chunk-64 m deepest, every fixed rung measured)
Six levels after Jeroen's interview-2 rung-identity correction: rung 0 = Global (the variable body-surface region-grid map opener, always-kept), then five fixed metre rungs Region→Chunk.
| Rung | Level | Spacing | Factor (from prev) | Canvas | Cells | World extent | Derive cost (parallel) |
|---|---|---|---|---|---|---|---|
| 0 | Global (opener) | 1 gridunit / region (~205 km) | — | variable — the body's region grid | ~18K (avg/body; ~19K Earth-class) | whole body | ~16–21 ms/body single-thread (Earth-class 18,915 cells = 15.9–16.2 ms; largest 25,200 = 20.9–21.3 ms; ~830–910 ns/cell); ~8.85 MB PNG all 267 bodies |
| 1 | Region | 204.8 km | — (variable→fixed seam) | 3840×2160 | 8.3M | whole body (capped mosaic) | 1,827 ms |
| 2 | District | 2,048 m | 100× | 3840×2160 | 8.3M | 7,864 × 4,424 km | 1,827 ms |
| 3 | Quarter | 512 m | 4× | 3840×2160 | 8.3M | 1,966 × 1,106 km | ~1,827 ms (same-band) |
| 4 | Block | 128 m | 4× | 3840×2160 | 8.3M | 491 × 276 km | ~1,827 ms (measured) |
| 5 (deepest) | Chunk | 64 m | 2× | 3840×2160 | 8.3M | 245.8 × 138.2 km | 1,724–1,733 ms (measured) |
Rung 0 (Global) is categorically different from the fixed rungs: its canvas
is the body's region grid (one gridunit per region), so its extent is variable
per body (the D-243 elastic seam — region count floats per body_radius_km,
~19K gridunits Earth-class, far smaller than a fixed 4K canvas) and it is the
sole always-kept tier. Rung 1 (Region) is the largest fixed rung — 204.8 km
spacing, a fixed 3840×2160 viewport canvas, evictable like every rung below. The
Global→Region transition (rung 0→1) is the variable→fixed seam, not a metre
factor; the first metre factor is Region→District (rung 1→2, ÷100).
Every fixed row (1–5) is directly measured or in a directly-measured band — the "zero asterisks" property the old Option B earned by skipping chunk, now earned by measuring it. (Rung 0 is Dudley-measured too: ~16–21 ms/body single-thread over ~18K region-grid gridunits, ~8.85 MB PNG across all 267 bodies — trivially cheap to derive and store.) Two things Option D settles that the old tables couldn't:
- The deepest-step canvas-sizing special case is GONE. The old voxel/tile deepest step needed a display-ratio-sized canvas (216×384 m at 10 px/tile, not the fixed-budget convention every other step used, because the two were incompatible at 1 m spacing). Chunk has no such incompatibility — at 1×1 px/gridunit the fixed 3840×2160 budget and the "no magnification margin" bottom-out rule are the same rule, so chunk uses the plain fixed-canvas convention like every other rung. Dropping the special case is a genuine simplification, a free consequence of Jeroen's own ruling.
- Deepest-step derive cost rose two orders of magnitude in absolute terms (17 ms → ~1.7 s) — and that is correct, not a regression. Chunk's canvas covers a vastly larger world area (216×384 m → 245.8×138.2 km) at the same cell count, so it costs the same as every other rung's full canvas (1.7–1.8 s parallel band) — which is exactly what "no special case" means. 1.7 s parallel is comfortably inside the step-cross tolerance every number in this workshop uses. Cost still does not gate this rung.
Bottom-out rule (record-level, §(a.0)/§(a.4)): 1 screen px per 64 m gridunit, no additional magnification margin. The old 10×-per-tile rule was a legibility margin for a sub-readable 1 m unit; a 64 m gridunit is already a legible map feature, so it does not carry over — applying it would needlessly shrink coverage 10× for no legibility gain.
My snap constraints (hard, from the snap rule + interviews 1 & 2, corrected for the Global/Region rung-identity fix):
- Every fixed rung's gridunit spacing = one of D-243's metre rungs. The Atlas ladder's fixed rungs are region ~205 km (rung 1), district 2,048 m, quarter 512 m, block 128 m, chunk 64 m (rung 5) — tile/voxel (1 m) is NOT an Atlas rung (§(a.8b), Phase-5 in-world content).
- Rung 0 = Global — the variable map opener (one gridunit per region, the body's region grid; D-243 elastic seam), the whole-body canonical / always-keep tier. This is the ONE variable-extent level; it is not viewport-derived (its gridunit is a whole region, a fixed property of the body).
- Rung 1 = Region (~205 km) — the largest fixed rung, viewport-sized and evictable like every rung below it; not the always-kept tier (that is Global).
- Deepest rung (5) bottoms at chunk (64 m), at 1×1 px/gridunit, no margin — fixed 3840×2160 canvas like every other fixed rung (no display-ratio-sized exception; that oddity died with the tile rung).
- No fixed rung invents a spacing D-243 doesn't name.
- Display ratio (px/gridunit, 1×1 → 5×5) is the free client knob, decoupled from spacing — it sizes the canvas extent and the on-screen scale, never the spacing.
The material below (Options A/B/C + convention notes) is pre-interview-2 (voxel-deepest) reasoning, superseded by Option D above. Retained for the carried-forward logic (factor-unevenness analysis, the zero-asterisk argument) — every "voxel 1 m / 216×384 m / 10 px/tile" row is void.
The tables and convention notes below are pre-interview-2 (voxel-deepest) reasoning, retained for the carried-forward logic (canvas convention, factor analysis, zero-asterisk argument). Options A/B/C and every "voxel 1 m / 216×384 m / 10 px/tile" row are SUPERSEDED by Dudley's Option D (chunk-64 m deepest). The display-ratio-split logic below still holds — it just now lands the "display-ratio-sized deepest step" at the chunk rung, with Dudley's chunk bench supplying the deepest-row numbers that replace 216×384 m / 17 ms.
Canvas convention (Dudley's correction, adopted — reads at chunk now, not voxel): the fixed 3840×2160 canvas-pixel budget holds at every step except the deepest — at the deepest rung the fixed-px-budget convention and the display-ratio contract are mutually incompatible (a fixed 3840×2160 canvas at metre-scale spacing covers little ground yet holds many cells, oversized for the bottom-out display density), so the deepest step is display-ratio-sized instead. (Pre-interview-2 this was voxel 1 m → 216 × 384 m / 82,944 cells, measurement ③; post-interview-2 the deepest rung is chunk 64 m and the extent is Dudley's Option-D chunk display band.) This is a convention-level split (fixed-budget shallow, display-ratio deep), not a skeleton-specific one.
Per-step display ratio (Stig, measurement ⑥): the px-per-gridunit ratio is
step-dependent, not flat — 1×1 at Block/chunk (full fidelity where the
player is nearest visible detail; ⑥ confirms set_pixel at 77.5 ns/cell flat,
so cost is cell-count-bound, not display-density-bound), 1×1 preferred at
Quarter/District while the realistic canvas stays under ~2M cells, ~5×5 at
the shallow rungs (Region and the Global opener) where extent grows. This
tightens the extent column above: at
the shallow steps the ~5×5 ratio means a coarser realistic canvas than the
fixed 3840×2160 worst-case (fewer cells, cheaper), so the 8.3M/1,827 ms figures
in the tables are the fidelity-ceiling cost, not the typical one — the actual
shallow-step canvas at ~5×5 is proportionally smaller. The deep steps stay at
1×1 (the 17 ms/83K deep-step number is already at full 1×1 fidelity). Cost only
improves against the table where the ratio relaxes; nowhere does it worsen.
Three candidate ladders — Dudley's cost fills folded in (all costs MEASURED or same-band-confirmed against ①–④; the one honest gap, chunk at 64 m, is flagged not guessed):
Option A — one-rung-per-step (6 steps, clean 1:1 to D-243)
| Step | Gridunit rung | Spacing | Factor | Viewport extent | Cells | Derive cost (parallel) |
|---|---|---|---|---|---|---|
| 0 | region | 204.8 km | — (canonical) | whole body (capped-tile mosaic) | 8.3M | 1,827 ms MEASURED |
| 1 | district | 2,048 m | ÷100 | 7,864 × 4,424 km | 8.3M | 1,827 ms MEASURED |
| 2 | quarter | 512 m | ÷4 | 1,966 × 1,106 km | 8.3M | ~1,827 ms same-band (T-1154) |
| 3 | block | 128 m | ÷4 | 491 × 276 km | 8.3M | ~1,827 ms MEASURED (T-1154) |
| 4 | chunk | 64 m | ÷2 | 246 × 138 km | 8.3M | UNMEASURED — never benched; cutoff-mechanism reasoning strongly implies same-band, but Dudley refuses to report a number he didn't run |
| 5 | voxel | 1 m | ÷64 | 216 × 384 m (display-ratio) | 83K | 17 ms MEASURED (③) |
My concern with A, now confirmed by cost: chunk (64 m) is the one rung nobody measured, and it's D-243's stream/derive unit, not a natural display rung — its ÷2 factor is a barely-perceptible zoom notch that adds a fetch and an asterisk for no visual gain.
Option B — skip-chunk (5 steps) — the joint recommendation
| Step | Gridunit rung | Spacing | Factor | Viewport extent | Cells | Derive cost (parallel) |
|---|---|---|---|---|---|---|
| 0 | region | 204.8 km | — (canonical) | whole body | 8.3M | 1,827 ms MEASURED |
| 1 | district | 2,048 m | ÷100 | 7,864 × 4,424 km | 8.3M | 1,827 ms MEASURED |
| 2 | quarter | 512 m | ÷4 | 1,966 × 1,106 km | 8.3M | ~1,827 ms same-band |
| 3 | block | 128 m | ÷4 | 491 × 276 km | 8.3M | ~1,827 ms MEASURED |
| 4 (deepest) | voxel | 1 m | ÷128 | 216 × 384 m (display-ratio) | 83K | 17 ms MEASURED (③) |
Why B wins, and it's an evidence argument, not a taste one (Dudley + me converge here independently): every row is directly measured or same-band- confirmed — zero asterisks. That's a direct consequence of chunk never having been benched: B is the only one of the three skeletons that doesn't lean on the unmeasured rung. The one genuinely large factor (block→voxel ÷128) lands at the deepest step where between-step magnification matters least (max detail already; no finer step to under-serve). The ÷100 Region→District factor at 0→1 is the one that maps onto a real seam — see the factor note below.
Option C — coarse-doubled (4 steps, skip District too)
| Step | Gridunit rung | Spacing | Factor | Viewport extent | Cells | Derive cost |
|---|---|---|---|---|---|---|
| 0 | region | 204.8 km | — (canonical) | whole body | 8.3M | 1,827 ms MEASURED |
| 1 | quarter | 512 m | ÷400 | 1,966 × 1,106 km | 8.3M | ~1,827 ms same-band |
| 2 | block | 128 m | ÷4 | 491 × 276 km | 8.3M | ~1,827 ms MEASURED |
| 3 (deepest) | voxel | 1 m | ÷128 | 216 × 384 m (display-ratio) | 83K | 17 ms MEASURED |
Why I list but don't recommend C: it costs identically to B row-for-row (same rungs, same measured rates — District's absence is not a cost saving, it's purely a pacing choice, Dudley confirms). Its distinguishing feature is the ÷400 Region→Quarter jump at 0→1 — a brutal between-step magnification interval (the held Region canvas magnified ~400× to approximate a Quarter view before the fetch lands is the D-166-corollary artifact at its worst). Only viable if fetch latency makes that magnified hold imperceptible — and since costs don't separate B from C at all, this is a pure UX-pacing call for Jeroen, not a cost tradeoff.
The factor-unevenness note (Dudley's serving answer, folded in)
The rung-identity correction makes the serving-seam story cleaner, not messier — the architectural boundary now lines up with a genuine rung boundary instead of being buried inside a metre factor. The two seams that matter are now distinct:
- The variable→fixed / global→sub-global seam is rung 0→1 (Global→Region). This is the one real serving-side boundary: Global (rung 0) is variable-extent and always-kept; Region (rung 1) is the first fixed, viewport-sized, evictable rung. The cache-tier split (keep-always vs. storage-evictable, Dudley's §(d)) falls exactly on this seam — cleaner than the old framing, which had the cache boundary and the ÷100 metre factor collapsed onto one "step 0→1" edge.
- The metre factors (÷100, ÷4, ÷4, ÷2) are all within the sub-global fixed ladder (Region→District ÷100, then ÷4/÷4/÷2). None crosses a serving seam — Region, District, Quarter, Block, chunk are all sub-global geometry, same eviction policy, same derive path, same flat per-cell cost. The ÷100 Region→District jump is the largest metre factor but it is pure UX pacing now that it no longer coincides with the cache boundary (which moved up to rung 0→1). Option D's gentle bottom factors (largest sub-global jump ÷4, deepest transition a barely-perceptible ÷2) are strictly better for the between-step magnification red flag than any prior option.
Recommendation — Option D (adopted)
The Option D table at the top of §(c) is the adopted ladder: six levels (Global opener + 5 fixed rungs: Region→District→Quarter→Block→Chunk), every fixed rung measured, no unmeasured rung, no deepest-step canvas-sizing special case, and the gentlest factor profile of any candidate. It inherits everything the old Option B earned (measured-not-inferred rows) and removes Option B's one remaining awkwardness (the voxel deepest-step special case) for free, as a consequence of Jeroen's own tile-drop ruling. (The old A/B/C ranking below is superseded — Option D is what the chunk-deepest ruling produces, and it dominates all three.) The one call left for Jeroen is confirming the six-level shape (Global opener + 5 fixed rungs) — Option D is Dudley's and my joint recommendation, no B-vs-C fork survives the tile drop.
(d) DEPRECATION-SWEEP DRAFT (Expected Output 2)
Every DQR record and ticket that conflicts with the decided setup, each with a disposition one-liner — ready for the Clerk consistency audit at wrap-up. The audit's job is to catch conflicts this list didn't name; this list is the known-conflicts starting set (the governance delta's named items + the round-1 ticket reconciliations the brief called out).
DQR records — amend / supersede
| Record | Disposition |
|---|---|
| D-166 corollary (2026-07-21) | AMEND — repoint the "continuous field, not fixed display rasters" sentence to per-step (§(a.1)); it now owns between-step magnification as a bounded exception. Not deleted. |
| D-226 T-1124 §2 windowed-family ceiling | AMEND — re-scope "exactly one windowed field" to the legacy district_window carrier only; the tagged step-canvas envelope is a new carrier outside the rule (§(a.5)). Purpose preserved, mechanism narrowed. (Re-scope is final — Dudley ruled district_window survives, envelope carries only new traffic, §(b); the SUPERSEDE branch does not fire.) |
| D-226 T-1143 ruling 2 ("no forced tagged-envelope migration") | SUPERSEDE — migration now triggered (§(a.2), §(a.5)). |
| D-226 T-1143 ruling 3 (continuous cursor-anchored zoom) | SUPERSEDE for transport (stepped); cursor-centering/edge-scroll/full-reset survive (§(a.2)). |
D-226 T-1143 §6 select_rung / MAX_COVERAGE_M coverage-walk model |
SUPERSEDE — replaced by the discrete step index (§(a.3)). |
| D-226 T-1143 ruling 1 (item-(d) floor opened "toward block/tile") | AMEND / NARROW (interview 2, §(a.8b)) — the opening now lands at chunk (64 m); tile/voxel (1 m) re-closes for the Atlas (Phase-5 in-world content). A deliberate scoping of the BHAG, not a reversal. |
| D-243 item (5) vocabulary | AMEND (additive) — add gridunit as a role name for a rung; add the display-ratio-vs-spacing distinction; the Atlas ladder bottoms at chunk (64 m), tile/voxel not an Atlas rung (§(a.4), interview 2). No D-243 rung definitions change — the metre ladder is intact; only which rungs the Atlas uses is narrowed. |
| D-225 (2026-06-12 tagged-envelope-deferral constraint) | SATISFY (note, not supersede) — the deferred constraint is now executed by this workshop's envelope; annotate D-225 that its "next inbound message type must be a tagged envelope" constraint is discharged here (§(a.5)). |
| D-226 item (d) whole-body prohibition | AMEND (Troblum S3 + interview 2) — state the prohibition as a per-request / per-derivation constraint, not aggregate-storage; add the per-body deep-rung client-cache retention cap (§(a.8)); and record the floor's partial-restore at chunk (§(a.8b) — the accumulation case is now chunk/block spacing, tile/voxel Atlas-invisible again). The prohibition's substance survives; this hardens it and re-narrows its floor. |
| D-227 (derive-don't-store) | AMEND (additive) — (1) the map-time TTL-split + staleness-vs-storage eviction-axes distinction (§(a.6)); (2) the persistent-cache schema/version-tag requirement (§(a.9), Troblum S5); (3) the seed-chaining "cache-accelerated pure function" model (§(a.10), interview 2) — a finer step may read a resident coarser canvas as an optimization with derive-fresh fallback, staying inside derive-don't-store because the coarser value is itself re-derivable to identical bytes (optimization, not semantic dependency); (4) the lake sourcing fix (§(a.11)) — MorphologyZone::Lake sourced from HydrologyResult's continuous filled_scaled (mechanism B), a derive-pipeline data-source change, not a D-239 vocabulary change (the frozen 17-zone set is reused verbatim — see the D-239 note below). All four are additive; derive-don't-store's core is unchanged and, for (3), reinforced (the byte-identical-paths determinism test is D-227's own eviction-validity property applied to a fast path). |
| D-192 (no client/server version handshake) | CROSS-REF note (Troblum S5) — annotate that the co-ship "always in sync" guarantee does not extend to the persistent disk cache; the schema/version tag (§(a.9)) is where that boundary is handled. Not a change to D-192's live-wire reasoning, which stands. |
| river-courses-t1170.md carrier rule (Ruling 1c) | AMEND (note) — terminology repoint ("windowed payload" → step-canvas envelope) + add cliffs as rule (iii)'s second vector member (§(a.7)). Substance unchanged. |
Records confirmed SURVIVING UNTOUCHED (state explicitly so the Clerk audit
doesn't over-rewrite): D-010 (four principles — the server relocation
reinforces principle 4); D-166 cascade + phase gating (still Phase-4 Atlas);
D-169/D-170 (implant UI — the map component still lives in the implant Atlas
app, occludes gameplay via HudGroups); D-223 (atlas_city_names — Araminta's
settlement-name lookup rides it unchanged); D-239 (the 17-zone morphology +
vegetation/glaciation vocabulary — frozen across every step per Araminta's
one-colorizer-family ruling; the §(a.11) lake fix explicitly does NOT touch it
— it reuses the existing MorphologyZone::Lake discriminant, changing only its
data source, and the endorheic cue rides courses precisely to avoid an 18th
zone). (D-226 item (d) moved out of this list — it is
now AMENDED per Troblum S3, above.)
Tickets — cancel / re-scope / repurpose
| Ticket | Current status | Disposition |
|---|---|---|
| T-1176 (design discussion: revise the Atlas map render mechanism) | in_progress | CLOSE as delivered — this workshop is its output; the render-architecture D-record + amendments are the deliverable. Mark done at filing, referencing the new D-record. |
T-1158 (decompose atlas_window_viewer.gd — canonical-frame + rung-reselection cluster) |
backlog | CANCEL with supersession note (Stig's round-1 call, confirmed): the canonical-frame state machine T-1158 wanted to extract is exactly what changes shape under stepped zoom (no continuous zoom floor, no _canonical_fit_zoom()); extracting code about to be deleted is waste. The new component's three-piece decomposition (input/pan, step-cross orchestration, two draw layers) is decided fresh in the implementation ticket, not by reviving T-1158. Note: "superseded by body-map-viewer render architecture (D-NNN); decomposition folded into the new component's implementation." |
| T-1175 (Atlas map-reading polish — river/nature presentation, single large pass) | backlog | RE-SCOPE + note the styling-engine dependency: T-1175's per-vertex river tapering/width-grammar work lands on the screen-space annotation layer (§ Stig round-1) via a Polygon2D-strip mechanism (draw_polyline can't taper). The c1 blocker is now cleared — measurement ⑥ landed (Stig: Image.set_pixel 77.5 ns/cell flat) and the c1 call resolved CPU-first (terrain raster colorized CPU-side; shaders deferred, not a ladder precondition). T-1175's tapering is a screen-space-annotation-layer concern independent of the terrain c1 call, so it depends only on (a) the new annotation layer landing — the ⑥-gated dependency is discharged. Not cancelled; re-homed onto the new component, unblocked. |
| T-1157 (redesign atlas visual-capture goldens for the zoom ladder) | backlog | RE-SCOPE as the new mechanism's verification story: the dead-goldens problem T-1157 targets is a direct consequence of the AtlasViewer/orbital-mosaic split that the stepped model collapses (global zoom = step 0, not a separate code path — Stig round-1). Re-scope to "capture harness for the stepped render architecture" — goldens key on (body, step) canvases, not the retired continuous-zoom frames. Keep, don't cancel: the capture harness is more needed than ever (it's the eyeball-check substrate for every step canvas). |
| T-1174 (batch vs window derive paths sample different world positions for the same DistrictPos) | backlog | KEEP, unchanged in intent — this is a derivation-correctness bug (two derive paths disagreeing on the same position) that is orthogonal to the render pivot and survives it: the tagged envelope still needs batch and window derive to agree cell-for-cell (it's the same derive_at_metres correctness both carriers depend on). If anything the stepped model raises its priority (more derive paths sharing the same position math). No supersession; note only that it now blocks the step-canvas serving path too. |
| T-1153 (continuous cursor-anchored zoom ladder in the client) | done | Its shipped CODE is superseded (the continuous zoom transport, _view_zoom float, progressive cross-rung refinement machinery) — the ticket stays done (it delivered what it was scoped for), but its code is on the _canvas.scale retirement path (below). No ticket action; flag its shipped surfaces in the retirement-path note so the implementation ticket knows what it's replacing. |
| T-1152 (derived planetary rung — progressive capped-density tiling; AtlasViewer heightmap texture retires) | done | Its compute_tile_grid() whole-body Region-tile mosaic is superseded by the rung-0 Global canvas (the body-surface region grid, one gridunit per region — the map opener; there is no beyond-Region mosaic, and Region itself is now rung 1, a viewport-sized fixed rung, not the top). Ticket stays done; its mosaic code is on the retirement path. The heightmap-texture retirement it did land (the reliefmap.png display path) stays retired — that survives the pivot (heightmaps were already demoted to derivation input by the D-166 corollary). |
| T-1153/T-1152 test suites | — | The zoom-ladder goldens and rung-selection tests those two stories shipped are retired with their code (they test continuous zoom + coverage-walk selection + the Region-tile mosaic — all superseded). T-1157's re-scoped capture harness (above) is their replacement. Concretely: the select_rung/coverage-walk unit tests, the continuous-zoom seam tests, and the compute_tile_grid mosaic tests are deleted in the same change that deletes the code they cover; new step-index + step-canvas tests land under the re-scoped T-1157. Do NOT leave the old goldens asserting against retired frames (the T-1157 dead-goldens problem, repeated). |
| NEW — lake morphology sourcing (§(a.11) converged core) | new | CREATE — source the existing MorphologyZone::Lake emission from HydrologyResult's continuous filled_scaled field (bilinear per-rung sampling, seed-chaining mechanism B), replacing the ocean_fraction_q >= 60 heightmap heuristic as the authoritative Lake trigger with heuristic fallback. Self-contained; no wire change, no vocabulary change. Blocks nothing; consumes T-1177's HydrologyResult (currently prototype-only). |
| NEW — hydrology basin-outlet → D8 wiring (§(a.11) endorheic follow-up) | new | CREATE — thread a HydrologyResult overflow basin's resolved outlet_path/spill point into RiverNetwork/courses as a D8 downstream continuation (so an overflow lake's outlet edge appears in courses, an endorheic basin's absence reads as "no course"). Pre-cleared additive by T-1170 Ruling 7b (reserved TERMINAL sentinel; river_course::build_edges already no-op-safe on TERMINAL) — not a wire migration. This is the deliverable the endorheic-vs-overflow distinction ships on: the cue is outflow-course presence (§(a.11) FINAL — no bit, no zone), so until this ticket lands the map shows lakes but not the drains-vs-closed distinction. Required regardless (overflow lakes must show exit rivers to be hydrologically honest); the endorheic cue is a side effect of that work. |
The _canvas.scale retirement path (explicit, for the implementation ticket)
Retired in the same change that lands the new two-layer component (Stig round-1 §1; sequenced so close inspection is never stranded, the T-1138 discipline):
_canvas.scale/_canvas.positiontransform model +_apply_transform()(continuous scale) — replaced by the step-canvas anchor (a fixed per-step texture draw, not a continuous scale node)._zs()/_zs_stroke()/_zs_ring_radius()compensation family inatlas_window_geometry_nature.gd— deleted wholesale; the unscaled screen-space annotation layer makes them structurally impossible to need.select_rung()+MAX_COVERAGE_M+compute_tile_grid()(T-1152/T-1153 code) — replaced by the step index.- The
AtlasViewer/orbital-mosaic-vs-window two-code-path split — collapses to "the Global opener is rung 0" (one viewer, one path; global zoom is the rung-0 body-surface canvas, not a separate code path). _view_zoomfloat +_canonical_fit_zoom()continuous fit — replaced by the discrete rung index + the rung-0 (Global) canonical frame.
Surviving client surfaces (Stig round-1, not on the retirement path):
_filter_for_granularity_v2() (NEAREST/LINEAR per rung still a real RTT
draw-time question), atlas_window_tile_set.gd's LRU shape (right skeleton
for the new client cache, plus the two-tier eviction), and the
compositing/legend/overlay-bar chrome (call-site updates only, no structural
rewrite).
Summary — 100% COMPLETE, Clerk-audit-ready
All governance calls are decided and Jeroen-ratifiable, and every cross-agent
input is folded in — Dudley's interview-2 response (chunk-64 m display band +
Option D + seed-chaining confirm + S2/S4) and his corrected global-tier byte
number (~8.85 MB PNG all-bodies), Jeroen's Global/Region rung-identity
correction (below), on top of round 2's Dudley/Araminta/Stig/Troblum inputs.
No [DUDLEY] brackets and no held clauses remain. §(a.11) (lakes) is
FINAL — both parts converged on both sides: (1) the core — lakes reuse the
existing MorphologyZone::Lake (no new field/zone, a data-source fix) sourced
from HydrologyResult's continuous filled_scaled field sampled bilinearly per
rung (lake edges refine with zoom, not blocky-magnified — seed-chaining
mechanism B); and (2) the endorheic-vs-overflow cue = outflow-course
presence (Dudley picked Araminta's (i); no wire bit, no 18th zone). Rationale
recorded: proportionality (4.63% endorheic doesn't justify permanently widening
the D-239-frozen vocabulary), the outlet-wiring is required regardless (overflow
lakes must show exit rivers to be honest — the cue is a side effect), and the
inference is definitionally sound with no misfire (every Overflow basin has a
non-empty outlet_path, every Endorheic none). Honest sequencing stated: until
the outlet-wiring ticket ships, the map shows lakes but not the drains-vs-closed
distinction. The stale "4-state water field" crossing is documented (superseded
by Araminta's withdrawal, Dudley's doc marked SUPERSEDED-BY-CROSSING) — never
adopted.
Jeroen's rung-identity correction (post-briefing-back) — folded in throughout. Round 2 conflated the map opener's spacing with its rung identity: it called Region "step 0 / the canonical tier." Corrected to six levels: rung 0 = Global (the body-surface map opener — variable extent, one gridunit per region, the D-243 elastic seam made visible; this is the canonical always-kept tier), rung 1 = Region (the largest fixed-size rung, viewport-sized and evictable like every rung below it), then District (2), Quarter (3), Block (4), Chunk (5). Corrected everywhere: §(a.0) ladder/canvas/ cache bullets, §(a.1)/§(a.2) full-zoom-out reset (→ Global frame), §(a.4) gridunit entry (Global is the one variable-extent level, fixed rungs snap to metres), §(a.6) keep-always tier (→ rung 0, not Region), §(a.8) retention floor (→ rung 0), §(b) envelope carriers (both Global and Region ride it), §(c) Option D table + snap constraints + factor note, and the T-1152 disposition. The correction makes the serving-seam story cleaner: the global/sub-global cache boundary now falls on a real rung edge (rung 0→1, the variable→fixed seam) instead of being buried in the ÷100 Region→District metre factor. Byte-math consequence (Dudley, measured): the always-kept global tier is the tiny variable region-grid canvas — ~8.85 MB PNG-encoded across all ~267 bodies (27.61 MB raw; avg ~18K cells/body), not a fixed 4K-class canvas. This supersedes the ~174 MB figure (~440× too many cells) and makes the tier trivially process-resident, not merely disk-safe — "always keep global" gets easier under the correction. Sub-global (Tier 2) is unchanged: disk + storage-eviction.
Interview-2 reworks are folded in (two changes, two ratifications):
- RATIFIED as-is: the ceiling re-scope (§(a.5)/§(b), files as drafted) and everything in the package not touched by the two reworks below.
- REWORK 1 — ladder bottom → chunk (64 m), Option D delivered: tile/voxel
dropped (Jeroen: "the actual tile level rung seems unusable, maybe replace
with 64"). New amendment §(a.8b) records this as a deliberate interview-2
narrowing of his interview-1 floor opening — used to chunk, tile/voxel
re-closes for the Atlas (Phase-5 in-world content). Updated consistently
across §(a.0), §(a.4) (the "10 px per tile" bottom-out superseded by "1 px
per 64 m gridunit, no magnification margin" — Dudley's chunk bench), §(a.1),
§(a.8), and §(c). Option D is the adopted ladder (six levels: Global opener
- 5 fixed rungs Region→District→Quarter→Block→Chunk; every fixed rung measured — chunk deepest = 245.8×138.2 km / ~1.7 s parallel). Its bonus: the deepest-step canvas-sizing special case is gone — chunk uses the plain fixed-3840×2160 budget like every fixed rung (a free simplification), and its factor profile (÷100/÷4/÷4/÷2, all within the sub-global fixed ladder) is the gentlest of any candidate, strictly best for the between-step magnification flag.
- REWORK 2 — seed-chaining → "cache-accelerated pure function": Jeroen
ruled he meant consuming the coarser output, not independent re-derivation.
New amendment §(a.10) reconciles this with D-227 without weakening it: the
definition stays pure (
derive(seed, position)), the implementation may read a resident coarser canvas as an optimization with derive-fresh fallback, and it stays inside derive-don't-store because the coarser value is itself re-derivable to identical bytes (optimization, not semantic dependency — proven by a mandatory byte-identical-paths determinism test). Dudley's §(b) independent-re-derivation ruling survives as the fallback path; the benched numbers survive as the cache-cold worst-case ceiling, which closes Troblum B2. Dudley-confirmed (dudley-interview2-response.md§2): the model is D-227-sound, no chain-reaction on eviction (each rung's fallback is self-contained), and his A/B mechanism distinction is folded into §(a.10) — "consuming coarser output" means reading the coarser continuous primitive baseline (mechanism B, the shipped district-reads-region pattern) as input to a fresh classification, not reading the coarser resolved classification (mechanism A, ruled out — it would violate Araminta's categorical re-derivation rule). Acceleration magnitude is unquantified but not architecture-gating (a future impl-time measurement).
Final and record-ready (§a, §b, §c, §d) — 1 new-record draft (§(a.0)) + twelve
amendment texts (§(a.1)–§(a.11), including §(a.8b)): §(a.1) D-166 corollary;
§(a.2) T-1143 rulings 2/3 supersession; §(a.3) select_rung→step-index; §(a.4)
D-243 gridunit; §(a.5) D-226 §2 ceiling→envelope; §(a.6) D-227 TTL-split; §(a.7)
T-1170 carrier + cliff; §(a.8) D-226(d) per-request+cap; §(a.8b) D-226(d)
floor→chunk (interview 2); §(a.9) D-227/D-192 cache schema-tag; §(a.10)
seed-chaining (interview 2); §(a.11) lakes — FINAL (morphology-fold +
filled_scaled sourcing + endorheic cue via outflow-course presence, interview
2). §(a.7) cliff cost is survey-confirmed (0/267 carve).
§(c) carries the adopted Option D ladder (six levels: Global opener + 5 fixed
rungs, chunk-deepest, every fixed rung measured). Deprecation sweep: 12 DQR
dispositions (adds D-226 T-1143-ruling-1 narrow + the D-227 seed-chaining line)
- 10 ticket dispositions (adds the two lake tickets — morphology-sourcing +
basin-outlet D8 wiring) + the
_canvas.scaleretirement path. No[DUDLEY]brackets, no held clauses, no open items remain — the global-tier byte total is in (~8.85 MB PNG all-bodies, Dudley measured; supersedes the ~174 MB figure, tier now trivially process-resident) and §(a.11)'s endorheic cue is finalized (outflow-course presence). The package is 100% complete and Clerk-audit-ready.
For Jeroen's final ratification (governance calls, decided text ready):
(1) §(a.10) seed-chaining against his phrase "serves as seed information for
the deeper cascade" — the cache-accelerated-pure-function model (mechanism B) is
the reconciliation of his "consuming coarser output" intent with D-227;
(2) Option D's six-level shape (Global opener + Region→District→Quarter→Block
→Chunk) — the tile-drop removed the old B-vs-C fork, so this is a single confirm,
not a choice.
The migration is the one real chunk of new work; Dudley's code read puts it at
"doable" (one Inbound variant + one SimBridge method on a pattern proven five
times), with the "challenging" part in Stig's client rebuild.
Troblum's adversarial pass is now fully dispositioned: B1 (cliff survey)
resolved 0/267 → §(a.7) survey-confirmed; B2 (seed-chaining) resolved by §(a.10);
S2 (deep-step course density) run by Dudley — a real finding (+38%–87% cost
at chunk/block vs. District's <5%, traced to course point-count scaling inversely
with rung spacing; still affordable in absolute terms, flagged as an
implementation consideration — a possible rung-independent station-spacing cap —
for the ticket plan; the measurement is filed as the "S2 ADDENDUM" in
measurements/t1178-t1154-derive-bench.md, alongside the chunk-64 m
"INTERVIEW-2 ADDENDUM" — both already written by Dudley); S4 (sim-state phase
cadence) resolved by a Dudley+Araminta joint formula (SIM_STATE_TTL bound to
1× the field's own driving sim bucket — tidal-or-seasonal for flooded, seasonal
for glaciation; 1× confirmed cost-affordable). S1 (evict-then-revisit costing)
remains a Dudley cache-spec tuning number, not a governance-text change — my
§(a.6) TTL amendment already separates the two eviction axes it probes. S2's
finding may warrant a one-line note in the §(a.7)/render-record wire discussion
if course rendering at chunk needs the station-cap; flagging for the Clerk audit.
Full adversarial-pass disposition is visible for the audit.