external-pr-viability
External PR Viability
Use this before writing a single line of code for an unsolicited PR against a repository you do not already have merged standing in.
The problem
A correct, fully-tested, contribution-guideline-compliant PR can be closed within seconds, with zero review and zero comment, even though CI passed. That is not a code-quality signal — a genuine quality rejection leaves a comment or a "changes requested" review, because the point of a comment is to get the author to fix something. A silent, near-instant close with passing checks means the PR was never evaluated on its merits: it was closed because of who opened it, not what was in it. No amount of correctness, test coverage, or contribution-guideline compliance changes that outcome, and reattempting on the same repo (a different issue, a rewritten description) wastes the same amount of effort again.
Confirmed directly: a PR fixing a real, independently-verified one-line bug — with a red/green-tested regression test, a linked issue, a filled-in contribution template, and the required changelog entry — was closed by a core-team member 34 seconds after the final push. Checking the last 100 merged PRs on that repository showed every single author was either a core-team member or the dependency-update bot: zero outside contributors merged, ever, in that window. Other recent external PRs from unrelated contributors had received the identical silent treatment.
Rule
Before implementing a fix for an unsolicited external PR, run this check:
gh pr list --repo <owner>/<repo> --state merged --limit 100 --json author,authorAssociation— collect the unique author logins together with GitHub's ownauthorAssociationfor each (MEMBER/OWNER/COLLABORATORvsCONTRIBUTOR/FIRST_TIME_CONTRIBUTOR/NONE). TreatauthorAssociationas the primary signal — it comes from GitHub's own view of the relationship, not an inference.- Only when
authorAssociationdoesn't resolve a login clearly, cross-check org membership:gh api orgs/<org>/members/<login>(204 = member, 404 = not a member) — or use employer/bio signals when the repo isn't org-owned. Treat that call's own result with caution:GET /orgs/{org}/members/{username}only reports a private membership correctly when the caller is themselves an org member. Called from outside — which this skill always is — a privately-set member reads back as 404 and gets miscounted as external, biasing the whole check toward the wrong, unsafe conclusion (a real core-team repo reading as a healthy mix). Never let this call override aMEMBER/OWNERauthorAssociationfrom step 1. - Count how many distinct people among those authors are genuinely external (not a member/owner/collaborator, not a bot) — not how many external-authored PRs there are. Note separately whether those merges are spread across many different people or concentrated in one or two: a dozen merged PRs from one long-time contributor who behaves like an unofficial team member is a different, weaker signal than a dozen merged PRs from a dozen different first-time contributors.
Decision, checked in this order: