From c0bef0bfbef14208c27bb4191cd9c4aa7848e1cc Mon Sep 17 00:00:00 2001 From: gsxdsm Date: Wed, 15 Jul 2026 16:47:01 -0700 Subject: [PATCH] FN-7969: deprecate unused builtin Coding (Ideas) workflow Hide builtin:coding-ideas from new selection after occupancy preflight, while keeping it resolvable for any existing task selections. - Add builtin:coding-ideas to DEPRECATED_BUILTIN_WORKFLOW_IDS so it is excluded from defaultEnabledBuiltinWorkflowIds and listWorkflowDefinitions selection listings - Keep getBuiltinWorkflow / direct resolution working for pre-existing Coding (Ideas) task selections - Document deprecation and custom-workflow copy path in dashboard-guide and workflow-steps - Extend builtin-workflows and settings-sections tests for hide-from-selection + management/resolution retention - Add minor changeset for @runfusion/fusion Files changed: .changeset/fn-7969-deprecate-coding-ideas.md | 7 +++++++ docs/dashboard-guide.md | 2 +- docs/workflow-steps.md | 2 +- .../core/src/__tests__/builtin-workflows.test.ts | 28 ++++++++++++++-------- packages/core/src/builtin-workflows.ts | 9 +++---- packages/core/src/types.ts | 9 ++++--- .../app/__tests__/settings-sections.test.tsx | 2 ++ 7 files changed, 43 insertions(+), 16 deletions(-) Fusion-Task-Id: FN-7969 Fusion-Task-Lineage: 578ae727-e1b6-4ff9-a3a2-d1228c50fba6 Co-authored-by: Fusion (runfusion.ai) --- .changeset/fn-7969-deprecate-coding-ideas.md | 7 +++++ docs/dashboard-guide.md | 2 +- docs/workflow-steps.md | 2 +- .../src/__tests__/builtin-workflows.test.ts | 28 ++++++++++++++----- packages/core/src/builtin-workflows.ts | 9 +++--- packages/core/src/types.ts | 9 ++++-- .../app/__tests__/settings-sections.test.tsx | 2 ++ 7 files changed, 43 insertions(+), 16 deletions(-) create mode 100644 .changeset/fn-7969-deprecate-coding-ideas.md diff --git a/.changeset/fn-7969-deprecate-coding-ideas.md b/.changeset/fn-7969-deprecate-coding-ideas.md new file mode 100644 index 0000000000..9518aef771 --- /dev/null +++ b/.changeset/fn-7969-deprecate-coding-ideas.md @@ -0,0 +1,7 @@ +--- +"@runfusion/fusion": minor +--- + +summary: Deprecate the built-in Coding (Ideas) workflow — it no longer appears for new task selection. +category: internal +dev: builtin:coding-ideas is excluded from defaultEnabledBuiltinWorkflowIds() and hidden from listWorkflowDefinitions via the shared DEPRECATED_BUILTIN_WORKFLOWS registry / isBuiltinWorkflowDeprecated helper; it remains resolvable by id for existing task selections. Applied only after a preflight verified no active task (including parked ideas in the `ideas` intake column) selects it. diff --git a/docs/dashboard-guide.md b/docs/dashboard-guide.md index 25ee65387a..2be07c9df5 100644 --- a/docs/dashboard-guide.md +++ b/docs/dashboard-guide.md @@ -484,7 +484,7 @@ The **New Task** dialog's workflow selector also defaults to the current or last -Create requests never send an explicit `column`. The task store resolves the landing column from the (selected or project-default) workflow's intake column, so most tasks still land in `triage` under the default Coding workflow, byte-identical to before. A workflow with a **manual intake column** — for example the built-in **Coding (Ideas)** workflow's `ideas` column (`autoTriage: false`) — parks new cards there instead: they wait for you to promote them into `todo` and are not auto-planned by the triage service until you do. +Create requests never send an explicit `column`. The task store resolves the landing column from the (selected or project-default) workflow's intake column, so most tasks still land in `triage` under the default Coding workflow, byte-identical to before. A workflow with a **manual intake column** parks new cards there instead: they wait for you to promote them into `todo` and are not auto-planned by the triage service until you do. The built-in **Coding (Ideas)** `ideas` composition (`autoTriage: false`) is deprecated and hidden from new selection; copy it into a custom workflow when that manual-intake behavior is needed. Existing Coding (Ideas) selections remain resolvable. Optional workflow steps declared by the active workflow are available from the quick-add action row and the **New Task** dialog's inline quick buttons. For example, the coding workflow's browser verification option appears as a quick drop-down when that workflow is active; each option is seeded from the workflow step's `defaultOn` setting and is sent with the task's `enabledWorkflowSteps` payload at creation time. diff --git a/docs/workflow-steps.md b/docs/workflow-steps.md index 37b65abb12..1898178dc8 100644 --- a/docs/workflow-steps.md +++ b/docs/workflow-steps.md @@ -83,7 +83,7 @@ Use this inventory as the documentation map for current workflow behavior: | Routing boundary | Agents may select/change a workflow only for explicit user requests or tasks they created; no-commit markers do not imply Quick fix or any other workflow. | This page, [Selecting workflows](#selecting-workflows); [Agents](./agents.md#interactive-cli-chat). | | Dashboard board/list/graph selection | Board/List/Header/Graph share durable per-project workflow selection; stale saved ids fall back to a valid workflow. Board adds a dashboard-only **All workflows** aggregate and task workflow-name badges; Graph uses **All workflows** for the full active graph. | [Dashboard Guide → Board View](./dashboard-guide.md#board-view), [Graph View](./dashboard-guide.md#graph-view), and [Workflow Selection and Editor](./dashboard-guide.md#workflow-selection-and-editor). | | Create/planning forwarding | Quick-create task creation, Planning Mode, Subtask Breakdown, and the New Task dialog forward the active real workflow id when creating tasks; **All workflows** quick-create chooses a real workflow intake/default column instead of saving a synthetic aggregate id. | [Dashboard Guide → Planning Mode](./dashboard-guide.md#planning-mode). | -| Manual-intake column parking | Dashboard create surfaces never send an explicit `column`; the store resolves the landing column from the (selected or project-default) workflow's intake column. A workflow whose intake column sets `autoTriage: false` (e.g. built-in Coding (Ideas)'s `ideas` column) parks new cards there instead of auto-planning them, until an operator promotes the card. The full lifecycle — create → parked → operator "Start" promotion → poll-time todo-discovery of the still-unplanned (bootstrap-stub) card — is regression-tested at the engine (triage poll ordering/discovery), UI (`TaskCard` Start affordance), and store (create → `moveTask` promotion) layers (FN-7596). | [Dashboard Guide → Create/Planning Forwarding](./dashboard-guide.md#planning-mode). | +| Manual-intake column parking | Dashboard create surfaces never send an explicit `column`; the store resolves the landing column from the (selected or project-default) workflow's intake column. A workflow whose intake column sets `autoTriage: false` parks new cards there instead of auto-planning them, until an operator promotes the card. Built-in Coding (Ideas)'s `ideas` composition is deprecated and hidden from new selection; copy that composition into a custom workflow when needed. Existing Coding (Ideas) selections remain resolvable. The full lifecycle — create → parked → operator "Start" promotion → poll-time todo-discovery of the still-unplanned (bootstrap-stub) card — is regression-tested at the engine (triage poll ordering/discovery), UI (`TaskCard` Start affordance), and store (create → `moveTask` promotion) layers (FN-7596). | [Dashboard Guide → Create/Planning Forwarding](./dashboard-guide.md#planning-mode). | ### Skill-backed workflow steps diff --git a/packages/core/src/__tests__/builtin-workflows.test.ts b/packages/core/src/__tests__/builtin-workflows.test.ts index 8b96cd291d..f9caa06893 100644 --- a/packages/core/src/__tests__/builtin-workflows.test.ts +++ b/packages/core/src/__tests__/builtin-workflows.test.ts @@ -357,6 +357,15 @@ describe("built-in workflows", () => { ); }); + it("keeps deprecated builtin:coding-ideas resolvable while excluding it from defaults", () => { + const codingIdeas = getBuiltinWorkflow("builtin:coding-ideas"); + expect(codingIdeas).toBeDefined(); + expect(codingIdeas!.kind).toBe("workflow"); + expect(() => parseWorkflowIr(codingIdeas!.ir)).not.toThrow(); + expect(isBuiltinWorkflowDeprecated("builtin:coding-ideas")).toBe(true); + expect(defaultEnabledBuiltinWorkflowIds()).not.toContain("builtin:coding-ideas"); + }); + it("orders builtin:brainstorming's ask-user/exit-gate loop ahead of the plan/execute spine", () => { const brainstorming = getBuiltinWorkflow("builtin:brainstorming")!; const nodes = brainstorming.ir.nodes; @@ -736,15 +745,16 @@ describe("built-in workflows", () => { expect(defaultEnabledBuiltinWorkflowIds()).toContain("builtin:marketing"); expect(defaultEnabledBuiltinWorkflowIds()).not.toContain("builtin:compound-engineering"); expect(defaultEnabledBuiltinWorkflowIds()).not.toContain("builtin:brainstorming"); + expect(defaultEnabledBuiltinWorkflowIds()).not.toContain("builtin:coding-ideas"); expect(defaultEnabledBuiltinWorkflowIds()).not.toContain("builtin:pr-workflow"); expect(getBuiltinWorkflow("builtin:pr-workflow")!.kind).toBe("fragment"); expect(defaultEnabledBuiltinWorkflowIds().length).toBeGreaterThanOrEqual(5); expect(defaultEnabledBuiltinWorkflowIds().slice(0, 5)).toEqual([ "builtin:coding", - "builtin:coding-ideas", "builtin:legacy-coding", "builtin:quick-fix", "builtin:review-heavy", + "builtin:marketing", ]); expect(defaultEnabledBuiltinWorkflowIds()).toContain("builtin:stepwise-coding"); }); @@ -754,6 +764,7 @@ describe("built-in workflows", () => { expect(isBuiltinWorkflowPluginGated("builtin:coding")).toBe(false); expect(isBuiltinWorkflowPluginGated("builtin:quick-fix")).toBe(false); expect(isBuiltinWorkflowDeprecated("builtin:brainstorming")).toBe(true); + expect(isBuiltinWorkflowDeprecated("builtin:coding-ideas")).toBe(true); expect(isBuiltinWorkflowDeprecated("builtin:coding")).toBe(false); }); @@ -1057,15 +1068,18 @@ describe("built-in workflows", () => { expect(managementList.some((workflow) => workflow.id === "builtin:compound-engineering")).toBe(false); }); - it("hides deprecated brainstorming from selection listings while preserving management and direct resolution", async () => { + it("hides deprecated built-ins from selection listings while preserving management and direct resolution", async () => { + const deprecatedIds = ["builtin:brainstorming", "builtin:coding-ideas"]; const selectionList = await store.listWorkflowDefinitions(); - expect(selectionList.some((workflow) => workflow.id === "builtin:brainstorming")).toBe(false); + for (const id of deprecatedIds) { + expect(selectionList.some((workflow) => workflow.id === id)).toBe(false); + } const managementList = await store.listWorkflowDefinitions({ includeDisabledBuiltins: true }); - expect(managementList.some((workflow) => workflow.id === "builtin:brainstorming")).toBe(true); - expect(await store.getWorkflowDefinition("builtin:brainstorming")).toMatchObject({ - id: "builtin:brainstorming", - }); + for (const id of deprecatedIds) { + expect(managementList.some((workflow) => workflow.id === id)).toBe(true); + expect(await store.getWorkflowDefinition(id)).toMatchObject({ id }); + } }); it("hides the compound-engineering built-in when its plugin is not installed", async () => { diff --git a/packages/core/src/builtin-workflows.ts b/packages/core/src/builtin-workflows.ts index 4fe5ace238..5c74be2578 100644 --- a/packages/core/src/builtin-workflows.ts +++ b/packages/core/src/builtin-workflows.ts @@ -35,10 +35,11 @@ const PLUGIN_GATED_BUILTIN_WORKFLOWS: ReadonlyMap = new Map([ ]); /* - * FNXC:WorkflowBrainstorming 2026-07-15-15:49: - * FN-7970 deprecates builtin:brainstorming after its occupancy preflight: hide it - * from new selection while retaining its definition for existing task resolution. - * Keep this generic registry so later deprecated built-ins share the same policy. + * FNXC:CodingIdeasWorkflow 2026-07-15-16:35: + * FN-7969 deprecates builtin:coding-ideas only after its occupancy preflight + * verified no active task, including a parked `ideas` intake card, selected it. + * This generic registry hides deprecated workflows from new selection while + * retaining their definitions so existing task selections continue to resolve. */ const DEPRECATED_BUILTIN_WORKFLOWS: ReadonlySet = DEPRECATED_BUILTIN_WORKFLOW_IDS; diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 539090579d..d16e123c81 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -33,12 +33,15 @@ export type { GitlabConfigSettingsSource, ResolvedGitlabConfig, ResolveGitlabCon export { validateMcpServerDefinitionDetailed, validateMcpServerDefinitionsDetailed } from "./settings-validation.js"; /* - * FNXC:WorkflowBrainstorming 2026-07-15-15:49: - * Keep deprecation IDs browser-safe because Settings renders the management list - * (including disabled built-ins) and must not offer deprecated entries again. + * FNXC:WorkflowDeprecation 2026-07-15-16:35: + * Keep deprecated IDs browser-safe because Settings loads the management list + * (including disabled built-ins) but must not re-offer retired workflows for new + * selection. FN-7970 and FN-7969 preserve direct resolution for pre-existing + * Brainstorming and Coding (Ideas) task selections while hiding them elsewhere. */ export const DEPRECATED_BUILTIN_WORKFLOW_IDS: ReadonlySet = new Set([ "builtin:brainstorming", + "builtin:coding-ideas", ]); diff --git a/packages/dashboard/app/__tests__/settings-sections.test.tsx b/packages/dashboard/app/__tests__/settings-sections.test.tsx index b380987d14..1be673362c 100644 --- a/packages/dashboard/app/__tests__/settings-sections.test.tsx +++ b/packages/dashboard/app/__tests__/settings-sections.test.tsx @@ -123,6 +123,7 @@ describe("GeneralSection", () => { vi.mocked(fetchWorkflows).mockResolvedValue([ { id: "builtin:coding", name: "Coding", kind: "workflow", ir: {} }, { id: "builtin:brainstorming", name: "Brainstorming", kind: "workflow", ir: {} }, + { id: "builtin:coding-ideas", name: "Coding (Ideas)", kind: "workflow", ir: {} }, ] as never); render( @@ -141,6 +142,7 @@ describe("GeneralSection", () => { await waitFor(() => expect(screen.getByLabelText("Coding")).toBeInTheDocument()); expect(screen.queryByLabelText("Brainstorming")).not.toBeInTheDocument(); + expect(screen.queryByLabelText("Coding (Ideas)")).not.toBeInTheDocument(); }); it("emits the absolute file-browser path toggle via setForm", () => {