fix(review): enforce close autonomy on draft-dodge and reopen-reclose paths - #4637
Merged
Merged
Conversation
… paths closeDraftDodgeAttemptIfBlocked and recloseDisallowedReopenIfNeeded bypass the unified maintenance planner by design (procedural-integrity enforcement, not a merit verdict), but unlike their 3 correct siblings (closeReviewEvasionSelfCloseIfActive/DraftConversionIfActive/ RepeatedDraftCyclingIfDetected) they never checked the close-specific autonomy class -- draft-dodge checked no actionClass at all (so any acting autonomy class satisfied it), and reopen-reclose only checked isAgentConfigured (true for any acting class). A repo that opts into some other autonomy class while deliberately leaving close unconfigured (deny-by-default) could still get PRs auto-closed via either path. Both now resolve the close autonomy class directly and deny (with an audit event) when it is not "auto", mirroring the 3 already-correct siblings. Extraction of the shared enforceDeterministicClose helper across all 5 close paths (this issue's second acceptance criterion) is deferred to an immediate fast-follow PR to keep this security fix minimal and reviewable in isolation. Fixes #4602
Contributor
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #4637 +/- ##
==========================================
- Coverage 94.11% 94.10% -0.01%
==========================================
Files 432 432
Lines 38371 38382 +11
Branches 13989 13994 +5
==========================================
+ Hits 36111 36120 +9
Misses 1602 1602
- Partials 658 660 +2
🚀 New features to boost your workflow:
|
JSONbored
added a commit
that referenced
this pull request
Jul 10, 2026
Part of #4602 (second acceptance criterion): the 5 deterministic close- enforcement paths in src/queue/processors.ts each duplicated ~150-230 lines of scaffolding -- agent-action-mode resolution, the close-autonomy check, dry-run/paused stand-down, write-permission readiness, and the live freshness re-check -- the exact class of duplication that let 2 of the 5 silently miss the close-autonomy check (fixed in #4637). Extracts withPrActuationLock (the byte-identical lock claim/try/finally- release wrapper) and evaluateCloseEnforcementGate (the mode/autonomy/ standdown/permission-readiness/freshness scaffolding, parameterized by each caller's exact detail text and metadata) so all 5 call sites now share one function for that scaffolding. The actual GitHub mutation and its post- success side effects stay caller-owned, since they differ too much to unify (self-close's reopen-then-close with asymmetric error handling vs. the other 4's single close call). Two pre-existing, intentionally-preserved asymmetries: draft-dodge records no audit event on a paused/frozen repo (every other guard does), and reopen-reclose has never had a write-permission-readiness check (every other guard does). Neither is introduced or fixed here -- a refactor must not change behavior.
21 tasks
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
closeDraftDodgeAttemptIfBlockedandrecloseDisallowedReopenIfNeededare 2 of the 5 deterministicclose-enforcement paths that bypass the unified
planAgentMaintenanceActionsplanner by design. Unliketheir 3 correct siblings (
closeReviewEvasionSelfCloseIfActive/DraftConversionIfActive/RepeatedDraftCyclingIfDetected), neither checked the close-specific autonomy class before closing:closeDraftDodgeAttemptIfBlockedcalledresolveAgentPermissionReadiness(...)withoutactionClass: "close", so it checked the union of any acting autonomy class's write-permissiongrant instead of specifically
close's.recloseDisallowedReopenIfNeededgated only onisAgentConfigured(...)(true when any class isacting), never on
resolveAutonomy(..., "close").Impact: a repo that enables any other autonomy class (e.g.
assign: "auto") but deliberately leavescloseunconfigured (documented deny-by-default) could still have PRs auto-closed via these 2 paths.Fix
Both now resolve
closeautonomy directly and deny (with an audit event, matching the 3 correctsiblings' shape) when it is not
"auto".Scope note
This issue's second acceptance criterion (extract a shared
enforceDeterministicClosehelper across all5 close paths, ~600-700 line reduction) is deferred to an immediate fast-follow PR — keeping this fix
minimal and independently reviewable given the security-sensitive nature of the change.
Testing
4 new regression tests (draft-dodge × {denied, auto_with_approval}, reopen-reclose × {denied,
auto_with_approval}) asserting no write call and a
deniedaudit outcome whencloseautonomy isn'tauto. Verified these fail pre-fix and pass post-fix. Typecheck clean; fullqueue.test.tssuite(787 tests) passes.
Fixes #4602