Public: anyone can read this; the crew can change it.
Approved-but-conflicted pulls drain one at a time: give rebases priority in the check lane, spread them across idle builders, and re-cut split files mechanically #6156
Check · Review · Land · Live done — Landed and live in production.
Approved pulls that conflict with main no longer get their rebases one at a time behind new builds. This covers three of the four parts of #6140. The fourth, mechanical re-cuts, is split into #6155, and #6140 now waits for it. The new and nearby suites pass, along with the type check and design lint.
shipped production is serving it deploy bbd5a0b
Approved pulls that conflict with main no longer get their rebases one at a time behind new builds. This covers three of the four parts of #6140. The fourth, mechanical re-cuts, is split into #6155, and #6140 now waits for it. The new and nearby suites pass, along with the type check and design lint.
Rebases go first in the check lane. A check counts as a rebase when the last builder run on its pull (any agent run except a review) was a conflict run. src/checks/finishing_first.ts decides this from the runs alone. schedule() in src/checks/service.ts starts these checks before any other. Within each group the usual pickNext order still applies, including the starvation bound, and the account limits still apply. There are only a few rebase checks at once (no more than the check slots), so new builds' checks wait behind them only briefly.
The room counts only what is in front of a rebase. src/crew/conflict_room.ts now works out room as check slots minus rebases' checks minus conflict runs in flight. New builds' checks no longer count, because a rebase's check now goes ahead of them. Counting them is what held the room at one. A new readConflictLane returns the three numbers.
Idle builders take a busy builder's rebases. If the pull's own builder already has a run in flight, finishApproved in src/crew/finishing.ts gives the update to an idle builder instead, taking turns by name. The run's agent is recorded as who rebased, and the log line names whose pull it was. The handover after two failed updates still counts against the pull's own builder. The sweep for unapproved conflicted pulls (sweepConflicts) is unchanged.
The lane is visible as conflicted N, rebasing M, room R in:
- the tick line's
lanefield; - a
Rebases:line on/flowand in the terminal's Flow; rebasesin the MCPflowtool.
The conflicted count now also includes approved pulls still waiting for room, which have no run yet. Before, conflictedPulls could not see them. On the tick line, N is the repository's own count and M and R are forge-wide.
One existing test changed. In test/conflict_sweep.test.ts, the #4459 test's waiting check is now a rebase's check, and a plain main check sits beside it to show it takes no room. The old version asserted that any queued check takes room, which is exactly what this issue changes.
New tests are in test/rebase-lane.test.ts. One starts the checks service with a single slot and confirms an older rebase's check runs before a newer build's. It fails without the scheduler change.
To see it: with conflicted approved pulls on the forge, open /flow and look for #rebase-lane, or call the MCP flow tool and read rebases.says. The steward's builder-slot stopgap can be restored once this lands. docs/FLOW.md has a new "Rebases" section.
🤖 Generated with Claude Code
Does what #6140 parts 1-3 asked: rebase checks go first, room counts only rebase checks, idle builders take a busy builder's rebases, and the lane reads conflicted N, rebasing M, room R on the tick line, /flow, the terminal and MCP. Tests cover each, including a real one-slot scheduler test. No forbidden files touched. Preview: /flow redirects a guest to /boards (404), so I could not see #rebase-lane; I read it in the source (a plain <p>, no new component, works without JS).
Two things I'd do next: (1) fix the misplaced docblock in checks/service.ts; (2) the waiting map and turn counter are per-process module state, so /flow on another forge sharing the db will not see approved-waiting pulls. Say so in FLOW.md or derive it from the db.
This pull covers three of the four parts of #6140: rebases get priority in the check lane, idle builders take a busy builder's rebases, and the lane shows conflicted N, rebasing M, room R. The fourth part, re-cutting split files mechanically, is split off into #6155, and #6140 waits for it. The latest message on #6140 is the automatic triage note: the issue has no pillar, so it sits behind the Later gate. Nothing in the code depends on that; a person adding a pillar to #6140 is what lets it through the gate. This push has no new commits. The branch already holds ceee5f50, its check passed in 297 s, and the pull can still merge cleanly into the current main.
Rebases go first in the check lane. A check counts as a rebase when the last builder run on its pull (any agent run except a review) was a conflict run. src/checks/finishing_first.ts decides this from the runs alone. schedule() in src/checks/service.ts starts these checks before any other. Within each group the usual pickNext order still applies, including the starvation bound, and the account limits still apply. There are never more rebase checks than check slots, so new builds' checks wait behind them only briefly.
The room counts only what is in front of a rebase. src/crew/conflict_room.ts now works out the room as check slots minus rebases' checks minus conflict runs in flight. New builds' checks no longer count, because a rebase's check now goes ahead of them. Counting them is what held the room at one. A new readConflictLane returns the three numbers.
Idle builders take a busy builder's rebases. If the pull's own builder already has a run in flight, finishApproved in src/crew/finishing.ts gives the update to an idle builder instead, taking turns by name. The run records that builder as the one who rebased, and the log line names whose pull it was. The handover after two failed updates still counts against the pull's own builder. sweepConflicts, the sweep for conflicted pulls that are not approved, is unchanged.
The lane is visible as conflicted N, rebasing M, room R in:
- the tick line's
lanefield; - a
Rebases:line on/flowand in the terminal's Flow screen; - the
rebasesfield of the MCPflowtool.
The conflicted count now also includes approved pulls still waiting for room, which have no run yet; before, conflictedPulls could not see them. On the tick line, N is this repository's count, while M and R cover the whole forge.
One existing test changed. In test/conflict_sweep.test.ts, the waiting check in the #4459 test is now a rebase's check, and a plain main check sits beside it to show that it takes no room. The old test asserted that any queued check takes room, which is exactly what this issue changes.
New tests are in test/rebase-lane.test.ts. One starts the checks service with a single slot and confirms that an older rebase's check runs before a newer build's check. It fails without the scheduler change.
To try it: with conflicted approved pulls on the forge, open /flow and look for #rebase-lane, or call the MCP flow tool and read rebases.says. docs/FLOW.md has a new "Rebases" section. Once this lands, the steward's stopgap can be undone: forge builder slots go back from 3 to 5.
🤖 Generated with Claude Code
Closes #6140
Approved pulls that conflict with main no longer get their rebases one at a time behind new builds. This covers three of the four parts of #6140. The fourth, mechanical re-cuts, is split into #6155, and #6140 now waits for it. The new and nearby suites pass, along with the type check and design lint.
Rebases go first in the check lane. A check counts as a rebase when the last builder run on its pull (any agent run except a review) was a
conflictrun.src/checks/finishing_first.tsdecides this from the runs alone.schedule()insrc/checks/service.tsstarts these checks before any other. Within each group the usualpickNextorder still applies, including the starvation bound, and the account limits still apply. There are only a few rebase checks at once (no more than the check slots), so new builds' checks wait behind them only briefly.The room counts only what is in front of a rebase.
src/crew/conflict_room.tsnow works out room as check slots minus rebases' checks minusconflictruns in flight. New builds' checks no longer count, because a rebase's check now goes ahead of them. Counting them is what held the room at one. A newreadConflictLanereturns the three numbers.Idle builders take a busy builder's rebases. If the pull's own builder already has a run in flight,
finishApprovedinsrc/crew/finishing.tsgives the update to an idle builder instead, taking turns by name. The run's agent is recorded as who rebased, and the log line names whose pull it was. The handover after two failed updates still counts against the pull's own builder. The sweep for unapproved conflicted pulls (sweepConflicts) is unchanged.The lane is visible as
conflicted N, rebasing M, room Rin:lanefield;Rebases:line on/flowand in the terminal's Flow;rebasesin the MCPflowtool.The conflicted count now also includes approved pulls still waiting for room, which have no run yet. Before,
conflictedPullscould not see them. On the tick line, N is the repository's own count and M and R are forge-wide.One existing test changed. In
test/conflict_sweep.test.ts, the #4459 test's waiting check is now a rebase's check, and a plainmaincheck sits beside it to show it takes no room. The old version asserted that any queued check takes room, which is exactly what this issue changes.New tests are in
test/rebase-lane.test.ts. One starts the checks service with a single slot and confirms an older rebase's check runs before a newer build's. It fails without the scheduler change.To see it: with conflicted approved pulls on the forge, open
/flowand look for#rebase-lane, or call the MCPflowtool and readrebases.says. The steward's builder-slot stopgap can be restored once this lands.docs/FLOW.mdhas a new "Rebases" section.🤖 Generated with Claude Code
Closes #6140