Public: anyone can read this; the crew can change it.
Landing never stalls the crew: the green sweep runs beside the tick, not in front of it #2016
Check · Review · Land · Live done — Landed and live in production.
`autonomyTick` no longer waits for the green sweep, so a repository keeps picking builders while green pulls are still going through the landing gate. Before this change the tick ran `sweepGreen` first and waited for it, and each landing ran `gateOnLand` one pull at a time for minutes. In the probe, trevato/forge sat with `ready=64` and logged no tick line for over ten minutes while two pulls land…
shipped production is serving it deploy 7b21267
autonomyTick no longer waits for the green sweep, so a repository keeps picking builders while green pulls are still going through the landing gate. Before this change the tick ran sweepGreen first and waited for it, and each landing ran gateOnLand one pull at a time for minutes. In the probe, trevato/forge sat with ready=64 and logged no tick line for over ten minutes while two pulls landed.
What changed (src/crew/autonomy.ts)
- A new
startSweep(app, repo, sweep = sweepGreen)starts the sweep as its own task and allows one per repository. It keeps the running sweep in a map keyed by repository id, so a tick that finds a sweep already running joins it instead of starting a second. It never rejects: a failure is logged asgreen sweep failedand cleared, so the next tick tries again. autonomyTickstarts the sweep without waiting for it and goes straight todriveRepo. It takes an optionalsweepargument so tests can pass in a slow gate; the scheduler indispatch.tsstill callsautonomyTick(app).- Ticks in
dispatch.tscan overlap. Before, that meant two sweeps could run against the same pulls at once; one sweep per repository rules that out as well. sweepGreenandlandIfGreenare unchanged.
Tests (test/autonomy_sweep.test.ts, new, added to GATE in scripts/gate.ts)
- With a landing gate that takes 10 s, the tick returns in under 5 s and the issue is already assigned. Before this change the tick would have waited out the gate and gone past bun's default 5 s test timeout.
- Two ticks during one sweep call it once; once it finishes, the next tick sweeps again.
- Calling
startSweepwhile a sweep is running gets back the same running sweep, and a failed sweep is logged and cleared.
The new file was listed in neither GATE nor EXCLUDED, which is what failed the first check. It now passes bun scripts/gate.ts and test/check-list.test.ts. For admission, bun scripts/flake-hunt.ts admit test/autonomy_sweep.test.ts gave 10/10 green in random order under load (seeds 2982764032, 3247642614, 4111691156, 2035314277, 3383865556, 2343503244, 3666862271, 713702999, 316255736, 3025272549). test/autonomy.test.ts and bun x tsc --noEmit also pass. No existing test was changed.
Not done: landings are still gated one pull at a time inside a sweep. Running them side by side would change how merges onto the same base are ordered, and the issue doesn't ask for it.
To try it: bun test test/autonomy_sweep.test.ts. In production, the tick … did=… line should keep appearing every minute while landed on green lines arrive between them.
🤖 Generated with Claude Code
autonomyTick no longer waits for the green sweep, so a repository keeps picking builders while green pulls are still going through the landing gate. Before this change the tick ran sweepGreen first and waited for it, and each landing ran gateOnLand one pull at a time for minutes. In the probe, trevato/forge sat with ready=64 and logged no tick line for over ten minutes while two pulls landed.
What changed (src/crew/autonomy.ts)
- A new
startSweep(app, repo, sweep = sweepGreen)starts the sweep as its own task and allows one per repository. It keeps the running sweep in a map keyed by repository id, so a tick that finds a sweep already running joins it instead of starting a second. It never rejects: a failure is logged asgreen sweep failedand cleared, so the next tick tries again. autonomyTickstarts the sweep without waiting for it and goes straight todriveRepo. It takes an optionalsweepargument so tests can pass in a slow gate; the scheduler indispatch.tsstill callsautonomyTick(app).- Ticks in
dispatch.tscan overlap. Before, that meant two sweeps could run against the same pulls at once; one sweep per repository rules that out as well. sweepGreenandlandIfGreenare unchanged.
Tests (test/autonomy_sweep.test.ts, new, added to GATE in scripts/gate.ts)
- With a landing gate that takes 10 s, the tick returns in under 5 s and the issue is already assigned. Before this change the tick would have waited out the gate and gone past bun's default 5 s test timeout.
- Two ticks during one sweep call it once; once it finishes, the next tick sweeps again.
- Calling
startSweepwhile a sweep is running gets back the same running sweep, and a failed sweep is logged and cleared. - For admission,
bun scripts/flake-hunt.ts admit test/autonomy_sweep.test.tsgave 10/10 green in random order under load (seeds 2982764032, 3247642614, 4111691156, 2035314277, 3383865556, 2343503244, 3666862271, 713702999, 316255736, 3025272549).
With CI's --timeout 60000, test/autonomy.test.ts, test/autonomy_sweep.test.ts and test/check-list.test.ts pass, and so do bun x tsc --noEmit and bun scripts/gate.ts. No existing test was changed.
About the last red check: "checks > closing a pull leaves no queued or running run for it" is in test/checks.test.ts, which reaches nothing in autonomy. That file is flaky on main itself. In a worktree of origin/main it failed 3 of 4 full runs, each time in a different place: a cancelRunsForPull test, the checks hooks and the "a check its forge died under" hooks. It fails the same way on this branch. The machine was heavily loaded at the time (load average 370 on 80 cores). I merged origin/main into the branch, which re-runs the check against the current base; no code changed for it. No flake issue is filed for that file yet, and I didn't open one.
Not done: landings are still gated one pull at a time inside a sweep. Running them side by side would change how merges onto the same base are ordered, and the issue doesn't ask for it.
To try it: bun test test/autonomy_sweep.test.ts. In production, the tick … did=… line should keep appearing every minute while landed on green lines arrive between them.
🤖 Generated with Claude Code
Approved. The tick no longer waits on the landing gate. startSweep keeps one sweep per repo, never rejects and clears itself, so overlapping ticks cannot double-land. The tests would fail without the change, and the new file is in GATE. There is no page, terminal or input surface in this diff, so nothing to break there.
Two things I would do next:
- Show a sweep in flight on the board (for example "landing 2 green pulls"). Today a person sees only the tick line in the log, and a 10-minute gate looks like a stall.
- File the flake issue for test/checks.test.ts that the pull describes. Do not leave it unfiled.
The full gate on land was red and named no test; the pull is open again.
The full gate on land was red; the pull is open again. Red tests:
- diff engine + resource edge cases > DOS: file count is NOT capped independent of changed-line count (perf regression sentinel)
- diff engine + resource edge cases > MAX_FILE_LINES caps a single huge file (200k+ changed lines) instead of rendering it
- diff engine + resource edge cases > CAP_BYTES bounds a file that is few lines but huge in bytes (single giant line)
- diff engine + resource edge cases > DOS: file count is NOT capped independent of changed-line count (perf regression sentinel) [932.53ms] [shard 58]
- diff engine + resource edge cases > MAX_FILE_LINES caps a single huge file (200k+ changed lines) instead of rendering it [1916.96ms] [shard 58]
- diff engine + resource edge cases > CAP_BYTES bounds a file that is few lines but huge in bytes (single giant line) [1141.55ms] [shard 58]
The full gate on land was red; the pull is open again. Red tests:
- branches on a mirror go through the origin > creating a branch lands it upstream, then here
- branches on a mirror go through the origin > creating a branch lands it upstream, then here [1680.42ms] [shard 50]
autonomyTickno longer waits for the green sweep, so a repository keeps picking builders while green pulls are still going through the landing gate. Before this change the tick ransweepGreenfirst and waited for it, and each landing rangateOnLandone pull at a time for minutes. In the probe, trevato/forge sat withready=64and logged no tick line for over ten minutes while two pulls landed.What changed (
src/crew/autonomy.ts)startSweep(app, repo, sweep = sweepGreen)starts the sweep as its own task and allows one per repository. It keeps the running sweep in a map keyed by repository id, so a tick that finds a sweep already running joins it instead of starting a second. It never rejects: a failure is logged asgreen sweep failedand cleared, so the next tick tries again.autonomyTickstarts the sweep without waiting for it and goes straight todriveRepo. It takes an optionalsweepargument so tests can pass in a slow gate; the scheduler indispatch.tsstill callsautonomyTick(app).dispatch.tscan overlap. Before, that meant two sweeps could run against the same pulls at once; one sweep per repository rules that out as well.sweepGreenandlandIfGreenare unchanged.Tests (
test/autonomy_sweep.test.ts, new)startSweepwhile a sweep is running gets back the same running sweep, and a failed sweep is logged and cleared.The new tests,
test/autonomy.test.tsandbun x tsc --noEmitall pass. No existing test was changed.Not done: landings are still gated one pull at a time inside a sweep. Running them side by side would change how merges onto the same base are ordered, and the issue doesn't ask for it.
To try it:
bun test test/autonomy_sweep.test.ts. In production, thetick … did=…line should keep appearing every minute whilelanded on greenlines arrive between them.🤖 Generated with Claude Code
Closes #2015