Skip to content

Look up an incremental baseline by commit ancestry before branch names (v1.16.2) - #182

Merged
Ibrahimrahhal merged 4 commits into
mainfrom
cursor/ancestry-first-baseline-b3b6
Oct 5, 2026
Merged

Ibrahimrahhal merged 4 commits into
mainfrom
cursor/ancestry-first-baseline-b3b6

Conversation

@Ibrahimrahhal

@Ibrahimrahhal Ibrahimrahhal commented Oct 4, 2026 •

Copy link
Copy Markdown
Member

What

Changes the order corgea scan blast uses to pick the baseline scan for an incremental scan.

Before: the branch being scanned → the nearest of the last 10 commits → trunk (origin/HEAD, main, master).

After:

  1. Nearest scanned ancestor commit. Look at up to 20 commits behind HEAD, asking about 10 at a time, nearest first. Take the scan of the closest commit, whatever branch it was recorded under. The second batch of 10 is only requested if the first batch has no usable scan.
  2. Only if none was found: the branch being scanned, then trunk (origin/HEAD, main, master). Same behavior as before, including the clean-only second walk per branch group.

Why

A scan of a commit HEAD descends from differs from this upload by exactly what the history has done since. That makes it the most reliable baseline. A branch's newest scan can be of a commit this checkout is behind or was rebased away from. Trunk's newest scan also includes whatever trunk did after the branch forked.

Details

  • Closest commit wins: fewest commits back wins, then a commit on HEAD's first-parent line, then a scan with readable checksums, then the newest.
  • Merge commits: both parents of a merge are one commit back. The first parent wins the tie, because the diff from it is the merge itself. The diff from the other parent is everything the first line did since the fork, which can go past the server's 300-file limit. The other side is still used when the first parent was never scanned.
  • Paging: the server orders scans by recency, not by distance from HEAD, so a batch is now read across pages (up to the existing 3-page budget). It stops early once it has the best rank any commit in the batch could give. Before, the CLI stopped at the first page with any match, which could miss a nearer commit's scan on page 2.
  • Errors: if a later page of a batch fails after a scan was already found, that scan is used. If the commit lookup fails outright, the CLI falls back to the branch lookups, as before.
  • Shallow clones: the history walk stops at the clone's depth, so a depth-1 clone sends just HEAD, then falls back to the branch lookups. A branch baseline outside the clone can still be diffed through its stored checksums. Without checksums, the run scans every file and suggests fetch-depth: 0.
  • "No baseline" message: now lists the commits first, then the branches. It reads "the only commit in this checkout's history" when only HEAD is reachable.

Tests

  • Updated the end-to-end request plans for the new order.
  • Added a_scan_beyond_the_first_ten_commits_is_found_by_the_second_batch.
  • Added the_closest_commit_wins_even_when_its_scan_is_on_a_later_page.
  • Added between_the_parents_of_a_merge_the_first_parent_wins, and extended the merge-walk test to check which commits are on the first-parent line.
  • Added a_shallow_clone_offers_only_the_commits_it_holds, a unit test using a real git clone --depth 1 and --depth 2.
  • Added a_shallow_clone_asks_about_the_commits_it_holds_then_falls_back_to_the_branch, an end-to-end run from a depth-1 clone, with and without stored checksums.
  • ./harness check passes.
Open in Web Open in Cursor 

cursoragent and others added 2 commits October 4, 2026 11:12
Search the 20 nearest commits behind HEAD in batches of 10, nearest first,
and take the scan of the closest commit, reading every page of a batch so a
nearer commit's scan on a later page is not missed. Fall back to the branch
being scanned, then trunk, only when none of those commits was scanned.

Co-authored-by: ibrahim <ibrahim@corgea.com>
A shallow clone holds its boundary commit's parent ids but not the parents,
so the commit lookup asks only about the commits the clone has, then falls
back to the branch lookups. Covered with a real git clone --depth, and the
no-baseline message no longer says 'the 1 most recent commits'.

Co-authored-by: ibrahim <ibrahim@corgea.com>
@Ibrahimrahhal
Ibrahimrahhal marked this pull request as ready for review October 4, 2026 11:20

@corgea-security corgea-security left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review risk: 2/5.

The baseline-selection change is coherent and well covered by focused tests. No actionable critical, high-priority, or non-blocking defects are supported by the supplied diff.

No critical or high-priority changes were found.

@corgea-security corgea-security added the dennis-reviewed Dennis completed an automated review label Oct 4, 2026

@corgea-security corgea-security left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved by Dennis: high policy risk and automated risk 2/5.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On a merge commit both parents are the same distance, and the newer one wins. Ancestry now runs before the branch lookup, so that newer parent becomes the baseline: the feature tip when landing on trunk, or trunk when a long-lived branch merges trunk in. The diff is the other line's work since the fork, and past the server's 300-file cap the run scans the whole tree. The first parent is the scan this order used to take.

Open in Web View Automation 

Sent by Cursor Automation: pr-flow

Comment thread src/incremental.rs
Comment on lines +471 to +480
/// Order among scans found by ancestry, lowest best: fewest commits back,
/// then one this run can diff by its checksums over one it cannot.
fn ancestor_rank(&self, checksums_usable: bool) -> (usize, bool) {
let readable_checksums = self.manifest_root.is_some()
&& self.manifest_version.as_deref() == Some(MANIFEST_VERSION);
(
self.commits_back.unwrap_or(usize::MAX),
!(checksums_usable && readable_checksums),
)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both parents of a merge are the same distance. Ancestry::walk stores depth + 1 for every parent, and the_walk_follows_both_sides_of_a_merge_and_skips_other_branches asserts both are 1. This rank is (commits_back, without_checksums); nearest_ancestor_baseline then breaks the tie with page position, and the server lists newest first, so the newer parent wins.

plan_diff only calls find_baseline when this lookup returns NotFound, so the tie is the baseline whenever both parents were scanned. On a merge that is the second parent. The diff from it is every file the other line changed after the fork. The server full-scans above 300 (INCREMENTAL_SCAN_MAX_FILES, the comment on MAX_CHANGED_FILES). The diff from the first parent is the merge. Before this change the branch lookup returned that scan and never reached this rank.

is_usable_baseline drops a scan only when pull_request_id is set. A branch scan from this CLI leaves it empty, so the other side stays eligible. the_nearest_ancestor_scan_wins_whatever_branch_it_names only covers a strictly smaller commits_back.

Walk parent(0) into a set, capped at ANCESTOR_LOOKUP_COMMITS (a missing parent ends it, which is already where a shallow clone stops), and set on_first_parent on the BaselineScan built in nearest_ancestor_baseline. A second-parent scan is still the baseline when the first parent was never scanned. unbeatable at line 844 has to be this same triple, using that sha's own off-spine bit, so a checksum scan of HEAD still stops the page walk.

Suggested change
/// Order among scans found by ancestry, lowest best: fewest commits back,
/// then one this run can diff by its checksums over one it cannot.
fn ancestor_rank(&self, checksums_usable: bool) -> (usize, bool) {
let readable_checksums = self.manifest_root.is_some()
&& self.manifest_version.as_deref() == Some(MANIFEST_VERSION);
(
self.commits_back.unwrap_or(usize::MAX),
!(checksums_usable && readable_checksums),
)
}
/// Order among scans found by ancestry, lowest best: fewest commits back,
/// then one on this checkout's first-parent line over the other side of a
/// merge, then one this run can diff by its checksums over one it cannot.
fn ancestor_rank(&self, checksums_usable: bool) -> (usize, usize, bool) {
let readable_checksums = self.manifest_root.is_some()
&& self.manifest_version.as_deref() == Some(MANIFEST_VERSION);
(
self.commits_back.unwrap_or(usize::MAX),
usize::from(!self.on_first_parent),
!(checksums_usable && readable_checksums),
)
}

The suggestion needs on_first_parent: bool on BaselineScan (false from from_response) and HashSet on the walk; it does not compile on its own. Add a unit test on the existing merge fixture: both parents scanned, the second parent's scan newer, the first parent returned.

cursoragent and others added 2 commits October 4, 2026 13:03
Both parents of a merge sit one commit back, so recency decided between
them and the merged-in side could win. Its diff is everything the first
line did since the fork, which can outgrow an incremental scan; the diff
from the first parent is the merge itself. Rank first-parent ancestors
ahead at equal distance, and compute the page walk's early-stop rank over
the whole batch.

Co-authored-by: ibrahim <ibrahim@corgea.com>
Co-authored-by: ibrahim <ibrahim@corgea.com>
@cursor cursor Bot changed the title Look up an incremental baseline by commit ancestry before branch names Look up an incremental baseline by commit ancestry before branch names (v1.16.2) Oct 5, 2026
@Ibrahimrahhal
Ibrahimrahhal merged commit e7d6fe6 into main Oct 5, 2026
18 checks passed
@Ibrahimrahhal
Ibrahimrahhal deleted the cursor/ancestry-first-baseline-b3b6 branch October 5, 2026 08:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dennis-reviewed Dennis completed an automated review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants