⚠️ Definition of Done: this issue must be completed in full, in a single PR. Do not split this
work across multiple PRs, and do not defer any Deliverable below to a follow-up issue. A PR that
satisfies only some of the Deliverables, stubs a required test, or leaves a checkbox
partially-done does NOT resolve this issue and will be closed.
Context
withInstallationTokenRetry (src/github/app.ts:180) exists to evict and re-mint a stale cached installation token on a 401/permission-scope error, and every GitHub write helper in this directory routes through it (src/github/assignees.ts:39, src/github/labels.ts:32,87: "Self-heal a stale cached installation token once before giving up (#6191)"). src/github/pr-freshness.ts:110-124's fetchPullRequestFreshness instead calls createInstallationToken directly and feeds the (possibly-stale, shared-cache) token straight into fetchLivePullRequestResult, which uses raw githubJsonWithHeaders/githubGraphQl with no retry wrapper anywhere in backfill.ts (zero references to withInstallationTokenRetry or "bad credentials" in that file). A single stale-token 401 on this path is classified as status: "stale", reason: "unavailable" -- used by the reopen-guard/gate-override re-check to fail closed -- for what a write-path call would have transparently retried and succeeded on. test/unit/pr-freshness.test.ts has no 401/stale-token test case.
Requirements
Route fetchPullRequestFreshness (and the shared backfill.ts read helpers it depends on -- fetchLivePullRequestResult, fetchLiveIssueState, fetchLivePullRequestHeadSha) through withInstallationTokenRetry, matching the existing write-path self-heal convention (#6191).
Deliverables
All of the above Deliverables are required in the same PR unless the deliverable text itself states otherwise.
Test Coverage Requirements
src/** -- 99%+ patch coverage, branch-counted, on the new retry-wrapper wiring.
Expected Outcome
A stale cached installation token on a PR-freshness read self-heals via one retry, matching the existing write-path convention, instead of causing the reopen-guard/gate-override re-check to fail closed on a transient token issue.
Links & Resources
src/github/app.ts:180
src/github/assignees.ts:39
src/github/labels.ts:32,87
src/github/pr-freshness.ts:110-124
test/unit/pr-freshness.test.ts
Context
withInstallationTokenRetry(src/github/app.ts:180) exists to evict and re-mint a stale cached installation token on a 401/permission-scope error, and every GitHub write helper in this directory routes through it (src/github/assignees.ts:39,src/github/labels.ts:32,87: "Self-heal a stale cached installation token once before giving up (#6191)").src/github/pr-freshness.ts:110-124'sfetchPullRequestFreshnessinstead callscreateInstallationTokendirectly and feeds the (possibly-stale, shared-cache) token straight intofetchLivePullRequestResult, which uses rawgithubJsonWithHeaders/githubGraphQlwith no retry wrapper anywhere inbackfill.ts(zero references towithInstallationTokenRetryor "bad credentials" in that file). A single stale-token 401 on this path is classified asstatus: "stale", reason: "unavailable"-- used by the reopen-guard/gate-override re-check to fail closed -- for what a write-path call would have transparently retried and succeeded on.test/unit/pr-freshness.test.tshas no 401/stale-token test case.Requirements
Route
fetchPullRequestFreshness(and the sharedbackfill.tsread helpers it depends on --fetchLivePullRequestResult,fetchLiveIssueState,fetchLivePullRequestHeadSha) throughwithInstallationTokenRetry, matching the existing write-path self-heal convention (#6191).Deliverables
fetchPullRequestFreshnessand thebackfill.tsread helpers it calls route their GitHub calls throughwithInstallationTokenRetrystatus: "stale"All of the above Deliverables are required in the same PR unless the deliverable text itself states otherwise.
Test Coverage Requirements
src/**-- 99%+ patch coverage, branch-counted, on the new retry-wrapper wiring.Expected Outcome
A stale cached installation token on a PR-freshness read self-heals via one retry, matching the existing write-path convention, instead of causing the reopen-guard/gate-override re-check to fail closed on a transient token issue.
Links & Resources
src/github/app.ts:180src/github/assignees.ts:39src/github/labels.ts:32,87src/github/pr-freshness.ts:110-124test/unit/pr-freshness.test.ts