Waves and checkpoints
How independent jobs run in parallel, and the four ways execution can legitimately stop.
Wave-based parallelism
The planner records a dependency position on each job. At execution time, jobs are grouped into waves: everything in a wave is independent of everything else in that wave, so it can run concurrently.
Wave 1: job 4-01 job 4-02 job 4-03 ← no dependencies, run together
│ │ │
└──────────┴──────────┘
Wave 2: job 4-04 ← depends on wave 1 output
Each job goes to its own executor subagent with a fresh context window. This is
not just a speed optimisation — it is the mechanism from
context rot. Three jobs in a wave means three clean
windows rather than one window carrying all three jobs’ reconnaissance.
Worktree isolation
Each parallel executor gets its own git worktree, so concurrent jobs cannot collide on the working tree. The orchestrator provisions them itself:
aof-tools exec-context worktree --repo <repo> --id <plan-id> --base <wave-base>
The repo and the base are both stated. They used to be inferred — the executor
agent declared isolation: worktree and let the harness resolve it, which took the
repo from the controller session’s cwd (a dispatch into one repository could land
in another) and the base from the default branch (so wave 2 started without wave
1’s commits). Each executor now runs aof-tools exec-context check --repo ... --base ...
first and stops loudly on either mismatch
(#86).
The worktree guard is not an AOForge hook
Claude Code’s harness has its own worktree-isolation guard that refuses compound Bash commands it cannot statically verify — including commands with no git in them. NoAOFORGE_* escape hatch applies to it, because it is not AOForge’s. Executors
mitigate it by emitting one plain command per Bash call.Tuning it
{
"parallelization": {
"enabled": true,
"job_level": true,
"task_level": false,
"skip_checkpoints": true,
"max_concurrent_agents": 3,
"min_jobs_for_parallel": 2
}
}
job_level parallelism is the useful one and is on by default. task_level is
off: tasks within a job usually share files, and the coordination cost exceeds the
gain.
max_concurrent_agents: 3 is a deliberate default rather than a limit of the
system — more concurrent agents means more simultaneous model calls, and past
three the wall-clock gain flattens while cost keeps climbing.
Checkpoints
A checkpoint is a formalised stop in an execution plan. The governing principle is narrow: if Claude can run it, Claude runs it. Checkpoints are for human judgement, never for manual labour.
The golden rules the executor works to:
- Never ask you to run a CLI command, start a server or run a build.
- Claude sets up the verification environment itself — starts the dev server, seeds the database, sets env vars.
- You only do what needs human judgement: does this look right, does this feel right.
- Secrets come from you; the automation that uses them comes from Claude.
The three types
checkpoint:human-verify — about 90% of checkpoints. Claude built and deployed
something; you confirm it works. Visual UI checks, click-through flows, animation
smoothness, accessibility.
checkpoint:decision — a fork the agent should not pick unilaterally. Which
library, which schema shape, which trade-off.
checkpoint:human-action — something only you can do. An auth flow, a
credential, a dashboard toggle. This always stops, in every mode — auth gates
cannot be automated away.
Mode changes what a checkpoint does
| Mode | human-verify | decision | human-action |
|---|---|---|---|
| interactive (default) | presents to you | presents to you | stops |
yolo (auto_advance: true) | auto-approves | auto-picks the first option | stops |
autonomous (mode: "autonomous") | delegated to the verifier, approved only on green machine evidence | parked in the decision queue | stops |
The distinction between yolo and autonomous matters. Yolo is legacy convenience —
it approves without evidence. Autonomous is stricter than interactive in one
respect: a human-verify checkpoint passes only when the verifier reports
status: passed, which is a higher bar than a human glancing at a screen and
saying “looks fine”.
The decision queue
In autonomous mode, a checkpoint:decision is parked rather than guessed. A
DECISION-NNN.md file lands in .aoforge/decisions/pending/ and execution
continues with other work.
Resolve it when you get to it:
/aoforge:decide DECISION-003 option-b
Execution resumes from where it parked. Enable the queue with
workflow.decision_queue: true.