Repository navigation
pr-review: mention-triggered runs silently lost to ci-pending skip (self-referential check runs) #469
Description
Summary
Mention-triggered (FORCE_REVIEW=true) PR-review runs are silently swallowed by the CI gate in scripts/review-one-pr.sh. The bot acks "I'm on it — starting a fresh review now" and then the dispatched run exits 100 with skip: CI checks still in progress — no review, no retry, no follow-up comment.
Related: #463 (general ci-pending skip with no CI-completion re-trigger). This issue is the mention-path slice plus the self-referential check problem that makes it much more likely to fire.
Evidence (2026-06-07)
After #468 merged, @donpetry-bot review was posted simultaneously on 6 open PRs (#458, #383, #226, #152, #465, #455). All 6 dispatch runs skipped:
- 5×
{"decision":"skip","reason":"ci-pending"}— e.g. run 27107259250 (PR feat: implement advisory bot review gate in pr-review agent #458):skip: CI checks still in progress — will re-evaluate when checks complete - 1×
ci-failing(PR feat: implement issue #382 — Enhance dev-lead and pr-review engines for Gemini 3.5 models #383, genuine failure)
The pending entries in statusCheckRollup were largely caused by the mention burst itself: the mention-ack, ci-relay, and the PR Review Agent's own review/dispatch check runs attach to the PR head SHA and appear in its own rollup. The dispatched run starts ~30s after the mention, sees its sibling check runs still queued, classifies CI as pending, and exits.
A second mention round ~10 minutes later (after the rollup settled) worked and produced APPROVED verdicts — confirming the first round was lost purely to transient rollup churn.
Why this matters
- Same false-promise shape as the (fixed) cycle-cap defect pr-review: cycle cap counts approvals, ignores human re-requests, and escalation is unrecoverable #467: the ack promises a review that never arrives, and exit 100 means nothing retries.
- The CI gate runs before the
FORCE_REVIEWhandling, so an explicit human request — the strongest possible trigger — is the easiest to lose.
Proposed fix (for dev-lead)
In scripts/review-one-pr.sh:
- Exclude the agent's own check runs from CI classification — filter
statusCheckRollupentries namedreview/dispatch/mention-ack (the PR Review Agent / Mention Trigger workflows) before computingCI_STATUS, so the cascade never blocks on itself. - When
FORCE_REVIEW=trueand CI ispending: poll the rollup briefly (e.g. up to 5 min with 30s interval) instead of skipping immediately. If still pending after the window, post a visible reply ("CI still running — re-mention when green" or auto-requeue) instead of exiting silently. - (Optional, overlaps PR Review Agent never reviews at green CI — skips on ci-pending with no CI-completion re-trigger (clean PRs stuck at REVIEW_REQUIRED) #463) on
ci-pendingskip, schedule/dispatch a delayed re-check so non-mention runs also recover.
Acceptance criteria
- A
@donpetry-bot reviewmention during check churn produces either a review or a visible explanatory comment — never a silent no-op. - The PR Review Agent's own check runs never cause
ci-pending/ci-failingclassification. - Bats coverage for the rollup-filtering logic.
Activity
don-petry commentedon Jun 8, 2026
Dev-Lead Implementation Plan
Issue: #469 — pr-review: mention-triggered runs silently lost to ci-pending skip (self-referential check runs)
Scope
Filter the PR Review Agent's own check runs from the CI gate and add FORCE_REVIEW polling so mention-triggered runs never silently no-op on self-induced CI churn.
Implementation Checklist
scripts/lib/ci-status.sh— extract CI_STATUS jq logic into a testablecompute_ci_statusfunction that filters self-referential check runs (review,dispatch,ci-relay,pr-review-mention,mention-ackand theirworkflow / jobvariants)scripts/review-one-pr.sh— sourceci-status.sh, usecompute_ci_status, add FORCE_REVIEW polling (up toFORCE_REVIEW_POLL_ATTEMPTS × FORCE_REVIEW_POLL_INTERVAL_SEC, default 10×30s = 5 min) when CI is pending, post visible comment if still pending after pollingtests/test_ci_status.bats— BATS coverage for the rollup-filtering logictests/test_ci_status.batsto thebatsjob in.github/workflows/lint.ymlTests to Write
compute_ci_status: empty rollup → "passing"compute_ci_status: own check namedreviewfiltered — does not cause pendingcompute_ci_status: own check nameddispatchfilteredcompute_ci_status: own check namedci-relayfilteredcompute_ci_status: own check inworkflow / jobformat filtered (e.g.PR Review Agent / review)compute_ci_status: external pending check → "pending"compute_ci_status: external failing check → "failing"compute_ci_status: mix — own pending + external passing → "passing"compute_ci_status: mix — own pending + external pending → "pending"compute_ci_status: mix — all own checks only → "passing"compute_ci_status: status-context checks not accidentally filteredTest Command
bats tests/test_ci_status.bats tests/test_review_cycle.batsdon-petry commentedon Jun 8, 2026
Dev-Lead: Implementation Complete
Plan Execution
scripts/lib/ci-status.shwithcompute_ci_statusfunction (own-check filter + CI classification)tests/test_ci_status.bats(31 tests, TDD red phase)compute_ci_status— all 31 tests pass (green phase)scripts/review-one-pr.sh: sourcedci-status.sh, replaced inline jq, added FORCE_REVIEW polling blocktests/test_ci_status.batsto.github/workflows/lint.ymlbats jobTest Results
Lint:
shellcheckon 35 files + agent profile frontmatter — all checks passed.Files Changed
scripts/lib/ci-status.sh(new):compute_ci_statusfunction — filters self-referential check runs namedreview,dispatch,ci-relay,pr-review-mention,mention-ack(bare andworkflow / jobformats) before computing pending/passing/failingscripts/review-one-pr.sh: sourceci-status.sh; replace 14-line inline jq withcompute_ci_status; add FORCE_REVIEW polling block (defaults: 10 × 30s = 5 min) — polls for CI to settle, posts visible "CI still running — re-mention when done" comment if poll window exhausted, handlesci-failingdetected during polling, refreshesREVIEW_DECISIONafter CI settlestests/test_ci_status.bats(new): 31 BATS tests covering own-check filtering (both name forms), external check classification, mix scenarios, malformed input.github/workflows/lint.yml: addedtests/test_ci_status.batsto bats jobNotes
FORCE_REVIEW_POLL_ATTEMPTS=0; interval is overridable viaFORCE_REVIEW_POLL_INTERVAL_SEC— both env vars let CI/tests stub the timing without sleeps.ci-pending-ackcomment marker (<!-- pr-review-agent ci-pending-ack -->) is distinct from the review marker and escalation marker — safe to add without breaking idempotency or cycle-cap logic.don-petry commentedon Jun 8, 2026
feat: implement issue #469 — pr-review: mention-triggered runs silent…
fix(ci-status): filter the cascade's nested 'review / review' own-che…
feat: implement issue #469 — pr-review: mention-triggered runs silent…
fix(ci-status): filter the cascade's nested 'review / review' own-che…
feat: implement issue #469 — pr-review: mention-triggered runs silent…
fix(ci-status): filter the cascade's nested 'review / review' own-che…
feat: implement issue #469 — pr-review: mention-triggered runs silent…
fix(ci-status): filter the cascade's nested 'review / review' own-che…
feat: implement issue #469 — pr-review: mention-triggered runs silent…
fix(ci-status): filter the cascade's nested 'review / review' own-che…
feat: implement issue #469 — pr-review: mention-triggered runs silent…
fix(ci-status): filter the cascade's nested 'review / review' own-che…