Files
jpmschweitzerandClaude Opus 4.6 4a3febbe29 refactor(schema): rename commission_certified to commission_certifiable
The flag is a susceptibility marker, not an absolute state — Commission
certification only applies when trading in TRACTUS_PRIMARY zones.
Compact-internal trade ignores it entirely. Renamed across all TOML
source files, schema docs, workshop outputs, and D-184.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 23:32:18 +02:00

14 KiB

Commodity Catalog — Schema Specification

Definitive schema for #804 (systems.db extension), TOML field spec, and validation rules.

Decisions: D-173, D-177, D-178, D-182


1. SQL Schema (for #804)

-- =========================================================================
-- Compiled from wiki/economics/commodities.toml
-- =========================================================================

CREATE TABLE commodities (
    commodity_id TEXT PRIMARY KEY,
    name TEXT NOT NULL,
    tier TEXT NOT NULL CHECK(tier IN (
        'raw', 'intermediate', 'final',
        'service_professional', 'service_luxury'
    )),
    elasticity TEXT NOT NULL CHECK(elasticity IN (
        'perfectly_inelastic', 'inelastic', 'unit_elastic', 'elastic'
    )),
    base_price REAL NOT NULL CHECK(base_price > 0),
    bulk_class TEXT NOT NULL CHECK(bulk_class IN (
        'bulk', 'liquid', 'perishable', 'standard', 'compact',
        'precision', 'oversized', 'non_physical'
    )),
    unit TEXT NOT NULL CHECK(unit IN ('tonnes', 'units', 'contracts')),
    production_ubiquity TEXT NOT NULL CHECK(production_ubiquity IN (
        'ubiquitous', 'common', 'regional', 'concentrated', 'monopolistic'
    )),
    demand_model TEXT NOT NULL CHECK(demand_model IN (
        'market', 'utility', 'compliance'
    )),
    commission_certifiable INTEGER NOT NULL DEFAULT 0,
    compact_contested INTEGER NOT NULL DEFAULT 0,
    shadow_viable INTEGER NOT NULL DEFAULT 0,
    panic_threshold_weeks INTEGER NOT NULL DEFAULT 0 CHECK(panic_threshold_weeks >= 0),
    description TEXT
);

-- =========================================================================
-- Compiled from wiki/economics/production_chains.toml
-- =========================================================================

CREATE TABLE production_chains (
    chain_id TEXT PRIMARY KEY,
    output_commodity TEXT NOT NULL REFERENCES commodities(commodity_id),
    output_quantity REAL NOT NULL DEFAULT 1.0 CHECK(output_quantity > 0),
    location_bound INTEGER NOT NULL DEFAULT 0,
    description TEXT
);

CREATE TABLE chain_inputs (
    chain_id TEXT NOT NULL REFERENCES production_chains(chain_id) ON DELETE CASCADE,
    commodity_id TEXT NOT NULL REFERENCES commodities(commodity_id),
    quantity REAL NOT NULL CHECK(quantity > 0),
    PRIMARY KEY (chain_id, commodity_id)
);

-- =========================================================================
-- Indexes
-- =========================================================================

CREATE INDEX idx_commodities_tier ON commodities(tier);
CREATE INDEX idx_commodities_ubiquity ON commodities(production_ubiquity);
CREATE INDEX idx_commodities_demand ON commodities(demand_model);
CREATE INDEX idx_chains_output ON production_chains(output_commodity);
CREATE INDEX idx_chain_inputs_commodity ON chain_inputs(commodity_id);

Alignment notes for server team

  • Every column maps 1:1 from a TOML field. No computed columns.
  • Booleans are INTEGER (0/1) — standard SQLite convention, consistent with existing schema (inhabited, asteroid_belt, etc.).
  • FK constraints enforce referential integrity at the DB level.
  • chain_inputs composite PK: one commodity appears at most once per chain (Leontief fixed-coefficient — one coefficient per input per chain).
  • panic_threshold_weeks is integer ≥ 0. Zero means no panic behavior. Non-zero triggers the stockpile-target panic mechanism at runtime when actual stockpile falls below this threshold.

2. TOML Field Specification

commodities.toml

Field Type Required Constraint Source
TOML key string yes [a-z][a-z0-9_]* (snake_case slug) ID
name string yes non-empty, Title Case display
tier enum yes raw, intermediate, final, service_professional, service_luxury D-173
elasticity enum yes perfectly_inelastic, inelastic, unit_elastic, elastic D-173 (4 classes)
base_price float yes > 0 Tractus equilibrium
bulk_class enum yes bulk, liquid, perishable, standard, compact, precision, oversized, non_physical transport cost
unit enum yes tonnes, units, contracts quantity basis
production_ubiquity enum yes ubiquitous, common, regional, concentrated, monopolistic B-S init guidance
demand_model enum yes market, utility, compliance B-S demand floors
commission_certifiable bool yes true/false Gestalt political
compact_contested bool yes true/false Gestalt political
shadow_viable bool yes true/false Gestalt political
panic_threshold_weeks int yes ≥ 0 B-S panic mechanism
description string no flavor text

production_chains.toml

Field Type Required Constraint Source
TOML key string yes [a-z][a-z0-9_]* (snake_case slug) chain ID
output string yes must exist in commodities.toml commodity_id ref
output_quantity float no > 0, default 1.0 yield per cycle
inputs array yes ≥ 1 entry, each { commodity, quantity } recipe
inputs[].commodity string yes must exist in commodities.toml commodity_id ref
inputs[].quantity float yes > 0 input coefficient
location_bound bool no default false geographic constraint
description string no human-readable recipe

3. Bulk Class Transport Multipliers

Class Multiplier Gate cost at 8% base 5-hop price 10-hop price Commodities
bulk 1.2x 9.6%/hop 1.58x 2.50x ore, stone, timber
liquid 1.3x 10.4%/hop 1.64x 2.69x water, chemical_feedstock, fusion_fuel
perishable 1.8x 14.4%/hop 1.97x 3.87x agricultural_produce
standard 1.0x 8.0%/hop 1.47x 2.16x refined_metals, alloys, food, chemicals, textiles, panels
compact 0.8x 6.4%/hop 1.36x 1.86x electronics, drive_cores, lattice_substrate, consumer_goods, medical_goods
precision 0.6x 4.8%/hop 1.26x 1.60x rare_minerals, lattice_grade_material, implant_hardware
oversized 2.0x 16.0%/hop 2.10x 4.41x heavy_equipment, vehicles, haulers, gate_components, habitat_modules, rail
non_physical N/A N/A N/A all services

4. Validation Rules for make economy-db

Hard failures (build aborts)

# Rule Rationale
V-01 Every inputs[].commodity must exist in commodities.toml Dangling reference
V-02 Every output must exist in commodities.toml Dangling reference
V-03 Every chain must have ≥ 1 input Zero-input chain = free production, breaks Leontief
V-04 No commodity may appear as both input and output in the same chain Self-referential production
V-05 No circular dependencies in the chain graph (topological sort) Infinite loop in sim
V-06 base_price > 0 for all commodities Zero/negative prices break tâtonnement
V-07 quantity > 0 for all chain inputs and output_quantity > 0 Dead inputs
V-08 All enum fields match their allowed values Typo protection
V-09 No duplicate commodity IDs (TOML-enforced, but validate) Collision
V-10 Services (tier = service_*) must NOT appear as chain inputs or outputs D-173: services outside production chain
V-11 panic_threshold_weeks >= 0 Schema constraint
V-12 demand_model = "utility" requires elasticity ∈ {perfectly_inelastic, inelastic} Utility demand can't be highly deferrable
V-13 demand_model = "compliance" requires commission_certifiable = true Compliance demand requires a certifying authority
V-14 Services must have bulk_class = "non_physical" Services can't be transported
V-15 Services must have unit = "contracts" Service unit convention
V-16 Commodity IDs must match pattern [a-z][a-z0-9_]* Slug format for Rust/SQL

Soft warnings (build succeeds, prints warning)

# Rule Rationale
W-01 Every non-service physical commodity SHOULD appear as chain input or chain output Orphan detection
W-02 Raw tier commodities SHOULD NOT appear as chain outputs Raws are extracted, not produced
W-03 Final tier commodities SHOULD NOT appear as chain inputs Finals are end-of-chain
W-04 shadow_viable = true SHOULD have commission_certifiable = true OR compact_contested = true Shadow markets arise from regulatory friction
W-05 production_ubiquity = "monopolistic" commodities with elasticity = "inelastic" SHOULD be reviewed Monopoly + inelastic = potential runaway pricing

Coverage warnings (future — gated by corp data)

# Rule Rationale
C-01 3+ corporations per major commodity type (D-175) Simulation density
C-02 1+ corporation per inhabited system > 100K population (D-175) Coverage threshold

5. Catalog Totals

Category Count Notes
Raw materials 9 +2 over D-173's ~7: chemical_feedstock (substitution route), lattice_grade_material (east reach anchor)
Intermediate goods 10 +2 over D-173's ~8: fusion_fuel (water→fuel, locked), lattice_substrate (lattice chain)
Final goods 9 +2 over D-173's ~7: freight_haulers (distinct demand function), rail_infrastructure (locked)
Professional services 5 commission_certification (shadow economy mechanism) is the key addition
Luxury services 3 matches D-173
Total 36 D-173 target: ~30. Each addition has locked justification.

Production chains

Tier transition Count Substitution routes
Raw → Intermediate 12 2 (chemicals: geological vs biological; panels: timber vs stone)
Intermediate → Final 9 0
Total 21 2

Panic-flagged commodities

Commodity Threshold Behavior
water 1 week Life-or-death hoarding. Demand spikes 3-5x
fusion_fuel 2 weeks Station emergency reserves. Demand spikes 2-3x
processed_food 2 weeks Consumer panic buying. Demand spikes 1.5-2x
chemicals 3 weeks Hospital/industrial stockpiling. Demand spikes 1.5x

All other commodities: panic_threshold_weeks = 0 (no panic behavior).

Key chokepoints

  1. lattice_grade_material → lattice_substrate → implant_hardware + gate_components: Geographically sparse, no substitute, feeds the two most politically sensitive finals. Single supply disruption cascades to both neural tech AND gate infrastructure.

  2. rare_minerals → electronics / advanced_alloys / drive_cores: Appears in 3 intermediate chains. Electronics is input to 9 of 9 finals. A rare minerals shortage cascades to the entire manufacturing sector.

  3. water → fusion_fuel + chemicals + processed_food: Water feeds three intermediate chains (fuel at 8:1, chemicals, food processing). A water shortage simultaneously degrades energy, industrial chemistry, AND food supply. Fuel is the sharpest cascade (8:1 amplification), but the breadth across three chains makes water the single most dangerous raw material disruption. Frontier stations far from ice sources face permanent cost pressure on all three fronts.

Design notes for sim implementation

Berth capacity as transport cost modifier: Station docking/berth capacity is NOT a commodity — renting a berth is a property transaction tied to a specific location. However, berth capacity constrains the transport graph: a station with limited docking has higher effective transport costs (queuing, diversion, wait times). Model this as a per-node modifier on the effective hop cost. Expanding station infrastructure (consuming habitat_modules) reduces the modifier. This creates an investment incentive for station expansion without requiring a tradeable "berth" commodity.

Brand-layer demand: Brand corporations (Calloway, VGV, thrds, Bífröst Marmor, etc.) appear in the commodity simulation as demand nodes — they purchase raws and intermediates at their local market node. Their output (branded goods) is priced through a separate brand/cultural value system, not through the tâtonnement. Brand revenue appears as a GDP income cluster per system. The brand system is a future DLC deliverable built on top of this commodity foundation.

Items removed from catalog during review: commercial_intelligence (corporate behavioral advantage, not a tradeable commodity — what does the buyer receive?), habitation_berths (property transaction at a specific location, not a commodity flow through the gate network). Both are real economic concepts but belong in other systems.

Gate energy transmission (Level 3 — mass + data + energy): Span gates transmit mass, data (the Meridian is a live real-time network — already canon), and energy. Energy-over-gate is a commercial service offered by Gate Corporation — NOT an Assembly policy. Gate Corp is an independent monopoly with its own interests; it is not a government body and not Assembly-controlled. The Commission regulates gate infrastructure, but Gate Corp's energy service is a corporate commercial decision.

Implementation: per-node gate_energy_connected boolean in systems.db. On-grid nodes get reduced fusion_fuel utility demand (~0.3x baseline — still need backup fuel). Industrial chain inputs are unaffected (smelting still burns fuel per the Leontief recipe). Gate Corp charges a Tractus-denominated service fee. MARK_PRIMARY zones default to gate_energy_connected = false — the Compact refused Gate Corp energy dependency as a political choice, building independent fusion capacity instead.

Key dynamics: (1) Gate Corp cutting energy to a dependent node spikes that node's fuel demand — nearby Compact systems with surplus fuel capacity become emergency suppliers. The Compact's political independence becomes an economic asset. (2) Gate Corp energy cutoff is a corporate threat, not a government act — no democratic accountability, which is arguably more frightening. (3) fusion_fuel remains a single commodity; the demand differential emerges from subscription status, not from commodity bifurcation.