mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-08 00:54:38 +02:00
ci: time retained Pi13 Intel startup phases
Co-authored-by: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
94848f0415
commit
fed3c8b9ba
6 files changed
+72
-48
No files matched your search
@@ -205,7 +205,7 @@ jobs:
|
||||
test "$SOURCE_E2E_SUPPORT_ONLY" != true
|
||||
test "$DIAGNOSE_AJV" != true
|
||||
test "$IMAGE_MODE" != true
|
||||
test "$EXPECTED_SOURCE_SHA" = b9e5d6ecdb05ab7244c90976e07c950f8d09b15b
|
||||
test "$EXPECTED_SOURCE_SHA" = f5c5fde380f60937ef26cc5a92e1d6a043e9cddc
|
||||
test "$EXPECTED_LOCK_SHA256" = 38338a6867358440c5ab5993eaeb85fb501bc7df65d24acf52fbd63c880ee4ba
|
||||
test "$(gh api "repos/$REPOSITORY" --jq '.visibility')" = public
|
||||
fi
|
||||
@@ -300,7 +300,7 @@ jobs:
|
||||
if-no-files-found: error
|
||||
|
||||
manual_pi_startup_diagnostic:
|
||||
name: Retained B9 profile12 native Intel startup timing diagnostic (not qualification)
|
||||
name: Retained f5 profile13 native Intel startup timing diagnostic (not qualification)
|
||||
if: github.event_name == 'workflow_dispatch' && inputs.diagnose_pi_startup
|
||||
needs: authorize_manual
|
||||
runs-on: macos-15-intel
|
||||
@@ -321,16 +321,16 @@ jobs:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
gh api repos/paperclipai/paperclip/actions/artifacts/11208570718/zip \
|
||||
> "$RUNNER_TEMP/pi-startup-36959948724.zip"
|
||||
printf '%s %s\n' b82cf6c843006781e2e6d5f0a06e0ff39497ffc457b94a511f8bdda66628aa43 \
|
||||
"$RUNNER_TEMP/pi-startup-36959948724.zip" | shasum -a 256 --check
|
||||
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 instrumented startup with original assertions and deadlines
|
||||
timeout-minutes: 18
|
||||
run: |
|
||||
set -euo pipefail
|
||||
python3 -B trusted-ci/scripts/ci/pi-intel/startup_diagnostic.py \
|
||||
--archive "$RUNNER_TEMP/pi-startup-36959948724.zip" \
|
||||
--archive "$RUNNER_TEMP/pi-startup-36984851998.zip" \
|
||||
--output "$GITHUB_WORKSPACE/pi-startup-diagnostic-evidence"
|
||||
- name: Admit complete diagnostic evidence within the storage bound
|
||||
if: always()
|
||||
|
||||
@@ -3,7 +3,10 @@ import {readFileSync,writeFileSync} from 'node:fs';
|
||||
import {createHash} from 'node:crypto';
|
||||
import {join} from 'node:path';
|
||||
import {canonicalJson,sha256Tree,sha256File,requireTrue,verifyPack} from './verify-pack.mjs';
|
||||
const [pack,originalSidecar,source] = process.argv.slice(2);
|
||||
import {verifyProfile13Selection} from './verify-pack-profile13.mjs';
|
||||
const [pack,originalSidecar,source,profileMode] = process.argv.slice(2);
|
||||
requireTrue(profileMode === undefined || profileMode === 'profile13', 'Unexpected diagnostic profile mode');
|
||||
requireTrue(process.argv.length === (profileMode ? 6 : 5), 'Unexpected diagnostic arguments');
|
||||
const file=join(pack,'provider-pack.json'); const manifest=JSON.parse(readFileSync(file));
|
||||
requireTrue(manifest.payload.runnerSourceRevision===source,'Original source mismatch');
|
||||
requireTrue(manifest.payload.artifacts.acpxSidecar.path==='dist/cli/acpx-runtime-sidecar.cjs','Sidecar path mismatch');
|
||||
@@ -14,4 +17,4 @@ p.distDigest=sha256Tree(join(pack,'dist'));
|
||||
p.bridgeDigest='sha256:'+createHash('sha256').update(p.artifacts.opencodeProxy.sha256).update('\n').update(p.artifacts.acpxSidecar.sha256).update('\n').update(p.distDigest).digest('hex');
|
||||
manifest.digest='sha256:'+createHash('sha256').update(canonicalJson(p)).digest('hex');
|
||||
writeFileSync(file,JSON.stringify(manifest,null,2)+'\n');
|
||||
console.log(JSON.stringify(verifyPack(pack,source,'darwin','x64')));
|
||||
console.log(JSON.stringify(verifyPack(pack,source,'darwin','x64',profileMode === 'profile13' ? verifyProfile13Selection : undefined)));
|
||||
@@ -1,60 +1,62 @@
|
||||
{
|
||||
"schema": "paperclip.native-intel-startup-diagnostic-input/v1",
|
||||
"sourceRevision": "b9e5d6ecdb05ab7244c90976e07c950f8d09b15b",
|
||||
"sourceRevision": "f5c5fde380f60937ef26cc5a92e1d6a043e9cddc",
|
||||
"resolvedLockSha256": "38338a6867358440c5ab5993eaeb85fb501bc7df65d24acf52fbd63c880ee4ba",
|
||||
"artifactRunId": "36959948724",
|
||||
"artifactId": "11208570718",
|
||||
"artifactWorkflowRevision": "9541eb18789bac35242eeea3e569b77fa90d1818",
|
||||
"artifactZipBytes": 1076365959,
|
||||
"artifactZipSha256": "b82cf6c843006781e2e6d5f0a06e0ff39497ffc457b94a511f8bdda66628aa43",
|
||||
"artifactRunId": "36984851998",
|
||||
"artifactId": "11218057612",
|
||||
"artifactWorkflowRevision": "94848f04150ed4f5de7762ff4687c633c7c9cc1a",
|
||||
"artifactZipBytes": 699248654,
|
||||
"artifactZipSha256": "5159dcb57b380648679d441a73b87d50334dcca969adc95150e8429a71cbdfeb",
|
||||
"selectedFiles": {
|
||||
"receipt.json": {
|
||||
"bytes": 32763,
|
||||
"sha256": "47ef1f494c59c1249ac42f08308a2fb83edcb0759890960059cc367ebdf12bf0"
|
||||
"bytes": 31957,
|
||||
"sha256": "28a572c4278ddbf99219dc720f78debc93dc442114478abf39a561390a8c3a7e"
|
||||
},
|
||||
"provider-pack.tar.gz": {
|
||||
"bytes": 1029214229,
|
||||
"sha256": "5a550004ca982c49a2d86b3196676f3ce1877b6655ec730d1971b4cec2ba547d"
|
||||
"bytes": 648246195,
|
||||
"sha256": "cc4de9c130102fdb94f57556bac8efa225b2ee9035e72661d6b68a254799f8e9"
|
||||
},
|
||||
"provider-pack.json": {
|
||||
"bytes": 3629,
|
||||
"sha256": "db5b1d7d825a0533a6506755c6209ccc4d45776c3abbf6c87ff845d1d47e99b2"
|
||||
"bytes": 2743,
|
||||
"sha256": "11f4dba65bb8d144898b5879271d72ff19920785c294ea32b22510c4442d2537"
|
||||
},
|
||||
"pack-inventory.json": {
|
||||
"bytes": 10633748,
|
||||
"sha256": "172f0f4f2319f3716cca656cdeafd03b4f0db652def53101dfbf148850a20eaa"
|
||||
"bytes": 10353069,
|
||||
"sha256": "8de75e0f0185cbe0d9dfafefa417632e185ed3421fed85469ba20792f7fa8f69"
|
||||
},
|
||||
"paperclip-runnerd": {
|
||||
"bytes": 32035568,
|
||||
"sha256": "29d5b0fc2ae2a552b89a107e3777e2c8ee356ebdbb13a14ceab8865e1cea1d45"
|
||||
"bytes": 32036944,
|
||||
"sha256": "cc9dcfb006e78d5808f642152c24304a84d84b80dc33ea352ddbc5ad2e216713"
|
||||
},
|
||||
"source.tar": {
|
||||
"bytes": 141742080,
|
||||
"sha256": "b32d8e32639e6527804fe11bfa1aaefcefa87fca31e9155499e6b9a28f69dbd4"
|
||||
"bytes": 141987840,
|
||||
"sha256": "374600761ad9e0268f6e323bc9eb16aff800106d8baf886e39063ebc52d42e8a"
|
||||
},
|
||||
"source-input-inventory.json": {
|
||||
"bytes": 1033702,
|
||||
"sha256": "7c160bb1fc4d049378004d014e398d42dabf12e8a73ec9cdda7679113aaa6949"
|
||||
"bytes": 1035823,
|
||||
"sha256": "849fc4f538e592c892c9e5b4eae9d37a606ffca301227d8649a5a6eff9c13edc"
|
||||
},
|
||||
"resolved-pnpm-lock.yaml": {
|
||||
"bytes": 607788,
|
||||
"sha256": "38338a6867358440c5ab5993eaeb85fb501bc7df65d24acf52fbd63c880ee4ba"
|
||||
}
|
||||
},
|
||||
"originalSidecarSha256": "7462825f4b82bce8e2a69425eafe4ca8b2c8812df345269c82fb75aa21f3043c",
|
||||
"originalPackDigest": "sha256:9cf4f88d9fcf63746f7716f773cb8d062544c19e0a78e111e60f659a3596b13f",
|
||||
"daemonSha256": "29d5b0fc2ae2a552b89a107e3777e2c8ee356ebdbb13a14ceab8865e1cea1d45",
|
||||
"originalSidecarSha256": "ce987993ffb92f449ef0432dee6cd7eb90ea19521ce3d7b51a185fed16ed8c47",
|
||||
"originalPackDigest": "sha256:183e5a337dbf0edd9a3c210b2f539443996cf70ed35b77d281ae0e49d8eeb974",
|
||||
"daemonSha256": "cc9dcfb006e78d5808f642152c24304a84d84b80dc33ea352ddbc5ad2e216713",
|
||||
"nodeSha256": "7abcf39bd37ab251015337ff75304d7555f0d8e88c6e0fbf04bce8ce34636f49",
|
||||
"testPath": "packages/paperclip-runner/test/pi-closed-startup.test.mjs",
|
||||
"testSha256": "8967cf9c8cd130b68bf9d64abef8cb8d352af00646e2288b341d8c6ae758b47a",
|
||||
"testSha256": "32bb057e1505082c0ed6b1d71cdd8cdb3271d920c2bea9cdc1ebddedf568c0c4",
|
||||
"observerSha256": "1fcf353beb90722f90401a7792a5853bf0807d964a1065e3f55b76a63bc4b4cc",
|
||||
"profileDigest": "sha256:47306e6d2a9b59e8f9189f725ebb7a0a7f91826044d1739e1a35ab31f228ba1f",
|
||||
"closureDigest": "sha256:03351f4a250a8db0e79411a9079b43a0ff05f72a2aff41fae17f1fc2de24bd41",
|
||||
"profileDigest": "sha256:fe1e6da01b2a9e4c691ca27cf689d2d6de846a93be6b23fc1e103c9addd7b177",
|
||||
"closureDigest": "sha256:4728e5a4e7fc1ba602c3e219824fb84884b05a06cdd19dd3e521ee312e1b373a",
|
||||
"model": "openrouter/deepseek/deepseek-v4-flash-0731",
|
||||
"originalFailure": "Original 30s session.open timeout; settled35032ms; runner exit0 and owned cleanup verified;48SDK contracts passed; fresh Rust daemon and complete pack passed.",
|
||||
"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
|
||||
"retentionDays": 7,
|
||||
"profileVersion": 13,
|
||||
"phaseLimit": "Native get_state is internal to unchanged wrapper; ACP new/set spans include it but do not identify its internal duration."
|
||||
}
|
||||
@@ -132,7 +132,7 @@ def execute(args):
|
||||
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.mjs',pack,PIN['sourceRevision'],'darwin','x64'],180))
|
||||
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())
|
||||
sink=scratch/'startup-timings.jsonl';fd=os.open(sink,os.O_WRONLY|os.O_CREAT|os.O_EXCL|os.O_NOFOLLOW,0o600);st=os.fstat(fd);os.close(fd)
|
||||
@@ -140,9 +140,9 @@ def execute(args):
|
||||
sidecar=pack/'dist/cli/acpx-runtime-sidecar.cjs';original_sidecar=sidecar.read_bytes();patched,patch=patch_sidecar(original_sidecar,identity)
|
||||
# Preserve original file mode; this one private copy now has an explicit diagnostic identity.
|
||||
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-B9-sidecar',tofile='diagnostic-sidecar')))
|
||||
(out/'sidecar.diff').write_text(''.join(difflib.unified_diff(original_sidecar.decode().splitlines(True),patched.decode().splitlines(True),fromfile='original-f5-profile13-sidecar',tofile='diagnostic-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']],180))
|
||||
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))
|
||||
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]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""Sparse additive instrumentation of one pinned bundle; never edits vendor closure bytes."""
|
||||
import hashlib,json
|
||||
from source_guard import require
|
||||
ORIGINAL_SHA='7462825f4b82bce8e2a69425eafe4ca8b2c8812df345269c82fb75aa21f3043c'
|
||||
ORIGINAL_SHA='ce987993ffb92f449ef0432dee6cd7eb90ea19521ce3d7b51a185fed16ed8c47'
|
||||
PREFIX='__pcStartupDiagnostic'
|
||||
|
||||
def patch_sidecar(original,sink):
|
||||
@@ -56,6 +56,14 @@ def patch_sidecar(original,sink):
|
||||
mark('// src/drivers/acpx/codex-runtime-adapter.ts',' commandLaunches.count += 1;','runtime.spawn.callback')
|
||||
mark('// src/drivers/acpx/codex-runtime-adapter.ts',' const ensuredSession = Promise.resolve().then(','runtime.ensure.begin')
|
||||
mark('// src/drivers/acpx/codex-runtime-adapter.ts',' cursorInstructions?.assertReady();','runtime.ensure.settled')
|
||||
# Native RPC internals remain in the unchanged closure; these are ACP boundaries only.
|
||||
mark('', ' async initializeProtocolConnection(connection, launch) {', 'acp.initialize.begin', True)
|
||||
mark('', ' await this.authenticateIfRequired(connection, initialized.authMethods ?? []);', 'acp.initialize.response')
|
||||
mark('// src/drivers/acpx/pi-thinking.ts', ' if (method === "session/new" || method === "session/load") {', 'pi.acp.session.request', True)
|
||||
mark('// src/drivers/acpx/pi-thinking.ts', ' const result = object(message.result);', 'pi.acp.correlated.response')
|
||||
mark('// src/drivers/acpx/pi-thinking.ts', ' state.mode = mode;', 'pi.acp.mode.verified', True)
|
||||
mark('// src/drivers/acpx/codex-runtime-adapter.ts', ' await runtime.setConfigOption({ handle: ensuredHandle, key: "thought_level", value: selectedPiThinkingLevel });', 'pi.acp.thought_level.begin')
|
||||
mark('// src/drivers/acpx/codex-runtime-adapter.ts', ' piThinking.assertReady();', 'pi.acp.thought_level.verified', True)
|
||||
# Catch-all standalone function boundaries relevant to verified-runtime preparation.
|
||||
for name in ['verifyAcpxProfileInstallation','verifyQualifiedRuntimeExecutable','openVerifiedRuntimeExecutable','openVerifiedCommandDirectory','createAcpxPrivateSnapshot','acquireAcpxProviderLifetimeLease']:
|
||||
anchor='async function '+name+'('
|
||||
|
||||
@@ -37,20 +37,20 @@ class DiagnosticTests(unittest.TestCase):
|
||||
for change in reversed(proof['insertions']):
|
||||
shift-=len(change['inserted']);at=change['offset']+shift;text=text[:at]+text[at+len(change['inserted']):]
|
||||
self.assertEqual(text.encode(),self.original);self.assertEqual(hashlib.sha256(text.encode()).hexdigest(),ORIGINAL_SHA)
|
||||
self.assertEqual(len(proof['phases']),47)
|
||||
self.assertEqual(len(proof['phases']),54)
|
||||
def test_wrong_original_rejected(self):
|
||||
with self.assertRaises(RuntimeError):patch_sidecar(self.original+b' ',{'path':'unused','dev':'1','ino':'2','uid':'3'})
|
||||
def test_retained_b9_pack_identity_and_original_test_contract(self):
|
||||
self.assertEqual(PIN['sourceRevision'],'b9e5d6ecdb05ab7244c90976e07c950f8d09b15b')
|
||||
self.assertEqual(PIN['artifactRunId'],'36959948724')
|
||||
self.assertEqual(PIN['artifactId'],'11208570718')
|
||||
def test_retained_f5_pack_identity_and_original_test_contract(self):
|
||||
self.assertEqual(PIN['sourceRevision'],'f5c5fde380f60937ef26cc5a92e1d6a043e9cddc')
|
||||
self.assertEqual(PIN['artifactRunId'],'36984851998')
|
||||
self.assertEqual(PIN['artifactId'],'11218057612')
|
||||
self.assertEqual(PIN['originalSidecarSha256'],ORIGINAL_SHA)
|
||||
self.assertEqual(PIN['selectedFiles']['paperclip-runnerd']['sha256'],PIN['daemonSha256'])
|
||||
self.assertEqual(PIN['selectedFiles']['resolved-pnpm-lock.yaml']['sha256'],PIN['resolvedLockSha256'])
|
||||
self.assertEqual(PIN['testSha256'],'8967cf9c8cd130b68bf9d64abef8cb8d352af00646e2288b341d8c6ae758b47a')
|
||||
self.assertEqual(PIN['testSha256'],'32bb057e1505082c0ed6b1d71cdd8cdb3271d920c2bea9cdc1ebddedf568c0c4')
|
||||
self.assertEqual((PIN['executionCount'],PIN['providerCalls'],PIN['timeoutChanges']),(1,0,False))
|
||||
self.assertEqual((PIN['archiveBytesMaximum'],PIN['retentionDays']),(268435456,7))
|
||||
def test_b9_markers_follow_outer_layout_and_snapshot_boundaries(self):
|
||||
def test_f5_markers_follow_outer_layout_and_snapshot_boundaries(self):
|
||||
_,proof=patch_sidecar(self.original,{'path':'/private/tmp/pc-intel-diagnostic-fixture/startup-timings.jsonl','dev':'1','ino':'2','uid':'501'})
|
||||
phases=proof['phases']
|
||||
self.assertFalse(any(p.startswith('pi.hash.') for p in phases))
|
||||
@@ -62,6 +62,17 @@ class DiagnosticTests(unittest.TestCase):
|
||||
start=source.index(begin);finish=source.index(end,start)
|
||||
interior=[x for x in proof['insertions'] if start < x['offset'] < finish]
|
||||
self.assertEqual(interior,[])
|
||||
def test_pi_acp_markers_preserve_actual_admission_and_no_native_rpc_claim(self):
|
||||
_,proof=patch_sidecar(self.original,{'path':'/private/tmp/pc-intel-diagnostic-fixture/startup-timings.jsonl','dev':'1','ino':'2','uid':'501'})
|
||||
for phase in ['acp.initialize.begin','acp.initialize.response','pi.acp.session.request','pi.acp.correlated.response','pi.acp.mode.verified','pi.acp.thought_level.begin','pi.acp.thought_level.verified']:
|
||||
self.assertEqual(proof['phases'].count(phase),1)
|
||||
self.assertFalse(any('get_state' in phase for phase in proof['phases']))
|
||||
source=self.original.decode()
|
||||
selected=next(x for x in proof['insertions'] if 'Mark("pi.acp.thought_level.verified")' in x['inserted'])
|
||||
self.assertTrue(source[:selected['offset']].endswith(' piThinking.assertReady();'))
|
||||
def test_unknown_rebind_profile_rejects_before_any_pack_access(self):
|
||||
result=subprocess.run([os.environ['PI_DIAGNOSTIC_TEST_NODE'],str(Path(__file__).parent/'rebind-diagnostic-pack.mjs'),'/nonexistent-pack','0'*64,'0'*40,'unknown'],capture_output=True,text=True,timeout=5)
|
||||
self.assertNotEqual(result.returncode,0);self.assertIn('Unexpected diagnostic profile mode',result.stderr);self.assertNotIn('ENOENT',result.stderr)
|
||||
def test_missing_terminal_retains_incomplete_classification(self):
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
p,b=self.binding(Path(tmp))
|
||||
|
||||
Reference in new issue
Block a user