docs(meta): D-258 — rung-0.5 expanded layer, one derived base for the ladder
Every Atlas rung currently re-derives from the heightmap independently. D-258 inserts one deterministic whole-body layer between the baked inputs and the ladder, and points every deeper rung at it instead of at the source files. Two failures forced it. The Global rung was deriving a five-class hue map while a per-body artefact labelled "clean color hypsometric render (display / Atlas)" sat unused beside it. And hydrology was not derivable at all: flow is a global solve, so no per-window derivation could produce a coherent water system — Region carried no courses and lakes could not fill. The record also fixes what the reliefmap IS. It is a plurality, not a classification: each cell names the biome dominating ~38 km, a vote already counted and discarded. So rung 0.5 un-summarises it rather than upscaling it, which binds three consequences — biome edges are gradients never lines (D-243's climate rule extended to biome), descending reveals composition rather than sharpness, and invented detail must downsample back to the summary it came from. That last one is the acceptance gate for any sub-biome algorithm. Rung 0.5 is a stored derived artefact and therefore a named carve-out from D-227's derive-don't-store. The boundary is principled: D-227 governs what is LOCALLY computable, where storage is pure cost. A whole-body flow solve is not locally computable by construction — that is why it must exist — so storage here buys correctness, not convenience. Everything below rung 0.5 stays derive-don't-store. Record precedes implementation; no code changes here. Complements the same session's D-255 extent inversion, which governs how a canvas is sized rather than what it is made of. Pair session with Jeroen, 2026-07-26. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -2329,4 +2329,32 @@ Technical foundation decisions that constrain implementation: engine, client-ser
|
||||
|
||||
---
|
||||
|
||||
*110 decisions (D-001 through D-256, excluding gaps). Last updated: 2026-07-24 (D-256 — canonical sampling convention: one absolute-metre derive core (`derive_at_metres` family), batch pseudo-grid re-scoped as `SurveyCellPos` survey raster (real newtype), thin-wrapper unification fixing the three-latitude inconsistency and the region-(0,0) climate collapse, exact-position feature judgments, step-canvas fencing; discharges the T-1174 blocker on D-255's T-1181 envelope).*
|
||||
### D-258: Rung-0.5 expanded layer — one derived base for the whole ladder
|
||||
|
||||
- **Date:** 2026-07-26
|
||||
- **Decision:** The Atlas cascade gains a single **expanded layer ("rung 0.5")**, generated once per body from the rung-0 input files, and every zoom tier below it derives from **that layer** rather than from the source files. This replaces the "each rung independently re-derives from the heightmap" model.
|
||||
- **Rung 0 is the baked input pair, never displayed.** `heightmap.png` (1024×512, 16-bit greyscale elevation — the canonical cascade input) and `reliefmap.png` (1024×512 colour, the **biome** input). Both are build-time artefacts of `import_heightmaps.py`. Neither is ever blitted to screen; D-255's "heightmap PNGs remain invisible derivation input" is extended to cover the reliefmap, which now carries **data**, not merely display.
|
||||
- **Rung 0.5 is a deterministic expansion of rung 0**, finer than the inputs, sized so a whole body can be drawn at **2 screen px per gridunit** on a large display. Same body, same seed → same layer, every time.
|
||||
- **Hydrology resolves on rung 0.5 and nowhere else.** Drainage, course routing and lake fill are whole-body computations: water arrives from upstream and leaves downstream, both off-screen at every rung below Global. No window is large enough to answer the question, so it is answered once, for the entire body, on this layer.
|
||||
- **Rung 0.5 is cached, and is the sole input to Region/District/Quarter/Block/Chunk.** No deeper rung reads the source files. Cross-rung agreement — the coastline zoomed out is the coastline zoomed in; the river crossing a district is the river reaching the sea on the global map — therefore holds **by construction** rather than by policing two derivation paths against each other.
|
||||
- **Global displays rung 0.5**: biomes as viewed from orbit, in simplified colour and texture in the game's own visual flavour — not a photograph, not a topographic diagram. Hypsometric shading is a *reading aid* within that image, not its subject. The subject is biome.
|
||||
|
||||
**The reliefmap is a plurality, not a classification.** Each reliefmap cell records the biome that **dominates** roughly 38 km of ground — a vote already counted and discarded, not a claim that the cell is uniform. Rung 0.5 therefore **un-summarises** the reliefmap; it does not upscale it. Three consequences bind:
|
||||
|
||||
1. **Biome edges are gradients, never lines.** Where biomes meet, the transition blends, so no boundary falls on a cell edge and the rung-0 grid is invisible in the output. This is the D-243 climate rule — *climate does not change on a line* — applied to biome.
|
||||
2. **Descending the ladder reveals composition, not sharpness.** A cell reading "forest" globally contains clearings, marsh, rock and scrub — biomes the vote suppressed. Those minorities emerge deterministically as the ladder descends. Detail is a distribution resolving into its parts, never the same picture at higher resolution.
|
||||
3. **Invented detail must be conservative — the binding invariant.** Downsampling rung 0.5 must reproduce the rung-0 summary it came from: a forest cell may gain marsh pockets, but it must still read as forest from orbit. Detail may add variety; it may never change the summary. This is the test that keeps (1) and (2) honest, and it is the acceptance gate for any sub-biome invention algorithm.
|
||||
|
||||
- **Rationale:** Two failures forced this, one visible and one structural. **Visible:** the Global rung derived a five-class hue map while a per-body artefact explicitly labelled *"clean color hypsometric render (display / Atlas)"* sat unused beside it — the Atlas was ignoring the picture built for it, and read as a data readout rather than a world. **Structural:** hydrology was not derivable at all under the old model. Courses were invented per canvas from a network, but *flow* — which way water runs, where it pools — is a global solve, so no per-window derivation could produce a coherent water system; Region carried no courses whatsoever and lakes could not fill. Deriving one whole-body layer first solves both, and converts cross-rung consistency from something enforced into something structural.
|
||||
|
||||
The plurality reading of the reliefmap is what prevents the obvious wrong implementation: treating it as ground truth and interpolating, which yields hard biome boundaries on a 38 km lattice — a visibly gridded world, precisely the artefact D-243's edge-fuzz rule exists to prevent one tier up. Conservation (3) prevents the opposite failure, where invention drifts far enough that zooming out no longer agrees with the map you zoomed in from.
|
||||
|
||||
**Relationship to [D-227](#d-227) (derive, don't store).** Rung 0.5 is a deliberately **stored** derived artefact, and a named carve-out from that rule rather than a violation of it. The boundary is principled: D-227 governs anything **locally** computable, where storage is pure cost because the value is recoverable from position and seed. A whole-body flow solve is not locally computable by construction — that is the entire reason it must exist — so it cannot be re-derived per window at any price. Storage here buys correctness, not convenience. Everything below rung 0.5 remains derive-don't-store.
|
||||
- **Raised by:** Jeroen, pair session 2026-07-26, after eyeballing the post-inversion Global rung and finding it "still off kilter". His framing throughout: rung 0.5 "is where the hydroflow takes place", its cached output "serves as input for the higher zoom tiers", and the reliefmap biome is "the largest player on the block". Principle restated and confirmed before this record was written.
|
||||
- **Implementation:** Not yet ticketed — this record precedes implementation. Consumers to re-point: `step_canvas.rs` (every rung sources rung 0.5 instead of resolving the heightmap), `heightmap.rs` (the rung-0 loader gains the reliefmap as a second input), and the client map-art function (biome-from-orbit palette at Global). Interacts with the same session's D-255 extent inversion (a rung sets extent; spacing falls out) — that change stands; this one governs what the canvas is *made of*, not how it is sized.
|
||||
- **Cross-reference:** [D-255](#d-255) (stepped Atlas ladder — this amends its per-rung derivation model, not its rung set or its texel-exactness), [D-243](#d-243) (scale ladder; the climate edge-fuzz rule this extends to biome), [D-227](#d-227) (derive-don't-store — named carve-out above), [D-256](#d-256) (one absolute-metre derive core, which rung 0.5 becomes the input to), [D-202](#d-202) (per-body elevation assets — `import_heightmaps.py` produces both rung-0 files), [D-166](content.md#d-166) (generation before player: a walkable world needs coherent water).
|
||||
- **Dissent:** None.
|
||||
|
||||
---
|
||||
|
||||
*112 decisions (D-001 through D-258, excluding gaps). Last updated: 2026-07-26 (D-258 — rung-0.5 expanded layer: one cached whole-body derivation from heightmap + reliefmap, hydrology resolved there and only there, every deeper rung sourced from it; the reliefmap read as a dominant-biome plurality, so descending reveals composition under a conservation invariant).*
|
||||
|
||||
Reference in New Issue
Block a user