coily dispatch reap should handle orphaned worktree dirs - registration gone, dir survived #123

Open
opened 2026-05-28 00:59:59 +00:00 by coilysiren · 0 comments
Owner

Problem

coily dispatch reap errors out on dispatch worktree directories whose worktree registration has been deleted but whose directory survives:

fatal: '/Users/kai/projects/coilysiren/.dispatch-worktrees/gauntlet/issue-39' is not a working tree
dispatch reap: skip /Users/kai/projects/coilysiren/.dispatch-worktrees/gauntlet/issue-39: exit status 128

The dir is a real directory with content (.claude, .claude-plugin, .coily, .git file, .github, .python-version, .venv), but the .git file points at /Users/kai/projects/coilysiren/gauntlet/.git/worktrees/issue-39 which no longer exists in the parent repo. So git -C returns 128, and reap can't act.

Net result: orphaned worktree dirs accumulate forever, indistinguishable to reap from worktrees that legitimately failed to clean.

Likely root causes

Either:

  1. The parent gauntlet repo got rebuilt or re-cloned somewhere along the way (e.g. nuked and re-cloned during repo migration), which invalidates every registered worktree. Dirs are left behind because git only owns the registration, not the disk.
  2. Someone ran git worktree remove --force against the registration externally, but couldn't (or didn't) delete the dir.

Either origin produces the same end state for reap.

Fix

coily dispatch reap should detect this case and handle it:

  • If <dir>/.git is a file pointing at a path that doesn't exist in the parent repo, treat the dir as orphaned.
  • For orphaned dirs: confirm there are no source-code files outside the bookkeeping set (.claude*, .coily, .github, .python-version, .venv), then rm -rf the dir.
  • If there are source-code files (real work, never committed), surface them to the operator and skip with a louder message than "is not a working tree" so it's clear what's needed.

Evidence today

One orphan observed 2026-05-27: .dispatch-worktrees/gauntlet/issue-39. Contents are bookkeeping-only - no source. Safe to rm -rf once the systemic fix is in.

Sibling issues

  • coilysiren/coily#122 - dispatch poisons its own reap by mutating .claude/*. Different failure mode; same family ("reap leaves dispatch worktrees uncleanable").
  • coilysiren/agentic-os#79 - untracked agentic_os.egg-info / uv.lock / .claude. Repo-side gitignore policy.

Out of scope

  • rm -rf of the existing gauntlet/issue-39 dir today. Safe to do manually now; waiting on the systemic fix is fine since the dir is inert.
**Problem** `coily dispatch reap` errors out on dispatch worktree directories whose worktree registration has been deleted but whose directory survives: ``` fatal: '/Users/kai/projects/coilysiren/.dispatch-worktrees/gauntlet/issue-39' is not a working tree dispatch reap: skip /Users/kai/projects/coilysiren/.dispatch-worktrees/gauntlet/issue-39: exit status 128 ``` The dir is a real directory with content (`.claude`, `.claude-plugin`, `.coily`, `.git` file, `.github`, `.python-version`, `.venv`), but the `.git` file points at `/Users/kai/projects/coilysiren/gauntlet/.git/worktrees/issue-39` which no longer exists in the parent repo. So `git -C` returns 128, and reap can't act. Net result: orphaned worktree dirs accumulate forever, indistinguishable to reap from worktrees that legitimately failed to clean. **Likely root causes** Either: 1. The parent `gauntlet` repo got rebuilt or re-cloned somewhere along the way (e.g. nuked and re-cloned during repo migration), which invalidates every registered worktree. Dirs are left behind because `git` only owns the registration, not the disk. 2. Someone ran `git worktree remove --force` against the registration externally, but couldn't (or didn't) delete the dir. Either origin produces the same end state for reap. **Fix** `coily dispatch reap` should detect this case and handle it: - If `<dir>/.git` is a file pointing at a path that doesn't exist in the parent repo, treat the dir as orphaned. - For orphaned dirs: confirm there are no source-code files outside the bookkeeping set (`.claude*`, `.coily`, `.github`, `.python-version`, `.venv`), then `rm -rf` the dir. - If there are source-code files (real work, never committed), surface them to the operator and skip with a louder message than "is not a working tree" so it's clear what's needed. **Evidence today** One orphan observed 2026-05-27: `.dispatch-worktrees/gauntlet/issue-39`. Contents are bookkeeping-only - no source. Safe to `rm -rf` once the systemic fix is in. **Sibling issues** - coilysiren/coily#122 - dispatch poisons its own reap by mutating `.claude/*`. Different failure mode; same family ("reap leaves dispatch worktrees uncleanable"). - coilysiren/agentic-os#79 - untracked agentic_os.egg-info / uv.lock / .claude. Repo-side gitignore policy. **Out of scope** - `rm -rf` of the existing `gauntlet/issue-39` dir today. Safe to do manually now; waiting on the systemic fix is fine since the dir is inert.
coilysiren added
P4
and removed
P3
labels 2026-05-31 06:59:42 +00:00
Sign in to join this conversation.
No labels
P0
P1
P2
P3
P4
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
coilyco-bridge/coily#123
No description provided.