#!/usr/bin/env python3 """Frozen Pi native Intel evidence; synthetic loopback only, no external providers or publication.""" import argparse,re,datetime,difflib,hashlib,json,os,platform,shutil,signal,subprocess,sys,tempfile,time from pathlib import Path from closed_inventory import closed_tree from owned_processes import OwnedProcesses,atomic_json import source_guard from lifecycle import Lifecycle, run_test_cases from retain_pack import retain_pack from native_daemon_reuse import import_daemon from qualification_observer import QualificationInspection, wait_for_owned_command HERE=Path(__file__).resolve().parent INPUTS=json.loads((HERE/'profile-inputs.json').read_text()) PIN=INPUTS['localComparison'] SOURCE=PIN['sourceRevision'] sha=source_guard.sha require=source_guard.require def tool_invocation(name): found=shutil.which(name) require(found is not None,'Required executable not found: '+name) # Multicall CLIs dispatch on argv[0]; preserve the name returned by PATH lookup. invocation=Path(found).absolute() target=invocation.resolve(strict=True) require(invocation.name==name and target.is_file() and os.access(invocation,os.X_OK),'Unexpected executable invocation') return invocation, {'invocationPath':str(invocation),'resolvedTarget':str(target),'targetSha256':sha(target)} def verify_tool_invocation(invocation, audit): require(str(invocation)==audit['invocationPath'] and str(invocation.resolve(strict=True))==audit['resolvedTarget'], 'Executable invocation or target changed') require(sha(invocation.resolve(strict=True))==audit['targetSha256'],'Executable target bytes changed') def build_native_daemon(stage, scratch, env, run, receipt, save): """Compile this source; historical artifact bytes are never an input.""" pin=INPUTS['freshNativeBuild'] require(pin=={'toolchain':'1.97.1','target':'x86_64-apple-darwin','jobs':2,'deadlineSeconds':1500},'Unexpected native build recipe') rustup,audit=tool_invocation('rustup') verify_tool_invocation(rustup,audit) receipt['rustup']=audit;save() run([rustup,'toolchain','install',pin['toolchain'],'--profile','minimal','--component','rustfmt'],'rust-install',600) verify_tool_invocation(rustup,audit) cargo=Path(run([rustup,'which','--toolchain',pin['toolchain'],'cargo'],'cargo-path',30).strip()).resolve(strict=True) rustc=Path(run([rustup,'which','--toolchain',pin['toolchain'],'rustc'],'rustc-path',30).strip()).resolve(strict=True) env['RUSTC']=str(rustc) version=run([rustc,'--version','--verbose'],'rust-version-verbose',30) require(version.startswith('rustc 1.97.1 '),'Wrong Rust') cargo_version=run([cargo,'--version'],'cargo-version',30) require(cargo_version.startswith('cargo 1.97.1 '),'Wrong Cargo') sdk=Path(run(['/usr/bin/xcrun','--show-sdk-path'],'sdk-path',30).strip()).resolve(strict=True) require(sdk.is_dir(),'Apple SDK missing') sdk_version=run(['/usr/bin/xcrun','--show-sdk-version'],'sdk-version',30).strip() require(sdk_version,'Apple SDK version missing') env['SDKROOT']=str(sdk) tools={} for name in ('clang','ld'): path=Path(run(['/usr/bin/xcrun','--find',name],name+'-path',30).strip()).resolve(strict=True) require(path.is_file() and os.access(path,os.X_OK),'Apple tool missing: '+name) tools[name]={'path':str(path),'sha256':sha(path)} settings={p.name:sha(p) for p in (sdk/'SDKSettings.json',sdk/'SDKSettings.plist') if p.is_file()} require(settings,'Apple SDK settings missing') receipt['compiler']={'rustcSha256':sha(rustc),'cargoSha256':sha(cargo),'versionVerbose':version,'cargoVersion':cargo_version,'jobs':2, 'sdk':{'path':str(sdk),'version':sdk_version,'settings':settings},'appleTools':tools, 'target':pin['target'],'rustflags':env.get('RUSTFLAGS',''),'targetDirectory':env['CARGO_TARGET_DIR']} save() run([cargo,'build','--release','--target',pin['target'],'--manifest-path','packages/paperclip-runner/runner/Cargo.toml','--locked', '-p','paperclip-runner-core','--bin','paperclip-runnerd','-j','2'],'daemon-build',pin['deadlineSeconds']) daemon=stage/'packages/paperclip-runner/dist/bin/paperclip-runnerd';daemon.parent.mkdir(parents=True,exist_ok=True) shutil.copy2(scratch/'target'/pin['target']/'release/paperclip-runnerd',daemon) run(['/usr/bin/codesign','--force','--sign','-',daemon],'daemon-sign',30) run(['/usr/bin/codesign','--verify','--strict',daemon],'daemon-signature-verify',30) require('Mach-O 64-bit executable x86_64' in run(['/usr/bin/file',daemon],'daemon-architecture',30),'Wrong daemon architecture') receipt['daemonBuildMetadata']=json.loads(run([daemon,'--build-metadata'],'daemon-metadata',30)) require(receipt['daemonBuildMetadata']==INPUTS['expectedDaemonBuildMetadata'],'Wrong daemon build metadata') receipt.update(nativeRecompiled=True,nativeDaemonReuse=False,nativeBuildSource=SOURCE,daemonSha256=sha(daemon)) save() return daemon def reuse_native_daemon(archive,stage,out,scratch,run,receipt,save): """Retain original compiler/signature provenance; do not rebuild or re-sign.""" pin=INPUTS['nativeDaemonReuse'] require(pin['nativeInputEquivalentTo']==SOURCE and pin['claims']['freshNativeCompilation'] is False,'Wrong native reuse authority') daemon=stage/'packages/paperclip-runner/dist/bin/paperclip-runnerd' retained=scratch/'original-native-artifact' reuse=import_daemon(archive,out/'source.tar',retained,daemon,pin) require(reuse['declaredInputCount']==145,'Unexpected native input inventory scope') refs=out/'original-native-provenance';refs.mkdir(mode=0o700) for name in ('receipt.json','source-input-inventory.json','declared-input-equality.json'): shutil.copy2(retained/name,refs/name) receipt.update(nativeRecompiled=False,nativeDaemonReuse=reuse,nativeBuildSource=pin['originalBuildSource'], originalNativeCompiler=pin['compiler'],daemonSha256=sha(daemon));save() run(['/usr/bin/codesign','--verify','--strict',daemon],'daemon-signature-verify',30) require('Mach-O 64-bit executable x86_64' in run(['/usr/bin/file',daemon],'daemon-architecture',30),'Wrong daemon architecture') receipt['daemonBuildMetadata']=json.loads(run([daemon,'--build-metadata'],'daemon-metadata',30)) require(receipt['daemonBuildMetadata']==INPUTS['expectedDaemonBuildMetadata'],'Wrong daemon build metadata') require(sha(daemon)==pin['selectedFiles']['paperclip-runnerd']['sha256'],'Reused daemon changed during verification') save();return daemon def activate_profile13(): global INPUTS, PIN, SOURCE inputs=json.loads((HERE/'profile13-inputs.json').read_text()) pin=inputs['localComparison'] require(isinstance(pin.get('sourceRevision'),str) and re.fullmatch(r'[a-f0-9]{40}',pin['sourceRevision']) is not None,'Final profile13 source is not frozen') require(isinstance(pin.get('sourceArchiveSha256'),str) and re.fullmatch(r'[a-f0-9]{64}',pin['sourceArchiveSha256']) is not None,'Final profile13 archive is not frozen') require('nativeDaemonReuse' not in inputs and inputs['normalProviderSelection']['pi']['profileVersion']==13,'Profile13 requires fresh native compilation') tests=inputs.get('testSourcePins',{}) require(set(tests)=={'pi-closed-startup.test.mjs','pi-native-package-contract.test.mjs','pi-acp-package-contract.test.mjs'} and all(isinstance(value,str) and re.fullmatch(r'[a-f0-9]{64}',value) is not None for value in tests.values()),'Profile13 test source pins missing or malformed') INPUTS=inputs;PIN=pin;SOURCE=pin['sourceRevision'] def execute(args): stage=args.source.resolve(strict=True);out=args.output.resolve() out.mkdir(mode=0o700,parents=True,exist_ok=False) scratch=Path(tempfile.mkdtemp(prefix='pc-intel-',dir='/private/tmp'));scratch.chmod(0o700) identity=(scratch.stat().st_dev,scratch.stat().st_ino,scratch.stat().st_uid) receipt={'status':'running','sourceRevision':SOURCE,'trustedWorkflowRevision':os.environ['GITHUB_WORKFLOW_SHA'], 'startedAt':datetime.datetime.now(datetime.timezone.utc).isoformat(),'runId':os.environ['GITHUB_RUN_ID'],'runAttempt':os.environ['GITHUB_RUN_ATTEMPT'], 'runnerLabel':'macos-15-intel','hostIsBareMetalClaim':False,'providerCalls':0,'credentialsRead':False, 'externalProviderPromptsSubmitted':0,'syntheticLoopbackModelPromptsExpected':True,'imagePublications':0,'cloudSandboxesCreated':0,'automaticRetries':0, 'model':PIN['model'],'commands':[],'helpers':{p.name:sha(p) for p in HERE.iterdir() if p.is_file()}, 'originalTestSourceUnmodified':True,'cleanupObserverUsed':True,'localComparison':PIN} def save():atomic_json(out/'receipt.json',receipt) save() inherited_path=os.environ['PATH'] node=Path(shutil.which('node')).resolve(strict=True) pnpm=Path(shutil.which('pnpm')).resolve(strict=True) env={'PATH':inherited_path,'HOME':str(scratch/'home'),'TMPDIR':str(scratch),'LANG':'en_US.UTF-8','CI':'true', 'PAPERCLIP_TELEMETRY_ENABLED':'false','PAPERCLIP_RUNNER_SOURCE_REVISION':SOURCE, 'CARGO_HOME':str(scratch/'cargo'),'RUSTUP_HOME':str(scratch/'rustup'),'CARGO_TARGET_DIR':str(scratch/'target'), 'RUSTUP_TOOLCHAIN':'1.97.1','CARGO_BUILD_JOBS':'2','npm_config_audit':'false','npm_config_fund':'false', 'npm_config_update_notifier':'false','npm_config_package_import_method':'copy'} Path(env['HOME']).mkdir(mode=0o700) active=None;owner=None;lifecycle=Lifecycle() def stop_signal(signum,_):raise InterruptedError('CI stopped with signal '+str(signum)) signal.signal(signal.SIGTERM,stop_signal) def run(command,label,timeout,cwd=stage,command_env=None,owned=False): nonlocal active,owner lifecycle.begin() row={'label':label,'startedAt':datetime.datetime.now(datetime.timezone.utc).isoformat(),'command':list(map(str,command)),'deadlineSeconds':timeout,'status':'running'} receipt['commands'].append(row);save();start=time.monotonic() with (out/(label+'.log')).open('x') as log: try: if owned: owner=OwnedProcesses(out/(label+'-processes.json'),scratch,stage,pack/'dist/cli/acpx-runtime-sidecar.cjs') inspection=QualificationInspection(owner,start+timeout) owner.table=inspection.table;owner.argv=inspection.argv row['processInspection']={'maximumCallSeconds':5,'activeCadenceSeconds':.5,'sharedDefaultSeconds':2, 'deadlineCap':'remaining command or existing owned cleanup phase','activeFailuresFatal':True,'activeInspectionRetries':0} save() active=subprocess.Popen(row['command'],cwd=cwd,env=command_env or env,stdout=log,stderr=log,start_new_session=True) if owner:wait_for_owned_command(active,inspection) else: while active.poll() is None: require(time.monotonic()-start