fix(agent-actions): recheck non-ci staged closes#2902
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #2902 +/- ##
=======================================
Coverage 96.06% 96.06%
=======================================
Files 259 259
Lines 28655 28660 +5
Branches 10428 10432 +4
=======================================
+ Hits 27528 27533 +5
Misses 490 490
Partials 637 637
🚀 New features to boost your workflow:
|
|
Warning 🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨 ⏸️ Gittensory review result - manual review recommendedReview updated: 2026-07-04 08:30:01 UTC
⏸️ Suggested Action - Manual Review
Review summary Blockers
Nits — 5 non-blocking
Concerns raised — review before merging
Review context
Contributor next steps
Signal definitions
🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed 💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.
|
…staleness closeRequiresCiState: "not_required" means CI was never the justification for a heuristic close, so gating the accept-time staleness check on ciState === "passed" left the safety gap open whenever live CI was pending, failed, or unverified: a cleared conflict on an otherwise-clean, non-conflicting PR would still execute the close. Base staleness only on mergeableState and reviewDecision, matching the non-CI signals the close actually depended on.
6a9984d to
f2bdf81
Compare
…tified closes closeRequiresCiState === "not_required" covers every non-CI heuristic close reason (duplicate PR, slop score, a gate blocker, or a base conflict), but the accept-time recheck only has a cheap live signal for the conflict case. Gating staleness on mergeableState/reviewDecision for ALL of them meant a duplicate- or slop-justified close was superseded merely because the PR happened to read clean, even though its actual justification was still live. Add closeRequiresMergeableState, set at plan time only when a base conflict was part of the close's reasons, and scope the recheck to that. Also stop treating a failed live review-decision read as equivalent to "no changes requested" -- a rejected fetch now fails open instead of silently satisfying the staleness check.
… level Prove the planner sets closeRequiresMergeableState: true only when a base conflict is part of the close's reasons, and false for a duplicate-justified close with no conflict -- the approval queue's accept-time recheck depends on this discriminator being planned correctly, not just consumed correctly.
Motivation
closeRequiresCiState: "not_required"could be accepted and executed without any accept-time live revalidation, allowing a stale justification (conflict/duplicate/gate) to be acted on.src/services/agent-approval-queue.ts:205), not a pre-planned feature.Description
decidePendingAgentAction(insrc/services/agent-approval-queue.ts) that runs the samefetchLiveCiAggregate/fetchLivePullRequestMergeState/fetchLivePullRequestReviewDecisionchecks used for merges when the pending row is a staged merge or a non-CI heuristic close withcloseRequiresCiState === "not_required".mergeableState/reviewDecision, dropping theciState === "passed"requirement:closeRequiresCiState: "not_required"already means CI was never this close's justification, so gating staleness on CI meant a cleared conflict on an otherwise-clean PR would still execute the close whenever live CI happened to be pending, failed, or unverified at accept time.test/unit/agent-approval-queue.test.tscovering: live-CI-passing + clean → superseded; live conflict remains → still executes; clean mergeability with live CI merely pending (not passed) → still superseded (the case the gate's own AI review flagged as reachable and uncovered); a reviewer requesting changes → still executes.main(branch was ~280 commits behind).Testing
npm run typecheck— clean.git diff --check— clean.npx vitest run test/unit/agent-approval-queue.test.ts— 62/62 passed.vitest --coverageonsrc/services/agent-approval-queue.tsvia this test file: 100% branch/line/statement coverage.Codex Task