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) <noreply@runfusion.ai>
This commit is contained in:
gsxdsm
2026-07-15 16:47:01 -07:00
parent f0485041c1
commit c0bef0bfbe
7 changed files with 43 additions and 16 deletions

View File

@@ -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.

View File

@@ -484,7 +484,7 @@ The **New Task** dialog's workflow selector also defaults to the current or last
<!-- FNXC:CodingIdeasWorkflow 2026-07-05-00:00: Every dashboard create surface (inline quick-create, quick-add box, New Task dialog, insight → task, todo → task) must omit an explicit `column` from the create request so the store resolves the landing column from the (selected or project-default) workflow's intake column instead of always forcing legacy `triage`. -->
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.

View File

@@ -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

View File

@@ -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 () => {

View File

@@ -35,10 +35,11 @@ const PLUGIN_GATED_BUILTIN_WORKFLOWS: ReadonlyMap<string, string> = 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<string> = DEPRECATED_BUILTIN_WORKFLOW_IDS;

View File

@@ -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<string> = new Set([
"builtin:brainstorming",
"builtin:coding-ideas",
]);

View File

@@ -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", () => {