feat(simulation): brand layer schema and import pipeline (#827)

Adds the brand layer per D-189 §5:
- Schema: brand_products, brand_inputs, system_fiscal, corp_financial_state,
  corp_lifecycle_events (+ 5 indexes).
- Importer: reads wiki/economics/corporations/brands.toml, populates the
  new tables, validates V-B01–V-B05 structural rules, and derives
  system_fiscal for inhabited systems.
- Data: 8 brand_products, 16 brand_inputs, 301 system_fiscal rows.

Brand products are demand nodes — they consume commodities; they are not
commodities themselves (D-185). Depends on copy PR #127 for the corp
records referenced by brands.toml.
This commit is contained in:
2026-04-14 17:24:51 +02:00
parent 826b6fe1c7
commit 03e0d1c022
4 changed files with 620 additions and 10 deletions
+60
View File
@@ -276,6 +276,60 @@ CREATE TABLE IF NOT EXISTS corp_presence (
PRIMARY KEY (corp_id, location_id)
);
-- Brand layer (D-189) — administered-price layer above commodity tâtonnement.
-- Brands consume commodities as demand nodes; they are NOT commodities (D-185).
CREATE TABLE IF NOT EXISTS brand_products (
brand_product_id TEXT PRIMARY KEY,
corp_id TEXT NOT NULL REFERENCES corporations(corp_id),
product_name TEXT NOT NULL,
brand_category TEXT NOT NULL, -- terroir|heritage_craft|tech_premium|cultural|service_premium|commodity_branded|design_heritage|platform_catalogue
value_trajectory TEXT NOT NULL, -- appreciating|depreciating|timeless
scarcity_class TEXT NOT NULL, -- capped|constrained|scalable|unlimited
product_subcategory TEXT,
base_premium_multiplier REAL NOT NULL DEFAULT 1.0,
premium_floor REAL NOT NULL DEFAULT 0.0,
origin_system TEXT REFERENCES star_systems(system_id),
terroir_locked INTEGER NOT NULL DEFAULT 0, -- boolean: production bound to origin_system
currency_denomination TEXT NOT NULL DEFAULT 'tractus', -- tractus|mark|mixed|sol_adjacent
shadow_viable INTEGER NOT NULL DEFAULT 0, -- boolean: circulates in shadow economy
brand_tier TEXT NOT NULL, -- halo|volume
halo_brand_id TEXT REFERENCES brand_products(brand_product_id), -- NULL for halo tier
updated_at TEXT DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS brand_inputs (
brand_product_id TEXT NOT NULL REFERENCES brand_products(brand_product_id),
commodity_id TEXT NOT NULL REFERENCES commodities(commodity_id),
quantity REAL NOT NULL,
PRIMARY KEY (brand_product_id, commodity_id)
);
-- Fiscal parameters per star system (D-189 section 5 + section 6)
CREATE TABLE IF NOT EXISTS system_fiscal (
system_id TEXT PRIMARY KEY REFERENCES star_systems(system_id),
corp_tax_rate REAL NOT NULL DEFAULT 0.22, -- 0.01.0
collection_efficiency REAL NOT NULL DEFAULT 1.0, -- derived: 1.0 - shadow_intensity × 0.6
updated_at TEXT DEFAULT (datetime('now'))
);
-- Phase 2: passive corp health tracking (D-189 section 8)
CREATE TABLE IF NOT EXISTS corp_financial_state (
corp_id TEXT PRIMARY KEY REFERENCES corporations(corp_id),
health_metric REAL NOT NULL DEFAULT 1.0, -- 0.0 (distressed) to 1.0 (healthy)
updated_at TEXT DEFAULT (datetime('now'))
);
-- Phase 3 lifecycle state machine stub (D-189 section 8) — schema correct, not driven yet
CREATE TABLE IF NOT EXISTS corp_lifecycle_events (
event_id INTEGER PRIMARY KEY AUTOINCREMENT,
corp_id TEXT NOT NULL REFERENCES corporations(corp_id),
event_type TEXT NOT NULL, -- Founded|Growing|Active|Distressed|Acquired|Dissolved
event_tick INTEGER NOT NULL DEFAULT 0,
event_data TEXT, -- JSON blob for future lifecycle detail
created_at TEXT DEFAULT (datetime('now'))
);
-- Indexes
-- astronomical_id removed: system_id IS the GJ catalog number
CREATE INDEX IF NOT EXISTS idx_star_systems_sector ON star_systems(geographic_sector);
@@ -304,3 +358,9 @@ CREATE INDEX IF NOT EXISTS idx_production_chains_output ON production_chains(out
CREATE INDEX IF NOT EXISTS idx_chain_inputs_commodity ON chain_inputs(input_commodity_id);
CREATE INDEX IF NOT EXISTS idx_corp_presence_corp ON corp_presence(corp_id);
CREATE INDEX IF NOT EXISTS idx_corp_presence_location ON corp_presence(location_id);
-- Brand layer indexes (D-189 section 5 — composite for UI queries)
CREATE INDEX IF NOT EXISTS idx_brand_products_corp_category ON brand_products(corp_id, brand_category);
CREATE INDEX IF NOT EXISTS idx_brand_products_origin ON brand_products(origin_system);
CREATE INDEX IF NOT EXISTS idx_brand_products_tier ON brand_products(brand_tier);
CREATE INDEX IF NOT EXISTS idx_brand_inputs_commodity ON brand_inputs(commodity_id);
CREATE INDEX IF NOT EXISTS idx_corp_lifecycle_events_corp ON corp_lifecycle_events(corp_id);