"""Focused presentation-repair checks for numberdb.org/T663.
Run with Sage: sage -python repair_checks.py
Place generate.py, checks.py, table-before.json and table-proposed.json beside it.
This reads local snapshots and writes only its JSON result to stdout.
It does not publish, offer, or independently approve the argument selection.
"""
import ast,json,platform,re
from pathlib import Path
from decimal import Decimal
import numberdb.sage as numberdb
import mpmath as mp
from sage.env import SAGE_VERSION
from generate import BertinP, COMMENTS, density
from checks import modular
root=Path(__file__).resolve().parent
before=json.loads((root/'table-before.json').read_text())
after=json.loads((root/'table-proposed.json').read_text())
expected=[str(k) for k in range(13)]+['18']
assert [p['k'] for p in BertinP().enumerate()]==list(after['Numbers'])==expected
assert before['Parameters']==after['Parameters']
assert [(k,v['number']) for k,v in before['Numbers'].items()]==[(k,v['number']) for k,v in after['Numbers'].items()]
assert BertinP.digits==100
assert all(after['Numbers'][str(k)]['comment']==v for k,v in COMMENTS.items())
assert r'\tau' not in json.dumps(after)
f0=before['Formulas']['formula-jensen']; f1=after['Formulas']['formula-jensen']
assert f1.replace(r'$, where $\displaystyle ',r',\qquad ',1).replace(r'$ and $\displaystyle ',r',\qquad ',1)==f0
program=ast.parse(after['Programs']['program-python']['code'])
generator=ast.parse((root/'generate.py').read_text())
for name in ('density','compute'):
    p=next(n for n in program.body if isinstance(n,ast.FunctionDef) and n.name==name)
    g=next(n for n in generator.body if isinstance(n,ast.FunctionDef) and n.name==name)
    assert ast.dump(p,include_attributes=False)==ast.dump(g,include_attributes=False)
report={'table':'T663','manifest':'agents/runs/20261102T001449Z-repair-skills/manifest.json',
        'skill_sha256':{'local':'a2b28d9953264d7b0ca62663785c2952190c5be6d6d3597fd695d9a54d606278','live':'a2b28d9953264d7b0ca62663785c2952190c5be6d6d3597fd695d9a54d606278'},
        'versions':{'sage':SAGE_VERSION,'python':platform.python_version(),'mpmath':mp.__version__},
        'enumeration':expected,'values_unchanged':True,'formula_math_unchanged':True,
        'program_functions_match_generator':True,'generator_comments_match_rows':True,
        'method':'Existing attached modular checker at two freshly recomputed working precisions; no Jensen quadrature used for these comparisons. This is a repair check, not a new independent critique.',
        'rigour':'Heuristic agreement, not certified enclosures; exact integer input arguments; auxiliary eta parameters recomputed at each precision.',
        'rows':[]}
with mp.workdps(200):
    # Known-answer control before using the comparison on all rows.
    control=mp.im(mp.polylog(2,mp.exp(mp.j*mp.pi/3)))/mp.pi
    v=mp.mpf(modular(0,150)[0]); assert mp.isfinite(v) and abs(v-control)<mp.mpf('1e-140')
    stored=before['Numbers']['0']['number']; ulp=mp.power(10,Decimal(stored).as_tuple().exponent)
    assert abs(mp.mpf(stored)+mp.mpf('1e-90')-control)>ulp
    report['control']={'smyth_dilog_error':mp.nstr(abs(v-control),12),'perturbation_rejected':True}
    for k in expected:
        low=modular(int(k),140); high=modular(int(k),180)
        a,b=mp.mpf(low[0]),mp.mpf(high[0]); assert mp.isfinite(a) and mp.isfinite(b)
        text=after['Numbers'][k]['number']; u=mp.power(10,Decimal(text).as_tuple().exponent)
        ratio=abs(mp.mpf(text)-b)/u; agreement=-mp.log10(abs(a-b)/max(1,abs(a),abs(b)))
        assert ratio<1 and agreement>130
        report['rows'].append({'k':k,'stored_error_ulps':mp.nstr(ratio,15),'agreement_digits':mp.nstr(agreement,15),'eta_residual_180':high[1],'series_tail_180':high[2]})
    # Evaluate both mathematical expressions in the reformatted density.
    errors=[]
    for s in [mp.mpf(-4),-2,-1,mp.mpf(1)/3,1,2,4]:
        kform=mp.ellipk(1-s*s/16)/(2*mp.pi**2)
        assert mp.isfinite(kform)
        errors.append(abs(kform-density(s)))
    report['density_identity_max_error']=mp.nstr(max(errors),12)
    assert max(errors)<mp.mpf('1e-190')
    jerrors=[]
    for a in [-5,-3,-2,-1,0,1,2,3,5]:
        root1=(mp.mpf(a)+mp.sqrt(mp.mpf(a)**2-4))/2
        root2=(mp.mpf(a)-mp.sqrt(mp.mpf(a)**2-4))/2
        jroots=sum(mp.log(max(1,abs(z))) for z in (root1,root2))
        jpiece=0 if abs(a)<=2 else mp.acosh(mp.mpf(abs(a))/2)
        jerrors.append(abs(jroots-jpiece))
    report['jensen_branch_max_error']=mp.nstr(max(jerrors),12)
    assert max(jerrors)<mp.mpf('1e-190')
print(json.dumps(report,indent=2))
