feat(FN-4069): add direct merge commit routing to merger

Adds direct merge commit routing to the merger, allowing non-squash merges to bypass the squash-audit path when configured. The feature includes new `mergeCommitStrategy` settings, updated dashboard UI, expanded merger lifecycle tests, and documentation.

Fusion-Task-Id: FN-4069
This commit is contained in:
Fusion
2026-05-12 15:50:22 -07:00
committed by gsxdsm
parent dfb613e2f1
commit be5e1fbd97
17 changed files with 899 additions and 135 deletions

View File

@@ -77,6 +77,12 @@ describe("settings key parity", () => {
expect(DEFAULT_PROJECT_SETTINGS.completionDocumentationMode).toBe("off");
});
it("keeps directMergeCommitStrategy project-scoped with auto default", () => {
expect(DEFAULT_PROJECT_SETTINGS.directMergeCommitStrategy).toBe("auto");
expect(isProjectSettingsKey("directMergeCommitStrategy")).toBe(true);
expect(isGlobalSettingsKey("directMergeCommitStrategy")).toBe(false);
});
it("keeps task stuck timeout active by default without coupling to workflow step timeout", () => {
expect(DEFAULT_PROJECT_SETTINGS.taskStuckTimeoutMs).toBe(600_000);
expect(DEFAULT_PROJECT_SETTINGS.workflowStepTimeoutMs).toBe(360_000);

View File

@@ -1,5 +1,6 @@
import { describe, expect, it } from "vitest";
import {
validateDirectMergeCommitStrategy,
validateGithubAuthMode,
validateGithubRepoSlug,
validateUnavailableNodePolicy,
@@ -19,6 +20,20 @@ describe("settings-validation", () => {
});
});
describe("validateDirectMergeCommitStrategy", () => {
it("accepts supported direct-merge routing values", () => {
expect(validateDirectMergeCommitStrategy("auto")).toBe("auto");
expect(validateDirectMergeCommitStrategy("always-squash")).toBe("always-squash");
expect(validateDirectMergeCommitStrategy("always-rebase")).toBe("always-rebase");
});
it("returns undefined for invalid routing values", () => {
expect(validateDirectMergeCommitStrategy("squash")).toBeUndefined();
expect(validateDirectMergeCommitStrategy(123)).toBeUndefined();
expect(validateDirectMergeCommitStrategy(undefined)).toBeUndefined();
});
});
describe("validateGithubAuthMode", () => {
it("accepts supported auth modes", () => {
expect(validateGithubAuthMode("gh-cli")).toBe("gh-cli");

View File

@@ -61,6 +61,15 @@ describe("TaskStore", () => {
const settings = await harness.store().getSettings();
expect(settings.mergeStrategy).toBe("pull-request");
});
it("defaults directMergeCommitStrategy to auto and persists updates", async () => {
const defaults = await harness.store().getSettings();
expect(defaults.directMergeCommitStrategy).toBe("auto");
await harness.store().updateSettings({ directMergeCommitStrategy: "always-rebase" });
const settings = await harness.store().getSettings();
expect(settings.directMergeCommitStrategy).toBe("always-rebase");
});
});
// ── Planning/Validator Model Settings ────────────────────────────