"""Read-only repair checks for numberdb.org/T604.

Run: sage -python repair-checks.py
Place T604-before.json, generate.py, finite_formulas.py and independent.py
beside this file. This reuses the unchanged attached algorithms; it is not
a fresh independent critique. No credential is needed for the saved document.
"""
import json
from pathlib import Path
from decimal import Decimal
from fractions import Fraction
import numberdb.sage as numberdb
from sage.rings.rational_field import QQ
from sage.rings.real_arb import RealBallField
from sage.env import SAGE_VERSION
from generate import HemisphereNeumann
from independent import continuation

ROOT = Path(__file__).resolve().parent
MANIFEST = 'agents/runs/20261029T082442Z-repair-skills/manifest.json'

def exact(value):
    f = Fraction(value)
    return QQ(f.numerator) / QQ(f.denominator)

def decimal_interval(text, field):
    d = Decimal(text)
    center = exact(d)
    ulp = QQ(10)**int(d.as_tuple().exponent)
    return field(center).add_error(field(ulp)), center-ulp, center+ulp

def inside(value, text, field):
    stored, lower, upper = decimal_interval(text, field)
    assert value.is_finite() and value.rad_as_ball() < field(10)**(-130)
    assert value > field(lower) and value < field(upper)
    assert not (value + field(10)**(-90)).overlaps(stored)

if __name__ == '__main__':
    doc = json.loads((ROOT / 'T604-before.json').read_text())
    print(json.dumps({'table': 'T604', 'skill_manifest': MANIFEST,
                     'skill_versions_sha256': {
                         'local': '28ecbeeccb0c5e5d6eb541b5a5b0f88aec47b154374d909085116d34f5629199',
                         'live': '28ecbeeccb0c5e5d6eb541b5a5b0f88aec47b154374d909085116d34f5629199'},
                     'sage': SAGE_VERSION, 'numberdb': numberdb.__version__}), flush=True)
    g = HemisphereNeumann()
    expected = [{'d': d, 'convention': c}
                for d, group in doc['Numbers'].items() for c in group]
    assert list(g.enumerate()) == expected
    R = RealBallField(800)
    min_bits = 10000
    for params in expected:
        text = doc['Numbers'][params['d']][params['convention']]
        value = g.value(params, 100)
        inside(value, text, R)
        min_bits = min(min_bits, int(value.accuracy()))
    for d, group in doc['Numbers'].items():
        det = decimal_interval(group['det'], R)[0]
        logdet = decimal_interval(group['logdet'], R)[0]
        assert det.is_finite() and logdet.is_finite()
        assert det.rad_as_ball() < R(10)**(-97)
        assert logdet.rad_as_ball() < R(10)**(-97)
        assert det > 0 and logdet.exp().overlaps(det)
        assert det.log().overlaps(logdet)
    # Nonzero interval control derived directly from Z_1(s)=zeta(2s).
    inside(2*R.pi(), doc['Numbers']['1']['det'], R)
    inside((2*R.pi()).log(), doc['Numbers']['1']['logdet'], R)
    # Re-execute the attached alternate spectral continuation at both parity
    # endpoints and the displayed low-dimensional cases. This is fresh output
    # from an existing algorithm, not a new independently authored checker.
    for d in (1, 2, 3, 19, 20):
        logdet, info = continuation(d)
        inside(logdet, doc['Numbers'][str(d)]['logdet'], R)
        inside(logdet.exp(), doc['Numbers'][str(d)]['det'], R)
        print(json.dumps({'d': d, 'alternate_continuation': info,
                          'stored_intervals_contain_enclosures': True}), flush=True)
    print(json.dumps({'status': 'PASS', 'generator_values_checked': 40,
                      'minimum_generator_accuracy_bits': min_bits,
                      'conversion_pairs_checked': 20,
                      'alternate_algorithm_values_checked': 10,
                      'perturbed_values_rejected': 52,
                      'enumeration_matches': True}), flush=True)
