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>
36 KiB
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_factionalready exists — this pass POPULATES it, does not add a new column.system_culture.cultural_registeralready exists as free-text, NPC-voice field (wiki_sync.py pipeline). The new D-232 generator input is renamedcultural_specialization(onsystem_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.
# 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
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_registerstays untouched on its own wiki_sync.py pathway for NPC voice.- No collision. Authors know: both
*_specializationfields are generator inputs onsystem_economy;cultural_registeris the narrative field onsystem_culture.
Database columns
-- 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:
- Reads
wiki/economics/system_specialization.toml - Validates all fields against vocabulary tables and FK constraints
- UPSERTs
system_economy.economic_specializationandsystem_economy.cultural_specialization - UPSERTs
system_factions.dominant_factionfor each authored system (column already exists; this populates it for named systems — does NOT affect systems without a TOML entry) - Prints coverage report
Also compiles wiki/economics/specialization_vocabulary.toml into a new specialization_vocabulary DB table (read-only reference, not authored per-system):
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 byterroir_organics(Dagat's kelp farms are organic_compounds at monopoly scale, identical to the terroir_organics template)alloy_hub→ absorbed bygeneral_industrialat 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
breadbasket90% 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.tomland imported viaimport_economics.pyat 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 TEXTA 26-value curated vocabulary (defined inwiki/economics/specialization_vocabulary.toml, compiled to thespecialization_vocabularyDB 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 —breadbasketis notestate_farmingeven though both referenceagricultural_produce, becausebreadbasketpinsProductionUbiquity = Specialistwhere the catalog default would giveUbiquitous. 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 TEXTA 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 namedcultural_specialization(notcultural_register) to avoid name collision withsystem_culture.cultural_register(existing free-text NPC-voice field, wiki_sync.py pipeline, untouched by this workshop).cultural_specializationis the machine-readable D-232 generator input;system_culture.cultural_registeris 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 onsystem_factions(D-199 field 4, present in systems-schema.sql).import_economics.pyUPSERTS 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_commissionis dropped — ACB and Bastion areconcord_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_specializationis derived via a seed-hashed weighted draw over the vocabulary. The weight table is built fromeconomic_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_registerfallback uses corridor assignment (D-232 existing).dominant_factionfallback 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-232atlas_body_trait_biashero 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 toIMPORT_ECONOMICS_SOURCESfor 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 — consumesdominant_faction), D-172 (currency zone alignment withdominant_faction), D-174 (shadow economy —dominant_faction = compactelevates 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_classanddominant_production_ubiquityare now sourced from the authored specialization layer (D-[236]) rather than derived from the highest-output production chain. The derivation chain is:
If
system_economy.economic_specializationis authored → resolve viaspecialization_vocabulary(economic_specialization)→(commodity_id, production_ubiquity_override)→(BulkClass, ProductionUbiquity). Use the vocabulary-specifiedProductionUbiquity(which may override the catalog default per the equal-or-higher rule).If
economic_specializationis 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)populatesCityGenerationContext.dominant_bulk_classandCityGenerationContext.dominant_production_ubiquity. The frozen-amber constraint is unchanged:fill_chunk(ctx, seed)holds noPressureStatereference. 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: Addeconomic_specialization TEXTandcultural_specialization TEXTtosystem_economyMIGRATION_SQLinimport_economics.py: idempotentALTER TABLEfor both new columnssystem_factions.dominant_faction: no schema change — column exists,import_economics.pypopulates it for authored systems- New table:
specialization_vocabulary(compiled fromwiki/economics/specialization_vocabulary.toml)
New files:
wiki/economics/system_specialization.toml— per-system authored entrieswiki/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 reportcity_context_reader.rs: replace#982 design-blockedstubs with vocabulary lookup + fallback draw algorithm
Content pass:
- Miri: ~80-100
economic_specializationpins + ~30cultural_specializationpins for named/hero systems + D-177 terroir pins - Paula: ~40-60
dominant_factionpins (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_biashero pins (~30-40 bodies) as co-authoring activity in same pass