diff --git a/packages/paperclip-runner/src/drivers/opencode/opencode-server-driver.test.ts b/packages/paperclip-runner/src/drivers/opencode/opencode-server-driver.test.ts index 130b34f53b3..0d066a4e4be 100644 --- a/packages/paperclip-runner/src/drivers/opencode/opencode-server-driver.test.ts +++ b/packages/paperclip-runner/src/drivers/opencode/opencode-server-driver.test.ts @@ -1,5 +1,6 @@ import { chmod, + copyFile, lstat, mkdir, mkdtemp, @@ -11,7 +12,7 @@ import { } from "node:fs/promises"; import { tmpdir } from "node:os"; import { join, resolve } from "node:path"; -import { afterAll, afterEach, describe, expect, it } from "vitest"; +import { afterAll, afterEach, beforeAll, describe, expect, it } from "vitest"; import { NATIVE_RUNTIME_ASSET_SCHEMA, @@ -29,7 +30,15 @@ import { } from "./opencode-server-driver.js"; const roots: string[] = []; -const fixture = resolve("test/fixtures/fake-opencode-server.mjs"); +let fixtureRoot: string | undefined; +let fixture: string; + +beforeAll(async () => { + fixtureRoot = await mkdtemp(join(tmpdir(), "paperclip-opencode-fixture-")); + fixture = join(fixtureRoot, "fake-opencode-server.mjs"); + // Other suites execute this fixture concurrently. Never chmod their source. + await copyFile(resolve("test/fixtures/fake-opencode-server.mjs"), fixture); +}); function runtimeContext( skillRoot: string, @@ -98,7 +107,7 @@ afterEach(async () => { }); afterAll(async () => { - await chmod(fixture, 0o644); + if (fixtureRoot) await rm(fixtureRoot, { recursive: true, force: true }); }); describe("OpenCodeServerDriver", () => { diff --git a/packages/paperclip-runner/src/drivers/opencode/prepared-context-transport.test.ts b/packages/paperclip-runner/src/drivers/opencode/prepared-context-transport.test.ts index dd6f34e8677..6c592fbd6ec 100644 --- a/packages/paperclip-runner/src/drivers/opencode/prepared-context-transport.test.ts +++ b/packages/paperclip-runner/src/drivers/opencode/prepared-context-transport.test.ts @@ -1,4 +1,4 @@ -import { chmod, mkdtemp, rm } from "node:fs/promises"; +import { chmod, copyFile, mkdtemp, rm } from "node:fs/promises"; import { tmpdir } from "node:os"; import { join, resolve } from "node:path"; import { afterEach, describe, expect, it } from "vitest"; @@ -7,7 +7,6 @@ import { OpenCodeServerDriver, } from "./opencode-server-driver.js"; -const fixture = resolve("test/fixtures/fake-opencode-server.mjs"); const roots: string[] = []; afterEach(async () => { @@ -18,12 +17,16 @@ afterEach(async () => { describe("prepared OpenCode context transport", () => { it("sends prepared initial prompts without the proxy task envelope", async () => { - await chmod(fixture, 0o755); const root = await mkdtemp(join(tmpdir(), "paperclip-opencode-prepared-")); + roots.push(root); + // Executable modes belong to the test's copy, not the shared checkout. + const fixture = join(root, "fake-opencode-server.mjs"); + await copyFile(resolve("test/fixtures/fake-opencode-server.mjs"), fixture); + await chmod(fixture, 0o755); const workspace = await mkdtemp( join(tmpdir(), "paperclip-opencode-prepared-workspace-"), ); - roots.push(root, workspace); + roots.push(workspace); const submitted: Record[] = []; const driver = new OpenCodeServerDriver({ model: "openrouter/deepseek/deepseek-v4-flash-0731",