Files
settled-reach/docs/workshops/planet-down-cascade/burnelli-sheldon-round1.md
T
jpmschweitzerandClaude Opus 4.6 b9fd75b840 docs(workshops): planet-down cascade workshop + misc stray files
Planet-down cascade workshop (3 rounds, 5 agents): layer-by-layer
generation from empty world through population overlay, city planning,
and street rendering. Includes consultant review by Troblum.

Also commits: pre-Sprint-35 DB backup, Claude Code team-mode tmux
test log (team-test.md).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-03 20:18:30 +02:00

25 KiB
Raw Blame History

title, description, type, status, workshop, agent, round, created
title description type status workshop agent round created
Round 1 — Burnelli-Sheldon: Economics Inventory and Amendment 6 Analysis Economics domain inventory for the planet-down cascade workshop. Question triage, Amendment 6 weight table critique with proposed alternative, and economic field mapping per layer. workshop active planet-down-cascade burnelli-sheldon 1 2026-05-01

Round 1 — Burnelli-Sheldon: Economics Inventory and Framing

This document is my Round 1 contribution to the planet-down cascade workshop. I'm working from the Brief, the Consultant Review amendments, the four prior generation-cascade rounds, and the existing systems.db schema. My job this round: inventory the open questions from an economics perspective, triage them by difficulty and prerequisite structure, and deliver a concrete alternative to the 10×9 weight table that Amendment 6 has unlocked for revision.


1. What the Amendments Change for My Domain

Before the question inventory, the amendments require me to update my prior assumptions.

Amendment 1 (Three-Tier Execution Model) — Clean Win for Economics

The brief had conflated "Layer 1-2 stored in systems.db" with "economic sim needs Layer 1-2 data." Amendment 1 correctly separates them:

  • Economic simulation runs on system-level aggregateseconomic_tier, corp_presence, corp_financial_state.health_metric, commodity flows, gate connectivity. All of this is already in systems.db from build-time generation. The sim does not need to know where a mining camp sits on a planetary surface to compute inter-system commodity pricing.

  • Layer 1-2 spatial data — drainage, settlement positions, road graphs, TerritorialStatus — is consumed only by Layer 3 city planning and Layer 4 tile rendering. Neither of those feeds back into the economic simulation; they read from it.

This is the correct separation. My Round 4 mapping of "economic fields at Layer 2" still holds — those fields are read by the Layer 2 generator as inputs to settlement placement. But the Layer 2 generator is now a runtime background process reading from systems.db snapshots, not a Python batch process. The economics data it reads is already there.

What this changes: generate_regional.py as designed in Tyre's Round 3 becomes a reference/validation tool. The algorithms I propose must be implementable in Rust on a background thread, without Python-specific dependencies.

Amendment 3 (Fully Generative Placement) — New Question Required

L1-Q1, L2-Q1, and CL-Q4 (all variants of "authored rivers vs. generated network" and "anchor vs. re-derive city positions") are eliminated. Every city position is now generator-derived. This adds two new questions:

  • Attractor-matching algorithm: N named cities with known economic roles must be matched to M geographic attractors. This is my primary Layer 2 algorithm contribution.
  • Name reservation fulfillment: How does the generator know which city name resolves to which generated position? This is an architecture question (Tyre) with economics constraints (I need to flag which cities are "locked" because corporate cross-references in systems.db point to them by name).

Amendment 6 (10×9 Weight Table Unlocked) — See §4 Below

The weight table is no longer a given fact. The lead's challenge is correct and I'll address it in full in §4.


2. Question Inventory — By Status

Eliminated (no workshop resolution needed)

Question Why eliminated
L1-Q1 Amendment 3: rivers are fully generated, no authored network
L2-Q1 Amendment 3: all city positions are generator-derived
CL-Q4 Amendment 3: same as L1-Q1

Economics Primary — I Own These

Question Type Prerequisite for
L1-Q4 (biome probability prior) Novel design Nothing downstream blocks on this; pure quality improvement
L2-Q2 (sub-settlement placement algorithm) Novel design + data schema L2-Q6 (flag storage), Layer 3 corp district intensity
L2-Q4 (hinterland shape algorithm) Novel design Land use grid → Layer 3 city context
L2-Q5 (TerritorialStatus thresholds) Novel design (quantitative) Paula's political framing; snapshot accuracy
L2-Q6 (latent settlement flag storage) Data/schema Runtime active/ghost status across all settlement types
L3-Q4 (topographic constraints on zoning) Novel design Blocks L3-Q5 derivation unless we agree topo is advisory only
L3-Q5 (prosperity_baseline formula) Novel design (quantitative) Layer 3 minimum viable output
L3-Q7 (port/station direction) Data/schema Deferred — not min viable scope
Amendment 6 (district mix alternative) Novel design ALL of Layer 3 — this is the zoning foundation
New: Attractor-matching algorithm Novel design L2-Q2 depends on it

Economics Advisory — I Contribute, Others Lead

Question Who leads My input
L3-Q1 (FoundingOrientation grid orientation) Gestalt prosperity gradient direction = my input
L3-Q2 (political archetype spatial arrangement) Paula economic role shapes arrangement alongside political type
L3-Q6 (town vs. city code path) Tyre unified path preferred — I have no economics objection
L4-Q1 (economics-variable rendering mechanism) Tyre + Gestalt my input: threshold-crossing, not per-tick
L4-Q2 (condition update trigger) Tyre my input: threshold thresholds I can specify
L4-Q6 (prosperity_delta architecture) Paula I co-own the field definition
CL-Q1 (prosperity_baseline vs. current naming) All I proposed the field names; agree to lock them
CL-Q2 (regional land-use evolution) Tyre I proposed the resolution boundary in R4-B2
CL-Q3 (ruin lifecycle) Paula Amendment 5: emergent only, no dedicated mechanics

Independent (do not block other questions)

L1-Q4, L3-Q7, and CL-Q3 can all be answered or deferred without blocking anything else.

Prerequisite Questions (must resolve first)

  1. Amendment 6 / district mix — blocks all of Layer 3 algorithm design. Everything about zoning, prosperity gradients, and block skeletons depends on knowing the district type distribution method.
  2. Attractor-matching algorithm (new from Amendment 3) — blocks L2-Q2 sub-settlement placement, since camps are placed relative to tether cities, and tether cities are now generator-placed.
  3. CL-Q1 (field naming lock) — blocks all Layer 3 and Layer 4 algorithm descriptions that need to reference these fields.

3. What Algorithms Exist vs. What Is Novel

Reusable from Prior Work

From Round 3 / Round 4 — economic field mapping: The bodies, system_economy, corp_presence, system_fiscal, corp_financial_state table reads are defined and stable. The 6-field minimum read set for CityGenerationContext is confirmed. These are not novel design work — they are schema reads.

From Round 4 — determinism split: The layout-vs-appearance split is confirmed. Seed-locked = positions. Economics-variable = tile conditions, lighting, activity states. This is done. CL-Q2 (regional land use resolution boundary) I recommended in Round 4-B2: coarse biome-cell resolution can update at runtime; city-internal layout never changes. I hold this position.

From Round 4 — latent settlement principle: Settlement positions are seed-locked at Layer 2. Active/ghost status is runtime economic sim state. The four settlement types (mining camps, trade waypoints, agricultural nodes, shadow nodes) and their trigger conditions are specified. This is not novel design work for Round 1 — it's a carry-forward.

From the brief — D-C4 district count formula: max(1, floor(city.population / 50_000)), log-scaled, WorldTier caps, capital bonus. This is locked and reusable.

Novel Design Work Required This Round

1. District mix algorithm (Amendment 6) — the primary economics deliverable for this workshop. See §4 for my full proposal.

2. Attractor-matching algorithm — new question from Amendment 3. Economic role determines which geographic attractor is the right match for each city. I have a framework for this (comparative advantage matching); see §5.

3. Prosperity gradient formula (L3-Q5) — the formula is sketched in the brief but needs topographic interaction defined. My proposal: topography sets gradient DIRECTION, distribution_index sets gradient MAGNITUDE. A stratified city on a hill has elite zones at the top with a steep gradient. A moderate city on a hill has mixed zoning across elevations with a shallow gradient.

4. TerritorialStatus thresholds (L2-Q5) — quantitative thresholds need values. Paula owns the taxonomy; I can supply the economic proxies for each tier.

Data/Schema Questions Only (no algorithm)

CL-Q1 — just a naming lock. prosperity_baseline, prosperity_current, prosperity_delta (derived). I hold the definitions from my Round 4 document.

L2-Q6 — latent settlement flag storage. My Round 4 recommendation: option (b), Phase 3 output table. In the three-tier model, this becomes a runtime background generation output stored in session DB, not systems.db. No change to the algorithm; just where the output lands.

L3-Q7 — port/station direction. Feasible from systems.db stations table (orbits_body_id + atlas body grid coordinates). Recommended deferred for minimum viable scope.


4. Amendment 6: Why the 10×9 Table Is Wrong and What Replaces It

The lead's challenge is economically exact. I'll state the theorem clearly, then propose the replacement.

The Theorem: Concentrated Labor Creates Service Demand

When workers concentrate in a settlement, service industries emerge to serve them — regardless of what those workers produce. This is not optional. It is a consequence of basic human needs. Miners need food, clothing, medical care, and — critically — social venues. They drink. They gamble. They fight and need someone to stitch them up. The company may own the tavern (company town), the union may run the recreation hall (labour-movement town), or it may be informal (frontier dive), but the entertainment function exists.

The 10×9 table violates this theorem by assigning zero weight to entertainment for mining, extraction, and energy economic roles. A real mining town with zero entertainment establishments either just opened yesterday or is a forced-labour camp. Neither is the default.

What the table actually encodes is what the settlement produces. What it should encode is how the settlement configures the services it necessarily has.

The Three-Component Replacement

Component 1: Population Tier — Baseline District Guarantees

Every inhabited settlement receives a minimum set of district types determined by population. These are non-negotiable floors because the economics of human settlement make them inevitable:

Settlement Tier Population Guaranteed District Types
Outpost 50999 Residential + Mixed (combined commerce/basic services)
Town 1,0009,999 + Commercial (dedicated)
City 10,00099,999 + Entertainment (character varies by role)
Large City 100,000+ + Administrative (dedicated)

These floors apply before the economic role weights are applied. If D-C4 formula gives a 1-district city, the single district is Mixed (it carries all functions). If it gives 2 districts, one is Residential and one is Mixed-plus-specialty. At 3+ districts, dedicated Commercial and Entertainment emerge as separable entities.

Note: this integrates cleanly with the D-C4 district count formula. The guarantee is not "always build 5 districts." It is "whatever districts you DO build, allocate these types first before filling with production-role specialty."

Component 2: Economic Role — Multiplier on Weight, Not On/Off Switch

Once the guaranteed minimums are placed, the remaining district slots are filled using a weight multiplier table. Key change from the 10×9 table: no weight is ever zero. Minimum weight is 0.2, meaning "present but small/rough." Maximum is 3.0. This encodes economic role as a proportion and character modifier, not a presence/absence gate.

Proposed multiplier table (replaces the 10×9 weight table):

economic_role Res Com Ind Adm Log Ent Mix Trn Spe
manufacturing 1.5 0.4 2.5 0.5 1.5 0.4 0.6 0.5 0.2
agricultural 2.0 0.8 0.4 0.8 1.8 0.5 1.2 0.4 0.2
extraction 1.5 0.4 2.5 0.3 2.0 0.5 0.8 0.7 0.2
transit 0.8 1.5 0.4 0.4 1.8 1.0 1.2 2.0 0.2
research 1.5 0.5 0.4 1.2 0.4 0.6 0.8 0.2 2.5
commercial 1.2 2.5 0.4 0.5 0.8 1.2 1.2 0.3 0.2
service_mixed 1.8 1.5 0.4 0.8 0.5 1.2 1.5 0.2 0.2
mining 1.5 0.4 2.0 0.2 2.5 0.5 0.7 0.5 0.2
frontier 2.5 0.8 0.8 0.4 1.5 0.5 1.2 0.2 0.2
energy 0.8 0.2 1.5 0.5 2.0 0.2 0.5 0.5 2.5

The mining row now has Ent = 0.5 (half baseline, but present) and Com = 0.4. The energy row has Ent = 0.2 (minimal, but not zero). A large energy facility has workers, and those workers have somewhere to socialize — it's just a spartan canteen and a gym, not a cultural district.

How to apply the multiplier table:

  1. Apply population tier guarantees. Mark those district slots as filled.
  2. Remaining district slots = D-C4 total count minus guaranteed minimums.
  3. Normalize the multiplier table row for this city's economic role to sum to 1.0.
  4. Distribute remaining slots by normalized weights, rounding to integers.
  5. Apply political_archetype modifiers on top (existing mechanic, unchanged).
  6. Apply distribution_index to set the prosperity gradient magnitude across the resulting district set.

Component 3: Settlement Age — Character Modifier

bodies.founding_age_years tells us how long a settlement has had to develop its services. New settlements are production-focused and sparse. Old settlements have had time for secondary and tertiary industries to emerge.

I do NOT propose that age changes district count (that's population-driven) or district presence (that's the guarantee floor). Age modifies the character and quality of districts within a given type:

founding_age_years Character effect
< 50 (new) Entertainment = bare-minimum (company rec hall or single dive bar)
50150 (established) Entertainment = working-class functional (taverns, union halls, local sports)
150300 (mature) Entertainment = differentiated (high/low-end venues, cultural institutions beginning)
300+ (old) Entertainment = layered (heritage venues, class-stratified nightlife, institutions)

This is a character descriptor attached to the district, not a structural change to district count or type. The renderer and content system read it to choose tile variants and NPC archetypes. The generator doesn't need to do extra layout work for this.

The Combined Guarantee: No Zero-Service Settlements

Under this model:

  • A mining outpost (population 200) has: Residential + Mixed. The Mixed district is the supply store, the first-aid shack, and the bar, packed into one cluster.
  • A mining town (population 5,000) has: Residential + Commercial + Entertainment (guaranteed) + Ind + Log (from weight table, dominant). The entertainment district is rough bars and a gambling hall, not a theatre.
  • A mining city (population 80,000) has 12 Industrial, 12 Logistics, 1 Residential, 1 Commercial, 1 Entertainment (rough but present), 01 Mixed from remaining slots. That's 67 districts. All production-role character, but no zero-service gap.

The lead's intuition is exactly right: mining towns have rough entertainment because miners drink. This model produces that outcome mechanically.


5. New Question: Attractor-Matching Algorithm

Amendment 3 eliminates authored city positions and requires the generator to match N named cities (with known economic roles) to M geographic attractors. From an economics standpoint, this is a constraint satisfaction problem with a clear theoretical framework: comparative advantage assignment.

The economic principle: Each city has an economic role that implies a preferred attractor type. Agricultural cities prefer arable plains + water access. Mining cities prefer resource concentration sites + transport. Transit cities prefer natural chokepoints — mountain passes, river crossings, harbor narrows.

Proposed matching algorithm sketch:

For each body_id with N named cities in atlas_cities:
  1. Run Layer 1 to completion: get attractor set M with typed features
     (RiverConfluence, CoastalHarbor, MountainPass, ArablePlain,
      ResourceConcentration, Defensible, NaturalBarrier)
  2. Score matrix: S[city_i, attractor_j] = compatibility(city.economic_role, attractor.feature_type)
  3. Hard constraints: if corporations.headquarters_body = city, that city must be
     placed at an attractor compatible with its economic role (name-locked)
  4. Solve: maximize sum of compatibility scores subject to one-city-per-attractor
     (Hungarian algorithm or greedy by largest gap if N << M)
  5. Overflow: if M < N (more cities than attractors), generate synthetic attractors
     as secondary sites (river bends, coastal plains) by seed

Compatibility matrix (partial — sufficient for framing):

economic_role RiverConfl. CoastalHarbor MtnPass ArablePlain ResourceConc. Defensible
agricultural high medium low very high low low
extraction low low medium low very high medium
mining low low medium low very high medium
transit high high high low low medium
commercial high high medium medium low low
research medium medium medium medium medium high
manufacturing medium medium low medium medium low
frontier medium medium medium medium medium high

The attractor-matching algorithm is a Layer 2 entry point. It runs after Layer 1 completes for a body and before Layer 2 sub-settlement placement. Its output is: a mapping from (city_id → attractor_position) that seeds the rest of Layer 2.

This question is new and needs Round 2 algorithm concreteness. For now I'm flagging the economic framework and the constraint structure.


6. Economics Field Mapping — Revised for Three-Tier Model

My Round 4 field mapping remains correct in content. What changes under Amendment 1 is when each field is accessed:

Build-Time (systems.db — always available)

Field Table Purpose
economic_role bodies Layer 1 biome prior (advisory); Layer 2 hinterland; Layer 3 weight table
settlement_pattern bodies Layer 2 population distribution
founding_age_years bodies Layer 3 district character modifier
economic_tier system_economy Infrastructure density (Layer 2), prosperity baseline (Layer 3)
distribution_index system_economy Prosperity gradient magnitude (Layer 3)
corp_id, location_id, primary_operation corp_presence Layer 2 settlement triggers; Layer 3 district intensity
health_metric corp_financial_state Layer 2 settlement active/ghost seed state
collection_efficiency system_fiscal Layer 2 shadow node trigger
behavioral_archetype corporations Layer 3 district layout character
headquarters_body corporations Name-locked city constraint (Amendment 3)

Runtime Background (Layer 1-2 generation, Rust)

Layer 1-2 reads from systems.db fields above and produces:

  • Attractor positions (Layer 1 output, consumed by Layer 2)
  • Settlement positions (Layer 2 output, stored in session DB)
  • TerritorialStatus and PoliticalTether (Layer 2 output)
  • Land use grid (Layer 2 output)

These are not economics tables — they are geography outputs that economics data shapes. The economic sim does not consume them.

Runtime On-Demand (Layer 3-4 generation, Rust)

CityGenerationContext struct is populated from systems.db at startup — no runtime query. Layer 3 receives it and uses economic_role, economic_tier, distribution_index, corp_presence count, and headquarters_system/body match. That is the 6-field minimum read set, unchanged.

Runtime Simulation Variables (read by Layer 4 renderer)

Signal Source Effect
prosperity_current Economic simulation Tile condition selection
health_metric (updated) Economic simulation Corporate signage, maintenance state
Active/ghost status Economic simulation Lighting, activity density

These are not consumed by the generator. They are render parameters updated by the sim.


7. TerritorialStatus Thresholds (L2-Q5) — Quantitative Proposal

Paula owns the taxonomy. Here are the economic proxies I propose for threshold derivation:

TerritorialStatus Economic derivation
CoreTerritory settlement_density ≥ 1 city per province + road maintenance_authority on all connecting edges
FrontierTerritory settlement present but road density < 0.5 of CoreTerritory average for this economic_tier
ExtractiveZone ResourceConcentration feature + corp_presence with matching commodity + road to resource but sparse off-corridor
ContestZone Two settlement clusters within overlapping territory (distance < 2 × footprint_radius) with different political_archetype or dominant_faction
WildernessBuffer No settlement placed by Layer 2 algorithm
AbandonedZone Settlement placed but corp_financial_state.health_metric < 0.2 for all operating corps at founding time

These thresholds are derivable from fields already in systems.db. No new data required. The key economic inputs are corp presence count and health metric at seed time (not runtime), plus road graph density.


8. Open Questions I'm Raising for Round 2

BS-Q1: Population tier floor table — is the 50-person minimum too low for guaranteed Entertainment?

I've proposed Entertainment as guaranteed at City tier (10,000+). A 9,999-person Town doesn't get a dedicated Entertainment district under this model — it gets some in its Commercial district. Does that feel right? A 9,000-person mining town with no Entertainment dedicated district but Entertainment-character Commercial seems plausible. Flag this for Gestalt's "does this feel inhabited" check.

BS-Q2: How does founding_age_years interact with WorldTier?

A Waypoint-tier settlement by definition has population < 50. It can't be old enough to have cultural institutions even if founding_age_years = 300. The age modifier needs to be capped by WorldTier ceiling. Proposed: age modifier only applies at Town tier and above.

BS-Q3: The energy row minimum Entertainment weight of 0.2 — is this adequate for large energy production facilities?

An energy facility with 200,000 workers has a lot of people who need social services. At weight 0.2 against a population that produces 4 districts by D-C4, we might get zero Entertainment districts from the weight allocation (if 0.2 normalized against all the Log and Spe weights is too small). The guarantee floor rescues this — Entertainment is guaranteed at City tier. But I want to flag that the weight 0.2 for energy/Entertainment will produce the minimum possible dedicated Entertainment district, and the guaranteed floor + character descriptor is doing the real work here, not the weight.

BS-Q4: Does the attractor-matching algorithm need to handle bodies with no geographic attractors?

The consultant review says "if M < N, generate synthetic attractors." This is algorithmically straightforward. But economically: what does it mean for a body to have N cities and fewer geographic attractors than cities? It suggests a high-tier economic world where secondary manufacturing cities exist independent of natural features (because technology overrides geography). This is plausible for manufacturing, service, and commercial roles on high-economic_tier bodies. The synthetic attractor rule seems correct: place remaining cities along existing road corridors at seed-derived offsets.


9. What I Need from Other Participants

From Gestalt: The Amendment 6 population tier guarantee table should be evaluated against "does this produce places that feel inhabited?" at each tier. The economic logic says the guarantees are correct; Gestalt should verify the fun-and-legibility layer.

From Tyre: The attractor-matching algorithm (§5) needs a concreteness check. Is the Hungarian algorithm appropriate for this scale (N ≤ 30 cities per body, M = 50-200 attractors)? What is the performance cost?

From Paula: TerritorialStatus thresholds (§7) — do these economic proxies produce the political texture you need for narrative differentiation? CoreTerritory vs. FrontierTerritory based purely on settlement density and road maintenance seems thin for narrative purposes. Is there a political pressure field I'm missing?

From all: CL-Q1 (field naming lock) should be confirmed at the start of Round 2 so all algorithm descriptions use consistent field names.