"""Read-only source extraction/preparation; no numbered research actions."""
from pathlib import Path
import json,re,hashlib

ROOT=Path('/workspace/scratch/1b40da62dcbd')
OUT=ROOT/'c732_c831/prep'
paths={
 'File18':ROOT/'project_sources/38-File_18.Chronological_Data_Tables-20260919-141048-.md',
 'File09':ROOT/'project_sources/30-File_09.Cumulative_Architecture-9-.md',
 'File22':ROOT/'project_sources/15-File_22.Cumulative_MT_Harmonics-20260906-202427-.md',
}
sources={k:{'path':str(p),'sha256':hashlib.sha256(p.read_bytes()).hexdigest()} for k,p in paths.items()}
lines=paths['File18'].read_text().splitlines()
def cellrow(line): return [x.strip() for x in line.strip('|').split('|')]
def number(cell): return int(re.search(r'\d+',cell).group())
shared=['Adam','Seth','Enosh','Kenan','Mahalalel','Jared','Enoch','Methuselah','Lamech','Noah','Shem','Arphaxad','Shelah','Eber','Peleg','Reu','Serug','Nahor','Terah']
trunk=shared+['Abraham','Isaac','Jacob','Levi','Kohath','Amram','Moses']
ranges={'MT':[(1228,1237),(1244,1252)],'SP':[(1447,1456),(1600,1608)],'LXX':[(1697,1706),(1716,1725)]}
rows={}
for trad,blocks in ranges.items():
 data=[]
 for lo,hi in blocks:
  for no in range(lo,hi+1):
   raw=lines[no-1]
   cells=cellrow(raw)
   if len(cells)!=5: raise ValueError((no,raw))
   name=cells[0].split(' /')[0].split(' —')[0]
   if name=='2nd Cainan': name='Cainan2'
   birth,death,L,b=map(number,cells[1:])
   row={'name':name,'birth_BC':birth,'death_BC':death,'b_ledger':b,'L_ledger':L,'r_calculated':L-b,'r_status':'derived L_ledger minus b_ledger; not an independently quoted remainder','b_literal':cells[4],'L_literal':cells[3],'source':{'key':'File18','line':no,'raw':raw}}
   if trad=='SP' and name in ['Jared','Methuselah','Lamech']:
    row['L_counting']='inclusive; do not replace by simple birth-death difference'
    row['completed_lifespan_from_dates']=birth-death
   if trad=='SP' and name=='Lamech':
    row['b_completed_primary']=52
    row['b_completed_companion']=53
   if name=='Noah':
    row['following_Shem_binding']='Arphaxad-bound; source births differ by 502 despite b ledger 500. Boundary term +2.'
   if trad=='LXX' and name=='Lamech': row['source_hierarchy']='Selected restored 182 / attested 753; 571 calculated. No joint attestation asserted; 188 non-operative; 777 appendix only.'
   if name=='Terah': row['selected_begetting_state']='70, minimum no +60. Alternate 130 is a distinct admitted state.'
   data.append(row)
 rows[trad]=data

mt_cum=[]
for no in list(range(1935,1946))+list(range(1948,1963)):
 cells=cellrow(lines[no-1])
 if len(cells)!=6: raise ValueError((no,lines[no-1]))
 name=cells[0].split(',')[0]
 if name not in trunk: raise ValueError((no,name))
 mt_cum.append({'name':name,'L':number(cells[1]),'Moses_Nisan_BC':number(cells[2]),'Aaron_Tishri_exact_literal':cells[3],'envelope_literal':cells[4],'source':{'key':'File18','line':no,'raw':lines[no-1]}})
assert [r['name'] for r in mt_cum]==trunk

source_facts=[]
for no in [1127,1128,1129,1134,1135,1136,1143,1144,1145,1146,1147,1148,1474,1475,1532,1533,1534,1718,1729,1731,1733,1947,1969,1974,2025,2027,2028,2029,2030,2031,2061,2062,2063,2064,2065,2072,2074,2077]:
 source_facts.append({'key':'File18','line':no,'text':lines[no-1]})
packet={
 'status':'source extraction and candidate preparation only; no numbered research execution',
 'sources':sources,
 'shared_regular_order':shared,
 'cumulative_MT_direct_trunk_order':trunk,
 'regular_source_rows':rows,
 'MT_cumulative_literal_rows':mt_cum,
 'source_extracts':source_facts,
 'mode_states':{
  'regular_frame':'Literal File18 Minimum-Regular tables. Hold no +60 Terah, no +215 Sojourn. Compare primary Noah / Arphaxad-bound Shem, with b500 +2 boundary. All three share Abraham1951. Adding +215 to allowed common region does not alter inter-tradition differences.',
  'cumulative_frame':'Moses/Nisan centers, Conquest1406; shared Abraham2435 and complete MT tail. SP uses official653 inclusive and145 Terah in lifespan sum. Joshua extension to1296 remains additional terminal110, not a replacement subtraction inside the shared trunk.',
  'native_Cainan':{'MT':'OFF','SP':'OFF','LXX':'ON'},
  'leveled_Cainan':'Comparisons may match ON/ON or OFF/OFF by explicitly admitted single insertion/removal. Absent Cainan is no source row, not a zero-lifespan person.',
  'phase':'Use Moses/Nisan centers first; exact Aaron +3.5 and lower/upper envelope selections remain separate.',
 },
 'guardrails':['No upstream Gear transport','No primers or1486','No second decimal inversion','No canonical edits','SP companion belongs Noah/Shem only','LXX182/753 main;777 appendix;188 non-operative'],
 'prior_completed_not_to_repeat':{
  'C485':'LXX six +100 pre-Flood b repartitions and Lamech -24 lifespan',
  'C486':'SP aggregate regular +300, cumulative -608 including primary52 convention',
  'C487':'2x2 row projection and cumulative-kernel repartition',
  'C488':'Cainan cross-mode (130,460) and bridge+330',
  'C491':'LXX cumulative890 decomposition454+460-24',
 },
 'candidate_questions':[
  'Reconstruct the complete ordered node displacement profiles from suffix incidence of row changes, and recover exact row support by adjacent differences.',
  'Why do LXX and SP regular birth profiles agree from Shelah through Terah while cumulative/death profiles remain different?',
  'Does Cainan leveling make the whole LXX/MT cumulative trunk a translation? Determine the maximal constant-displacement blocks rather than only the Adam430 total.',
  'Can every inherited lifespan-row perturbation be localized from intermediate boundaries, and can source-row rearrangements preserve Creation totals while failing the full profile?',
  'Does the MT/LXX/SP comparison compose pointwise through MT across both modes, once absent-row and annual-boundary terms are explicit?',
 ]
}
# Derived candidate arrays are separate from the literal source rows above.
prepared={}
for trad in ['MT','SP','LXX']:
 ordered=rows[trad]
 cumulative={}
 c=2435
 for r in reversed(ordered):
  c+=r['L_ledger']
  cumulative[r['name']]=c
 coords=[]
 for i,r in enumerate(ordered):
  nxt=ordered[i+1] if i+1<len(ordered) else {'name':'Abraham','birth_BC':1951}
  effective=r['birth_BC']-nxt['birth_BC']
  coords.append({'name':r['name'],'regular_min_literal_BC':r['birth_BC'],'regular_full430_derived_BC':r['birth_BC']+215,'cumulative_Moses_center_derived_BC':cumulative[r['name']],'cumulative_lower_envelope_derived_BC':cumulative[r['name']]-2,'L_selected':r['L_ledger'],'b_ledger':r['b_ledger'],'b_effective_to_next_birth':effective,'kappa_effective_minus_ledger':effective-r['b_ledger'],'next_name':nxt['name'],'literal_regular_source_line':r['source']['line'],'coordinate_status':'Rfull430 derived from literal Minimum+215; C generated from selected official lifespans held at Abraham2435; every C not necessarily separately printed in File18'})
 coords.append({'name':'Abraham','regular_min_literal_BC':1951,'regular_full430_derived_BC':2166,'cumulative_Moses_center_derived_BC':2435,'cumulative_lower_envelope_derived_BC':2433,'coordinate_status':'Common terminal source row; Gcenter269 / Glower267'})
 prepared[trad]=coords
packet['prepared_native_coordinate_arrays']=prepared
packet['prepared_array_status']='Preparatory candidate reconstruction; root must freeze and verify in numbered sequence. Not additional literal source rows.'
packet['bridge_pairing_note']='Use C lower-envelope=center−2 and R full430 to reproduce the established completion bridge14004−4114=9890. Moses-center14006 is AdamYear6, while regular4114 is completion; their difference9892 is a distinct chart pairing. Uniform−2 preserves recurrence but must not erase node/phase labels. At Abraham C lower2433 and R2166 give267.'
packet['boundary_support']={'all_traditions_Noah_to_Arphaxad_bound_Shem':{'b_ledger':500,'b_effective':502,'kappa':2},'SP_Lamech_to_primary_Noah':{'b_ledger':53,'b_effective':52,'kappa':-1},'others_in_selected_native_Adam_to_Terah_arrays':{'kappa':0}}
OUT.joinpath('source_modes_packet.json').write_text(json.dumps(packet,indent=2)+'\n')
print(json.dumps({'rows':{k:len(v) for k,v in rows.items()},'MT_cumulative_rows':len(mt_cum),'output':str(OUT/'source_modes_packet.json')}))
