feat(simulation): run Layer-3 settlement placement in the runtime cascade (#955)

Wire the existing D-211 attractor-matching engine into the live
generation cascade so settlements are placed in-game, not just in tests.

- CityContextReader::read_body_settlements reads a body's settlements
  from atlas_city_names (ordered by id for determinism). NULL
  settlement_class defaults to PopulationBudget, not NameLocked: the
  class is NULL until placement runs, and NameLocked would force every
  settlement Tier-A in match_cities and collapse population tiering
  (D-211). NULL economic_role falls back to residential.
- The AnalyzeBody work item carries the body's Vec<CityRecord>, and
  run_work_item now runs up_to Settlement (was Topography). A body with
  no settlements yields empty placements at negligible cost.
- The atlas layer proxy reads settlements on a cache miss and pins them
  onto the work item, keeping the Rayon task DB-free (D-225). A read
  failure is non-fatal: log and place no cities (Layer 1 still runs).
  Threaded through a new CityContextReaderResource Bevy resource opened
  in main.rs, mirroring BodySourceResolverResource.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-03 17:14:18 +02:00
co-authored by Claude Opus 4.8
parent f748b017cb
commit e2787fbfb1
5 changed files with 227 additions and 8 deletions
+17
View File
@@ -198,6 +198,23 @@ fn main() {
),
}
// Settlement reader for Layer-3 placement (#955): reads a body's settlements
// from systems.db on a cache miss so the cascade work item stays DB-free.
match settled_reach_server::atlas::city_context_reader::CityContextReader::open(
&systems_db_path,
) {
Ok(reader) => {
tracing::info!("City context reader opened: {:?}", systems_db_path);
app.insert_resource(
settled_reach_server::atlas::city_context_reader::CityContextReaderResource(reader),
);
}
Err(e) => tracing::warn!(
"City context reader unavailable ({}). Settlements will not be placed.",
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");