mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-23 17:33:51 +02:00
ci: diagnose retained W native Intel startup
Bind the existing bounded diagnostic to the exact failed W pack and add sparse native-manifest and layout timings without changing startup assertions, deadlines, or cleanup. Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
31e7bc15b0
commit
2b3924f91d
5 files changed
+65
-36
No files matched your search
@@ -32,7 +32,7 @@ on:
|
||||
type: boolean
|
||||
default: false
|
||||
diagnose_pi_startup:
|
||||
description: "Instrument one retained S native Intel startup with unchanged deadlines (diagnostic only, no provider prompts)"
|
||||
description: "Instrument one retained W native Intel startup with unchanged deadlines (diagnostic only, no provider prompts)"
|
||||
type: boolean
|
||||
default: false
|
||||
diagnose_ajv_pack:
|
||||
@@ -190,7 +190,7 @@ jobs:
|
||||
test "$SOURCE_E2E_SUPPORT_ONLY" != true
|
||||
test "$DIAGNOSE_AJV" != true
|
||||
test "$IMAGE_MODE" != true
|
||||
test "$EXPECTED_SOURCE_SHA" = 586af4d7f3b07aa683338aedb4e5182603b70401
|
||||
test "$EXPECTED_SOURCE_SHA" = efe019a79f50440d7bd6c3bc6c75fb8f18953093
|
||||
test "$EXPECTED_LOCK_SHA256" = 38338a6867358440c5ab5993eaeb85fb501bc7df65d24acf52fbd63c880ee4ba
|
||||
test "$(gh api "repos/$REPOSITORY" --jq '.visibility')" = public
|
||||
fi
|
||||
@@ -267,7 +267,7 @@ jobs:
|
||||
if-no-files-found: error
|
||||
|
||||
manual_pi_startup_diagnostic:
|
||||
name: Retained S native Intel startup timing diagnostic (not qualification)
|
||||
name: Retained W 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
|
||||
@@ -288,16 +288,16 @@ jobs:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
gh api repos/paperclipai/paperclip/actions/artifacts/11200013599/zip \
|
||||
> "$RUNNER_TEMP/pi-startup-36940079040.zip"
|
||||
printf '%s %s\n' 9e0209b69b2ee886c4cc8c9c74310a6c1a9010c81e41d618499b2a4d42f92830 \
|
||||
"$RUNNER_TEMP/pi-startup-36940079040.zip" | shasum -a 256 --check
|
||||
gh api repos/paperclipai/paperclip/actions/artifacts/11204971146/zip \
|
||||
> "$RUNNER_TEMP/pi-startup-36952019178.zip"
|
||||
printf '%s %s\n' 5f9bfabcb5a3d1b3180c2eb6f0eb8ebe58770b0c63a8b7dcbd379729b6c468f9 \
|
||||
"$RUNNER_TEMP/pi-startup-36952019178.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-36940079040.zip" \
|
||||
--archive "$RUNNER_TEMP/pi-startup-36952019178.zip" \
|
||||
--output "$GITHUB_WORKSPACE/pi-startup-diagnostic-evidence"
|
||||
- name: Admit complete diagnostic evidence within the storage bound
|
||||
if: always()
|
||||
|
||||
@@ -1,48 +1,48 @@
|
||||
{
|
||||
"schema": "paperclip.native-intel-startup-diagnostic-input/v1",
|
||||
"sourceRevision": "586af4d7f3b07aa683338aedb4e5182603b70401",
|
||||
"sourceRevision": "efe019a79f50440d7bd6c3bc6c75fb8f18953093",
|
||||
"resolvedLockSha256": "38338a6867358440c5ab5993eaeb85fb501bc7df65d24acf52fbd63c880ee4ba",
|
||||
"artifactRunId": "36940079040",
|
||||
"artifactId": "11200013599",
|
||||
"artifactWorkflowRevision": "9b7a91e3fca55eba893bd62dd7b0ca9e94abdb4d",
|
||||
"artifactZipBytes": 1128953890,
|
||||
"artifactZipSha256": "9e0209b69b2ee886c4cc8c9c74310a6c1a9010c81e41d618499b2a4d42f92830",
|
||||
"artifactRunId": "36952019178",
|
||||
"artifactId": "11204971146",
|
||||
"artifactWorkflowRevision": "31e7bc15b00ba651b9c2e321d425a7e6320a48f9",
|
||||
"artifactZipBytes": 1129002006,
|
||||
"artifactZipSha256": "5f9bfabcb5a3d1b3180c2eb6f0eb8ebe58770b0c63a8b7dcbd379729b6c468f9",
|
||||
"selectedFiles": {
|
||||
"receipt.json": {
|
||||
"bytes": 28434,
|
||||
"sha256": "6e67bf4b79806bde77287350994ee91086cce7574ea5ab893303b1bdf2f40fa4"
|
||||
"bytes": 26708,
|
||||
"sha256": "338d7d93ba07b09d55de9a54640eb57c498bb4b35bc7ab1ad02d8fdbb72eb44a"
|
||||
},
|
||||
"provider-pack.tar.gz": {
|
||||
"bytes": 1029171454,
|
||||
"sha256": "825f95d44ae81ec2d382aa2ffc203cf023e3b9862f91b0fa6f592eed9ad96d4f"
|
||||
"bytes": 1029188649,
|
||||
"sha256": "680d5a7ed3cb7813fbce0a994d0b91b7ec4991b538da640ed9cc5175baf4b60e"
|
||||
},
|
||||
"provider-pack.json": {
|
||||
"bytes": 3629,
|
||||
"sha256": "0cac1cfee6b980601fcb6f34d06060f4e9f5746df06f458632d041b18c47b1a0"
|
||||
"sha256": "ffb81f911990dc66558a277ab8ec20698af03e671f44bdd8a41fda0f392e4e6a"
|
||||
},
|
||||
"pack-inventory.json": {
|
||||
"bytes": 10633747,
|
||||
"sha256": "c95c9cfbcbefb0e566add7ca70ba9bc115e3ff8c1b6a9d113b677583287b807e"
|
||||
"bytes": 10633748,
|
||||
"sha256": "5d2fbdb0976ae1f4431cf66ee3611c2104d23a3ce04910be8941f8a03e36d710"
|
||||
},
|
||||
"paperclip-runnerd": {
|
||||
"bytes": 32035568,
|
||||
"sha256": "a0c7ace7ad0be9ac5b5f9c58749d9c452cd3a1ef143a38d5120d8e4f2bf82d6a"
|
||||
},
|
||||
"source.tar": {
|
||||
"bytes": 141598720,
|
||||
"sha256": "87f48d5c0df9c4e9c30c880c5b1da862b063d9ba4c12afc4788ee5fd6adcfc6e"
|
||||
"bytes": 141690880,
|
||||
"sha256": "587c0f60a30f0ca4b43361830cb611fcaa4a83f492cb7a9fd66b7908b45f72be"
|
||||
},
|
||||
"source-input-inventory.json": {
|
||||
"bytes": 1032538,
|
||||
"sha256": "88ccb84c519bfc99f4ac8d8801c93cf083b3ba5b836405a345697d2243f7b64d"
|
||||
"bytes": 1033276,
|
||||
"sha256": "1356cd9a81d4c94e477a50cf2879efc7002fd687337fdad121f0c2381689ab36"
|
||||
},
|
||||
"resolved-pnpm-lock.yaml": {
|
||||
"bytes": 607788,
|
||||
"sha256": "38338a6867358440c5ab5993eaeb85fb501bc7df65d24acf52fbd63c880ee4ba"
|
||||
}
|
||||
},
|
||||
"originalSidecarSha256": "97eedf930681729c6a1654e6c54bcc9657154e5dd2761f9922f4b01c7358f9f7",
|
||||
"originalPackDigest": "sha256:dd7e629c794dc8cdcd43cf1326b4d812bb3dd97949384f13ce97500f47fc4d01",
|
||||
"originalSidecarSha256": "1f0ee222b2edaad997b898aec6580982afc179fc60e5abc87fa3e6f2386a691f",
|
||||
"originalPackDigest": "sha256:ae455e79f07f189e6d5d2bb9eeb01d26040e4b19370bfcda47d288c7b1d60b24",
|
||||
"daemonSha256": "a0c7ace7ad0be9ac5b5f9c58749d9c452cd3a1ef143a38d5120d8e4f2bf82d6a",
|
||||
"nodeSha256": "7abcf39bd37ab251015337ff75304d7555f0d8e88c6e0fbf04bce8ce34636f49",
|
||||
"testPath": "packages/paperclip-runner/test/pi-closed-startup.test.mjs",
|
||||
@@ -51,7 +51,7 @@
|
||||
"profileDigest": "sha256:5e276f48c8a87b3e6165369faac62d3925282c84b98934575b1b7b97ad50b309",
|
||||
"closureDigest": "sha256:8c6e7802d47da9410af56e367f6cf7af572fcbf3e361627cee026e8cffc9bdd3",
|
||||
"model": "openrouter/deepseek/deepseek-v4-flash-0731",
|
||||
"originalFailure": "PRP command session.open timed out; settledMs30684; durationMs31720;44SDK contracts passed; cleanup verified",
|
||||
"originalFailure": "Durable session.open failed: ACPX sidecar request timed out at session.open; drain issued 30.275s after open; secondary close could not durably suspend provider;44SDK contracts passed; cleanup verified; no report.json produced",
|
||||
"executionCount": 1,
|
||||
"providerCalls": 0,
|
||||
"timeoutChanges": false,
|
||||
|
||||
@@ -104,7 +104,7 @@ 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-S-sidecar',tofile='diagnostic-sidecar')))
|
||||
(out/'sidecar.diff').write_text(''.join(difflib.unified_diff(original_sidecar.decode().splitlines(True),patched.decode().splitlines(True),fromfile='original-W-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))
|
||||
after_manifest=json.loads((pack/'provider-pack.json').read_text());expected=copy.deepcopy(before_manifest)
|
||||
|
||||
@@ -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='97eedf930681729c6a1654e6c54bcc9657154e5dd2761f9922f4b01c7358f9f7'
|
||||
ORIGINAL_SHA='1f0ee222b2edaad997b898aec6580982afc179fc60e5abc87fa3e6f2386a691f'
|
||||
PREFIX='__pcStartupDiagnostic'
|
||||
|
||||
def patch_sidecar(original,sink):
|
||||
@@ -31,13 +31,13 @@ def patch_sidecar(original,sink):
|
||||
mark('// src/drivers/acpx/runtime-host.ts',' const commandOwner = createAcpxCommandLeaseOwner(','command.acquire.end')
|
||||
mark('// src/drivers/acpx/runtime-host.ts',' runtime = await acquireAbortableAdmissionResource({','runtime.acquire.begin')
|
||||
mark('// src/drivers/acpx/pi-installation.ts','async function verifyPiInstallation(profile) {','pi.install.begin',True)
|
||||
mark('// src/drivers/acpx/pi-installation.ts',' const verified = await verifyPiRuntimeManifest(runtimeRoot, manifest);','pi.manifest.begin')
|
||||
mark('// src/drivers/acpx/pi-installation.ts',' if (verified.manifestDigest !== metadata.manifestDigest)','pi.manifest.end')
|
||||
mark('// src/drivers/acpx/pi-installation.ts',' const entries = await readNativeAcpxDistributionEntries(declaration);','pi.native_manifest.begin')
|
||||
mark('// src/drivers/acpx/pi-installation.ts',' const layout = await verifyPiRuntimeLayoutForNativeSnapshot(runtimeRoot, manifest, { entries }, expectedClosure);','pi.native_manifest.end')
|
||||
mark('// src/drivers/acpx/pi-installation.ts',' return Object.freeze({','pi.install.end')
|
||||
mark('// src/drivers/acpx/pi-verified-runtime.ts','async function inventoryPiRuntimeFiles(root) {','pi.discovery.begin',True)
|
||||
mark('// src/drivers/acpx/pi-verified-runtime.ts','async function discoverPiRuntimeFiles(root) {','pi.discovery.begin',True)
|
||||
mark('// src/drivers/acpx/pi-verified-runtime.ts',' await visit(physicalRoot);','pi.discovery.end',True)
|
||||
mark('// src/drivers/acpx/pi-verified-runtime.ts',' for (let index = 0; index < regular.length;','pi.hash.begin')
|
||||
mark('// src/drivers/acpx/pi-verified-runtime.ts',' return files;','pi.hash.end')
|
||||
mark('// src/drivers/acpx/pi-verified-runtime.ts','async function verifyPiRuntimeLayoutForNativeSnapshot(root, manifest, nativeManifest, expectedClosureSha256) {','pi.layout.begin',True)
|
||||
mark('// src/drivers/acpx/pi-verified-runtime.ts',' return { manifestDigest };','pi.layout.end')
|
||||
mark('// src/drivers/acpx/native-distribution-integrity.ts','async function createNativeAcpxDistributionSnapshot(input, entries) {','snapshot.begin',True)
|
||||
mark('// src/drivers/acpx/native-distribution-integrity.ts',' const copyEntry = async (entry) => {','snapshot.directories.end')
|
||||
mark('// src/drivers/acpx/native-distribution-integrity.ts',' for (let start = 0; start < entries.length; ) {','snapshot.copy.begin')
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import copy,hashlib,json,os,subprocess,tempfile,unittest
|
||||
from pathlib import Path
|
||||
from startup_timing_patch import patch_sidecar,ORIGINAL_SHA
|
||||
from startup_diagnostic import validate_pack_delta,validate_timing_sink,reject_sink_failure
|
||||
from startup_diagnostic import validate_pack_delta,validate_timing_sink,reject_sink_failure,PIN
|
||||
from diagnostic_lifecycle import DiagnosticChild,DiagnosticInspection
|
||||
from owned_processes import process_table,command_tokens,ProcessInspectionUnavailable
|
||||
from unittest.mock import patch
|
||||
@@ -40,6 +40,35 @@ class DiagnosticTests(unittest.TestCase):
|
||||
self.assertEqual(len(proof['phases']),46)
|
||||
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_w_pack_identity_and_original_test_contract(self):
|
||||
self.assertEqual(PIN['sourceRevision'],'efe019a79f50440d7bd6c3bc6c75fb8f18953093')
|
||||
self.assertEqual(PIN['artifactRunId'],'36952019178')
|
||||
self.assertEqual(PIN['artifactId'],'11204971146')
|
||||
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['executionCount'],PIN['providerCalls'],PIN['timeoutChanges']),(1,0,False))
|
||||
self.assertEqual((PIN['archiveBytesMaximum'],PIN['retentionDays']),(268435456,7))
|
||||
def test_w_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))
|
||||
for begin,end in [('pi.native_manifest.begin','pi.native_manifest.end'),('pi.discovery.begin','pi.discovery.end'),('pi.layout.begin','pi.layout.end'),('snapshot.copy.begin','snapshot.copy.end'),('snapshot.seal.begin','snapshot.seal.end')]:
|
||||
self.assertEqual(phases.count(begin),1);self.assertEqual(phases.count(end),1)
|
||||
# Discovery recursion and descriptor-copy loops must not emit one row per file.
|
||||
source=self.original.decode()
|
||||
for begin,end in [(' const visit = async (directory) => {',' await visit(physicalRoot);'),(' const copyEntry = async (entry) => {',' for (let start = 0; start < entries.length; ) {')]:
|
||||
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_missing_terminal_retains_incomplete_classification(self):
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
p,b=self.binding(Path(tmp))
|
||||
p.write_text(''.join(json.dumps({'phase':phase,'ns':str(i)})+'\n' for i,phase in enumerate(['sidecar.entry','session.open.begin','snapshot.copy.begin'])))
|
||||
with self.assertRaisesRegex(RuntimeError,'terminal marks missing'):
|
||||
validate_timing_sink(p,b,{'sidecar.entry','session.open.begin','snapshot.copy.begin','sidecar.exit'})
|
||||
self.assertIn('snapshot.copy.begin',p.read_text())
|
||||
def test_numeric_inode_rejected(self):
|
||||
with self.assertRaises(RuntimeError):patch_sidecar(self.original,{'path':'/private/tmp/pc-intel-diagnostic-x/startup-timings.jsonl','dev':1,'ino':2,'uid':3})
|
||||
def run_prelude(self,extra='',identity_mutation=None):
|
||||
|
||||
Reference in new issue
Block a user