-
Initialize the worktree once per feature branch. Run a setup script (e.g. bash scripts/agent-worktree-setup.sh <branch-name>) that creates .worktrees/<branch-name>/ off the target branch. All work for that unit of change happens only inside that directory — never touch the primary checkout for in-flight work.
-
Discover work in coherent, bounded batches. For batch refactors: grep a regex across the target file set to find candidates, filter out a standing skip list (regex-based skips plus a documented permanent-skip list), then pick one coherent name-glob cluster (e.g. pihole-*, sync-*) to work on at a time. Keep each batch under ~800 LOC of change; split further if it's larger.
-
Migrate with judgment, not blind substitution. Apply edits per file individually — never a blind sed across the whole cluster — since naming clusters can still hide file-specific structure.
-
Verify before committing. Run a syntax check, confirm required sourcing/imports precede first use, confirm no orphaned variables, and exercise the contract (smoke test) before moving to commit.
-
Log the batch. Prepend a progress.md entry describing the batch scope and any new skip categories discovered, so later batches (or later sessions) don't rediscover the same edge cases.
-
Commit, rebase, merge from the worktree.
- Stage and commit inside the worktree, on the feature branch.
git fetch + rebase onto origin/dev (or target base) before opening a PR.
- Push, open the PR, wait for CI to go green, then merge from the primary checkout (not the worktree) — this avoids Windows file-lock issues during merge.
- Fast-forward the primary checkout, then tear down:
git worktree remove. On Windows, a transient "Permission denied" during removal is benign — git has already untracked the worktree; retry with git worktree prune then rm -rf if the directory lingers.
-
Guard against same-branch collisions. The worktree primitive isolates across branches, not within a branch shared by two sessions. Before any git add/commit, check for MERGE_HEAD, REBASE_HEAD, or CHERRY_PICK_HEAD in the target — if present, either wait/notify the other session or pivot to a fresh worktree on a different branch. Record this as a lessons-learned entry so future sessions don't repeat the collision.
-
Design the loop to trust git state, not chat history. Each iteration should independently: git fetch + git log to confirm the current tip, re-read the plan/task file for the next eligible item, and derive next-action purely from repo state. Emit a handoff prompt at the end of each turn carrying forward only what's reproducible from git (branch name, evidence links) — never rely on the model "remembering" prior turns. Define explicit pause conditions: no eligible todo task remains, a release isn't authorized, or the token budget is approaching its limit. When self-pacing a loop, wait roughly 2–2.5 minutes after a merge before firing the next iteration, to keep any prompt cache warm for the next discovery step.