Skip to content

PR Base Freshness passes and then expires: 36 open PRs read CLEAN while over MAX_BEHIND, and the guard is not a required check #1326

Description

@lilyshen0722

Measured at origin/main ccacf023, 2026-08-28. Two independent defects; the second makes the first worse rather than redundant.

1. The guard measures a quantity that decays after it runs

pr-base-freshness.yml fails when the PR's merge-base is more than MAX_BEHIND: 40 commits behind main. It triggers on pull_request only — opened/synchronize/reopened/edited. Every one of those is a branch event.

But the quantity it measures is a function of main, not of the branch. Main moves; the check does not re-run. So a PR that passed at 3 behind is at 94 behind three days later, with a green Stale-base merge guard row and nothing to re-evaluate it.

Sweep of all 76 open PRs, merge-base recomputed against ccacf023 (second read on mergeStateStatus, since the first is a cache):

  • 49 are over the threshold.
  • 36 of those read CLEAN.
  • Range: 41 to 139 behind. #1081 and #1083 at 139, #1097 at 127, #1140 at 94, #1122/#1132 at 80.

Two confirmed instances of the stale green, run timestamps not inferred:

PR behind today Stale-base merge guard when it ran
#1140 94 success 2026-08-22T20:21:42Z
#1238 41 success 2026-08-25T13:37:50Z

The guard's own header comment is careful about exactly this class of gap — it explains at length why edited is load-bearing, because a retargeted child PR would otherwise "arrive already-passing on a check set it was never subject to". That is the same failure this issue reports, one axis over: here the PR was subject to the check, and the answer expired afterwards.

2. It is not a required check, so a red one would not block anyway

repos/Team-Commonly/commonly/branches/main/protection/required_status_checks:

{ "strict": false, "checks": [ { "context": "Test & Coverage", "app_id": 15368 } ] }

One required context. strict: false, so GitHub does not require the branch to be up to date either. The only ruleset on the repo (15758146 main branch) is disabled.

So Stale-base merge guard, Detect secrets, Package Version Guard, Service Tests, E2E Tests, Chart Lint and CodeQL are all advisory. A PR with any of them red merges; it just reads UNSTABLE (three currently do).

Why this matters beyond CI hygiene

The guard exists for #516 — a stale-base squash-merge that silently reverted intervening merged work, with a clean-looking GitHub diff because the diff is computed against the merge-base rather than the tip of main. That footgun is a property of the merge, not of the check. It is live right now on 36 PRs that display green.

Options, not a recommendation

  1. Add Stale-base merge guard to the required contexts, or set strict: true — either makes the guard load-bearing, and strict: true subsumes it entirely.
  2. Re-evaluate on main's movement (a push: branches: [main] job that re-dispatches, or a scheduled sweep) so the answer cannot go stale silently.
  3. Neither, and treat the guard as documentation — but then the green row should not read like an enforced gate.

I have not measured whether any merged PR actually reverted work this way; that is the natural next question and it needs a different instrument (comparing merge-base diffs against main at press time).

Not filed as a fix because which of the three is right is a repo-policy decision, not a defect with one correct repair.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions