Files
2026-09-30 21:00:33 +08:00

56 lines
3.0 KiB
Python

"""Detached parent supervisor, with real final exit receipts outside EXP.
Administrative stdout is separate from the immutable per-trial ledger. Launch
is exclusive, never a retry policy. A launch PID is NOT a completion receipt.
"""
import argparse
from datetime import datetime, timezone
import os
import subprocess
import sys
import time
from normal_io import *
CONTROL=ROOT/'logs/phase4ar-normal-conditioning'
def authority(sha):
require(sys.dont_write_bytecode,'Use -B')
require(digest(EXP/'protocol/preregistered.json')==sha,'Registration differs')
reg=read(EXP/'protocol/preregistered.json');verify(reg['source_sha256'])
require(reg['scientific_scope']=='normal-acquisition-only' and unlinked(CONTROL).is_dir(),'Wrong scope/control directory')
require(not (EXP/'audit/stopped.json').exists() and not (EXP/'audit/execution-complete.json').exists(),
'Stopped/completed phase cannot launch')
return reg
def launch(sha):
authority(sha)
require(not any(CONTROL.iterdir()),'Control directory nonempty: inspect, do not retry')
save(CONTROL/'launch-attempt.json',dict(registration_sha256=sha,started_utc=datetime.now(timezone.utc).isoformat(),
complete=False,terminal_state='UNKNOWN',automatic_retry=False))
command=[sys.executable,'-B',str(MODEL/'run_normal.py'),'supervise','--registration-sha256',sha]
with unlinked(CONTROL/'stdout.log').open('xb') as out,unlinked(CONTROL/'stderr.log').open('xb') as err:
process=subprocess.Popen(command,cwd=MODEL,stdin=subprocess.DEVNULL,stdout=out,stderr=err,start_new_session=True,
env={**os.environ,'PYTHONDONTWRITEBYTECODE':'1'})
record=dict(supervisor_pid=process.pid,argv=command,registration_sha256=sha,launch_observed=True,
final_exit_observed=False,not_evidence_of_completion=True)
save(CONTROL/'launch.json',record);return record
def supervise(sha):
authority(sha)
save(CONTROL/'supervisor-start.json',dict(pid=os.getpid(),registration_sha256=sha,
started_utc=datetime.now(timezone.utc).isoformat(),complete=False))
command=[sys.executable,'-B',str(MODEL/'normal_runner.py'),'--registration-sha256',sha]
started=time.perf_counter();code=None;error=None
try:code=subprocess.run(command,cwd=MODEL,stdin=subprocess.DEVNULL).returncode
except BaseException as exc:error=type(exc).__name__+': '+str(exc)
save(CONTROL/'exit.json',dict(registration_sha256=sha,argv=command,exit_code=code,
final_exit_observed=type(code)is int,wall_seconds=time.perf_counter()-started,error=error,
complete=code==0,learning_success_claimed=False,scientific_analysis_required=True))
return 0 if code==0 else 1
if __name__=='__main__':
parser=argparse.ArgumentParser();parser.add_argument('mode',choices=('launch','supervise'))
parser.add_argument('--registration-sha256',required=True);args=parser.parse_args()
if args.mode=='launch':print(canonical(launch(args.registration_sha256)),flush=True)
else:sys.exit(supervise(args.registration_sha256))