ea4a96aad6
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>