"""Check T533's unchanged values during the link repair.
Run: sage -python repair-checks-20261027.py document-before.json generate.py
With agents/sage.sh, mount both data files beside this script.
The exact convolution check is independent of generate.py's Bessel-series
coefficient extraction. No floating point or approximated argument is used.
"""
import numberdb.sage as numberdb
from sage.rings.rational_field import QQ
from sage.env import SAGE_VERSION
from fractions import Fraction as F
from pathlib import Path
import hashlib, importlib.util, json, platform, sys
w=Path(__file__).resolve().parent
path=Path(sys.argv[1]) if len(sys.argv)>1 else w/'document-before.json'
generator_path=Path(sys.argv[2]) if len(sys.argv)>2 else w/'generate.py'
doc=json.loads(path.read_text())
def moments(nu, maximum):
    nu=F(nu)
    values=[F(0),F(1,4)/(nu+1)]
    for n in range(2,maximum+1):
        values.append(sum((values[r]*values[n-r] for r in range(1,n)),F(0))/(nu+n))
    return values
assert moments('0',3)[1:]==[F(1,4),F(1,32),F(1,192)]
assert moments('1/2',3)[1:]==[F(1,6),F(1,90),F(1,945)]
expected=[{'nu':nu,'n':n} for nu,block in doc['Numbers'].items() for n in block]
assert len(expected)==96
assert list(doc['Numbers'])==[str(F(a,2)) for a in range(8)]
independent=0
for nu,block in doc['Numbers'].items():
    assert list(block)==[str(n) for n in range(1,13)]
    vals=moments(nu,12)
    for n,value in block.items():
        assert F(value)==vals[int(n)]
        independent+=1
perturbed=F(doc['Numbers']['7/2']['12'])+F(1,10**100)
assert perturbed!=moments('7/2',12)[12]
spec=importlib.util.spec_from_file_location('t533_attached_generator',generator_path)
mod=importlib.util.module_from_spec(spec);spec.loader.exec_module(mod)
gen=mod.BesselRayleighSums()
assert list(gen.enumerate())==expected
for p in expected:
    stored=F(doc['Numbers'][p['nu']][p['n']])
    assert gen.value(p,100)==QQ(stored.numerator)/QQ(stored.denominator)
program={}
exec(doc['Programs']['program-python']['code'],program)
for p in expected:
    assert program['rayleigh'](p['nu'],int(p['n']))==F(doc['Numbers'][p['nu']][p['n']])
print(json.dumps({
 'table':'T533','purpose':'Verification of unchanged exact values for prose repair; not an independent argument-selection verdict',
 'skill_manifest':'agents/runs/20261027T001754Z-repair-skills/manifest.json',
 'skill_sha256':'b4d51ded0d52cfe3dcc0859de0845c3879b0c2363273ba7e809a7e06ded40b18',
 'document_sha256':hashlib.sha256(path.read_bytes()).hexdigest(),
 'generator_sha256':hashlib.sha256(generator_path.read_bytes()).hexdigest(),
 'python':platform.python_version(),'sage':SAGE_VERSION,
 'independent_exact_recurrence_matches':independent,'generator_exact_matches':96,
 'program_exact_matches':96,'enumeration_order_matches':True,
 'known_nonzero_controls_passed':True,'perturbed_value_detected':True,
 'new_values':0,'uncertainty':'Exact rational nu and integer n; exact rational arithmetic throughout; no argument approximation or error tolerance.'
},indent=2))
