Files

50 lines
2.5 KiB
Python

"""The quantitative bar (§5.1, §6.6) — the single gate between nomination and the frontier judge.
Two tiers:
- evidence bar → clears hard gates → WRITE A LEDGER ROW (the denominator, §6.6), even if never judged.
- promotion bar → also clears the score threshold → goes to the frontier judge.
THE GLOBAL META-RULE (applied to every scorer): no candidate clears on a single source or single
cluster — EISC_adj >= 2.0 AND K_eff >= 2. This is the §2.1 anti-lonely-outlier law, enforced once.
"""
from __future__ import annotations
EISC_FLOOR = 2.0
KEFF_FLOOR = 2
# Defaults; overridable via the score_thresholds table (so the backtest can sweep without code edits).
DEFAULT_MIN_SCORE = {"under_acted": 0.3, "emergence": 2.0, "contrarian": 1.5,
"convergence": 2.5, "intersection": 2.0}
def _min_score(conn, scorer: str) -> float:
if conn is not None:
row = conn.execute("SELECT min_score FROM score_thresholds WHERE scorer=?", (scorer,)).fetchone()
if row and row[0] is not None:
return float(row[0])
return DEFAULT_MIN_SCORE.get(scorer, 0.0)
def evaluate(scorer: str, result: dict, *, conn=None) -> tuple[bool, bool]:
"""Returns (cleared_evidence_bar, cleared_promotion_bar)."""
if scorer == "under_acted":
return _under_acted(result, _min_score(conn, scorer))
return (False, False) # Job A scorers wired with the forward pilot
def _under_acted(result: dict, min_score: float) -> tuple[bool, bool]:
i = result["inputs"]
breaker = bool(i.get("is_breaker"))
# §4.4 Job B = "rising INDEPENDENT corroboration". EISC>=2.0 enforces independence (shared-guest +
# same-cluster discounting), so this is NOT an isolated point or one-guest echo (§2.1). Cross-cluster
# (k_eff>=2) is the §4.5 GOLD for Job A DISCOVERY — NOT a hard gate for Job B corroboration: N
# independent energy companies confirming a power thesis is real corroboration. Cross-cluster still
# BOOSTS the score (eisc_corrob = eisc_adj includes the xcluster_mult) so cross-cluster ranks first.
corroborated = (i.get("n_confirmed", 0) >= 4 and i.get("n_src", 0) >= 2
and i.get("eisc_corrob", 0.0) >= EISC_FLOOR and i.get("a_corrob", 0.0) > 0)
conv_ok = breaker or i.get("conviction_weight", 0.0) >= 0.7 # med-high / high
expo_ok = breaker or i.get("exposure") in ("none", "lt2") # genuine exposure gap
evidence = corroborated and conv_ok and expo_ok
promotion = evidence and result["score"] >= min_score
return evidence, promotion