refactor(simulation): rename carrier RegionProfile->DistrictProfile + re-scale to the D-243 ladder (T-1077)

Phase 2 of the D-243 re-scale. The ~1km carrier is renamed and re-scaled to
the 2km district, and every consumer reads scale from the canonical scale.rs
instead of a local literal.

- region_profile.rs -> district_profile.rs; RegionProfile -> DistrictProfile,
  RegionPos -> DistrictPos (re-exported from scale::DistrictPos), derive_*_regions
  -> derive_*_districts, across all 10 consumers + the derivation harness.
- chunk_context now references scale:: for the carrier cell: district 1024m -> 2048m,
  shift 4 -> 5 (CHUNK_DISTRICT_SHIFT). This caught a real latent bug: the seed-district
  index used a literal '>> 4' while the anchor used the constant, so same-district
  chunks could derive different anchors — now both use scale::CHUNK_DISTRICT_SHIFT.
- derivation_harness scale literals ('>> 4', '* 1024', '0..16') converted to
  scale:: constants (the same drift the canonical source eliminates). Believability
  tests pass at 2km; the voxel determinism golden re-pinned (anchors moved with the
  re-scale — deterministic, intended).

Full suite + clippy --all-targets -D warnings green. The district DERIVATION still
tiles the heightmap at 8 cells (the old coarse path); replacing it with on-demand
heightmap interpolation + detail-scatter is phase 3.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-14 22:53:18 +02:00
co-authored by Claude Opus 4.8
parent 38054d4b12
commit b3b5bfc2e3
12 changed files with 945 additions and 886 deletions
+23 -11
View File
@@ -1,9 +1,9 @@
//! Pre-dispatch reader for body physical parameters (T-1032, D-239 §1).
//!
//! Reads the columns needed to construct a [`BodyParams`] for the RegionProfile
//! Reads the columns needed to construct a [`BodyParams`] for the DistrictProfile
//! carrier layer from `systems.db` at `AnalyzeBody` enqueue time. This keeps
//! the Rayon work item DB-free while supplying the climate/tectonic inputs
//! required by `derive_all_regions`.
//! required by `derive_all_districts`.
//!
//! **D-240:** orbit/star fields (`orbital_period_days`, `axial_tilt_deg`,
//! `spectral_class`, `star_type`) are non-canonical placeholder data — they are
@@ -23,8 +23,8 @@
//!
//! `tectonic_activity` is **not** in the current schema; `BodyParams.tectonic_activity`
//! is left `None` so the derivation falls back to `planet_class` as documented
//! on the struct. The per-region fields `region_latitude_deg` and `elevation_km`
//! are set by `derive_all_regions` / `derive_region_profile`, not here; they
//! on the struct. The per-district fields `district_latitude_deg` and `elevation_km`
//! are set by `derive_all_districts` / `derive_district_profile`, not here; they
//! remain at their struct defaults (0.0) from this reader.
//!
//! Read-only `systems.db` access follows the same pattern as
@@ -37,7 +37,7 @@ use std::sync::{Arc, Mutex};
use rusqlite::{Connection, OpenFlags};
use thiserror::Error;
use crate::atlas::region_profile::BodyParams;
use crate::atlas::district_profile::BodyParams;
// ---------------------------------------------------------------------------
// Error type
@@ -119,9 +119,9 @@ impl BodyParamsReader {
planet_class,
// tectonic_activity not in schema — leave None.
tectonic_activity: None,
// Per-region fields are set by derive_all_regions / derive_region_profile,
// Per-district fields are set by derive_all_districts / derive_district_profile,
// not at the body level. Leave at struct defaults (0.0).
region_latitude_deg: 0.0,
district_latitude_deg: 0.0,
elevation_km: 0.0,
body_radius_km,
}),
@@ -185,7 +185,13 @@ mod tests {
conn.execute(
"INSERT INTO bodies (body_id, hydrosphere, atmosphere, planet_class, body_radius_km)
VALUES (?1, ?2, ?3, ?4, ?5)",
rusqlite::params![body_id, hydrosphere, atmosphere, planet_class, body_radius_km],
rusqlite::params![
body_id,
hydrosphere,
atmosphere,
planet_class,
body_radius_km
],
)
.expect("insert body");
@@ -209,8 +215,8 @@ mod tests {
assert_eq!(params.atmosphere.as_deref(), Some("breathable"));
assert_eq!(params.planet_class.as_deref(), Some("temperate"));
assert_eq!(params.body_radius_km, Some(6371.0));
// Per-region fields always start at 0.0 from the reader.
assert_eq!(params.region_latitude_deg, 0.0);
// Per-district fields always start at 0.0 from the reader.
assert_eq!(params.district_latitude_deg, 0.0);
assert_eq!(params.elevation_km, 0.0);
// tectonic_activity not in schema → None.
assert!(params.tectonic_activity.is_none());
@@ -238,7 +244,13 @@ mod tests {
#[test]
fn read_is_deterministic() {
let db = make_test_db("GJ4d", Some("ice"), Some("thin"), Some("frozen"), Some(3389.5));
let db = make_test_db(
"GJ4d",
Some("ice"),
Some("thin"),
Some("frozen"),
Some(3389.5),
);
let reader = BodyParamsReader::open(&db).expect("open");
let p1 = reader.read_body_params("GJ4d").expect("first read");
let p2 = reader.read_body_params("GJ4d").expect("second read");