feat: complete isolated-worktree helpers — worktree-review, worktree-clean, tests (#39)

Finishes the isolated-worktree standard begun in #38 (which merged the
branches/ gitignore, runbook, and scripts/worktree-start). Adds the two
remaining helpers and their tests.

- scripts/worktree-review: isolated DETACHED review worktree under
  branches/review-<branch> (fetch/prune first, refuse to overwrite, print path,
  --dry-run). Detached so a reviewer cannot accidentally commit and review work
  never blocks the author's implementation folder.
- scripts/worktree-clean: the only deleting helper — removes a branches/
  worktree after merge/close, refuses a dirty worktree (no --force), optionally
  safe-deletes a merged branch (git branch -d), fetch/prune first, --dry-run.
  Deletes nothing unless explicitly invoked.
- tests/test_worktrees.py: path generation + refuse-to-overwrite for all three
  helpers via --dry-run (no real worktrees/branches/network/deletions).
- runbook: reference worktree-review / worktree-clean and the --dry-run flag.

Checks: bash -n clean on all three scripts; git diff --check clean; full suite
286 passed, 0 failures.

Closes #39. Follow-up to #38.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-02 02:54:50 -04:00
parent 7e8256cfaf
commit 46db3f73e8
4 changed files with 255 additions and 4 deletions
+62
View File
@@ -0,0 +1,62 @@
#!/usr/bin/env bash
set -euo pipefail
usage() {
cat <<'EOF'
usage: scripts/worktree-review [--dry-run] <branch-name> [start-ref]
Create an isolated, DETACHED review worktree under branches/review-<branch>.
Reviews an existing branch in its own folder without creating a local branch,
so review work never blocks or contaminates the author's implementation folder
and a reviewer cannot accidentally commit. Default start-ref is prgs/<branch>.
Examples:
scripts/worktree-review fix/issue-123-example
scripts/worktree-review --dry-run fix/issue-123-example prgs/fix/issue-123-example
EOF
}
dry_run=0
if [[ "${1:-}" == "--dry-run" ]]; then
dry_run=1
shift
fi
if [[ $# -lt 1 || $# -gt 2 ]]; then
usage >&2
exit 2
fi
branch="$1"
start_ref="${2:-prgs/$branch}"
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
repo_root="$(cd "$script_dir/.." && pwd)"
worktree_name="review-${branch//\//-}"
worktree_path="$repo_root/branches/$worktree_name"
if [[ -e "$worktree_path" ]]; then
cat >&2 <<EOF
Refusing to reuse existing review worktree:
$worktree_path
Inspect it manually. Do not overwrite another reviewer's folder.
EOF
exit 1
fi
if [[ "$dry_run" -eq 1 ]]; then
printf 'repo: %s\n' "$repo_root"
printf 'branch: %s\n' "$branch"
printf 'start-ref: %s\n' "$start_ref"
printf 'worktree: %s\n' "$worktree_path"
printf 'commands:\n'
printf ' git -C %q fetch prgs --prune\n' "$repo_root"
printf ' git -C %q worktree add --detach %q %q\n' \
"$repo_root" "$worktree_path" "$start_ref"
exit 0
fi
git -C "$repo_root" fetch prgs --prune
git -C "$repo_root" worktree add --detach "$worktree_path" "$start_ref"
printf '%s\n' "$worktree_path"