fix(prep): only a submitted verdict clears a live REQUEST_CHANGES #1249
No reviewers
Labels
No labels
bump
major
bump
minor
bump
patch
kind/bug
kind/chore
kind/docs
kind/feature
priority/critical
priority/high
priority/low
priority/medium
size/L
size/M
size/S
size/XL
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
frankenbit/release-toolkit!1249
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "i/1246-verdict-allowlist"
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?
A comment, a re-request, or an unrecognised review state each cleared a live
REQUEST_CHANGES, letting the bot force-push the rolling PR and dismiss its approvals.Intended-targets: #1246
Why this is an allowlist and not a longer denylist
#1237fixed this predicate by excludingPENDING. A denylist admits the next row type, and two more walked through it:⚠️ Each fix admitted the next one on a different axis. "Skip PENDING" let
COMMENTthrough precisely becauseCOMMENTis submitted — so the property the first fix keyed on was not the property that mattered.REQUEST_REVIEWis neither an unsubmitted draft nor a verdict.All four fail toward merge. This predicate has never once failed closed.
The gate's question is "what is this user's current VERDICT?", and exactly two row states answer it. Everything else is ignored by construction, so an unrecognised state is a non-event rather than the next incident.
The mutations are the argument for the shape
🔑 M1 and M2 together are the point: extending the denylist by one term reduces the leak by one term and closes nothing. M3 and M4 pin both directions, so "ignore everything" and "block on everything" are both red.
Measured before the change
The arm that matters
SOME_FUTURE_STATE— a state string this build has never heard of, asserted to be ignored rather than treated as a verdict. That is the arm that makes the next Forgejo review type a non-event instead of a fourth incident, and it is the one an allowlist can have and a denylist cannot.The second arm pins the other direction: a lone non-verdict row must not become a block either, or "treat everything as a rejection" would pass every arm above while deadlocking every rolling refresh.
⚠️ Scope note in the code
This answers "is there a live REJECTION", not "is this PR approved".
/srv/CLAUDE.mdrecords that aREQUEST_REVIEWrow supersedes an approval for merge-readiness — true, and irrelevant here, because a re-request neither creates nor clears a rejection. The comment says so, so the predicate is not reused for an approval count without re-deriving which rows that question needs.Stacked on #1237
This supersedes the
PENDINGskip that PR introduces. If#1237merges first this rebases clean; if you would rather have one PR, say so and I will fold them.🤖 Generated with Claude Code
https://claude.ai/code/session_01DbnWrAAh3iGuPAQF53nuXG
7b7b08f1f79d79a09fdd9d79a09fdd9537e2fa9aReviewed at the exact server head
9537e2fa9a. The fix uses a positive allowlist of the two verdict states and applies it before the newest-per-user reduction, so PENDING, COMMENT, REQUEST_REVIEW, and future unknown rows cannot evict a live REQUEST_CHANGES. APPROVED and REQUEST_CHANGES still supersede one another by the existing timestamp/ID ordering.The consequence assertions are present: the live blocker prevents UpdatePR, while a lone non-verdict row still permits it. I independently ran the full Go tests and vet; the old PENDING-only and PENDING+COMMENT denylists, an accept-everything mutant, and an accept-nothing mutant all redden the relevant controls. CI is 28/28 success at this head.