#!/usr/bin/env python3
"""Real T3/Codex runtime proof. Never writes either state database.
Usage: evidence-driver.py CHECKOUT CODEX_HOME RUN_OUTPUT LABEL SHA [--resume]
Start each checkout with T3CODE_DEV_SEED=0 and its scratch CODEX_HOME.
Create a synthetic git project, then use t3 project add and t3 thread start
--provider codex --model "$EVIDENCE_MODEL" --wait --json. Store the returned
JSON as RUN_OUTPUT/start.json. The model must come from Codex model/list.
Prompt: Delegate exactly one task to a Codex child using T3's delegate_task:
'Act as the implementation subagent. Reply with the single word DONE.'
Use the same provider and model as yourself, wait, and relay the answer.
The driver watches the ordinary 30-minute idle cleanup without changing time.
Only synthetic state and an allowlist of public fields enter its captures.
"""
import sys,json,sqlite3,time,subprocess,datetime
from pathlib import Path
checkout,home,out,label,sha=sys.argv[1:6]
root=Path(out);root.mkdir(parents=True,exist_ok=True)
base=Path(checkout)/'.t3'
def query(path,sql,args=()):
 with sqlite3.connect('file:'+str(path)+'?mode=ro',uri=True) as c:
  c.row_factory=sqlite3.Row
  return [dict(r) for r in c.execute(sql,args)]
def snapshot():
 db=base/'userdata/statev2.sqlite'
 task=query(db,'select child_thread_id,status,completion_delivery_state,payload_json from orchestration_v2_projection_subagents')[0]
 parent=json.loads((root/'start.json').read_text())
 rows=[]
 for p in query(db,'select thread_id,payload_json from orchestration_v2_projection_provider_threads'):
  native=json.loads(p['payload_json'])['nativeThreadRef']['nativeId']
  row=query(Path(home)/'state_5.sqlite','select id,source,originator,attached_thread_parent_id,agent_path,archived,archived_at from threads where id=?',(native,))[0]
  row['role']='child' if p['thread_id']==task['child_thread_id'] else 'parent'
  rows.append(row)
 return {'utc':datetime.datetime.now(datetime.timezone.utc).isoformat(timespec='seconds'),'commit':sha,'parent_reply':parent['reply'],'task_status':task['status'],'delivery':task['completion_delivery_state'],'rows':sorted(rows,key=lambda r:r['role'])}
def emit(s):
 with (root/'observations.jsonl').open('a') as f:f.write(json.dumps(s)+'\n')
 print('\033[2J\033[H\033[?25l',end='')
 print('ISSUE 29778 | REAL SERVER / CLI / NATIVE CODEX STATE')
 print(label+' | '+sha[:10]+' | '+s['utc'])
 print('Linux; fresh synthetic T3 + Codex databases; no replay or mocks')
 print('Default 30-minute idle timeout; read-only SQL observation\n')
 print('Parent final reply: '+s['parent_reply'])
 print('Delegated child: '+s['task_status']+' | result delivery: '+s['delivery'])
 print('\nNative Codex threads (actual database rows):')
 for r in s['rows']:
  print('\n  '+r['role'].upper()+' '+r['id'])
  print('  source='+r['source']+'  originator='+str(r['originator']))
  print('  attached_thread_parent_id='+str(r['attached_thread_parent_id'])+'  agent_path='+str(r['agent_path']))
  print('  archived='+str(r['archived'])+'  archived_at='+str(r['archived_at']))
 print('\nWaiting for the unchanged idle timeout; no archive command sent by driver.')
 print('Read-only query: SELECT id,source,originator,attached_thread_parent_id,')
 print('  agent_path,archived,archived_at FROM threads WHERE id=?;')
 sys.stdout.flush()
def cli(*args):
 p=subprocess.run(['node','apps/server/src/bin.ts',*args,'--base-dir',str(base),'--wait','--json'],cwd=checkout,text=True,capture_output=True)
 if p.returncode: raise RuntimeError('Continuation failed; inspect private stderr')
 d=json.loads(p.stdout);return {k:d[k] for k in ['status','reply','error']}
if '--resume' in sys.argv:
 db=base/'userdata/statev2.sqlite'
 child=query(db,'select child_thread_id from orchestration_v2_projection_subagents')[0]['child_thread_id']
 parent=json.loads((root/'start.json').read_text())['threadId']
 result={}
 for role,tid,prompt in [('child',child,'Reply with the single word CHILD-OK.'),('parent',parent,'Reply with the single word PARENT-OK.')]:
  result[role]=cli('thread','send',tid,prompt)
  print(role+' continuation: '+json.dumps(result[role]),flush=True)
 result['native_state_after_resume']=snapshot()
 (root/'continuation.json').write_text(json.dumps(result,indent=2))
 print('Native child archived after continuation: '+str(next(r['archived'] for r in result['native_state_after_resume']['rows'] if r['role']=='child')),flush=True)
else:
 # At least 31 minutes since the observed child terminal time, on both commits.
 task=query(base/'userdata/statev2.sqlite','select completed_at from orchestration_v2_projection_subagents')[0]
 end=datetime.datetime.fromisoformat(task['completed_at'].replace('Z','+00:00')).timestamp()+31*60
 while True:
  s=snapshot();emit(s)
  if time.time()>=end:break
  time.sleep(min(10,max(0,end-time.time())))
 (root/'final-state.json').write_text(json.dumps(s,indent=2))
 print('\nIdle observation complete. Next: continue the child and parent.',flush=True)
 time.sleep(5)
