From 4ba81672ae9f3d4cbfcccf3417fa372f3b7c5023 Mon Sep 17 00:00:00 2001 From: Dotta Date: Fri, 2 Oct 2026 05:31:16 -0500 Subject: [PATCH] ci: evaluate isolated Pi admission overlap Co-authored-by: Paperclip --- .github/workflows/docker-runner-check.yml | 63 +++++++++- .../ci/pi-intel/startup-overlap-inputs.json | 86 +++++++++++++ .../ci/pi-intel/startup-overlap-patch.json | 85 +++++++++++++ scripts/ci/pi-intel/startup_overlap.py | 119 ++++++++++++++++++ scripts/ci/pi-intel/startup_overlap_patch.py | 46 +++++++ scripts/ci/pi-intel/test_startup_overlap.py | 75 +++++++++++ 6 files changed, 472 insertions(+), 2 deletions(-) create mode 100644 scripts/ci/pi-intel/startup-overlap-inputs.json create mode 100644 scripts/ci/pi-intel/startup-overlap-patch.json create mode 100644 scripts/ci/pi-intel/startup_overlap.py create mode 100644 scripts/ci/pi-intel/startup_overlap_patch.py create mode 100644 scripts/ci/pi-intel/test_startup_overlap.py diff --git a/.github/workflows/docker-runner-check.yml b/.github/workflows/docker-runner-check.yml index e217c84bb1..1d88a386dd 100644 --- a/.github/workflows/docker-runner-check.yml +++ b/.github/workflows/docker-runner-check.yml @@ -39,6 +39,10 @@ on: description: "Measure exact retained B9 snapshots in four process-start pool4/16 ABBA children (diagnostic only)" type: boolean default: false + pi_startup_overlap: + description: "With diagnose_pi_startup, evaluate one unpublished two-module admission-overlap derivative (not qualification)" + type: boolean + default: false diagnose_pi_startup: description: "Instrument one retained B9 profile12 native Intel startup with unchanged deadlines (diagnostic only, no provider prompts)" type: boolean @@ -78,7 +82,7 @@ permissions: {} concurrency: # Different immutable manual sources retain independent evidence; the same # source/mode still supersedes itself. Ordinary PR grouping is unchanged. - group: docker-runner-check-${{ github.event.pull_request.number || github.ref }}-${{ inputs.diagnose_pi_snapshot_streaming && 'pi-snapshot-streaming' || inputs.diagnose_pi_snapshot_pool && 'pi-snapshot-pool' || inputs.diagnose_pi_startup && 'pi-startup-diagnostic' || inputs.verify_pi_intel && 'pi-native-intel' || inputs.diagnose_ajv_pack && 'ajv-diagnostic' || inputs.verify_runner && 'runner-verification' || inputs.source_e2e_support_only && 'source-e2e-support' || inputs.source_root_tests_only && 'source-root-tests' || inputs.verify_source && 'verification' || inputs.verify_public_install && 'public-install' || inputs.build_eval_viewer && 'viewer' || 'image' }}${{ github.event_name == 'workflow_dispatch' && inputs.expected_source_sha && format('-{0}', inputs.expected_source_sha) || '' }} + group: docker-runner-check-${{ github.event.pull_request.number || github.ref }}-${{ inputs.diagnose_pi_snapshot_streaming && 'pi-snapshot-streaming' || inputs.diagnose_pi_snapshot_pool && 'pi-snapshot-pool' || inputs.pi_startup_overlap && 'pi-startup-overlap' || inputs.diagnose_pi_startup && 'pi-startup-diagnostic' || inputs.verify_pi_intel && 'pi-native-intel' || inputs.diagnose_ajv_pack && 'ajv-diagnostic' || inputs.verify_runner && 'runner-verification' || inputs.source_e2e_support_only && 'source-e2e-support' || inputs.source_root_tests_only && 'source-root-tests' || inputs.verify_source && 'verification' || inputs.verify_public_install && 'public-install' || inputs.build_eval_viewer && 'viewer' || 'image' }}${{ github.event_name == 'workflow_dispatch' && inputs.expected_source_sha && format('-{0}', inputs.expected_source_sha) || '' }} cancel-in-progress: true jobs: @@ -136,6 +140,7 @@ jobs: DIAGNOSE_PI_SNAPSHOT_STREAMING: ${{ inputs.diagnose_pi_snapshot_streaming }} DIAGNOSE_PI_SNAPSHOT_POOL: ${{ inputs.diagnose_pi_snapshot_pool }} DIAGNOSE_PI_STARTUP: ${{ inputs.diagnose_pi_startup }} + PI_STARTUP_OVERLAP: ${{ inputs.pi_startup_overlap }} DIAGNOSE_AJV: ${{ inputs.diagnose_ajv_pack }} OTHER_MODE: ${{ inputs.publish_eval_image || inputs.verify_source || inputs.verify_public_install || inputs.build_eval_viewer || inputs.verify_pi_intel || inputs.diagnose_pi_startup || inputs.diagnose_pi_snapshot_pool || inputs.diagnose_pi_snapshot_streaming || inputs.source_e2e_support_only }} run: | @@ -195,6 +200,9 @@ jobs: # Artifact storage and unrelated resource costs are not inferred here. test "$(gh api "repos/$REPOSITORY" --jq '.visibility')" = public fi + if [ "$PI_STARTUP_OVERLAP" = true ]; then + test "$DIAGNOSE_PI_STARTUP" = true + fi if [ "$DIAGNOSE_PI_STARTUP" = true ]; then test "$DIAGNOSE_PI_SNAPSHOT_STREAMING" != true test "$DIAGNOSE_PI_SNAPSHOT_POOL" != true @@ -301,7 +309,7 @@ jobs: manual_pi_startup_diagnostic: name: Retained f5 profile13 native Intel startup timing diagnostic (not qualification) - if: github.event_name == 'workflow_dispatch' && inputs.diagnose_pi_startup + if: github.event_name == 'workflow_dispatch' && inputs.diagnose_pi_startup && !inputs.pi_startup_overlap needs: authorize_manual runs-on: macos-15-intel timeout-minutes: 25 @@ -350,6 +358,57 @@ jobs: retention-days: 7 if-no-files-found: error + manual_pi_startup_overlap: + name: Retained f5 native Intel admission overlap prototype (not qualification) + if: github.event_name == 'workflow_dispatch' && inputs.diagnose_pi_startup && inputs.pi_startup_overlap + needs: authorize_manual + runs-on: macos-15-intel + timeout-minutes: 25 + permissions: + contents: read + actions: read + steps: + - name: Checkout trusted diagnostic helpers only + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + with: + ref: ${{ github.workflow_sha }} + path: trusted-ci + persist-credentials: false + - name: Download exact failed qualification artifacts + timeout-minutes: 5 + env: + GH_TOKEN: ${{ github.token }} + run: | + set -euo pipefail + gh api repos/paperclipai/paperclip/actions/artifacts/11218057612/zip \ + > "$RUNNER_TEMP/pi-startup-36984851998.zip" + printf '%s %s\n' 5159dcb57b380648679d441a73b87d50334dcca969adc95150e8429a71cbdfeb \ + "$RUNNER_TEMP/pi-startup-36984851998.zip" | shasum -a 256 --check + - name: Run one unpublished overlap startup with original assertions and deadlines + timeout-minutes: 18 + run: | + set -euo pipefail + python3 -B trusted-ci/scripts/ci/pi-intel/startup_overlap.py \ + --archive "$RUNNER_TEMP/pi-startup-36984851998.zip" \ + --output "$GITHUB_WORKSPACE/pi-startup-overlap-evidence" + - name: Admit complete diagnostic evidence within the storage bound + if: always() + id: diagnostic_evidence + timeout-minutes: 2 + run: | + python3 -B trusted-ci/scripts/ci/pi-intel/admit_diagnostic_evidence.py \ + --evidence "$GITHUB_WORKSPACE/pi-startup-overlap-evidence" \ + --github-output "$GITHUB_OUTPUT" + - name: Retain original and prototype identities, assertions and cleanup + if: always() && steps.diagnostic_evidence.outputs.admitted == 'true' + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + with: + name: pi-startup-overlap-${{ github.run_id }} + include-hidden-files: true + path: pi-startup-overlap-evidence/ + retention-days: 7 + if-no-files-found: error + manual_pi_snapshot_pool: name: Retained B9 native Intel snapshot pool ABBA (not qualification) if: github.event_name == 'workflow_dispatch' && inputs.diagnose_pi_snapshot_pool diff --git a/scripts/ci/pi-intel/startup-overlap-inputs.json b/scripts/ci/pi-intel/startup-overlap-inputs.json new file mode 100644 index 0000000000..7e525bc704 --- /dev/null +++ b/scripts/ci/pi-intel/startup-overlap-inputs.json @@ -0,0 +1,86 @@ +{ + "schema": "paperclip.native-intel-startup-overlap-input/v1", + "sourceRevision": "f5c5fde380f60937ef26cc5a92e1d6a043e9cddc", + "resolvedLockSha256": "38338a6867358440c5ab5993eaeb85fb501bc7df65d24acf52fbd63c880ee4ba", + "artifactRunId": "36984851998", + "artifactId": "11218057612", + "artifactWorkflowRevision": "94848f04150ed4f5de7762ff4687c633c7c9cc1a", + "artifactZipBytes": 699248654, + "artifactZipSha256": "5159dcb57b380648679d441a73b87d50334dcca969adc95150e8429a71cbdfeb", + "selectedFiles": { + "receipt.json": { + "bytes": 31957, + "sha256": "28a572c4278ddbf99219dc720f78debc93dc442114478abf39a561390a8c3a7e" + }, + "provider-pack.tar.gz": { + "bytes": 648246195, + "sha256": "cc4de9c130102fdb94f57556bac8efa225b2ee9035e72661d6b68a254799f8e9" + }, + "provider-pack.json": { + "bytes": 2743, + "sha256": "11f4dba65bb8d144898b5879271d72ff19920785c294ea32b22510c4442d2537" + }, + "pack-inventory.json": { + "bytes": 10353069, + "sha256": "8de75e0f0185cbe0d9dfafefa417632e185ed3421fed85469ba20792f7fa8f69" + }, + "paperclip-runnerd": { + "bytes": 32036944, + "sha256": "cc9dcfb006e78d5808f642152c24304a84d84b80dc33ea352ddbc5ad2e216713" + }, + "source.tar": { + "bytes": 141987840, + "sha256": "374600761ad9e0268f6e323bc9eb16aff800106d8baf886e39063ebc52d42e8a" + }, + "source-input-inventory.json": { + "bytes": 1035823, + "sha256": "849fc4f538e592c892c9e5b4eae9d37a606ffca301227d8649a5a6eff9c13edc" + }, + "resolved-pnpm-lock.yaml": { + "bytes": 607788, + "sha256": "38338a6867358440c5ab5993eaeb85fb501bc7df65d24acf52fbd63c880ee4ba" + } + }, + "originalSidecarSha256": "ce987993ffb92f449ef0432dee6cd7eb90ea19521ce3d7b51a185fed16ed8c47", + "originalPackDigest": "sha256:183e5a337dbf0edd9a3c210b2f539443996cf70ed35b77d281ae0e49d8eeb974", + "daemonSha256": "cc9dcfb006e78d5808f642152c24304a84d84b80dc33ea352ddbc5ad2e216713", + "nodeSha256": "7abcf39bd37ab251015337ff75304d7555f0d8e88c6e0fbf04bce8ce34636f49", + "testPath": "packages/paperclip-runner/test/pi-closed-startup.test.mjs", + "testSha256": "32bb057e1505082c0ed6b1d71cdd8cdb3271d920c2bea9cdc1ebddedf568c0c4", + "observerSha256": "1fcf353beb90722f90401a7792a5853bf0807d964a1065e3f55b76a63bc4b4cc", + "profileDigest": "sha256:fe1e6da01b2a9e4c691ca27cf689d2d6de846a93be6b23fc1e103c9addd7b177", + "closureDigest": "sha256:4728e5a4e7fc1ba602c3e219824fb84884b05a06cdd19dd3e521ee312e1b373a", + "model": "openrouter/deepseek/deepseek-v4-flash-0731", + "originalFailure": "Durable session.open command timed out at original30s; close drain barrier failed secondarily.61 SDK contracts passed; fresh Rust and full normal Pi13 pack verified; cleanup certain.", + "executionCount": 1, + "providerCalls": 0, + "timeoutChanges": false, + "archiveBytesMaximum": 268435456, + "retentionDays": 7, + "profileVersion": 13, + "phaseLimit": "No inner-phase instrumentation. Compare original assertion result and test durations only; one run is not statistical performance proof.", + "prototypePatchSha256": "34d98771a8ed53576ca7875e0cff6fc5b582f6f8f1a95282b99c3a895bb5621b", + "prototypeSidecarSha256": "b28efa0a99d968dd9304487fdec6890d01186ec9e2c0fc5779508c0d7bd8a9c5", + "prototypeSource": { + "baseRevision": "f5c5fde380f60937ef26cc5a92e1d6a043e9cddc", + "reviewedPrototypeBaseRevision": "eac50643213d0902a93a5384bae2f1d6c065c9f2", + "changes": [ + { + "path": "packages/paperclip-runner/src/drivers/acpx/pi-installation.ts", + "beforeSha256": "09a13bdad937b68bf129458d4c00c4ae174c93fad3ae447db3fad922f66c49e5", + "afterSha256": "e9f35098a604637a78431a3717c7afa40e666f7acc673f05296e08e8c4255203" + }, + { + "path": "packages/paperclip-runner/src/drivers/acpx/pi-verified-runtime.ts", + "beforeSha256": "dfb5f6604da0abc307c4bb514e3dd47354f4b867be28fdeb64273c3c055b68c1", + "afterSha256": "2120d9dccaf639ad43266e0d8a2cd33c82f0da4c7ee4646ecf26eba7b7c06d18" + } + ], + "compileReceiptSha256": "98a7acb31f1401a0118707736babd5d7bec9877d106b8e4fe94050517405c8c8", + "reviewSha256": "2da03536aae1ff8daec593379184da3941be60fff6f49e08da5071a6e86f2135", + "baseReproducedExactly": true, + "buildInputsSha256": "20ddd97c8c806a76398688f56a6fccc5f272a475e9ebebbf14c2244d0de079e4", + "dependencyTopologySha256": "9de0a7067971b2280b7607656423a5cfc7b238c97424012f320720d41c1b67aa" + }, + "prototypePackDigest": "sha256:6110072039d5b683dde8b19333c16f16255aed51a37cad7f53ed7de340f94103" +} diff --git a/scripts/ci/pi-intel/startup-overlap-patch.json b/scripts/ci/pi-intel/startup-overlap-patch.json new file mode 100644 index 0000000000..76376223ad --- /dev/null +++ b/scripts/ci/pi-intel/startup-overlap-patch.json @@ -0,0 +1,85 @@ +{ + "schema": "paperclip.exact-sidecar-overlap-patch/v1", + "originalSha256": "ce987993ffb92f449ef0432dee6cd7eb90ea19521ce3d7b51a185fed16ed8c47", + "candidateSha256": "b28efa0a99d968dd9304487fdec6890d01186ec9e2c0fc5779508c0d7bd8a9c5", + "sourceChanges": [ + { + "path": "packages/paperclip-runner/src/drivers/acpx/pi-installation.ts", + "beforeSha256": "09a13bdad937b68bf129458d4c00c4ae174c93fad3ae447db3fad922f66c49e5", + "afterSha256": "e9f35098a604637a78431a3717c7afa40e666f7acc673f05296e08e8c4255203" + }, + { + "path": "packages/paperclip-runner/src/drivers/acpx/pi-verified-runtime.ts", + "beforeSha256": "dfb5f6604da0abc307c4bb514e3dd47354f4b867be28fdeb64273c3c055b68c1", + "afterSha256": "2120d9dccaf639ad43266e0d8a2cd33c82f0da4c7ee4646ecf26eba7b7c06d18" + } + ], + "operations": [ + { + "oldStartLine": 73015, + "oldLines": [ + "async function verifyPiRuntimeLayoutForNativeSnapshot(root, manifest, nativeManifest, expectedClosureSha256) {\n" + ], + "newLines": [ + "async function preparePiRuntimeLayoutForNativeSnapshot(root, manifest, nativeManifest, expectedClosureSha256) {\n" + ] + }, + { + "oldStartLine": 73021, + "oldLines": [ + " const { files } = await discoverPiRuntimeFiles(root);\n", + " const layout = (values) => values.map(({ path: path3, kind }) => ({ path: path3, kind })).sort((a, b) => a.path.localeCompare(b.path, \"en\"));\n", + " if (JSON.stringify(layout(files)) !== JSON.stringify(layout(sorted))) throw new Error(\"Pi runtime package graph differs from its qualified manifest\");\n", + " const { manifestDigest } = await bindPiRuntimeManifestPaths(root, manifest, sorted, unique2);\n", + " return { manifestDigest };\n" + ], + "newLines": [ + " const declaration = { ...manifest, files: sorted };\n", + " const manifestDigest = hash3(JSON.stringify(declaration));\n", + " return Object.freeze({\n", + " manifestDigest,\n", + " async verifyLayout() {\n", + " const { files } = await discoverPiRuntimeFiles(root);\n", + " const layout = (values) => values.map(({ path: path3, kind }) => ({ path: path3, kind })).sort((a, b) => a.path.localeCompare(b.path, \"en\"));\n", + " if (JSON.stringify(layout(files)) !== JSON.stringify(layout(sorted))) throw new Error(\"Pi runtime package graph differs from its qualified manifest\");\n", + " await bindPiRuntimeManifestPaths(root, declaration, sorted, unique2);\n", + " }\n", + " });\n" + ] + }, + { + "oldStartLine": 73182, + "oldLines": [ + " const layout = await verifyPiRuntimeLayoutForNativeSnapshot(runtimeRoot, manifest, { entries }, expectedClosure);\n" + ], + "newLines": [ + " const layout = await preparePiRuntimeLayoutForNativeSnapshot(runtimeRoot, manifest, { entries }, expectedClosure);\n" + ] + }, + { + "oldStartLine": 73191, + "oldLines": [ + " return native.openCommand();\n" + ], + "newLines": [ + " const [checkedLayout, command] = await Promise.allSettled([\n", + " layout.verifyLayout(),\n", + " native.openCommand()\n", + " ]);\n", + " if (checkedLayout.status === \"rejected\") {\n", + " if (command.status === \"rejected\") throw new AggregateError([checkedLayout.reason, command.reason], \"Pi layout and snapshot admission failed\");\n", + " if (command.status === \"fulfilled\") {\n", + " try {\n", + " await command.value.close();\n", + " } catch (cleanupError) {\n", + " throw new AggregateError([checkedLayout.reason, cleanupError], \"Pi layout admission and unpublished command cleanup failed\");\n", + " }\n", + " }\n", + " throw checkedLayout.reason;\n", + " }\n", + " if (command.status === \"rejected\") throw command.reason;\n", + " return command.value;\n" + ] + } + ] +} diff --git a/scripts/ci/pi-intel/startup_overlap.py b/scripts/ci/pi-intel/startup_overlap.py new file mode 100644 index 0000000000..7c4ec1ea30 --- /dev/null +++ b/scripts/ci/pi-intel/startup_overlap.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python3 +"""One original native Intel startup with a separately bound overlap prototype; never qualification.""" +import argparse,copy,datetime,difflib,hashlib,json,os,platform,shutil,signal,stat,subprocess,tarfile,tempfile,time +from pathlib import Path +from source_guard import require,sha +from native_daemon_reuse import extract_selected +from retain_pack import verify_archive +from closed_inventory import closed_tree +from startup_overlap_patch import apply_overlap +from owned_processes import OwnedProcesses,atomic_json +from diagnostic_lifecycle import DiagnosticChild,DiagnosticInspection +HERE=Path(__file__).resolve().parent +PIN=json.loads((HERE/'startup-overlap-inputs.json').read_text()) + +from startup_diagnostic import restore_pack,validate_pack_delta,post_run_integrity,finalize_diagnostic + +def execute(args): + out=args.output.resolve();out.mkdir(mode=0o700,parents=True,exist_ok=False) + scratch=Path(tempfile.mkdtemp(prefix='pc-intel-diagnostic-',dir='/private/tmp'));scratch.chmod(0o700) + scratch_id=(scratch.stat().st_dev,scratch.stat().st_ino,scratch.stat().st_uid) + proof={'schema':'paperclip.native-intel-startup-overlap-experiment/v1','status':'preparing','sourceRevision':PIN['sourceRevision'],'runId':os.environ['GITHUB_RUN_ID'],'trustedWorkflowRevision':os.environ['GITHUB_WORKFLOW_SHA'],'originalQualificationRunId':PIN['artifactRunId'],'startedAt':datetime.datetime.now(datetime.timezone.utc).isoformat(),'isQualification':False,'providerCalls':0,'credentialsRead':False,'runtimePromptsSubmitted':0,'nativeRecompiled':False,'dependencyInstallExecuted':False,'testSourceUnmodified':True,'deadlineChanged':False,'helpers':{p.name:sha(p) for p in HERE.iterdir() if p.is_file()},'commands':[],'cleanupUncertain':False,'scratchRemoved':False,'hardwareBareMetalClaim':False,'physicalColdDiskClaim':False,'cacheNote':'Artifact integrity verification necessarily reads payload before testing; no startup warmup is performed.','prototypeSource':PIN['prototypeSource'],'timingInstrumentation':False,'originalSourceRole':'frozen base provenance; sidecar is explicitly a two-module unpublished derivative'} + def save():atomic_json(out/'receipt.json',proof) + active=None;pack=None;after=None;daemon=None;original=None;test=None + def cancelled(sig,_): + if active is not None:active.cancel('signal '+str(sig)) + else:raise InterruptedError('Diagnostic cancelled') + signal.signal(signal.SIGTERM,cancelled);signal.signal(signal.SIGINT,cancelled) + env={'PATH':'/usr/bin:/bin:/usr/sbin:/sbin','HOME':str(scratch/'home'),'LANG':'en_US.UTF-8','TMPDIR':str(scratch)};Path(env['HOME']).mkdir(mode=0o700) + def command(label,argv,timeout=30): + row={'label':label,'argv':list(map(str,argv)),'deadlineSeconds':timeout};proof['commands'].append(row);save() + with (out/(label+'.log')).open('xb') as log:r=subprocess.run(row['argv'],env=env,cwd=scratch,stdout=log,stderr=log,timeout=timeout) + row.update(exitCode=r.returncode,logSha256=sha(out/(label+'.log')));save();require(r.returncode==0,'Diagnostic preparation failed: '+label) + return (out/(label+'.log')).read_text() + save() + try: + require(platform.system()=='Darwin' and platform.machine()=='x86_64','Native Intel required') + for flag in ['sysctl.proc_translated','hw.optional.arm64']: + r=subprocess.run(['/usr/sbin/sysctl','-in',flag],capture_output=True,text=True,env=env,timeout=10) + require(r.stdout.strip() in ('','0'),'Rosetta/ARM rejected');proof[flag]={'value':r.stdout.strip(),'exitCode':r.returncode} + hardware=command('hardware',['/usr/sbin/sysctl','hw.machine','machdep.cpu.vendor','machdep.cpu.brand_string']) + require('GenuineIntel' in hardware and 'x86_64' in hardware,'Intel hardware evidence missing') + original=extract_selected(args.archive,scratch/'original-artifact',PIN) + references=out/'original-reference';references.mkdir(mode=0o700) + for name in ['receipt.json','provider-pack.json','pack-inventory.json','source-input-inventory.json','resolved-pnpm-lock.yaml']:shutil.copy2(original/name,references/name) + atomic_json(out/'original-input-pins.json',PIN) + receipt=json.loads((original/'receipt.json').read_text());require(receipt['sourceRevision']==PIN['sourceRevision'] and receipt['runId']==PIN['artifactRunId'] and receipt['trustedWorkflowRevision']==PIN['artifactWorkflowRevision'],'Original artifact provenance mismatch') + require(receipt['cleanupUncertain'] is False and receipt['status']=='failed_no_retry','Unexpected original qualification disposition') + proof['originalFailure']={'status':receipt['status'],'testFailures':receipt.get('testFailures'),'packArchiveSha256':sha(original/'provider-pack.tar.gz'),'daemonSha256':sha(original/'paperclip-runnerd')} + require(sha(original/'paperclip-runnerd')==PIN['daemonSha256'] and sha(original/'resolved-pnpm-lock.yaml')==PIN['resolvedLockSha256'],'Original daemon/lock mismatch') + inventory=json.loads((original/'pack-inventory.json').read_text());pack=restore_pack(original/'provider-pack.tar.gz',scratch/'unpacked',inventory) + node=pack/'node_modules/node/bin/node';daemon=scratch/'paperclip-runnerd';shutil.copyfile(original/'paperclip-runnerd',daemon);daemon.chmod(0o755) + require(sha(node)==PIN['nodeSha256'] and sha(daemon)==PIN['daemonSha256'],'Native executable changed') + require(json.loads(command('node-identity',[node,'-p','JSON.stringify([process.platform,process.arch,process.version])']))==['darwin','x64','v24.21.0'],'Node platform mismatch') + command('daemon-signature',['/usr/bin/codesign','--verify','--strict',daemon]);require('Mach-O 64-bit executable x86_64' in command('daemon-architecture',['/usr/bin/file',daemon]),'Daemon architecture mismatch') + proof['originalPackVerification']=json.loads(command('original-pack-verify',[node,HERE/('verify-pack-profile13.mjs' if PIN.get('profileVersion')==13 else 'verify-pack.mjs'),pack,PIN['sourceRevision'],'darwin','x64'],180)) + require(proof['originalPackVerification']['manifestDigest']==PIN['originalPackDigest'],'Original pack identity mismatch') + before_manifest=json.loads((pack/'provider-pack.json').read_text()) + patch_path=HERE/'startup-overlap-patch.json' + require(sha(patch_path)==PIN['prototypePatchSha256'],'Prototype patch identity changed') + patch=json.loads(patch_path.read_text()) + require(patch['originalSha256']==PIN['originalSidecarSha256'] and patch['candidateSha256']==PIN['prototypeSidecarSha256'],'Prototype source/output binding mismatch') + require(patch['sourceChanges']==PIN['prototypeSource']['changes'],'Unexpected prototype source delta') + sidecar=pack/'dist/cli/acpx-runtime-sidecar.cjs';original_sidecar=sidecar.read_bytes();patched=apply_overlap(original_sidecar,patch) + sidecar.write_bytes(patched);atomic_json(out/'sidecar-patch.json',patch) + (out/'sidecar.diff').write_text(''.join(difflib.unified_diff(original_sidecar.decode().splitlines(True),patched.decode().splitlines(True),fromfile='original-f5-profile13-sidecar',tofile='unpublished-overlap-sidecar'))) + command('diagnostic-sidecar-syntax',[node,'--check',sidecar]) + proof['diagnosticPackVerification']=json.loads(command('diagnostic-pack-rebind',[node,HERE/'rebind-diagnostic-pack.mjs',pack,PIN['originalSidecarSha256'],PIN['sourceRevision'],*(['profile13'] if PIN.get('profileVersion')==13 else [])],180)) + require(proof['diagnosticPackVerification']['manifestDigest']==PIN['prototypePackDigest'],'Prototype pack differs from independently derived inventory identity') + after_manifest=json.loads((pack/'provider-pack.json').read_text());expected=copy.deepcopy(before_manifest) + expected['payload']['artifacts']['acpxSidecar']['sha256']=after_manifest['payload']['artifacts']['acpxSidecar']['sha256'] + for key in ['distDigest','bridgeDigest']:expected['payload'][key]=after_manifest['payload'][key] + expected['digest']=after_manifest['digest'];require(expected==after_manifest,'Diagnostic changed other manifest authority') + proof['closureBinding']={'before':before_manifest['payload']['candidateProviders']['pi'],'after':after_manifest['payload']['candidateProviders']['pi'],'daemonSha256':sha(daemon),'nativeBytesChanged':False} + after=closed_tree(pack);proof['allowedPackDelta']=validate_pack_delta(inventory,after);atomic_json(out/'diagnostic-pack-inventory.json',after) + shutil.copy2(pack/'provider-pack.json',out/'diagnostic-provider-pack.json') + shutil.copy2(sidecar,out/'diagnostic-acpx-runtime-sidecar.cjs') + proof['diagnosticReconstruction']={'originalArtifactId':PIN['artifactId'],'originalZipSha256':PIN['artifactZipSha256'],'originalPackTarSha256':PIN['selectedFiles']['provider-pack.tar.gz']['sha256'],'replaceOnly':['dist/cli/acpx-runtime-sidecar.cjs','provider-pack.json'],'sidecarSha256':sha(out/'diagnostic-acpx-runtime-sidecar.cjs'),'manifestSha256':sha(out/'diagnostic-provider-pack.json'),'inventorySha256':sha(out/'diagnostic-pack-inventory.json'),'fullOriginalPackDuplicated':False,'diagnosticPackArchiveDuplicated':False} + test=out/'pi-closed-startup.test.mjs' + with tarfile.open(original/'source.tar','r:') as source: + member=source.getmember(PIN['testPath']);require(member.isfile(),'Original test is not regular');test.write_bytes(source.extractfile(member).read()) + require(sha(test)==PIN['testSha256'] and sha(HERE/'retain-test-state.mjs')==PIN['observerSha256'],'Test/observer changed');test.chmod(0o444);shutil.copy2(HERE/'retain-test-state.mjs',out/'retain-test-state.mjs') + retained=out/'retained-test-state';retained.mkdir(mode=0o700) + tenv={**env,'PAPERCLIP_TEST_PI_STARTUP_PACKAGE_ROOT':str(pack),'PAPERCLIP_TEST_PI_STARTUP_RUNNER_BINARY':str(daemon),'PI_INTEL_OWNED_TMP':str(scratch),'PI_INTEL_RETAINED_STATE':str(retained)} + owner=OwnedProcesses(out/'closed-startup-processes.json',scratch,pack,sidecar);active=DiagnosticChild(owner) + inspection=DiagnosticInspection(owner,active);owner.table=inspection.table;owner.argv=inspection.argv + proof['processInspection']={'activeCadenceSeconds':0.5,'maximumCallSeconds':5,'defaultSharedCallSeconds':2,'deadlineCap':'remaining active70s or existing cleanup100s','activeFailuresFatal':True,'activeInspectionRetries':0} + row={'label':'original-closed-startup-test-with-unpublished-overlap-sidecar','argv':[str(node),'--import',str(HERE/'retain-test-state.mjs'),'--test',str(test)],'outerDeadlineSeconds':70,'originalTestTimeoutMs':60000,'originalAdmissionLimitMs':30000,'startedAt':datetime.datetime.now(datetime.timezone.utc).isoformat(),'startedMonotonicNs':str(time.monotonic_ns())};proof['commands'].append(row);proof['status']='diagnostic_running';save() + try: + with (out/'closed-startup.log').open('xb') as log: + result=active.execute(lambda:subprocess.Popen(row['argv'],env=tenv,cwd=pack,stdout=log,stderr=log,start_new_session=True),70) + finally: + row.update(finishedAt=datetime.datetime.now(datetime.timezone.utc).isoformat(),finishedMonotonicNs=str(time.monotonic_ns())) + row['supervisorElapsedMs']=round((int(row['finishedMonotonicNs'])-int(row['startedMonotonicNs']))/1e6,3) + proof['clockScope']='Only original test report durations and supervisor monotonic duration are recorded; no cross-process clock subtraction or inner-phase attribution.' + save() + reports=list(retained.rglob('report.json')) + if len(reports)==1: + report=json.loads(reports[0].read_text());proof['originalTestReport']={k:report.get(k) for k in ['error','settledMs','durationMs']} + row.update(exitCode=result,logSha256=sha(out/'closed-startup.log'));proof['originalAssertionExitCode']=result;proof['shutdown']=owner.stop_result + proof.update(status='experiment_complete_original_test_passed' if result==0 else 'experiment_complete_original_test_failed',isQualification=False,finishedAt=datetime.datetime.now(datetime.timezone.utc).isoformat());save() + return result + except BaseException as error: + proof.update(status='diagnostic_failed',errorType=type(error).__name__,error=str(error),finishedAt=datetime.datetime.now(datetime.timezone.utc).isoformat()) + raise + finally: + def post_check(): + if after is None or test is None:return {'complete':False,'passed':False,'reason':'diagnostic pack/test preparation not completed'} + return post_run_integrity(pack,after,daemon,original,test,PIN) + def retain(): + if (out/'retained-test-state').is_dir():proof['retainedTestStateInventory']=closed_tree(out/'retained-test-state') + def remove(): + st=scratch.lstat();require((st.st_dev,st.st_ino,st.st_uid)==scratch_id and stat.S_ISDIR(st.st_mode),'Scratch identity changed') + shutil.rmtree(scratch) + try:finalize_diagnostic(proof,active,post_check,retain,remove) + finally:save() + +if __name__=='__main__': + p=argparse.ArgumentParser(description=__doc__);p.add_argument('--archive',type=Path,required=True);p.add_argument('--output',type=Path,required=True) + raise SystemExit(execute(p.parse_args())) diff --git a/scripts/ci/pi-intel/startup_overlap_patch.py b/scripts/ci/pi-intel/startup_overlap_patch.py new file mode 100644 index 0000000000..29ab35cc0e --- /dev/null +++ b/scripts/ci/pi-intel/startup_overlap_patch.py @@ -0,0 +1,46 @@ +"""Apply an exact compiled two-module derivative, without executing bundle contents.""" +import hashlib + + +def apply_overlap(original, patch): + def require(value, message): + if not value: + raise ValueError(message) + + require(isinstance(original, bytes) and len(original) <= 8 * 1024 * 1024, + 'Original sidecar bound') + require(patch.get('schema') == 'paperclip.exact-sidecar-overlap-patch/v1', + 'Unexpected patch schema') + require(hashlib.sha256(original).hexdigest() == patch['originalSha256'], + 'Original sidecar identity mismatch') + lines = original.decode('utf-8').splitlines(keepends=True) + operations = patch['operations'] + require(isinstance(operations, list) and 0 < len(operations) <= 64, + 'Patch operation bound') + result = [] + cursor = 0 + previous = -1 + added_bytes = 0 + for operation in operations: + require(set(operation) == {'oldStartLine', 'oldLines', 'newLines'}, + 'Unexpected patch fields') + start, old, new = (operation[key] for key in + ['oldStartLine', 'oldLines', 'newLines']) + require(type(start) is int and previous < start and cursor <= start <= len(lines), + 'Overlapping or unordered patch operation') + require(isinstance(old, list) and isinstance(new, list) + and all(isinstance(line, str) for line in old + new), + 'Malformed patch lines') + require(lines[start:start + len(old)] == old, 'Original patch context mismatch') + require(start + len(old) <= len(lines), 'Patch past original end') + added_bytes += sum(len(line.encode('utf-8')) for line in new) + require(added_bytes <= 256 * 1024, 'Patch addition bound') + result.extend(lines[cursor:start]) + result.extend(new) + cursor, previous = start + len(old), start + result.extend(lines[cursor:]) + candidate = ''.join(result).encode('utf-8') + require(len(candidate) <= 8 * 1024 * 1024, 'Candidate sidecar bound') + require(hashlib.sha256(candidate).hexdigest() == patch['candidateSha256'], + 'Compiled candidate identity mismatch') + return candidate diff --git a/scripts/ci/pi-intel/test_startup_overlap.py b/scripts/ci/pi-intel/test_startup_overlap.py new file mode 100644 index 0000000000..a63abb53f6 --- /dev/null +++ b/scripts/ci/pi-intel/test_startup_overlap.py @@ -0,0 +1,75 @@ +import copy +import hashlib +import json +import os +import unittest +from pathlib import Path +from startup_overlap_patch import apply_overlap + + +class OverlapPatchTests(unittest.TestCase): + def setUp(self): + self.original = b'first\nold\nlast\n' + self.candidate = b'first\nnew\nextra\nlast\n' + self.patch = { + 'schema': 'paperclip.exact-sidecar-overlap-patch/v1', + 'originalSha256': hashlib.sha256(self.original).hexdigest(), + 'candidateSha256': hashlib.sha256(self.candidate).hexdigest(), + 'operations': [{'oldStartLine': 1, 'oldLines': ['old\n'], + 'newLines': ['new\n', 'extra\n']}], + } + + def test_exact_compiled_bytes(self): + self.assertEqual(apply_overlap(self.original, self.patch), self.candidate) + + def test_original_mutation(self): + with self.assertRaisesRegex(ValueError, 'Original sidecar identity'): + apply_overlap(self.original + b'changed', self.patch) + + def test_wrong_context(self): + self.patch['operations'][0]['oldLines'] = ['foreign\n'] + with self.assertRaisesRegex(ValueError, 'context mismatch'): + apply_overlap(self.original, self.patch) + + def test_changed_candidate(self): + self.patch['operations'][0]['newLines'] = ['wrong\n'] + with self.assertRaisesRegex(ValueError, 'Compiled candidate identity'): + apply_overlap(self.original, self.patch) + + def test_duplicate_or_overlapping_operations(self): + self.patch['operations'].append(copy.deepcopy(self.patch['operations'][0])) + with self.assertRaisesRegex(ValueError, 'Overlapping or unordered'): + apply_overlap(self.original, self.patch) + + def test_unbounded_patch(self): + self.patch['operations'][0]['newLines'] = ['x' * (256 * 1024 + 1)] + with self.assertRaisesRegex(ValueError, 'addition bound'): + apply_overlap(self.original, self.patch) + + +class RetainedCandidateTests(unittest.TestCase): + def test_exact_compiled_candidate_and_unchanged_base_contract(self): + here = Path(__file__).parent + inputs = json.loads((here / 'startup-overlap-inputs.json').read_text()) + patch_bytes = (here / 'startup-overlap-patch.json').read_bytes() + self.assertEqual(hashlib.sha256(patch_bytes).hexdigest(), inputs['prototypePatchSha256']) + patch = json.loads(patch_bytes) + original = Path(os.environ['PI_DIAGNOSTIC_ORIGINAL_SIDECAR']).read_bytes() + candidate = apply_overlap(original, patch) + self.assertEqual(hashlib.sha256(candidate).hexdigest(), inputs['prototypeSidecarSha256']) + self.assertEqual(patch['sourceChanges'], inputs['prototypeSource']['changes']) + self.assertEqual({row['path'] for row in patch['sourceChanges']}, { + 'packages/paperclip-runner/src/drivers/acpx/pi-installation.ts', + 'packages/paperclip-runner/src/drivers/acpx/pi-verified-runtime.ts', + }) + self.assertTrue(inputs['prototypeSource']['baseReproducedExactly']) + base = json.loads((here / 'startup-diagnostic-inputs.json').read_text()) + for name in ['sourceRevision', 'selectedFiles', 'daemonSha256', 'testSha256', + 'originalSidecarSha256', 'originalPackDigest', 'nodeSha256', + 'executionCount', 'providerCalls', 'timeoutChanges', + 'archiveBytesMaximum', 'retentionDays']: + self.assertEqual(inputs[name], base[name], name) + + +if __name__ == '__main__': + unittest.main()