diff --git a/package.json b/package.json index 744719a708..97d7ec547c 100644 --- a/package.json +++ b/package.json @@ -103,7 +103,8 @@ "acpx@0.13.1": "patches/acpx@0.13.1.patch", "@agentclientprotocol/claude-agent-acp@0.70.0": "patches/@agentclientprotocol__claude-agent-acp@0.70.0.patch", "@agentclientprotocol/claude-agent-acp@0.73.0": "patches/@agentclientprotocol__claude-agent-acp@0.73.0.patch", - "@agentclientprotocol/codex-acp@1.6.2": "patches/@agentclientprotocol__codex-acp@1.6.2.patch" + "@agentclientprotocol/codex-acp@1.6.2": "patches/@agentclientprotocol__codex-acp@1.6.2.patch", + "node@24.11.0": "patches/node@24.11.0.patch" }, "overrides": { "rollup": ">=4.59.0", diff --git a/packages/paperclip-runner/src/drivers/acpx/installation-integrity.test.ts b/packages/paperclip-runner/src/drivers/acpx/installation-integrity.test.ts index f799d30b93..01ca79dbad 100644 --- a/packages/paperclip-runner/src/drivers/acpx/installation-integrity.test.ts +++ b/packages/paperclip-runner/src/drivers/acpx/installation-integrity.test.ts @@ -89,6 +89,8 @@ describe("ACPX installation integrity", () => { await Promise.all([ mkdir(join(runnerPackage, "node_modules"), { recursive: true }), mkdir(pnpmProviderDirectory, { recursive: true }), + ]); + await Promise.all([ writeFile(runnerManifest, JSON.stringify({ private: true })), writeFile( join(pnpmProviderDirectory, "package.json"), diff --git a/packages/paperclip-runner/src/drivers/acpx/qualified-profiles.ts b/packages/paperclip-runner/src/drivers/acpx/qualified-profiles.ts index 79b287100c..3d28a9467b 100644 --- a/packages/paperclip-runner/src/drivers/acpx/qualified-profiles.ts +++ b/packages/paperclip-runner/src/drivers/acpx/qualified-profiles.ts @@ -81,7 +81,7 @@ export const QUALIFIED_ACPX_PROFILES: Readonly< agentRuntimePackage: "@openai/codex", agentRuntimeVersion: "0.148.0", commandDigest: - "sha256:94049b3e3c3aee87de62703786e4fa81d031d7bd979f99bdf516d84f28791a79", + "sha256:7a923b3829884d3cabcc9659d22cace3f86813e7bfffc90974b10140a45bc400", qualificationModel: "gpt-5.6-sol", reportedModelId: "gpt-5.6-sol", permissionPolicy: "interactive", diff --git a/packages/paperclip-runner/src/live/runnerd-codex-transport.ts b/packages/paperclip-runner/src/live/runnerd-codex-transport.ts index 7d5c22b148..70e1f53d10 100644 --- a/packages/paperclip-runner/src/live/runnerd-codex-transport.ts +++ b/packages/paperclip-runner/src/live/runnerd-codex-transport.ts @@ -60,7 +60,12 @@ import { releaseMaterializedNativeRuntimeSkills, } from "../drivers/runtime-context-materializer.js"; -const packageRoot = fileURLToPath(new URL("../..", import.meta.url)); +// URL directory conversion preserves a trailing separator while path-derived +// build artifacts do not. Normalize once so a source build cannot be +// misclassified as an external provider pack by a string-only comparison. +const packageRoot = resolve( + fileURLToPath(new URL("../..", import.meta.url)), +); const executableSuffix = process.platform === "win32" ? ".exe" : ""; const MAX_NOTIFICATION_COUNT = 2_048; const MAX_NOTIFICATION_BYTES = 4 * 1024 * 1024; diff --git a/packages/paperclip-runner/test/acpx-codex-package-contract.test.mjs b/packages/paperclip-runner/test/acpx-codex-package-contract.test.mjs index 6f96a49e53..189d4ffa06 100644 --- a/packages/paperclip-runner/test/acpx-codex-package-contract.test.mjs +++ b/packages/paperclip-runner/test/acpx-codex-package-contract.test.mjs @@ -30,6 +30,10 @@ const claudePatch = await readFile( ), "utf8", ); +const nodePatch = await readFile( + new URL("../../../patches/node@24.11.0.patch", import.meta.url), + "utf8", +); test("the runner pins every qualified ACPX production dependency", () => { assert.equal(runnerPackage.dependencies.node, "24.11.0"); @@ -86,6 +90,13 @@ test("old and new pnpm configuration both apply the exact runtime patches", () = workspace, /claude-agent-acp@0\.70\.0': patches\/@agentclientprotocol__claude-agent-acp@0\.70\.0\.patch/, ); + assert.equal( + rootPackage.pnpm.patchedDependencies["node@24.11.0"], + "patches/node@24.11.0.patch", + ); + assert.match(workspace, /node@24\.11\.0: patches\/node@24\.11\.0\.patch/); + assert.match(nodePatch, /- "bin": \{/); + assert.match(nodePatch, /- "node": "bin\/node"/); }); test("the ACPX patch preserves launch-only state and verified spawning", () => { diff --git a/patches/node@24.11.0.patch b/patches/node@24.11.0.patch new file mode 100644 index 0000000000..2278170a9c --- /dev/null +++ b/patches/node@24.11.0.patch @@ -0,0 +1,13 @@ +diff --git a/package.json b/package.json +--- a/package.json ++++ b/package.json +@@ -14,9 +14,6 @@ + "scripts": { + "preinstall": "node installArchSpecificPackage" + }, +- "bin": { +- "node": "bin/node" +- }, + "dependencies": { + "node-bin-setup": "^1.0.0" + }, diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 1a903feeef..5ac292bef3 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -22,3 +22,4 @@ patchedDependencies: '@agentclientprotocol/claude-agent-acp@0.70.0': patches/@agentclientprotocol__claude-agent-acp@0.70.0.patch '@agentclientprotocol/claude-agent-acp@0.73.0': patches/@agentclientprotocol__claude-agent-acp@0.73.0.patch '@agentclientprotocol/codex-acp@1.6.2': patches/@agentclientprotocol__codex-acp@1.6.2.patch + node@24.11.0: patches/node@24.11.0.patch