Symptoom: TASK_IMPLEMENTATION jobs in een sprint-run met pr_strategy=
SPRINT kregen branch=null in claudeJob.branch, ook al maakte
attachWorktreeToJob de juiste worktree-branch (feat/sprint-<id>) aan en
returnde die in de payload-response.
Gevolg: update_job_status (na PR #43-fix) leest claudeJob.branch uit de
DB → null → valt terug op legacy `feat/job-<8>` → `git push` faalt met
"src refspec feat/job-xxx does not match any" → job FAILED → cascade-
cancel van sibling-tasks in dezelfde sprint-run. Live waargenomen voor
sprint-run cmoy9irr8000ci017fvy30lvv (T-806 FAILED, T-807-T-811
CANCELLED) ondanks dat Claude PR #174 op feat/sprint-fvy30lvv had
gemaakt.
Root cause: attachWorktreeToJob (wait-for-job.ts:205-209) update'de
alleen base_sha. Voor SPRINT_IMPLEMENTATION-kind wordt branch wel naar
DB geschreven (regel 655) maar voor TASK_IMPLEMENTATION-pad zat dat gat.
Fix: altijd branch + (indien aanwezig) base_sha schrijven naar
claudeJob in de update aan het eind van attachWorktreeToJob.
Tests: __tests__/wait-for-job-worktree.test.ts mock-prisma uitgebreid
met `claudeJob.update`. 341 tests in 38 files passed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Implementeert vier open stories uit PBI 'Veilige Claude-agent-workflow':
**Branch per story (cmon11tbe001zbortx35n155c)**
- `resolveBranchForJob`: zoek sibling-job in dezelfde story; reuse z'n
branch (1 PR per story i.p.v. per task).
- Branch-naam: `feat/story-<8-char>` voor nieuwe stories.
- `createWorktreeForJob` kent nu `reuseBranch=true`: detecteert stale
sibling-worktree die de branch nog vasthoudt en verwijdert die eerst.
- `attachWorktreeToJob` neemt `storyId` mee.
**PR-hergebruik (zelfde story)**
- `maybeCreateAutoPr`: als sibling-job in story al een pr_url heeft,
hergebruik die zonder nieuwe `gh pr create`-call. PR-titel komt nu
van de story (was task) zodat het als 'story-PR' leest.
**Worktree-cleanup uitgesteld bij actieve siblings**
- `cleanupWorktreeForTerminalStatus`: count active sibling-jobs in
dezelfde story; defer als > 0 (volgende sub-task gebruikt branch).
**Worktree-cleanup logging (cmon0jc14001ubortjxf2a2ck)**
- Warning bij ontbrekende repoRoot, met productId + jobId in message.
- Warning bij removeWorktreeForJob-failure met keepBranch in message.
**resolveRepoRoot fallback (cmon0jc14001ubortjxf2a2ck)**
- Convention-based fallback: `~/Projects/<repo-name>` afgeleid uit
`product.repo_url` als noch env-var noch config-bestand iets oplevert.
- `repoNameFromUrl` helper geëxporteerd voor herbruikbaarheid.
**Verify EMPTY-detection edge-case (cmon0kdq6001xbort2kgbcqmr)**
- `classifyDiffAgainstPlan`: na file-paths-check ook content-lines
checken; als alle +/- regels alleen headers of whitespace zijn,
return EMPTY met duidelijke reasoning.
Tests: 120/120 groen (3 nieuwe), tsc clean, build clean.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
After claiming a job, resolves repoRoot (env SCRUM4ME_REPO_ROOT_<productId>
or ~/.scrum4me-agent-config.json), creates a git worktree, and returns
worktree_path + branch_name in the response. Rolls back claim to QUEUED
on failure. Tool description updated to instruct agent to work in worktree.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>