fix(worktree): force-remove leftover dir so claims don't loop on 'already exists' #21

Merged
janpeter merged 1 commit from fix/remove-worktree-fs-fallback into main 2026-05-28 15:09:10 +02:00
Owner

Probleem

SPRINT_IMPLEMENTATION-jobs (en in principe elke job met een worktree) konden permanent vastlopen in een loop: claim → getFullJobContext geeft null → rollback → re-queue → opnieuw. Waargenomen op 2026-05-27: job cmpnyil26000pvi7rjjncv5sz deed 20 mislukte runs tot hij met de hand op CANCELLED ging.

Oorzaak

Na een mislukte run (bv. Anthropic 529 "Overloaded") bleef de worktree-map /home/agent/.scrum4me-agent-worktrees/<jobId> staan. removeWorktreeForJob deed alleen git worktree remove --force. Als git het pad niet (meer) als worktree kent — half-afgebroken git worktree add, handmatige leftover, of een container-recreate die de clone wiste — faalt dat commando, blijft de map staan, en gooit createWorktreeForJob vervolgens Worktree path already exists (src/git/worktree.ts) → getFullJobContext geeft null.

Dit is de defense-in-depth aanvulling op #20, dat rollbackClaim al de sprint-worktree + sprint_task_executions laat opruimen. Die fix dekt de happy-path rollback; deze PR dekt het geval waarin het pad bestaat maar git het niet als worktree herkent.

Fix

removeWorktreeForJob: als git worktree remove --force faalt, fallback naar fs.rm(path, { recursive, force }) + git worktree prune, zodat het pad altijd verdwijnt en een volgende claim niet opnieuw loopt.

Test

Nieuwe vitest-case in __tests__/git/worktree.test.ts: een plain directory op het worktree-pad die git niet als worktree kent, wordt nu force-verwijderd (removed: true, map weg). Faalde vóór de fix met fatal: '…' is not a working tree.

  • worktree-suite: 11/11 groen
  • tsc --noEmit: clean
## Probleem `SPRINT_IMPLEMENTATION`-jobs (en in principe elke job met een worktree) konden permanent vastlopen in een loop: claim → `getFullJobContext` geeft `null` → rollback → re-queue → opnieuw. Waargenomen op 2026-05-27: job `cmpnyil26000pvi7rjjncv5sz` deed 20 mislukte runs tot hij met de hand op CANCELLED ging. ## Oorzaak Na een mislukte run (bv. Anthropic 529 "Overloaded") bleef de worktree-map `/home/agent/.scrum4me-agent-worktrees/<jobId>` staan. `removeWorktreeForJob` deed alleen `git worktree remove --force`. Als git het pad **niet (meer) als worktree kent** — half-afgebroken `git worktree add`, handmatige leftover, of een container-recreate die de clone wiste — faalt dat commando, blijft de map staan, en gooit `createWorktreeForJob` vervolgens `Worktree path already exists` (`src/git/worktree.ts`) → `getFullJobContext` geeft `null`. Dit is de defense-in-depth aanvulling op #20, dat `rollbackClaim` al de sprint-worktree + `sprint_task_executions` laat opruimen. Die fix dekt de happy-path rollback; deze PR dekt het geval waarin het pad bestaat maar git het niet als worktree herkent. ## Fix `removeWorktreeForJob`: als `git worktree remove --force` faalt, fallback naar `fs.rm(path, { recursive, force })` + `git worktree prune`, zodat het pad altijd verdwijnt en een volgende claim niet opnieuw loopt. ## Test Nieuwe vitest-case in `__tests__/git/worktree.test.ts`: een plain directory op het worktree-pad die git niet als worktree kent, wordt nu force-verwijderd (`removed: true`, map weg). Faalde vóór de fix met `fatal: '…' is not a working tree`. - worktree-suite: 11/11 groen - `tsc --noEmit`: clean
removeWorktreeForJob threw when `git worktree remove` hit a path git
doesn't register as a worktree (partial `worktree add`, manual leftover,
or a container recreate that wiped the clone). The directory then
survived rollback cleanup, so the next claim looped forever on
"Worktree path already exists" -> getFullJobContext null (notably for
SPRINT_IMPLEMENTATION jobs after a transient Claude failure). Fall back
to fs.rm + `git worktree prune` so cleanup always clears the path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
janpeter/scrum4me-mcp!21
No description provided.