import csv
import hashlib
import json
import os
from pathlib import Path
import subprocess

os.umask(0o077)
R=Path(__file__).parent
def read(path): return json.loads(path.read_text())
def save(name,obj): (R/name).write_text(json.dumps(obj,ensure_ascii=False,indent=2))
old=Path('/tmp/codex/ltb1021/2026-09-15_contextra-sixteen-prepared_r01')
retry=old.with_name(old.name.replace('_r01','_r02'))
a=read(old/'startup-samples.json')[-1];b=read(old/'failure-state.json');dt=b['at']-a['at']
rows=[]
for sid,q in b['channels'].items():
    if q['state']!='running':continue
    before=a['channels'][sid]
    assert q['run_id']==before['run_id'] and q['generation']==before['generation']
    row=dict(stream_id=sid,seconds=dt,scope='startup_reference_not_steady')
    row.update({k: (q['counts'].get(k,0)-before['counts'].get(k,0))/dt
                for k in ['decoded','selected','preprocess','infer','native','result','publisher_submit']})
    row['processed']=(q['processed']-before['processed'])/dt
    rows.append(row)
with (R/'sixteen-reference-boundaries.csv').open('w') as f:
    writer=csv.DictWriter(f,fieldnames=list(rows[0]));writer.writeheader();writer.writerows(rows)
data=read(R/'three-current.json');summary=read(R/'three-current-summary.json')
first,last=data['samples'][0],data['samples'][-1]
before,after=data['resources']; seconds=after['at']-before['at']
threads=[]
for tid,t in after['threads'].items():
    previous=before['threads'].get(tid)
    if previous and previous['start']==t['start']:
        threads.append(dict(pid=t['pid'],tid=tid,name=t['comm'],
            cpu_percent=100*(t['runtime_ns']-previous['runtime_ns'])/1e9/seconds,
            runqueue_ms=(t['runqueue_wait_ns']-previous['runqueue_wait_ns'])/1e6))
current=[]
for source,value in summary.items():
    x,y=first['channels'][source]['state'],last['channels'][source]['state']
    seconds_channel=last['channels'][source]['at']-first['channels'][source]['at']
    exact={k:(v-x['roles']['det']['stage_counts'].get(k,0))/seconds_channel
           for k,v in y['roles']['det']['stage_counts'].items()}
    current.append(dict(source=source,result_fps=value['counter_delta']['processed']/seconds_channel,
        redis_fps=value['redis_fps'],queue_min=min(value['queue']),queue_max=max(value['queue']),
        queue_final=value['queue'][-1],stale_delta=value['counter_delta'].get('stale',0),
        drop_delta=value['counter_delta'].get('queue_drop',0),role_stage_fps=exact,
        observation_missed_delta=y['metadata_path']['performance']['observation_missed']-x['metadata_path']['performance']['observation_missed'],
        redis_length=last['channels'][source]['redis']['length'],ttl_ms=value['ttl']))
with (R/'current-three.csv').open('w') as f:
    fields=['source','result_fps','redis_fps','queue_min','queue_max','queue_final','stale_delta','drop_delta','redis_length']
    writer=csv.DictWriter(f,fieldnames=fields,extrasaction='ignore');writer.writeheader();writer.writerows(current)
pubdelta={k:last['publisher']['metrics'].get(k,0)-first['publisher']['metrics'].get(k,0)
          for k in ['sent_frames','sent_status','replaced','expired','send_error','control_handoff_timeout']}
rp,rf=read(retry/'plan.json'),read(retry/'final.json')
retrydelta={k:rf['publisher']['metrics'].get(k,0)-rp['publisher'].get(k,0)
            for k in ['workers_created','worker_start_error','worker_limit','worker_unavailable','control_handoff_timeout']}
plan=read(R/'plan.json');final=read(R/'final.json')
same=all(next(q for q in plan['states'] if q['stream_id']==sid)['run_id']==next(q for q in final['states']['streams'] if q['stream_id']==sid)['run_id']
         for sid in ['rtsp-test-01','web-cam08-test','web-cam01-test'])
out=dict(current_three=current,publisher_delta=pubdelta,retry_admission_delta=retrydelta,
    sixteen_reference_ranges={k:[min(r[k] for r in rows),max(r[k] for r in rows)] for k in ['decoded','selected','preprocess','infer','native','result']},
    resources=dict(cgroup_cpu_percent=100*(after['cpu']['usage_usec']-before['cpu']['usage_usec'])/1e6/seconds,
                   throttled_delta=after['cpu'].get('nr_throttled',0)-before['cpu'].get('nr_throttled',0),
                   ram_mib=[before['memory']/1024**2,after['memory']/1024**2],gpu=[before['gpu'],after['gpu']],
                   top_threads=sorted(threads,key=lambda x:x['cpu_percent'],reverse=True)[:12]),
    preserved=dict(original_runs=same,registry_hash=plan['registry_hash']==final['registry_hash']),
    limitations=['16-channel markers are startup reference, not steady FPS or GPU kernel time.',
                 'No paired Triton statistics/CPU timings in historical16 window.',
                 'Handoff timeout confirmed; original bootstrap traceback unavailable.',
                 'Current result>10 reflects queue draining/boundary timing, not increased configured FPS.',
                 'Diagnostic source tested, not deployed to existing image.'])
save('summary.json',out)
print(json.dumps(out,ensure_ascii=False))
code="import urllib.request,json; print(json.dumps({x:json.load(urllib.request.urlopen('http://127.0.0.1:8000/v2/models/RFDETRMedium/'+x,timeout=3)) for x in ['config','stats']}))"
triton=json.loads(subprocess.check_output(['docker','exec','contextra-analytics-1','python3','-c',code],text=True))
save('triton-single-snapshot.json',dict(cumulative_not_window=True,**triton))
