fix(FN-5627): default auto-prerebase to fire when branch >=1 commit behind
decideAutoPrerebase() previously defaulted prerebaseDivergenceThreshold to 0, which meant the threshold path NEVER fired unless the user explicitly set a positive value. Only hot-file matches could trigger prerebase. The result: tasks whose branch was started against an older main tip (because other tasks landed concurrently) skipped prerebase, built their squash commit against the stale base, and then failed at git update-ref because the squash didn't descend from current main. The merger correctly detected this as non-fast-forward and threw IntegrationBranchConcurrentAdvanceError, but with both 'expected' and 'observed' SHAs set to current main tip \u2014 because observedCurrentSha was captured from the pre-update rev-parse, not post-failure. This produced the misleading 'expected X, observed X' same-SHA error signature that stranded FN-5632 stuck at mergeRetries=3 after the FN-5627 merger fix and engine restart. New default: prerebaseDivergenceThreshold = 1. Any branch behind by at least 1 commit auto-rebases before squash. Users who want the legacy never-fire behavior can explicitly set prerebaseDivergenceThreshold = 0. Threshold comparison also changed from > to >= so an explicit threshold of N rebases at N+ commits behind instead of N+1+. The self-healing classifier comment for spurious-concurrent-advance-same-sha is updated to note the signature can come from either pre-FN-5627 misclassification OR the legitimate post-FN-5627 non-FF path; the auto-recovery sweep is unchanged because both cases self-heal cleanly once prerebase fires on the retry. Tests (3 new): - Default threshold (undefined) fires at 1 commit behind - Explicit threshold = 0 stays as opt-out (never fire on commit-count) - Default threshold doesn't fire when branch is up-to-date Engine suite: 6160 tests pass. In-flight: FN-5632 manually SQL-reset to mergeRetries=0 / status=null once more so the next merger tick (after engine restart picks up this code) auto-prerebases and lands the work. Future occurrences self-recover. Fusion-Task-Id: FN-5627
This commit is contained in:
@@ -49,6 +49,63 @@ describe("decideAutoPrerebase", () => {
|
||||
expect(decision.fire).toBe(false);
|
||||
expect(decision.reason).toBe("no-divergence");
|
||||
});
|
||||
|
||||
it("FN-5627: fires on default threshold (1 commit) when prerebaseDivergenceThreshold is undefined", () => {
|
||||
// Pre-FN-5627 default behavior: undefined threshold meant 'never fire on
|
||||
// commit-count'. This left tasks that branched off older main tips with
|
||||
// no recourse — the merger would build the squash against the stale
|
||||
// base, update-ref would refuse non-FF, and IntegrationBranchConcurrentAdvanceError
|
||||
// surfaced with a misleading same-SHA pair (the exact signature that
|
||||
// stranded FN-5632). New default: threshold=1, fire on any divergence.
|
||||
const settingsNoThreshold = {
|
||||
prerebaseAutoEnabled: true,
|
||||
prerebaseHotFiles: ["AGENTS.md"],
|
||||
// prerebaseDivergenceThreshold intentionally undefined
|
||||
};
|
||||
const decision = decideAutoPrerebase({
|
||||
settings: settingsNoThreshold,
|
||||
baseCommitSha: "abc",
|
||||
commitsBehind: 1,
|
||||
changedFiles: ["x.ts"],
|
||||
worktrunkEnabled: false,
|
||||
});
|
||||
expect(decision.fire).toBe(true);
|
||||
expect(decision.reason).toBe("divergence-threshold");
|
||||
expect(decision.commitsBehind).toBe(1);
|
||||
});
|
||||
|
||||
it("FN-5627: respects explicit prerebaseDivergenceThreshold = 0 as opt-out (never fire on commit-count)", () => {
|
||||
const settingsOptOut = {
|
||||
prerebaseAutoEnabled: true,
|
||||
prerebaseHotFiles: ["AGENTS.md"],
|
||||
prerebaseDivergenceThreshold: 0,
|
||||
};
|
||||
const decision = decideAutoPrerebase({
|
||||
settings: settingsOptOut,
|
||||
baseCommitSha: "abc",
|
||||
commitsBehind: 100,
|
||||
changedFiles: ["x.ts"],
|
||||
worktrunkEnabled: false,
|
||||
});
|
||||
expect(decision.fire).toBe(false);
|
||||
expect(decision.reason).toBe("no-divergence");
|
||||
});
|
||||
|
||||
it("FN-5627: default threshold doesn't fire when branch is up-to-date", () => {
|
||||
const settingsNoThreshold = {
|
||||
prerebaseAutoEnabled: true,
|
||||
prerebaseHotFiles: ["AGENTS.md"],
|
||||
};
|
||||
const decision = decideAutoPrerebase({
|
||||
settings: settingsNoThreshold,
|
||||
baseCommitSha: "abc",
|
||||
commitsBehind: 0,
|
||||
changedFiles: [],
|
||||
worktrunkEnabled: false,
|
||||
});
|
||||
expect(decision.fire).toBe(false);
|
||||
expect(decision.reason).toBe("no-divergence");
|
||||
});
|
||||
});
|
||||
|
||||
describeIfGit("merger-auto-prerebase git integration", () => {
|
||||
|
||||
Reference in New Issue
Block a user