"""Reproduce Session 43 counts and native-resolution evidence crops.
Run with Pillow installed. Visual judgments remain recorded human/model observations,
not assertions that can be independently established by this script.
"""
from pathlib import Path
from io import BytesIO
import json, hashlib
from PIL import Image, ImageDraw
from lexical_words import tokenize_words
from word_core import lp, LET
F=Path(__file__).resolve().parent
j=json.loads((F/'singleton43_observations.json').read_text())
ws=[w for w in tokenize_words('%'.join(lp[:56])) if len(w['values'])==1]
assert len(ws)==83 and len({w['values'][0] for w in ws})==28
expected={(w['page'],w['page_rune_offset'],LET[w['values'][0]]) for w in ws if w['section']!=8}
assert expected=={(r['page'],r['offset'],r['label']) for r in j['observations']}
def save(im,name):
    b=BytesIO();im.save(b,format='PNG');(F/name).write_bytes(b.getvalue())
for r in j['observations']:
    p=F/r['source_file'];assert hashlib.sha256(p.read_bytes()).hexdigest()==r['source_sha256']
    save(Image.open(p).convert('RGB').crop(r['box']),r['file'])
for p,box in j['context_boxes'].items():
    save(Image.open(F/f'{int(p)+17:02}.jpg').crop(box),f'singleton43_context_{p}.png')
for k in range(0,68,4):
    rs=j['observations'][k:k+4];ims=[Image.open(F/r['file']) for r in rs]
    out=Image.new('RGB',(1450,sum(im.height+40 for im in ims)),'white');d=ImageDraw.Draw(out);y=0
    for r,im in zip(rs,ims):
        d.text((10,y+7),f"ID {r['id']:02} | LP2 {r['page']} offset {r['offset']} | {r['label']} | line {r['line']+1}, rune index {r['line_index']}",fill='black')
        out.paste(im,(0,y+35));y+=im.height+40
    save(out,f'singleton43_sheet_{k//4:02}.png')
print('68 locations matched; image hashes verified; 83 singletons / 28 symbols; crops reproduced.')
