Skip to content

fix: clear stale claude-prompts dir before each write#1288

Open
kyungilpark wants to merge 1 commit intoanthropics:mainfrom
kyungilpark:fix/clear-stale-claude-prompts
Open

fix: clear stale claude-prompts dir before each write#1288
kyungilpark wants to merge 1 commit intoanthropics:mainfrom
kyungilpark:fix/clear-stale-claude-prompts

Conversation

@kyungilpark
Copy link
Copy Markdown

Fixes #1287.

Problem

${RUNNER_TEMP}/claude-prompts/ is shared across jobs on non-ephemeral self-hosted runners — the documented RUNNER_TEMP cleanup contract is not honored there. In particular, claude-user-request.txt is only written by create-prompt when a user request exists; in agent mode it is left untouched, so a stale value left by an earlier mention-mode job in repo A leaks into a later agent-mode job in repo B running on the same runner agent.

We observed this happen on ~40% of agent-mode review jobs landing on an affected runner agent over a 5-day window — every affected review surfaced an unrelated stale question from a much-earlier mention-mode job in another repo.

Issue #1287 has the full reproducer, evidence, and root-cause analysis.

Fix

Add await rm(dir, { recursive: true, force: true }) before each await mkdir(...) in both write sites:

  • src/create-prompt/index.ts (tag/comment mode — writes claude-prompt.txt and claude-user-request.txt)
  • src/modes/agent/index.ts (agent mode — writes claude-prompt.txt)

Each invocation now starts with a guaranteed-clean directory.

Side effect: extracted the shared path into a promptDir local in both files, eliminating four duplicated \${process.env.RUNNER_TEMP || "/tmp"}/claude-prompts literals.

Why this approach

Considered alternatives (per #1287):

  1. Per-invocation subdirectory keyed by ${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}-${GITHUB_JOB}.
    Cleaner isolation but requires changes at every consumer (src/entrypoints/run.ts:269 reads ${RUNNER_TEMP}/claude-prompts/claude-prompt.txt), bigger blast radius.
  2. Cleanup at the start (this PR). One-line guard, idempotent, no consumer changes, handles every existing and future file in the directory uniformly.
  3. Always-write claude-user-request.txt (sentinel). Fixes the specific leak but leaves the general cross-job staleness intact for any future file added to the directory.

Option 2 is the smallest, least invasive change and self-heals on every invocation.

Tests

The fs writes here are not covered by existing tests (test/create-prompt.test.ts, test/modes/agent.test.ts neither mock nor exercise the mkdir/writeFile path). I did not add new tests to keep the patch focused; happy to add an integration-style test that:

  • creates a stale claude-user-request.txt in RUNNER_TEMP/claude-prompts/
  • runs through createPrompt with a context that does not produce a user request
  • asserts the stale file is gone after invocation

— if reviewers want it.

Verification

Manual reproducer from #1287 was used to confirm the leak exists on v1.0.67. After applying this patch in a downstream wrapping composite (mirroring the same rm-then-mkdir shape via shell), the leak no longer manifests.

Previously, prompt files at `${RUNNER_TEMP}/claude-prompts/` from a prior
invocation could persist on non-ephemeral self-hosted runners (where the
documented `RUNNER_TEMP` cleanup contract is not reliably honored). In
particular, `claude-user-request.txt` is only written by `create-prompt`
when a user request exists; an `agent`-mode invocation does not overwrite
it, so a stale value left by an earlier mention-mode job in another repo
would leak into a later agent-mode job's effective context on the same
runner agent.

Fix: `rm -rf` the directory before `mkdir` in both write sites
(`src/create-prompt/index.ts`, `src/modes/agent/index.ts`). Idempotent,
safe on hosted runners (where the dir is already empty), and self-heals
on self-hosted runners.

Closes anthropics#1287
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Stale prompt files in ${RUNNER_TEMP}/claude-prompts/ leak between jobs on non-ephemeral self-hosted runners

1 participant