#!/usr/bin/env python3
from __future__ import annotations
import hashlib, json, math
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]
R = ROOT / 'research' / 'proton_origin'
OUT = ROOT / 'results' / 'row29_proton_origin' / 'result.json'
OUT.parent.mkdir(parents=True, exist_ok=True)

EXPECTED_MAIN_SHA = 'fd4fe7cf9a0d42e9a9a1def50d49c4a03d8fcd6772f857cc5a269e183986e34a'
EXPECTED_FORWARD_SHA = '3d3058e25117f4b8fe7c97dd124bcdc35e6b7ce1a644a8c568d40b0ac15fb921'
EXPECTED_CLOSEOUT_SHA = '00809ce9ab9fb021423bb1fa9e049eb89e0183999b073aa1f8c27d8e0e2f964e'

def sha(p: Path) -> str:
    return hashlib.sha256(p.read_bytes()).hexdigest()

def load(name: str):
    return json.loads((R / name).read_text(encoding='utf-8'))

forward_name = 'PROTON_ORIGIN_CLS_RGI_QUARK_HARDENING_V2_2026-08-16.json'
diag_name = 'PROTON_ORIGIN_CLS_RGI_QUARK_HARDENING_V2_POSTFREEZE_DIAGNOSTICS_2026-08-16.json'
closeout_name = 'PROTON_ORIGIN_RESULT04_FINAL_CLOSEOUT_V2_2026-08-16.json'
flavor_name = 'PROTON_ORIGIN_FLAVOR_BOUNDARY_CLOSEOUT_2026-08-16.json'

forward = load(forward_name)
diag = load(diag_name)
closeout = load(closeout_name)
flavor = load(flavor_name)

forward_sha = sha(R / forward_name)
closeout_sha = sha(R / closeout_name)
main_sha = sha(ROOT / 'main.tex')

model_weights = [float(v['weight']) for v in forward['models'].values()]
weighted = sum(float(v['weight']) * float(v['M_GeV']) for v in forward['models'].values())
central = float(forward['model_avg_central_GeV'])
sigma = float(forward['MC']['sigma_GeV'])

checks = {
    'main_tex_protected_unchanged': main_sha == EXPECTED_MAIN_SHA,
    'forward_v2_hash_matches_frozen_record': forward_sha == EXPECTED_FORWARD_SHA,
    'closeout_v2_hash_matches_frozen_record': closeout_sha == EXPECTED_CLOSEOUT_SHA,
    'closeout_points_to_forward_hash': closeout['forward_sha256'] == forward_sha,
    'diagnostics_point_to_forward_hash': diag['forward_sha256'] == forward_sha,
    'holdout_not_used_in_forward_calculation': forward['holdout_used'] is False and closeout['forward_holdout_used'] is False,
    'no_post_freeze_retuning': diag['no_post_freeze_retuning'] is True,
    'model_weights_sum_to_one': abs(sum(model_weights) - 1.0) < 1e-12,
    'weighted_mean_reproduces_forward': abs(weighted - central) < 1e-12,
    'finite_positive_forward_uncertainty': math.isfinite(sigma) and sigma > 0.0,
    'final_verdict_is_target_isolated_isoQCD_pass': closeout['verdict'] == 'PASS_TARGET_ISOLATED_ISOQCD_NUCLEON_MASS_CLOSURE',
    'flavor_origin_kept_separate': closeout['scientific_boundary']['flavor_origin'].startswith('SEPARATE_FUTURE_RESEARCH'),
    'physical_charged_proton_not_overclaimed': closeout['scientific_boundary']['proton_specific_QED_isospin'].startswith('OPEN_SEPARATE_SUBGATE'),
    'pdf_policy_preserved': closeout['publication_policy'].startswith('Ron updates the final PDF himself.'),
    'v22_flavor_derivation_not_claimed': flavor['v22_status'] == 'FAIL_UNIQUE_FIRST_GENERATION_YUKAWA_DERIVATION',
}
passed = all(checks.values())

result = {
    'row': 29,
    'gate': 'proton_origin_isoqcd_nucleon_mass_closure',
    'context': 'POST_RELEASE_RESEARCH',
    'tier': 'Diagnostic',
    'blocking': False,
    'verdict': 'PASS' if passed else 'FAIL',
    'status': 'PASS_TARGET_ISOLATED_ISOQCD_NUCLEON_MASS_CLOSURE' if passed else 'FAIL_RESULT04_V2_INTEGRITY',
    'checks': checks,
    'result04': {
        'quantity': closeout['forward_quantity'],
        'M_N_isoQCD_MeV': 1000.0 * central,
        'sigma_MeV': 1000.0 * sigma,
        'AICc_preferred_model_MeV': float(closeout['preferred_AICc_model_MeV']),
        'n_ensembles': int(forward['n_ensembles']),
        'betas': forward['betas'],
        'forward_sha256': forward_sha,
        'closeout_sha256': closeout_sha,
    },
    'post_freeze_diagnostics': {
        'published_CLS_continuum_nucleon_crosscheck_MeV': 1000.0 * float(diag['published_CLS_continuum_nucleon_crosscheck']['value_GeV']),
        'difference_to_CLS_crosscheck_MeV': float(diag['published_CLS_continuum_nucleon_crosscheck']['difference_MeV']),
        'historical_physical_proton_diagnostic_difference_MeV': float(diag['archived_physical_proton_diagnostic']['difference_MeV']),
        'historical_physical_proton_diagnostic_absolute_percent': float(diag['archived_physical_proton_diagnostic']['absolute_percent_difference']),
        'warning': diag['archived_physical_proton_diagnostic']['warning'],
    },
    'claim_boundary': {
        'claimed': closeout['scientific_boundary']['what_is_claimed'],
        'not_claimed': closeout['scientific_boundary']['what_is_not_claimed'],
        'research_status': closeout['research_status'],
        'flavor_origin_status': flavor['v22_status'],
    },
    'protected_main_tex_sha256': main_sha,
    'notes': 'Result 04 V2 target-isolated isoQCD nucleon/matter-scale closure. Final PDF and main.tex remain untouched; flavor-origin and full QCD+QED charged-proton calculation remain separate research boundaries.',
}
OUT.write_text(json.dumps(result, indent=2, sort_keys=True) + '\n', encoding='utf-8')
print(json.dumps(result, indent=2, sort_keys=True))
