CONCEPTS · PARALLEL EXECUTION

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:

  1. It gives each selected task its own worktree on branch feature/[task-id]-[short-description], created from your current checkout. On Claude Code with the default .claude/worktrees base path, Claude Code creates the worktree: each Tech Lead is spawned with isolation: "worktree" and renames its branch to the task branch. On other hosts, or with a custom base path, Synthex runs git worktree add at {base_path}/feature/[task-id]-[short-description].
  2. It launches a Tech Lead sub-agent per worktree, scoped to that working directory. On hosts with background spawning (such as Cursor), the Tech Leads run in the background so the batch really runs in parallel.
  3. Each Tech Lead orchestrates the specialists it needs — coding, frontend, security, testing — and commits to its own branch only.
  4. Once a task passes its acceptance gates, the orchestrator merges its branch into your current branch with git merge --ff-only and removes the worktree immediately.

The feature/ branch prefix and .claude/worktrees/ base path are configurable with worktrees.branch_prefix and worktrees.base_path; see Workspaces & config layers.

Where the workers run is set by --in-cloud / --in-workspace / --local or next_priority.execution_environment (default local). With cloud on Cursor, step 1 is skipped: each worker gets a cloud VM, pushes its branch, and the orchestrator fetches and fast-forwards it. With workspace inside Orca or Herdr, each worker is its own agent session in a child workspace that the tool owns and Synthex removes after the merge. When a mode isn't available, Synthex prints a one-line notice and uses local worktrees. See Cloud agents and Host workspaces.

Is it safe to run agents in parallel?

Yes, because the isolation invariant guarantees two concurrent tasks never share a working tree, and the same gates run on every task before merge regardless of how many tasks ran simultaneously. Worktrees give each task a separate filesystem; the merge step serialises back into your branch one task at a time. Quality is not relaxed for speed — every parallel-built task still needs its linked tests, your [H] approvals, and a passing test suite before it lands.

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 up to concurrent_tasks tasks, ranked by priority rating, dependency chains, business value, and the current milestone. Within that:

  1. Status must be actionable. Tasks that are done, blocked, or awaiting [H] approval do not enter the batch.
  2. Dependencies must be satisfied. A task whose prerequisites are not yet done is skipped.
  3. The current milestone is the boundary. Every task in the current milestone is finished before the next milestone starts, and phase boundaries are never crossed in a single session.
  4. Only truly independent tasks run together. Tasks that depend on each other are sequenced, never run in parallel.

Before starting, the orchestrator also searches the codebase for existing implementations so a task doesn't rebuild something that already exists. If nothing is actionable — every remaining task is blocked or waiting on you — it tells you which tasks remain and why.

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: 3

The 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.

init/synthex:init offers these levels when it sets up the project: Default (3), Aggressive (75% of CPUs), and Yolo (all CPUs). 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 to its branch, writing the message in the project's commit convention. (Cloud workers also push the branch, since the orchestrator can't see their VM.)

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 gates exist to absorb the risk.

Inside each task, the Tech Lead reviews all code — including specialist output — before accepting it, and security-sensitive changes go through the Security Reviewer as a required gate.

Before the orchestrator merges a task:

  • Every [T] acceptance criterion must have a linked, passing test. A missing test sends the task back to the Tech Lead.
  • Every [H] acceptance criterion must have your explicit approval. This holds even under --auto-decide.
  • The full test suite must pass, not just the acceptance-linked tests.

[O] criteria are recorded as post-deployment metrics and are not checked at merge.

Failure modes and recovery

A few failure modes are common enough to plan for:

  • A task gets stuck. The orchestrator first tries to resolve simple issues (test failures, lint errors) by re-engaging the Tech Lead. For persistent blockers it marks the task blocked in the plan with details and moves on. Recoverable changes are preserved, and you get the exact path and 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 your branch has advanced. The orchestrator falls back to a merge commit and resolves conflicts carefully.
  • Worktree removal fails. Synthex stops that task's handoff, diagnoses the problem, and retries before continuing. It never uses git worktree remove --force and never removes a worktree with uncommitted changes. Run git worktree list to inspect anything left behind.

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. Synthex removes each worktree as soon as its task merges, and on Cursor cloud agents move the work off your machine entirely.

When the trade-offs bite, drop concurrent_tasks to 1. The full lifecycle still works sequentially — you only lose the speed-up.

Next