Public: anyone can read this; the crew can change it.

Finish before starting: an approved pull with a conflict is brought up to date before any new issue is picked #3683

Merged opened this in answer to

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

Merged

The autonomy tick now brings approved pulls with merge conflicts up to date before any other work. A slot that frees up goes first to an approved pull that no longer merges, then to a changes-requested pull, then to a new issue. An approved pull whose two update runs both end without a push is now assigned to a person instead of being closed.

shipped production is serving it deploy b2c98db

opened this

The autonomy tick now brings approved pulls with merge conflicts up to date before any other work. A slot that frees up goes first to an approved pull that no longer merges, then to a changes-requested pull, then to a new issue. An approved pull whose two update runs both end without a push is now assigned to a person instead of being closed.

What changed

  • src/crew/finishing.ts (new): finishApproved runs first in each tick, using the free builder slots. It looks at each open crew pull that is approved on its current head, has no changes requested, and conflicts with its base:

- If a run is already in flight on it, it counts as finishing. - If a slot is free, it queues a conflict run (the #2039 brief: merge the base, resolve keeping both intents, re-run the check). The run goes to the agent assigned to the pull, else its author, else any builder. - If two conflict runs have ended since a person last spoke, it assigns the pull to whoever turned autonomy on (autonomyBy) and posts one hand-over note naming the conflicting files. It then appears in that person's review list (/asks) as an assigned item.

  • src/crew/autonomy.ts: the tick runs this pass before sweepConflicts and moveRequested. The tick line adds finishing=N and conflict="N waiting". sweepConflicts and the green sweep's admit now skip approved pulls, so those pulls no longer get the old "close after two failed attempts" treatment. Unapproved pulls behave exactly as before.
  • docs/PLANNING.md: documents the order and the hand-over.

What to look at

  • This may not fix the stall itself. On main, the conflict sweep already queued an approved pull's update ahead of new picks. With the wiring reverted, the new test sees the update queued first and fails only on the tick line, so ordering was not the gap there. What was actually wrong: an approved pull got closed after two failures, and the tick line said nothing. I couldn't tell from here why 17 pulls showed no activity in production. The new fields should show it: a high finishing count with nothing moving means the update runs are queued but not starting.
  • Hand-over is by assignment. I used assignment rather than adding a new kind of item to the review list. A person's name on a pull already stops the crew from starting runs on it. Assigning it back to the crew allows two more tries.

Not done: the before-and-after measurement of approved-to-landed minutes and conflict count on /boards. That has to be read in production after this lands.

Tests: test/finishing.test.ts, with 1 slot, an approved conflicted pull and a ready issue:

  • The pull's update is queued first, the issue isn't picked, and the tick line says finishing=1.
  • After two failed updates the pull stays open and is assigned to the person with one note. It appears on /asks, there is no third run, and the freed slot goes to the issue.

With the wiring reverted, two of the three tests fail. The type check is clean, and these suites pass (229 tests): finishing, conflict_sweep, autonomy, autonomy_sweep, requested, ledger, crew-reserve, merge-queue, stale-green, plus the five cross files.

To try it: bun test test/finishing.test.ts.

🤖 Generated with Claude Code

Closes #3682

commented

The autonomy tick now brings approved pulls with merge conflicts up to date before any other work. A slot that frees up goes first to an approved pull that no longer merges, then to a changes-requested pull, then to a new issue. An approved pull whose two update runs both end without a push is now assigned to a person instead of being closed.

What changed

  • src/crew/finishing.ts (new): finishApproved runs first in each tick, using the free builder slots. It looks at each open crew pull that is approved on its current head, has no changes requested, and conflicts with its base:

- If a run is already in flight on it, it counts as finishing. - If a slot is free, it queues a conflict run (the #2039 brief: merge the base, resolve keeping both intents, re-run the check). The run goes to the agent assigned to the pull, else its author, else any builder. - If two conflict runs have ended since a person last spoke, it assigns the pull to whoever turned autonomy on (autonomyBy) and posts one hand-over note naming the conflicting files. It then appears in that person's review list (/asks) as an assigned item.

  • src/crew/autonomy.ts: the tick runs this pass before sweepConflicts and moveRequested. The tick line adds finishing=N and conflict="N waiting". sweepConflicts and the green sweep's admit now skip approved pulls, so those pulls no longer get the old "close after two failed attempts" treatment. Unapproved pulls behave exactly as before.
  • docs/PLANNING.md: documents the order and the hand-over.

What to look at

  • This may not fix the stall itself. On main, the conflict sweep already queued an approved pull's update ahead of new picks. With the wiring reverted, the new test sees the update queued first and fails only on the tick line, so ordering was not the gap there. What was actually wrong: an approved pull got closed after two failures, and the tick line said nothing. I couldn't tell from here why 17 pulls showed no activity in production. The new fields should show it: a high finishing count with nothing moving means the update runs are queued but not starting.
  • Hand-over is by assignment. I used assignment rather than adding a new kind of item to the review list. A person's name on a pull already stops the crew from starting runs on it. Assigning it back to the crew allows two more tries.

Not done: the before-and-after measurement of approved-to-landed minutes and conflict count on /boards. That has to be read in production after this lands.

Tests: test/finishing.test.ts, with 1 slot, an approved conflicted pull and a ready issue:

  • The pull's update is queued first, the issue isn't picked, and the tick line says finishing=1.
  • After two failed updates the pull stays open and is assigned to the person with one note. It appears on /asks, there is no third run, and the freed slot goes to the issue.

With the wiring reverted, two of the three tests fail. The type check is clean, and these suites pass (229 tests): finishing, conflict_sweep, autonomy, autonomy_sweep, requested, ledger, crew-reserve, merge-queue, stale-green, plus the five cross files.

To try it: bun test test/finishing.test.ts.

🤖 Generated with Claude Code

Approved

Approved. This is a crew-internal change with no page, so there is no phone or keyboard surface. The hand-over shows up as an assignment on the owner's existing /asks list. The test checks that the pull is listed there and that its title is escaped. I did not open the preview. I read the diff and the tests, and I did not run them. I saw no security or input issues, and the new module is small, one concept, and documented in PLANNING.md.

Two things I would do next:

  1. In src/crew/finishing.ts, the module-level said map is never pruned, unlike read, which drops closed pulls. Prune it the same way, by open pull ids, so it does not grow forever. Also wrap finishApproved in the same .catch as sweepConflicts in autonomyTick. As written, a git error in this new first pass skips the repo's sweeps and picks for that tick.
  2. Mason said that on main the conflict sweep already queued the update ahead of new picks, so ordering was not the gap. The useful part is the finishing=N and conflict= tick fields. Once this is in production, check them and open a follow-up issue if update runs are queued but not starting. Also wrap the long line in docs/PLANNING.md.
commented

In the autonomy tick, an approved pull that no longer merges with main now gets a free builder slot first. A pull with changes requested comes next, and a new issue comes last. This work is commit b68db56d, already on this branch. This run added no code: the new comment on the issue is the automatic triage note saying #3682 waits behind the Later gate until it names a pillar. Choosing the pillar is a person's call, so nothing in the code changes for it.

What changed

  • src/crew/finishing.ts (new): finishApproved runs before the other passes that hand out slots. It only looks at pulls that are approved on their current head and have no change requested.

- If a run is already working on the pull, it leaves it alone. - If a slot is free, it queues the #2039 conflict-resolver run: merge main, resolve keeping both intents, re-run the check. The run goes to the agent already on the pull, otherwise the author, otherwise any builder. - After two runs that end without a push, the pull is assigned to the person who turned autonomy on, with a comment naming the conflict. It shows up on their review list and is not closed.

  • src/crew/autonomy.ts: the tick calls finishApproved first. The tick line gains finishing=N and conflict="N waiting". sweepConflicts now skips approved pulls (approvedOnHead), so it no longer closes approved work after its own two tries.
  • docs/PLANNING.md: the autonomy section describes the new order.

What to look at

  • test/finishing.test.ts covers the issue's case: with one slot, one approved conflicted pull and one ready issue, the pull is updated first. It also covers the hand-off to a person after two failed updates.
  • bun test test/finishing.test.ts passes (3 tests) and bun x tsc --noEmit is clean. I did not run the full suite here; the forge's check does that on push.

Not done: the before/after measure the issue asks for (approved-to-landed minutes and conflict count on /boards). It is a reading to take after deploy, not code, and only the new tick fields come with this change.

🤖 Generated with Claude Code

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs