feat(simulation): dispatch RegionProfile layer in production (T-1032)

The D-239 carrier layer (T-1023/1024/1026) only ran in tests because every
production AnalyzeBody enqueue passed body_params: None. Wire the real path:

- New BodyParamsReader (server/src/atlas/body_params_reader.rs): read-only
  systems.db reader, joins bodies -> star_systems (LEFT JOIN) for the climate/
  tectonic inputs. SQL verified against systems-schema.sql. All fields Option,
  NULLs handled; tectonic_activity absent from schema -> None (derives from
  planet_class). 5 unit tests.
- layer_proxy.rs: on cache miss, read the body's params and pass
  Some(Box::new(..)). On read error, warn + fall back to None (cascade stops at
  Settlement, no panic) — graceful degradation.
- plugin.rs / main.rs: register BodyParamsReaderResource (CityContextReader
  pattern) and thread it through serve_atlas_requests.

BodyWorldState.regions now populates for real bodies in the D-206 background
pass. End-to-end tests cover wired (regions populated) + unwired (empty) paths.

cargo test 1504 pass, clippy -D warnings clean, fmt clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-08 12:28:01 +02:00
co-authored by Claude Opus 4.8
parent a516b06de9
commit 1887c886ef
5 changed files with 581 additions and 7 deletions
+18
View File
@@ -215,6 +215,24 @@ fn main() {
),
}
// Body physical params reader for RegionProfile carrier layer (T-1032, D-239 §1):
// reads hydrosphere / atmosphere / planet_class / orbital_period_days /
// axial_tilt_deg / spectral_class / star_type on a cache miss so the Rayon
// cascade work item stays DB-free (D-225 pattern).
match settled_reach_server::atlas::body_params_reader::BodyParamsReader::open(&systems_db_path)
{
Ok(reader) => {
tracing::info!("Body params reader opened: {:?}", systems_db_path);
app.insert_resource(
settled_reach_server::atlas::body_params_reader::BodyParamsReaderResource(reader),
);
}
Err(e) => tracing::warn!(
"Body params reader unavailable ({}). RegionProfile layer will be skipped.",
e
),
}
// Initialize SQLite settings store (#627).
// Path: alongside save files in the server's working directory.
let settings_path = std::path::PathBuf::from("settings.db");