import hashlib
import json
import os
from pathlib import Path
import shutil
import signal
import subprocess
import tarfile
import time
import urllib.request

os.umask(0o077)
HERE=Path(__file__).parent;HERE.chmod(0o700)
REPO=Path('/workspace/contextra-analytics-runtime-lifecycle-refactor')
PRIVATE=Path('/workspace/contextra-runtime-config')
def cmd(args,timeout=25):
    p=subprocess.run(args,text=True,capture_output=True,timeout=timeout)
    if p.returncode:
        save('error-'+str(time.time_ns())+'.json',dict(code=p.returncode,stderr=p.stderr,stdout=p.stdout))
        raise RuntimeError('COMMAND_FAILED; private evidence saved')
    return p.stdout
def save(name,value):
    with (HERE/name).open('x') as f:json.dump(value,f,indent=2)
def inspect(name):return json.loads(cmd(['docker','inspect',name]))[0]
def states():
    with urllib.request.urlopen('http://127.0.0.1:35000/api/v1/streams',timeout=5) as r:
        return {s['stream_id']:{k:s.get(k) for k in ('state','child_pid','run_id','run_generation')} for s in json.load(r)['streams']}
assert shutil.disk_usage('/var/lib/docker').free>15*1024**3
before=dict(analytics=inspect('contextra-analytics-1')['Id'],redis=inspect('contextra-redis-1')['Id'],
    states=states(),sidecar=inspect('contextra-ai-control-sidecar-1')['Id'])
save('before.json',before)
head=cmd(['git','-C',str(REPO),'rev-parse','HEAD']).strip()
source={str(p.relative_to(REPO)):hashlib.sha256(p.read_bytes()).hexdigest() for p in (REPO/'control_sidecar').glob('*.py')}
digest=hashlib.sha256(json.dumps(source,sort_keys=True).encode()).hexdigest()[:8]
tag='contextra-sidecar:event-http-'+head[:7]+'-'+digest
snapshot=HERE/'snapshot';snapshot.mkdir()
proc=subprocess.Popen(['git','-C',str(REPO),'archive','HEAD','control_sidecar'],stdout=subprocess.PIPE)
with tarfile.open(fileobj=proc.stdout,mode='r|') as archive:archive.extractall(snapshot,filter='data')
assert proc.wait()==0
for p in source:shutil.copy2(REPO/p,snapshot/p)
base='contextra-analytics:secure-rest-b644461-9d617905'
save('build-intent.json',dict(tag=tag,head=head,source=source,base=base))
with (HERE/'build.log').open('x') as log:
    proc=subprocess.Popen(['docker','build','--pull=false','--network=default',
        '--build-arg','SIDECAR_BASE_IMAGE='+base,'-t',tag,'.'],cwd=snapshot/'control_sidecar',stdout=log,stderr=log,start_new_session=True)
    start=time.monotonic()
    while proc.poll() is None:
        if time.monotonic()-start>300 or shutil.disk_usage('/var/lib/docker').free<15*1024**3:
            os.killpg(proc.pid,signal.SIGTERM);proc.wait(20);raise RuntimeError('BUILD_BOUND')
        time.sleep(1)
assert proc.returncode==0
image=json.loads(cmd(['docker','image','inspect',tag]))[0]['Id']
envfile=PRIVATE/'web-start-candidate-20260918/candidate.env'
original=envfile.read_text();save('env-before.json',dict(path=str(envfile),content=original))
assert 'AI_CONTROL_EVENT_ENDPOINT=' not in original and 'CONTEXTRA_SIDECAR_IMAGE=' not in original
updated=original.rstrip()+'\nCONTEXTRA_SIDECAR_IMAGE='+image+'\nAI_CONTROL_EVENT_ENDPOINT=http://192.168.50.101:9090/api/v1/events\n'
assert envfile.read_text()==original
temp=envfile.with_suffix('.pending');assert not temp.exists()
temp.write_text(updated);temp.chmod(0o600);temp.replace(envfile)
compose=json.loads(Path('/tmp/codex/ltb1021/2026-09-18_contextra-web-integration_r01/ready.json').read_text())['compose_command']
merged=json.loads(cmd(compose+['config','--format','json']))
side=merged['services']['ai-control-sidecar']
assert side['image']==image and side['environment']['AI_CONTROL_MANAGER_BASE_URL']=='https://192.168.50.101'
assert side['environment']['AI_CONTROL_EVENT_ENDPOINT']=='http://192.168.50.101:9090/api/v1/events'
save('reflect-intent.json',dict(image=image,tag=tag,compose=compose))
cmd(compose+['up','-d','--no-deps','--no-build','--pull','never','ai-control-sidecar'],120)
deadline=time.monotonic()+45
while time.monotonic()<deadline:
    actual=inspect('contextra-ai-control-sidecar-1')
    if actual['State'].get('Health',{}).get('Status')=='healthy':break
    time.sleep(1)
else:raise RuntimeError('SIDECAR_READINESS_FAILED')
env=dict(v.split('=',1) for v in actual['Config']['Env'])
assert actual['Image']==image and env['AI_CONTROL_EVENT_ENDPOINT']=='http://192.168.50.101:9090/api/v1/events'
assert env['AI_CONTROL_MANAGER_BASE_URL']=='https://192.168.50.101'
assert inspect('contextra-analytics-1')['Id']==before['analytics']
assert inspect('contextra-redis-1')['Id']==before['redis']
after=states()
save('result.json',dict(image=image,tag=tag,event_endpoint=env['AI_CONTROL_EVENT_ENDPOINT'],
    manager=env['AI_CONTROL_MANAGER_BASE_URL'],analytics_redis_preserved=True,
    channel_states_unchanged=after==before['states'],states=after,manual_post=False,source=source))
print(json.dumps(dict(tag=tag,healthy=True,channel_states_unchanged=after==before['states'],manual_post=False)),flush=True)
