skills(running-tend): carry a superseded PR's findings into its successor's review - #421
skills(running-tend): carry a superseded PR's findings into its successor's review#421dormouse-bot wants to merge 3 commits into
Conversation
…ssor's review A PR body saying "Supersedes #N" is common here, and the successor's review never fetches #N — bot-review-state.sh and the review skill's prior-review machinery are both scoped to the PR under review. Findings the bot already published on #N are therefore dropped, including a review it had to post as a plain comment because #N closed mid-session.
Deploying mouseterm with
|
| Latest commit: |
d895da6
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://9e1c3f77.mouseterm.pages.dev |
| Branch Preview URL: | https://daily-review-runs-3234813257.mouseterm.pages.dev |
dormouse-bot
left a comment
There was a problem hiding this comment.
The premise and the incident trace check out — #416's body does open Supersedes #398, and neither review run fetched #398. One gap in the recipe, though, and it bites on the exact PR the note is about.
GET /pulls/<N>/reviews returns review bodies only — a review's inline comments are a separate endpoint (/pulls/<N>/comments), the same trap running-in-ci calls out under "A review's inline comments are a separate fetch". On #398 the bot left 7 inline comments (6 on SELF_HOST.md, 1 on server/src/config.ts) that the two commands here return nothing for. Since the review skill makes inline suggestions mandatory for concrete fixes, inline is where most of a predecessor's actionable findings live — so a successor following this note verbatim would report "I re-checked #398" while having read none of them, which is worse than not fetching at all.
Two smaller things folded into the same suggestion: --paginate (the default page is 30, and a superseded PR is by definition a long thread), and dropping the dormouse-bot filter on the inline endpoint so the maintainer's replies come back with the findings. That last one matters for the "carry it forward" decision — a finding the maintainer answered in-thread on #N shouldn't be re-raised on #N+1, and a bot-only filter makes an answered finding indistinguishable from an ignored one.
Not approving because this is a self-authored PR — GitHub rejects self-approval — not because of the finding above.
`/pulls/<N>/reviews` returns review bodies only, and inline is where the review skill puts every concrete fix — on #398 that is 7 of the findings against 1 in a body. A successor following the recipe as written would report having re-checked the predecessor while having read almost none of it.
dormouse-bot
left a comment
There was a problem hiding this comment.
The three-fetch recipe holds up, and dropping the login filter on the inline endpoint is the part that makes it useful. One factual correction in the sentence that justifies it.
0 reviews is wrong for #398. GET /pulls/398/reviews returns two bot reviews with substantive bodies — 4958193149 (3.2k chars, opening on docs/specs/server.md's state enumeration) and 4958280791 (2.4k chars, the DORMOUSE_BIND_HOST verification) — both submitted 2026-08-18T07:0x, so they predate this commit and the recipe's --jq '.body' prints both. The count that actually holds is 1 conversation comment, 2 review bodies, 7 inline.
That doesn't weaken "all three, not a subset" — the 7 inline findings still reach a successor through nothing but the third fetch, which is the point. But a future session reading "the body endpoints return 0 reviews" has a written reason to skip a fetch that returns ~5.7k chars of findings, which is the exact failure mode this note exists to prevent. Suggestion inline.
Not approving because this is a self-authored PR — GitHub rejects self-approval — not because of the finding above.
When a PR body says "Supersedes #N", the successor's review never fetches #N —
bot-review-state.shand the review skill's prior-review machinery are both scoped to the PR under review — so findings the bot already published on #N are silently dropped. This adds arunning-tendnote telling the review to fetch the predecessor's bot comments and reviews and re-check each finding against the current diff. Verified against the #398 → #416 session logs, where exactly that happened: of three findings, one was adopted by the maintainer, one merged tomainunaddressed, and one was re-derived from scratch ten hours later.Docs-only, so no test. The root cause is generic rather than repo-specific, so the durable fix probably belongs in the bundled
reviewskill upstream — would you like me to file an issue atmax-sixty/tendfor it? The overlay note works in the meantime, since repo guidance takes precedence.The incident, traced
What happened.
tend-review32304083586 started on #398 at21:28:55Z; you closed the PR at21:31:54Z, about three minutes in. The session handled that correctly — it noticed, and at21:45:06Zposted its findings as a plain comment rather than a review, explicitly because the branch was still live and one finding was a production bug.You took the top one:
stillOurscomparing inode numbers alone, fixed in2bd97f09about two hours later (withdev+ctimeNs, which is better than thebirthtimeNsthe comment suggested).What the successor's review did. #416's body opens
Supersedes #398 with the final review fixes.Both review sessions read that body — it is in the tool output in each session log — and neither fetched #398:#398fetchedgh pr view 416,bot-review-state.sh 416,sed -n 1,200p peer-link.tsgh pr view 416 --json comments,reviews,body,bot-review-state.sh 416,cat -n peer-link.ts | sed -n '1,340p'The draft review closed with "Nothing else surfaced"; the full pass raised one unrelated inline suggestion; the PR was approved at
02:27:46Zand merged at03:00:53Z.Where the other two findings went.
ensureTokenadopting an empty token — merged tomainand still there. The full-pass session's file dump did include those lines (they are atpeer-link.ts:221, inside its1,340pwindow), but nothing in the session reasons about them; the only two occurrences ofensureTokenin that log are both insidecatoutput. Fixed in fix(vscode-ext): wait out a half-created peer token instead of adopting an empty one #420.service.tscomment pointing at a#lifecyclefield that never existed — rediscovered independently bytend-nightly32342390821 about ten hours later and fixed in fix(remote): reject an enroll response that is not an enrollment #418, at the cost of re-deriving it.Why an overlay note rather than nothing. This is structural, not a lapse: no decision point existed, because the predecessor is never in context. Replaying the same scenario produces the same result every time. It is also the shape that does not self-correct — a review that never sees the finding cannot flag it, and the only reason this one surfaced is that a
review-runssweep happened to read both threads.Adjacent upstream work, for whoever picks this up: max-sixty/tend#1014 adds a prior-rejection fetch to nightly/triage/ci-fix dedup. Same shape — a fact recorded on a closed PR that no later run fetches — but the opposite direction (there a rejection is lost, so work is redone; here a finding is lost, so a defect ships) and a different skill, so it does not cover this.