--- title: "Round 4 — Burnelli-Sheldon: Economics Integration for Planet-Down Cascade" description: "Economics domain requirements for the planet-down brief: layer entry points, determinism split, dynamic settlement latency, and per-layer DB field mapping" type: workshop status: active workshop: generation-cascade agent: burnelli-sheldon round: 4 created: 2026-04-30 --- # Round 4 — Burnelli-Sheldon: Economics Integration for Planet-Down Cascade The lead has reframed the cascade as planet-down. This changes the framing, not the economics. My job this round is to map my accepted contributions from Round 3 into the new four-layer model and answer the specific questions the lead flagged. --- ## 1. Where Does Economic Data First Enter? **Answer: Layer 1, weakly. Layer 2, in full.** ### Layer 1 — Empty World (weak influence) The lead defines Layer 1 as "natural world, no civilization." That is exactly right. Economics does not shape terrain. But there is one legitimate economics-adjacent influence at this layer: **biome quality distribution**. A planet was settled because it was worth settling. The body's `economic_role` in systems.db is not a cause of its terrain — it is the *outcome* of someone deciding this terrain was worth exploiting. That selection creates a plausibility constraint: an `agricultural` world had to have arable soil; an `extraction` world had to have accessible ore. If the Layer 1 generator produces a volcanic hellscape for a body with `economic_role = agricultural`, the world is self-contradictory. The fix is not to have economics drive terrain geometry. It is to use `bodies.economic_role` + `bodies.planet_class` as a **biome probability prior** in the sub-biome refinement step: | economic_role | Sub-biome quality bias | |---|---| | agricultural | More temperate/arable cells, gentler slopes, fewer badlands | | extraction / mining | More rugged terrain, higher mineral-rich designations | | research | More terrain variety (observable geography = research value) | | transit | More navigable terrain, natural passes and harbors | | frontier | Unconstrained — hostile terrain is plausible | | manufacturing | Near-neutral; manufacturing follows settlement, not terrain | This is a prior, not a hard constraint. The biome generator can still produce a difficult agricultural world (thin soil, reclamation history) — but the prior nudges it toward plausibility. If this is too complicated for Layer 1, the alternative is simply to trust that `planet_class` encodes this well enough already (`temperate` planets are already the natural home of `agricultural` worlds) and leave Layer 1 fully physics-driven. Either approach is defensible. I flag it because the contradiction risk is real and cheap to address at Layer 1 rather than later. **Economic fields at Layer 1:** - `bodies.economic_role` — biome probability prior (optional) - `bodies.planet_class`, `bodies.atmosphere`, `bodies.surface_gravity` — primary physical inputs ### Layer 2 — Population Overlay (primary entry point) This is where economics enters in full force and where my Round 3 work connects most directly. The lead's description — "economics onto geography, settlements anchor where geography supports them, felled forests → farmland, road/rail networks, anchored by wiki population counts" — is precisely what the economics data enables. The `atlas_cities` table provides wiki-anchored city positions and populations. The `bodies` table provides the economic character. The `corp_presence` table shows which corporations cluster where. The `atlas_roads` and `atlas_railroads` tables provide infrastructure. All of this is pre-computed and stored in systems.db. Layer 2 is not city-internal planning — it is the hinterland: what fills the space between cities. Economic role determines hinterland character: | economic_role | Hinterland fill | Notes | |---|---|---| | agricultural | Cleared farmland, irrigation networks, processing nodes | "Felled forests → farmland" lives here | | extraction | Access corridors, mining infrastructure, stockpile areas | Extends to resource deposit locations | | manufacturing | Industrial fringe, rail freight yards, supply zones | Follows logistics corridors | | transit | Dense road/rail, relay stations, fuel depots | The infrastructure IS the hinterland | | research | Exclusion zones, observatory sites, quiet buffer | Sparse, low-density | | service_mixed | Suburban residential spread, civic infrastructure | Generic low-density | **Economic fields at Layer 2 (full list):** From `bodies`: `economic_role`, `settlement_pattern`, `industrial_corridor`, `population`, `planet_class` From `atlas_*` tables: city positions and populations, road/rail presence, POI kinds From `system_economy`: `economic_tier` (infrastructure density), `economic_base_primary/secondary` From `system_gates`: `gate_connections` (trade route intensity → transport infrastructure density) From `corp_presence`: which corps operate here, `primary_operation` commodity Dynamic settlement triggers (see §3 below) are also evaluated at Layer 2. --- ## 2. The Determinism Rule — Layout vs. Appearance The lead's rule is economically clean and I agree with it completely: > Economic sim's rolling state affects RENDERING (prosperity, repair) NOT LAYOUT > (streets locked by seed). This is how real cities work. Detroit's street grid did not change when its industrial base collapsed. Buenos Aires' Palermo grid was not rezoned during financial crisis. The buildings aged and emptied; the streets persisted. Here is the full split as I see it: ### Seed-Locked (Layout) — Generated Once, Never Changed These are determined by `(world_seed + CityGenerationContext)` at generation time: - Street grid pattern and block geometry - Building footprints and lot parcels - District boundaries - Perimeter treatment type (Open / Fenced / Walled / Gated / Checkpoint) - Access point positions - Settlement positions — including LATENT settlements (see §3) - Corporate campus footprints (the campus exists even if the corp is failing) - Port infrastructure physical extent - Road quality tier (narrow_unpaved through boulevard) ### Economic-Sim-Dynamic (Appearance) — Updated at Runtime These are driven by the economic simulation's rolling state: - `prosperity_index` per district — the sim updates this; rendering reads it to choose tile variants - Building repair state — prosperity below threshold triggers decay tiles (ChunkMutations record explicit player damage; general decay is a rendering parameter) - Active vs. ghost status of latent settlements (see §3) - Corporate signage and branding presence — corp `health_metric` from `corp_financial_state` drives whether branded signage renders - Stockpile visibility in logistics districts — active trade → visible cargo tiles; depressed trade → empty yard tiles - Lighting state — prosperity floor affects illumination (powered vs. dark windows) ### The Key Insight: Prosperity Is a Render Parameter, Not a Tile Mutation The most important implication of this split is that `prosperity_index` should NOT be implemented as tile-level ChunkMutations for routine decay. It is a single float per district. The renderer reads it and applies a decay probability to tile selection. When prosperity drops from 0.6 to 0.3: - The streets don't change - The building footprints don't change - The tile SELECTION changes (cracked pavement variant instead of clean; boarded window instead of lit; rust on the facade) - This happens purely in the rendering path, with no world mutation ChunkMutations remain reserved for player-caused or explicit-event damage — a specific building explosion, a player-placed barricade. General economic decay is a render parameter. This distinction matters for performance: prosperity changes don't generate millions of tile mutations. ### The "Felled Forest → Farmland" Exception The lead specifically mentioned this as a Layer 2 dynamic. It seems to contradict the layout-lock rule. Reconciliation: "Felled forests → farmland" is **regional-scale land use** (Layer 2), not **city-scale tile layout** (Layer 4). The lock rule applies to city-internal geometry (streets, buildings). Regional land use — what biome category fills the hinterland between cities — CAN change as a Layer 2 update when economic conditions shift. Concretely: if the agriculture corp expands, new farmland clears adjacent to existing cities. This is a land-use tile change at biome-cell resolution (large tiles covering hectares), not a building-by-building tile mutation. The distinction: - Layer 2 regional land use: coarse-resolution, economics-driven, can update - Layer 4 city street/building layout: fine-resolution, seed-locked, never changes This is not a contradiction. It is a resolution boundary. --- ## 3. Dynamic Settlements in the Planet-Down Model In Round 3, I proposed four types of economically-triggered dynamic settlements: mining camps, trade route waypoints, agricultural dispersed nodes, and shadow economy nodes. The planet-down model changes how these work. ### The Latency Principle Under the determinism rule, settlement POSITIONS must be seed-locked at generation time. But economic conditions change — a mine depletes, a trade route shifts. The reconciliation is **latent settlements**: > The generator places ALL economically plausible settlement positions at Layer 2. > Whether each settlement is ACTIVE is determined by the economic sim's running state. > An inactive settlement exists spatially — as ruins, as empty structures, as cleared > ground — but it is dark, unmaintained, and depopulated. This is economically accurate. Ghost towns exist. The buildings are there; no one lives in them. The road to the closed mine still exists. ### How This Works Per Settlement Type **Mining camps:** - At Layer 2 generation: evaluate `corp_presence` against body. Every body with `economic_role IN ('extraction', 'mining')` and 2+ corps operating `metallic_ore` or `rare_minerals` gets N seed-derived camp positions (N = corp count / 2). - Active status at runtime: `corp_financial_state.health_metric > 0.4` for the operating corp → camp is active (populated, lit, maintained). Corp distressed or dissolved → camp becomes ghost state (dark, decayed render variants). - Why this is seed-locked: the geological deposit that caused the camp to be placed is geological fact, not economic contingency. The deposit doesn't move when the corp fails; the camp's position doesn't either. **Trade route waypoints:** - At Layer 2 generation: `atlas_roads` entries with `point_count > 5` (long roads) get a seed-derived waypoint at the geometric midpoint. - Active status: `gate_links` trade flow proxy (nearby system still connected and populated) → active. If the terminal system is abandoned, the waypoint becomes a ruin. - Seed-locked because: the road was built; the physical clearing was made. Even abandoned trade routes leave ruins. **Agricultural dispersed nodes:** - At Layer 2 generation: `settlement_pattern IN ('dispersed', 'dispersed_rural')` AND `economic_role = 'agricultural'` → scatter farm cluster positions at interval derived from `1/economic_tier`. - Active status: `corp_presence` corp with `primary_operation = 'agricultural_produce'` health_metric → active or fallow. - Fallow farms look different from ghost towns: cleared land, overgrown structures, but the clearing and track remain. These are the richest "economic decay visible in the world" cases. **Shadow economy nodes:** - At Layer 2 generation: `system_fiscal.collection_efficiency < 0.6` on the parent system → place one informal settlement adjacent to the largest atlas city, position seed-derived. - Active status: shadow viability is a structural condition, not a corp health metric. If collection_efficiency recovers (enforcement crackdown), the settlement is still there but its character changes (from busy informal market to quiet derelict cluster). ### What This Means for the Layer 2 Implementation Layer 2 must query the full economics dataset and produce: 1. All atlas-city hinterland characterizations 2. All latent dynamic settlement positions (with type tag and activating corp/condition) 3. Regional land use grid (farmland, industrial fringe, wilderness, etc.) None of this requires the economic sim to be running. It is all derived from the snapshot in systems.db at world generation time. The sim then drives the active/ghost flag as its rolling state changes. --- ## 4. Economic Data Per Cascade Layer — Full Mapping ### Layer 1 — Empty World | Field | Source table | Usage | |---|---|---| | `economic_role` | bodies | Biome probability prior (optional) | | `planet_class` | bodies | Primary terrain generation input | | `atmosphere` | bodies | Surface physics input | | `surface_gravity` | bodies | Terrain height ceiling | Economics is a soft advisory at this layer. The primary inputs are physical. ### Layer 2 — Population Overlay | Field | Source table | Usage | |---|---|---| | `city_id`, `center_row`, `center_col`, `population`, `kind` | atlas_cities | Settlement anchor positions and sizes | | `economic_role` | bodies | Hinterland character | | `settlement_pattern` | bodies | Population distribution mode | | `industrial_corridor` | bodies | Corridor-specific infrastructure character | | `economic_tier` | system_economy | Infrastructure density floor | | `economic_base_primary/secondary` | system_economy | System-level hinterland bias | | `gate_connections`, `gate_topology` | system_gates | Trade route intensity → transport density | | `corp_id`, `location_id`, `primary_operation` | corp_presence | Corporate cluster positions | | `behavioral_archetype` | corporations | HQ layout character | | `road_*` entries | atlas_roads | Existing road network | | `railroad_*` entries | atlas_railroads | Rail corridors | | `collection_efficiency` | system_fiscal | Shadow node trigger condition | | `health_metric` | corp_financial_state | Settlement active/ghost status at generation | Dynamic settlement triggers are evaluated from this field set. ### Layer 3 — City-Level Planning (zoning) This is where the 10×9 matrix applies. The City-Level Planning layer receives a `CityGenerationContext` (the Phase 3 → Phase 5 handoff struct from Round 3 consensus) and produces a **zoning map** — land-use assignments per parcel, constrained by topography from Layer 1 and infrastructure from Layer 2. | Field | Source | Usage | |---|---|---| | `political_archetype` | atlas_cities (Phase 3 derived) | Zoning mix character | | `prosperity_index` | atlas_cities (Phase 3 derived) | Base wealth gradient for zoning | | `founding_orientation` | atlas_cities (Phase 3 derived) | Grid orientation, oldest district direction | | `road_entry_directions` | atlas_road_edges (Phase 3 derived) | Commercial spine anchor | | `surrounding_biome` | atlas_regional_biomes (Phase 3 derived) | Topographic zoning constraints | | `district_count` | CityGenerationContext | How many zones to carve | | `economic_role` | bodies | 10×9 weight matrix row selector | | `distribution_index` | system_economy | Prosperity gradient shape (stratified vs. moderate) | | `corp_presence` count | corp_presence (query) | Corporate district intensity | | `behavioral_archetype` | corporations | District layout shape (Monopolist → homogeneous) | | `shadow_economy_access` | corporations | Informal district placement trigger | | `collection_efficiency` | system_fiscal | Informal district size multiplier | | `currency_zone` | star_systems | Regulatory character (Commission presence) | | `governance_type`, `dominant_faction` | system_factions | Administrative district character | **The 10×9 matrix in this context:** The matrix from Round 3 still applies at Layer 3, but the framing shifts from "assign district types" to "weight zoning categories." Topography from Layer 1 and infrastructure from Layer 2 interact with the matrix weights: - Industrial zones: weighted toward flat terrain near logistics access (road/rail from Layer 2). If the only flat terrain is already occupied by the commercial spine, Industrial zones shift to city fringe. - Residential zones: weighted against flood plains (Layer 1 biome data), toward terrain above the industrial elevation. - LogisticsHub: always adjacent to road/rail entry points from Layer 2. - Specialized (research): weighted toward elevated or secluded terrain. The matrix provides the prior. Topography and infrastructure provide the constraints. The product is a zoning map that is economically motivated AND geographically sensible. **Prosperity gradient at Layer 3:** `distribution_index = stratified` → the zoning map assigns a monotonic prosperity gradient across district types. Highest prosperity zones go at the end of the road spine (historic center); lowest at the industrial fringe. This is the "Cities Skylines" version of the formula I proposed in Round 3. `distribution_index = moderate` → zones cluster in the 0.4–0.6 prosperity band with less variation. The zoning map is flatter economically. ### Layer 4 — Street-Level Rendering Layer 4 receives the zoning map from Layer 3 and produces tile grids. Most of Layer 4 is seed-derived (street pattern, building footprints). Economics enters at two points: **At generation time (seed-locked):** | Field | Source | Usage | |---|---|---| | `bulk_class` | commodities (via corp_presence.primary_operation) | Building archetype (open yard vs. clean room vs. office) | | `base_premium_multiplier` | brand_products | Landmark building height/prominence | | `prosperity_index` | Per-district from Layer 3 | Initial tile variant selection | | `scarcity_class` | brand_products | Frequency of branded signage tiles | **At runtime (dynamic, no tile mutation):** | Signal | Source | Render effect | |---|---|---| | `prosperity_index` (updated by sim) | Economic simulation | Tile variant selection (clean vs. decayed vs. ruined) | | `corp_financial_state.health_metric` | Economic simulation | Corporate signage presence, maintenance appearance | | Active/ghost settlement status | Economic simulation | Lighting, activity, population density rendering | | `collection_efficiency` | Economic simulation | Shadow market visual density | The runtime signals do not change tile positions. They change which tile variant renders at each position. The implementation is: the rendering system reads `prosperity_index` per district from the sim's current state and applies a decay curve to tile selection. --- ## 5. Data Quality Issues That Must Be Resolved Before Layer 3 I flagged two data quality issues in Round 3. They become blockers at Layer 3: **Issue 1: `behavioral_archetype` is mostly NULL** Of the 275 corporation rows I surveyed, `behavioral_archetype` is NULL on most records. The fallback chain I proposed in Round 3 still applies: `behavioral_archetype` → `supply_chain_role` → commodity tier derivation from `primary_operation`. But `supply_chain_role` is also sparse. The realistic near-term fallback is commodity tier: a corp whose `primary_operation = 'metallic_ore'` is a Producer; `'financial_services'` is an Intermediary; `'gate_components'` is a Specialist. This derivation should be added to `import_economics.py` as a backfill step — it can fill NULL `behavioral_archetype` rows from commodity tier with a low confidence flag. This is not required for the minimum viable slice but it enriches Layer 3 zoning quality significantly. **Issue 2: `scope` field is mixed-type text** Corporation `scope` values are a mix of enum-ish text ("reach-wide", "local") and prose descriptions ("GJ 338B local; north corridor secondary"). The generator cannot reliably parse prose scope descriptions. For Layer 3 corporate district intensity, I use `corp_count` as the proxy (not scope). But for landmark building placement, I need to identify reach-wide HQ corps. A cleanup pass on `scope` to normalize it to an enum (reach_wide | sector | system | local) would be the right fix. Until then, the generator should treat any `scope` value that doesn't exactly match a known enum string as `system`-tier. --- ## 6. Open Questions This Round Raises The planet-down model introduces new questions that Round 3 didn't address: **OQ-R4-B1: Who owns the latent settlement active/ghost flag?** I've proposed that settlement active/ghost status is driven by the economic sim at runtime. But the sim needs to know which settlements are latent and what conditions activate them. Does this flag live: - (a) In the generated world state as a sim-readable component on each settlement entity? - (b) In a systems.db Phase 3 output table (settlement positions + trigger conditions)? - (c) Computed entirely at runtime from corp presence + health? Option (b) is cleanest — Phase 3 stores latent settlement positions and trigger conditions, and the sim reads them alongside `corp_financial_state`. This integrates naturally with the `generate_regional.py` pipeline. **OQ-R4-B2: Does the "felled forests → farmland" change generate ChunkMutations?** I argued above that this is a Layer 2 regional-scale change (large cells, biome-level), not a Layer 4 tile mutation. But practically: when an agricultural corp expands and new farmland appears, does this register as ChunkMutations in the save file, or as a biome grid update to systems.db (requiring `make regen-db`)? I lean toward: regional land use changes are coarse enough that they update a `regional_land_use` column in the biome grid at runtime (not a full regen-db), and the Layer 4 renderer reads the coarse grid to determine what large-scale tile type fills undeveloped hinterland cells. This is not ChunkMutations — it's a different resolution. This needs an answer before Phase 3 and Phase 5 teams start building their respective land-use systems with incompatible resolution assumptions. **OQ-R4-B3: Does `prosperity_index` apply at district-level or block-level?** In Round 3 I defined it at district level (one float per district). Under the planet-down model, with topography-constrained zoning, a single district might span dramatically different terrain (the industrial hillside vs. the commercial valley floor). Should prosperity be a per-district scalar, or a per-block modifier? Per-district is simpler and consistent with the Phase 5 architecture (DistrictSkeleton has one `prosperity_index`). Per-block would enable richer decay gradients (a district where prosperity collapses from the periphery inward). I recommend per-district for now with a note that the field can be moved to BlockSkeleton in a later pass if the single-value model proves too coarse. **OQ-R4-B4: How does `distribution_index = stratified` interact with topography?** In a stratified system, the wealth gradient is steep — executive district at 0.9, worker housing at 0.15. In the planet-down model, topography often already encodes wealth geography (hilltops are historically desirable; industrial lowlands are not). Do we: - (a) Let the topographic constraint drive the gradient independently of distribution_index? - (b) Use `distribution_index` to set gradient magnitude and topography to set direction? - (c) Only apply distribution_index when topography is flat (no natural gradient)? Option (b) is my recommendation: topography tells us WHICH end is high-prosperity; distribution_index tells us HOW STEEP the gradient is. A stratified city on a hill has elite zones at the top; a moderate city on a hill has mixed zoning across all elevations. --- ## Summary: Requirements for the Brief The brief should specify: 1. **Economics enters weakly at Layer 1** (biome probability prior from economic_role — optional but recommended) and **fully at Layer 2** (hinterland character, settlement placement, infrastructure density). 2. **The determinism split is:** Layer 4 street/building layout is seed-locked. Economic sim updates `prosperity_index` per district (render parameter, not tile mutation). Regional land use (Layer 2) CAN update at biome-cell resolution. 3. **Dynamic settlements are latent at generation:** All economically plausible settlement positions are placed seed-derived at Layer 2. Active/ghost status is driven by economic sim. Ghost settlements exist spatially — they just look abandoned. 4. **The 10×9 matrix applies at Layer 3** (City-Level Planning), modified by topographic constraints from Layer 1 and infrastructure access from Layer 2. The matrix provides the zoning prior; terrain provides the spatial constraints. 5. **The minimum economics read set for Layer 3** is the same 6-field set from Round 3, now delivered via the `CityGenerationContext` struct rather than direct DB queries at generation time. This is already captured in D-C12. 6. **`prosperity_index` is a Layer 3 output** (derived from economics data, stored in CityGenerationContext / atlas_cities) and a **Layer 4 runtime parameter** (the sim updates it; the renderer reads it for tile variant selection). 7. **Data quality pre-work:** `import_economics.py` should add a `behavioral_archetype` backfill pass from commodity tier before `generate_regional.py` runs. `scope` field normalization is recommended but not blocking.