Comparing base-branch-tip -> head made a fork that is behind main report
all of main's later additions as phantom removals/modifications, which
would wrongly fail the scope guard for a legitimate additions-only PR.
Diff merge-base -> head (the PR's actual changes) instead; keep the
"already live" check against the current base branch.
Found by an end-to-end run of evaluate() against real PR data (#3298
stayed clean; #3044's phantom drift collapsed to its real one-line change).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the curated source-org allowlist with auto-derivation from the
live marketplace. A non-member PR stays open only if it ADDS entries
whose source.url repo ALREADY backs a live plugin here, additions-only,
nothing else touched. No list to maintain, no individuals named.
Trust is anchored in the source repo + pinned SHA (org-controlled), not
the submitter's identity; merge still requires CI + maintainer approval.
- remove external-pr-allowed-sources.json
- scripts/external-pr-scope.js: derive allowed repos from base marketplace.json
- both workflows drop the allowlist-file arg
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the per-username allowlist with a source-org allowlist so no
individual is named in the repo. A non-member PR stays open only if it
adds marketplace.json entries whose source.url is under an allowlisted
prefix and changes nothing else; merge still requires CI + maintainer
approval.
- external-pr-allowed-sources.json: flat allowed_sources prefixes (no usernames)
- scripts/external-pr-scope.js: shared additions-only / allowed-source logic
- close-external-prs.yml + external-pr-scope-guard.yml: both use the shared module
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>