diff --git a/packages/paperclip-runner/acpx-profiles.json b/packages/paperclip-runner/acpx-profiles.json index deb47d3d79e..00309cb963e 100644 --- a/packages/paperclip-runner/acpx-profiles.json +++ b/packages/paperclip-runner/acpx-profiles.json @@ -37,7 +37,7 @@ "agentServerVersion": "1.0.88", "agentRuntimePackage": null, "agentRuntimeVersion": null, - "commandDigest": "sha256:6326444af8fd447032ca8ad10ce3a1280af9aeeddacd563cf48b430202dbbefd", + "commandDigest": "sha256:754e74c58bc9b22b49d38e0b9ff0a4708caff46abf6ac531975ea2d91c27de41", "requiresProviderPolicy": true }, "claude": { diff --git a/packages/paperclip-runner/runner/crates/runner-core/src/generated_acpx_profiles.rs b/packages/paperclip-runner/runner/crates/runner-core/src/generated_acpx_profiles.rs index 88b30f4793b..bb9e2991f06 100644 --- a/packages/paperclip-runner/runner/crates/runner-core/src/generated_acpx_profiles.rs +++ b/packages/paperclip-runner/runner/crates/runner-core/src/generated_acpx_profiles.rs @@ -47,7 +47,7 @@ pub(crate) fn acpx_release_profile(agent: &str) -> Option { agent_runtime_package: None, agent_runtime_version: None, command_digest: - "sha256:6326444af8fd447032ca8ad10ce3a1280af9aeeddacd563cf48b430202dbbefd", + "sha256:754e74c58bc9b22b49d38e0b9ff0a4708caff46abf6ac531975ea2d91c27de41", requires_provider_policy: true, }, "claude" => AcpxReleaseProfile { diff --git a/packages/paperclip-runner/src/drivers/acpx/copilot-installation.test.ts b/packages/paperclip-runner/src/drivers/acpx/copilot-installation.test.ts index 1764b29da2b..33bbff8409e 100644 --- a/packages/paperclip-runner/src/drivers/acpx/copilot-installation.test.ts +++ b/packages/paperclip-runner/src/drivers/acpx/copilot-installation.test.ts @@ -89,7 +89,7 @@ describe("Copilot build-owned installation", () => { it("admits the current profile with environment launch preparation", () => { expect(QUALIFIED_ACPX_PROFILES.copilot.agentProfileVersion).toBe(70); expect(QUALIFIED_ACPX_PROFILES.copilot.qualificationStatus).toBeUndefined(); - expect(QUALIFIED_ACPX_PROFILES.copilot.commandDigest).toBe("sha256:6326444af8fd447032ca8ad10ce3a1280af9aeeddacd563cf48b430202dbbefd"); + expect(QUALIFIED_ACPX_PROFILES.copilot.commandDigest).toBe("sha256:754e74c58bc9b22b49d38e0b9ff0a4708caff46abf6ac531975ea2d91c27de41"); }); it("preserves v69 while binding closed startup diagnostics in v70", async () => { diff --git a/packages/paperclip-runner/src/drivers/acpx/generated-profiles.ts b/packages/paperclip-runner/src/drivers/acpx/generated-profiles.ts index ec9dd009337..09aeea2965b 100644 --- a/packages/paperclip-runner/src/drivers/acpx/generated-profiles.ts +++ b/packages/paperclip-runner/src/drivers/acpx/generated-profiles.ts @@ -53,7 +53,7 @@ export const QUALIFIED_ACPX_PROFILE_DATA = { "agentServerVersion": "1.0.88", "agentRuntimePackage": null, "agentRuntimeVersion": null, - "commandDigest": "sha256:6326444af8fd447032ca8ad10ce3a1280af9aeeddacd563cf48b430202dbbefd", + "commandDigest": "sha256:754e74c58bc9b22b49d38e0b9ff0a4708caff46abf6ac531975ea2d91c27de41", "permissionPolicy": "interactive" }, "claude": { diff --git a/packages/paperclip-runner/src/drivers/acpx/runtime-host.test.ts b/packages/paperclip-runner/src/drivers/acpx/runtime-host.test.ts index e3f5397972e..bc488a6a7e6 100644 --- a/packages/paperclip-runner/src/drivers/acpx/runtime-host.test.ts +++ b/packages/paperclip-runner/src/drivers/acpx/runtime-host.test.ts @@ -203,6 +203,35 @@ afterEach(async () => { }); describe("ACPX runtime host", () => { + it("retains the admission stage when provider classification replaces the error", async () => { + const fixture = await hostFixture(); + const openRuntime = vi.fn(async () => { throw new Error("Unauthorized private-token-canary"); }); + const failure = await AcpxRuntimeHost.open({ ...fixture.options, agent: "copilot", model: "gpt-5.6-sol", + permissionMode: "approve-all", environment: {COPILOT_GITHUB_TOKEN:"synthetic-test-token"} }, fixture.dependencies({openRuntime})).catch(error => error); + expect(failure).toMatchObject({code:"COPILOT_AUTH_REQUIRED"}); + expect(acpxSidecarErrorCode(failure)).toBe("ACPX_ADMISSION_RUNTIME"); + expect(failure.message).not.toContain("private-token-canary"); + expect(openRuntime).toHaveBeenCalledOnce(); + expect(fixture.commandClose).toHaveBeenCalledOnce(); + }); + it("reports failed Pi skill materialization as skills admission before launch", async () => { + const fixture = await hostFixture(); + const digest = "0".repeat(64); + const bundle = {schema:NATIVE_RUNTIME_ASSET_SCHEMA,digest,manifestDigest:digest, + rootPath:join(fixture.root,"missing-assigned-skill"),fileCount:1,totalBytes:1}; + const snapshot = {prompt:{revision:PAPERCLIP_EXECUTION_PROMPT_REVISION,text:PAPERCLIP_EXECUTION_PROMPT,digest:nativeRuntimePromptDigest()}, + instructions:{entryPath:"AGENTS.md",bundle},skills:[{key:"assigned",runtimeName:"assigned",versionId:"v1",bundle}], + mcp:{assignmentSetId:"none",digest,bindingId:null}}; + const context = {...snapshot,aggregateDigest:canonicalNativeRuntimeContextDigest(snapshot)}; + const openRuntime = vi.fn(async () => runtimePort()); + const failure = await AcpxRuntimeHost.open({ ...fixture.options, agent:"pi",model:"anthropic/claude-sonnet-5", + piThinkingLevel:"low",permissionMode:"approve-all",providerPolicy:{readOnly:false},runtimeContext:context },fixture.dependencies({openRuntime})).catch(error => error); + expect(failure).toBeInstanceOf(Error); + expect(failure.message).toContain("missing-assigned-skill"); + expect(acpxSidecarErrorCode(failure)).toBe("ACPX_ADMISSION_SKILLS"); + expect(openRuntime).not.toHaveBeenCalled(); + expect(fixture.commandClose).not.toHaveBeenCalled(); + }); it.each(["installation", "sandbox", "credential", "runtime"] as const)("retains the failed %s admission stage through the sidecar boundary", async stage => { const fixture = await hostFixture(); const failure = new Error("private-token-canary"); diff --git a/packages/paperclip-runner/src/drivers/acpx/runtime-host.ts b/packages/paperclip-runner/src/drivers/acpx/runtime-host.ts index 5ad12ec6206..f9658074522 100644 --- a/packages/paperclip-runner/src/drivers/acpx/runtime-host.ts +++ b/packages/paperclip-runner/src/drivers/acpx/runtime-host.ts @@ -552,6 +552,7 @@ export class AcpxRuntimeHost { ); options.signal?.throwIfAborted(); } + admissionStage = "skills"; if (options.agent === "pi") { const skills = await acquireAbortableAdmissionResource({ signal: options.signal, @@ -574,7 +575,6 @@ export class AcpxRuntimeHost { PAPERCLIP_PI_READ_ROOTS: JSON.stringify([...(options.providerPolicy?.readRoots ?? []), ...skills.readRoots]), }); } - admissionStage = "skills"; if (!preconfigured && (options.agent === "claude" || options.agent === "grok")) { // The lifetime lease proves the previous provider has stopped. Refresh // the assigned snapshot before every launch, including durable resume; @@ -742,8 +742,8 @@ export class AcpxRuntimeHost { : [], }); } catch (error) { - recordAcpxAdmissionFailure(error, admissionStage); error = classifyAcpxProfileError(options.agent, error) ?? error; + recordAcpxAdmissionFailure(error, admissionStage); const cleanup = cleanupRuntimeResources( runtime, toolBridge, diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v70-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v70-identity.json index 3fff21706b3..40463e44999 100644 --- a/packages/paperclip-runner/test/fixtures/copilot-profile-v70-identity.json +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v70-identity.json @@ -1,5 +1,5 @@ { - "commandDigest": "sha256:6326444af8fd447032ca8ad10ce3a1280af9aeeddacd563cf48b430202dbbefd", + "commandDigest": "sha256:754e74c58bc9b22b49d38e0b9ff0a4708caff46abf6ac531975ea2d91c27de41", "declaration": { "schema": "paperclip.acpx_profile_declaration.v1", "agent": "copilot", @@ -77,7 +77,7 @@ "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", - "runtimeHostSourceSha256": "f12712a06c9d25ba78f61883d6582237de405e79f38586e20419522e5a7059f2", + "runtimeHostSourceSha256": "be14218ad4477e083cfc32f6680fcfed776056a4084615d6b0efd1e521e66232", "runtimeAdapterSourceSha256": "7c47c05306ebe7d1ca6b5d046a96f5726a48adec4d27e7c16788f505f25b5db2", "runtimeSandboxSourceSha256": "981449a4c6d10f682ecf86d834eed07faca30a7d9b419fb8db4973a442a343ec", "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca",