import base64,hashlib,io,json,pathlib,sys,tarfile
ROOT=pathlib.Path(__file__).resolve().parent
REPO=pathlib.Path('/workspace/contextra-analytics-runtime-lifecycle-refactor')
REMOTE='/storage/contextra/maintenance/fight-display-20261102-r01'
sys.path.insert(0,'/data/codex-artifacts/contextra/action-model-eval/2026/2026-10-26_contextra-camera24-prep_r01/helpers')
from remote import run

def call(args,sudo=False,data=None,timeout=60):
 r=run(args,sudo=sudo,data=data,timeout=timeout)
 if r.returncode:raise RuntimeError(r.stderr.decode(errors='replace')[-2000:])
 return r.stdout

def prepare():
 code="""import json,sys,hashlib,pathlib
d=json.loads(pathlib.Path('/etc/contextra-maintenance/server.json').read_text());sys.path.insert(0,d['paths']['tools']);import compose_backend as cb
rows=cb.containers();print(json.dumps({'images':{r['Config']['Labels']['com.docker.compose.service']:r['Image'] for r in rows}}))
"""
 m=json.loads(call(['python3','-B','-c',code],sudo=True))
 code="import hashlib,pathlib;print(hashlib.sha256(pathlib.Path('/opt/contextra/app/fight_r5/runtime.py').read_bytes()).hexdigest())"
 before=call(['docker','exec','contextra-ai2-analytics-1','python3','-B','-c',code],sudo=True).decode().strip()
 head=__import__('subprocess').check_output(['git','show','HEAD:app/fight_r5/runtime.py'],cwd=REPO)
 assert hashlib.sha256(head).hexdigest()==before,'Site source differs from development baseline'
 package=ROOT/'package';package.mkdir()
 names=['app/fight_r5/runtime.py','app/fight_r5/display.py','app/fight_r5/display_policy.py']
 after={}
 for n in names:
  p=package/'payload'/n;p.parent.mkdir(parents=True,exist_ok=True);p.write_bytes((REPO/n).read_bytes());after[n]=hashlib.sha256(p.read_bytes()).hexdigest()
 manifest=dict(server='icerti-ai2',images=m['images'],before={'app/fight_r5/runtime.py':before},after=after)
 (package/'manifest.json').write_text(json.dumps(manifest,indent=2))
 for n in ('artifact_install.py','trace_install.py'):
  s=(REPO/'tools/icerti_offline'/n).read_text().replace("['docker','run','--rm','--pull=never','--name'","['docker','run','--rm','--runtime=runc','--pull=never','--name'")
  (package/n).write_text(s)
 (package/'install.py').write_bytes((ROOT/'install.py').read_bytes())
 (package/'tests').mkdir()
 for p in (REPO/'tests').glob('*.py'):(package/'tests'/p.name).write_bytes(p.read_bytes())
 stream=io.BytesIO()
 with tarfile.open(fileobj=stream,mode='w:gz') as t:t.add(package,arcname='.')
 blob=stream.getvalue();incoming='/home/si/fight-display-20261102-r01.tar.gz'
 call(['python3','-B','-c','import sys,pathlib;p=pathlib.Path('+repr(incoming)+');assert not p.exists();p.write_bytes(sys.stdin.buffer.read())'],data=blob)
 call(['python3','-B','-c','import pathlib,tarfile;d=pathlib.Path('+repr(REMOTE)+');assert not d.exists();d.mkdir(mode=0o700);tarfile.open('+repr(incoming)+').extractall(d,filter="data")'],sudo=True)
 print('PACKAGE_READY')

if __name__=='__main__':
 action=sys.argv[1]
 if action=='package':prepare()
 else:
  assert action in ('prepare','build','test','activate','verify')
  out=call(['python3','-B',REMOTE+'/install.py',REMOTE,action],sudo=True,timeout=750)
  (ROOT/(action+'.log')).write_bytes(out);print(out.decode()[-3000:])
