The server half of the Atlas visual-defect batch (the frames Jeroen flagged).
T-1186 — climate now respects latitude on both hemispheres.region_centre_latitude_deg was pole-anchored (row 0 = north pole, lat_frac clamped [0,1]) while the derive core keys equator-anchored SIGNED region rows — so every northern-hemisphere region clamped to +90° (polar everywhere) and the south read as compressed northern tropics. Now mirrors the derive core's exact inverse mapping. The ticket's own datapoint flips precisely as predicted: GJ338Bd region (136,43) baseline +13.94°/26.8°C → −76.06°/10.3°C; the 76°S district cell derives Lake/2.07°C/Light glaciation instead of an 18°C ice-free lake. Goldens regenerated (stable on rerun); two unit tests repositioned (their probe coordinates meant different places under the old convention). Convention audit: step-canvas rung-0 already used the correct signed convention; layer_proxy's pole-anchored pseudo-grid stays deferred to T-1181's rung-0 rebuild per D-256(f) — unification proposal on record there.
T-1188 — lake shorelines gain a depth gradient. Hypothesis (a) (broken positional refinement) disproven first: shoreline-crossing sweeps at 2048/512/128m + a 10m fine sweep all land on the same continuous crossing. Hypothesis (b) confirmed: every coastal-transition morphology gate keys ocean_fraction_q, definitionally 0 in a lake basin — lake edges had no gradient vocabulary. New DistrictProfile.lake_margin_q (0-100 settled-hydrology depth band from the same bilinear pair the lake test already samples; ceiling calibrated against GJ338Bd's 5,043-cell depth survey), threaded through both derive paths → EncodedStepCanvas → client protocol → terrain-layer plane → colorize (Lake cells shade by depth band, not bedrock elev_q). project.yaml 0.4.0 → 0.4.1 — the new wire field invalidates the client disk cache via its version tag (T-1183's D-192 mechanism).
Verification
Full double gate green on push: client 3,520/3,520 (includes SR_LIVE e2e), server 1,943 lib + believability/derivation/cascade goldens + step_canvas_acceptance_gate 5/5 (lossless round-trip + cache-hit==cache-miss with the new field), clippy -D warnings, deny. Merge seam with PR #205 taken cleanly (terrain-layer auto-merge verified by targeted suite re-runs: colorize 18/18, viewer 76/76). Reviews next; the District-frame eyeball (depth-shaded lake on corrected climate) runs on the final tip — merge waits on it.
## Summary
The server half of the Atlas visual-defect batch (the frames Jeroen flagged).
**T-1186 — climate now respects latitude on both hemispheres.** `region_centre_latitude_deg` was pole-anchored (row 0 = north pole, lat_frac clamped [0,1]) while the derive core keys equator-anchored SIGNED region rows — so every northern-hemisphere region clamped to +90° (polar everywhere) and the south read as compressed northern tropics. Now mirrors the derive core's exact inverse mapping. The ticket's own datapoint flips precisely as predicted: GJ338Bd region (136,43) baseline +13.94°/26.8°C → −76.06°/10.3°C; the 76°S district cell derives Lake/2.07°C/Light glaciation instead of an 18°C ice-free lake. Goldens regenerated (stable on rerun); two unit tests repositioned (their probe coordinates meant different places under the old convention). Convention audit: step-canvas rung-0 already used the correct signed convention; layer_proxy's pole-anchored pseudo-grid stays deferred to T-1181's rung-0 rebuild per D-256(f) — unification proposal on record there.
**T-1188 — lake shorelines gain a depth gradient.** Hypothesis (a) (broken positional refinement) disproven first: shoreline-crossing sweeps at 2048/512/128m + a 10m fine sweep all land on the same continuous crossing. Hypothesis (b) confirmed: every coastal-transition morphology gate keys ocean_fraction_q, definitionally 0 in a lake basin — lake edges had no gradient vocabulary. New `DistrictProfile.lake_margin_q` (0-100 settled-hydrology depth band from the same bilinear pair the lake test already samples; ceiling calibrated against GJ338Bd's 5,043-cell depth survey), threaded through both derive paths → EncodedStepCanvas → client protocol → terrain-layer plane → colorize (Lake cells shade by depth band, not bedrock elev_q). **project.yaml 0.4.0 → 0.4.1** — the new wire field invalidates the client disk cache via its version tag (T-1183's D-192 mechanism).
## Verification
Full double gate green on push: client 3,520/3,520 (includes SR_LIVE e2e), server 1,943 lib + believability/derivation/cascade goldens + step_canvas_acceptance_gate 5/5 (lossless round-trip + cache-hit==cache-miss with the new field), clippy -D warnings, deny. Merge seam with PR #205 taken cleanly (terrain-layer auto-merge verified by targeted suite re-runs: colorize 18/18, viewer 76/76). Reviews next; the District-frame eyeball (depth-shaded lake on corrected climate) runs on the final tip — merge waits on it.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
region_centre_latitude_deg mapped row 0 to the north pole with lat_frac
clamped [0,1] while the derive core floor-divides equator-anchored signed
world metres — every northern-hemisphere region clamped to +90 (polar
everywhere) and the southern hemisphere read as compressed northern
tropics. Now mirrors the derive core's exact inverse mapping (lat_frac =
centre_y/meridian clamped [-0.5,0.5], lat = -frac*180). The ticket's
in-the-wild datapoint flips as predicted: GJ338Bd region (136,43), old
baseline +13.94N/26.8C -> new -76.06S/10.3C; the 76S district cell now
derives Lake/2.07C/Light glaciation. Goldens regenerated (believability +
window derivation, stable on rerun); two region_profile unit tests
repositioned — their probe coordinates meant different places under the
old convention. step_canvas rung-0 already used the correct signed
convention; layer_proxy's pole-anchored pseudo-grid stays deferred to
T-1181's rung-0 rebuild per D-256(f).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Lake edges rendered as hard step-edges while ocean coasts got multi-tone
transition bands: every coastal-transition morphology gate keys on
ocean_fraction_q, definitionally 0 inside a lake basin (hypothesis (b)
of the ticket; (a) disproven first — a shoreline-crossing sweep at
2048/512/128m plus a 10m fine sweep all land on the same continuous
crossing, so positional refinement was never broken). New
DistrictProfile.lake_margin_q (0-100 settled-hydrology depth band, from
the same bilinear filled/elevation pair the lake test already samples;
ceiling calibrated just above the observed p90 depth on GJ338Bd's 5,043
flooded cells), threaded through both derive paths onto
EncodedStepCanvas (serde-default for shape tolerance) and down the
client: protocol decode, terrain-layer plane, colorize shades Lake cells
by depth band instead of elev_q (bedrock-under-water, the wrong signal).
project.yaml 0.4.0 -> 0.4.1: the new wire field must invalidate the
client disk cache via its version tag (T-1183's D-192 mechanism).
Acceptance gates green with the new field (lossless round-trip,
cache-hit==cache-miss, every rung).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Hoshe's review finding: the build_step_canvas row-space convention block
still described region_centre_latitude_deg as pole-anchored/bugged and
said 'T-1186 stays open' — both false after this PR's own first commit.
Rewritten to reflect the fixed state; the deliberate signed-convention
rationale and the layer_proxy deferral (still true, still T-1181's scope)
are preserved.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Reviewers: Hoshe (code quality) + Tyre (architecture).
Tyre (architecture): APPROVE
No comments. Verification highlights worth the record: the latitude fix is structurally a single-point correction (one production call path, no parallel formula — verified by caller graph); the golden diff shows exactly the D-256-predicted blast radius (a south-of-equator probe flipping −4.3 °C polar-misread → +12.3 °C correctly-read while morphology/elevation/ocean-fraction topology stays byte-identical across all 20 probes); the layer_proxy deferral's reader-isolation claim holds (sole consumer is the stale body-view overlay); lake_margin_q is D-255(c)/(e)/(f)-conformant and the acceptance gate covers the new field for free via whole-struct equality; the version bump targets the one persistent store needing invalidation. The LAKE_MARGIN_DEPTH_CEILING single-body calibration was examined and cleared: it operates in the per-body-normalized elevation-fraction domain (partially auto-scales), degrades safely, and is isolated from the believability metric — the right rigor for a cosmetic shading parameter.
Hoshe (code quality): REQUEST_CHANGES
#
File
Issue
Resolution
1
step_canvas.rs:899-926
Stale doc block on build_step_canvas still described region_centre_latitude_deg as pole-anchored/bugged and stated "T-1186 stays open" — both false after this PR's own first commit; would mislead the next reader
Fixed — block rewritten to the resolved state, preserving the still-true signed-convention rationale and the layer_proxy/T-1181 deferral (b39dd4995)
Hoshe's verified-clean list: the latitude inverse mapping matches the derive core bit-for-bit (including the +0.5 row-centre offset and clamp bounds); the two repositioned unit tests preserve their assertion intent; believability golden churn is small-magnitude and direction-plausible, not a rewrite; lake_margin_q threading, clamps, no-hydrology default, serde-default decode, and the Lake-only colorize gating are all correct; the #205 merge seam is coherent.
Verdict: CHANGES REQUESTED -> addressed in b39dd4995; the District/Global eyeball on the final tip gates the merge.
# Review: atlas-latitude-fix -> main (type: code)
Reviewers: Hoshe (code quality) + Tyre (architecture).
### Tyre (architecture): APPROVE
No comments. Verification highlights worth the record: the latitude fix is structurally a single-point correction (one production call path, no parallel formula — verified by caller graph); the golden diff shows exactly the D-256-predicted blast radius (a south-of-equator probe flipping −4.3 °C polar-misread → +12.3 °C correctly-read while morphology/elevation/ocean-fraction topology stays byte-identical across all 20 probes); the layer_proxy deferral's reader-isolation claim holds (sole consumer is the stale body-view overlay); lake_margin_q is D-255(c)/(e)/(f)-conformant and the acceptance gate covers the new field for free via whole-struct equality; the version bump targets the one persistent store needing invalidation. The LAKE_MARGIN_DEPTH_CEILING single-body calibration was examined and cleared: it operates in the per-body-normalized elevation-fraction domain (partially auto-scales), degrades safely, and is isolated from the believability metric — the right rigor for a cosmetic shading parameter.
### Hoshe (code quality): REQUEST_CHANGES
| # | File | Issue | Resolution |
|---|------|-------|------------|
| 1 | step_canvas.rs:899-926 | Stale doc block on build_step_canvas still described region_centre_latitude_deg as pole-anchored/bugged and stated "T-1186 stays open" — both false after this PR's own first commit; would mislead the next reader | **Fixed** — block rewritten to the resolved state, preserving the still-true signed-convention rationale and the layer_proxy/T-1181 deferral (`b39dd4995`) |
Hoshe's verified-clean list: the latitude inverse mapping matches the derive core bit-for-bit (including the +0.5 row-centre offset and clamp bounds); the two repositioned unit tests preserve their assertion intent; believability golden churn is small-magnitude and direction-plausible, not a rewrite; lake_margin_q threading, clamps, no-hydrology default, serde-default decode, and the Lake-only colorize gating are all correct; the #205 merge seam is coherent.
### Verdict: CHANGES REQUESTED -> addressed in `b39dd4995`; the District/Global eyeball on the final tip gates the merge.
The PR #206 eyeball caught what every numeric gate passed: the depth
signal was visually flat on both test lakes (GJ1c lmq=0 across the whole
basin; GJ338Bd 0-13 of 100). Two compounding causes: a fixed absolute
ceiling (one body's p90 cell depth) compressing skewed depth
distributions into single digits, and heightmap-pitch depth variation
being sub-texel-tiny within most basins. lake_margin_q is now
depth / the basin's own maximum settled depth: HydrologyResult grows
basin_max_depth_scaled (computed in solve() from existing basin_cells
membership, broadcast per basin), threaded through
HydrologySample.basin_max_depth, normalized in lake_from_hydrology_at
with a degenerate-basin epsilon guard (a genuinely uniform pond shades
flat — honest, not forced). Lake EXISTENCE (filled > original) is
untouched — only tone changes. Measured at district spacing:
GJ1c min=0 p50=33 max=84; GJ338Bd min=8 p50=38 max=70 — full-range
shore-to-deep ramps on both. No perceptual curve added: the linear
per-basin ramp is already well-quartiled. project.yaml 0.4.1 -> 0.4.2
(0.4.1-tagged canvases carrying flat-lmq semantics reached real disk
caches during eyeball runs and must miss). Acceptance gates green;
zero golden churn (lake_margin_q not captured by either golden shape).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The first eyeball FAILED the lake-depth shading despite every numeric gate passing: the mechanism worked end-to-end but the signal was visually flat — GJ1c's lake at lake_margin_q=0 across the entire basin, GJ338Bd using ~10% of the range. Root cause: a fixed absolute depth ceiling (one body's p90 cell depth) compressing skewed depth distributions, compounded by heightmap-pitch depth variation being sub-texel-tiny within most basins.
Fix (39f0fd8c5 + style 4a9567c66): per-basin normalization — lake_margin_q = depth / the basin's own maximum settled depth. HydrologyResult grows basin_max_depth_scaled (computed in solve() from existing basin membership, broadcast per basin), threaded through HydrologySample, normalized in lake_from_hydrology_at with a degenerate-basin epsilon guard (a genuinely uniform pond shades flat — honest, not forced). Lake EXISTENCE is untouched; only tone changes. Measured distributions at district spacing: GJ1c min=0/p50=33/max=84, GJ338Bd min=8/p50=38/max=70 — full-range shore→deep ramps on both, vs round 1's 0 and 0–13. No perceptual curve: linear is already well-quartiled. project.yaml → 0.4.2 (0.4.1-tagged flat-semantic canvases reached real disk caches during eyeball runs and must miss). Acceptance gates green; zero golden churn.
Also adjudicated from eyeball round 1:
The "76°S lake still not cold-looking" finding is retracted as an expectation error: grade-1 Light glaciation renders at alpha 0.0 by design (erosion signatures, not ice cover — the ported reference implementation's own documented rule), and a 10.3 °C baseline legitimately reads green. The temperature/glaciation data flip was already proven live.
T-1186's both-poles ice banding: PASS by color decomposition (north edge 100% grade-2, south edge climbing to 28% — asymmetry noted; the re-eyeball adds a second body's Global as a symmetry check).
Re-eyeball on 4a9567c66 gates the merge.
# Eyeball round 1 → fix round 2 (T-1188 depth gradient)
The first eyeball FAILED the lake-depth shading despite every numeric gate passing: the mechanism worked end-to-end but the signal was visually flat — GJ1c's lake at `lake_margin_q=0` across the entire basin, GJ338Bd using ~10% of the range. Root cause: a fixed absolute depth ceiling (one body's p90 cell depth) compressing skewed depth distributions, compounded by heightmap-pitch depth variation being sub-texel-tiny within most basins.
**Fix (`39f0fd8c5` + style `4a9567c66`): per-basin normalization** — `lake_margin_q = depth / the basin's own maximum settled depth`. `HydrologyResult` grows `basin_max_depth_scaled` (computed in `solve()` from existing basin membership, broadcast per basin), threaded through `HydrologySample`, normalized in `lake_from_hydrology_at` with a degenerate-basin epsilon guard (a genuinely uniform pond shades flat — honest, not forced). Lake EXISTENCE is untouched; only tone changes. Measured distributions at district spacing: GJ1c min=0/p50=33/max=84, GJ338Bd min=8/p50=38/max=70 — full-range shore→deep ramps on both, vs round 1's 0 and 0–13. No perceptual curve: linear is already well-quartiled. `project.yaml` → 0.4.2 (0.4.1-tagged flat-semantic canvases reached real disk caches during eyeball runs and must miss). Acceptance gates green; zero golden churn.
**Also adjudicated from eyeball round 1:**
- The "76°S lake still not cold-looking" finding is **retracted as an expectation error**: grade-1 Light glaciation renders at alpha 0.0 *by design* (erosion signatures, not ice cover — the ported reference implementation's own documented rule), and a 10.3 °C baseline legitimately reads green. The temperature/glaciation data flip was already proven live.
- T-1186's both-poles ice banding: PASS by color decomposition (north edge 100% grade-2, south edge climbing to 28% — asymmetry noted; the re-eyeball adds a second body's Global as a symmetry check).
Re-eyeball on `4a9567c66` gates the merge.
GJ338Bd Global symmetry check: polar banding present at both edges; asymmetry runs the OPPOSITE direction from GJ1c at ~3× smaller magnitude — the latitude fix has no systematic polar bias; GJ1c's north-dominance is genuine per-body variation. Not ticket-worthy.
Version tag: stale 0.4.1/0.4.0 entries confirmed on disk going in; every touched key now 0.4.2 with fresh timestamps, untouched keys stayed stale — per-key miss-and-refetch, no blanket flush, nothing stale ever decoded.
Captures: .cache/screenshots/t1186-88-eyeball-r2/. Input-path fidelity label as established (in-process navigation; unchanged by this PR). Merging.
# Re-eyeball round 2 — PASS (merge gate cleared)
Live run on `4a9567c66`, rebuilt server, recalibrated criteria.
- **GJ1c district lake:** 67 distinct color bands, radial shore→center darkening confirmed by depth heatmap + centroid-distance monotonicity — categorical improvement over round 1's flat single tone.
- **GJ338Bd district lake:** 98 bands, strictly monotone radial gradient (centroid-distance thirds 54.3 → 83.5 → 112.2).
- **GJ338Bd Global symmetry check:** polar banding present at both edges; asymmetry runs the OPPOSITE direction from GJ1c at ~3× smaller magnitude — the latitude fix has no systematic polar bias; GJ1c's north-dominance is genuine per-body variation. Not ticket-worthy.
- **Version tag:** stale 0.4.1/0.4.0 entries confirmed on disk going in; every touched key now 0.4.2 with fresh timestamps, untouched keys stayed stale — per-key miss-and-refetch, no blanket flush, nothing stale ever decoded.
Captures: `.cache/screenshots/t1186-88-eyeball-r2/`. Input-path fidelity label as established (in-process navigation; unchanged by this PR). Merging.
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
The server half of the Atlas visual-defect batch (the frames Jeroen flagged).
T-1186 — climate now respects latitude on both hemispheres.
region_centre_latitude_degwas pole-anchored (row 0 = north pole, lat_frac clamped [0,1]) while the derive core keys equator-anchored SIGNED region rows — so every northern-hemisphere region clamped to +90° (polar everywhere) and the south read as compressed northern tropics. Now mirrors the derive core's exact inverse mapping. The ticket's own datapoint flips precisely as predicted: GJ338Bd region (136,43) baseline +13.94°/26.8°C → −76.06°/10.3°C; the 76°S district cell derives Lake/2.07°C/Light glaciation instead of an 18°C ice-free lake. Goldens regenerated (stable on rerun); two unit tests repositioned (their probe coordinates meant different places under the old convention). Convention audit: step-canvas rung-0 already used the correct signed convention; layer_proxy's pole-anchored pseudo-grid stays deferred to T-1181's rung-0 rebuild per D-256(f) — unification proposal on record there.T-1188 — lake shorelines gain a depth gradient. Hypothesis (a) (broken positional refinement) disproven first: shoreline-crossing sweeps at 2048/512/128m + a 10m fine sweep all land on the same continuous crossing. Hypothesis (b) confirmed: every coastal-transition morphology gate keys ocean_fraction_q, definitionally 0 in a lake basin — lake edges had no gradient vocabulary. New
DistrictProfile.lake_margin_q(0-100 settled-hydrology depth band from the same bilinear pair the lake test already samples; ceiling calibrated against GJ338Bd's 5,043-cell depth survey), threaded through both derive paths → EncodedStepCanvas → client protocol → terrain-layer plane → colorize (Lake cells shade by depth band, not bedrock elev_q). project.yaml 0.4.0 → 0.4.1 — the new wire field invalidates the client disk cache via its version tag (T-1183's D-192 mechanism).Verification
Full double gate green on push: client 3,520/3,520 (includes SR_LIVE e2e), server 1,943 lib + believability/derivation/cascade goldens + step_canvas_acceptance_gate 5/5 (lossless round-trip + cache-hit==cache-miss with the new field), clippy -D warnings, deny. Merge seam with PR #205 taken cleanly (terrain-layer auto-merge verified by targeted suite re-runs: colorize 18/18, viewer 76/76). Reviews next; the District-frame eyeball (depth-shaded lake on corrected climate) runs on the final tip — merge waits on it.
🤖 Generated with Claude Code
Review: atlas-latitude-fix -> main (type: code)
Reviewers: Hoshe (code quality) + Tyre (architecture).
Tyre (architecture): APPROVE
No comments. Verification highlights worth the record: the latitude fix is structurally a single-point correction (one production call path, no parallel formula — verified by caller graph); the golden diff shows exactly the D-256-predicted blast radius (a south-of-equator probe flipping −4.3 °C polar-misread → +12.3 °C correctly-read while morphology/elevation/ocean-fraction topology stays byte-identical across all 20 probes); the layer_proxy deferral's reader-isolation claim holds (sole consumer is the stale body-view overlay); lake_margin_q is D-255(c)/(e)/(f)-conformant and the acceptance gate covers the new field for free via whole-struct equality; the version bump targets the one persistent store needing invalidation. The LAKE_MARGIN_DEPTH_CEILING single-body calibration was examined and cleared: it operates in the per-body-normalized elevation-fraction domain (partially auto-scales), degrades safely, and is isolated from the believability metric — the right rigor for a cosmetic shading parameter.
Hoshe (code quality): REQUEST_CHANGES
b39dd4995)Hoshe's verified-clean list: the latitude inverse mapping matches the derive core bit-for-bit (including the +0.5 row-centre offset and clamp bounds); the two repositioned unit tests preserve their assertion intent; believability golden churn is small-magnitude and direction-plausible, not a rewrite; lake_margin_q threading, clamps, no-hydrology default, serde-default decode, and the Lake-only colorize gating are all correct; the #205 merge seam is coherent.
Verdict: CHANGES REQUESTED -> addressed in
b39dd4995; the District/Global eyeball on the final tip gates the merge.Eyeball round 1 → fix round 2 (T-1188 depth gradient)
The first eyeball FAILED the lake-depth shading despite every numeric gate passing: the mechanism worked end-to-end but the signal was visually flat — GJ1c's lake at
lake_margin_q=0across the entire basin, GJ338Bd using ~10% of the range. Root cause: a fixed absolute depth ceiling (one body's p90 cell depth) compressing skewed depth distributions, compounded by heightmap-pitch depth variation being sub-texel-tiny within most basins.Fix (
39f0fd8c5+ style4a9567c66): per-basin normalization —lake_margin_q = depth / the basin's own maximum settled depth.HydrologyResultgrowsbasin_max_depth_scaled(computed insolve()from existing basin membership, broadcast per basin), threaded throughHydrologySample, normalized inlake_from_hydrology_atwith a degenerate-basin epsilon guard (a genuinely uniform pond shades flat — honest, not forced). Lake EXISTENCE is untouched; only tone changes. Measured distributions at district spacing: GJ1c min=0/p50=33/max=84, GJ338Bd min=8/p50=38/max=70 — full-range shore→deep ramps on both, vs round 1's 0 and 0–13. No perceptual curve: linear is already well-quartiled.project.yaml→ 0.4.2 (0.4.1-tagged flat-semantic canvases reached real disk caches during eyeball runs and must miss). Acceptance gates green; zero golden churn.Also adjudicated from eyeball round 1:
Re-eyeball on
4a9567c66gates the merge.Re-eyeball round 2 — PASS (merge gate cleared)
Live run on
4a9567c66, rebuilt server, recalibrated criteria.Captures:
.cache/screenshots/t1186-88-eyeball-r2/. Input-path fidelity label as established (in-process navigation; unchanged by this PR). Merging.Pull request closed