diff --git a/.changeset/fn-6193-merger-deleted-task.md b/.changeset/fn-6193-merger-deleted-task.md new file mode 100644 index 0000000000..b646f69c68 --- /dev/null +++ b/.changeset/fn-6193-merger-deleted-task.md @@ -0,0 +1,5 @@ +--- +"@runfusion/fusion": patch +--- + +Fix merger AI commit finalization so deleted tasks no longer crash settings resolution while the merge is completing. diff --git a/packages/engine/src/__tests__/merger-settings-degrade.test.ts b/packages/engine/src/__tests__/merger-settings-degrade.test.ts new file mode 100644 index 0000000000..f7f8b9cdf3 --- /dev/null +++ b/packages/engine/src/__tests__/merger-settings-degrade.test.ts @@ -0,0 +1,43 @@ +import { describe, expect, it, vi } from "vitest"; + +import { BUILTIN_WORKFLOW_SETTINGS, type Settings } from "@fusion/core"; +import { mergeEffectiveSettings } from "../effective-settings.js"; + +const PROJECT = "proj-1"; + +function baseSettings(): Settings { + const catalogDefaults = Object.fromEntries( + BUILTIN_WORKFLOW_SETTINGS + .filter((setting) => setting.default !== undefined) + .map((setting) => [setting.id, setting.default]), + ); + return { + ...catalogDefaults, + persistAgentToolOutput: false, + executionProvider: "project-anthropic", + executionModelId: "claude-project", + } as unknown as Settings; +} + +describe("merger settings degrade path", () => { + it("uses a fallback task id so deleted-task getTask failures still return base settings", async () => { + const taskId = "FN-6193-DELETED"; + const store = { + getTask: vi.fn(async () => { + throw new Error(`Task ${taskId} not found`); + }), + getTaskWorkflowSelection: vi.fn(() => { + throw new Error(`Task ${taskId} not found`); + }), + getWorkflowDefinition: vi.fn(async () => undefined), + getWorkflowSettingValues: vi.fn(() => ({})), + getWorkflowSettingsProjectId: vi.fn(() => PROJECT), + }; + const base = baseSettings(); + + const taskForSettings = await store.getTask(taskId).catch(() => ({ id: taskId } as const)); + const merged = await mergeEffectiveSettings(store as any, taskForSettings, base); + + expect(merged).toEqual(base); + }); +}); diff --git a/packages/engine/src/merger.ts b/packages/engine/src/merger.ts index d76103d78b..81fe69852a 100644 --- a/packages/engine/src/merger.ts +++ b/packages/engine/src/merger.ts @@ -11679,9 +11679,10 @@ async function runAiAgentForCommit(params: AiAgentParams): Promise<{ success: bo // Merge per-task effective workflow settings (U3, KTD-3) — this worker re-fetches // settings independently of aiMergeTask, so apply the same merge here (covers the // titleSummarizer lane reads in resolveSafeCommitBody). Behavior-inert by default. + const taskForSettings = await store.getTask(taskId).catch(() => ({ id: taskId } as const)); const settings = await mergeEffectiveSettings( store, - await store.getTask(taskId), + taskForSettings, await store.getSettings(), );