mirror of
https://github.com/Comfy-Org/github-workflows.git
synced 2026-11-05 00:17:37 +00:00
[PR #360] [MERGED] fix(cursor-review): gate a delta re-raise on an earlier round's open thread even without repeat_of #362
Labels
No labels
cursor-review-catalog-drift
groom
groom
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Comfy-Org/github-workflows#362
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/Comfy-Org/github-workflows/pull/360
Author: @mattmillerai
Created: 10/7/2026
Status: ✅ Merged
Merged: 10/7/2026
Merged by: @mattmillerai
Base:
main← Head:be-19480-gate-unmarked-reraises📝 Commits (3)
29b44a3fix(cursor-review): gate a delta re-raise on an earlier round's open thread even without repeat_of06d8514Merge origin/main into be-19480-gate-unmarked-reraisesb4491abfix(cursor-review): gate delta re-raises on post-review's one pre-post thread snapshot📊 Changes
7 files changed (+291 additions, -10 deletions)
View changed files
📝
.github/cursor-review/README.md(+1 -1)📝
.github/cursor-review/auto-approve.py(+110 -2)📝
.github/cursor-review/gate-unresolved.py(+6 -0)📝
.github/cursor-review/post-review.py(+16 -1)📝
.github/cursor-review/tests/test_auto_approve.py(+145 -0)📝
.github/workflows/cursor-review.yml(+12 -5)📝
docs/callers/cursor-review.md(+1 -1)📄 Description
ELI-5
On review rounds after the first,
approve_scope: deltalets the bot approve even when an old finding outside the new changes is still open. Re-raising a finding that is still open was supposed to block. It only did so when the judge linked the old thread (repeat_of), and the judge only links threads someone has already answered. An unanswered finding could therefore come back every round and the bot kept approving anyway. Now the bot checks where the finding sits: if it lands on the same file and line as an earlier round's thread that is still open, it blocks.What changed
Of the three options, this PR takes option 2 (structural match, no model trust).
gate-unresolved.py: the sharedreviewThreadsquery now also fetches each thread'spath,lineandstartLine. These are additive fields.auto-approve.py:earlier_thread_anchors()is pure. It collects{path: [(start, line)]}for every open (unresolved, non-outdated) cursor-review thread in the list it is given.with_open_anchors()reads the threads (only underdelta) with a 90s wall-clock budget and adds the anchors to the scope.gating_reason()returns "on an unresolved earlier thread's line" for a finding inside one of those anchors.cmd_decideno longer reads threads for this. It gates on post-review's snapshot (--open-anchors), so marking and gating come from one read. A snapshot that is missing, malformed or for another commit makes the round fail closed tofull.post-review.pyload_non_gating(): it reads the anchors before posting, so every thread in the snapshot is from an earlier round and no head-SHA filter is needed. A gating re-raise is posted without the non-gating marker, and the snapshot is saved for decide (--open-anchors-out). A failed or over-budget read (including theSystemExit(2)fromrun_graphql) marks nothing and leaves no snapshot, so decide usesfulltoo.cursor-review.yml: passes/tmp/open-anchors.jsonfromPost reviewtoAuto-approve decision. These are steps in the same job.approve_scoperow indocs/callers/cursor-review.md, the inputs table in.github/cursor-review/README.md, and the workflow input description now say that a re-raise gates either byrepeat_ofor by landing on the path and line of an earlier round's still-open thread, and that an unreadable list of earlier threads fails closed tofull.main, which brings inapprove_authors(#358) and the approve_scope review fixes (#359). Main's rule that an empty or unparseable incremental block fails closed tofulltakes precedence.Judgment call: the match covers any open earlier-round cursor-review thread, not only threads carrying the non-gating marker. That is a superset of what the ticket asked for, and it is what the docs already promised ("re-raises an earlier finding whose thread is still unresolved"). For an unmarked thread above the threshold, the open-thread check already blocks, so nothing changes there. The only new case is a below-threshold earlier thread re-raised above the threshold outside the delta, which now gates. That is the fail-closed direction.
Provenance
.github/cursor-review/testspasses (1023 tests),.github/cursor-approve/testspasses (149), and.github/workflow-pins/testspasses, all on the current headrepeat_ofAPPROVEs without the anchors and gets REQUEST_CHANGES with them. It also gates when the thread was opened on the reviewed head itself (head reset) or has a nulloriginalCommitfull, and a failed post-review read removes any stale snapshot. The walk budget is testedcheck_workflow_pins.py(including the input-drift harness),check_agents_md.pyandcheck-org-repo-literals.shall passdeltaround against a real PRResidual
linealong) still has norepeat_ofand is not matched, so it stays non-gating underdelta. Closing that would need either a line-proximity window or option 1 (the judge emitsrepeat_offor unanswered re-raises too). Both are design choices left for a follow-up.deltaround was run against a GitHub PR. The new GraphQL fields (path,line,startLineonPullRequestReviewThread) are verified only by mocked tests. If the read fails on the first realdeltaround, the decision note will show "post-review's earlier open-thread snapshot is unavailable, so the round fails closed tofull".delta, post-review makes one additional paginatedreviewThreadswalk per round, capped at 90s. decide makes none.🤖 Generated with Claude Code
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.