Parallel execution
Synthex's Build phase runs multiple plan tasks at the same time, each in its own isolated git worktree, each delegated to its own Tech Lead instance. The model is borrowed from how senior engineers actually work — multiple branches in flight, merged when reviewed — and lifted to the agent layer.
The isolation invariant
The single rule that makes parallel work safe: two concurrent tasks never share a working
tree. If Task A is editing app/page.tsx and Task B is also editing app/page.tsx, they live
on separate branches in separate worktree directories. Neither knows the other exists until they
both reach merge.
Concretely, when next-priority/synthex:next-priority picks up a batch:
- It creates one git worktree per selected task at
.claude/worktrees/feature/{task-id}-{slug}on a fresh branch offmain. - It launches a Tech Lead sub-agent per worktree, scoped to that working directory.
- Each Tech Lead orchestrates the specialists it needs — coding, frontend, security, testing — and commits to its own branch only.
- Once a task passes its acceptance gates, the orchestrator fast-forward merges into
mainand removes the worktree.
The feature/ branch prefix and .claude/worktrees/ base path are configurable; see
Configuration for the worktree settings.
Why worktrees, not branches in one tree
A single working directory with git checkout switching between branches works fine for a human
context-switching at human speed. It does not work for agents running in parallel:
- Two simultaneous edits to the same file produce undefined results.
- Build artifacts and test caches collide.
- A failing pre-commit hook on one task can block another from committing.
Worktrees solve this with first-class support: git worktree add creates a real second working
directory pointing at the same .git repository. Branches are independent, file states are
independent, but commits all reach the same ref store. Merges are ordinary git merges.
Task selection rules
The orchestrator picks the next batch by intersecting four constraints:
- Status must be actionable. Tasks marked
done,blocked, or awaiting[H]review do not enter the batch. - Dependencies must be satisfied. A task whose listed dependencies are not yet
doneis skipped. - The current milestone is the boundary. Phase boundaries are never crossed in a single session. Milestone boundaries are honored unless the entire prior milestone is done.
- Concurrency cap. No more tasks are picked up than your
concurrent_tasksbudget allows.
Independent tasks are scheduled in parallel. Tasks with implicit overlap — for example, two tasks that touch the same shared component — are sequenced even if the plan does not list them as dependencies, since the orchestrator will catch the conflict at merge time anyway and prefers to avoid the wasted work.
The concurrent_tasks budget
concurrent_tasks lives in .synthex/config.yaml under the next_priority section. It caps
the number of worktrees in flight at once.
next_priority:
concurrent_tasks: 3The right value depends on your machine, your model budget, and your patience for review:
- 3 — The conservative default. Easy to follow what each Tech Lead is doing; review queues stay short.
- 75% of CPU cores ("Aggressive") — A reasonable upper bound for laptops. Leaves headroom for typecheck, build, and test passes that fan out within each worktree.
- One per CPU core ("Yolo") — Maximises throughput. Be ready for the model to feel busy and
for
[H]review queues to grow.
You can override per-invocation: next-priority/synthex:next-priority accepts a
concurrent_tasks parameter that wins for that one run.
What runs inside each worktree
Each Tech Lead instance treats its worktree as a normal local checkout. It can:
- Read any file in the project, including the plan and the PRD.
- Write to any file in its worktree (other worktrees are isolated).
- Run scripts — typecheck, test, lint, build — scoped to the worktree.
- Commit and push to its branch.
What it does not do:
- Touch other worktrees (they are not in its working directory).
- Merge to
main(that is the orchestrator's job, after gates pass). - Skip pre-commit hooks. Hook failures are diagnosed and fixed, not bypassed.
Quality gates between fan-out and merge
Parallel execution amplifies both speed and risk. The mandatory gates exist to absorb the risk:
- Code review runs on every diff before merge.
- Security review runs on every diff before merge.
- Optional reviewers (performance, design system, reliability, accessibility) attach when configured for the project.
[T]acceptance criteria must each have a linked, passing test.[H]acceptance criteria must each have explicit human approval.
Findings at severity high or critical block the merge until addressed. medium and below
are logged but do not block.
Failure modes and recovery
A few failure modes are common enough to plan for:
- A task gets stuck. The Tech Lead reports a blocker; the orchestrator marks the task
blockedin the plan with diagnostic notes and moves on. The worktree is preserved for inspection, then cleaned up when you resolve the blocker. - Pre-commit hook fails. The Tech Lead investigates and fixes the underlying issue. Hooks are never skipped — the project's quality bar is non-negotiable.
- Merge conflict. Fast-forward fails when
mainhas advanced. The orchestrator falls back to a merge commit; if the conflict requires judgment, it pauses and reports. - Worktree lingers after a crash. Run
git worktree listto inspect, thengit worktree remove --forceto clean up. Synthex is conservative about deleting your work on its own.
Trade-offs to be aware of
Parallel execution is the right default for tasks that fit cleanly into independent slices, but it has costs:
- Review attention is a bottleneck. If your plan is heavy on
[H]criteria, reviewing five parallel tasks at once is harder than reviewing them one at a time. Batch the[H]reviews. - Wide refactors fight the model. A task that touches dozens of files across the codebase conflicts with everything. Sequence those alone, with the rest of the plan paused.
- Disk and memory cost. Each worktree is a full checkout. On large repos, ten worktrees can add up.
When the trade-offs bite, drop concurrent_tasks to 1. The full lifecycle still works
sequentially — you only lose the speed-up.
Next
- The lifecycle — where parallel execution sits in the five-phase loop
- Configuration — tune
concurrent_tasks, worktree paths, and review behavior - Getting started — install Synthex and run a first parallel batch