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. No AOFORGE_* 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:

  1. Never ask you to run a CLI command, start a server or run a build.
  2. Claude sets up the verification environment itself — starts the dev server, seeds the database, sets env vars.
  3. You only do what needs human judgement: does this look right, does this feel right.
  4. 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

Modehuman-verifydecisionhuman-action
interactive (default)presents to youpresents to youstops
yolo (auto_advance: true)auto-approvesauto-picks the first optionstops
autonomous (mode: "autonomous")delegated to the verifier, approved only on green machine evidenceparked in the decision queuestops

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.