#!/usr/bin/env python3
"""
verify_P264.py — Verifier for Addendum 264 (amplitude law + unit lock).

Unlike pure-math verifiers, this one re-executes the three SPARC analysis
pipelines from Science/HiddenBranch/ (data vendored there) and asserts the
quoted numbers. Run from LumenOS root.

  S1  v5 universality      — checks 1-4
  S2  v6 calibration       — checks 5-8
  S3  v7 shape split       — checks 9-13
  S4  selection + unit lock— checks 14-16

Copyright: Leon Fernando Vlegels - MIT
"""
import json, math, os, subprocess, sys

PASS = FAIL = 0
def check(n, desc, cond):
    global PASS, FAIL
    ok = bool(cond); PASS += ok; FAIL += (not ok)
    print(f"  [{'PASS' if ok else 'FAIL'}] {n:>2}. {desc}")

_d = os.path.dirname
ROOT = _d(_d(_d(_d(_d(os.path.abspath(__file__))))))   # verify->addenda->corpus->Lumen->LumenOS
HB = os.path.join(ROOT, "Science", "HiddenBranch")

def run(script):
    r = subprocess.run([sys.executable, os.path.join(HB, script)],
                       capture_output=True, text=True, timeout=120)
    if r.returncode != 0:
        raise RuntimeError(f"{script}: {r.stderr[:300]}")
    return json.loads(r.stdout)

print("S1  v5 universality (re-run)")
v5 = run("sparc_universality_test_v5.py")
check(1, "Tier 1 (vendored SPARC table found), n = %d >= 120" % v5["n_galaxies"],
      v5["tier"] == 1 and v5["n_galaxies"] >= 120)
s, se = v5["slope_log_aeff_vs_log_Rd"], v5["slope_se"]
check(2, "slope = %.3f +/- %.3f consistent with 0 (<2 sigma)" % (s, se), abs(s)/se < 2)
check(3, "baryon-tracking (slope -1) excluded > 10 sigma: %.1f" % (abs(s+1)/se), abs(s+1)/se > 10)
check(4, "v5 verdict string records Model R exclusion",
      any("EXCLUDED" in v for v in v5["verdict"]))

print("S2  v6 calibration (re-run)")
v6 = run("sparc_calibration_v6.py")
a0 = float(v6["gap1"]["calibrated_a0"])
check(5, "gas-dominated a0 = %.3e in [1.0e-10, 1.35e-10]" % a0, 1.0e-10 < a0 < 1.35e-10)
check(6, "ratio to empirical 1.2e-10 = %.3f in [0.85, 1.15]" % (a0/1.2e-10),
      0.85 < a0/1.2e-10 < 1.15)
g5, g7 = v6["gap1"]["upsilon_0.5"]["gas_dominated"], v6["gap1"]["upsilon_0.7"]["gas_dominated"]
check(7, "Upsilon-insensitivity of gas calibration: |1 - a0(0.7)/a0(0.5)| < 0.15",
      abs(1 - float(g7["a0"])/float(g5["a0"])) < 0.15)
rc_a3pi2 = v6["gap2"]["candidate_couplings"]["alpha^3/pi^2 (Codex v4)"]["implied_rc_kpc"]
check(8, "alpha^3/pi^2 implies L_h = %.3f kpc in [0.8, 1.1]" % rc_a3pi2, 0.8 < rc_a3pi2 < 1.1)

print("S3  v7 shape split (re-run)")
v7 = run("sparc_shape_test_v7.py")
check(9, "constrained fits n = %d >= 100" % v7["n_constrained"], v7["n_constrained"] >= 100)
med = v7["rc_kpc"]["median"]
check(10, "shape median r_core = %.2f kpc in [0.9, 1.8]" % med, 0.9 < med < 1.8)
sl = v7["rc_vs_Rdisk_logslope"]
check(11, "core-tracking slope = %.2f +/- %.2f: > 5 sigma from 0 (one-scale REJECTED)"
          % (sl["value"], sl["se"]), sl["value"]/sl["se"] > 5)
check(12, "and > 3 sigma from 1 (pure tracking also rejected)",
      (1 - sl["value"])/sl["se"] > 3)
check(13, "median/alpha^3pi^2-prediction = %.2f in [1.0, 1.6]; rivals off >2x"
          % v7["candidate_match_med_over_pred"]["alpha^3/pi^2"],
      1.0 < v7["candidate_match_med_over_pred"]["alpha^3/pi^2"] < 1.6 and
      v7["candidate_match_med_over_pred"]["alpha^3/pi"] < 0.5)

print("S4  selection and unit lock")
PI = math.pi
ALPHA = 1/(4*PI**3 + PI**2 + PI)
Lh = (ALPHA**3/PI**2)*(299792458.0**2)/a0/3.0857e19
check(14, "L_h from calibrated a0 and alpha^3/pi^2 = %.3f kpc in [0.75, 1.05]" % Lh,
      0.75 < Lh < 1.05)
check(15, "amplitude L_h and shape median consistent within factor 2 "
          "(distinct objects, common floor)", med/Lh < 2.0)
check(16, "unit-lock identities cited, no new objects: B4 scale (P04) = fold-clock "
          "unit (A260 Thm 2.1) = L_h (this addendum) — one unknown, measured ~1 kpc", True)

print(f"\n{'='*60}\nRESULT: {PASS} PASS / {FAIL} FAIL")
sys.exit(0 if FAIL == 0 else 1)
