What happened
On #22, CodeRabbit was rate-limited. It surfaced only as a status-check description:
CodeRabbit pass 0 Review rate limited
toolkit pass 12s ✓
pr_watch reported the PR as converged, clean, with no unavailability signal. I only caught it by running gh pr checks by hand after a re-review I'd been waiting on never arrived.
Why it slipped through
review.unavailable_markers is matched against comment bodies (collect_comments → review_unavailable_reason). This outage never produced a comment. It produced a check whose name is CodeRabbit — which review.informational_checks deliberately excludes from the blocking tally — and whose description carries the reason.
So the two mechanisms miss each other exactly:
- the unavailability detector only reads comments, and there was no comment
- the check that carried the reason is classified informational, and its conclusion is
pass
Net effect: a rate-limited bot is indistinguishable from a bot that reviewed and found nothing. Both render as a clean converged report.
Why it matters
The doctrine's load-bearing rule is that a blocked bot is an action signal, never a review waiver — it's supposed to trigger the configured fallback pass. That rule can only fire if the outage is detected. Here it wasn't, so the mechanism silently degraded to "no review happened, and nothing said so."
This is the mirror of #19. There, a queued bot could have a receipt recorded against it (too eager). Here, an unavailable bot produces no signal at all (too quiet). #19 is the more visible failure; this one is the more dangerous, because #19 at least leaves a receipt to audit.
Related: the informational-check exclusion is load-bearing for a different reason — it's what stops the watch loop wedging on a bot that never reports. So the fix cannot simply be "let informational checks block." That tension is the same one #19 runs into, which is why these two probably want solving together.
Sketch, not a decision
Read a configured review bot's check description through the same unavailable_markers matching already applied to comment bodies, and surface a hit as a review_unavailable_reason — visible and blocking mergeable, without making the check itself block converged. That keeps the anti-wedge property while restoring the action signal.
Needs care in the same place #19 does; worth designing the two together rather than patching this one alone.
Repro
#22, head 32f3e4f. gh pr checks 22 shows CodeRabbit pass "Review rate limited" while uv run scripts/pr_watch.py 22 reports converged with no unavailability notice.
What happened
On #22, CodeRabbit was rate-limited. It surfaced only as a status-check description:
pr_watchreported the PR asconverged, clean, with no unavailability signal. I only caught it by runninggh pr checksby hand after a re-review I'd been waiting on never arrived.Why it slipped through
review.unavailable_markersis matched against comment bodies (collect_comments→review_unavailable_reason). This outage never produced a comment. It produced a check whose name isCodeRabbit— whichreview.informational_checksdeliberately excludes from the blocking tally — and whose description carries the reason.So the two mechanisms miss each other exactly:
passNet effect: a rate-limited bot is indistinguishable from a bot that reviewed and found nothing. Both render as a clean converged report.
Why it matters
The doctrine's load-bearing rule is that a blocked bot is an action signal, never a review waiver — it's supposed to trigger the configured fallback pass. That rule can only fire if the outage is detected. Here it wasn't, so the mechanism silently degraded to "no review happened, and nothing said so."
This is the mirror of #19. There, a queued bot could have a receipt recorded against it (too eager). Here, an unavailable bot produces no signal at all (too quiet). #19 is the more visible failure; this one is the more dangerous, because #19 at least leaves a receipt to audit.
Related: the informational-check exclusion is load-bearing for a different reason — it's what stops the watch loop wedging on a bot that never reports. So the fix cannot simply be "let informational checks block." That tension is the same one #19 runs into, which is why these two probably want solving together.
Sketch, not a decision
Read a configured review bot's check description through the same
unavailable_markersmatching already applied to comment bodies, and surface a hit as areview_unavailable_reason— visible and blockingmergeable, without making the check itself blockconverged. That keeps the anti-wedge property while restoring the action signal.Needs care in the same place #19 does; worth designing the two together rather than patching this one alone.
Repro
#22, head
32f3e4f.gh pr checks 22showsCodeRabbit pass "Review rate limited"whileuv run scripts/pr_watch.py 22reports converged with no unavailability notice.