#!/usr/bin/env bash # Finish a task worktree: clear activity, remove worktree + branch, prune target. # Binding: wiki/process/agent-scale.md slices A + D. # # Usage: # tools/worktree-done.sh [--status done|abandoned] [--keep-target] # # Run from the primary checkout (or any worktree of the same repo). Does not # delete uncommitted work without asking — requires a clean task worktree # unless --force. set -euo pipefail root=$(cd "$(dirname "$0")/.." && pwd) # Resolve primary checkout (shared .git). primary=$root if [ -f "$root/.git" ]; then common=$(git -C "$root" rev-parse --path-format=absolute --git-common-dir) case "$common" in */.git) primary=${common%/.git} ;; esac fi cd "$primary" worktree_root=${MISALIGNED_WORKTREE_ROOT:-.Codex/worktrees} case "$worktree_root" in /*) ;; *) worktree_root="$primary/$worktree_root" ;; esac task="" status=done keep_target=0 force=0 while [ $# -gt 0 ]; do case "$1" in --status) shift; status="${1:-done}"; shift || true ;; --keep-target) keep_target=1; shift ;; --force) force=1; shift ;; -h|--help) sed -n '2,12p' "$0" | sed 's/^# \{0,1\}//' exit 0 ;; -*) echo "unknown flag: $1" >&2 exit 2 ;; *) task=$1 shift ;; esac done [ -n "$task" ] || { echo "usage: tools/worktree-done.sh " >&2; exit 2; } wt="$worktree_root/$task" branch="worktree-$task" if [ -d "$wt" ]; then if [ "$force" -eq 0 ]; then dirty=$(git -C "$wt" status --porcelain 2>/dev/null || true) if [ -n "$dirty" ]; then echo "FAIL: worktree has uncommitted changes. Commit/land first, or --force." >&2 echo "$dirty" | head -20 exit 1 fi fi if [ "$keep_target" -eq 0 ] && [ -d "$wt/target" ]; then echo "worktree-done: removing $wt/target" rm -rf "$wt/target" fi echo "worktree-done: removing worktree $wt" git worktree remove --force "$wt" 2>/dev/null || git worktree remove "$wt" fi if git show-ref --verify --quiet "refs/heads/$branch"; then # Only delete if merged or force. if git merge-base --is-ancestor "$branch" origin/main 2>/dev/null || \ git merge-base --is-ancestor "$branch" main 2>/dev/null || \ [ "$force" -eq 1 ]; then git branch -D "$branch" 2>/dev/null || git branch -d "$branch" || true echo "worktree-done: deleted branch $branch" else echo "worktree-done: branch $branch not merged; leave it (use --force to delete)" fi fi if [ -x "$primary/tools/claim.sh" ] || [ -f "$primary/tools/claim.sh" ]; then bash "$primary/tools/claim.sh" release "$task" --status "$status" 2>/dev/null || \ echo "worktree-done: no activity named '$task' (ok)" fi echo "worktree-done: finished $task ($status)"