T-1156 wave 1: the nature layer's hydrology arrives on the Atlas zoom ladder — rivers, drainage basins, and attractors drawn over the derived terrain, per-rung filtered. Wave 2 (everything civilizational) remains explicitly deferred per the nature-first order.
The design pass (before any code)
Tyre's carrier ruling reframed the ticket: the river skeleton already rides the wire — AtlasLayerResponse.layer1 has serialized RiverNetwork/drainage_basins/attractors whole-body since #952, and the retired draw code survives intact. So wave 1 is a re-hosting plus one additive field, touching neither D-226 ceiling (windowed family stays at one field; whole-body family untouched — layer1 predates that framing). Per-rung refinement is client-side class filtering — deliberately unlike T-1162's server-side cutoff, because a fixed finite graph has nothing to Nyquist-truncate. The ruling establishes the wave-2 pattern for free: discrete map features ride the whole-body overlay family filtered client-side; only continuous per-metre fields ride the windowed per-cell arrays. Captured as a D-226 note on this branch.
Design-pass honesty, ticketed not buried: T-1168 (riparian vegetation response — near_perennial_water is a hardcoded-false stub, so rivers draw over barren-painted banks for now, deliberately not suppressed per Araminta+Tyre), T-1169 (feature-name labels — three dormant pieces, not "cheap"), T-1170 (the skeleton is 512×256 heightmap-resolution, ~76 km/cell — river courses below Region scale need invention, the linear analog of the coast crinkle).
Server (Dudley) — river_class on RiverNetwork
river_class: Vec<u8> (0=stream 1=tributary 2=trunk) parallel to river_cells, #[serde(default)], computed at drainage-analysis time by log-scaled binning between RIVER_THRESHOLD and the river-restricted max accumulation. The restriction matters: grid-wide max includes below-sea-level ocean cells where accumulation peaks past the coastline — anchoring there starves the trunk class exactly on wet large-ocean bodies (caught in lead review of round 1; GJ1c went from zero trunk cells to a healthy 72/18/3 distribution). By construction every body with rivers has trunk cells, pinned by a non-synthetic regression on the committed GJ1c heightmap. cascade_layer1.json regenerated: every pre-existing field byte-identical (python-verified), only river_class added.
Client (Stig) — the nature overlay on the ladder
New AtlasWindowNatureOverlay node: self-connects to the shared atlas_layers_received broadcast (the established one-signal-N-consumers shape), consumes the whole-body skeleton, draws over the terrain composite. Pure tested coordinate chain layer1_pixel → world_m → district → canvas-local with the vertical convention verified against the server source (row 0 = north pole) and revert-verified pole tests.
Araminta's presentation ruling (supersedes the provisional add-as-you-descend mapping, on the resolution evidence): Region/orbital = full skeleton (radii 0.9/1.4/2.2 px by class, confluence 3.5, mouth double-ring), District = trunk-only at 60%/1.6 px with mouths kept at full landmark styling, Quarter = rivers off until T-1170 — isolated 76 km dots there are placement coincidence, not information. Retired palette reused verbatim. Toggles RVR on / BAS off / ATR off.
Live rounds (the eyeball check earning its keep again)
Zoom-scaled marker sizes: all marker radii were raw constants drawn inside the zoom-scaled canvas — sub-pixel-invisible at orbital fit zoom (~0.014 effective px), correctly-sized at District, which is exactly why one capture worked and the headline rung didn't. Diagnosed with live instrumentation (the tile-mode-rung suspect was ruled out with evidence but pinned with a named test anyway); fixed via pure zoom_compensated_size(); numeric pin of the pre-fix magnitude in the test suite.
Byte-identical basins captures: root cause was the lead's drive script passing a button label where the API takes an overlay id — no product bug, but the chase banked a real regression pin (draw-counting spy proving toggles redraw the nature overlay).
R1: full river skeleton threading Lendel's continents at the orbital rest state, mouth rings on the coasts. R2: 7 watershed boundaries at the ruling's barely-there alphas. D: trunk-dim + mouth carve-out at a District window. Q: rivers correctly absent at Quarter.
Test discipline
Server: drainage 16/16 (+10 incl. the non-synthetic GJ1c trunk guard), layer1/layer_proxy/body_world_state green, cargo build --tests clean, revert-verified binning monotonicity. Client: 58+ new tests across four files (pure mapping/policy, lifecycle, real-driver draw smoke — with the smoke suite's vacuous-pass mode under X11 BadMatch honestly documented and the pure-function suite installed as the real gate), 11 existing atlas suites regression-free, three independent revert-verifications. Known accepted lint: atlas_window_viewer.gd at 1016/1000 advisory lines on trivial wiring — rides T-1158's decomposition rather than degrading its postmortem comments.
## Summary
T-1156 wave 1: the nature layer's hydrology arrives on the Atlas zoom ladder — rivers, drainage basins, and attractors drawn over the derived terrain, per-rung filtered. Wave 2 (everything civilizational) remains explicitly deferred per the nature-first order.
### The design pass (before any code)
Tyre's carrier ruling reframed the ticket: the river skeleton **already rides the wire** — `AtlasLayerResponse.layer1` has serialized `RiverNetwork`/`drainage_basins`/`attractors` whole-body since #952, and the retired draw code survives intact. So wave 1 is a *re-hosting* plus one additive field, touching **neither** D-226 ceiling (windowed family stays at one field; whole-body family untouched — `layer1` predates that framing). Per-rung refinement is **client-side class filtering** — deliberately unlike T-1162's server-side cutoff, because a fixed finite graph has nothing to Nyquist-truncate. The ruling establishes the wave-2 pattern for free: *discrete map features ride the whole-body overlay family filtered client-side; only continuous per-metre fields ride the windowed per-cell arrays.* Captured as a D-226 note on this branch.
Design-pass honesty, ticketed not buried: **T-1168** (riparian vegetation response — `near_perennial_water` is a hardcoded-false stub, so rivers draw over barren-painted banks for now, deliberately not suppressed per Araminta+Tyre), **T-1169** (feature-name labels — three dormant pieces, not "cheap"), **T-1170** (the skeleton is 512×256 heightmap-resolution, ~76 km/cell — river *courses* below Region scale need invention, the linear analog of the coast crinkle).
### Server (Dudley) — `river_class` on `RiverNetwork`
`river_class: Vec<u8>` (0=stream 1=tributary 2=trunk) parallel to `river_cells`, `#[serde(default)]`, computed at drainage-analysis time by log-scaled binning between `RIVER_THRESHOLD` and the **river-restricted** max accumulation. The restriction matters: grid-wide max includes below-sea-level ocean cells where accumulation peaks past the coastline — anchoring there starves the trunk class exactly on wet large-ocean bodies (caught in lead review of round 1; GJ1c went from zero trunk cells to a healthy 72/18/3 distribution). By construction every body with rivers has trunk cells, pinned by a non-synthetic regression on the committed GJ1c heightmap. `cascade_layer1.json` regenerated: every pre-existing field byte-identical (python-verified), only `river_class` added.
### Client (Stig) — the nature overlay on the ladder
New `AtlasWindowNatureOverlay` node: self-connects to the shared `atlas_layers_received` broadcast (the established one-signal-N-consumers shape), consumes the whole-body skeleton, draws over the terrain composite. Pure tested coordinate chain `layer1_pixel → world_m → district → canvas-local` with the vertical convention **verified against the server source** (row 0 = north pole) and revert-verified pole tests.
**Araminta's presentation ruling** (supersedes the provisional add-as-you-descend mapping, on the resolution evidence): Region/orbital = full skeleton (radii 0.9/1.4/2.2 px by class, confluence 3.5, mouth double-ring), District = trunk-only at 60%/1.6 px with mouths kept at full landmark styling, **Quarter = rivers off** until T-1170 — isolated 76 km dots there are placement coincidence, not information. Retired palette reused verbatim. Toggles RVR on / BAS off / ATR off.
### Live rounds (the eyeball check earning its keep again)
1. **Zoom-scaled marker sizes**: all marker radii were raw constants drawn inside the zoom-scaled canvas — sub-pixel-invisible at orbital fit zoom (~0.014 effective px), correctly-sized at District, which is exactly why one capture worked and the headline rung didn't. Diagnosed with live instrumentation (the tile-mode-rung suspect was ruled out with evidence but pinned with a named test anyway); fixed via pure `zoom_compensated_size()`; numeric pin of the pre-fix magnitude in the test suite.
2. **Byte-identical basins captures**: root cause was the *lead's drive script* passing a button label where the API takes an overlay id — no product bug, but the chase banked a real regression pin (draw-counting spy proving toggles redraw the nature overlay).
### Acceptance captures (`.cache/screenshots/rivers-eyeball/`)
R1: full river skeleton threading Lendel's continents at the orbital rest state, mouth rings on the coasts. R2: 7 watershed boundaries at the ruling's barely-there alphas. D: trunk-dim + mouth carve-out at a District window. Q: rivers correctly absent at Quarter.
### Test discipline
Server: drainage 16/16 (+10 incl. the non-synthetic GJ1c trunk guard), layer1/layer_proxy/body_world_state green, `cargo build --tests` clean, revert-verified binning monotonicity. Client: 58+ new tests across four files (pure mapping/policy, lifecycle, real-driver draw smoke — with the smoke suite's vacuous-pass mode under X11 BadMatch honestly documented and the pure-function suite installed as the real gate), 11 existing atlas suites regression-free, three independent revert-verifications. Known accepted lint: `atlas_window_viewer.gd` at 1016/1000 advisory lines on trivial wiring — rides T-1158's decomposition rather than degrading its postmortem comments.
Tickets: T-1156 (wave 1). Filed from design pass: T-1168, T-1169, T-1170.
Rivers/basins/attractors ride the existing whole-body layer1 field —
neither AtlasLayerResponse ceiling touched, no tagged-envelope
migration. Per-rung refinement is client-side class filtering on the
additive river_class (distinct from T-1162's server-side Nyquist
cutoff: a fixed finite graph has nothing to truncate). General rule:
discrete map features ride the whole-body overlay family filtered
client-side; continuous per-metre fields ride the windowed per-cell
arrays — wave 2's roads/settlements inherit this unchanged. Riparian
vegetation response is the named T-1168 forward contract, deferred.
Tickets: T-1156
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The one additive server change of wave 1 per Tyre's carrier ruling:
river_class: Vec<u8> parallel to river_cells, serde-default-safe, no
new wire field. Log-scaled binning between RIVER_THRESHOLD and the
RIVER-RESTRICTED max accumulation (max over cells passing the is_river
elevation filter — NOT the grid-wide max, which peaks past the
coastline on wet large-ocean bodies and would starve the trunk class
exactly where Araminta's District-shows-trunk-only table needs it;
caught in lead review of round 1, fixed round 2). Log not linear
because accumulation grows combinatorially downstream. By construction
every body with rivers has trunk cells — pinned by a non-synthetic
regression on the committed GJ1c heightmap at the golden's exact
downsample. cascade_layer1.json regenerated: every pre-existing field
byte-identical (python-verified), only the new river_class arrays
added — GJ1c distribution stream 72 / tributary 18 / trunk 3.
drainage 16/16 (+10), layer1 3/3, layer_proxy 50/50, build --tests
clean; revert-verified (non-monotonic binning fails the monotonicity
test by name).
Tickets: T-1156
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
New AtlasWindowNatureOverlay (Node2D on the viewer canvas, above
terrain): self-connects to the shared atlas_layers_received broadcast
(the established one-signal-N-consumers shape) and consumes the whole-
body layer1 skeleton per Tyre's carrier ruling — no windowed wire
touched. Coordinate chain layer1_pixel_to_world_m -> world_m_to_
district -> canvas-local lives in atlas_window_geometry as pure tested
functions; vertical convention (row 0 = North pole, wy increases
south) verified against the server's own pixel_to_world_m, pinned by
pole tests and revert-verified (sign flip fails them by name).
Araminta's per-rung presentation table implemented exactly: Region
full skeleton (radii 0.9/1.4/2.2, confluence 3.5, mouth double-ring),
District trunk-only 1.6px at 60% with mouths at full landmark styling,
Quarter off until T-1170 course invention; retired palette reused
verbatim; RVR on / BAS off / ATR off defaults; missing river_class
falls back to trunk. 58 new tests (34 geometry, 22 lifecycle, 2 real-
driver draw smoke actually rendered); 11 existing atlas suites
regression-free. atlas_window_viewer.gd runs 16 lines past the
advisory 1000-line cap on trivial wiring — accepted, rides T-1158's
decomposition.
Tickets: T-1156
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Live round 2 (the real bug): every nature-overlay marker size was a raw
screen-space constant drawn inside _canvas, whose scale IS view_zoom —
at Lendel's orbital fit zoom (0.0063) a 2.2px trunk dot rendered at
~0.014px, invisible; the same code at District's 3.75 zoom produced the
correctly-visible mouth ring, which is why one capture worked and the
headline rung didn't. Fixed via AtlasWindowGeometry.zoom_compensated_
size() (pure, floor-guarded) wired through every radius/line-width;
basin FILL points are positions and correctly stay unscaled. Suspect
tile-mode-rung-detection was ruled out live (granularity_v2=Region
confirmed in tile mode) but pinned with a named regression test anyway.
+8 pure-function tests incl. a numeric pin of the pre-fix magnitude
(<0.02px at orbital zoom); revert-verified by name. Draw-smoke suite
documented as supplementary (the shared SubViewport background harness
can pass vacuously under X11 BadMatch — the pure suite is the gate).
Live round 3 (drive-script bug, no product change): the lead's scratch
drive passed the button LABEL to set_overlay_visible() and the unknown-
id guard silently no-op'd — but the chase banked a real pin:
test_set_overlay_visible_gen_basins_flips_gate_and_redraws_nature_
overlay (draw-counting spy per the cold-start precedent; is_queued_for_
redraw does not exist in this build). Revert-verified.
Basins verified live: 7 Lendel watershed boundaries render at the
ruling's alphas. Suites: viewer 76/76, geometry-nature 42/42, nature-
overlay 22/22, zoom-ladder 50/50, no regressions across the cluster.
Tickets: T-1156
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
At 1.6px/60% the trunk dot under the mouth ring read as 'mouth glyph
over plain terrain' — invisible without knowing where to look,
underselling the ruling's own 'a major river crosses near here'
intent. 2.0px/80% preserves the fade-down ladder vs Region's
2.2px/100% without reading as accidentally-erased. Doc comment
records the revision provenance.
Tickets: T-1156
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
I1: _draw_attractor_shape's three stroke-width args (Confluence arc,
Coastal/NaturalHarbor arc, Oasis spokes) were raw screen-space literals
— Godot multiplies stroke widths by canvas scale exactly like radii, so
at the Region orbital fit zoom the outlines rasterized at ~0.01px, the
identical sub-pixel class the dot/ring compensation fixed, missed on
glyph internals (and attractors are Region-only — precisely where it
bites). Widths now arrive pre-compensated via a px_w param, keeping the
primitive pure. Regression pin: a source-scan test asserting no
draw_arc/draw_line in the function carries a bare numeric width (the
draw-smoke suite documents its own vacuous-pass mode, so source-scan is
the environment-independent gate); revert-verified by name. I2: D-226
visibility-direction sentence — Araminta's fade-down inversion recorded
as pre-T-1170 with its single revisit point named. I3: class-header
call-site claim corrected (enter() funnels through _enter_at_rung).
Tickets: T-1156
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
RVR-on-by-default is the single most player-visible behavior wave 1
ships (rivers appear with no toggle hunt) and was only exercised by
live captures; gen_basins' default was pinned incidentally inside the
toggle-redraw spy test and gen_attractors not at all. One named test
now asserts all three fresh-construction defaults per Araminta's
ruling (RVR on, BAS off, ATR off). Revert-verified: flipping the
gen_rivers init line fails exactly this test by name (1 failure total
in the 78-test suite). Suite 78/78; gdlint clean.
Tickets: T-1156
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Review: rivers-ladder → main (type: code + visual sign-off)
Branch tip reviewed: c1cae7c9b (both fix rounds included). Reviewers: Tyre (architecture — reviewing the implementation of his own wave-1 carrier ruling), Hoshe (QA), Araminta (presentation sign-off on her own per-rung ruling).
Tyre (Architecture): APPROVE (after one fix round)
Initial REQUEST_CHANGES with one code find and two captures:
#
Finding
Resolution
I1
_draw_attractor_shape's three stroke-width args were raw literals — Godot multiplies widths by canvas scale like radii, so glyph outlines rasterized at ~0.01 px at the Region orbital fit zoom (the identical sub-pixel class the live-round dot/ring fix closed, missed on glyph internals — and attractors are Region-only, precisely where it bites)
8a747e332 — widths arrive pre-compensated via a px_w param (primitive stays pure); source-scan regression pin asserting no bare numeric width in the function (the environment-independent gate, since the smoke suite documents its own vacuous-pass mode); revert-verified by name
I2
Araminta's fade-down visibility inversion superseded the provisional add-as-you-descend mapping but lived only in code comments
D-226 visibility-direction sentence: fade-down, explicitly pre-T-1170, RIVER_CLASS_VISIBLE_BY_RUNG named as the single revisit point
I3
Class-header call-site claim (doc nit)
Corrected
His six architecture answers, in brief: the river-restricted anchor is ruled the correct model (not merely a bugfix — grid-wide max admits a ceiling no river cell can reach; per-basin anchoring recorded as a T-1170 forward option); the client-side const-table visibility is "the purest possible expression" of his carrier mechanism; the zero-ceilings claim confirmed definitively (empty diff on layer_proxy.rs — river_class nests inside the pre-existing whole-body layer1); the overlay's request-per-body-switch lifecycle is correct against D-227 "valid forever"; the D-226 note is faithful with no drift; and the divide-by-zoom compensation is defensible for wave 1 with an unscaled-sibling-layer refactor recorded for wave 2 (T-1158-adjacent, appended to T-1156).
Hoshe (QA): APPROVE (after one fix round)
Initial REQUEST_CHANGES on one gap: RVR-on-by-default — the single most player-visible behavior the feature ships — had no named regression assertion (gen_basins was pinned only incidentally; gen_attractors not at all). Fixed in c1cae7c9b: one named test pinning all three fresh-construction defaults, revert-verified to fail alone by name; Hoshe repeated the revert-verification independently. Full client gate re-run at the final tip: 3770/3770.
His verification was execution-grade throughout: own Python structural diff of the cascade golden (pure-append confirmed independently — only river_class added, 72/18/3 recomputed from the JSON); a forced clean rebuild proving no missed struct-literal site (the field is non-Option, so the compiler is the proof); his own sign-flip revert-test on the pole convention (exactly the two named tests fail); breaking the toggle-redraw wiring to confirm the spy test bites; and tracing cascade_golden.rs to confirm the GJ1c regression shares the golden's exact source and downsample. One tool incident self-caught and cleaned (a gdformat --check that mutates on this version; hand-restored byte-identical to HEAD).
Araminta (presentation sign-off): APPROVED, all four captures
R1 "delivers the read... dotted courses trace visibly across the continent"; R2's basin subtlety confirmed as designed ("tint, not paint" — do not strengthen); D initially objected — the District trunk dot at 1.6 px/60% read as accidentally-erased — fixed to her exact ask (2.0 px/80%, 0366e8286) and re-confirmed on a representative mid-latitude capture; Q's rivers-off validated in situ ("no false-precision artifact").
Live rounds during implementation (pre-review, for the record)
Two eyeball rounds preceded review: zoom-scaled marker sizes (sub-pixel-invisible at orbital fit zoom — diagnosed with live instrumentation, the wrong suspect ruled out with evidence and pinned anyway) and a byte-identical basins capture whose root cause was the lead's drive script passing a button label where the API takes an overlay id (no product bug; the chase still banked the toggle-redraw spy pin). One pole-adjacent entry wobble observed and filed as T-1171 rather than chased in-batch.
## Review: rivers-ladder → main (type: code + visual sign-off)
Branch tip reviewed: `c1cae7c9b` (both fix rounds included). Reviewers: Tyre (architecture — reviewing the implementation of his own wave-1 carrier ruling), Hoshe (QA), Araminta (presentation sign-off on her own per-rung ruling).
### Tyre (Architecture): APPROVE (after one fix round)
Initial REQUEST_CHANGES with one code find and two captures:
| # | Finding | Resolution |
|---|---------|------------|
| I1 | `_draw_attractor_shape`'s three stroke-width args were raw literals — Godot multiplies widths by canvas scale like radii, so glyph outlines rasterized at ~0.01 px at the Region orbital fit zoom (the identical sub-pixel class the live-round dot/ring fix closed, missed on glyph internals — and attractors are Region-only, precisely where it bites) | `8a747e332` — widths arrive pre-compensated via a `px_w` param (primitive stays pure); source-scan regression pin asserting no bare numeric width in the function (the environment-independent gate, since the smoke suite documents its own vacuous-pass mode); revert-verified by name |
| I2 | Araminta's fade-down visibility inversion superseded the provisional add-as-you-descend mapping but lived only in code comments | D-226 visibility-direction sentence: fade-down, explicitly pre-T-1170, `RIVER_CLASS_VISIBLE_BY_RUNG` named as the single revisit point |
| I3 | Class-header call-site claim (doc nit) | Corrected |
His six architecture answers, in brief: the **river-restricted anchor** is ruled the correct model (not merely a bugfix — grid-wide max admits a ceiling no river cell can reach; per-basin anchoring recorded as a T-1170 forward option); the client-side const-table visibility is "the purest possible expression" of his carrier mechanism; the **zero-ceilings claim confirmed definitively** (empty diff on `layer_proxy.rs` — `river_class` nests inside the pre-existing whole-body `layer1`); the overlay's request-per-body-switch lifecycle is correct against D-227 "valid forever"; the D-226 note is faithful with no drift; and the divide-by-zoom compensation is defensible for wave 1 with an **unscaled-sibling-layer refactor recorded for wave 2** (T-1158-adjacent, appended to T-1156).
### Hoshe (QA): APPROVE (after one fix round)
Initial REQUEST_CHANGES on one gap: RVR-on-by-default — the single most player-visible behavior the feature ships — had no named regression assertion (gen_basins was pinned only incidentally; gen_attractors not at all). Fixed in `c1cae7c9b`: one named test pinning all three fresh-construction defaults, revert-verified to fail alone by name; Hoshe repeated the revert-verification independently. Full client gate re-run at the final tip: 3770/3770.
His verification was execution-grade throughout: own Python structural diff of the cascade golden (pure-append confirmed independently — only `river_class` added, 72/18/3 recomputed from the JSON); a forced clean rebuild proving no missed struct-literal site (the field is non-`Option`, so the compiler is the proof); his own sign-flip revert-test on the pole convention (exactly the two named tests fail); breaking the toggle-redraw wiring to confirm the spy test bites; and tracing `cascade_golden.rs` to confirm the GJ1c regression shares the golden's exact source and downsample. One tool incident self-caught and cleaned (a `gdformat --check` that mutates on this version; hand-restored byte-identical to HEAD).
### Araminta (presentation sign-off): APPROVED, all four captures
R1 "delivers the read... dotted courses trace visibly across the continent"; R2's basin subtlety confirmed as designed ("tint, not paint" — do not strengthen); D initially objected — the District trunk dot at 1.6 px/60% read as accidentally-erased — fixed to her exact ask (2.0 px/80%, `0366e8286`) and re-confirmed on a representative mid-latitude capture; Q's rivers-off validated in situ ("no false-precision artifact").
### Live rounds during implementation (pre-review, for the record)
Two eyeball rounds preceded review: zoom-scaled marker sizes (sub-pixel-invisible at orbital fit zoom — diagnosed with live instrumentation, the wrong suspect ruled out with evidence and pinned anyway) and a byte-identical basins capture whose root cause was the lead's drive script passing a button label where the API takes an overlay id (no product bug; the chase still banked the toggle-redraw spy pin). One pole-adjacent entry wobble observed and filed as T-1171 rather than chased in-batch.
### Verdict: APPROVED
Tickets: T-1156 (wave 1). Filed from design pass and review: T-1168 (riparian forward contract), T-1169 (labels), T-1170 (course invention + per-basin anchoring option), T-1171 (pole-entry wobble).
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
T-1156 wave 1: the nature layer's hydrology arrives on the Atlas zoom ladder — rivers, drainage basins, and attractors drawn over the derived terrain, per-rung filtered. Wave 2 (everything civilizational) remains explicitly deferred per the nature-first order.
The design pass (before any code)
Tyre's carrier ruling reframed the ticket: the river skeleton already rides the wire —
AtlasLayerResponse.layer1has serializedRiverNetwork/drainage_basins/attractorswhole-body since #952, and the retired draw code survives intact. So wave 1 is a re-hosting plus one additive field, touching neither D-226 ceiling (windowed family stays at one field; whole-body family untouched —layer1predates that framing). Per-rung refinement is client-side class filtering — deliberately unlike T-1162's server-side cutoff, because a fixed finite graph has nothing to Nyquist-truncate. The ruling establishes the wave-2 pattern for free: discrete map features ride the whole-body overlay family filtered client-side; only continuous per-metre fields ride the windowed per-cell arrays. Captured as a D-226 note on this branch.Design-pass honesty, ticketed not buried: T-1168 (riparian vegetation response —
near_perennial_wateris a hardcoded-false stub, so rivers draw over barren-painted banks for now, deliberately not suppressed per Araminta+Tyre), T-1169 (feature-name labels — three dormant pieces, not "cheap"), T-1170 (the skeleton is 512×256 heightmap-resolution, ~76 km/cell — river courses below Region scale need invention, the linear analog of the coast crinkle).Server (Dudley) —
river_classonRiverNetworkriver_class: Vec<u8>(0=stream 1=tributary 2=trunk) parallel toriver_cells,#[serde(default)], computed at drainage-analysis time by log-scaled binning betweenRIVER_THRESHOLDand the river-restricted max accumulation. The restriction matters: grid-wide max includes below-sea-level ocean cells where accumulation peaks past the coastline — anchoring there starves the trunk class exactly on wet large-ocean bodies (caught in lead review of round 1; GJ1c went from zero trunk cells to a healthy 72/18/3 distribution). By construction every body with rivers has trunk cells, pinned by a non-synthetic regression on the committed GJ1c heightmap.cascade_layer1.jsonregenerated: every pre-existing field byte-identical (python-verified), onlyriver_classadded.Client (Stig) — the nature overlay on the ladder
New
AtlasWindowNatureOverlaynode: self-connects to the sharedatlas_layers_receivedbroadcast (the established one-signal-N-consumers shape), consumes the whole-body skeleton, draws over the terrain composite. Pure tested coordinate chainlayer1_pixel → world_m → district → canvas-localwith the vertical convention verified against the server source (row 0 = north pole) and revert-verified pole tests.Araminta's presentation ruling (supersedes the provisional add-as-you-descend mapping, on the resolution evidence): Region/orbital = full skeleton (radii 0.9/1.4/2.2 px by class, confluence 3.5, mouth double-ring), District = trunk-only at 60%/1.6 px with mouths kept at full landmark styling, Quarter = rivers off until T-1170 — isolated 76 km dots there are placement coincidence, not information. Retired palette reused verbatim. Toggles RVR on / BAS off / ATR off.
Live rounds (the eyeball check earning its keep again)
zoom_compensated_size(); numeric pin of the pre-fix magnitude in the test suite.Acceptance captures (
.cache/screenshots/rivers-eyeball/)R1: full river skeleton threading Lendel's continents at the orbital rest state, mouth rings on the coasts. R2: 7 watershed boundaries at the ruling's barely-there alphas. D: trunk-dim + mouth carve-out at a District window. Q: rivers correctly absent at Quarter.
Test discipline
Server: drainage 16/16 (+10 incl. the non-synthetic GJ1c trunk guard), layer1/layer_proxy/body_world_state green,
cargo build --testsclean, revert-verified binning monotonicity. Client: 58+ new tests across four files (pure mapping/policy, lifecycle, real-driver draw smoke — with the smoke suite's vacuous-pass mode under X11 BadMatch honestly documented and the pure-function suite installed as the real gate), 11 existing atlas suites regression-free, three independent revert-verifications. Known accepted lint:atlas_window_viewer.gdat 1016/1000 advisory lines on trivial wiring — rides T-1158's decomposition rather than degrading its postmortem comments.Tickets: T-1156 (wave 1). Filed from design pass: T-1168, T-1169, T-1170.
Review: rivers-ladder → main (type: code + visual sign-off)
Branch tip reviewed:
c1cae7c9b(both fix rounds included). Reviewers: Tyre (architecture — reviewing the implementation of his own wave-1 carrier ruling), Hoshe (QA), Araminta (presentation sign-off on her own per-rung ruling).Tyre (Architecture): APPROVE (after one fix round)
Initial REQUEST_CHANGES with one code find and two captures:
_draw_attractor_shape's three stroke-width args were raw literals — Godot multiplies widths by canvas scale like radii, so glyph outlines rasterized at ~0.01 px at the Region orbital fit zoom (the identical sub-pixel class the live-round dot/ring fix closed, missed on glyph internals — and attractors are Region-only, precisely where it bites)8a747e332— widths arrive pre-compensated via apx_wparam (primitive stays pure); source-scan regression pin asserting no bare numeric width in the function (the environment-independent gate, since the smoke suite documents its own vacuous-pass mode); revert-verified by nameRIVER_CLASS_VISIBLE_BY_RUNGnamed as the single revisit pointHis six architecture answers, in brief: the river-restricted anchor is ruled the correct model (not merely a bugfix — grid-wide max admits a ceiling no river cell can reach; per-basin anchoring recorded as a T-1170 forward option); the client-side const-table visibility is "the purest possible expression" of his carrier mechanism; the zero-ceilings claim confirmed definitively (empty diff on
layer_proxy.rs—river_classnests inside the pre-existing whole-bodylayer1); the overlay's request-per-body-switch lifecycle is correct against D-227 "valid forever"; the D-226 note is faithful with no drift; and the divide-by-zoom compensation is defensible for wave 1 with an unscaled-sibling-layer refactor recorded for wave 2 (T-1158-adjacent, appended to T-1156).Hoshe (QA): APPROVE (after one fix round)
Initial REQUEST_CHANGES on one gap: RVR-on-by-default — the single most player-visible behavior the feature ships — had no named regression assertion (gen_basins was pinned only incidentally; gen_attractors not at all). Fixed in
c1cae7c9b: one named test pinning all three fresh-construction defaults, revert-verified to fail alone by name; Hoshe repeated the revert-verification independently. Full client gate re-run at the final tip: 3770/3770.His verification was execution-grade throughout: own Python structural diff of the cascade golden (pure-append confirmed independently — only
river_classadded, 72/18/3 recomputed from the JSON); a forced clean rebuild proving no missed struct-literal site (the field is non-Option, so the compiler is the proof); his own sign-flip revert-test on the pole convention (exactly the two named tests fail); breaking the toggle-redraw wiring to confirm the spy test bites; and tracingcascade_golden.rsto confirm the GJ1c regression shares the golden's exact source and downsample. One tool incident self-caught and cleaned (agdformat --checkthat mutates on this version; hand-restored byte-identical to HEAD).Araminta (presentation sign-off): APPROVED, all four captures
R1 "delivers the read... dotted courses trace visibly across the continent"; R2's basin subtlety confirmed as designed ("tint, not paint" — do not strengthen); D initially objected — the District trunk dot at 1.6 px/60% read as accidentally-erased — fixed to her exact ask (2.0 px/80%,
0366e8286) and re-confirmed on a representative mid-latitude capture; Q's rivers-off validated in situ ("no false-precision artifact").Live rounds during implementation (pre-review, for the record)
Two eyeball rounds preceded review: zoom-scaled marker sizes (sub-pixel-invisible at orbital fit zoom — diagnosed with live instrumentation, the wrong suspect ruled out with evidence and pinned anyway) and a byte-identical basins capture whose root cause was the lead's drive script passing a button label where the API takes an overlay id (no product bug; the chase still banked the toggle-redraw spy pin). One pole-adjacent entry wobble observed and filed as T-1171 rather than chased in-batch.
Verdict: APPROVED
Tickets: T-1156 (wave 1). Filed from design pass and review: T-1168 (riparian forward contract), T-1169 (labels), T-1170 (course invention + per-basin anchoring option), T-1171 (pole-entry wobble).
Pull request closed