import base64
import hashlib
import importlib.util
import json
from pathlib import Path
import subprocess

spec=importlib.util.spec_from_file_location('transport','/tmp/codex/ltb1021/2026-10-06_icerti-ai2-deploy_r01/remote.py')
remote=importlib.util.module_from_spec(spec);spec.loader.exec_module(remote)
repo=Path('/workspace/contextra-analytics-runtime-lifecycle-refactor')
relative='tools/icerti_offline/maintenance/vscode_safety.py'
before=subprocess.check_output(['git','-C',str(repo),'show','HEAD:'+relative],timeout=10)
after=(repo/relative).read_bytes()
header='EXPECTED='+repr(hashlib.sha256(before).hexdigest())+'\nPAYLOAD='+repr(base64.b64encode(after).decode())+'\n'
CODE=r'''
import base64,hashlib,json,os,signal,subprocess,sys,time
from pathlib import Path
signal.alarm(50)
prefix=Path('/usr/local/lib/contextra-maintenance/portable-20261006T192646')
sys.path.insert(0,str(prefix))
import field_profiles as fp,server_context as server
server.verify_tools()
assert server.operator()=='si'
def states():
    r=subprocess.run(['docker','ps','-a','--filter','label=com.docker.compose.project=contextra-ai2','--format','{{.ID}} {{.State}} {{.Image}}'],text=True,capture_output=True,timeout=10)
    assert r.returncode==0
    return sorted(r.stdout.splitlines())
services=states();assert len(services)==5 and all(' exited ' in x for x in services)
active=fp.RUNTIME/'state/active.json';active_before=active.read_bytes()
target=prefix/'vscode_safety.py';raw=target.read_bytes()
assert hashlib.sha256(raw).hexdigest()==EXPECTED,'SOURCE_INSTALL_CONFLICT'
inventory_path=prefix/'installed-files.json';inventory_raw=inventory_path.read_bytes();inventory=json.loads(inventory_raw)
assert inventory['vscode_safety.py']==EXPECTED
backup=fp.STATE/'vscode-tool-updates'/str(time.time_ns());backup.mkdir(parents=True,mode=0o700)
fp.atomic(backup/'vscode_safety.py',raw)
fp.atomic(backup/'installed-files.json',inventory_raw)
data=base64.b64decode(PAYLOAD)
fp.atomic(target,data,mode=0o644)
inventory['vscode_safety.py']=hashlib.sha256(data).hexdigest()
fp.atomic(inventory_path,inventory,mode=0o644)
server.verify_tools()
r=subprocess.run(['/usr/local/bin/ct','vscode','apply'],input='APPLY\n',capture_output=True,text=True,timeout=15)
assert r.returncode==0,'SETTINGS_APPLY_FAILED'
print(r.stdout)
import vscode_safety as safety
current,settings_raw=safety.load()
assert not safety.plan(current)[1]
assert safety.SETTINGS.stat().st_uid==fp.account().pw_uid
assert services==states() and active.read_bytes()==active_before,'RUNTIME_STATE_CHANGED'
record=dict(tool_before=EXPECTED,tool_after=inventory['vscode_safety.py'],tool_backup=str(backup),settings=str(safety.SETTINGS),settings_backup=fp.read_json(fp.STATE/'vscode-safety-last.json')['backup'],settings_sha256=hashlib.sha256(settings_raw).hexdigest(),owner_uid=safety.SETTINGS.stat().st_uid,services_unchanged=True,active_unchanged=True)
fp.atomic(backup/'receipt.json',record)
print('RECEIPT',json.dumps(record))
'''
raw=remote.run(header+CODE,root=True,timeout=60)
p=Path(__file__).parent/'apply.log';p.write_text(raw);p.chmod(0o600)
print(raw)
