"""Real-app evidence driver. Requires agent-browser, ffmpeg, Pillow, and two running app servers.
Run seed.py once for a shared synthetic Git workspace; add it and start a Replay showcase
thread titled 'Checkbox accessibility' through each server's CLI. Pass a fresh pairing
URL to this script for each side. Never upload pairing URLs or raw full-window recordings.
"""
import argparse,subprocess,pathlib,time,json,hashlib
from PIL import Image,ImageDraw,ImageFont
p=argparse.ArgumentParser();p.add_argument('--browser',default='agent-browser');p.add_argument('--session',required=True);p.add_argument('--pair-url');p.add_argument('--side',required=True);p.add_argument('--out',required=True);a=p.parse_args()
out=pathlib.Path(a.out)/f'{a.side}-{time.time_ns()}';out.mkdir(parents=True)
def ab(*args):
 r=subprocess.run([a.browser,'--session',a.session,*args],capture_output=True,text=True)
 if r.returncode: raise RuntimeError(r.stderr+r.stdout)
 return r.stdout
if a.pair_url: ab('open',a.pair_url)
ab('set','viewport','1280','900');ab('set','media','dark')
ab('wait','--text','Checkbox accessibility')
# Select the seeded, completed synthetic thread.
import re
thread_line=next(l for l in ab('snapshot','-i').splitlines() if 'button "Checkbox accessibility,' in l)
ab('click','@'+re.search(r'ref=(e\d+)',thread_line).group(1))
ab('wait','--text','Showcase')
ab('find','role','button','click','--name','Git action options')
ab('find','role','menuitem','click','--name','Commit')
ab('wait','--text','Review and confirm your commit.')
ab('record','start',str(out/'raw.webm'))
time.sleep(1)
ab('find','role','button','click','--name','Edit')
time.sleep(1)
def capture(stage):
 tree=ab('snapshot','-s','[role=dialog]','-i')
 (out/f'{stage}-accessibility.txt').write_text('Environment: Linux Chrome, web dev app, 1280 x 900, dark theme\n'+tree)
 # Require two byte-identical full-window screenshots, at least 500 ms apart.
 previous=None
 for i in range(10):
  path=out/f'{stage}-raw-{i}.png';ab('screenshot',str(path))
  im=Image.open(path).crop((370,145,910,755)).convert('RGB')
  digest=hashlib.sha256(path.read_bytes()).hexdigest()
  if digest==previous: break
  previous=digest;time.sleep(.5)
 else: raise RuntimeError('Dialog did not stabilize')
 im.save(out/f'{stage}-dialog.png')
 lines=[l.strip() for l in tree.splitlines() if l.lstrip().startswith('- checkbox')]
 lines=[l.split(', ref=')[0].replace(' [ref=', ' [ref=') for l in lines]
 import re
 lines=[re.sub(r',? ref=e\d+','',l) for l in lines]
 canvas=Image.new('RGB',(1000,710),'#15171b');canvas.paste(im,(15,70))
 d=ImageDraw.Draw(canvas);font=ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf',17);small=ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf',13)
 d.text((20,15),f'{a.side.title()} | {stage} | Web / Chrome / Linux | 1280 x 900 | Dark',font=font,fill='white')
 d.text((575,80),'Browser accessibility snapshot',font=font,fill='white')
 y=125
 for line in lines:
  # Wrap each checkbox at its state for legible full repository-relative names.
  parts=line.split(' [checked=')
  d.text((575,y),parts[0],font=small,fill='#e4e7ec');y+=25
  if len(parts)>1:d.text((590,y),'checked='+parts[1],font=small,fill='#83d3a7');y+=25
  y+=20
 d.text((575,600),'UI crop + unmodified runtime AX values',font=small,fill='#aeb6c4')
 canvas.save(out/f'{stage}-evidence.png')
capture('all-selected')
# Use positional CSS on both versions: unnamed base checkboxes cannot be selected by name.
ab('focus','[role="checkbox"]');ab('press','Tab');ab('press','Tab');ab('press','Space');time.sleep(1)
capture('one-unchecked')
ab('press','Tab');ab('press','Tab');time.sleep(1)
ab('record','stop')
subprocess.run(['ffmpeg','-y','-i',str(out/'raw.webm'),'-vf','crop=540:610:370:145','-an','-c:v','libx264','-pix_fmt','yuv420p',str(out/'interaction.mp4')],check=True,stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL)
print(out)
