When a supersede umbrella reaches COMPLETED (our own PR merged), close-on-land
retires the contributor's PR with a linking thank-you comment:
- TaskService.supersede_umbrellas_pending_close() finds landed umbrellas not yet
marked closed=1; mark_supersede_pr_closed() records the close (idempotent).
- orchestrator._close_superseded_prs runs in the external-PR poll tick: parses
the contributor PR# from the umbrella's quick_context and calls
GitService.close_pull_request(delete_branch=False) — we never touch the
contributor's fork branch. _parse_supersede_pr is unit-tested.
Completes the supersede flow: CEO authorizes -> fork branch -> Main PM -> cell
-> our PR -> CEO merge -> contributor PR closed + linked. ruff + mypy clean
(279); foundation + gateway suites green (5208).
At ingest, a non-empty external_pr_author_allowlist restricts which external
PRs are reviewed to those GitHub logins (case-insensitive). An empty allowlist
(default) reviews every external PR — safe because the review is read-only; the
confirmed_by_human gate still guards any later supersede that runs fork code.
Unit-tested (_pr_author_allowed).
Add the dormant inbound path for external-PR review (gated by external_pr_enabled,
off by default):
- GitService.list_open_prs lists a project's open PRs, normalized with fork /
author-association classification (the inbound counterpart to the org's
outbound, head-filtered PR calls).
- TaskService.ingest_external_pr + external_review_task_exists create one
de-duped review task per newly-seen external PR (source='external_pr',
confirmed_by_human=False) — a gate so no agent fetches or runs contributor
code until a human confirms the PR.
- A poll loop in the orchestrator, mirroring the strategy-engine loop: only when
enabled it lists each active project's open PRs, ingests the external ones, and
wakes the dispatcher.
The trust-critical author/fork classifier is unit-tested; the GitHub-list and
DB-ingest paths are exercised by the integration gate.