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

Merged opened this in answer to

Check · Review · Land · Live done — Landed and live in production.

Merged

`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

opened this

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 as green sweep failed and cleared, so the next tick tries again.
  • autonomyTick starts the sweep without waiting for it and goes straight to driveRepo. It takes an optional sweep argument so tests can pass in a slow gate; the scheduler in dispatch.ts still calls autonomyTick(app).
  • Ticks in dispatch.ts can overlap. Before, that meant two sweeps could run against the same pulls at once; one sweep per repository rules that out as well.
  • sweepGreen and landIfGreen are unchanged.

Tests (test/autonomy_sweep.test.ts, new)

  • 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 startSweep while a sweep is running gets back the same running sweep, and a failed sweep is logged and cleared.

The new tests, test/autonomy.test.ts and bun x tsc --noEmit all 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

Closes #2015

commented

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 as green sweep failed and cleared, so the next tick tries again.
  • autonomyTick starts the sweep without waiting for it and goes straight to driveRepo. It takes an optional sweep argument so tests can pass in a slow gate; the scheduler in dispatch.ts still calls autonomyTick(app).
  • Ticks in dispatch.ts can overlap. Before, that meant two sweeps could run against the same pulls at once; one sweep per repository rules that out as well.
  • sweepGreen and landIfGreen are 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 startSweep while 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

commented

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 as green sweep failed and cleared, so the next tick tries again.
  • autonomyTick starts the sweep without waiting for it and goes straight to driveRepo. It takes an optional sweep argument so tests can pass in a slow gate; the scheduler in dispatch.ts still calls autonomyTick(app).
  • Ticks in dispatch.ts can overlap. Before, that meant two sweeps could run against the same pulls at once; one sweep per repository rules that out as well.
  • sweepGreen and landIfGreen are 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 startSweep while 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.ts gave 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

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:

  1. 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.
  2. File the flake issue for test/checks.test.ts that the pull describes. Do not leave it unfiled.
commented

The full gate on land was red and named no test; the pull is open again.

commented

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]
commented

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]
Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs