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

A stale green holds back the inbox's look ask and disables the merge button (after #1179) #2288

Merged opened this

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

Merged

A stale green no longer asks for a look in the inbox, and the pull page no longer offers a merge for it. I'm pushing this again unchanged in substance, because the earlier red looks unrelated to my change.

shipped production is serving it deploy f0961d3

opened this

A stale green no longer asks for a look in the inbox, and the pull page no longer offers a merge for it. I'm pushing this again unchanged in substance, because the earlier red looks unrelated to my change.

The check failed on "apps: identity, and a deploy that never answers > a deploy that never answers leaves servingAt null". That test is about app deploys and touches nothing I changed. It passes here on this branch and on a fresh merge of current main, so it was probably a timing flake on a busy check lane. I did not edit it.

This push merges the newer main (0.7.154) into the branch. bun x tsc --noEmit is clean. check-stale-gate, check-stale-wiring and apps-identity pass. I did not run the full suite.

  • Asks (src/web/studio/asks.ts): the look and review asks skip a pull whose green was checked against an older base. They come back when a re-check passes against the current base.
  • Base tip (src/crew/stale_asks.ts): the stale-ask sweep now also records each pull's base tip, including in autonomous repositories, where it only reads the tip. staleGreen() compares that tip with the check's baseOid using checkStale.
  • Sweep lag: the ask drops after the next sweep, not the instant the base moves. A tip the sweep has not read yet counts as not stale.
  • Merge box (src/web/pages/pull.ts): with requireChecks set, a stale green reads "Waiting on checks", "This head was checked against an older <base>; checking again", and Merge pull request is disabled. The page reads the base live.
  • Tests: test/check-stale-gate.test.ts runs green → main moves → re-check green. The "main moves" test fails without the src change.

Left out: mergePull still does not refuse a stale green, since the issue only asked for the page and asks to follow the gate.

Closes #2028

commented

A stale green no longer asks for a look in the inbox, and the pull page no longer offers a merge for it. I'm pushing this again unchanged in substance, because the earlier red looks unrelated to my change.

The check failed on "apps: identity, and a deploy that never answers > a deploy that never answers leaves servingAt null". That test is about app deploys and touches nothing I changed. It passes here on this branch and on a fresh merge of current main, so it was probably a timing flake on a busy check lane. I did not edit it.

This push merges the newer main (0.7.154) into the branch. bun x tsc --noEmit is clean. check-stale-gate, check-stale-wiring and apps-identity pass. I did not run the full suite.

  • Asks (src/web/studio/asks.ts): the look and review asks skip a pull whose green was checked against an older base. They come back when a re-check passes against the current base.
  • Base tip (src/crew/stale_asks.ts): the stale-ask sweep now also records each pull's base tip, including in autonomous repositories, where it only reads the tip. staleGreen() compares that tip with the check's baseOid using checkStale.
  • Sweep lag: the ask drops after the next sweep, not the instant the base moves. A tip the sweep has not read yet counts as not stale.
  • Merge box (src/web/pages/pull.ts): with requireChecks set, a stale green reads "Waiting on checks", "This head was checked against an older <base>; checking again", and Merge pull request is disabled. The page reads the base live.
  • Tests: test/check-stale-gate.test.ts runs green → main moves → re-check green. The "main moves" test fails without the src change.

Left out: mergePull still does not refuse a stale green, since the issue only asked for the page and asks to follow the gate.

Changes requested — before the latest push

The page and the inbox are right and the test covers green, main moves, re-check. One door was missed: the terminal. src/tui/screens/pull.ts:474 gates the merge on check.state !== "ok" only, so on a stale green the page disables Merge pull request while m in the terminal still lands it. checkOld is already computed there at line 282, so fix this first: checksGated = requireChecks && (check.state !== "ok" || checkOld), show the same wording, and add a tty test that fails without it. Smaller: the pull text says the review ask skips stale greens, but only the look and autonomous-land branches changed. Say which, or cover review. The inbox ask drops only after the next sweep, and the README does not mention the new behaviour. Add a line. Leaving mergePull ungated is a defensible choice, but then API and MCP merges bypass the gate, so open an issue for it. I did not view the preview screenshots or curl the preview.

commented

A stale green no longer gets a merge from any door that renders one: the page and the terminal now read one shared check, and the inbox asks wait.

I ran bun x tsc --noEmit and the stale-check, tui-apps and tui-screens tests, which pass; I did not run the full suite. I didn't view the preview or curl it.

  • Shared predicate: checksHold(requireChecks, state, stale) in src/checks/stale.ts now decides the checks gate for both the page (mergeBox) and the terminal (checksGated).
  • Terminal: on a stale green the merge box reads "Waiting on checks: checked against an older base; checking again". m is refused with the same reason and nothing lands. It uses the checkOld value already computed on that screen.
  • Terminal test: test/check-stale-gate.test.ts has a new tty test. It presses m on a stale green and asserts the older-base wording, no "Ready to merge", and the pull still unmerged. It fails without the terminal change. The re-check step also asserts the terminal shows "Ready to merge" again.
  • Which asks skip a stale green: the look ask for non-autonomous repositories, and the review ask for autonomous ones (kind: "review" is only produced in the autonomous branch). I corrected my earlier wording, which said both skip it everywhere.
  • Sweep lag and README: I added a README line saying the inbox ask drops after the next sweep rather than the moment the base moves. It also names the page, terminal and ask behaviour and says API and MCP merges are not held.
  • mergePull ungated: I kept it ungated and opened #2290 to refuse a stale green there when requireChecks is set.
Changes requested — before the latest push

The gate itself is right and well shared (checksHold feeds page and terminal; the test fails without the change). One thing to fix first: the copy promises a re-check that nothing in this change starts. The page says "checking again" and the terminal says "checked against an older base; checking again", but I found nothing that queues a new check when the base moves (only requeue of abandoned runs). With require_checks on, a stale green then disables Merge pull request until someone pushes to the branch, and the inbox look ask never returns. A person on a phone sees a dead button with a false promise. Either make the base moving queue a re-check of open pulls whose green is stale (and test it), or change the wording to say what to do (push or re-run the check) and give a way to ask for the re-check from the page and from src/tty.ts. Smaller: the nested ternary in drawMergeBox in src/tui/screens/pull.ts is left mis-indented after your insertion; and the ask side lags by one sweep while the page is live, so the inbox can briefly offer a look the page then shows as waiting. mergePull ungated is tracked in #2290, fine.

commented

I took the reviewer's second option. The copy no longer promises a re-check, and both doors now give a way to ask for one. A stale green still waits for a person to ask for the re-check. I did not make a base move queue a re-check on its own, so nothing re-runs until someone asks.

bun x tsc --noEmit is clean and check-stale-gate, check-stale-wiring, tui-apps and pull-check-again pass. I did not run the full suite.

  • Page: the merge box reads "Waiting on checks. This head was checked against an older <base>. Use Check again to judge it on the current base; the merge unlocks when that passes." The page already had the Check again button, and the test now asserts it is present.
  • Terminal: the terminal had no way to ask for a check. C now calls askCheck, the same call the page's button and the API use, and shows a toast. The merge box and the refusal for m say "press C to check again", and C is in the key hints. The test presses C and expects the toast. No check service runs in that test, so it sees the "no check was asked for" refusal, which shows the key reaches askCheck.
  • Indentation: I fixed the mis-indented nested ternary in drawMergeBox.
  • Inbox lag: I left this as it is. The inbox ask follows the stale-ask sweep while the page reads the base live, so the inbox can briefly offer a look the page then shows as waiting. The README states the lag. Closing it would mean resolving the base tip for every pull on the request path, which the issue warned against.
  • Auto re-queue: making a base move queue re-checks for every open green pull would be a separate change. It would spend check capacity on every merge to main, which seems like a decision for a person. Say so if you want it.
Approved — before the latest push

Approved. One predicate (checksHold) now drives the page and the terminal. The look/review asks skip a stale green. The disabled button says why and offers Check again. The tty gets C, the same askCheck the page uses. The new test fails without the src change, covers both doors, and the README states the sweep lag and the ungated API/MCP merge (#2290). I read the diff and tests only; I did not curl the preview or view the screenshots.

Two things I would do next:

  1. Close the dead end. A stale green now drops out of the inbox with no ask and no re-check queued, so the owner has to remember to open the pull and press Check again. Queue the re-check when the sweep sees a green go stale, or surface a one-tap ask in the inbox (pillar 1: decide, then leave).
  2. Name the C key in the README next to the checks paragraph, and make mergePull itself refuse a stale green (#2290) so API and MCP merges match the page and terminal.
commented

I merged main into the branch and pushed.

The only conflict was in the import block of src/web/pages/pull.ts. main added checkWords and this branch adds checksHold, so I kept both.

bun x tsc --noEmit is clean. These tests pass:

  • check-stale-gate
  • check-stale-wiring
  • tui-apps
  • pull-checks-line
  • pull-check-again

I did not run the full suite.

Approved

Approved from the diff; I did not run the preview or run the tests. The page and the terminal now read one checksHold answer, so a stale green disables Merge pull request on the page and refuses m in the terminal. The inbox look and review asks wait for the re-check. The terminal gains C, which calls the same askCheck as the page button, and the copy points to it. The test covers green, then main moves, then a re-check green, on the page, the inbox and the terminal.

Two things I would do next:

  1. Make mergePull refuse a stale green when requireChecks is set (#2290). Today API and MCP merges bypass a gate the page and terminal enforce. The README states this.
  2. Close the inbox lag. The ask follows the sweep while the page reads the base live, so a look can briefly be offered that the page then shows as waiting. Re-checking the base tip when the inbox row is opened would fix it without adding work to every request.

One gap in tests: the C test only asserts the refusal toast, because no check service runs there. Add one case where the check is accepted.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs