"""Real-app proof driver. Args: checkout home origin environment-id output-dir.
Start hub.py, seed.py HOME, and T3CODE_DEV_SEED=0 vp run dev --home-dir HOME first.
Pair this browser session before running. Requires agent-browser on PATH.
"""
import sys,pathlib,subprocess,json,time,os
checkout,home,origin,environment,out=sys.argv[1:]
out=pathlib.Path(out)/time.strftime('%Y%m%d-%H%M%S');out.mkdir(parents=True)
browser=os.environ.get('PROOF_BROWSER','agent-browser')
def ab(*args):
 p=subprocess.run([browser,'--session','proof26574',*args],text=True,capture_output=True)
 if p.returncode:raise RuntimeError(p.stderr+p.stdout)
 return p.stdout

def cli(*args):
 p=subprocess.run(['node','apps/server/src/bin.ts',*args,'--base-dir',home,'--json'],cwd=checkout,text=True,capture_output=True)
 if p.returncode:raise RuntimeError(p.stderr+p.stdout)
 return json.loads(p.stdout)
project=str(pathlib.Path(home)/'demo');pathlib.Path(project).mkdir(exist_ok=True)
subprocess.run(['git','init','-q',project],check=True)
subprocess.run(['node','apps/server/src/bin.ts','project','add',project,'--title','Recovery proof','--base-dir',home],cwd=checkout,capture_output=True)
t=cli('thread','start',project,'Please say hello','--title','CLIProxy recovery','--provider','claudeHub','--model','claude-haiku-5-5')
from urllib.parse import quote
ab('open',origin+'/'+environment+'/'+quote(t['threadId'],safe=''))
ab('wait','--text','CLIProxy recovery')
if 'region "Thread details"' in ab('snapshot'):
 ab('find','role','button','click','--name','Toggle thread details panel')
ab('hover','[aria-label="Message CLIProxy recovery"]')
ab('record','start',str(out/'recovery.mp4'))
queued=cli('thread','send',t['threadId'],'Do not lose this queued message')
assert queued['delivery']=='queued',queued
ab('wait','--text','Usage limit reached')
# Wait for recovery worker to commit its post-failure decision before capturing.
time.sleep(35)
for attempt in range(10):
 ab('screenshot',str(out/'recovery-a.png'));time.sleep(.5);ab('screenshot',str(out/'recovery-b.png'))
 if (out/'recovery-a.png').read_bytes()==(out/'recovery-b.png').read_bytes():break
else:raise RuntimeError('Capture did not stabilize')
print('Stable recovery captures: True')
ab('record','stop')
(out/'run.json').write_text(json.dumps({'thread':t['threadId'],'queuedDelivery':queued['delivery'],'snapshot':ab('snapshot')},indent=2))
print(out)
