Files
cleveragents-core/tools
drew ea4a96aad6 feat(auto-agents): worktree hygiene — startup janitor + retry-on-failure
Live evidence on PR #29 (runs 15-18): 4 implementer worktrees
accumulated in ``/tmp/cleveragents-implementer-worktrees/``, one
with a corrupted ``.git`` link (``fatal: not a git repository``).
Root cause: every SIGTERM-induced dispatcher restart leaves the
in-flight cycle's worktree orphaned, and the mirror's
``worktrees/<name>/`` bookkeeping survives without the directory.
The next cycle's ``git worktree add`` against the same mirror can
then fail with "already exists" or unhelpful path collisions.

Two fixes that together close the loop:

1. **Startup janitor** (``_pr_clone.prune_orphan_worktrees``): scans
   the per-kind worktree base on dispatcher startup and removes
   any dir matching the canonical ``pr-{N}-{kind}-{hex-tag}``
   shape that is EITHER older than the OpenCode worker ceiling
   (default 30 min — longer than any possible in-flight cycle)
   OR has a missing / zero-byte ``.git`` link (definitionally
   corrupted). Removes the dir AND the mirror's ``worktree``
   bookkeeping. Idempotent. Skips operator scratch dirs that
   don't match the canonical name. Disable via
   ``DISPATCHER_WORKTREE_JANITOR_DISABLE=1``. Called once at the
   top of both ``dispatch_review.main`` and
   ``dispatch_implementer.main``.

2. **Retry-on-failure** in ``prepare_pr_worktree``: when
   ``git worktree add`` fails the first time, run
   ``git worktree prune`` to clear stale mirror bookkeeping, force-
   remove the target path if present, and retry exactly once.
   This rescues cycles whose janitor-min-age cushion missed a
   fresh orphan from a very-recent SIGTERM.

Coverage: 13 new tests in ``test_pr_clone_janitor.py`` (recent vs
stale removal, corruption detection regardless of age, non-canonical
name safety, idempotency, disable env, ``git worktree remove``
call count). Full auto_agents suite: 2059 passing (+13 vs prior
commit).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 15:42:06 -04:00
..