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

A "stop" decision must not outlive the red check that caused it: re-decide when the pull's head turns green #544

Merged opened this in answer to

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

Merged

A failing check no longer keeps a pull from landing once a later check on it passes. The stuck pulls in the issue should go through the normal green path (review, then land) on the first tick after this deploys. The full `forge.json` check passes: types are clean and all 670 tests pass.

shipped production is serving it deploy d5b2fe2

opened this

A failing check no longer keeps a pull from landing once a later check on it passes. The stuck pulls in the issue should go through the normal green path (review, then land) on the first tick after this deploys. The full forge.json check passes: types are clean and all 670 tests pass.

Why they never landed. The decider's stop wasn't what held these pulls; landIfGreen never looked at it. #495 shows the real cause: its head has a failed check run and then a passing retry re-run on the same commit. landIfGreen refused the pull if any run on the head wasn't ok, so the old red blocked it forever. The ledger already recorded the stop's outcome as green.

What changed

  • src/core/runs.ts: new verdictForHead gives the newest run of each kind and environment on a head. A re-run replaces the red it was run for.
  • src/crew/autonomy.ts: landIfGreen judges the head by verdictForHead. It also refuses to land a pull whose stop is still in force.
  • src/core/decisions.ts: new stopStands says when a stop decision is still in force.

- A stop the crew took because of a failing check (the check is in the recorded state) ends once a check passes. That is either the ledger's green outcome, or a passing result that finished after the stop. The second case covers a newer head turning green after the re-run on the old head was red too. - Any other stop counts as a person's, and a passing check never lifts it.

  • src/web/studio/asks.ts: the studio's "stopped" card uses the same rule. A stop that a green check has answered no longer shows as "the decider stopped for you" if the check goes red again later. The 'needs you' count comes from this same list.

Tests

  • test/autonomy.test.ts: three cases.

- Same head: red, crew stop, green re-run, and sweepGreen lands the pull. - Newer head: red, stop, red re-run, then a newer head passes and the pull lands. - A person's stop: still held after a green check.

  • test/asks.test.ts: the stopped card for a crew stop disappears once a check on that head passes. In an assisted repository the pull shows as a look card instead.
  • Both new tests fail with their source change reverted. No existing test changed.

What to look at

  • No way to record a person's stop yet. Every retry decision in the ledger today comes from the crew, so the "a person's stop stays" rule is enforced but nothing writes one. A way for a person to record a stop would be separate work.
  • In assisted repositories the pull stays in 'needs you'. Once its stop is answered it moves from a "stopped" card to a "look" card, because a green pull there waits for a person. In autonomous repositories stopped cards were never shown.

🤖 Generated with Claude Code

Closes #542

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs