"""Run from each checkout. Fresh synthetic state only. Cancel the queued run with cancel-in-browser.js between first and second."""
import argparse,json,os,pathlib,sqlite3,subprocess,time
p=argparse.ArgumentParser();p.add_argument('phase',choices=['start','first','second','finish','report']);p.add_argument('root');a=p.parse_args();root=pathlib.Path(a.root).resolve();workspace=root/'workspace';root.mkdir(parents=True,exist_ok=True)
first='Use Bash run_in_background=true to run `until test -f finish-first; do sleep 1; done; echo FIRST_WAKE_OUTPUT`. Write ready to checkpoint.proof. End your turn immediately replying only FIRST_STARTED, no explanation. When the background task finishes reply only FIRST_WAKE_OUTPUT.'
second='Now start a second background Bash command with run_in_background=true: `until test -f finish-second; do sleep 1; done; echo SECOND_WAKE_OUTPUT`. End immediately replying only SECOND_STARTED, no explanation. When that background task finishes, reply exactly SECOND_WAKE_OUTPUT.'
def cli(*args):
 r=subprocess.run(['node','apps/server/src/bin.ts',*args,'--base-dir','.t3'],text=True,capture_output=True);r.check_returncode();return r.stdout.strip()
def git(*args):subprocess.run(['git','-C',str(workspace),*args],check=True,capture_output=True)
def state():
 c=sqlite3.connect('file:.t3/userdata/statev2.sqlite?mode=ro',uri=True)
 rows=[json.loads(x[0]) for x in c.execute('select payload_json from orchestration_v2_projection_runs where thread_id=? order by ordinal',(thread,))];c.close();return rows
def wait(check,limit=25):
 until=time.monotonic()+limit
 while time.monotonic()<until:
  rows=state()
  if check(rows):return rows
  time.sleep(.1)
 raise RuntimeError('State not reached: '+str([(r['ordinal'],r['status']) for r in rows]))
if a.phase=='start':
 workspace.mkdir(exist_ok=True);git('init','-q');(workspace/'.gitattributes').write_text('*.proof filter=proof\n');git('add','.gitattributes');git('-c','user.name=Demo','-c','user.email=demo@example.invalid','commit','-qm','Initial')
 gate=root/'gate-filter.py';gate.write_text("import pathlib,sys,time\nr=pathlib.Path(__file__).parent\ndata=sys.stdin.buffer.read()\nif (r/'hold').exists():\n (r/'held').touch()\n while (r/'hold').exists():time.sleep(.05)\nsys.stdout.buffer.write(data)\n")
 git('config','filter.proof.clean','python3 '+str(gate));print(cli('project','add',str(workspace),'--title','Wake cancellation evidence'))
 (root/'hold').touch();launch=json.loads(cli('thread','start',str(workspace),first,'--provider','claudeAgent','--model',os.environ['PROOF_MODEL'],'--title','Cancelled continuation proof','--json'));(root/'thread.json').write_text(json.dumps(launch));print(json.dumps(launch))
else:
 thread=json.loads((root/'thread.json').read_text())['threadId']
 if a.phase=='first':
  wait(lambda rs:rs[0]['status']=='waiting');(workspace/'finish-first').touch();rs=wait(lambda rs:any(r['status']=='queued' for r in rs));print(json.dumps({'threadId':thread,'queuedRunId':rs[-1]['id']}))
 elif a.phase=='second':
  wait(lambda rs:len(rs)==2 and rs[0]['status']=='completed' and rs[1]['status']=='cancelled');print(cli('thread','send',thread,second,'--wait','--json'))
 elif a.phase=='finish':
  wait(lambda rs:len(rs)==3 and rs[-1]['status']=='completed');(workspace/'finish-second').touch();print('Second background task released')
 elif a.phase=='report':
  clean=[{k:r.get(k) for k in ['ordinal','status','requestedAt','startedAt','completedAt']} for r in state()];print(json.dumps(clean,indent=2));(root/'runs-public.json').write_text(json.dumps(clean,indent=2))
