refactor(simulation): rename DistrictSkeleton→QuarterSkeleton per D-222 (#950)

D-222 renamed the 512m generation cell from District to Quarter (District
is now a new 2048m tier above it). Align the generation skeleton code to
the canonical vocabulary. Pure naming — no behavior change; all 1296 lib
tests + integration tests pass unchanged.

Renamed (spatial-cell identifiers):
- DistrictSkeleton → QuarterSkeleton, DistrictWorldState → QuarterWorldState
- DistrictId → QuarterId, DistrictContext/DistrictBoundaries → Quarter*
- field district_id → quarter_id, district_type → quarter_type
- BodyWorldState.districts map → .quarters
- generate_skeleton → generate_quarter_skeleton

Deliberately left as-is (these name functional ZONING, not the spatial
tier — orthogonal to D-222): DistrictType, DistrictLayoutMode, the
district_mix module (DistrictMix/compute_district_mix), and the
GenWorkItem::GenerateSkeleton / GenCompletion::SkeletonGenerated variants.

Also aligned the perception "sim tile" → "subtile" vocabulary (D-222:
Subtile = 0.5m) in decisions/perception.md and the generation-cascade code
comments. Historical D-066/D-094/D-201/D-220 decision bodies keep their
existing D-222 amendment notes (not rewritten in place); the public
max_offset_sim_tiles fn name is unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-05 13:06:44 +02:00
co-authored by Claude Opus 4.8
parent f7a21c6b8d
commit c71c26a1a6
10 changed files with 108 additions and 97 deletions
+21 -21
View File
@@ -12,7 +12,7 @@
//!
//! **Work item types (D-206):**
//! - `AnalyzeBody`: D8 drainage + attractor extraction for a body.
//! - `GenerateSkeleton`: Phase 1 DistrictSkeleton for a city.
//! - `GenerateSkeleton`: Phase 1 QuarterSkeleton for a city.
//! - `FillChunk`: Phase 2 chunk fill for a pre-loaded district.
//!
//! Completion events are delivered to the main thread via
@@ -31,9 +31,9 @@ use crate::atlas::attractor_matching::CityRecord;
use crate::atlas::body_world_state::BodyWorldState;
use crate::atlas::cascade::{run_cascade_from_heightmap, CascadeLayer};
use crate::atlas::heightmap::{load_heightmap_png, GRID_H, GRID_W};
use crate::atlas::skeleton_gen::generate_skeleton;
use crate::atlas::skeleton_gen::generate_quarter_skeleton;
use crate::seed::SeedChain;
use crate::simulation::generator::{CityGenerationContext, DistrictWorldState};
use crate::simulation::generator::{CityGenerationContext, QuarterWorldState};
// ---------------------------------------------------------------------------
// Priority
@@ -73,7 +73,7 @@ pub enum GenWorkItem {
/// (#955); empty if the body has no settlements (cascade stops at Layer 1).
cities: Vec<CityRecord>,
},
/// Generate a Phase 1 DistrictSkeleton for this city.
/// Generate a Phase 1 QuarterSkeleton for this city.
///
/// `context` is the D-199 economic read-set pre-resolved at dispatch time.
/// All 6 required fields must be populated before this item is submitted
@@ -83,11 +83,11 @@ pub enum GenWorkItem {
/// `body_id` routes the resulting `SkeletonGenerated` completion into the
/// correct `BodyWorldState` cache entry (D-230).
///
/// `district_id` is the stable content-addressable id for the generated
/// `quarter_id` is the stable content-addressable id for the generated
/// district (keyed by city position + world seed).
///
/// `economic_role`, `population`, and `founding_age_years` are D-199 fields
/// carried alongside the context because `generate_skeleton` accepts them as
/// carried alongside the context because `generate_quarter_skeleton` accepts them as
/// separate parameters (its signature is not changed by this ticket).
GenerateSkeleton {
city_id: u64,
@@ -95,17 +95,17 @@ pub enum GenWorkItem {
/// D-199 economic read-set + all other context fields.
context: Box<CityGenerationContext>,
/// Stable content-addressable district id (D-194/D-230).
district_id: u64,
quarter_id: u64,
/// District-level seed chain (D-224).
chain: SeedChain,
// D-199 raw fields passed to generate_skeleton separately.
// D-199 raw fields passed to generate_quarter_skeleton separately.
economic_role: String,
population: i64,
founding_age_years: u32,
},
/// Pre-fill a chunk in an existing district.
FillChunk {
district_id: u64,
quarter_id: u64,
block_pos: (u32, u32),
},
}
@@ -135,14 +135,14 @@ pub enum GenCompletion {
SkeletonGenerated {
city_id: u64,
/// The body this skeleton belongs to — used to route state into
/// `BodyWorldState.districts` (D-230).
/// `BodyWorldState.quarters` (D-230).
body_id: String,
/// District-level world state (skeleton + block tags) produced by the plan phase (D-230).
/// Boxed to keep `GenCompletion` variant sizes balanced (D-230 skeleton is ~2.7 KB).
state: Box<DistrictWorldState>,
state: Box<QuarterWorldState>,
},
ChunkFilled {
district_id: u64,
quarter_id: u64,
block_pos: (u32, u32),
},
/// Work item failed — body_id or city_id for logging.
@@ -385,7 +385,7 @@ fn run_work_item(item: &GenWorkItem) -> GenCompletion {
city_id,
body_id,
context,
district_id,
quarter_id,
chain,
economic_role,
population,
@@ -394,29 +394,29 @@ fn run_work_item(item: &GenWorkItem) -> GenCompletion {
// Build the Phase 1 skeleton from the pre-resolved D-199 context.
// `economic_role`, `population`, and `founding_age_years` are the
// D-199 raw fields carried alongside the context because
// `generate_skeleton` accepts them as separate parameters.
let skeleton = generate_skeleton(
// `generate_quarter_skeleton` accepts them as separate parameters.
let skeleton = generate_quarter_skeleton(
context,
*population,
economic_role,
*district_id,
*quarter_id,
*founding_age_years,
*chain,
);
GenCompletion::SkeletonGenerated {
city_id: *city_id,
body_id: body_id.clone(),
state: Box::new(DistrictWorldState {
state: Box::new(QuarterWorldState {
skeleton,
block_tags: std::collections::BTreeMap::new(),
}),
}
}
GenWorkItem::FillChunk {
district_id,
quarter_id,
block_pos,
} => GenCompletion::ChunkFilled {
district_id: *district_id,
quarter_id: *quarter_id,
block_pos: *block_pos,
},
}
@@ -493,7 +493,7 @@ mod tests {
dominant_bulk_class: BulkClass::NonPhysical,
dominant_production_ubiquity: ProductionUbiquity::Common,
}),
district_id: city_id * 10,
quarter_id: city_id * 10,
chain: SeedChain::root(42 + city_id),
economic_role: "service_mixed".to_string(),
population: 500_000,
@@ -590,7 +590,7 @@ mod tests {
let q = make_queue();
q.submit(
GenWorkItem::FillChunk {
district_id: 99,
quarter_id: 99,
block_pos: (0, 0),
},
GenPriority::High,