Every point where the loop stops and waits for a person, and why it stops there and not elsewhere.
View raw Markdown · llms.txt · For agents
The loop runs unattended. It stops in exactly these places, and the rule behind all of them is the same: a human decides where the machine would be acting on the world, or acting on itself.
| Gate | Where | How it is passed |
|---|---|---|
| The PRD | loop plan | loop plan approve <id> |
| The technical design | loop plan, after the vote | loop plan approve-design <id> |
| The queue entry | loop plan decompose --create writes issues in the entry state | Moving them to the ready state |
| Merge approval | deliver, when merge.requireHumanApproval | Approving the pull request on GitHub |
| Release | release | loop release approve, bound to a head sha |
| A blocked issue | After the fix rounds run out | Reading the PR comment and deciding |
| An escalation | Unverifiable contract, no plan consensus, stuck worker, budget exceeded | Answering on the ticket |
| A paused issue or stage | After repeated failures | loop resume <issue> or loop resume --stage <stage> |
| Publishing an agent | The retro may propose; it never publishes | A human, to the registry |
Why the design gate exists even after a vote
Three agents agreeing is evidence, not authority. Everything built afterwards inherits the design, so the cost of a wrong one is every issue decomposed from it. Consensus makes the design worth reading; it does not make it someone's decision.
Why the release approval binds to a sha
An approval that outlived its commits is a rubber stamp. The approval records the head it was given for; if anything merged after it, the batch is different and needs its own approval. A successful promotion spends the approval, so nothing merged later rides on it.
Escalations are not retries
The loop never answers its own question by trying again more cheaply:
- an issue over
budget.perIssueTokensescalates, it does not continue with less headroom; - a plan without consensus after
maxCyclesescalates, with the objections still standing; - a contract with a blocking ambiguity escalates instead of dispatching a worker to guess;
- an issue that failed
resilience.maxConsecutiveFailurestimes is paused and labelled, so the next tick does not pick it up and fail the same way.
Every one of those writes an event and, where a channel is configured, calls it. notifications.events lists
which types reach the channel; onEscalate always does, whatever that list says.
What the loop does without asking
Merging a pull request whose checks are green, whose review is clean and whose two definition-of-done lists are
proven — when merge.auto is on and requireHumanApproval is off. That is the one action it takes on the
world by itself, and it is precisely the one that every other gate above exists to make safe.