Skip to content

orb(review): prReadyForReview defers forever and silently when a required CI context never reports — no surface, no label, no alert #9011

Description

@JSONbored

The largest silent stuck class

prReadyForReview (src/queue/processors.ts ~3944-3992) can defer a PR forever, with no output of any kind. The path:

const isLiveBaseConflict = (liveMergeState ?? pr.mergeableState) === "dirty";
if (ci.hasMissingRequiredContext && !isLiveBaseConflict) { …audit… return false; }   // every pass, forever

hasMissingRequiredContext (src/github/backfill.ts ~3016-3027, ~3066) is set when a branch-protection-required (or expectedCiContexts) context name never appears at all in a fully-read check/status set. It is orthogonal to hasVisiblePending (~3067), which requires a required check to be visibly queued/in_progress. A check that is never created is missing, not visible-pending — so the guard above falls through and returns false on every pass. The defer cap is only MISSING_REQUIRED_CONTEXT_DEFER_MS = 2 minutes (~4090), after which it just… keeps deferring.

Contrast the generic stuck-CI path (~3993-4064), which correctly finalizes once per SHA and pages at error level. The missing-required-context branch has no finalize escape — by deliberate design (#3947), to avoid publishing a premature "passed" gate. But the safety goal (never auto-merge unverified) does not require silence.

Because the caller returns immediately on false (~3686-3698), the PR gets no public surface, no review comment, no disposition, no label, and no alert — the only trace is low-signal github_app.review_deferred_ci_pending audit rows with outcome queued. The PR silently vanishes from the pipeline. In production this event fired 1,800 times across 342 distinct PRs in 48h, which makes genuinely-stuck PRs indistinguishable from PRs healthily waiting on CI.

Real-world triggers: a required workflow with paths: filters that exclude this PR's files; a renamed or deleted required workflow; an uninstalled third-party required App; a required context configured that no workflow actually emits.

Fix

Add a terminal cap to the missing-required-context branch mirroring the generic stuck-CI finalize: once a required context has been missing for STUCK_CI_DEFER_MS, stop deferring and route the PR to a loud held-for-human state — a visible hold naming the exact missing context, plus the once-per-SHA error-level page. This preserves #3947's safety (a hold never merges) while eliminating the silence. Keep the SHA-scoped guard so it doesn't re-spend.

Also: make the defer audit event carry a distinguishable reason (missing_required_context vs ci_running) and the elapsed defer duration, so "waiting normally" and "stuck for hours" are separable in the ledger — today they are not.

Acceptance

  • A PR whose required check is never created gets a named, visible hold within the cap, and an operator alert — instead of silence.
  • Normal CI waits still produce no user-visible noise.

Refs #9003 (the decision-reason invariant this is the worst instance of).

Metadata

Metadata

Assignees

Labels

maintainer-onlyOwner-only work — yields no Gittensor points.orbGittensory Orb related - maintainer self-hosting analytics.

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions