Skip to content

fix(worktree): claim non-prompt tasks before worktree creation to prevent duplicate-worktree race - #540

Merged
carlospedreira merged 2 commits into
andresharpe:mainfrom
IBondarenko-iwg:fix/536-non-atomic-task-claim-worktree
Jun 26, 2026
Merged

fix(worktree): claim non-prompt tasks before worktree creation to prevent duplicate-worktree race#540
carlospedreira merged 2 commits into
andresharpe:mainfrom
IBondarenko-iwg:fix/536-non-atomic-task-claim-worktree

Conversation

@IBondarenko-iwg

Copy link
Copy Markdown
Contributor

Linked issue

Closes #536

Summary of changes

Non-prompt auto-dispatch tasks (script, mcp, task_gen) claimed in-progress status after worktree creation. Two concurrent runners could both observe the same task as todo via the lock-free Get-NextWorkflowTask, both call git worktree add to the same path, and the second would fail with fatal: '...' already exists.

Root fix: Added a pre-worktree claim guard for non-prompt tasks mirroring the existing prompt-task guard. Calls Invoke-TaskMarkInProgress (HTTP POST with server-side mutex) before any worktree I/O. no_op=true in the response signals the task was already claimed — the guard fetches a replacement task and breaks to the outer loop so full task_gen/prompt-template recovery runs on it. Removed the post-worktree Set-TaskInProgressForExecutorDispatch call, now superseded.

Additional hardening (from code review):

  • Re-syncs $processData.task_id / $env:DOTBOT_CURRENT_TASK_ID after the guard in case $task was replaced during retry
  • Fatal errors (unexpected status, non-HTTP exceptions) re-throw instead of silently retrying
  • 2s back-off before outer-loop continue when all claim attempts exhaust
  • On task swap, always breaks to outer loop so the replacement goes through task_gen/prompt_template recovery
  • Updated Test-ProcessDispatch.ps1 assertion to match Invoke-TaskMarkInProgress instead of the removed function name

Testing notes

  1. Unitpwsh tests/Test-ProcessDispatch.ps1: the "legal executor status transitions" assertion now validates the claim guard is present.
  2. Race reproduction — start two task-runner processes against a workflow with at least one pending non-prompt task. Before this fix both runners race to git worktree add; after, the second detects no_op=true and picks up a different task.
  3. Standalone runner — verify a single runner (-Slot not set) still claims and executes non-prompt tasks normally; the guard is unconditional and must not regress the single-runner path.

Checklist

@IBondarenko-iwg

Copy link
Copy Markdown
Contributor Author

@carlospedreira Heads up: potential merge conflict with #538 (feature/issue-510). Both PRs modify Invoke-WorkflowProcess.ps1 at the same hunk (~line 1485). This PR removes Set-TaskInProgressForExecutorDispatch and inserts the claim guard block there; #538 also adds lines in that area. No semantic overlap — whoever merges second will need a manual hunk combine.

@carlospedreira carlospedreira added type:bug Something is broken bug Something isn't working labels Jun 25, 2026 — with ChatGPT Codex Connector
@carlospedreira carlospedreira removed the type:bug Something is broken label Jun 25, 2026
@carlospedreira
carlospedreira merged commit afe3131 into andresharpe:main Jun 26, 2026
6 checks passed
@github-project-automation github-project-automation Bot moved this from Inbox to Done in Dotbot Product Backlog Jun 26, 2026
mirzazekicapi pushed a commit to mirzazekicapi/dotbot that referenced this pull request Jun 26, 2026
PR andresharpe#528 (fix andresharpe#516) landed Issue B upstream using the correct ownership fix:
delete Write-TaskInputInterviewAnswer and Get-TaskInputProductDir entirely,
enrich questions_resolved on the task instead. Took upstream version.
PR andresharpe#540 (fix andresharpe#536) and PR andresharpe#541 (fix andresharpe#537) auto-merged cleanly.
All v4-runtime issues now covered by upstream -- branch has zero unique changes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Non-atomic task claim causes duplicate worktree creation under concurrency

2 participants