You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(agent-actions): re-check the linked-issue hard rule on merge accept (#2388)
* fix(agent-actions): re-check the linked-issue hard rule on merge accept
decidePendingAgentAction re-validated only the head SHA before
replaying a staged auto_with_approval merge. The linked-issue hard
rule (owner-assigned / missing-point-label / maintainer-only) is
evaluated fresh on every planning pass and takes precedence over
merge, but a staged merge only replayed the plan-time snapshot: a
maintainer relabeling or reassigning the linked issue between staging
and accept (head SHA unchanged) would still merge a now-ineligible PR.
Re-run resolveLinkedIssueHardRule for a staged merge before executing
it, superseding the same way the head-moved check already does. Skips
the check for an owner/automation-authored PR (unless
closeOwnerAuthors is on), mirroring the planner's own closeEligible
exemption so a trusted PR the rule never blocks in the first place
isn't wrongly denied here.
Live CI re-verification for this same accept path is covered
separately by the already-open PR for #2128, which
executeAgentMaintenanceActions applies to every merge regardless of
caller — no changes needed here for that part.
* test(agent-actions): cover the linked-issue recheck's token-mint failure path
The rebase onto main's later head-pinning fixes shifted this diff's
covered range; close the resulting branch-coverage gap on the
createInstallationToken(...).catch(() => undefined) fallback added for
the #2132 linked-issue hard-rule recheck.
* fix(agent-actions): gate the linked-issue recheck on the post-downgrade plan
The linked-issue hard-rule recheck gated on pending.actionClass (the
ORIGINAL staged class) rather than the plan's actual contents after the
#2127 precision-breaker downgrade. A merge already downgraded to a
needs-human-review label by downgradeMergeToHold would still get its
whole row rejected on a stale linked-issue violation, silently swallowing
the hold label the breaker was supposed to guarantee -- since nothing is
about to merge, the linked-issue state is irrelevant to what plan is
actually going to execute.
Also documents why the recheck's best-effort token mint is intentionally
fail-open, consistent with the sibling #2126 CI/mergeable/review
re-check: resolveLinkedIssueHardRule already degrades to
env.GITHUB_PUBLIC_TOKEN before ever returning "not violated," and this is
the same shared resolver + fail-open contract the live planning path
already relies on for the primary hard-rule decision.
it("REGRESSION: a precision-breaker-downgraded merge still executes the hold/label plan even when the linked issue would now violate the hard rule",async()=>{
372
+
// Before the fix, the linked-issue recheck gated on pending.actionClass (the ORIGINAL staged class), not the
373
+
// post-downgrade plan -- so a merge already downgraded to a needs-human-review label by the #2127 precision
374
+
// breaker above would still get its whole row rejected on a stale linked-issue violation, silently swallowing
375
+
// the hold label the breaker was supposed to guarantee.
vi.mocked(resolveLinkedIssueHardRule).mockResolvedValueOnce({violated: true,reason: "Linked issue #9 is labeled `maintainer-only` — it is not open for community PRs."});
vi.mocked(resolveLinkedIssueHardRule).mockResolvedValueOnce({violated: true,reason: "Linked issue #9 is labeled `maintainer-only` — it is not open for community PRs."});
constaudit=awaitenv.DB.prepare("select detail from audit_events where event_type = ?").bind("agent.pending_action.superseded").first<{detail: string}>();
0 commit comments