fix(execute): use sequential dispatch instead of timing-based stagger (#1541)

Address review feedback: LLMs cannot enforce timing between tool calls.
Replace "stagger by ~2 seconds" with concrete, enforceable pattern:
dispatch each Task() one at a time with run_in_background: true. The
round-trip latency of each tool call provides natural spacing for
worktree creation, while agents still run in parallel once created.
Explicitly warn against sending multiple Task() calls in a single
message (which causes simultaneous git worktree add).

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Tibsfox
2026-04-04 04:12:27 -07:00
committed by GitHub
parent 12a4545124
commit 4abcfa1e3a
2 changed files with 65 additions and 0 deletions

View File

@@ -307,6 +307,22 @@ Execute each selected wave in sequence. Within a wave: parallel if `PARALLELIZAT
EXPECTED_BASE=$(git rev-parse HEAD)
```
**Sequential dispatch for parallel execution (waves with 2+ agents):**
When spawning multiple agents in a wave, dispatch each `Task()` call **one at a time
with `run_in_background: true`** — do NOT send all Task calls in a single message.
`git worktree add` acquires an exclusive lock on `.git/config.lock`, so simultaneous
calls race for this lock and fail. Sequential dispatch ensures each worktree finishes
creation before the next begins (the round-trip latency of each tool call provides
natural spacing), while all agents still **run in parallel** once created.
```
# CORRECT: dispatch one Task() per message, each with run_in_background: true
# → worktrees created sequentially, agents execute in parallel
#
# WRONG: multiple Task() calls in a single message
# → simultaneous git worktree add → .git/config.lock contention → failures
```
```
Task(
subagent_type="gsd-executor",

View File

@@ -0,0 +1,49 @@
/**
* GSD Worktree Sequential Dispatch Tests
*
* Validates that execute-phase workflow includes sequential dispatch
* instructions to prevent git config.lock contention when multiple
* agents create worktrees in parallel within the same wave.
*
* See: https://github.com/gsd-build/get-shit-done/issues/1511
*/
const { test, describe } = require('node:test');
const assert = require('node:assert');
const fs = require('fs');
const path = require('path');
const WORKFLOWS_DIR = path.join(__dirname, '..', 'get-shit-done', 'workflows');
describe('worktree sequential dispatch', () => {
const executePhasePath = path.join(WORKFLOWS_DIR, 'execute-phase.md');
let content;
test('execute-phase.md exists', () => {
assert.ok(fs.existsSync(executePhasePath), 'execute-phase.md should exist');
});
test('execute-phase explains git config.lock contention', () => {
content = fs.readFileSync(executePhasePath, 'utf-8');
assert.ok(
content.includes('config.lock'),
'execute-phase.md should explain the git config.lock race condition'
);
});
test('execute-phase requires sequential dispatch with run_in_background', () => {
content = content || fs.readFileSync(executePhasePath, 'utf-8');
assert.ok(
content.includes('run_in_background'),
'execute-phase.md should instruct one-at-a-time dispatch with run_in_background'
);
});
test('execute-phase warns against multiple Task calls in single message', () => {
content = content || fs.readFileSync(executePhasePath, 'utf-8');
assert.ok(
content.includes('WRONG') && content.includes('single message'),
'execute-phase.md should warn against sending multiple Task() calls simultaneously'
);
});
});