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:
Binary file not shown.
@@ -72,6 +72,7 @@ CREATE TABLE IF NOT EXISTS brand_products (
|
|||||||
shadow_viable INTEGER NOT NULL DEFAULT 0,
|
shadow_viable INTEGER NOT NULL DEFAULT 0,
|
||||||
brand_tier TEXT NOT NULL,
|
brand_tier TEXT NOT NULL,
|
||||||
halo_brand_id TEXT REFERENCES brand_products(brand_product_id),
|
halo_brand_id TEXT REFERENCES brand_products(brand_product_id),
|
||||||
|
price_tier TEXT,
|
||||||
updated_at TEXT DEFAULT (datetime('now'))
|
updated_at TEXT DEFAULT (datetime('now'))
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -177,6 +178,7 @@ COLUMN_MIGRATIONS = [
|
|||||||
("corporations", "behavioral_archetype", "TEXT"),
|
("corporations", "behavioral_archetype", "TEXT"),
|
||||||
("corporations", "supply_chain_role", "TEXT"),
|
("corporations", "supply_chain_role", "TEXT"),
|
||||||
("corporations", "shadow_economy_access", "INTEGER DEFAULT 0"),
|
("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_SCARCITY_CLASSES = {"capped", "constrained", "scalable", "unlimited"}
|
||||||
VALID_BRAND_TIERS = {"halo", "volume"}
|
VALID_BRAND_TIERS = {"halo", "volume"}
|
||||||
VALID_CURRENCY_DENOMINATIONS = {"tractus", "mark", "mixed", "sol_adjacent"}
|
VALID_CURRENCY_DENOMINATIONS = {"tractus", "mark", "mixed", "sol_adjacent"}
|
||||||
|
VALID_PRICE_TIERS = {"mass", "premium", "luxury", "flagship", "institutional"}
|
||||||
|
|
||||||
|
|
||||||
def import_brands(
|
def import_brands(
|
||||||
@@ -780,6 +783,7 @@ def import_brands(
|
|||||||
int(p.get("shadow_viable", False)),
|
int(p.get("shadow_viable", False)),
|
||||||
p["brand_tier"],
|
p["brand_tier"],
|
||||||
p.get("halo_brand_id"),
|
p.get("halo_brand_id"),
|
||||||
|
p.get("price_tier"),
|
||||||
))
|
))
|
||||||
|
|
||||||
input_rows = []
|
input_rows = []
|
||||||
@@ -797,8 +801,8 @@ def import_brands(
|
|||||||
value_trajectory, scarcity_class, product_subcategory,
|
value_trajectory, scarcity_class, product_subcategory,
|
||||||
base_premium_multiplier, premium_floor, origin_system,
|
base_premium_multiplier, premium_floor, origin_system,
|
||||||
terroir_locked, currency_denomination, shadow_viable,
|
terroir_locked, currency_denomination, shadow_viable,
|
||||||
brand_tier, halo_brand_id
|
brand_tier, halo_brand_id, price_tier
|
||||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
||||||
product_rows,
|
product_rows,
|
||||||
)
|
)
|
||||||
conn.executemany(
|
conn.executemany(
|
||||||
@@ -947,12 +951,15 @@ def validate_brands(conn: sqlite3.Connection) -> list[str]:
|
|||||||
("scarcity_class", VALID_SCARCITY_CLASSES),
|
("scarcity_class", VALID_SCARCITY_CLASSES),
|
||||||
("brand_tier", VALID_BRAND_TIERS),
|
("brand_tier", VALID_BRAND_TIERS),
|
||||||
("currency_denomination", VALID_CURRENCY_DENOMINATIONS),
|
("currency_denomination", VALID_CURRENCY_DENOMINATIONS),
|
||||||
|
("price_tier", VALID_PRICE_TIERS),
|
||||||
]
|
]
|
||||||
for column, valid_set in enum_checks:
|
for column, valid_set in enum_checks:
|
||||||
bad = conn.execute(
|
bad = conn.execute(
|
||||||
f"SELECT brand_product_id, {column} FROM brand_products"
|
f"SELECT brand_product_id, {column} FROM brand_products"
|
||||||
).fetchall()
|
).fetchall()
|
||||||
for pid, value in bad:
|
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:
|
if value not in valid_set:
|
||||||
errors.append(
|
errors.append(
|
||||||
f"V-B06: brand_product '{pid}' has {column}='{value}' — "
|
f"V-B06: brand_product '{pid}' has {column}='{value}' — "
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ terroir_locked = true
|
|||||||
currency_denomination = "tractus"
|
currency_denomination = "tractus"
|
||||||
shadow_viable = true
|
shadow_viable = true
|
||||||
brand_tier = "halo"
|
brand_tier = "halo"
|
||||||
|
price_tier = "flagship"
|
||||||
|
|
||||||
[[brand_inputs]]
|
[[brand_inputs]]
|
||||||
brand_product_id = "calloway-single-malt-halo"
|
brand_product_id = "calloway-single-malt-halo"
|
||||||
@@ -90,6 +91,7 @@ currency_denomination = "tractus"
|
|||||||
shadow_viable = true
|
shadow_viable = true
|
||||||
brand_tier = "volume"
|
brand_tier = "volume"
|
||||||
halo_brand_id = "calloway-single-malt-halo"
|
halo_brand_id = "calloway-single-malt-halo"
|
||||||
|
price_tier = "premium"
|
||||||
|
|
||||||
[[brand_inputs]]
|
[[brand_inputs]]
|
||||||
brand_product_id = "calloway-reserve-volume"
|
brand_product_id = "calloway-reserve-volume"
|
||||||
@@ -123,6 +125,7 @@ terroir_locked = true
|
|||||||
currency_denomination = "tractus"
|
currency_denomination = "tractus"
|
||||||
shadow_viable = true
|
shadow_viable = true
|
||||||
brand_tier = "halo"
|
brand_tier = "halo"
|
||||||
|
price_tier = "luxury"
|
||||||
|
|
||||||
[[brand_inputs]]
|
[[brand_inputs]]
|
||||||
brand_product_id = "vgv-premier-cru-halo"
|
brand_product_id = "vgv-premier-cru-halo"
|
||||||
@@ -150,6 +153,7 @@ currency_denomination = "tractus"
|
|||||||
shadow_viable = false
|
shadow_viable = false
|
||||||
brand_tier = "volume"
|
brand_tier = "volume"
|
||||||
halo_brand_id = "vgv-premier-cru-halo"
|
halo_brand_id = "vgv-premier-cru-halo"
|
||||||
|
price_tier = "premium"
|
||||||
|
|
||||||
[[brand_inputs]]
|
[[brand_inputs]]
|
||||||
brand_product_id = "vgv-standard-volume"
|
brand_product_id = "vgv-standard-volume"
|
||||||
@@ -183,6 +187,7 @@ terroir_locked = true
|
|||||||
currency_denomination = "tractus"
|
currency_denomination = "tractus"
|
||||||
shadow_viable = false
|
shadow_viable = false
|
||||||
brand_tier = "halo"
|
brand_tier = "halo"
|
||||||
|
price_tier = "luxury"
|
||||||
|
|
||||||
[[brand_inputs]]
|
[[brand_inputs]]
|
||||||
brand_product_id = "thrds-origin-halo"
|
brand_product_id = "thrds-origin-halo"
|
||||||
@@ -210,6 +215,7 @@ currency_denomination = "tractus"
|
|||||||
shadow_viable = false
|
shadow_viable = false
|
||||||
brand_tier = "volume"
|
brand_tier = "volume"
|
||||||
halo_brand_id = "thrds-origin-halo"
|
halo_brand_id = "thrds-origin-halo"
|
||||||
|
price_tier = "premium"
|
||||||
|
|
||||||
[[brand_inputs]]
|
[[brand_inputs]]
|
||||||
brand_product_id = "thrds-standard-volume"
|
brand_product_id = "thrds-standard-volume"
|
||||||
@@ -244,6 +250,7 @@ terroir_locked = true
|
|||||||
currency_denomination = "mark"
|
currency_denomination = "mark"
|
||||||
shadow_viable = true
|
shadow_viable = true
|
||||||
brand_tier = "halo"
|
brand_tier = "halo"
|
||||||
|
price_tier = "flagship"
|
||||||
|
|
||||||
[[brand_inputs]]
|
[[brand_inputs]]
|
||||||
brand_product_id = "bifrost-grade-a-halo"
|
brand_product_id = "bifrost-grade-a-halo"
|
||||||
@@ -271,6 +278,7 @@ currency_denomination = "mixed"
|
|||||||
shadow_viable = true
|
shadow_viable = true
|
||||||
brand_tier = "volume"
|
brand_tier = "volume"
|
||||||
halo_brand_id = "bifrost-grade-a-halo"
|
halo_brand_id = "bifrost-grade-a-halo"
|
||||||
|
price_tier = "luxury"
|
||||||
|
|
||||||
[[brand_inputs]]
|
[[brand_inputs]]
|
||||||
brand_product_id = "bifrost-commercial-volume"
|
brand_product_id = "bifrost-commercial-volume"
|
||||||
|
|||||||
Reference in New Issue
Block a user