LearnNewsExamplesServices
Frontmatter
id13214
titleHarness hygiene: ai:prune-worktrees force-removes ALL non-current worktrees (open-PR + dirty) — data-loss risk, no skip-active guard
stateClosed
labels
enhancementdeveloper-experienceai
assigneesneo-gpt
createdAtJun 14, 2026, 12:01 PM
updatedAtJun 14, 2026, 6:01 PM
githubUrlhttps://github.com/neomjs/neo/issues/13214
authorneo-opus-ada
commentsCount6
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtJun 14, 2026, 6:01 PM

Harness hygiene: ai:prune-worktrees force-removes ALL non-current worktrees (open-PR + dirty) — data-loss risk, no skip-active guard

Closed v13.1.0/archive-v13-1-0-chunk-2 enhancementdeveloper-experienceai
neo-opus-ada
neo-opus-ada commented on Jun 14, 2026, 12:01 PM

Context

Agents create git worktrees under .claude/worktrees/ (the Agent isolation path + manual git worktree add for per-ticket branches). Empirically (V-B-A'd 2026-06-14 from the shared checkout): git worktree list shows 51 worktrees. Only a handful map to currently-open PRs; the rest are NO-PR (transient / closed branches like pr-12122, pr12561re, worktree-agent-*, random claude/<adjective-name> isolation paths) or MERGED (e.g. store-remote-crud, test-store-isolation-12331).

There is no prune-on-merge/close step, so worktrees accrete monotonically across sessions.

The Problem

  • Disk + checkout weight: each worktree is a full ~19k-file checkout; 50+ multiplies disk and slows git operations in the shared root.
  • Agent confusion: a long git worktree list makes branch-state orientation noisier (esp. post-compaction, where worktree-branch verification is already a known footgun); stale isolation paths with no PR are pure noise.
  • No lifecycle owner: nothing ties worktree teardown to the PR it backed.

V-B-A done

  • gh issue list --search "worktree in:title" → no existing open hygiene ticket (this is not a dup).
  • Staleness sampled: branches-in-worktrees cross-checked against gh pr list --head <branch> --state all → the majority resolve to NO-PR or MERGED.

The Fix (approach — to be scoped by the owner)

  1. Investigate existing tooling first — confirm whether a prune helper already exists (e.g. a bootstrapWorktree sibling) before adding one; if so, the gap is wiring it to run, not new code.
  2. Prefer a periodic / on-demand sweep that removes worktrees whose branch is MERGED or has a CLOSED/no PR (with a guard: never remove a worktree with uncommitted changes or a currently-open PR). git worktree prune only reaps deleted dirs — it does not remove live-but-stale worktrees, so this needs the PR-state cross-check.
  3. Optional: a teardown hook on PR merge/close for agent-created worktrees.

Acceptance Criteria

  • A documented, safe way to sweep stale worktrees (MERGED / closed-or-no PR), guarded against removing dirty trees or open-PR worktrees.
  • The shared checkout's worktree count reflects roughly the open-PR set after a sweep.
  • No removal of a worktree with uncommitted work or an open PR (fail-safe).

Out of Scope

  • Removing the Agent isolation worktree mechanism itself (it is correct; only the cleanup is missing).
  • Any change to how worktrees are created.

Related

  • Sibling to the worktree-bootstrap discipline (bootstrapWorktree.mjs). Surfaced while shipping #13211/#13212 (a routine per-ticket worktree add brought the count to 51).

Live latest-open sweep: worktree in:title → none; checked 2026-06-14T09:5xZ.

Release classification: post-release (agent-harness tooling hygiene; nothing v13.x-blocking).

Authored by @neo-opus-ada (Ada, Claude Opus 4.8 [1M context]) — origin session 4c598c8f-d8a7-4288-9420-e825a45d310e.