test(simulation): walk/paint agreement invariant pinned on the live Quarter mouth window (not-a-bug determination)
The apparent course-over-drawn-water contradiction resolved to two reconciliation errors, neither in production: (1) the probe's first reconstruction bypassed the request layer's wire clamp (Quarter n=32 serves as n=16 — build_district_window_layer trusts n verbatim by doc); (2) the lead's capture read overestimated — the window frames only the estuarine tail of a 213-station course (178 land stations out of frame upstream; the visible water run is genuine Lake/ OpenOcean paint, RGB-verified against MORPHOLOGY_RGB_OPAQUE x elevation-lightness) and the terminus sits ~240m from the painted land->water crossing, not tens of km. Walk and paint agree at every instrumented position (zero flip-flops across the monotonic 178-land/ 35-water station sequence). New permanent test reproduces the exact live window (real GJ380c + systems.db params, district (13195,-2383), Quarter, clamped n=16; asserts 44 pts + Mouth as identity) and pins the terminus-lands-in-painted-water invariant mechanism-agnostically; revert-verified with an injected 500km positional slip. Probe deleted. cargo test --lib 1878/1878. Tickets: T-1170 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -3236,6 +3236,142 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// **T-1170 live GJ380c/Lendel reconciliation dossier (coordinator's
|
||||||
|
/// request) — walk/paint agreement invariant, pinned permanently.**
|
||||||
|
///
|
||||||
|
/// Live capture at GJ380c Quarter n=32 (server-clamped to n=16 — see
|
||||||
|
/// below), district (13195,-2383), reported the ENTIRE visible course
|
||||||
|
/// (44 wire points, `terminus=Mouth`) painting as water tones, with the
|
||||||
|
/// resolved terminus apparently landing deep in open water. Investigated
|
||||||
|
/// via an instrumented reproduction of `resolve_mouth_terminus`'s exact
|
||||||
|
/// walk (temporary probe, deleted after this landed) — DETERMINATION:
|
||||||
|
/// this is not a bug. The window's world-metre rect
|
||||||
|
/// (`x∈[27006976,27039744]`) simply sits ~60+ km from the course's
|
||||||
|
/// upstream land anchor and close to the resolved coastal terminus, so
|
||||||
|
/// the overwhelming majority of what's IN FRAME is genuinely
|
||||||
|
/// Lake/OpenOcean-painted — confirmed by hand-computing the exact RGB
|
||||||
|
/// (`MORPHOLOGY_RGB_OPAQUE` × elevation lightness) for the coordinator's
|
||||||
|
/// sampled pixel colors, which matched Lake/OpenOcean to the rounding
|
||||||
|
/// digit. The walk's own station-by-station classification (178 land
|
||||||
|
/// stations, then 35 water stations, ZERO flip-flops) is perfectly
|
||||||
|
/// monotonic and the resolved terminus sits ~240 m from the true
|
||||||
|
/// land→water crossing — not "tens of km past coast".
|
||||||
|
///
|
||||||
|
/// **The invariant this test pins, since the raw "N consecutive water
|
||||||
|
/// stations" framing turned out not to be the real signal:** the wire
|
||||||
|
/// course's resolved `Mouth` terminus point must land in a window CELL
|
||||||
|
/// whose PAINTED morphology is genuinely `OpenOcean`/`Lake` (never a
|
||||||
|
/// land-family zone) — i.e. the termination walk and the window's own
|
||||||
|
/// per-cell classification, sampled independently via the SAME
|
||||||
|
/// `derive_at_metres` call, must agree at the terminus. This is the
|
||||||
|
/// walk/paint reconciliation the dossier was asked to determine, made
|
||||||
|
/// permanent and mechanism-agnostic (it would catch a REAL divergence —
|
||||||
|
/// wrap slip, sign flip, station-order bug — regardless of which
|
||||||
|
/// specific window happens to expose it).
|
||||||
|
#[test]
|
||||||
|
fn mouth_terminus_lands_in_a_painted_water_cell_on_real_gj380c() {
|
||||||
|
use crate::atlas::body_params_reader::BodyParamsReader;
|
||||||
|
use crate::atlas::drainage;
|
||||||
|
use crate::atlas::heightmap::{load_heightmap_png, GRID_H, GRID_W};
|
||||||
|
use crate::atlas::river_course;
|
||||||
|
|
||||||
|
let manifest = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||||
|
let src = manifest.join("../wiki/star-systems/GJ-380/bodies/GJ380c/heightmap.png");
|
||||||
|
let systems_db = manifest.join("data/systems.db");
|
||||||
|
|
||||||
|
let params_reader = BodyParamsReader::open(&systems_db).expect("open committed systems.db");
|
||||||
|
let params = params_reader
|
||||||
|
.read_body_params("GJ380c")
|
||||||
|
.expect("read GJ380c body params from committed systems.db");
|
||||||
|
|
||||||
|
let heightmap = load_heightmap_png(&src, "GJ380c", 0.3).expect("decode GJ380c heightmap");
|
||||||
|
let working = if heightmap.width > GRID_W || heightmap.height > GRID_H {
|
||||||
|
heightmap.downsample(GRID_W, GRID_H)
|
||||||
|
} else {
|
||||||
|
heightmap
|
||||||
|
};
|
||||||
|
|
||||||
|
let dr = drainage::analyze(&working.data, working.width, working.height, working.sea_level);
|
||||||
|
let ta = crate::atlas::features::TerrainAnalysis::analyze(&working, &dr);
|
||||||
|
let rn = &dr.river_network;
|
||||||
|
|
||||||
|
// The exact real mouth cell from the live capture.
|
||||||
|
let target_px: (u16, u16) = (63, 354);
|
||||||
|
let edges = river_course::build_edges(rn);
|
||||||
|
let edge = edges
|
||||||
|
.iter()
|
||||||
|
.find(|e| e.edge_id == river_course::pack_cell_id(target_px))
|
||||||
|
.expect("GJ380c must have a Mouth edge at the live-captured cell");
|
||||||
|
assert_eq!(edge.edge_id, 4129122, "must be the same edge the live capture reported");
|
||||||
|
|
||||||
|
let seed = SeedChain::for_body(0, "GJ380c"); // production default world_seed
|
||||||
|
let climate = crate::atlas::district_profile::ClimateConstants::default();
|
||||||
|
|
||||||
|
// The EXACT live window shape: district (13195,-2383), REQUESTED
|
||||||
|
// n=32, Quarter granularity — server-side clamps n=32 down to n=16
|
||||||
|
// at Quarter granularity (`clamp_window_n`: cap_n = sqrt(4096)/4 =
|
||||||
|
// 16), which `build_district_window_layer` does NOT do itself (it
|
||||||
|
// trusts n verbatim by its own doc) — the request-handling layer
|
||||||
|
// (`handle_atlas_request`) applies `clamp_window_n_v2` BEFORE
|
||||||
|
// calling it. Pass the already-clamped n=16 here to match what a
|
||||||
|
// real client request actually receives.
|
||||||
|
let center = (13195, -2383);
|
||||||
|
let clamped_n = 16u32;
|
||||||
|
|
||||||
|
let layer = build_district_window_layer(
|
||||||
|
seed,
|
||||||
|
"GJ380c",
|
||||||
|
¶ms,
|
||||||
|
&ta,
|
||||||
|
rn,
|
||||||
|
center,
|
||||||
|
clamped_n,
|
||||||
|
&climate,
|
||||||
|
WindowGranularity::Quarter,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
let wire = layer
|
||||||
|
.courses
|
||||||
|
.iter()
|
||||||
|
.find(|c| c.edge_id == edge.edge_id)
|
||||||
|
.expect("edge 4129122 must ship in this window, matching the live capture");
|
||||||
|
assert_eq!(
|
||||||
|
wire.points.len(),
|
||||||
|
44,
|
||||||
|
"point count must match the live capture exactly, confirming this IS the \
|
||||||
|
reported window"
|
||||||
|
);
|
||||||
|
assert_eq!(wire.terminus, CourseTerminus::Mouth);
|
||||||
|
|
||||||
|
// The invariant: the terminus point's containing Quarter cell, read
|
||||||
|
// from THIS SAME layer's own painted `morphology` array, must be
|
||||||
|
// OpenOcean or Lake.
|
||||||
|
let side = WindowGranularity::Quarter.cell_grid_side(clamped_n);
|
||||||
|
let half = side / 2;
|
||||||
|
let step_m = WindowGranularity::Quarter.spacing_m();
|
||||||
|
let center_world_m = (
|
||||||
|
center.0 as f64 * DISTRICT_M as f64,
|
||||||
|
center.1 as f64 * DISTRICT_M as f64,
|
||||||
|
);
|
||||||
|
let (tx, ty) = *wire.points.last().unwrap();
|
||||||
|
let col = ((tx as f64 - center_world_m.0) / step_m + half as f64).round() as i32;
|
||||||
|
let row = ((ty as f64 - center_world_m.1) / step_m + half as f64).round() as i32;
|
||||||
|
assert!(
|
||||||
|
row >= 0 && row < side && col >= 0 && col < side,
|
||||||
|
"terminus point ({tx},{ty}) must map to an in-window cell, got (row={row},col={col})"
|
||||||
|
);
|
||||||
|
let cell_idx = (row * side + col) as usize;
|
||||||
|
let painted = layer.morphology[cell_idx];
|
||||||
|
assert!(
|
||||||
|
painted == crate::simulation::generator::MorphologyZone::OpenOcean as u8
|
||||||
|
|| painted == crate::simulation::generator::MorphologyZone::Lake as u8,
|
||||||
|
"walk/paint DIVERGENCE: the resolved Mouth terminus ({tx},{ty}) landed in a cell \
|
||||||
|
painted with morphology discriminant {painted} (not OpenOcean=0 or Lake=1) — the \
|
||||||
|
termination walk's own water verdict must agree with the window's painted \
|
||||||
|
classification at the SAME position"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// Clamped-window edge: `n = 1` is the minimum valid window (a single
|
/// Clamped-window edge: `n = 1` is the minimum valid window (a single
|
||||||
/// district) — no panic, no empty output, exactly one cell per array.
|
/// district) — no panic, no empty output, exactly one cell per array.
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
Reference in New Issue
Block a user