"""Check the T620 repair without changing its table or generator.

Run in a directory containing the unmodified generate.py and T620-before.json:
    sage -python repair_checks.py > repair-checks-evidence.json
The governing skill manifest is
agents/runs/20261030T074414Z-repair-skills/manifest.json.
Both archived skill versions have SHA-256
28ecbeeccb0c5e5d6eb541b5a5b0f88aec47b154374d909085116d34f5629199.
The n=31 example is computed for documentation testing only, not added as a row.
"""
from pathlib import Path
import contextlib
from decimal import Decimal
import hashlib
import io
import json
import platform
from generate import PolygonDirichletDeterminants, polygon_logdet
from sage.rings.rational_field import QQ
from sage.rings.real_arb import RealBallField
from sage.env import SAGE_VERSION

root=Path(__file__).resolve().parent
raw=(root/'T620-before.json').read_bytes()
doc=json.loads(raw)
g=PolygonDirichletDeterminants()

def rational_decimal(value):
    a,b=Decimal(value).as_integer_ratio()
    return QQ(a)/QQ(b)

def stored_bounds(value):
    middle=rational_decimal(value)
    ulp=QQ(10)**Decimal(value).as_tuple().exponent
    return middle-ulp,middle+ulp

rows=[({'n':n,'convention':convention},value)
      for n,group in doc['Numbers'].items() for convention,value in group.items()]
assert [p for p,v in rows]==list(g.enumerate())
checks=[]
for params,stored in rows:
    value=g.value(params,100)
    fresh=polygon_logdet(int(params['n']),750)
    if params['convention']=='det': fresh=fresh.exp()
    lo,hi=stored_bounds(stored)
    assert value.is_finite() and fresh.is_finite()
    assert value.accuracy()>=330 and fresh.accuracy()>=660
    assert value>lo and value<hi and fresh>lo and fresh<hi
    assert value.overlaps(fresh)
    checks.append({'params':params,'default_accuracy_bits':int(value.accuracy()),'fresh_accuracy_bits':int(fresh.accuracy()),'both_enclosures_inside_stored_interval':True})
field=RealBallField(750)
controls={3:field(QQ(1)/3).gamma()/(field.pi()**(QQ(2)/3)*field(3)**(QQ(11)/12)),
          4:field(QQ(1)/4).gamma()/(field(2)**(QQ(7)/4)*field.pi()**(QQ(3)/4))}
for n,control in controls.items():
    assert control.is_finite() and control.accuracy()>700
    lo,hi=stored_bounds(doc['Numbers'][str(n)]['det'])
    assert control>lo and control<hi
    assert control.overlaps(polygon_logdet(n,750).exp())

snippet="# Download the attached generate.py into the current directory.\nfrom generate import PolygonDirichletDeterminants\ng = PolygonDirichletDeterminants()\nprint(g.value({'n': '31', 'convention': 'det'}, 100))\n"
buffer=io.StringIO()
with contextlib.redirect_stdout(buffer): exec(snippet,{})
example=g.value({'n':'31','convention':'det'},100)
fresh=polygon_logdet(31,750).exp()
assert example.is_finite() and example>0 and example.accuracy()>330
assert fresh.is_finite() and fresh.accuracy()>660 and example.overlaps(fresh)
result={
    'table':'T620','purpose':'Presentation repair verification; no numerical edits',
    'skill_manifest':'agents/runs/20261030T074414Z-repair-skills/manifest.json',
    'skill_versions':[{'source':source,'sha256':'28ecbeeccb0c5e5d6eb541b5a5b0f88aec47b154374d909085116d34f5629199'} for source in ('local','live')],
    'document_sha256':hashlib.sha256(raw).hexdigest(),
    'generator_sha256':hashlib.sha256((root/'generate.py').read_bytes()).hexdigest(),
    'script_sha256':hashlib.sha256(Path(__file__).read_bytes()).hexdigest(),
    'versions':{'sage':SAGE_VERSION,'python':platform.python_version()},
    'enumeration_matches_all_56_stored_rows':True,'checked_entries':checks,
    'triangle_square_closed_form_controls_passed':True,
    'program':{'code':snippet,'output':buffer.getvalue(),'n31_default_accuracy_bits':int(example.accuracy()),'n31_fresh_accuracy_bits':int(fresh.accuracy()),'n31_precision_enclosures_overlap':True,'row_added':False},
    'limitations':'Recomputed all stored enclosures with the attached generator at two precisions; triangle/square use separate Gamma closed forms. No new independent numerical proof for general n is asserted.'}
print(json.dumps(result,indent=2))
