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

36 KiB
Raw Blame History

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.

# 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_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

-- 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):

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_stationmilitary_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_primarycompact, mixedcompact_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