//! Window-derivation golden regression (T-1162). //! //! Pins `derive_at_metres` (District/Quarter rungs) and //! `derive_orbital_at_metres` (Region rung) output at a fixed //! (seed, body, coords) sweep, across all three rung cutoffs — the window //! path `layer_proxy::derive_window_cell` actually calls in production. //! Mirrors `tests/derivation_harness.rs`'s golden pattern exactly (same //! regen convention, same double-derive determinism check, same JSON-value //! comparison so formatting drift doesn't false-positive). //! //! **T-1162 regen rationale:** this golden is generated AFTER the T-1162 //! octave-extension changes (extended coast-warp band, sub-district relief at //! Quarter, vegetation patchiness) — it deliberately pins the NEW output. //! There is no "pre-T-1162" golden to preserve: this file did not exist //! before this ticket, so there is nothing to regress against except itself //! from this point forward. Any future change to the coast warp, the voxel //! relief band, the vegetation-patchiness field, or the MIN_WL_BANDS_M //! quantization will change this golden's values — regenerate deliberately //! (per the asset-pipeline discipline: source changes, not hand-edits). //! //! Run: `cargo test --test window_derivation_golden` //! Regenerate: `UPDATE_GOLDEN=1 cargo test --test window_derivation_golden` use std::path::PathBuf; use settled_reach_server::atlas::district_profile::{ derive_at_metres, derive_orbital_at_metres, BodyParams, ClimateConstants, }; use settled_reach_server::atlas::drainage; use settled_reach_server::atlas::features::TerrainAnalysis; use settled_reach_server::atlas::heightmap::BodyHeightmap; use settled_reach_server::atlas::scale; use settled_reach_server::seed::{SeedChain, SeedDomain}; const GOLDEN_FILE: &str = "tests/golden/window_derivation_golden.json"; /// Compact representation of a `DistrictProfile` sample for golden pinning. /// Integer-discriminant fields only (D-010) — no float equality flakiness. #[derive(Debug, serde::Serialize, serde::Deserialize, PartialEq, Eq, Clone)] struct GoldenSample { label: String, rung: String, wx_m: i64, wy_m: i64, min_wl_m: i64, morphology: u8, tectonic: u8, glaciation: u8, precipitation: u8, slope_q: i32, elev_q: i32, ocean_fraction_q: i32, temperature_dc: i32, // deci-°C, i32::MIN sentinel for None (airless) moisture_q: i32, vegetation: u8, } fn sample_hm() -> BodyHeightmap { // Deterministic gradient with enough variance for coast/relief/vegetation // content to actually differ across the sweep positions — same shape // convention as district_profile.rs's own test_hm / zoom_ladder_bench's // bench_hm, sized a bit larger so the sweep coordinates land on distinct // heightmap cells rather than a single interpolated patch. let (w, h) = (128u32, 64u32); let n = (w * h) as usize; let data = (0..n) .map(|i| { let r = (i / w as usize) as f32 / h as f32; let c = (i % w as usize) as f32 / w as f32; // A gentle sine ripple on top of the linear gradient gives the // coastline invention real slope/ocean-mask variance to warp. let ripple = (c * std::f32::consts::TAU * 3.0).sin() * 0.08; (r * 0.55 + c * 0.35 + ripple + 0.05).clamp(0.0, 1.0) }) .collect(); BodyHeightmap { body_id: "golden_body".into(), width: w, height: h, data, sea_level: 0.32, } } fn sample_ta(hm: &BodyHeightmap) -> TerrainAnalysis { let dr = drainage::analyze(&hm.data, hm.width, hm.height, hm.sea_level); TerrainAnalysis::analyze(hm, &dr) } fn sample_params() -> BodyParams { BodyParams { hydrosphere: Some("ocean".into()), atmosphere: Some("breathable".into()), planet_class: Some("temperate".into()), body_radius_km: Some(6371.0), ..Default::default() } } /// Fixed sweep positions (world metres from origin) — a handful of points /// spanning a coastal stretch (per the heightmap's ripple) plus a couple of /// clearly inland/high-latitude points, so the golden exercises coast warp, /// sub-district relief, and vegetation patchiness all at once. fn sweep_positions() -> Vec<(&'static str, f64, f64)> { vec![ ("coastal_a", 2_000_000.0, 1_500_000.0), ("coastal_b", 2_050_000.0, 1_500_000.0), ("coastal_c", 2_100_000.0, 1_560_000.0), ("inland", 500_000.0, 3_000_000.0), ("high_lat", 1_200_000.0, 8_500_000.0), ] } fn derive_golden_sample( label: &str, rung: &str, seed: SeedChain, body_id: &str, params: &BodyParams, ta: &TerrainAnalysis, climate: &ClimateConstants, wx: f64, wy: f64, min_wl_m: f64, orbital: bool, ) -> GoldenSample { let prof = if orbital { derive_orbital_at_metres(seed, body_id, params, ta, wx, wy, climate) } else { derive_at_metres(seed, body_id, params, ta, wx, wy, climate, min_wl_m) }; GoldenSample { label: label.to_string(), rung: rung.to_string(), wx_m: wx as i64, wy_m: wy as i64, min_wl_m: min_wl_m as i64, morphology: prof.morphology_zone as u8, tectonic: prof.tectonic_class as u8, glaciation: prof.glaciation_grade as u8, precipitation: prof.precipitation_class as u8, slope_q: prof.slope_q, elev_q: prof.elev_q, ocean_fraction_q: prof.ocean_fraction_q, temperature_dc: prof .temperature_c .map(|t| (t * 10.0).round() as i32) .unwrap_or(i32::MIN), moisture_q: prof.moisture_q, vegetation: prof.vegetation_class as u8, } } /// District's real quantized `min_wl_m` band (`layer_proxy::MIN_WL_BANDS_M`'s /// pre-existing finest entry — District's own Nyquist floor, matching /// `detail_scatter::OCTAVE_WAVELENGTHS_M`'s finest octave). NOT `2 * /// DISTRICT_M` by construction coincidence alone — see the T-1162 discovery /// documented on `MIN_WL_BANDS_M` and on `district_floor_cutoff_is_stable_and_deterministic` /// in `district_profile.rs`: a District-rung request in production quantizes /// to exactly this value, so the golden pins the SAME cutoff a real window /// request would actually carry. const DISTRICT_MIN_WL_M: f64 = 4_096.0; /// Quarter's real quantized `min_wl_m` band (`layer_proxy::MIN_WL_BANDS_M`'s /// new T-1162 entry — Quarter's own Nyquist floor, `2 * QUARTER_M`). const QUARTER_MIN_WL_M: f64 = 1_024.0; /// Build the full fixed sweep: every position × the three rung cutoffs /// (District / Quarter use their REAL production `MIN_WL_BANDS_M` values / /// Region via `derive_orbital_at_metres`, which takes no cutoff parameter — /// see its own doc on why). fn golden_samples() -> Vec { let hm = sample_hm(); let ta = sample_ta(&hm); let params = sample_params(); let climate = ClimateConstants::default(); let seed = SeedChain::root(0xC0FFEE_u64).derive(SeedDomain::Body, 7); let body_id = "golden_body"; let mut out = Vec::new(); for (label, wx, wy) in sweep_positions() { out.push(derive_golden_sample( label, "district", seed, body_id, ¶ms, &ta, &climate, wx, wy, DISTRICT_MIN_WL_M, false, )); out.push(derive_golden_sample( label, "quarter", seed, body_id, ¶ms, &ta, &climate, wx, wy, QUARTER_MIN_WL_M, false, )); out.push(derive_golden_sample( label, "region", seed, body_id, ¶ms, &ta, &climate, wx, wy, 0.0, true, )); } out } #[test] fn window_derivation_golden_regression() { let manifest = PathBuf::from(env!("CARGO_MANIFEST_DIR")); let golden_path = manifest.join(GOLDEN_FILE); // Double-derive determinism check (D-010) before ever touching the golden. let run1 = golden_samples(); let run2 = golden_samples(); assert_eq!( run1, run2, "double-derivation mismatch — determinism is broken (D-010)" ); let actual_json = serde_json::to_string_pretty(&run1).expect("serialize") + "\n"; if std::env::var("UPDATE_GOLDEN").is_ok() { std::fs::create_dir_all(golden_path.parent().unwrap()).expect("mkdir golden"); std::fs::write(&golden_path, &actual_json).expect("write golden"); eprintln!( "Golden written: {} ({} bytes)", golden_path.display(), actual_json.len() ); return; } let golden_json = std::fs::read_to_string(&golden_path).unwrap_or_else(|e| { panic!( "Golden file not found: {}.\n\ First run: UPDATE_GOLDEN=1 cargo test --test window_derivation_golden\n{e}", golden_path.display() ) }); let actual_v: serde_json::Value = serde_json::from_str(&actual_json).expect("reparse actual"); let golden_v: serde_json::Value = serde_json::from_str(&golden_json).expect("parse golden"); if actual_v != golden_v { panic!( "Window-derivation golden mismatch — derivation chain changed.\n\ Update: UPDATE_GOLDEN=1 cargo test --test window_derivation_golden\n\ Golden: {}\nActual: {}", golden_json.trim(), actual_json.trim() ); } } /// Cross-rung coherence sanity check on the golden's own fixed sweep: for /// each coastal label, the Quarter-rung sample must differ from the /// District-rung sample at the SAME position (the whole point of the /// extension — Quarter sees finer content District's coarser cutoff /// truncates). This is a structural companion to the golden file itself, /// not a replacement for it — it fails loudly if the golden ever gets /// regenerated with `min_wl_m` accidentally identical across rungs. #[test] fn quarter_and_district_rungs_diverge_at_the_same_position() { let samples = golden_samples(); let mut any_diverged = false; for (label, _, _) in sweep_positions() { let district = samples .iter() .find(|s| s.label == label && s.rung == "district") .unwrap(); let quarter = samples .iter() .find(|s| s.label == label && s.rung == "quarter") .unwrap(); if district.elev_q != quarter.elev_q || district.slope_q != quarter.slope_q || district.moisture_q != quarter.moisture_q { any_diverged = true; } } assert!( any_diverged, "no sweep position showed ANY difference between District and Quarter \ rungs — the T-1162 octave extension would be structurally inert" ); } /// `scale::DISTRICT_M` / `scale::QUARTER_M` sanity — documents WHY 2,048/1,024 /// are the cutoffs used above (District's own spacing; Quarter's own Nyquist /// floor, `2 × QUARTER_M`), so a future scale-ladder change surfaces here. #[test] fn golden_cutoffs_match_the_scale_ladder() { assert_eq!(scale::DISTRICT_M, 2_048); assert_eq!(scale::QUARTER_M, 512); assert_eq!(2 * scale::QUARTER_M, 1_024); }