Add cmux-worktree-reaper for orphaned agent worktrees

Merged
TE
18d ago
+600-0

Summary

  • web/services/vms/hygiene/cmux-worktree-reaper removes agent worktrees whose owner is gone. An owner counts as live when its marker pid runs, a Claude session in ~/.claude/sessions with a live pid has its cwd there, any process has a cwd, file or binary inside, or anything outside build output, its git state or its transcript changed within --ttl-hours (3).
  • Clean, fully pushed worktrees go with a plain git worktree remove.
  • A worktree with uncommitted, untracked or unpushed work is held and reported. --show-files lists what a backup would carry.
  • --backup is opt-in and stays off until Leo approves it. It commits the work from a copy of the index, never including gitignored files, and refuses if a file name or its content looks like a secret, or if gitleaks is missing or finds anything. Only then does it push to wip/<session>/<branch>, read the ref back, and remove the worktree.
  • keep DIR [REASON] / unkeep DIR pin a worktree, which then only shows in the report. mark DIR [SESSION] writes the owner marker into the worktree's git dir.
  • It skips locked worktrees, rebases or merges in progress, dirty submodules and worktrees that hold another worktree. It runs report-only unless --apply, and every action goes to ~/.local/state/cmux-worktree-reaper/log.jsonl.

Design: manaflow-ai/cmuxterm-hq#2562.

Testing

bun test tests/vm-worktree-reaper.test.ts on Huge Blue: 11 pass. The keep test passed again after the HOME fix.

Observed / Not run

  • Observed: the tests above, plus a report-only run over 172 worktrees on Huge Blue.
  • Not run: macOS (lsof path) and the launchd/systemd timer wiring, which comes in a follow-up.

Changelog

none

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.


Summary by cubic

Adds cmux-worktree-reaper, a hygiene tool that removes agent worktrees whose owner is gone. Report-only unless --apply; every action is logged to ~/.local/state/cmux-worktree-reaper/log.jsonl.

  • Clean, fully pushed worktrees go with a plain git worktree remove; worktrees with uncommitted, untracked, or unpushed work are held and reported.
  • --backup stays off until approved: it commits the work from a copy of the index, never includes gitignored files, refuses when a file name or content looks like a secret—scanning every commit the push would publish—or when gitleaks is missing or finds something, then pushes to wip/<session>/<branch> and removes the worktree.
  • keep DIR [REASON]/unkeep DIR pin a worktree; mark DIR [SESSION] writes the owner marker into the worktree's git dir.
  • Skips locked worktrees, rebases or merges in progress, dirty submodules, worktrees holding another worktree, nested repositories, and gitignored non-build files; does nothing when open files can't be enumerated.
  • 11 tests cover removal, backup, secret refusal, and liveness.

Summary by CodeRabbit

  • New Features
    • Added a worktree cleanup utility that reports eligible worktrees and can remove clean, inactive worktrees when explicitly enabled.
    • Pinned, active, or otherwise protected worktrees are retained. Worktrees with changes or unpushed commits are held unless a backup is requested.
    • Backups are pushed before removal; worktrees remain in place if backup checks fail or the push cannot be confirmed.
    • Cleanup actions can be recorded in a log.