fix: Extract lib/worktree.sh — create, recover, cleanup (#797)

Extract reusable worktree management into lib/worktree.sh:
- worktree_create: git worktree add + checkout + submodules
- worktree_recover: detect existing worktree, reuse or recreate
- worktree_cleanup: remove worktree + clear Claude Code project cache
- worktree_cleanup_stale: scan /tmp for orphaned worktrees, skip preserved
- worktree_preserve: mark worktree for debugging (skip stale cleanup)

Update callers:
- dev-agent.sh: use worktree_create/worktree_recover/worktree_cleanup
- action-agent.sh: use worktree_cleanup/worktree_preserve
- formula-session.sh: delegate cleanup_stale_crashed_worktrees, use worktree_preserve
- All formula agents source lib/worktree.sh

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
openhands 2026-03-27 19:06:31 +00:00
parent 1c5970f4bf
commit c5c24cda67
11 changed files with 187 additions and 88 deletions

View file

@ -32,6 +32,7 @@ FORGE_TOKEN="${FORGE_ACTION_TOKEN:-${FORGE_TOKEN}}"
source "$(dirname "$0")/../lib/ci-helpers.sh"
source "$(dirname "$0")/../lib/agent-session.sh"
source "$(dirname "$0")/../lib/formula-session.sh"
source "$(dirname "$0")/../lib/worktree.sh"
# shellcheck source=../dev/phase-handler.sh
source "$(dirname "$0")/../dev/phase-handler.sh"
SESSION_NAME="action-${PROJECT_NAME}-${ISSUE}"
@ -62,13 +63,7 @@ status() {
# --- Action-specific helpers for phase-handler.sh ---
cleanup_worktree() {
cd "${PROJECT_REPO_ROOT}" 2>/dev/null || true
git worktree remove "$WORKTREE" --force 2>/dev/null || true
rm -rf "$WORKTREE"
# Clear Claude Code session history for this worktree to prevent hallucinated "already done"
local claude_project_dir
claude_project_dir="$HOME/.claude/projects/$(echo "$WORKTREE" | sed 's|/|-|g; s|^-||')"
rm -rf "$claude_project_dir" 2>/dev/null || true
worktree_cleanup "$WORKTREE"
log "destroyed worktree: ${WORKTREE}"
}
cleanup_labels() { :; } # action agent doesn't use in-progress labels
@ -108,7 +103,7 @@ cleanup() {
local final_phase=""
[ -f "$PHASE_FILE" ] && final_phase=$(head -1 "$PHASE_FILE" 2>/dev/null || true)
if [ "${final_phase:-}" = "PHASE:crashed" ] || [ "${_MONITOR_LOOP_EXIT:-}" = "crashed" ] || [ "$exit_code" -ne 0 ]; then
log "PRESERVED crashed worktree for debugging: $WORKTREE"
worktree_preserve "$WORKTREE" "crashed (exit=$exit_code, phase=${final_phase:-unknown})"
else
cleanup_worktree
fi