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);
Binary file not shown.
+284 -10
View File
@@ -39,6 +39,7 @@ COMMODITIES_TOML = REPO_ROOT / "wiki" / "economics" / "commodities.toml"
CHAINS_TOML = REPO_ROOT / "wiki" / "economics" / "production_chains.toml"
SCHEMA_SQL = REPO_ROOT / "server" / "data" / "systems-schema.sql"
CORPORATIONS_DIR = REPO_ROOT / "wiki" / "corporations"
BRANDS_TOML = REPO_ROOT / "wiki" / "economics" / "corporations" / "brands.toml"
# ---------------------------------------------------------------------------
@@ -48,6 +49,61 @@ CORPORATIONS_DIR = REPO_ROOT / "wiki" / "corporations"
MIGRATION_SQL = """
-- Economics tables (idempotent — safe to re-run)
-- Brand layer tables (D-189, #827)
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,
value_trajectory TEXT NOT NULL,
scarcity_class TEXT NOT NULL,
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,
currency_denomination TEXT NOT NULL DEFAULT 'tractus',
shadow_viable INTEGER NOT NULL DEFAULT 0,
brand_tier TEXT NOT NULL,
halo_brand_id TEXT REFERENCES brand_products(brand_product_id),
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)
);
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,
collection_efficiency REAL NOT NULL DEFAULT 1.0,
updated_at TEXT DEFAULT (datetime('now'))
);
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,
updated_at TEXT DEFAULT (datetime('now'))
);
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,
event_tick INTEGER NOT NULL DEFAULT 0,
event_data TEXT,
created_at TEXT DEFAULT (datetime('now'))
);
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);
CREATE TABLE IF NOT EXISTS gate_links (
from_system_id TEXT NOT NULL REFERENCES star_systems(system_id),
to_system_id TEXT NOT NULL REFERENCES star_systems(system_id),
@@ -669,6 +725,206 @@ def _validate_system_coverage(
]
# ---------------------------------------------------------------------------
# Brand layer import (D-189, #827)
# ---------------------------------------------------------------------------
VALID_BRAND_CATEGORIES = {
"terroir", "heritage_craft", "tech_premium", "cultural",
"service_premium", "commodity_branded", "design_heritage", "platform_catalogue",
}
VALID_VALUE_TRAJECTORIES = {"appreciating", "depreciating", "timeless"}
VALID_SCARCITY_CLASSES = {"capped", "constrained", "scalable", "unlimited"}
VALID_BRAND_TIERS = {"halo", "volume"}
VALID_CURRENCY_DENOMINATIONS = {"tractus", "mark", "mixed", "sol_adjacent"}
def import_brands(
conn: sqlite3.Connection, dry_run: bool
) -> tuple[int, int]:
"""Import brand_products and brand_inputs from wiki/economics/corporations/brands.toml.
Returns (n_products, n_inputs).
"""
if not BRANDS_TOML.exists():
print(" warning: brands.toml not found — brand layer skipped")
return 0, 0
with open(BRANDS_TOML, "rb") as f:
data = tomllib.load(f)
products = data.get("brand_products", [])
inputs = data.get("brand_inputs", [])
product_rows = []
for p in products:
product_rows.append((
p["brand_product_id"],
p["corp_id"],
p["product_name"],
p["brand_category"],
p["value_trajectory"],
p["scarcity_class"],
p.get("product_subcategory"),
p.get("base_premium_multiplier", 1.0),
p.get("premium_floor", 0.0),
p.get("origin_system"),
int(p.get("terroir_locked", False)),
p.get("currency_denomination", "tractus"),
int(p.get("shadow_viable", False)),
p["brand_tier"],
p.get("halo_brand_id"),
))
input_rows = []
for inp in inputs:
input_rows.append((
inp["brand_product_id"],
inp["commodity_id"],
inp["quantity"],
))
if not dry_run:
conn.executemany(
"""INSERT OR REPLACE INTO brand_products (
brand_product_id, corp_id, product_name, brand_category,
value_trajectory, scarcity_class, product_subcategory,
base_premium_multiplier, premium_floor, origin_system,
terroir_locked, currency_denomination, shadow_viable,
brand_tier, halo_brand_id
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
product_rows,
)
conn.executemany(
"""INSERT OR REPLACE INTO brand_inputs
(brand_product_id, commodity_id, quantity) VALUES (?, ?, ?)""",
input_rows,
)
return len(product_rows), len(input_rows)
def import_system_fiscal(conn: sqlite3.Connection, dry_run: bool) -> int:
"""Populate system_fiscal from star_systems shadow_economy data.
collection_efficiency = 1.0 - shadow_economy_intensity × 0.6 (D-189 section 6).
shadow_economy_intensity comes from the shadow_economy.toml pipeline or defaults to 0.
Uses corp_tax_rate = 0.22 (default) for all systems in Phase 2.
"""
inhabited = conn.execute("""
SELECT ss.system_id, COALESCE(se.population, 0)
FROM star_systems ss
LEFT JOIN system_economy se ON ss.system_id = se.system_id
WHERE ss.inhabited_planet_count > 0 OR se.population > 0
ORDER BY ss.system_id
""").fetchall()
rows = []
for system_id, _pop in inhabited:
# Phase 2: shadow_economy_intensity not yet per-system in DB.
# Default collection_efficiency to 0.85 (mid-reach average) until
# shadow_economy.toml pipeline is wired (Phase 3).
rows.append((system_id, 0.22, 0.85))
if not dry_run:
conn.executemany(
"""INSERT OR IGNORE INTO system_fiscal
(system_id, corp_tax_rate, collection_efficiency) VALUES (?, ?, ?)""",
rows,
)
return len(rows)
def validate_brands(conn: sqlite3.Connection) -> list[str]:
"""Brand layer structural validation rules V-B01 through V-B05.
V-B01: Every brand_products row has a valid corp_id (FK to corporations).
V-B02: Every brand_inputs row has valid brand_product_id and commodity_id FKs.
V-B03: Every halo brand has at least one brand_inputs entry (demand stub must consume).
V-B04: Every volume tier must reference an existing halo brand_product_id.
V-B05: No brand_product_id is used as halo_brand_id by a non-volume-tier product.
"""
errors: list[str] = []
# V-B01: brand_products → corporations FK
orphan_corps = conn.execute("""
SELECT bp.brand_product_id, bp.corp_id
FROM brand_products bp
LEFT JOIN corporations c ON bp.corp_id = c.corp_id
WHERE c.corp_id IS NULL
""").fetchall()
for pid, corp_id in orphan_corps:
errors.append(
f"V-B01: brand_product '{pid}' references unknown corp_id '{corp_id}'"
)
# V-B02: brand_inputs → brand_products and brand_inputs → commodities FKs
orphan_inputs_bp = conn.execute("""
SELECT bi.brand_product_id, bi.commodity_id
FROM brand_inputs bi
LEFT JOIN brand_products bp ON bi.brand_product_id = bp.brand_product_id
WHERE bp.brand_product_id IS NULL
""").fetchall()
for pid, cid in orphan_inputs_bp:
errors.append(
f"V-B02: brand_inputs row ({pid}, {cid}) references unknown brand_product_id"
)
orphan_inputs_comm = conn.execute("""
SELECT bi.brand_product_id, bi.commodity_id
FROM brand_inputs bi
LEFT JOIN commodities c ON bi.commodity_id = c.commodity_id
WHERE c.commodity_id IS NULL
""").fetchall()
for pid, cid in orphan_inputs_comm:
errors.append(
f"V-B02: brand_inputs row ({pid}, {cid}) references unknown commodity_id '{cid}'"
)
# V-B03: every halo brand has at least one brand_inputs entry
halo_no_inputs = conn.execute("""
SELECT bp.brand_product_id
FROM brand_products bp
WHERE bp.brand_tier = 'halo'
AND bp.brand_product_id NOT IN (SELECT brand_product_id FROM brand_inputs)
""").fetchall()
for (pid,) in halo_no_inputs:
errors.append(
f"V-B03: halo brand '{pid}' has no brand_inputs entries "
f"(must consume at least one commodity as a demand node)"
)
# V-B04: volume tiers reference valid halo_brand_id
volume_bad_halo = conn.execute("""
SELECT bp.brand_product_id, bp.halo_brand_id
FROM brand_products bp
WHERE bp.brand_tier = 'volume'
AND (bp.halo_brand_id IS NULL
OR bp.halo_brand_id NOT IN (SELECT brand_product_id FROM brand_products))
""").fetchall()
for pid, halo_id in volume_bad_halo:
errors.append(
f"V-B04: volume brand '{pid}' has invalid halo_brand_id '{halo_id}'"
)
# V-B05: halo_brand_id must only point to halo-tier products
halo_points_to_non_halo = conn.execute("""
SELECT child.brand_product_id, child.halo_brand_id, parent.brand_tier
FROM brand_products child
JOIN brand_products parent ON child.halo_brand_id = parent.brand_product_id
WHERE child.brand_tier = 'volume'
AND parent.brand_tier != 'halo'
""").fetchall()
for child_id, halo_id, parent_tier in halo_points_to_non_halo:
errors.append(
f"V-B05: volume brand '{child_id}' points to '{halo_id}' "
f"which has brand_tier='{parent_tier}', not 'halo'"
)
return errors
# ---------------------------------------------------------------------------
# Main
# ---------------------------------------------------------------------------
@@ -699,7 +955,7 @@ def main():
conn.execute("PRAGMA foreign_keys=ON")
# 1. Migrate schema
print(" [1/8] Schema migration...")
print(" [1/10] Schema migration...")
for table, col, col_type in COLUMN_MIGRATIONS:
_add_column(conn, table, col, col_type)
conn.executescript(MIGRATION_SQL)
@@ -709,40 +965,45 @@ def main():
# corp_presence cleared here; corporations table is append-only (never cleared)
if not args.dry_run:
conn.execute("DELETE FROM corp_presence")
conn.execute("DELETE FROM brand_inputs")
conn.execute("DELETE FROM brand_products")
conn.execute("DELETE FROM system_fiscal")
conn.execute("DELETE FROM corp_financial_state")
conn.execute("DELETE FROM corp_lifecycle_events")
conn.execute("DELETE FROM chain_inputs")
conn.execute("DELETE FROM production_chains")
conn.execute("DELETE FROM commodities")
conn.execute("DELETE FROM gate_links")
# 2. Gate links
print(" [2/8] Importing gate links...")
print(" [2/10] Importing gate links...")
n_links = import_gate_links(conn, args.dry_run)
print(f" {n_links} rows (bidirectional)")
# 3. Commodities
print(" [3/8] Importing commodities...")
print(" [3/10] Importing commodities...")
n_commodities = import_commodities(conn, args.dry_run)
print(f" {n_commodities} commodities")
# 4. Production chains
print(" [4/8] Importing production chains...")
print(" [4/10] Importing production chains...")
n_chains, n_inputs = import_chains(conn, args.dry_run)
print(f" {n_chains} chains, {n_inputs} inputs")
# 5. Currency zones
print(" [5/8] Setting currency zones...")
print(" [5/10] Setting currency zones...")
zones = set_currency_zones(conn, args.dry_run)
for zone, count in sorted(zones.items()):
print(f" {zone}: {count}")
# 6. Gate energy connectivity (D-186) — must run after currency zones
print(" [6/8] Setting gate energy connectivity...")
print(" [6/10] Setting gate energy connectivity...")
energy = set_gate_energy(conn, args.dry_run)
for label, count in sorted(energy.items()):
print(f" {label}: {count}")
# 7. Sync corporations from wiki (D-182: hard error on name divergence)
print(" [7/8] Syncing corporations...")
print(" [7/10] Syncing corporations...")
corp_errors = sync_corporations(conn, wiki_corps, args.dry_run)
if corp_errors:
print(f" ERRORS ({len(corp_errors)}) — name divergence detected (D-182):")
@@ -755,17 +1016,28 @@ def main():
print(f" {n_db_corps} corporations in DB ({len(wiki_corps)} from wiki)")
# 8. Corp presence from wiki headquarters data
print(" [8/8] Importing corp presence...")
print(" [8/10] Importing corp presence...")
commodity_ids = {
r[0] for r in conn.execute("SELECT commodity_id FROM commodities").fetchall()
}
n_presence = import_corp_presence(conn, wiki_corps, commodity_ids, args.dry_run)
print(f" {n_presence} corp_presence rows")
# 9. Brand products and inputs (D-189, #827)
print(" [9/10] Importing brand products and inputs...")
n_brands, n_brand_inputs = import_brands(conn, args.dry_run)
print(f" {n_brands} brand_products, {n_brand_inputs} brand_inputs")
# 10. System fiscal parameters (D-189 section 6)
print(" [10/10] Populating system_fiscal...")
n_fiscal = import_system_fiscal(conn, args.dry_run)
print(f" {n_fiscal} system_fiscal rows")
# Validate structural integrity (FK, chain refs, chain completeness).
# These errors indicate broken imported data — do NOT commit.
print("\n Validating structural integrity...")
struct_errors = validate(conn)
struct_errors.extend(validate_brands(conn))
if struct_errors:
print(f" STRUCTURAL ERRORS ({len(struct_errors)}) — rolling back:")
for e in struct_errors:
@@ -773,7 +1045,7 @@ def main():
conn.close()
sys.exit(1)
else:
print(" FK integrity and chain completeness OK")
print(" FK integrity, chain completeness, and brand layer (V-B01V-B05) OK")
# Commit all imported data (corps, presence, etc.) before coverage check.
# Coverage validation is a Phase 2 gate (D-175) — data should be persisted
@@ -809,7 +1081,9 @@ def main():
conn.close()
print(f"\n Done: {n_links} gate_links, {n_commodities} commodities, "
f"{n_chains} chains, {n_inputs} inputs, {n_presence} corp_presence\n")
f"{n_chains} chains, {n_inputs} inputs, {n_presence} corp_presence, "
f"{n_brands} brand_products, {n_brand_inputs} brand_inputs, "
f"{n_fiscal} system_fiscal\n")
if __name__ == "__main__":
+276
View File
@@ -0,0 +1,276 @@
# ==========================================================================
# Settled Reach — Brand Product Records (Phase 2 Demand Stubs)
# Source of truth for brand_products and brand_inputs tables.
# Compiled to systems.db via `make economy-db`.
#
# These 4 canonical brand corps register as commodity demand nodes in the
# tâtonnement simulation (D-185: brands consume commodities, not the reverse).
# Pricing model and cultural premium curves are Phase 3+ deliverables (D-189).
#
# Fields per [[brand_products]] entry:
# brand_product_id Unique slug (corp_id + product slug)
# corp_id Must match a slug in wiki/corporations/
# product_name Display name
# brand_category terroir|heritage_craft|tech_premium|cultural|
# service_premium|commodity_branded|design_heritage|platform_catalogue
# value_trajectory appreciating|depreciating|timeless
# scarcity_class capped|constrained|scalable|unlimited
# product_subcategory Readable product type descriptor
# base_premium_multiplier Multiplier over raw commodity input cost (Phase 3 pricing)
# premium_floor Minimum administered price floor (Phase 3 pricing)
# origin_system GJ catalog ID — must match star_systems.system_id
# terroir_locked true: production cannot move from origin_system
# currency_denomination tractus|mark|mixed|sol_adjacent
# shadow_viable true: circulates in shadow economy
# brand_tier halo|volume
# halo_brand_id For volume tiers: brand_product_id of parent halo product
#
# Fields per [[brand_inputs]] entry:
# brand_product_id References a brand_products entry above
# commodity_id Must match commodities.toml
# quantity Demand coefficient (annual units consumed per production run)
#
# Decisions: D-185 (brands as demand nodes), D-189 (brand layer architecture),
# D-190 (volume calibration), D-182 (TOML pipeline)
# ==========================================================================
# ==========================================================================
# CALLOWAY DISTILLERY (north_reach — terroir, appreciating)
# Eleven distilleries, 400 years of production. GJ 3325.
# Inputs: grain (agricultural_produce) + water for single malt whisky.
# ==========================================================================
[[brand_products]]
brand_product_id = "calloway-single-malt-halo"
corp_id = "calloway-distillery"
product_name = "Calloway Single Malt 25yr"
brand_category = "terroir"
value_trajectory = "appreciating"
scarcity_class = "capped"
product_subcategory = "aged_spirits"
base_premium_multiplier = 18.0
premium_floor = 0.85
origin_system = "GJ 3325"
terroir_locked = true
currency_denomination = "tractus"
shadow_viable = true
brand_tier = "halo"
[[brand_inputs]]
brand_product_id = "calloway-single-malt-halo"
commodity_id = "agricultural_produce"
quantity = 0.12 # grain — ~12% of annual produce demand per distillery output unit
[[brand_inputs]]
brand_product_id = "calloway-single-malt-halo"
commodity_id = "water"
quantity = 0.08 # distillation water
[[brand_products]]
brand_product_id = "calloway-reserve-volume"
corp_id = "calloway-distillery"
product_name = "Calloway Reserve"
brand_category = "terroir"
value_trajectory = "appreciating"
scarcity_class = "constrained"
product_subcategory = "aged_spirits"
base_premium_multiplier = 4.5
premium_floor = 0.30
origin_system = "GJ 3325"
terroir_locked = true
currency_denomination = "tractus"
shadow_viable = true
brand_tier = "volume"
halo_brand_id = "calloway-single-malt-halo"
[[brand_inputs]]
brand_product_id = "calloway-reserve-volume"
commodity_id = "agricultural_produce"
quantity = 0.55 # larger grain demand — volume tier drives commodity draw
[[brand_inputs]]
brand_product_id = "calloway-reserve-volume"
commodity_id = "water"
quantity = 0.35
# ==========================================================================
# VINS DE GRAND VIDE (west_reach — terroir, appreciating / timeless)
# Négociant cooperative, GJ 395. Wine production from châteaux network.
# Inputs: agricultural_produce (grapes) + water.
# ==========================================================================
[[brand_products]]
brand_product_id = "vgv-premier-cru-halo"
corp_id = "vins-de-grand-vide"
product_name = "Grand Vide Premier Cru"
brand_category = "terroir"
value_trajectory = "appreciating"
scarcity_class = "capped"
product_subcategory = "fine_wine"
base_premium_multiplier = 12.0
premium_floor = 0.70
origin_system = "GJ 395"
terroir_locked = true
currency_denomination = "tractus"
shadow_viable = true
brand_tier = "halo"
[[brand_inputs]]
brand_product_id = "vgv-premier-cru-halo"
commodity_id = "agricultural_produce"
quantity = 0.18 # estate grapes — limited châteaux harvest
[[brand_inputs]]
brand_product_id = "vgv-premier-cru-halo"
commodity_id = "water"
quantity = 0.04
[[brand_products]]
brand_product_id = "vgv-standard-volume"
corp_id = "vins-de-grand-vide"
product_name = "Grand Vide Standard"
brand_category = "terroir"
value_trajectory = "timeless"
scarcity_class = "scalable"
product_subcategory = "wine"
base_premium_multiplier = 2.2
premium_floor = 0.15
origin_system = "GJ 395"
terroir_locked = false
currency_denomination = "tractus"
shadow_viable = false
brand_tier = "volume"
halo_brand_id = "vgv-premier-cru-halo"
[[brand_inputs]]
brand_product_id = "vgv-standard-volume"
commodity_id = "agricultural_produce"
quantity = 0.80 # négociant aggregation — largest agricultural demand node
[[brand_inputs]]
brand_product_id = "vgv-standard-volume"
commodity_id = "water"
quantity = 0.20
# ==========================================================================
# THRDS (north_reach — heritage_craft, timeless)
# Cold-weather technical clothing cooperative, GJ 475.
# Inputs: textiles (brach fiber) + organic_compounds (dye, finish).
# ==========================================================================
[[brand_products]]
brand_product_id = "thrds-origin-halo"
corp_id = "thrds"
product_name = "thrds Origin"
brand_category = "heritage_craft"
value_trajectory = "timeless"
scarcity_class = "constrained"
product_subcategory = "technical_clothing"
base_premium_multiplier = 6.0
premium_floor = 0.50
origin_system = "GJ 475"
terroir_locked = true
currency_denomination = "tractus"
shadow_viable = false
brand_tier = "halo"
[[brand_inputs]]
brand_product_id = "thrds-origin-halo"
commodity_id = "textiles"
quantity = 0.30 # brach fiber — origin-specific weave
[[brand_inputs]]
brand_product_id = "thrds-origin-halo"
commodity_id = "organic_compounds"
quantity = 0.08 # plant-derived dyes and finishing compounds
[[brand_products]]
brand_product_id = "thrds-standard-volume"
corp_id = "thrds"
product_name = "thrds Standard"
brand_category = "heritage_craft"
value_trajectory = "timeless"
scarcity_class = "scalable"
product_subcategory = "technical_clothing"
base_premium_multiplier = 2.8
premium_floor = 0.20
origin_system = "GJ 475"
terroir_locked = false
currency_denomination = "tractus"
shadow_viable = false
brand_tier = "volume"
halo_brand_id = "thrds-origin-halo"
[[brand_inputs]]
brand_product_id = "thrds-standard-volume"
commodity_id = "textiles"
quantity = 1.20 # primary textile demand driver (volume tier production)
[[brand_inputs]]
brand_product_id = "thrds-standard-volume"
commodity_id = "organic_compounds"
quantity = 0.25
# ==========================================================================
# BÍFRÖST MARMOR (Compact / north_reach — terroir, appreciating)
# Kvitfjell moon marble quarry, Nyrheim (GJ 3737). Nyrheim Cooperative subsidiary.
# Inputs: stone (raw marble) + chemicals (polishing, finishing agents).
# Shadow viable: Compact-adjacent, some Sol trade on interior luxury markets.
# ==========================================================================
[[brand_products]]
brand_product_id = "bifrost-grade-a-halo"
corp_id = "bifrost-marmor"
product_name = "Kvitfjell Grade A"
brand_category = "terroir"
value_trajectory = "appreciating"
scarcity_class = "capped"
product_subcategory = "architectural_stone"
base_premium_multiplier = 22.0
premium_floor = 1.20
origin_system = "GJ 3737"
terroir_locked = true
currency_denomination = "mark"
shadow_viable = true
brand_tier = "halo"
[[brand_inputs]]
brand_product_id = "bifrost-grade-a-halo"
commodity_id = "stone"
quantity = 0.40 # high-purity calcite marble extraction — geological scarcity
[[brand_inputs]]
brand_product_id = "bifrost-grade-a-halo"
commodity_id = "chemicals"
quantity = 0.10 # precision polishing compounds
[[brand_products]]
brand_product_id = "bifrost-commercial-volume"
corp_id = "bifrost-marmor"
product_name = "Kvitfjell Commercial"
brand_category = "terroir"
value_trajectory = "appreciating"
scarcity_class = "constrained"
product_subcategory = "architectural_stone"
base_premium_multiplier = 5.5
premium_floor = 0.40
origin_system = "GJ 3737"
terroir_locked = true
currency_denomination = "mixed"
shadow_viable = true
brand_tier = "volume"
halo_brand_id = "bifrost-grade-a-halo"
[[brand_inputs]]
brand_product_id = "bifrost-commercial-volume"
commodity_id = "stone"
quantity = 1.50 # commercial-grade quarrying — volume demand node
[[brand_inputs]]
brand_product_id = "bifrost-commercial-volume"
commodity_id = "chemicals"
quantity = 0.30