feat(simulation): T-1152 server half — WindowGranularity enum, derive_orbital_at_metres, Region rung on the same carrier

R1 measured first: a capped Region tile through the real production path
(build_district_window_layer + T-1151 par_iter) at the 64x64 wire cap
costs 0.40-0.48ms — faster than the shipped district n=64 window, so
Jeroen's progressive capped-density tiling ruling is comfortably
interactive on-demand. Raw orbital derive ~0.9µs/cell (~2.3x faster than
full derive; region_baseline dominates, not invent_primitives).

R5 redesign: WindowGranularity enum (Quarter/District/Region), serde
named-variant per the RoadNodeKind precedent, spacing from D-243 scale::
constants — the single source of truth. Additive serde-default
window_granularity_v2 request field (None = legacy u32 path; v2 wins when
Some); DistrictWindowLayer.granularity_v2 always echoed. Legacy u32 echo
for Region uses reserved WINDOW_GRANULARITY_REGION_KEY = u32::MAX (never
a legal input) so the old slot cannot lie about aliasing. Cache and
coalescing keys carry the enum itself (Ord by declaration order, D-010).

n stays district-extent at every rung; Region's cell grid is a DIVISION
(round(n/100), min 1) with its own per-axis ceiling
DISTRICT_WINDOW_MAX_N_REGION=6400 and a bounded halving-loop clamp (no
closed form under the rounding division — the client mirror must
replicate the loop).

derive_orbital_at_metres: bilinear envelope reads + region_baseline
temperature, NO invent_primitives (proven by test — slope_q pinned 0),
routed through the shared build_district_profile classification tail so
the existing colorizer family renders orbital cells unchanged. R2
stepped-categorical behavior documented at the function, not implied.

Region aliasing + clamp/echo tests mirror the T-1150 discipline. 1813
lib tests green; clippy clean; fixture regenerated (254->278 bytes, new
echoed field).
This commit is contained in:
2026-07-22 10:35:37 +02:00
parent 2a4597e108
commit d356b09926
9 changed files with 1155 additions and 133 deletions
+30 -42
View File
@@ -34,7 +34,9 @@ use crate::atlas::cascade::{run_cascade_from_heightmap, CascadeLayer};
use crate::atlas::district_profile::{BodyParams, ClimateConstants, DistrictPos};
use crate::atlas::features::TerrainAnalysis;
use crate::atlas::heightmap::{load_heightmap_png, GRID_H, GRID_W};
use crate::atlas::layer_proxy::{build_district_window_layer, DistrictWindowLayer};
use crate::atlas::layer_proxy::{
build_district_window_layer, DistrictWindowLayer, WindowGranularity,
};
use crate::atlas::shell::{fill_chunk, FilledChunk};
use crate::atlas::skeleton_gen::{assign_all_block_tags, generate_quarter_skeleton};
use crate::atlas::trait_catalog_reader::ExteriorCatalog;
@@ -208,11 +210,18 @@ pub enum GenWorkItem {
/// before this item is built — never trusted from the wire again here.
center: DistrictPos,
n: u32,
/// Derivation granularity (T-1150) — `WINDOW_GRANULARITY_DISTRICT` (1)
/// or `WINDOW_GRANULARITY_QUARTER` (4). Already resolved via
/// `resolve_window_granularity` by the caller.
granularity: u32,
/// Derivation granularity (T-1150, widened T-1152 to the full
/// [`WindowGranularity`] vocabulary — `District`/`Quarter` (finer)
/// plus `Region` (coarser, T-1152)). Already resolved via
/// `resolve_window_granularity_v2` by the caller — this is a
/// concrete rung, never a raw wire value.
granularity: WindowGranularity,
/// Octave cutoff in whole metres (T-1149/T-1150), `0` = no cutoff.
/// Meaningless for `granularity: Region` (`derive_orbital_at_metres`
/// never calls the octave-scatter path this cuts off) but still
/// carried and echoed uniformly — see `derive_orbital_at_metres`'s
/// doc for why the field is harmless-but-unused there, not
/// special-cased away.
min_wl_m: u32,
},
}
@@ -227,13 +236,17 @@ impl GenWorkItem {
/// Coalescing key for `DeriveWindow` items only — `(connection, body,
/// granularity)` (T-1150, design doc §3 [SOFT] recommendation, extending
/// T-1137's `(connection, body)`). `granularity` is part of the key so an
/// in-flight district-spacing (granularity 1) pan-burst is never
/// superseded by an unrelated quarter-spacing (granularity 4) request for
/// the same connection+body, and vice versa — the two rungs are separate
/// in-flight derives, not competing updates to the same one.
/// T-1137's `(connection, body)`; widened T-1152 to carry the full
/// [`WindowGranularity`] enum rather than the legacy `u32`, so `Region`
/// occupies its own coalescing slot exactly like `District`/`Quarter` do
/// — this is one of the five T-1150 touch points the R5 redesign must
/// carry the new representation through). `granularity` is part of the
/// key so an in-flight district-spacing pan-burst is never superseded by
/// an unrelated quarter- or region-spacing request for the same
/// connection+body, and vice versa — every rung is a separate in-flight
/// derive, not a competing update to the same one.
/// `None` for every other variant (they don't coalesce this way).
pub fn window_supersede_key(&self) -> Option<(ConnectionId, &str, u32)> {
pub fn window_supersede_key(&self) -> Option<(ConnectionId, &str, WindowGranularity)> {
if let GenWorkItem::DeriveWindow {
body_id,
conn_id,
@@ -1150,19 +1163,14 @@ mod tests {
/// coalescing tests can exercise the granularity axis of
/// `window_supersede_key()` without a second near-duplicate helper.
fn derive_window(body_id: &str, conn_id: ConnectionId, center: DistrictPos) -> GenWorkItem {
derive_window_at(
body_id,
conn_id,
center,
crate::atlas::layer_proxy::WINDOW_GRANULARITY_DISTRICT,
)
derive_window_at(body_id, conn_id, center, WindowGranularity::District)
}
fn derive_window_at(
body_id: &str,
conn_id: ConnectionId,
center: DistrictPos,
granularity: u32,
granularity: WindowGranularity,
) -> GenWorkItem {
GenWorkItem::DeriveWindow {
body_id: body_id.to_string(),
@@ -1316,21 +1324,11 @@ mod tests {
let conn = ConnectionId(9);
q.submit_window(
derive_window_at(
"GranBody",
conn,
(0, 0),
crate::atlas::layer_proxy::WINDOW_GRANULARITY_DISTRICT,
),
derive_window_at("GranBody", conn, (0, 0), WindowGranularity::District),
GenPriority::Immediate,
);
q.submit_window(
derive_window_at(
"GranBody",
conn,
(0, 0),
crate::atlas::layer_proxy::WINDOW_GRANULARITY_QUARTER,
),
derive_window_at("GranBody", conn, (0, 0), WindowGranularity::Quarter),
GenPriority::Immediate,
);
assert_eq!(
@@ -1352,21 +1350,11 @@ mod tests {
let conn = ConnectionId(11);
q.submit_window(
derive_window_at(
"SameGranBody",
conn,
(0, 0),
crate::atlas::layer_proxy::WINDOW_GRANULARITY_QUARTER,
),
derive_window_at("SameGranBody", conn, (0, 0), WindowGranularity::Quarter),
GenPriority::Immediate,
);
q.submit_window(
derive_window_at(
"SameGranBody",
conn,
(5, 5),
crate::atlas::layer_proxy::WINDOW_GRANULARITY_QUARTER,
),
derive_window_at("SameGranBody", conn, (5, 5), WindowGranularity::Quarter),
GenPriority::Immediate,
);
assert_eq!(