#!/usr/bin/env python3
"""Read-only exact replay of the50-step record; writes only VERIFY.json.
Run from any extracted packet: python3 evidence/verify.py
No journal writer is imported. The replay uses an independent reversal routine.
"""
from pathlib import Path
from fractions import Fraction
import json,hashlib,types,sys,runpy
R=Path(__file__).resolve().parent.parent
rows=json.loads((R/'journal.json').read_text())
assert [x['step'] for x in rows]==list(range(482,532))
def clean(x):
if isinstance(x,Fraction): return x.numerator if x.denominator==1 else str(x)
if isinstance(x,dict):return {str(k):clean(v) for k,v in x.items()}
if isinstance(x,(list,tuple)):return [clean(v) for v in x]
return x
def inverse(n):
if not isinstance(n,int) or n<0:raise ValueError('nonnegative integer required')
if n==0:return 0
digits=str(n);core=digits.rstrip('0');return int(core[::-1])*10**(len(digits)-len(core))
expected_prev='C481:4d7a97cf35348c8ea23a23079b0682f739bb5b4b0cc734e24e7b9bc6e0b19455'
assertion_count=0
for row in rows:
material={k:v for k,v in row.items() if k!='sha256'}
assert row['sha256']==hashlib.sha256(json.dumps(material,sort_keys=True).encode()).hexdigest()
assert row['predecessor_sha256']==expected_prev
expected_prev=row['sha256']
def begin(n,title,question,inputs,sources):
assert (n,title,question,clean(inputs),sources)==(row['step'],row['title'],row['question'],row['inputs'],row['sources'])
return {'step':n,'inputs':clean(inputs)}
def finish(item,results,finding,next_question,checks):
assert all(checks.values()),checks
assert (clean(results),finding,next_question,checks)==(row['results'],row['finding'],row['reassessment'],row['checks'])
fake=types.ModuleType('research')
for key,val in {'Path':Path,'F':Fraction,'ROOT':R,'E':Fraction(25,23),'P':Fraction(70,69),'J':Fraction(300,299),'json':json,'hashlib':hashlib,'clean':clean,'inv':inverse,'begin':begin,'finish':finish}.items():setattr(fake,key,val)
sys.modules['research']=fake
runpy.run_path(str(R/'evidence'/f"s{row['step']}.py"),run_name=f"replay_{row['step']}")
assertion_count+=len(row['checks'])
source_manifest=json.loads((R/'evidence/SOURCE_MANIFEST.json').read_text())
for name,sha in source_manifest.items():
assert hashlib.sha256((R/'evidence/sources'/name).read_bytes()).hexdigest()==sha,name
assert source_manifest['File52c_latest.md']=='a5ea84562101158b60d0cf296765d6eff38e7a2abda4e74ad1b353dfd13b9530'
reviews=sorted(p.name for p in (R/'evidence').glob('INDEPENDENT_REVIEW_*.md'))
result={'status':'PASS','sequential_steps':len(rows),'first':rows[0]['step'],'last':rows[-1]['step'],'step_assertions_replayed':assertion_count,'source_hashes_verified':len(source_manifest),'journal_chain_verified':True,'independent_reversal_used':True,'independent_review_notes':reviews,'reviewed_analytical_steps':48,'reviewer_supplied_assertions':123,'scope':'Assertions include arithmetic and declared-scope checks; counts are not independent evidence. C530–C531 are review/synthesis decisions. Canonical historical suites were not rerun.'}
(R/'VERIFY.json').write_text(json.dumps(result,indent=2)+'\n')
print(json.dumps(result,indent=2))
Evidence
verify.py
Edition and provenance
verify.py
SHA-256 a69e4d8e665e75d35dfd509d457056274a806b9d592a2700fe7a9935bd0a97bd
C480–C1634/Research_Cycles/C0482_C0531/evidence/verify.py