diff --git a/.changeset/FN-6335-zero-step-workflow-defaults.md b/.changeset/FN-6335-zero-step-workflow-defaults.md new file mode 100644 index 0000000000..327f2e77d3 --- /dev/null +++ b/.changeset/FN-6335-zero-step-workflow-defaults.md @@ -0,0 +1,5 @@ +--- +"@runfusion/fusion": patch +--- + +Record explicit `builtin:coding` project-default workflow selections even when the compiled built-in has zero materialized steps, while preserving interpreter-deferred `builtin:stepwise-coding` fallback behavior. diff --git a/packages/core/src/__tests__/builtin-workflows.test.ts b/packages/core/src/__tests__/builtin-workflows.test.ts index d0d0bd14e3..2a7ab7dd57 100644 --- a/packages/core/src/__tests__/builtin-workflows.test.ts +++ b/packages/core/src/__tests__/builtin-workflows.test.ts @@ -380,10 +380,24 @@ describe("built-in workflows", () => { expect((await store.getTask(codingTask.id)).enabledWorkflowSteps ?? []).toEqual([]); expect(store.getTaskWorkflowSelection(codingTask.id)).toEqual({ workflowId: "builtin:coding", stepIds: [] }); + const reservedCodingTask = await store.createTaskWithReservedId( + { description: "reserved default builtin coding" }, + { taskId: "reserved-default-builtin-coding" }, + ); + expect((await store.getTask(reservedCodingTask.id)).enabledWorkflowSteps ?? []).toEqual([]); + expect(store.getTaskWorkflowSelection(reservedCodingTask.id)).toEqual({ workflowId: "builtin:coding", stepIds: [] }); + await store.setDefaultWorkflowId("builtin:stepwise-coding"); const stepwiseTask = await store.createTask({ description: "default builtin stepwise" }); expect((await store.getTask(stepwiseTask.id)).enabledWorkflowSteps ?? []).toEqual([]); expect(store.getTaskWorkflowSelection(stepwiseTask.id)).toBeUndefined(); + + const reservedStepwiseTask = await store.createTaskWithReservedId( + { description: "reserved default builtin stepwise" }, + { taskId: "reserved-default-builtin-stepwise" }, + ); + expect((await store.getTask(reservedStepwiseTask.id)).enabledWorkflowSteps ?? []).toEqual([]); + expect(store.getTaskWorkflowSelection(reservedStepwiseTask.id)).toBeUndefined(); }); it("rejects selecting the PR lifecycle fragment for a task", async () => { diff --git a/packages/core/src/store.ts b/packages/core/src/store.ts index 072bfa0882..cca5349662 100644 --- a/packages/core/src/store.ts +++ b/packages/core/src/store.ts @@ -14912,6 +14912,8 @@ ${stepsSection}`; // default falls back cleanly with nothing written. Interpreter-deferred // built-ins are valid selectable workflows but not lowerable to legacy // WorkflowStep rows, so default materialization falls back to legacy defaults. + // Built-ins that compile to zero steps still record a stepless selection, + // mirroring explicit workflow materialization. let inputs: import("./types.js").WorkflowStepInput[]; try { inputs = compileWorkflowToSteps(def.ir); @@ -14920,7 +14922,7 @@ ${stepsSection}`; throw err; } if (isBuiltinWorkflowId(workflowId) && inputs.length === 0) { - return undefined; + return { workflowId, stepIds: [] }; } const stepIds = await this.materializeWorkflowSteps(workflowId, inputs); return { workflowId, stepIds };