close guardrail gaps and fix the scoring pipeline top to bottom

Constraint resolver: aggregate mass/footprint across a combo instead of
pairwise-only checks, treat medium/atmosphere as agreement not supply/demand,
reduce multi-provider checks by best/sum instead of AND-ing every provider,
fail closed on unrecognized mutex values, add a propulsion-viability
(thrust-to-weight) rule. Seed data updated to match (nuclear/solar-sail
footprint floors, water-medium exclusions, explicit ground/gravity providers).

Domain metric units were stored globally per metric name instead of
per-domain, silently corrupting cost_efficiency for every domain but the
first one seeded — fixed with a schema migration.

Stub estimator's cost_efficiency/safety/availability/reliability were a
backwards formula and flat constants; replaced with heuristics grounded in
each entity's thrust_profile/energy_form/infrastructure.

LLM estimate_physics() now receives each metric's unit and expected range
instead of a bare name, fixing wildly miscalibrated estimates traced back to
the prompt's own hardcoded example anchoring the model to the wrong order of
magnitude. Sharpened the safety-estimation and plausibility-review prompts.
Deduped provider parsing logic into llm/parsing.py.

Web pipeline form can now pick an LLM provider per run instead of only via
server env var.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-26 00:13:16 -05:00
parent 63295ab80e
commit 434df718d7
18 changed files with 836 additions and 175 deletions

View File

@@ -233,6 +233,16 @@ class Repository:
)
self.conn.commit()
def backfill_metric_unit(self, domain_name: str, metric_name: str, unit: str) -> None:
"""Set this domain-metric row's unit — unit is domain-scoped, not global to the metric name."""
self.conn.execute(
"""UPDATE domain_metric_weights SET unit = ?
WHERE domain_id = (SELECT id FROM domains WHERE name = ?)
AND metric_id = (SELECT id FROM metrics WHERE name = ?)""",
(unit, domain_name, metric_name),
)
self.conn.commit()
def add_domain(self, domain: Domain) -> Domain:
cur = self.conn.execute(
"INSERT INTO domains (name, description) VALUES (?, ?)",
@@ -244,10 +254,10 @@ class Repository:
mb.metric_id = metric_id
self.conn.execute(
"""INSERT INTO domain_metric_weights
(domain_id, metric_id, weight, norm_min, norm_max, lower_is_better)
VALUES (?, ?, ?, ?, ?, ?)""",
(domain_id, metric_id, weight, norm_min, norm_max, lower_is_better, unit)
VALUES (?, ?, ?, ?, ?, ?, ?)""",
(domain.id, metric_id, mb.weight, mb.norm_min, mb.norm_max,
int(mb.lower_is_better)),
int(mb.lower_is_better), mb.unit),
)
for dc in domain.constraints:
for val in dc.allowed_values:
@@ -273,7 +283,7 @@ class Repository:
if not row:
return None
weights = self.conn.execute(
"""SELECT m.name, m.unit, dmw.weight, dmw.norm_min, dmw.norm_max,
"""SELECT m.name, dmw.unit, dmw.weight, dmw.norm_min, dmw.norm_max,
dmw.metric_id, dmw.lower_is_better
FROM domain_metric_weights dmw
JOIN metrics m ON dmw.metric_id = m.id
@@ -318,10 +328,10 @@ class Repository:
mb.metric_id = metric_id
self.conn.execute(
"""INSERT OR REPLACE INTO domain_metric_weights
(domain_id, metric_id, weight, norm_min, norm_max, lower_is_better)
VALUES (?, ?, ?, ?, ?, ?)""",
(domain_id, metric_id, weight, norm_min, norm_max, lower_is_better, unit)
VALUES (?, ?, ?, ?, ?, ?, ?)""",
(domain_id, metric_id, mb.weight, mb.norm_min, mb.norm_max,
int(mb.lower_is_better)),
int(mb.lower_is_better), mb.unit),
)
self.conn.commit()
return mb
@@ -332,15 +342,10 @@ class Repository:
) -> None:
self.conn.execute(
"""UPDATE domain_metric_weights
SET weight = ?, norm_min = ?, norm_max = ?, lower_is_better = ?
SET weight = ?, norm_min = ?, norm_max = ?, lower_is_better = ?, unit = ?
WHERE domain_id = ? AND metric_id = ?""",
(weight, norm_min, norm_max, int(lower_is_better), domain_id, metric_id),
(weight, norm_min, norm_max, int(lower_is_better), unit, domain_id, metric_id),
)
if unit:
self.conn.execute(
"UPDATE metrics SET unit = ? WHERE id = ?",
(unit, metric_id),
)
self.conn.commit()
def delete_metric_bound(self, domain_id: int, metric_id: int) -> None: