from pathlib import Path
from fractions import Fraction as F
from math import gcd,lcm
from itertools import permutations, product
import json,hashlib,re
R=Path('/workspace/scratch/1b40da62dcbd/c832_c931'); M=R/'model'
def read(n):return json.loads((M/n).read_text())
checks=[]
def chk(name,ok,detail=None):
 checks.append({'name':name,'pass':bool(ok),'detail':detail})
 if not ok:raise AssertionError(name)
K={'E':F(25,23),'P':F(70,69),'J':F(300,299)}
p=read('operator_inputs.json')
chk('seven_source_hashes_current',all(hashlib.sha256(Path(v['path']).read_bytes()).hexdigest()==v['sha256'] for v in p['sources'].values()),len(p['sources']))
chk('literal_excerpts_current',all('\n'.join(Path(p['sources'][e['source']]['path']).read_text().splitlines()[e['lines'][0]-1:e['lines'][1]])==e['text'] for e in p['source_excerpts']),len(p['source_excerpts']))
# Independent Euclidean proof criterion; coefficient is reduced and multiplication by nonzero h cancels.
chk('reduced_keys',all(gcd(v.numerator,v.denominator)==1 for v in K.values()))
dom=read('one_key_domains.json')
# Container has rows and intersections; inspect robustly.
rows=dom if isinstance(dom,list) else dom.get('rows',dom.get('domains',[]))
for r in rows:
 k=K[r['key']]
 chk('one_key_'+r['key'],r['integer_generator']==k.denominator and r['five_year_generator']==5*k.denominator)
chk('joint_lattice_generators',lcm(*(v.denominator for v in K.values()))==897 and 5*lcm(*(v.denominator for v in K.values()))==4485)
prof=read('existing_key_profiles.json')
for r in prof:
 chk('existing_profile_'+str(r['input']),all(F(r['images'][key])==r['input']*v for key,v in K.items()) and r['integer_keys']==[key for key,v in K.items() if (r['input']*v).denominator==1])
q=read('quarter_carrier_images.json');ms=[3,10,12,30,300]
chk('complete_quarter_inventory',[r['m'] for r in q]==ms)
for r in q:
 m=r['m'];x=F(161*m,4)
 chk('quarter_row_'+str(m),F(r['source'])==x and all(F(r['images'][key])==v*x and r['quarter_grid'][key]==((4*v*x).denominator==1) for key,v in K.items()))
chk('quarter_multiplier_conditions',all((4*K[k]*F(161,4)).denominator==d for k,d in {'E':1,'P':3,'J':13}.items()))
heads=read('File46_full_head_image.json')
for r in heads:
 x=r['head'];y=14006+K['E']*(x-14006)
 chk('head_'+str(x),F(r['image'])==y and F(r['E_radius'])==y-14006 and r['integral']==(y.denominator==1))
chk('complete_head_inventory',[r['head'] for r in heads]==[14926,14896,14466,14436,14006])
chk('anchor_independent_integer_obstruction',all((d*K['E']).denominator==23 for d in [430,30,430]),'D(u)-D(v)=k(u-v); integral endpoints would force integral differences; contradiction at430 alone suffices, even for a nonintegral common anchor.')
words=read('two_key_domains.json')
chk('complete_two_word_inventory',{r['execution'] for r in words}=={a+'→'+b for a,b in product(K,repeat=2)})
for r in words:
 w=r['execution'].split('→'); coeff=F(1);den=1
 for k in w:coeff*=K[k];den=lcm(den,coeff.denominator)
 chk('two_word_'+r['execution'],F(r['coefficient'])==coeff and r['final_integer_domain']==coeff.denominator and r['all_stage_integer_domain']==den and r['all_stage_5Z_domain']==5*den)
tri=read('three_distinct_key_domains.json')
chk('complete_three_word_inventory',{r['order'] for r in tri}=={'→'.join(w) for w in permutations(K)})
for r in tri:
 w=r['order'].split('→');coeff=F(1);den=1;prefix=[]
 for k in w:coeff*=K[k];den=lcm(den,coeff.denominator);prefix.append(coeff)
 chk('three_word_'+r['order'],[F(x) for x in r['prefixes']]==prefix and r['domain']==den and den==(474513 if w.index('P')<w.index('J') else 158171))
chains=read('File51a_authorized_key_chains.json')
for r in chains:
 n=r['civil_input'];chk('civil_EE_'+str(n),[F(x) for x in r['EE_chain']]==[F(n),n*K['E'],n*K['E']**2] and n==529*r['multiple529'])
 if 'EJ_chain' in r:chk('civil_EJ_55016',[F(x) for x in r['EJ_chain']]==[F(n),n*K['E'],n*K['E']*K['J']] and n==6877*r['multiple6877'])
for r in read('civil_Rounded_input_distinction.json'):
 c,w=r['civil'],r['Rounded_width']
 chk('civil_width_type_'+str(c),c-w==1 and F(r['E_width'])==w*K['E'] and F(r['EE_width'])==w*K['E']**2 and F(r['E_difference'])==(c-w)*K['E'] and F(r['EE_difference'])==(c-w)*K['E']**2)
field=read('complete_anchor_order_field.json');delta=(K['E']-1)*(K['P']-1)*(14006-4836)
def D(k,a,x):return a+k*(x-a)
for r in field:
 x=F(r['head']);left=D(K['E'],14006,D(K['P'],4836,x));right=D(K['P'],4836,D(K['E'],14006,x))
 chk('anchor_order_'+str(r['head']),F(r['left'])==left and F(r['right'])==right and left-right==F(r['difference'])==delta)
chk('anchor_constant_exact',delta==F(18340,1587))
for a,b in zip(field,field[1:]):chk('anchor_order_gap_'+str(a['head']),F(a['left'])-F(b['left'])==F(a['right'])-F(b['right'])==K['E']*K['P']*(a['head']-b['head']))
nt=read('NT_grid_domain_transfer.json')
for r in nt:
 k=K[r['key']];inds=[n for n in range(77) if (k*n).denominator==1 and 0<=k*n<=76]
 chk('NT_transfer_'+r['key'],r['same_slot_indices']==inds and r['integer_year_indices']==[n for n in range(77) if (70*k*n).denominator==1] and r['grid_input_generator']==70*k.denominator)
# Literal NT lookup, independent of prepared packet.
s=Path('/workspace/scratch/1b40da62dcbd/project_sources/06-File_43.Genealogical_Bridge-2-.md').read_text()
for line in ['| 1616–1546 BC | Asa | Melki |','| 1756–1686 BC | Rehoboam | Cosam |','| 3226–3156 BC | Eber | Salmon |','| 3506–3436 BC | Shem | Hezron |','| 4836–4766 BC |  | Enoch |','| 4906–4836 BC |  | Jared |','| 5256–5186 BC |  | Creation of Adam |']:
 chk('NT_literal_'+line.split('|')[-2].strip(),line in s)
# Check actual output records for required claim-type controls.
j={r['step']:r for r in json.loads((R/'journal.json').read_text())}
chk('root_claim_type_controls',all(token in j[n]['finding'].lower() or token in str(j[n]['sources']).lower() for n,token in [(872,'diagnostic'),(876,'source-licensed'),(882,'intermediate'),(883,'civil'),(885,'bounded'),(886,'formal'),(887,'diagnostic')]))
result={'scope':'Independent arithmetic and source-role review C872–C889; no root step scripts imported or replayed; no canonical changes.', 'reviewer':'operator_family','status':'PASS','checks':checks,'checks_passed':len(checks),'steps_reviewed':list(range(872,890)), 'proof_review':{'one_key':'For h!=0, input hm, gcd(p,q)=1: p*m/q integral iff q dividesm.','word':'Every reduced prefix denominator must dividem; the intersection is theirLCM.','integer_obstruction':'The fractional image gap excludes integral whole-field placement for every common anchor.','anchor_order':'Direct affine expansion gives(k-1)(l-1)(a-b), constant on the full path.'},'claim_status_review':{'source_authorized':'File51a civil EE/EJ chains retained; inherited483 and related completions remain inherited.','diagnostic':'Full unlicensed Key image matrices and mixed-anchor compositions remain formal diagnostics.','fractions':'No fraction is rounded away or treated as invalid merely for leaving the original grid.','NT':'Positive slot ranges are finite,0..76; named ledger positions do not become historical dates.'},'blocking_findings':[],'nonblocking_notes':['The one-Key theorem conventionally assumes a nonzero grid spacingh (positive for chronological units).','For these three Keys on70Z, integer-output and slot-return index sets coincide; C888 correctly states the distinction is conceptual here, rather than claiming extra failures.']}
(R/'evidence/INDEPENDENT_C872_C889.json').write_text(json.dumps(result,indent=2)+'\n')
print(json.dumps({'status':'PASS','checks_passed':len(checks)}))
