Files
ARCADIA-Studio/harness/experiments/state-bends-b868541-20260923/gates/recipes/final.py
T

89 lines
7.6 KiB
Python

"""Final identified State-bend gates. PREPARED ONLY; parent authorizes execution."""
from pathlib import Path
import argparse, datetime, hashlib, json, os, re, shutil, subprocess, sys
ROOT=Path(__file__).resolve().parent
REPO=ROOT.parent/'state-bends-20260923'
WORKSPACE=ROOT.parent.parent
ENV_SCRIPT=ROOT.parent/'toolchain/env.ps1'
RUNTIME=ROOT.parent/'toolchain/llvm-mingw-20260908-ucrt-x86_64/bin/libunwind.dll'
RUNTIME_SHA='aa282fa47bb2c4e210cea5e470cdbdca58568f0be0bc73e404d86ab9cd95ef6a'
def record(path):
p=Path(path).resolve();data=p.read_bytes();return {'path':str(p),'bytes':len(data),'sha256':hashlib.sha256(data).hexdigest()}
def save(path,value):
with path.open('x',encoding='utf-8',newline='\n') as f:json.dump(value,f,indent=2,ensure_ascii=False,allow_nan=False);f.write('\n')
def git(*args):return subprocess.check_output(['git','-c','core.longpaths=true','-C',str(REPO),*args])
def inputs():
return [record(REPO/p.decode()) for p in sorted(git('ls-files','--cached','--others','--exclude-standard','-z').split(b'\0')) if p and (REPO/p.decode()).is_file()]
def now():return datetime.datetime.now(datetime.timezone.utc).isoformat()
def main():
p=argparse.ArgumentParser(description=__doc__);p.add_argument('--source-commit',required=True);p.add_argument('--attempt',required=True);a=p.parse_args()
pin=a.source_commit
if not re.fullmatch('[0-9a-f]{40}',pin) or not re.fullmatch(r'final-[0-9]{2}',a.attempt):raise RuntimeError('Explicit full source pin and fresh final-NN attempt required')
def clean():
if git('rev-parse','HEAD').decode().strip()!=pin or git('status','--porcelain'):raise RuntimeError('Final gates require exact clean committed HEAD')
clean()
expected_cargo=(ROOT.parent/'toolchain/cargo').resolve();target=(WORKSPACE/'target').resolve()
if Path(os.environ.get('CARGO_HOME','')).resolve()!=expected_cargo or Path(os.environ.get('CARGO_TARGET_DIR','')).resolve()!=target or os.environ.get('RUSTUP_TOOLCHAIN')!='stable-x86_64-pc-windows-gnullvm':raise RuntimeError('Source parent env.ps1 and explicitly select shared target before invocation')
if record(RUNTIME)['sha256']!=RUNTIME_SHA:raise RuntimeError('Admitted runtime differs')
out=ROOT/a.attempt;out.mkdir(exist_ok=False);(out/'artifacts').mkdir()
before=inputs();save(out/'inputs-before.json',before)
environment={k:os.environ.get(k) for k in ['PATH','CARGO_HOME','RUSTUP_HOME','RUSTUP_TOOLCHAIN','CARGO_TARGET_DIR','CARGO_BUILD_JOBS','CARGO_INCREMENTAL','CARGO_TARGET_X86_64_PC_WINDOWS_GNULLVM_LINKER','RC','RUSTFLAGS','CARGO_ENCODED_RUSTFLAGS']}
configs=[];dirs=[REPO,*REPO.parents,expected_cargo]
for directory in dict.fromkeys(dirs):
for name in ('config','config.toml'):
path=directory/name if directory==expected_cargo else directory/'.cargo'/name
configs.append({'path':str(path),'present':path.is_file(),'record':record(path) if path.is_file() else None})
save(out/'environment.json',{'environment':environment,'env_script':record(ENV_SCRIPT),'cargo_configs':configs,'cargo_resolved':shutil.which('cargo'),'rustc_resolved':shutil.which('rustc'),'runtime':record(RUNTIME),'orchestrator':record(Path(__file__)),'command_runner':record(ROOT/'run.py')})
steps=[];outputs=[];relocations=[];failure=None;after=None;unchanged=False
def preserve(path):
original=record(path);dest=out/'artifacts'/path.name
with path.open('rb') as src,dest.open('xb') as dst:shutil.copyfileobj(src,dst)
copied=record(dest)
if record(path)!=original or any(original[k]!=copied[k] for k in ('bytes','sha256')):raise RuntimeError('Artifact changed during preservation')
outputs.append(copied);relocations.append({'original':original,'preserved':copied})
commands=[
('toolchain',['rustc','--version','--verbose'],[]),
('cargo-version',['cargo','--version','--verbose'],[]),
('workspace-tests',['cargo','test','--workspace','--locked','--offline'],[]),
('workspace-clippy',['cargo','clippy','--workspace','--all-targets','--locked','--offline','--','-D','warnings'],[]),
('desktop-build',['cargo','build','-p','oa-desktop','--locked','--offline'],[target/'debug/arcadia-studio.exe']),
('evaluators-build',['cargo','build','-p','oa-core','--example','attachment_snapshot','--example','state_bend_routing_snapshot','--locked','--offline'],[target/'debug/examples/attachment_snapshot.exe',target/'debug/examples/state_bend_routing_snapshot.exe'])]
started=now()
try:
for name,argv,artifacts in commands:
clean()
wrapper_log=out/(name+'.orchestration.log')
with wrapper_log.open('xb') as log:
proc=subprocess.run([sys.executable,str(ROOT/'run.py'),a.attempt+'/'+name,*argv],cwd=WORKSPACE,stdout=log,stderr=subprocess.STDOUT)
result_path=out/name/'result.json';result=json.loads(result_path.read_text(encoding='utf-8')) if result_path.is_file() else None
step={'name':name,'argv':argv,'runner_exit_code':proc.returncode,'orchestration_log':record(wrapper_log),'result':record(result_path) if result else None}
steps.append(step)
if proc.returncode or result is None or result['exit_code']!=0 or result['inputs_unchanged'] is not True or result['source_commit']!=pin or result['working_changes']:raise RuntimeError('Final gate failed: '+name)
for phase in ('inputs-before.json','inputs-after.json'):
if json.loads((out/name/phase).read_text(encoding='utf-8'))!=before:raise RuntimeError('Source inventory differs in '+name+'/'+phase)
for path in artifacts:preserve(path)
preserve(RUNTIME)
except Exception as error:failure=str(error)
finally:
verification_errors=[]
try:
after=inputs();save(out/'inputs-after.json',after);unchanged=before==after;clean()
if not unchanged:verification_errors.append('Source inventories changed')
frozen_environment=json.loads((out/'environment.json').read_text(encoding='utf-8'))
for key in ('env_script','runtime','orchestrator','command_runner'):
if record(frozen_environment[key]['path'])!=frozen_environment[key]:verification_errors.append('Bound gate input changed: '+key)
for cfg in configs:
path=Path(cfg['path'])
if path.is_file()!=cfg['present'] or (cfg['present'] and record(path)!=cfg['record']):verification_errors.append('Cargo config changed: '+str(path))
for entry in outputs:
if record(entry['path'])!=entry:verification_errors.append('Preserved artifact changed')
except Exception as error:verification_errors.append('Final capture/verification failed: '+str(error));unchanged=False
if verification_errors:failure='; '.join(([failure] if failure else [])+verification_errors)
save(out/'artifact-relocation.json',{'source_commit':pin,'artifacts':relocations,'scope':'Original shared-target locations are historical; native stage must bind preserved copies'})
passed=failure is None and unchanged and len(steps)==len(commands) and len(outputs)==4
save(out/'summary.json',{'source_commit':pin,'passed':passed,'inputs_unchanged':unchanged,'started_utc':started,'finished_utc':now(),'failure':failure,'steps':steps,'outputs':outputs,'source_manifest':record(out/'inputs-before.json'),'environment':record(out/'environment.json'),'relocation':record(out/'artifact-relocation.json'),'scope':'Recorded command exit codes and exact input inventories; no native GUI acceptance'})
print(json.dumps({'summary':str(out/'summary.json'),'passed':passed,'failure':failure},indent=2))
if not passed:raise SystemExit(1)
if __name__=='__main__':main()