diff --git a/src/create-prompt/index.ts b/src/create-prompt/index.ts index 36c54bf7..b7a48d31 100644 --- a/src/create-prompt/index.ts +++ b/src/create-prompt/index.ts @@ -1,7 +1,7 @@ #!/usr/bin/env bun import * as core from "@actions/core"; -import { writeFile, mkdir } from "fs/promises"; +import { writeFile, mkdir, rm } from "fs/promises"; import type { FetchDataResult } from "../github/data/fetcher"; import { formatContext, @@ -930,9 +930,14 @@ export async function createPrompt( claudeBranch, ); - await mkdir(`${process.env.RUNNER_TEMP || "/tmp"}/claude-prompts`, { - recursive: true, - }); + // Clear any stale prompt files from a prior invocation. RUNNER_TEMP is documented + // to be emptied between jobs, but on non-ephemeral self-hosted runners this is + // not reliably honored — a stale claude-user-request.txt left behind by a prior + // mention-mode invocation would not be overwritten by a subsequent agent-mode + // invocation, and would leak into the model's context. + const promptDir = `${process.env.RUNNER_TEMP || "/tmp"}/claude-prompts`; + await rm(promptDir, { recursive: true, force: true }); + await mkdir(promptDir, { recursive: true }); // Generate the prompt directly const promptContent = generatePrompt( @@ -948,10 +953,7 @@ export async function createPrompt( console.log("======================="); // Write the prompt file - await writeFile( - `${process.env.RUNNER_TEMP || "/tmp"}/claude-prompts/claude-prompt.txt`, - promptContent, - ); + await writeFile(`${promptDir}/claude-prompt.txt`, promptContent); // Extract and write the user request separately for SDK multi-block messaging // This allows the CLI to process slash commands (e.g., "@claude /review-pr") @@ -960,10 +962,7 @@ export async function createPrompt( githubData, ); if (userRequest) { - await writeFile( - `${process.env.RUNNER_TEMP || "/tmp"}/claude-prompts/${USER_REQUEST_FILENAME}`, - userRequest, - ); + await writeFile(`${promptDir}/${USER_REQUEST_FILENAME}`, userRequest); console.log("===== USER REQUEST ====="); console.log(userRequest); console.log("========================"); diff --git a/src/modes/agent/index.ts b/src/modes/agent/index.ts index b648716c..aca8d53c 100644 --- a/src/modes/agent/index.ts +++ b/src/modes/agent/index.ts @@ -1,4 +1,4 @@ -import { mkdir, writeFile } from "fs/promises"; +import { mkdir, rm, writeFile } from "fs/promises"; import { prepareMcpConfig } from "../../mcp/install-mcp-server"; import { parseAllowedTools } from "./parse-tools"; import { @@ -64,20 +64,19 @@ export async function prepareAgentMode({ } } - // Create prompt directory - await mkdir(`${process.env.RUNNER_TEMP || "/tmp"}/claude-prompts`, { - recursive: true, - }); + // Create prompt directory. Clear any stale files from a prior invocation first — + // see src/create-prompt/index.ts for context (non-ephemeral self-hosted runners + // do not reliably honor the RUNNER_TEMP cleanup contract). + const promptDir = `${process.env.RUNNER_TEMP || "/tmp"}/claude-prompts`; + await rm(promptDir, { recursive: true, force: true }); + await mkdir(promptDir, { recursive: true }); // Write the prompt file - use the user's prompt directly const promptContent = context.inputs.prompt || `Repository: ${context.repository.owner}/${context.repository.repo}`; - await writeFile( - `${process.env.RUNNER_TEMP || "/tmp"}/claude-prompts/claude-prompt.txt`, - promptContent, - ); + await writeFile(`${promptDir}/claude-prompt.txt`, promptContent); // Parse allowed tools from user's claude_args const userClaudeArgs = process.env.CLAUDE_ARGS || "";