Skip to content

Advisory gate cannot count Graphite's check-run clean pass: every clean PR waits out the 20-minute timeout #2005

Closed

Description

@don-petry

Problem

graphite-app is advisory_gate=yes in scripts/lib/reviewer-sources.tsv, but its clean pass is reported only as the Graphite / AI Reviews check run: no PR review, no comment. The advisory gate (scripts/lib/advisory-review-gate.sh, check_advisory_reviews) counts only reviews and comments, so a clean Graphite pass is invisible to it.

Effect: on a clean PR the gate can never reach the full quorum of 5 from real signal. It waits out ADVISORY_HEAD_AGE_TIMEOUT_SEC (1200s) and proceeds on partial evidence. It does not strand the PR, but it adds a fixed 20-minute delay to every clean PR.

Raised by cubic on PR #2003 and deliberately deferred there. Graphite was kept at advisory_gate=yes on purpose: its zero-review count is a measurement artefact, and the org is now on the paid plan.

Acceptance criteria

  1. check_advisory_reviews counts a completed, successful check run whose name matches the registry's check_run_name column as a clean submission from that bot, for the current head SHA only.
  2. A failed or neutral check run is not counted as clean; a pending one is not counted yet.
  3. The registry column check_run_name is the single source of truth. No check-run names are hard-coded in the gate.
  4. Bats coverage: clean check run counted; failed check run not counted; check run on a stale SHA not counted; a bot with check_run_name=- is unaffected.
  5. The scorecard behaviour from Reviewer scorecard misses Graphite's check-run reviews (clean passes read as 'No response') and undercounts its PR reviews ~8× #1908 is unchanged.

Out of scope

Changing graphite's advisory_gate value. The decision is recorded on the registry row: do not re-drop it.

Follow-up to #1997 / PR #2003. Context: #1894.

Measured answer to the open question (2026-10-02)

Checked against real data, not assumed. Of the last 40 merged PRs, 22 carried a check run named exactly Graphite / AI Reviews (equal to the registry's check_run_name), posted by app slug graphite-app, and all 22 had status=completed, conclusion=success. Zero other conclusions were observed. So matching the registry column is sufficient for the name, with two additions:

  1. A missing check run is not a clean pass. Some heads (e.g. the head of PR 2003) have no Graphite check at all. Absence must stay "no submission", never counted.
  2. Pin the app slug as well as the name. Any app with checks:write can create a check run with an arbitrary name. Count a check run only when app.slug equals the bot's registry login (graphite-app), so another app cannot satisfy the quorum by naming a check identically.
  3. A success check run means "Graphite reviewed this head", not "Graphite has no findings". Findings still arrive as inline threads and are gated by the existing disposition logic. Count the check run as a submission from the bot for this head SHA, exactly as a review would be counted, and add no code that treats it as clearing any finding.

Activity

  1. github-actions commented on Oct 1, 2026

    @github-actions
    Contributor

    Thanks for the detailed report and for tracking the context back to #1997 / PR #2003. The description and acceptance criteria are clear, so I only have one question: on a clean PR where Graphite reports only the Graphite / AI Reviews check run, can you confirm that check run's conclusion is success and that its name exactly matches the registry's check_run_name value for graphite-app? That would confirm that matching the registry column is enough to count it as a clean pass.

  2. don-petry commented on Oct 2, 2026

    @don-petry
    CollaboratorAuthor

    Dev-Lead Implementation Plan

    Issue: #2005 — Advisory gate cannot count Graphite's check-run clean pass: every clean PR waits out the 20-minute timeout

    Scope

    Make check_advisory_reviews count a completed, successful check run, named in the registry's check_run_name column for an advisory_gate=yes bot, as a clean (COMMENTED) submission from that bot, for the PR's current head SHA only.

    Implementation Checklist

    • scripts/lib/advisory-review-gate.sh: build a login→check-run-name map from reviewer_sources_check_run_reporters, keeping only advisory-gate bots. No names are hard-coded; if the registry is absent, the map is empty and no check runs are counted.
    • get_advisory_bot_states: add headRefOid to the existing gh pr view fetch. When the map is non-empty, fetch repos/{owner}/{repo}/commits/{sha}/check-runs (paginated), then keep only runs where head_sha == headRefOid, name matches the registry, status == completed and conclusion == success. Each kept run becomes {bot, state: COMMENTED, time: completed_at} in the same latest-per-bot stream. A failed, neutral or pending run is ignored. If the fetch fails, the gate logs a warning and falls back to counting reviews and comments only, as it does today, so it never errors.
    • scripts/lib/reviewer-sources.tsv: update the check_run_name column docs and the graphite row's "Known limitation" note to say the gate now reads the column too. No advisory_gate value changes.
    • scripts/lib/reviewer-sources.sh: update the doc comment on reviewer_sources_check_run_reporters.
    • Leave the scorecard (scripts/reviewer_report.sh, Reviewer scorecard misses Graphite's check-run reviews (clean passes read as 'No response') and undercounts its PR reviews ~8× #1908) unchanged.

    Tests to Write (tests/dev-lead/unit/test_advisory_review_gate.bats)

    • A clean (completed/success) Graphite check run at the head SHA is counted, and with the other 4 bots present the gate returns 0 within the head-age window
    • A failed check run is not counted (gate waits)
    • A neutral check run is not counted, and a pending one is not counted
    • A check run on a stale SHA (head_sha ≠ headRefOid) is not counted
    • A bot with check_run_name=- is unaffected: a matching-name run attributed via an override registry gives no credit to the - bot
    • Structural: no check-run name literal appears in the gate

    Test Command

    bats tests/dev-lead/unit/test_advisory_review_gate.bats tests/test_reviewer_sources.bats tests/reviewer_report.bats + bash .dev-lead/scripts/dev-lead-lint.sh

  3. don-petry commented on Oct 2, 2026

    @don-petry
    CollaboratorAuthor

    Answer to the clarifying question, measured on the last 40 merged PRs: 22 carried a check run named exactly Graphite / AI Reviews (matches the registry check_run_name), app slug graphite-app, and every one was completed / success. So yes, matching the registry column is enough for the name. Three additions are now acceptance criteria 6-8 in the issue body (missing check run is not clean; pin the app slug; a success check run is a submission, not a finding-clearance). Please proceed.

  4. don-petry commented on Oct 2, 2026

    @don-petry
    CollaboratorAuthor

    Dev-Lead: Implementation Complete — PR #2028

    The implementation for issue #2005 is durable: commits are pushed and a pull request is open. This record is backed by verifiable artifacts you can confirm in one click.

    Review happens on the PR. Acceptance criteria and test results are evidenced by the PR's diff and CI checks — not asserted here. If a later stage fails, this claim is retracted in place.

  5. added a commit that references this issue on Oct 2, 2026
  6. added 2 commits that reference this issue on Oct 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugBug reportsdev-leadFor dev-lead agent pickup

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions