Skip to content

Claude review lanes never review GitHub-App pushes to human-owned PRs (cursor[bot]) #637

Description

@kyle-sexton

Problem

Since #622, both Claude review lanes skip every event whose github.actor ends in [bot]:

!endsWith(github.actor, '[bot]')

(claude-review.yml at v0.29.1, line 113; the security lane carries the same clause.)

That condition keys on the pusher, not the PR author. When a GitHub App such as the Cursor agent (cursor[bot]) pushes to a same-repo PR a human org member opened, every synchronize and ready_for_review event has github.actor = cursor[bot], so neither lane ever reviews the PR. #622's own commit message notes this consequence: it stopped reviewing cursor[bot] pushes that #441/#443 had admitted.

Observed impact in melodic-software/claude-code-plugins on 2026-09-28: 182 open PRs, nearly all Cursor-driven, and every review lane run on them was SKIPPED. Local reviews then found destructive-command guard bypasses in 2 of the 3 guard-changing PRs (claude-code-plugins #5068, #4788) that no lane had seen.

Proposed fix

Gate the PR author on not being a bot, and admit a bot pusher only by explicit name, with the same list passed to the action:

# job if:
${{ vars.CLAUDE_LANES_DISABLED != 'true'
    && (github.event_name != 'pull_request'
        || (github.event.pull_request.head.repo.full_name == github.repository
            && github.event.pull_request.draft == false
            && !endsWith(github.event.pull_request.user.login, '[bot]')))
    && (!endsWith(github.actor, '[bot]')
        || contains(format(',{0},', inputs.allowed-bots), format(',{0},', github.actor))) }}

# claude-code-action step:
with:
  allowed_bots: ${{ inputs.allowed-bots }}   # e.g. 'cursor[bot]'; never '*'

Why each clause:

  • !endsWith(github.event.pull_request.user.login, '[bot]') keeps Dependabot-authored PRs skipped, including when a human pushes to one. GitHub's own Dependabot automation examples key on user.login.
  • The comma-wrapped contains on github.actor avoids substring matches and checks the same identity claude-code-action checks (GITHUB_ACTOR), so the workflow gate and the action cannot disagree, re-runs included.
  • allowed_bots is required: at v1.0.235, checkHumanActor throws for any non-User actor not in allowed_bots, so admitting cursor[bot] in if: alone makes the job fail instead of review.
  • The existing same-repo and draft guards stay. A same-repo head branch means the pusher had write access.
  • A new allowed-bots input, empty by default, keeps every current consumer's behaviour unchanged.

Deliberately not proposed: an author_association clause

#443 gated on OWNER,MEMBER,COLLABORATOR. Org members with private membership are reported to appear as CONTRIBUTOR in Actions payloads (flutter/flutter#101012, apache/arrow#34381), and nobody has captured what this org's payload reports. The clause could silently skip exactly the PRs it is meant to review. If it is wanted, settle it first with a one-off toJSON(github.event.pull_request.author_association) echo in a same-repo PR run.

Acceptance criteria

  • Both review lanes accept an allowed-bots input (default empty) and use the condition above.
  • The action step passes the same list as allowed_bots.
  • A test run proves it: a cursor[bot] push to a human-owned same-repo PR runs both lanes, and a Dependabot PR still skips. This live run is the independent check; the claims above rest on the action's source at v1.0.235 and GitHub's docs only.
  • The melodic-software/standards runner-policy contract permits callers to pass allowed-bots at the new pin.
  • node --test suites cover the four actor/author combinations: human/human, bot-listed/human, bot-unlisted/human, any/dependabot.

Related

Activity

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

    needs-triageNot yet classified. Floor until a type and one priority tier are set.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions