fix(simulation): PR #200 review round — cache sizing truth + endorheic assertion

Hoshe finding 1: dropping HydrologySample.elevation was PROVEN unsafe
(TerrainAnalysis.elev_pct is a rank percentile, not raw elevation;
HydrologyResult carries no elevation) — the copy stays, and the truth
moves into the docs instead: gen_queue's TerrainAnalysisCache sizing
comment corrected to real 512x256 working-grid numbers (~1.57 ->
~2.62 MB/entry, capacity-8 worst case ~21 MB), clone-on-hit cost
documented, byte-safety proof recorded on HydrologySample itself.
Arc<TerrainAnalysis> follow-up filed as T-1187.

Hoshe finding 2: the endorheic-split test now asserts the bowl basin's
BasinOutcome actually diverges (Endorheic at moisture 0, Overflow at
100, straddling ENDORHEIC_MOISTURE_CEILING=60) plus basin-count sanity
— mutation-verified by stubbing is_endorheic and watching it fail.

Doc/test-only round: goldens byte-unchanged, full suite 2114 green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-25 02:41:55 +02:00
co-authored by Claude Fable 5
parent 3f4c868daa
commit 4ef79b6b45
3 changed files with 136 additions and 14 deletions
+21
View File
@@ -98,6 +98,27 @@ pub struct TerrainAnalysis {
/// `[0.0, 1.0]` normalized domain the raw heightmap and `sea_level` already
/// share — so a bilinear sample of one is directly comparable to a bilinear
/// sample of the other, no rescaling at the call site.
///
/// **Size + clone cost (PR #200 review, Hoshe finding 1):** two `Vec<f32>` at
/// the real 512×256 working grid = ~1.05 MB/entry, added on top of
/// `TerrainAnalysis`'s pre-existing ~1.57 MB of dense fields (~2.62 MB total,
/// ×1.67 growth, not quite a doubling) — see the corrected sizing comment on
/// `GenWorkItem::DeriveWindow` (`gen_queue.rs`) for the full accounting and
/// the `TerrainAnalysisCache` cache-HIT clone-cost note (every hit
/// deep-copies both these `Vec`s, not just the first miss/insert).
///
/// **`elevation` is a deliberate, provably-necessary redundant copy, not an
/// oversight.** `TerrainAnalysis` has no OTHER field that retains the raw
/// `[0,1]` heightmap: `elev_pct` is a RANK PERCENTILE (`rank(elev[i]) /
/// (land_cell_count - 1)`, `compute_elev_percentile`'s own doc/impl) —
/// mathematically a different quantity from absolute elevation, and NOT
/// safe to compare against `filled` (two cells at different true elevations
/// can share adjacent ranks; ocean cells are forced to `0.0` regardless of
/// their real depth). `HydrologyResult` itself carries no elevation field
/// either (`hydrology_equilibrium.rs`: `basins`, `filled_scaled`,
/// `channel_depth_scaled`, `cliff_edge` — no `original`/`elevation` member).
/// So there is no existing bit-identical grid this field could point at
/// instead — carrying its own copy is the only byte-safe option today.
#[derive(Debug, Clone)]
pub struct HydrologySample {
/// The original (unfilled) heightmap elevation, `[0.0, 1.0]`. Not stored