maybeHandleRepositoryRenamedWebhookEvent guards on action !== "renamed" (src/queue/processors.ts ~5812) and returns. repository.transferred therefore does nothing — even though "transferred" is already listed in WEBHOOK_METRIC_ACTIONS (src/github/webhook.ts ~54), so the case was anticipated and never implemented.
On transfer from old-org/repo to new-org/repo, GitHub sends repository.transferred (carrying changes.owner.from), then ordinary events under the new full_name. upsertRepositoryFromGitHub simply INSERTs a fresh row.
Because repositories is keyed by full_name with no github_id column (src/db/schema.ts), every one of the ~40 tables that repo-identity-rename.ts migrates is orphaned: pull_requests, gate_outcomes, advisories, repository_settings (autonomy and gate config silently revert to defaults — the repo keeps operating, under different policy), contributor_repo_stats, submitter_stats, review_audit, contributor_gate_history, predicted_gate_calibration_ledger, orb_pr_outcomes, and agent_pending_actions (staged maintainer approvals lost). Calibration and reversal joins on project split across two names.
Nothing ever heals this — there is no id-based reconciliation. The same hole applies if a repository.renamed delivery is simply lost (see the dedup issue: a lost delivery is permanently un-redeliverable), since there is no non-webhook rename detection.
Also unhandled in the same family: repository.archived / privatized / deleted — ORB keeps sweeping an archived repo and 403s on every write.
Fix
- Extend the guard to
action === "renamed" || action === "transferred"; derive the old name from changes.repository.name.from ?? changes.owner.from.{user,organization}.login plus the current name; add changes.owner to the payload type.
- Store
repositories.github_id and reconcile identity by numeric id in backfillRegisteredRepositories, so a dropped rename/transfer delivery self-heals.
- Handle
archived/deleted by stopping the sweep for that repo.
maybeHandleRepositoryRenamedWebhookEventguards onaction !== "renamed"(src/queue/processors.ts~5812) and returns.repository.transferredtherefore does nothing — even though"transferred"is already listed inWEBHOOK_METRIC_ACTIONS(src/github/webhook.ts~54), so the case was anticipated and never implemented.On transfer from
old-org/repotonew-org/repo, GitHub sendsrepository.transferred(carryingchanges.owner.from), then ordinary events under the newfull_name.upsertRepositoryFromGitHubsimply INSERTs a fresh row.Because
repositoriesis keyed byfull_namewith nogithub_idcolumn (src/db/schema.ts), every one of the ~40 tables thatrepo-identity-rename.tsmigrates is orphaned:pull_requests,gate_outcomes,advisories,repository_settings(autonomy and gate config silently revert to defaults — the repo keeps operating, under different policy),contributor_repo_stats,submitter_stats,review_audit,contributor_gate_history,predicted_gate_calibration_ledger,orb_pr_outcomes, andagent_pending_actions(staged maintainer approvals lost). Calibration and reversal joins onprojectsplit across two names.Nothing ever heals this — there is no id-based reconciliation. The same hole applies if a
repository.renameddelivery is simply lost (see the dedup issue: a lost delivery is permanently un-redeliverable), since there is no non-webhook rename detection.Also unhandled in the same family:
repository.archived/privatized/deleted— ORB keeps sweeping an archived repo and 403s on every write.Fix
action === "renamed" || action === "transferred"; derive the old name fromchanges.repository.name.from ?? changes.owner.from.{user,organization}.loginplus the current name; addchanges.ownerto the payload type.repositories.github_idand reconcile identity by numeric id inbackfillRegisteredRepositories, so a dropped rename/transfer delivery self-heals.archived/deletedby stopping the sweep for that repo.