fix(simulation): per-body TerrainAnalysis LRU + full-path determinism test (PR #187 C1/C3)

C1 (Tyre): the DeriveWindow branch re-ran the ~45ms run_layer1 for
EVERY uncached window — the dominant pan-around-one-body path paid
~52ms per new window while the doc claimed one-time-per-body.
TerrainAnalysisCache: private per-body LRU (capacity 8, ~2MB/entry,
true access-recency eviction — which body the player keeps panning IS
a recency signal) held as Arc<Mutex<>> on GenerationQueue itself, the
in_flight field pattern, because run_work_item executes on a Rayon
worker where the main-thread caches are unreachable. DeriveWindow now
calls get_or_derive; the variant doc states the real model (first
window per body pays ~45ms once; subsequent windows any center/n hit
the LRU; eviction re-pays). End-to-end test proves two windows on one
body via two connections share exactly one cache entry.

C3 (Tyre): the determinism test reused one TerrainAnalysis — proving
the packer, not the derivation. New test runs run_layer1 twice
independently, asserts field-by-field analysis agreement, then
byte-identical packed windows end to end (D-227 save-critical proof).
Packer-only test kept alongside.

atlas:: 564/564; full lib 1778/1778; timing-sensitive suites 3x stable.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-21 13:56:58 +02:00
co-authored by Claude Fable 5
parent 9e1e6db614
commit df33e9f2fb
2 changed files with 366 additions and 24 deletions
+55
View File
@@ -1283,6 +1283,61 @@ mod tests {
);
}
/// FULL-PATH determinism (PR #187 review — Tyre C3, binding, load-bearing
/// for save-file lineage under D-227): the test above reuses ONE `ta` for
/// both passes, which only proves `build_district_window_layer` (the
/// packer) is a pure function of its arguments — it says nothing about
/// whether re-running `run_layer1` itself (the D8 drainage pass +
/// `TerrainAnalysis::analyze`) is deterministic, which is exactly what the
/// production `DeriveWindow` path depends on (T-1137's `TerrainAnalysis`
/// re-derive / `TerrainAnalysisCache::get_or_derive` on a cache miss, and
/// `aliveness_probe --render`'s workaround before it).
///
/// This test runs `run_layer1` TWICE, independently, from the SAME
/// `(seed, heightmap)` inputs — no shared `ta` — and asserts the two
/// COMPLETE `DistrictWindowLayer` outputs (derive AND pack) are
/// byte-identical. D-227's save-file guarantee ("same seed/body/position →
/// same derived output, always") is only as strong as the weakest link in
/// that chain; this closes the gap the packer-only test left open.
#[test]
fn full_path_two_independent_run_layer1_passes_produce_identical_window() {
let hm = window_test_hm();
let params = window_test_params();
let climate = crate::atlas::district_profile::ClimateConstants::default();
let seed = SeedChain::root(11).derive(SeedDomain::Body, 5);
let n = 6u32;
let center = (4, -1);
// Two INDEPENDENT calls to run_layer1 — each re-runs D8 drainage +
// TerrainAnalysis::analyze from scratch on the SAME heightmap, exactly
// mirroring what a cold TerrainAnalysisCache miss does on the real
// DeriveWindow path (or a second body eviction re-pay).
let (_, ta_pass1) = crate::atlas::layer1::run_layer1(&hm);
let (_, ta_pass2) = crate::atlas::layer1::run_layer1(&hm);
// Confirm the two independent TerrainAnalysis derivations themselves
// agree field-by-field — a precise failure signal if drainage/analyze
// ever introduces nondeterminism (unordered iteration, uninitialized
// memory, etc.) BEFORE the packer even runs.
assert_eq!(ta_pass1.ocean_mask, ta_pass2.ocean_mask);
assert_eq!(ta_pass1.lake_mask, ta_pass2.lake_mask);
assert_eq!(ta_pass1.water_dist, ta_pass2.water_dist);
assert_eq!(ta_pass1.slope_deg, ta_pass2.slope_deg);
assert_eq!(ta_pass1.elev_pct, ta_pass2.elev_pct);
// Now the FULL path: pack a DistrictWindowLayer from each independent
// TerrainAnalysis and confirm the complete served payload agrees.
let window_from_pass1 =
build_district_window_layer(seed, "test_body", &params, &ta_pass1, center, n, &climate);
let window_from_pass2 =
build_district_window_layer(seed, "test_body", &params, &ta_pass2, center, n, &climate);
assert_eq!(
window_from_pass1, window_from_pass2,
"two independent run_layer1 derivations from the same (seed, heightmap) \
must pack to a byte-identical DistrictWindowLayer end to end (D-227)"
);
}
/// [`DistrictWindowCache`] insert/get round-trips, and a capacity-1 cache
/// evicts the oldest entry FIFO — mirroring `BodyWorldStateCache`'s own
/// `evicts_lru_on_overflow` precedent, adapted to this cache's