"""Select public proof fields from T3's recorded native protocol; omit credentials and runtime metadata.
Usage: python3 extract-protocol.py PROVIDER_LOG COMMIT OUTPUT_JSON
Run after the browser fork and recall steps described in reproduction.md.
"""
import json, pathlib, sys
source, commit, output = sys.argv[1:]
events=[]
for line in pathlib.Path(source).read_text().splitlines():
    if 'NTIVE: ' in line:
        record=json.loads(line.split('NTIVE: ',1)[1])
        if record.get('kind')=='protocol':
            events.append(record['event'])
fork=next(e for e in events if e['direction']=='outgoing' and e['payload'].get('method')=='thread/fork')
request=fork['payload']
response=next(e['payload'] for e in events if e['direction']=='incoming' and e['payload'].get('id')==request['id'])
thread=response['result']['thread']
turns=thread['turns']
completed=[e['payload']['params'] for e in events if e['payload'].get('method')=='item/completed']
recall=next(x['item']['text'] for x in completed if x.get('threadId')==thread['id'] and x['item'].get('type')=='agentMessage' and x['item'].get('phase')=='final_answer')
boundary=next(x for x in completed if x.get('turnId')==request['params']['lastTurnId'] and x['item'].get('type')=='agentMessage' and x['item'].get('phase')=='final_answer')
proof={
    'commit':commit,
    'source':'Real app native provider protocol log; selected fields only',
    'request':{'id':request['id'],'method':'thread/fork','params':{k:v for k,v in request['params'].items() if k in ('threadId','lastTurnId','excludeTurns')}},
    'response':{'id':response['id'],'result':{'thread':{'id':thread['id'],'forkedFromId':thread['forkedFromId'],'turns':[{'id':t['id'],'items':[{'type':i['type']} for i in t['items']]} for t in turns]}}},
    'observations':{'returnedTurnCount':len(turns),'historicalItemCount':sum(len(t['items']) for t in turns),'selectedBoundaryIsLastReturnedTurn': bool(turns and turns[-1]['id']==request['params']['lastTurnId']) if turns else None,'selectedCompletedResponse':boundary['item']['text'],'recallReply':recall,'recallToolCalls':sum(x['item'].get('type') in ('commandExecution','fileChange','mcpToolCall') for x in completed if x.get('threadId')==thread['id']),'transportOverflowObserved':False},
    'redaction':'Only request identifiers and history flags, response thread identifiers, historical turn identifiers and item types retained; model, machine, paths, config, credentials and item bodies omitted.'
}
pathlib.Path(output).write_text(json.dumps(proof,indent=2)+'\n')
print(json.dumps(proof,indent=2))
