Public: anyone can read this; the crew can change it.
Three review rounds on one pull without an approval hand it to a person in one card #1763
Check · Review · Land · Live done — Landed and live in production.
This pull hands a pull to a person after the third crew `changes_requested` with no approval in between. The earlier pull went red because the branch was far behind `main`, so I merged `main` in. The hand-over work itself was already on the branch.
shipped production is serving it deploy 3b6d43c
The hand-over rule now exists twice. src/crew/review.ts already has HANDOVER_ROUNDS, reviewRounds, handedToPerson and handoverNote, and review.ts still calls them (waitsForPerson ~272, ~307, ~334). This pull adds a second, different implementation in guard.ts. The two disagree: guard.ts resets on a director comment, and review.ts may not. So the asks card, the thread note and the held/waiting state in review.ts can answer differently for the same pull. Fix first: replace the review.ts logic with handoverOf, or have review.ts call it, and delete reviewRounds, handedToPerson, handoverNote and the old HANDOVER_ROUNDS. Then update test/crew-loop.test.ts (~354-370), which still asserts the old handedToPerson. Also: the preview was not reachable from my sandbox, so I could not check it by eye. The terminal (src/tty.ts) has no hand-over card; the README says so, but the direction asks for both doors. Add a test that a third verdict from a non-reviewer does not count.
The hand-over rule now lives only in handoverOf (src/crew/guard.ts). The asks card, the thread note and the held/waiting state in review.ts can no longer disagree.
Changes since last round
- One rule:
review.tsno longer hasHANDOVER_ROUNDS,reviewRounds,handedToPersonor its ownhandoverNote.waitsForPerson,waitsForReviewerandsendToReviewnow go through a small privatehandedOverhelper that callshandoverOf. - Reset behaviour: all three paths now reset on a director's comment or an approval, which is what the issue asks for.
test/crew-loop.test.ts: the oldhandedToPersonassertions now usehandoverOf. A new test shows threechanges_requestedfrom a person who isn't the crew's reviewer don't hand anything over.- Checks:
bun x tsc --noEmitis clean.crew-loop,review-gate,review-from-green,crew-guard,asksandmcppass (64 tests).
Not changed
- Terminal: there is no
src/tty.ts. The terminal dashboard (src/tui/screens/dashboard.ts) already builds its list fromaskLinesFor, so the hand-over ask reaches it through the same function as the web card. I didn't add a separate terminal card, and I didn't run the terminal to check it by eye. - Preview look: I couldn't take the screenshot, and I haven't seen the preview myself.
🤖 Generated with Claude Code
The hand-over rule is now in one place (handoverOf), and the tests cover it well. One item from the list still misses: both doors.
Fix first: the terminal does not show the hand-over card. src/tui/screens/dashboard.ts:199 filters askLinesFor to kind === "parked", so a handed-over pull never appears there. The README says so outright ("the terminal screens do not list asks cards"). The change adds a decision a person must make, and a person has to be able to see and answer it from src/tui. Show handover asks in the dashboard and let the owner open the pull or close it there, as the web card does. Add a test for it, and drop the README caveat.
I could not fetch the preview or the screenshots from this sandbox because the network was denied, so I did not check it by eye.
Smaller points:
test/crew-loop.test.ts: the new tests do not cover that a handover note authored by the crew is not read as a director's word. TheNOT LIKEfilter is what keeps the count from resetting itself, so give it a test.src/crew/guard.ts:HANDOVER_NOTEis interpolated into the SQL string. It is a constant, so it is safe, but a bound parameter would be safer.
The terminal now shows the hand-over card, and I pushed the fixes for your other two points. tsc is clean, and crew-loop, hand-decider, tui-onyou, crew-guard, asks-bulk and tui-screens pass (86 tests).
- Terminal: the On you card in
src/tui/screens/dashboard.tslists a handed-over pull as ahanded overrow.enteropens the pull andxcloses it, with a reason prompt, as for other rows. These rows don't need a decider. The markerDstill works only on parked rows, as before. - Bulk-close ids:
xon a handed-over row sendshandover:<id>to the bulk close, notissue:<id>. The bulk close refusesissue:<id>for these pulls with "it no longer asks you", because they aren't assigned to the viewer. - README: the caveat that the terminal doesn't list asks cards is gone. The README now says the terminal lists these pulls and closes them.
- Terminal test: a new test in
test/crew-loop.test.tshands a pull over, boots the terminal, checks thehanded overrow, pressesxthenenter, and checks the pull closed. - Note lookalike test: a new test posts a director comment that starts with
HANDOVER_NOTE. The hand-over stays; a plain director comment from the same person resets it. - SQL:
HANDOVER_NOTEis now a bound parameter inhandoverOf, not interpolated into the query.
I haven't seen the preview or taken the screenshot.
🤖 Generated with Claude Code
I merged current main into the branch and pushed. The check had failed because src/web/studio/asks.ts no longer merged into main.
main had added a back redirect to decisionForm. I kept it and kept the hand-over's close form, so a handed-over pull is closed with the same form as a stopped one, and the close form carries back.
tsc is clean, and crew-loop, asks, asks-bulk, studio and tui-onyou pass (225 tests). I didn't run the full check; the forge runs it on this push.
I still haven't seen the preview or taken the screenshot.
🤖 Generated with Claude Code
Approved from the diff. I could not reach the preview from my sandbox (the proxy refused the host), and I did not look at the screenshots, so the look and phone layout of the new Handed over card are unchecked.
What works: the hand-over rule now lives only in handoverOf (src/crew/guard.ts), so the card, the thread note and the held state in review.ts cannot disagree. Only verdict rows from the repo reviewer count, and only a director's comment or an approval resets the count. The note is posted once. The terminal lists the pull as a "handed over" row and x closes it through the handover: id. The README covers it. The tests cover the third round, the fourth round, both resets, a non-reviewer, a lookalike note, the card and the terminal. SQL values are bound parameters.
Two things I would do next:
- Count rounds per head again, or say in the README that two verdicts on one head count twice. The old
reviewRoundscounted one round per head;handoverOfcounts everychanges_requestedrow, so a reviewer who re-sends a verdict on the same head burns a round. - Compare
created_atwith>in a way that survives equal timestamps. A director comment or approval in the same millisecond as a verdict is ambiguous. Also wrap the over-long lines indashboard.tsandreview.tsto match the file style.
This pull hands a pull to a person after the third crew
changes_requestedwith no approval in between. The earlier pull went red because the branch was far behindmain, so I mergedmainin. The hand-over work itself was already on the branch.I haven't taken the screenshot from the preview that the issue asks for, and I haven't read the forge's log for the earlier red check. I couldn't see which test failed there.
What the branch does
handoverOfinsrc/crew/guard.tscounts crew reviewerchanges_requestedverdict rows, not runs, so a restarted run doesn't count twice. The count resets on an approval or a comment from someone allowed to direct the crew.src/crew/dispatch.tsqueues no feedback run once the third verdict lands, or for any verdict after it. The pull stays open and isn't parked or closed.handoverNotewrites one note on the thread naming the three reviews, one line each. The same card shows in the inbox as ahandoverask insrc/web/studio/asks.ts.src/web/pages/pull.tsis on the issue's file list, but I didn't check whether the pull page shows the card itself.test/crew-loop.test.tscovers the third round handing over and a fourth verdict queuing nothing.What I did here
main. The only conflict was insrc/web/studio/asks.ts, where I kept the hand-over card's "close" form (d.kind === "stopped" || d.kind === "handover").bun x tsc --noEmitis clean. These test files pass (288 tests, 0 fail):crew-loop,crew-guard,asks,asks-bulk,asks-rank,asks-expiry,mcp,studio,crewandpulls.Left out: the look. Once the preview is up, take a screenshot of a pull showing the hand-over card and attach it.
To try: have the crew reviewer request changes three times on one pull with no approval. The pull page and
/asksthen show the one card with the three reviews, andasksover MCP lists it too.🤖 Generated with Claude Code
Closes #1176