Retry limits
Control how long the agents work on an issue before they give it back to a person.
Overview
A mission runs as a loop. The Builder pushes a commit, CI runs, the Reviewer reads the diff, and QA verifies the acceptance criteria. If one of these gates fails, the mission goes back to the Builder with the feedback from that gate. Then the loop runs again.
Two types of limit stop the loop and give the issue to a person:
| Limit | What it counts | Default |
|---|---|---|
| Oscillation limits | Rounds in which a gate fails the same way again | 2 |
| Outer ceiling | All Builder attempts, whatever the result | 25 |
An oscillation is the same failure, repeated. For example, the Reviewer gives the same blocking comment in consecutive rounds, or QA fails the same criterion in consecutive rounds. A gate that fails in a different way each round makes progress, and those failures do not count toward the limit.
In practice, the oscillation limits are what stop missions, because a stuck mission usually fails the same way each time. The ceiling is a backstop. It is much higher than the oscillation limits, so it rarely stops a mission.
If you increase only maxRetries, usually nothing changes. If missions stop earlier than you want, the cause is almost always an oscillation limit.
Configuration
Add a retries block to the ship.yml at the root of your repository. Every field is optional. A field that you leave out keeps its default.
version: 1
retries:
qaOscillationLimit: 5
reviewOscillationLimit: 4
deployments:
# ...| Field | Meaning | Default | Range |
|---|---|---|---|
reviewOscillationLimit | Number of review rounds that ask for changes before the mission stops | 2 | 1 to 50 |
qaOscillationLimit | Number of failed QA rounds before the mission stops | 2 | 1 to 50 |
ciOscillationLimit | Number of consecutive CI failures with the same signature before the mission stops | 2 | 1 to 50 |
maxReviewGrants | Extra review rounds that SHIP allows when it finds that the work makes progress | 3 | 0 to 50 |
maxRetries | Outer ceiling on Builder attempts | 25 | 1 to 200 |
SHIP changes a value outside its range to the nearest end of that range. A value that is not a number gets the default. An invalid entry can never turn a limit off.
When changes take effect
SHIP reads retries from ship.yml on your main branch, as it does the agents block. A pull request cannot change the limits for its own review, so a new value applies after the change merges.
Each mission reads its limits when it starts and keeps them until it ends. If you edit ship.yml while a mission runs, the change applies to the next mission, not to the current one.
Choosing values
If your codebase needs more rounds to get to a correct result, increase the oscillation limits. For example, acceptance criteria can depend on integration behavior that takes a few attempts to get right. Each extra round is a full agent run, so each round costs money.
If you prefer to see a stuck issue early, keep the defaults. It usually costs less to give the issue to a person after two identical failures than after five.
A higher limit does not make a stuck mission succeed. If the Reviewer gives the same comment again and again, more rounds usually give the same result. The limits give time to work that improves from round to round, not to a problem that the agents cannot solve.
What happens at the limit
The console shows the mission as Needs attention, and the Linear issue moves to In Review. SHIP posts the reason on the issue. The reason names the gate that stopped the mission and gives the feedback from the last round. The pull request stays open. You can take over the branch, or you can reply on the issue to send the agents back with new instructions.
A reply sets the counters back to zero. The limits apply to each period of autonomous work, not to the full life of the issue.
How is this page?