import sys,json,sqlite3,collections,pathlib
root=pathlib.Path(sys.argv[1]); out=pathlib.Path(sys.argv[2]); side=sys.argv[3]; sha=sys.argv[4]
out.mkdir(exist_ok=True)
db=sqlite3.connect(f'file:{root}/.t3/userdata/statev2.sqlite?mode=ro',uri=True)
rows=db.execute('select thread_id,provider_session_id,payload_json from orchestration_v2_projection_provider_threads order by rowid').fetchall()
threads=[dict(label=chr(65+i),threadId=r[0],sessionId=r[1],nativeId=json.loads(r[2])['nativeThreadRef']['nativeId']) for i,r in enumerate(rows)]
runs=db.execute('select thread_id,status from orchestration_v2_projection_runs').fetchall()
result=dict(side=side,commit=sha,environment='Linux; real T3 dev server; Codex CLI 0.167.2; fresh unseeded database',threads=threads,runs=[dict(threadId=t,status=s) for t,s in runs],files=[])
for f in sorted((root/'.t3/userdata/logs/provider').glob('events.*.log')):
 records=[]
 for line in f.read_text().splitlines():
  try: obj=json.loads(line[line.index('{'):])
  except (ValueError,json.JSONDecodeError): continue
  if obj.get('protocol')!='codex.app-server': continue
  e=obj['event']; p=e.get('payload',{}); raw=json.dumps(p)
  refs=[t['label'] for t in threads if t['nativeId'] in raw]
  # Preserve routing fields while excluding prompts, credentials, local paths and model instructions.
  records.append(dict(direction=e.get('direction'),stage=e.get('stage'),requestId=p.get('id'),method=p.get('method'),nativeThreadReferences=refs))
 result['files'].append(dict(file=f.name,protocolRecords=len(records),nativeReferences=dict(collections.Counter(x for r in records for x in r['nativeThreadReferences'])),records=records))
(out/f'{side}.json').write_text(json.dumps(result,indent=2)+'\n')
lines=[f'{side.upper()} | {sha}',result['environment'],'','Reproduction: Thread A: gpt-6-luna; Thread B: gpt-6.1-sol', 'Both prompts: Reply with the word alpha only.','Both runs completed; one shared Codex app-server session.','']
for t in threads: lines += [f"Thread {t['label']}: {t['threadId']}",f"  Native Codex id: {t['nativeId']}"]
lines+=['','Actual files in logs/provider/ (codex.app-server records):']
for f in result['files']:
 lines += [f"  {f['file']}",f"    {f['protocolRecords']} records; native-id references: {f['nativeReferences']}"]
for t in threads:
 filename='events.'+t['threadId'].replace(':','-')+'.log'
 if not any(f['file']==filename for f in result['files']): lines += [f"  MISSING: Thread {t['label']} events file"]
lines+=['','Counts match protocol payloads to native ids from the dev database.', 'Records without a native id are not assigned by this count.']
(out/f'{side}.txt').write_text('\n'.join(lines)+'\n')
from PIL import Image,ImageDraw,ImageFont
font=ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf',17)
im=Image.new('RGB',(1450,len(lines)*28+52),'#101820'); draw=ImageDraw.Draw(im)
for i,line in enumerate(lines): draw.text((24,24+i*28),line,font=font,fill='#e5eef5')
im.save(out/f'{side}.png')
print('\n'.join(lines))
