from ops import *
HERE.chmod(0o700);PRIVATE.mkdir(mode=0o700)
containers={}
for n in cmd(['docker','ps','-a','--format','{{.Names}}']).splitlines():
    c=inspect(n);containers[n]=dict(id=c['Id'],image=c['Image'],started=c['State']['StartedAt'],running=c['State']['Running'])
rows=api('/api/v1/streams')['streams']
save('baseline.json',dict(containers=containers,ledger=ledger(),states=[{k:r.get(k) for k in ('stream_id','state','child_pid','cleanup_pending')} for r in rows]))
save('compose-before.json',json.loads(cmd(compose()+['config','--format','json'])),private=True)
for src,name in [('/workspace/contextra-runtime-config/web-start-candidate-20260918/candidate.env','candidate.env.before'),('/data/contextra/runtime-state/streams_runtime.yaml','runtime-original.yaml')]:
    shutil.copyfile(src,PRIVATE/name)
assert shutil.disk_usage('/').free>15*1024**3
cmd(['docker','stop','--time','20','contextra-ai-gateway-1'])
for r in api('/api/v1/streams')['streams']:
    if r['state']!='stopped' or r.get('child_pid'):
        request('/api/v1/streams/'+r['stream_id']+'/stop',{},timeout=90)
deadline=time.monotonic()+30
while True:
    rows=api('/api/v1/streams')['streams']
    if all(r['state']=='stopped' and not r.get('child_pid') and not r.get('cleanup_pending') for r in rows):break
    if time.monotonic()>deadline:raise RuntimeError('STOP_REAP_FAILED')
    time.sleep(1)
save('stopped.json',dict(channels=len(rows)));print(json.dumps(dict(stopped=len(rows),baseline_image=containers['contextra-analytics-1']['image'])))
