fix(FN-5627): always rebase behind branches before squash (safety fallback)
The FN-5627 default-threshold fix changed the prerebase threshold default from 0 (never fire on commit-count) to 1 (fire on any divergence). But that only affected projects WITHOUT an explicit threshold. Projects with user-set values like 'prerebaseDivergenceThreshold: 50' continued to skip prerebase for small divergences (e.g., 4 commits behind), so the squash built against stale base and update-ref refused non-FF \u2014 producing the same-SHA spurious-concurrent-advance signature that stranded FN-5626/FN-5628/FN-5633. Root distinction missed earlier: - prerebaseDivergenceThreshold is for USER-VISIBLE SEVERITY REPORTING (this branch is N commits behind, warn me). - Engine correctness requires a SAFETY INVARIANT (any branch behind main MUST be rebased before squash or update-ref will fail). These are independent concerns. The safety invariant must not be gated on the user's threshold. decideAutoPrerebase() now returns fire=true with reason 'safety-fallback-any-divergence' whenever commitsBehind > 0, after the hot-file and threshold checks. The threshold path still wins the reason label when its condition trips, so user-visible severity reporting is unchanged for non-pathological cases. Full opt-out remains prerebaseAutoEnabled=false (skips the safety fallback; user accepts behind-branch merges will fail). prerebaseDivergenceThreshold=0 is no longer a complete opt-out from the commit-count gate \u2014 it only suppresses the threshold-based reason label. Tests (4 updated/new): - safety-fallback-any-divergence reason added to AutoPrerebaseDecision - 4 commits behind with threshold=50 fires via safety fallback - prerebaseAutoEnabled=false respects full opt-out - threshold trip still wins reason label - commitsBehind=0 returns no-divergence (unchanged) Engine suite: 6163 tests pass. In-flight: FN-5626, FN-5628, FN-5633 manually SQL-reset to mergeRetries=0, status=null, error=null, transientRecoveryCount=0 so the next merger tick (after engine restart picks up this code) auto-prerebases via safety fallback and lands the work. Future occurrences self-heal automatically. Fusion-Task-Id: FN-5627
This commit is contained in:
24
.changeset/FN-5627-prerebase-safety-fallback.md
Normal file
24
.changeset/FN-5627-prerebase-safety-fallback.md
Normal file
@@ -0,0 +1,24 @@
|
||||
---
|
||||
"@runfusion/fusion": patch
|
||||
---
|
||||
|
||||
fix(FN-5627): always rebase behind branches before squash regardless of user-configured prerebase threshold
|
||||
|
||||
After the FN-5627 default-threshold fix landed (threshold=1 default), tasks were still getting stuck at `mergeRetries=3` with `Integration branch main advanced concurrently (expected X, observed X)` errors because user projects with explicit `prerebaseDivergenceThreshold` values higher than the branch's commits-behind count still skipped prerebase entirely.
|
||||
|
||||
Example: a project with `prerebaseDivergenceThreshold: 50` for low-noise PR experience would skip prerebase on a task branched 4 commits behind main. The squash commit then doesn't descend from current main, and `git update-ref` correctly refuses the non-fast-forward advance — producing the misleading same-SHA error signature that stranded FN-5626, FN-5628, FN-5633.
|
||||
|
||||
Root distinction missed in the earlier fix: the user-configurable `prerebaseDivergenceThreshold` controls the *user-visible severity reporting* ("this branch is N commits behind"), while engine correctness requires a *safety invariant* ("any branch behind main MUST be rebased before squash, or update-ref will fail"). These are independent concerns.
|
||||
|
||||
New behavior:
|
||||
- After the hot-file and threshold checks, `decideAutoPrerebase()` now returns `fire: true` with `reason: "safety-fallback-any-divergence"` whenever `commitsBehind > 0`.
|
||||
- The threshold-based path still wins when tripped (so user-visible audit `reason` reflects the configured policy when applicable).
|
||||
- Full opt-out remains `prerebaseAutoEnabled: false` — that case skips the safety fallback too, and the user accepts that behind-branch merges will fail.
|
||||
- `prerebaseDivergenceThreshold: 0` is no longer a complete opt-out from the commit-count gate — it only suppresses the threshold-based reason label. Safety fallback still fires.
|
||||
|
||||
Tests:
|
||||
- New `safety-fallback-any-divergence` reason added to `AutoPrerebaseDecision.reason` union.
|
||||
- 4 commits behind with threshold=50 → fires via safety fallback (was: skipped).
|
||||
- `prerebaseAutoEnabled=false` → no fire (full opt-out preserved).
|
||||
- Configured threshold tripping still wins the `reason` label.
|
||||
- Branch fully up-to-date (commitsBehind=0) → no-divergence (unchanged).
|
||||
Reference in New Issue
Block a user