fix(content): add price_tier to brand layer schema, import, and V-B06 (#828 blocker)

price_tier was documented in D-189 §5 and present in brands.toml but
silently discarded on import — absent from schema, INSERT, and V-B06.

- Add price_tier TEXT column to brand_products CREATE TABLE
- Add COLUMN_MIGRATIONS entry for ALTER TABLE on existing DBs
- Add VALID_PRICE_TIERS constant (mass/premium/luxury/flagship/institutional)
- Include price_tier in product_rows tuple and INSERT OR REPLACE
- Add price_tier to V-B06 enum checks; skip NULL (nullable column)
- Backfill 4 pre-amendment anchor brands (8 entries): Calloway flagship/premium,
  VGV luxury/premium, thrds luxury/premium, Bífröst flagship/luxury

V-B01..V-B06 all pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-19 15:37:33 +02:00
co-authored by Claude Sonnet 4.6
parent cf3e14cc5e
commit add2507eac
3 changed files with 17 additions and 2 deletions
+9 -2
View File
@@ -72,6 +72,7 @@ CREATE TABLE IF NOT EXISTS brand_products (
shadow_viable INTEGER NOT NULL DEFAULT 0,
brand_tier TEXT NOT NULL,
halo_brand_id TEXT REFERENCES brand_products(brand_product_id),
price_tier TEXT,
updated_at TEXT DEFAULT (datetime('now'))
);
@@ -177,6 +178,7 @@ COLUMN_MIGRATIONS = [
("corporations", "behavioral_archetype", "TEXT"),
("corporations", "supply_chain_role", "TEXT"),
("corporations", "shadow_economy_access", "INTEGER DEFAULT 0"),
("brand_products", "price_tier", "TEXT"),
]
@@ -743,6 +745,7 @@ 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"}
VALID_PRICE_TIERS = {"mass", "premium", "luxury", "flagship", "institutional"}
def import_brands(
@@ -780,6 +783,7 @@ def import_brands(
int(p.get("shadow_viable", False)),
p["brand_tier"],
p.get("halo_brand_id"),
p.get("price_tier"),
))
input_rows = []
@@ -797,8 +801,8 @@ def import_brands(
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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
brand_tier, halo_brand_id, price_tier
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
product_rows,
)
conn.executemany(
@@ -947,12 +951,15 @@ def validate_brands(conn: sqlite3.Connection) -> list[str]:
("scarcity_class", VALID_SCARCITY_CLASSES),
("brand_tier", VALID_BRAND_TIERS),
("currency_denomination", VALID_CURRENCY_DENOMINATIONS),
("price_tier", VALID_PRICE_TIERS),
]
for column, valid_set in enum_checks:
bad = conn.execute(
f"SELECT brand_product_id, {column} FROM brand_products"
).fetchall()
for pid, value in bad:
if value is None:
continue # nullable columns (e.g. price_tier) may be unset
if value not in valid_set:
errors.append(
f"V-B06: brand_product '{pid}' has {column}='{value}'"