fix(review): correct stale-base grounding fact + close the mergeable_state blind spot - #7686
Merged
Merged
Conversation
…eable_state blind spot it depends on The base-branch staleness fact shipped in #7670 anchored its compare-API read on a PR's own base.sha -- but GitHub keeps that field pointed at the live tip of the target branch as it moves, so comparing it against the current default branch would read ~0 regardless of how stale a PR's actual code is, making the fact effectively dead. Anchors on the PR's HEAD instead, which the compare API resolves via a true git merge-base, independent of that metadata timing. Also adds gate.staleBaseAheadByThreshold: when a repo opts in, the pre-review readiness gate (prReadyForReview) forces an update_branch once the default branch has advanced at least that many commits beyond a PR's head -- the same action the existing BEHIND-base path takes, but triggered by the same compare-API read rather than GitHub's own mergeable_state, which only ever reports "behind" when a repo's branch protection requires branches to be up to date before merging. A repo without that setting can have a PR genuinely dozens of commits behind and never see it auto-rebased before review otherwise.
Contributor
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
loopover-ui | 4c15edd | Commit Preview URL Branch Preview URL |
Jul 21 2026, 08:11 AM |
Bundle ReportChanges will increase total bundle size by 308 bytes (0.0%) ⬆️. This is within the configured threshold ✅ Detailed changes
Affected Assets, Files, and Routes:view changes for bundle: loopover-uiAssets Changed:
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #7686 +/- ##
=======================================
Coverage 88.54% 88.55%
=======================================
Files 725 725
Lines 76170 76183 +13
Branches 22671 22677 +6
=======================================
+ Hits 67446 67461 +15
Misses 7680 7680
+ Partials 1044 1042 -2
Flags with carried forward coverage won't be shown. Click here to find out more.
|
This was referenced Jul 21, 2026
Closed
This was referenced Jul 23, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Follow-up to #7670. While building a related feature I found a real correctness bug in what shipped there, and fixed it alongside the new feature it directly motivates:
base.sha. GitHub keeps that field pointed at the live tip of the target branch as it moves, so comparing it against the current default branch reads~0regardless of how stale a PR's actual code is -- the fact was effectively dead on arrival. Now anchored on the PR's HEAD commit instead, which the compare API resolves via a true git merge-base, independent of that metadata timing.gate.staleBaseAheadByThreshold-- an opt-in per-repo commit-count threshold. When set, the pre-review readiness gate (prReadyForReview) forces anupdate_branchonce the repository's default branch has advanced at least that many commits beyond a PR's head, using the same (now-correct) compare-API read. This closes a real blind spot in the existing BEHIND-base auto-rebase path:mergeable_state: "behind"only ever fires when a repo's branch protection has "require branches up to date before merging" enabled -- a repo without that setting can have a PR genuinely dozens of commits behind and GitHub will never surface it, so the existing auto-rebase-before-review flow silently never fires. This is config-as-code only (mirrorsrequireFreshRebaseWindowMinutes's own shape/rationale): DB column + migration, settings resolver,.loopover.ymlgate:schema (engine package + docs), API/OpenAPI schema, and the behavioral wiring, fully wired end to end.Scope
type(scope): short summaryConventional Commit format.CONTRIBUTING.mdand does not reintroduce GitHub Pages, VitePress,site/, orCNAME.Validation
git diff --checknpm run actionlint,npm run lint:composite-actionsnpm run db:migrations:check,npm run db:schema-drift:checknpm run selfhost:env-reference:check,npm run miner:env-reference:checknpm run selfhost:validate-observabilitynpm run cf-typegen:checknpm run typechecknpm run test:coverage(unsharded) -- every line/branch touched by this diff verified 100% covered directly against lcov.info, not just the console tablenpm run test:engine-parity,npm run test:live-gate-parity,npm run test:driver-paritynpm run test --workspace @loopover/enginenpm run test:workersnpm run build:mcp,npm run test:mcp-packnpm run ui:openapi:check,npm run ui:openapi:settings-paritynpm run docs:drift-check,npm run manifest:drift-check,npm run engine-parity:drift-checknpm run command-reference:check,npm run branding-drift:check,npm run engines-nvmrc:check,npm run release-manifest:sync:checknpm run ui:lint,npm run ui:typecheck,npm run ui:buildnpm audit --audit-level=moderate-- 0 vulnerabilitiesnpm run test:cirun caught and this PR fixes a realconfig/examples/loopover.full.ymldrift (the new.loopover.yml.exampledoc block needed the same addition in its byte-matched sibling) -- confirmed green after the fix.prReadyForReviewbranches (threshold met/not-met/unconfigured/no-default-branch/denied-autonomy), mirroringrequireFreshRebaseWindowMinutes's own existing test coverage pattern site-by-site.Safety
npm run ui:openapiregenerated).UI Evidencesection -- N/A, no UI changes..loopover.yml.example+ its byte-matchedconfig/examples/loopover.full.ymlsibling); changelog itself intentionally not touched (release-prep only).Notes
The new
staleBaseAheadByThresholdsetting is opt-in and defaults tonull(off) for every existing repo -- zero behavior change until a repo's.loopover.yml(or the dashboard/API settings) explicitly sets it. Activating it for any of the maintainer's own gated repos is a private server-config change, not something this PR does.