diff --git a/packages/engine/src/executor.ts b/packages/engine/src/executor.ts index d82cdbfbe..b3bedf3e3 100644 --- a/packages/engine/src/executor.ts +++ b/packages/engine/src/executor.ts @@ -4347,11 +4347,45 @@ export class TaskExecutor { return; } + // Sase setup: Fusion only writes to origin/dev (main is human-merged from dev). + // Local `main` is never auto-updated, so the default `mainRef = "main"` makes the + // detector compare against a stale ref and mis-flag legit merged commits as foreign. + // Settings expose `worktreeRebaseRemote` (= "origin") and `baseBranch` (= "dev"); + // prefer the project's deploy branch (origin/) and fall back to origin/main + // then "main" so non-sase projects keep current behavior. + const settingsForContamination = await this.store.getSettings(); + const baseBranchSetting = (settingsForContamination as { baseBranch?: string }).baseBranch; + const remoteSetting = (settingsForContamination as { worktreeRebaseRemote?: string }).worktreeRebaseRemote; + const remoteName = typeof remoteSetting === "string" && remoteSetting.trim().length > 0 + ? remoteSetting.split(/\s+/)[0] + : "origin"; + const resolveContaminationRef = async (ref: string): Promise => { + try { + const { stdout } = await execAsync(`git -C "${this.rootDir}" rev-parse --verify ${ref}`, { timeout: 5000 }); + return stdout.trim() ? ref : null; + } catch { + return null; + } + }; + const contaminationMainRef = + (typeof baseBranchSetting === "string" && baseBranchSetting.trim().length > 0 + ? await resolveContaminationRef(`${remoteName}/${baseBranchSetting.trim()}`) + : null) + ?? (await resolveContaminationRef(`${remoteName}/main`)) + ?? "main"; + await this.store.logEntry( + task.id, + `[recovery] using contamination mainRef=${contaminationMainRef}`, + undefined, + this.currentRunContext, + ); + const classified = await classifyForeignCommits({ repoDir: this.rootDir, branchName: err.branchName, baseSha: err.baseSha, foreignCommits: err.foreignCommits, + mainRef: contaminationMainRef, }); const alreadyShas = classified.alreadyUpstream.map((commit) => commit.sha.slice(0, 12)).join(", ") || "none";