fix(economics): address PR #148 review — dry-run guard + pin validation
Review fixes (Hoshe/Tyre, both APPROVE): - populate_trait_templates / populate_atlas_body_trait_bias: the table DELETEs ran unconditionally (safe only via transaction rollback on dry-run, and divergent from every other populate_* function). Restructured so validation + guardrails always run (dry-run now actually surfaces the would-bake counts and catches errors) but mutations happen only under `if not dry_run:`. Verified: --dry-run reports 28 templates, writes nothing. - atlas_body_trait_bias: reject `pin` entries that carry a weight_multiplier_bps (pin is mandatory, no multiplier) — closes a silent- accept gap before #1017 authors ~30-40 real pins. Deferred (noted on tickets): visual_bundle fallback-map completeness (Phase-5/Araminta), pin-count-vs-K bake check (#1017 acceptance), geographic_sector pool-narrowing semantics (#977). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Binary file not shown.
@@ -2082,12 +2082,10 @@ def populate_trait_templates(conn: sqlite3.Connection, dry_run: bool) -> int:
|
||||
(the table still exists for the downstream pipeline). Deterministic rebuild:
|
||||
clears trait_templates (cascading atlas_body_trait_bias) first.
|
||||
"""
|
||||
if dry_run:
|
||||
# Still surface row count that WOULD be baked.
|
||||
pass
|
||||
conn.execute("DELETE FROM atlas_body_trait_bias")
|
||||
conn.execute("DELETE FROM trait_templates")
|
||||
if not ARCHITECTURE_TRAIT_CATALOG_TOML.exists():
|
||||
if not dry_run:
|
||||
conn.execute("DELETE FROM atlas_body_trait_bias")
|
||||
conn.execute("DELETE FROM trait_templates")
|
||||
return 0
|
||||
with open(ARCHITECTURE_TRAIT_CATALOG_TOML, "rb") as f:
|
||||
data = tomllib.load(f)
|
||||
@@ -2153,15 +2151,19 @@ def populate_trait_templates(conn: sqlite3.Connection, dry_run: bool) -> int:
|
||||
for e in gerrors:
|
||||
print(f" - {e}")
|
||||
raise _ImportAborted()
|
||||
conn.executemany(
|
||||
"""INSERT INTO trait_templates
|
||||
(tag, label, cultural_description, corridor_pool, geographic_sector,
|
||||
bulk_class_gate, production_ubiquity_gate, min_prosperity_bps,
|
||||
base_weight, weight_mods, zone_affinity, allow_tags, block_tags,
|
||||
era_scope, visual_bundle)
|
||||
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)""",
|
||||
rows,
|
||||
)
|
||||
# Validation/guardrails run on dry-run too; only mutate when committing.
|
||||
if not dry_run:
|
||||
conn.execute("DELETE FROM atlas_body_trait_bias")
|
||||
conn.execute("DELETE FROM trait_templates")
|
||||
conn.executemany(
|
||||
"""INSERT INTO trait_templates
|
||||
(tag, label, cultural_description, corridor_pool, geographic_sector,
|
||||
bulk_class_gate, production_ubiquity_gate, min_prosperity_bps,
|
||||
base_weight, weight_mods, zone_affinity, allow_tags, block_tags,
|
||||
era_scope, visual_bundle)
|
||||
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)""",
|
||||
rows,
|
||||
)
|
||||
return len(rows)
|
||||
|
||||
|
||||
@@ -2175,8 +2177,9 @@ def populate_atlas_body_trait_bias(conn: sqlite3.Connection, dry_run: bool) -> i
|
||||
multiplier). Hero-pin *content* is authored in #1017. Absent source -> 0
|
||||
rows. Must run AFTER populate_trait_templates.
|
||||
"""
|
||||
conn.execute("DELETE FROM atlas_body_trait_bias")
|
||||
if not ARCHITECTURE_TRAIT_BIAS_TOML.exists():
|
||||
if not dry_run:
|
||||
conn.execute("DELETE FROM atlas_body_trait_bias")
|
||||
return 0
|
||||
with open(ARCHITECTURE_TRAIT_BIAS_TOML, "rb") as f:
|
||||
data = tomllib.load(f)
|
||||
@@ -2205,18 +2208,22 @@ def populate_atlas_body_trait_bias(conn: sqlite3.Connection, dry_run: bool) -> i
|
||||
errors.append(f"{loc}: boost weight_multiplier_bps must be 10001..30000 (<=3x), got {mult}")
|
||||
if kind == "suppress" and not (mult and 3300 <= mult <= 9999):
|
||||
errors.append(f"{loc}: suppress weight_multiplier_bps must be 3300..9999 (>=0.33x, never 0), got {mult}")
|
||||
if kind == "pin" and mult is not None:
|
||||
errors.append(f"{loc}: pin is mandatory and must not carry weight_multiplier_bps (got {mult})")
|
||||
rows.append((bid, tag, kind, mult, b.get("note")))
|
||||
if errors:
|
||||
print(f" TRAIT BIAS ERRORS ({len(errors)}):")
|
||||
for e in errors:
|
||||
print(f" - {e}")
|
||||
raise _ImportAborted()
|
||||
conn.executemany(
|
||||
"""INSERT INTO atlas_body_trait_bias
|
||||
(body_id, template_tag, bias_kind, weight_multiplier_bps, note)
|
||||
VALUES (?,?,?,?,?)""",
|
||||
rows,
|
||||
)
|
||||
if not dry_run:
|
||||
conn.execute("DELETE FROM atlas_body_trait_bias")
|
||||
conn.executemany(
|
||||
"""INSERT INTO atlas_body_trait_bias
|
||||
(body_id, template_tag, bias_kind, weight_multiplier_bps, note)
|
||||
VALUES (?,?,?,?,?)""",
|
||||
rows,
|
||||
)
|
||||
return len(rows)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user