Files
settled-reach/docs/workshops/system-economic-specialization/burnelli-sheldon-round3.md
T
jpmschweitzerandClaude Opus 4.8 33c083f0ef docs(workshops): system-economic-specialization rounds + outcomes
Three-round design workshop (Miri, Burnelli-Sheldon, Paula; documented by
Qatux, ticketed by SI) that produced D-237. Includes per-agent round
outputs, round notes, the independent scout critique, and the final
workshop-outcomes.md with the consolidated schema, 27-value economic
vocabulary, cultural + faction vocabularies, deterministic-varied fallback
spec, must-pin table, and CI guardrails.

Clerk-Skip: workshop discussion docs, no D-record surface (D-237 filed separately)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 18:40:08 +02:00

443 lines
36 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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<specialization_id, u64> = {}
// --- 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