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:
parent
1c5970f4bf
commit
c5c24cda67
11 changed files with 187 additions and 88 deletions
|
|
@ -231,48 +231,11 @@ formula_phase_callback() {
|
|||
# ── Stale crashed worktree cleanup ─────────────────────────────────────────
|
||||
|
||||
# cleanup_stale_crashed_worktrees [MAX_AGE_HOURS]
|
||||
# Removes preserved crashed worktrees older than MAX_AGE_HOURS (default 24).
|
||||
# Scans /tmp for orphaned worktrees matching agent naming patterns.
|
||||
# Safe to call from any agent; intended for supervisor/gardener housekeeping.
|
||||
# Requires globals: PROJECT_REPO_ROOT.
|
||||
# Thin wrapper around worktree_cleanup_stale() from lib/worktree.sh.
|
||||
# Kept for backwards compatibility with existing callers.
|
||||
# Requires: lib/worktree.sh sourced.
|
||||
cleanup_stale_crashed_worktrees() {
|
||||
local max_age_hours="${1:-24}"
|
||||
local max_age_seconds=$((max_age_hours * 3600))
|
||||
local now
|
||||
now=$(date +%s)
|
||||
local cleaned=0
|
||||
|
||||
# Collect active tmux pane working directories for safety check
|
||||
local active_dirs=""
|
||||
active_dirs=$(tmux list-panes -a -F '#{pane_current_path}' 2>/dev/null || true)
|
||||
|
||||
local wt_dir
|
||||
for wt_dir in /tmp/*-worktree-* /tmp/action-*-[0-9]* /tmp/disinto-*; do
|
||||
[ -d "$wt_dir" ] || continue
|
||||
# Must be a git worktree (has .git file or directory)
|
||||
[ -f "$wt_dir/.git" ] || [ -d "$wt_dir/.git" ] || continue
|
||||
|
||||
# Check age (use directory mtime)
|
||||
local dir_mtime
|
||||
dir_mtime=$(stat -c %Y "$wt_dir" 2>/dev/null || echo "$now")
|
||||
local age=$((now - dir_mtime))
|
||||
[ "$age" -lt "$max_age_seconds" ] && continue
|
||||
|
||||
# Skip if an active tmux pane is using this worktree
|
||||
if [ -n "$active_dirs" ] && echo "$active_dirs" | grep -qF "$wt_dir"; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# Remove the worktree
|
||||
git -C "${PROJECT_REPO_ROOT}" worktree remove "$wt_dir" --force 2>/dev/null || rm -rf "$wt_dir"
|
||||
log "cleaned stale crashed worktree: ${wt_dir} (age: $((age / 3600))h)"
|
||||
cleaned=$((cleaned + 1))
|
||||
done
|
||||
|
||||
# Prune any dangling worktree references
|
||||
git -C "${PROJECT_REPO_ROOT}" worktree prune 2>/dev/null || true
|
||||
|
||||
[ "$cleaned" -gt 0 ] && log "cleaned ${cleaned} stale crashed worktree(s)"
|
||||
worktree_cleanup_stale "${1:-24}"
|
||||
}
|
||||
|
||||
# ── Scratch file helpers (compaction survival) ────────────────────────────
|
||||
|
|
@ -407,7 +370,7 @@ run_formula_and_monitor() {
|
|||
|
||||
# Preserve worktree on crash for debugging; clean up on success
|
||||
if [ "${_MONITOR_LOOP_EXIT:-}" = "crashed" ]; then
|
||||
log "PRESERVED crashed worktree for debugging: ${_FORMULA_SESSION_WORKDIR:-}"
|
||||
worktree_preserve "${_FORMULA_SESSION_WORKDIR:-}" "crashed (agent=${agent_name})"
|
||||
else
|
||||
remove_formula_worktree
|
||||
fi
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue