Running a Sprint
/gaia-run-sprint executes the committed sprint phase by
phase. Stories that share a dependency phase carry no ordering constraint
between them, so they can run at the same time; a story in a later phase
never starts until every story of the current phase has finished.
Each slot runs one story through the ordinary story workflow, in its own worktree. Nothing about how a single story is developed changes — this command only decides what runs when.
How it runs
The scheduler admits and tracks stories, but only a live turn can actually drive a story's dev agent — no background process can send it a message on its own. So the command works as a loop: it plans once, then repeatedly asks the scheduler which stories are ready, spawns a dev agent for each one, and reports back what happened once that agent finishes.
- Plan runs every degradation check up front and
prints
mode=parallelor amode=sequential reason=<token>line (see the table below). - Admit asks the scheduler which stories are ready to start. Each one gets a real worktree and a real dev-agent slot; a barrier line means the current phase is full or still finishing, and a complete line means the sprint is done.
- Dispatch spawns the story's stack developer against its own worktree, in the background.
- Report tells the scheduler what happened once a dispatched agent finishes — done, failed, timed out, or merged (in which case the scheduler independently confirms the review gate closed before it counts the story as finished).
Steps 2-4 repeat until every story in every phase has reported a final outcome.
Turning concurrency on
Concurrency is opt-in on three independent switches. All three must be set; if any one is missing the sprint runs one story at a time.
| Switch | Meaning |
|---|---|
GAIA_PARALLEL_EXECUTION=1 | you are asking for concurrency |
GAIA_WORKTREE_MODE=1 | per-story worktree isolation is available |
parallel_execution.max_parallel_dev_slots > 1 | the budget allows it |
Worktree isolation is a precondition rather than an option: several developers editing one checkout simultaneously is exactly the cross-contamination the isolation prevents. The command will not switch the mode on for you — it explains that it is off and runs sequentially.
Two further keys live in the same configuration section:
teammate_dispatch_ceiling, the total number of concurrent
agents of every class, which must leave headroom above the slot budget for
gate agents; and story_timeout_minutes, the per-story
wall-clock budget, 90 by default.
When it runs sequentially
Running sequentially is a normal outcome, never a failure, and it is always explained. One of these reasons is printed and the sprint proceeds:
| Reason | What happened |
|---|---|
parallel-opt-in-off | concurrency was not requested |
flock-unavailable | the locking primitive is missing, or forced off |
worktree-mode-off | per-story isolation is not switched on |
slots-1 | the budget allows no concurrency |
sprint-unreadable | the sprint file is missing, malformed or unparseable |
no-phase-fields | the sprint parses but carries no phase assignments |
ceiling-cannot-admit | the agent ceiling is saturated with no headroom |
admission-lock-timeout | the admission lock could not be acquired, so no story was admitted without it |
mode-b-fallback | the persistent-agent substrate is unavailable |
admission-error | an unclassified admission failure |
A sprint planned before execution phases existed reports
no-phase-fields. Re-plan it, or assign phases to its rows,
and concurrency becomes available.
On a machine without the locking primitive, note one deliberate difference: the sprint-state writer refuses when concurrency is requested without it, because a single state write has nothing to fall back to. This command instead reports the reason and keeps going, because it does have somewhere to fall back to — a sprint that does not run is a worse outcome than one that runs slowly.
What happens when things go wrong
- A failing story does not stop its siblings. The rest of the phase keeps running, the failure is recorded for the sprint review, and the barrier waits for every story to finish — successfully or not — before the next phase begins.
- A saturated agent ceiling is never a story failure. The story is queued and retried once a slot frees.
- A stalled story is bounded. After
story_timeout_minutesits slot is freed so the rest of the phase proceeds. The story is reported as timed out and its worktree is preserved, because a story that ran out of wall clock is the one most likely to hold work nobody has committed yet. - Re-entry is safe. A story whose worktree survived an earlier run is attached rather than started a second time, and leftovers from a killed run are cleared before anything new is created.
- Clean completion leaves nothing behind. Once a story merges, its worktree is removed along with build output and other ignored files. Memory and checkpoint state is never discarded, and a worktree holding uncommitted work is always kept and reported with a recovery command that works.