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
As a maintainer waiting for pr-review to approve a PR whose tests are green,
I want the "CI still pending" deferral to ignore other agents' own check runs and to time out on a check that never completes,
so that ordinary dev-lead activity — or a single stuck check — cannot defer the review indefinitely.
Problem — two ways a PR gets stuck at ci-pending forever
scripts/review-one-pr.sh skips with reason:"ci-pending" whenever compute_ci_status sees a non-completed check, posting a <!-- pr-review-agent ci-pending-ack --> comment that says "re-mention @donpetry-bot once they complete."scripts/lib/ci-status.sh deliberately filters the cascade's own check runs (review, review / review, PR Review*) so pr-review never blocks on itself (#469). It does not filter any other agent's checks, and the pending state has no upper bound — a FORCE_REVIEW mention polls only 10×30s before giving up.
Case A — dev-lead's own check defers pr-review (agent-vs-agent interference)
Observed on PR #1420 at 07:48Z: 57 checks COMPLETED, all tests green (bats, unit, unit-tests all SUCCESS), zero unresolved threads, zero genuine failures — and one check IN_PROGRESS: dev-lead / dispatch, started 07:39:01Z. pr-review posted ci-pending-ack at 07:45:08Z and declined to review.
The loop is self-sustaining, and it is easy to enter by trying to help:
Someone comments on the PR (including "@donpetry-bot review", the remedy the ack itself recommends)
The comment is an issue_comment event → dev-lead fires → dev-lead / dispatch check goes IN_PROGRESS
pr-review sees a pending check → defers → posts another ci-pending-ack
Because dev-lead's concurrency is cancel-in-progress: false, queued runs keep at least one dispatch check pending across the window, so step 3 repeats
Every attempt to re-engage the reviewer re-arms the condition that makes it defer. During the observed window, two mention-driven attempts to obtain an approval both ended in ci-pending-ack rather than a review.
Case B — a zombie check never completes
Observed on PR #1426 at 07:48Z: Validate AW specs, docs, and workflows reports status: IN_PROGRESS with conclusion: SUCCESS, started 06:57:49Z — inconsistent, and ~50 minutes stale. A check in this state will not transition, so the ci-pending skip is permanent: pr-review will defer on every future trigger, forever, with no timeout to rescue it.
Both PRs were otherwise fully merge-ready. Nothing has merged since 05:49Z.
Acceptance Criteria
compute_ci_statusexcludes other first-party agent check runs from the pending calculation — at minimum dev-lead / *, generalised from the existing self-filter rather than hard-coded per agent. A writing agent's own job must not gate the reviewing agent.
The ci-pending deferral is bounded: after a configurable age, pr-review either proceeds on the completed checks or escalates once, rather than deferring indefinitely. A check that is IN_PROGRESS while carrying a terminal conclusion is treated as complete.
The bound is fail-safe, not fail-open: proceeding past a genuinely pending required check must remain impossible — the timeout applies to the review decision, not to the merge gate, which the rulesets still enforce independently.
The ci-pending-ack comment stops recommending a remedy that re-triggers the condition. Either the ack is dropped for the self-inflicted case, or its text stops advising a re-mention when the only pending check belongs to another agent.
Tests cover: pending dev-lead check + otherwise-green PR → review proceeds; zombie check (IN_PROGRESS + conclusion) → treated as complete; a genuinely pending required check → still defers; the deferral timeout path.
Case B is a GitHub-side inconsistency we cannot prevent, only tolerate — hence AC Add @claude delegation, auto-merge, and rebase handling #3's "terminal conclusion wins" rule. Treating a check with a conclusion as complete is safe: a conclusion is by definition terminal.
scripts/lib/ci-status.sh (the filter and the pending calculation), scripts/review-one-pr.sh (the skip path and the ack copy); tests under tests/, registered in lint.yml's bats list.
Filed from overnight monitoring of epic #1402. Found while diagnosing why two fully-green PRs would not attract a code-owner approval: the reviewer was deferring on the writing agent's own check run, and each attempt to re-engage it re-armed that deferral.
Story
As a maintainer waiting for pr-review to approve a PR whose tests are green,
I want the "CI still pending" deferral to ignore other agents' own check runs and to time out on a check that never completes,
so that ordinary dev-lead activity — or a single stuck check — cannot defer the review indefinitely.
Problem — two ways a PR gets stuck at
ci-pendingforeverscripts/review-one-pr.shskips withreason:"ci-pending"whenevercompute_ci_statussees a non-completed check, posting a<!-- pr-review-agent ci-pending-ack -->comment that says "re-mention@donpetry-botonce they complete."scripts/lib/ci-status.shdeliberately filters the cascade's own check runs (review,review / review,PR Review*) so pr-review never blocks on itself (#469). It does not filter any other agent's checks, and the pending state has no upper bound — aFORCE_REVIEWmention polls only 10×30s before giving up.Case A — dev-lead's own check defers pr-review (agent-vs-agent interference)
Observed on PR #1420 at 07:48Z: 57 checks
COMPLETED, all tests green (bats,unit,unit-testsall SUCCESS), zero unresolved threads, zero genuine failures — and one checkIN_PROGRESS:dev-lead / dispatch, started 07:39:01Z. pr-review postedci-pending-ackat 07:45:08Z and declined to review.The loop is self-sustaining, and it is easy to enter by trying to help:
issue_commentevent → dev-lead fires →dev-lead / dispatchcheck goesIN_PROGRESSci-pending-ackcancel-in-progress: false, queued runs keep at least one dispatch check pending across the window, so step 3 repeatsEvery attempt to re-engage the reviewer re-arms the condition that makes it defer. During the observed window, two mention-driven attempts to obtain an approval both ended in
ci-pending-ackrather than a review.Case B — a zombie check never completes
Observed on PR #1426 at 07:48Z:
Validate AW specs, docs, and workflowsreportsstatus: IN_PROGRESSwithconclusion: SUCCESS, started 06:57:49Z — inconsistent, and ~50 minutes stale. A check in this state will not transition, so theci-pendingskip is permanent: pr-review will defer on every future trigger, forever, with no timeout to rescue it.Both PRs were otherwise fully merge-ready. Nothing has merged since 05:49Z.
Acceptance Criteria
compute_ci_statusexcludes other first-party agent check runs from the pending calculation — at minimumdev-lead / *, generalised from the existing self-filter rather than hard-coded per agent. A writing agent's own job must not gate the reviewing agent.ci-pendingdeferral is bounded: after a configurable age, pr-review either proceeds on the completed checks or escalates once, rather than deferring indefinitely. A check that isIN_PROGRESSwhile carrying a terminalconclusionis treated as complete.ci-pending-ackcomment stops recommending a remedy that re-triggers the condition. Either the ack is dropped for the self-inflicted case, or its text stops advising a re-mention when the only pending check belongs to another agent.IN_PROGRESS+conclusion) → treated as complete; a genuinely pending required check → still defers; the deferral timeout path.Tasks / Subtasks
ci-status.shself-filter into an agent-check filter sourced from the interaction contracts. (AC: test issue from agent #1, Go-live improvements for PR review agent #2)compute_ci_status/review-one-pr.sh. (AC: Add @claude delegation, auto-merge, and rebase handling #3, Optimize review: small-PR and incremental fast paths #4)ci-pending-ackcopy so it never recommends an action that re-arms the block. (AC: feat: add Copilot engine support via REVIEW_ENGINE toggle #5)Dev Notes
scripts/lib/ci-status.sh(pr-review: mention-triggered runs silently lost to ci-pending skip (self-referential check runs) #469) is the precedent and the right shape — this story widens its scope rather than inventing a mechanism. Note it also already treatsCANCELLEDas non-blocking (pr-review CI gate should gate on REQUIRED checks only — non-required CANCELLED *and* FAILED checks falsely block reviews #608), which is the same class of judgement.cancel-in-progress: true. That is what pr-review: per-PR cancel-in-progress cancels racing runs (concurrency thrash) #534 fixed for pr-review and it kills in-flight work; the queueing is deliberate. The fix belongs in what pr-review counts, not in how dev-lead queues.dev-lead / dispatch, started 07:39:01Z), all tests green; feat: implement issue #1409 — [Phase 5] Wire the standard into AGENTS.md and per-agent docs, and reconcile the ci-failure-analyst spec vs deployed divergence #1426 —Validate AW specs, docs, and workflowswithstatus: IN_PROGRESS+conclusion: SUCCESS, started 06:57:49Z.Project Structure Notes
scripts/lib/ci-status.sh(the filter and the pending calculation),scripts/review-one-pr.sh(the skip path and the ack copy); tests undertests/, registered inlint.yml's bats list.References
scripts/lib/ci-status.sh(compute_ci_status; the pr-review: mention-triggered runs silently lost to ci-pending skip (self-referential check runs) #469 self-filter; the pr-review CI gate should gate on REQUIRED checks only — non-required CANCELLED *and* FAILED checks falsely block reviews #608 CANCELLED rule)scripts/review-one-pr.sh(ci-pendingskip, theci-pending-ackcomment, the 10×30s FORCE_REVIEW poll).github/workflows/dev-lead-reusable.yml(concurrencycancel-in-progress: false)Likely target surface
scripts/lib/ci-status.sh,scripts/review-one-pr.shFiled from overnight monitoring of epic #1402. Found while diagnosing why two fully-green PRs would not attract a code-owner approval: the reviewer was deferring on the writing agent's own check run, and each attempt to re-engage it re-armed that deferral.