From 08f4937134fd316a251995f5b734d56db2f3e8b3 Mon Sep 17 00:00:00 2001 From: Garry Tan Date: Sat, 21 Mar 2026 13:59:24 -0700 Subject: [PATCH] fix: move prompt temp file outside workingDirectory to prevent race condition The .prompt-tmp file was written inside workingDirectory, which gets deleted by afterAll cleanup. With --concurrent --retry, afterAll can interleave with retries, causing "No such file or directory" crashes at 0s (seen in review-design-lite and office-hours-spec-review). Fix: write prompt file to os.tmpdir() with a unique suffix so it survives directory cleanup. Also convert review-design-lite from describeE2E to describeIfSelected for proper diff-based test selection. Co-Authored-By: Claude Opus 4.6 (1M context) --- test/helpers/session-runner.ts | 6 ++++-- test/skill-e2e-review.test.ts | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/test/helpers/session-runner.ts b/test/helpers/session-runner.ts index c9b85de0..ab9e2ee5 100644 --- a/test/helpers/session-runner.ts +++ b/test/helpers/session-runner.ts @@ -161,8 +161,10 @@ export async function runSkillTest(options: { '--allowed-tools', ...allowedTools, ]; - // Write prompt to a temp file and pipe it via shell to avoid stdin buffering issues - const promptFile = path.join(workingDirectory, '.prompt-tmp'); + // Write prompt to a temp file OUTSIDE workingDirectory to avoid race conditions + // where afterAll cleanup deletes the dir before cat reads the file (especially + // with --concurrent --retry). Using os.tmpdir() + unique suffix keeps it stable. + const promptFile = path.join(os.tmpdir(), `.prompt-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`); fs.writeFileSync(promptFile, prompt); const proc = Bun.spawn(['sh', '-c', `cat "${promptFile}" | claude ${args.map(a => `"${a}"`).join(' ')}`], { diff --git a/test/skill-e2e-review.test.ts b/test/skill-e2e-review.test.ts index 2d1b8550..103c6c9c 100644 --- a/test/skill-e2e-review.test.ts +++ b/test/skill-e2e-review.test.ts @@ -2,7 +2,7 @@ import { describe, test, expect, beforeAll, afterAll } from 'bun:test'; import { runSkillTest } from './helpers/session-runner'; import { ROOT, browseBin, runId, evalsEnabled, selectedTests, - describeIfSelected, describeE2E, testConcurrentIfSelected, + describeIfSelected, testConcurrentIfSelected, copyDirSync, setupBrowseShims, logCost, recordE2E, createEvalCollector, finalizeEvalCollector, } from './helpers/e2e-helpers'; @@ -161,7 +161,7 @@ The diff adds a new "returned" status to the Order model. Your job is to check i // --- Review: Design review lite E2E --- -describeE2E('Review design lite E2E', () => { +describeIfSelected('Review design lite E2E', ['review-design-lite'], () => { let designDir: string; beforeAll(() => {