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>
443 lines
36 KiB
Markdown
443 lines
36 KiB
Markdown
# 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
|