"""Real-app OpenCode 2 lost-report reproduction (no adapter mocks or database edits).

Prerequisites: each checkout has vp i, an isolated T3 dev server started with
T3CODE_DEV_SEED=0, and an enabled opencode provider pointing at fault-proxy.mjs.
Run an isolated real OpenCode 2.2.7 server upstream of that proxy, authenticated
with provider-password, configured with a working openai/gpt-6-luna model.
Sign the browser session into the corresponding dev app and add the checkout as
a project with `node apps/server/src/bin.ts project add . --base-dir .t3` first.
The proxy discards the first completion report for each child, forwarding every
other provider event unchanged. --repeat uses Sleep for BOTH tool descriptions.
"""
import argparse, json, pathlib, subprocess, time, urllib.request

p=argparse.ArgumentParser()
p.add_argument('--checkout',required=True)
p.add_argument('--origin',required=True)
p.add_argument('--browser',required=True)
p.add_argument('--out',required=True)
p.add_argument('--session',default='proof26336')
p.add_argument('--repeat',action='store_true')
a=p.parse_args()
out=pathlib.Path(a.out)/str(time.time_ns());out.mkdir(parents=True)

def cli(*args):
    r=subprocess.run(['node','apps/server/src/bin.ts',*args,'--base-dir','.t3'],cwd=a.checkout,text=True,capture_output=True,check=True)
    return r.stdout

def browser(*args):
    return subprocess.run([a.browser,'--session',a.session,*args],text=True,capture_output=True,check=True).stdout

def events():
    with urllib.request.urlopen('http://127.0.0.1:41964/evidence/status') as r:return json.load(r)['events']

def until(fn):
    end=time.monotonic()+90
    while time.monotonic()<end:
        value=fn(events())
        if value:return value
        time.sleep(.2)
    raise RuntimeError('Provider milestone did not arrive')

description='Sleep' if a.repeat else 'Again'
title='Repeated description' if a.repeat else 'Lost subagent report'
first='Use the native subagent tool to launch one BACKGROUND child, description Sleep, agent general, model openai/gpt-6-luna. Give it this exact prompt: Return exactly FIRST_OK and do nothing else. Do not wait for it or inspect files. Reply only LAUNCHED after the tool returns. Do not use any T3 delegation tool.'
offset=len(events())
thread=json.loads(cli('thread','start','.',first,'--title',title,'--provider','opencode','--model','openai/gpt-6-luna','--json'))['threadId']
def find_parent(es):
    return next((e['data']['sessionID'] for e in es[offset:] if e['type']=='session.inbox.enqueued' and e['data'].get('item',{}).get('payload',{}).get('text')==first),None)
parent=until(find_parent)
def lost_report(es):
    return next((e for e in es[offset:] if e['type']=='session.inbox.enqueued' and e['data'].get('sessionID')==parent and e.get('dropped')),None)
lost=until(lost_report)
child=lost['data']['item']['payload']['metadata']['childID']
until(lambda es:any(e['type']=='session.execution.succeeded' and e['data'].get('sessionID')==parent for e in es[es.index(lost)+1:]))
with urllib.request.urlopen(a.origin+'/.well-known/t3/environment') as r:env=json.load(r)['environmentId']
import urllib.parse
browser('open',a.origin+'/'+env+'/'+urllib.parse.quote(thread,safe=''))
browser('wait','--text','Waiting')
browser('eval','document.activeElement?.blur()')
browser('record','start',str(out/'resume.webm'),'--fps','10')
second=f'Use the native subagent tool to resume the SAME child session {child} in BACKGROUND with description {description} and prompt: Return exactly SECOND_OK and do nothing else. Do not create a new child. Do not wait, inspect files, or call T3 delegation tools. Reply only RESUMED after the tool returns.'
cli('thread','send',thread,second,'--json')
def second_report(es):
    return next((e for e in es[offset:] if e['type']=='session.inbox.enqueued' and e['data'].get('sessionID')==parent and e['data'].get('item',{}).get('payload',{}).get('metadata',{}).get('source')=='subagent' and not e.get('dropped')),None)
report=until(second_report)
until(lambda es:any(e['type']=='session.execution.succeeded' and e['data'].get('sessionID')==parent for e in es[es.index(report)+1:]))
browser('wait','--text','SECOND_OK')
browser('eval','Array.from(document.querySelectorAll("button")).filter(b=>(b.textContent.startsWith("Worked for")||b.textContent.startsWith("Previous agents"))&&b.getAttribute("aria-expanded")==="false").forEach(b=>b.click());document.activeElement?.blur()')
for i in range(20):
    x=out/f'stability-{i}-a.png';y=out/f'stability-{i}-b.png'
    browser('screenshot',str(x));time.sleep(.5);browser('screenshot',str(y))
    if x.read_bytes()==y.read_bytes():
        (out/'final.png').write_bytes(y.read_bytes());break
else:raise RuntimeError('No identical screenshots 500ms apart')
browser('record','stop')
# Public transcript contains only relevant synthetic report fields, never paths or credentials.
rows=[]
for e in events()[offset:]:
    d=e['data'];t=e['type']
    if d.get('sessionID') not in [parent,child]:continue
    if t=='session.tool.called':rows.append({'event':t,'input':d.get('input')})
    if t=='session.text.ended':rows.append({'event':t,'session':'child' if d['sessionID']==child else 'parent','text':d.get('text')})
    if t=='session.execution.succeeded':rows.append({'event':t,'session':'child' if d['sessionID']==child else 'parent'})
    if t=='session.inbox.enqueued' and d.get('item',{}).get('payload',{}).get('metadata',{}).get('source')=='subagent':rows.append({'event':t,'text':d['item']['payload']['text'],'withheld':e.get('dropped',False)})
(out/'transcript.json').write_text(json.dumps(rows,indent=2))
print(json.dumps({'output':str(out),'threadId':thread,'description':description}))
