diff --git a/.changeset/fn-6832-workflow-routing.md b/.changeset/fn-6832-workflow-routing.md new file mode 100644 index 0000000000..0a771cbabe --- /dev/null +++ b/.changeset/fn-6832-workflow-routing.md @@ -0,0 +1,5 @@ +--- +"@runfusion/fusion": patch +--- + +Stop triage and planning prompts from auto-selecting alternate workflows based on task type; agents now preserve the project default workflow unless the user explicitly requests a specific workflow. diff --git a/docs/workflow-steps.md b/docs/workflow-steps.md index 00e7513baa..4607e5c936 100644 --- a/docs/workflow-steps.md +++ b/docs/workflow-steps.md @@ -12,6 +12,9 @@ Public docs need one concise workflow overview that names the shipped built-ins, FNXC:Docs 2026-06-20-08:47: The built-in catalog now includes a business lead-generation workflow with custom columns, custom lead fields, and inline per-stage prompts, so the public inventory must show it beside coding workflows instead of implying all selectable built-ins are engineering-only. + +FNXC:WorkflowRouting 2026-06-21-04:25: +Triage and planning agents must preserve the project default workflow unless the user explicitly requests a different workflow. No-commit markers describe expected artifact behavior only; they no longer imply automatic Quick fix workflow selection. --> Fusion workflows define the task lifecycle policy that moves work from an idea to delivery. The default coding path is **Plan/Triage → Execute → Workflow steps → Review → Merge**, but that path is now represented as a workflow selection rather than only as fixed engine behavior. A task with no explicit workflow resolves to `builtin:coding`; an explicit missing/corrupt custom workflow fails closed instead of silently falling back. @@ -24,7 +27,7 @@ Operators can select workflows in the dashboard wherever the task or board workf - `fn_workflow_select` — assign a workflow to the current or named task. - `workflow_id` on `fn_task_create` / delegation tools — create a task with a workflow already selected. -Decision-only or investigation tasks can also declare `noCommitsExpected` / `**No commits expected:** true`; the built-in triage policy prefers the Quick fix workflow for that no-commit lane. +Decision-only or investigation tasks can also declare `noCommitsExpected` / `**No commits expected:** true`; that marker does not change workflow selection by itself. Tasks without an explicit workflow request stay on the project default (`builtin:coding`). ### Built-in workflow catalog diff --git a/packages/core/src/agent-prompts.ts b/packages/core/src/agent-prompts.ts index b13beb80f6..c4b36dda3f 100644 --- a/packages/core/src/agent-prompts.ts +++ b/packages/core/src/agent-prompts.ts @@ -405,8 +405,12 @@ If an executor later proves an ordinary implementation task is already satisfied ## Project commands When the user prompt includes explicit test/build commands, use those exact commands in the generated spec. + ## Workflow Routing -Call \`fn_workflow_list\` and use workflow descriptions as the routing signal. For investigation/audit/research, operational routing/coordination, or decision-only tasks that meet the no-commits criteria above, include \`**No commits expected:** true\` in the PROMPT.md header and prefer \`builtin:quick-fix\` or a custom investigation workflow; standard coding tasks can stay on the default \`builtin:coding\`. Use \`fn_workflow_select\` for the current task or pass \`workflow_id\` to \`fn_task_create\` for subtasks. +Keep the project default workflow (\`builtin:coding\`) unless the user explicitly requested a specific workflow for this task or subtask. Do NOT call \`fn_workflow_select\` or pass \`workflow_id\` to \`fn_task_create\` just because a task looks like investigation, audit, research, coordination, decision-only work, or coding work. If the user explicitly asks for a workflow, call \`fn_workflow_list\` to discover valid IDs, then use \`fn_workflow_select\` for the current task or pass \`workflow_id\` to \`fn_task_create\` for the requested subtask. For investigation/audit/research, operational routing/coordination, or decision-only tasks that meet the no-commits criteria above, still include \`**No commits expected:** true\` in the PROMPT.md header when appropriate; that header marker does not change the workflow. ## Task Artifact Location for Forensic / Reconciliation Tasks @@ -698,13 +702,15 @@ commands, use those EXACT commands in the testing/verification steps and anywher the spec references running tests or builds. Do NOT guess or infer commands from package.json when explicit commands are provided. + ## Workflow Routing -- Call \`fn_workflow_list\` to discover available workflows before selecting a routing path, and read each workflow description as the routing signal. -- For investigation, audit, research, operational routing/coordination, or decision-only tasks that produce no code/config/file changes, set \`**No commits expected:** true\` in the PROMPT.md header when the no-commits criteria above are met, then select an appropriate lightweight workflow. -- For decision-only tasks ({{triageNoCommitsDecisionVerbs}}), prefer \`{{triageDecisionOnlyWorkflowId}}\` or a custom investigation workflow when one is available. -- For standard coding tasks, \`{{triageDefaultWorkflowId}}\` is the default and is usually appropriate. -- Use \`fn_workflow_select\` to set the workflow on the current task, or pass \`workflow_id\` to \`fn_task_create\` when creating subtasks. -- Match the task nature to the workflow description; descriptions are authoritative for routing decisions. +- Keep the project default workflow (\`{{triageDefaultWorkflowId}}\`) unless the user explicitly requested a specific workflow for this task or subtask. +- Do NOT call \`fn_workflow_select\` or pass \`workflow_id\` to \`fn_task_create\` just because a task looks like investigation, audit, research, operational routing/coordination, decision-only work, or standard coding work. +- For decision-only tasks ({{triageNoCommitsDecisionVerbs}}) or other no-code tasks, set \`**No commits expected:** true\` in the PROMPT.md header when the no-commits criteria above are met; this is a header marker only and does not select \`{{triageDecisionOnlyWorkflowId}}\` or any custom investigation workflow by itself. +- If the user explicitly asks for a workflow, call \`fn_workflow_list\` to discover valid IDs, then use \`fn_workflow_select\` to set the workflow on the current task or pass \`workflow_id\` to \`fn_task_create\` when creating a requested subtask. ## Spec Review diff --git a/packages/engine/src/__tests__/triage-threshold-settings.test.ts b/packages/engine/src/__tests__/triage-threshold-settings.test.ts index 85bbfe63be..6b012898fa 100644 --- a/packages/engine/src/__tests__/triage-threshold-settings.test.ts +++ b/packages/engine/src/__tests__/triage-threshold-settings.test.ts @@ -43,8 +43,11 @@ describe("triage threshold workflow settings", () => { expect(rendered).toContain("at or above 30 items"); expect(rendered).toContain("S (<2h), M (2-4h), L (4-8h). Split if XL (8h+)"); expect(rendered).toContain("Decide, Evaluate, Verify, Confirm, Audit, Review whether, Investigate and report"); - expect(rendered).toContain("prefer `builtin:quick-fix`"); - expect(rendered).toContain("`builtin:coding` is the default"); + expect(rendered).toContain("Keep the project default workflow (`builtin:coding`)"); + expect(rendered).toContain("unless the user explicitly requested a specific workflow"); + expect(rendered).toContain("Do NOT call `fn_workflow_select` or pass `workflow_id`"); + expect(rendered).toContain("set `**No commits expected:** true` in the PROMPT.md header"); + expect(rendered).not.toContain("prefer `builtin:quick-fix`"); expect(rendered).not.toContain("{{"); }); diff --git a/packages/engine/src/__tests__/triage.test.ts b/packages/engine/src/__tests__/triage.test.ts index 50c50c11ab..5587d8d4b1 100644 --- a/packages/engine/src/__tests__/triage.test.ts +++ b/packages/engine/src/__tests__/triage.test.ts @@ -784,15 +784,12 @@ describe("fast-mode triage", () => { expect(FAST_PLANNING_PROMPT).not.toContain("Frontend UX Criteria"); }); - it("documents workflow routing in standard and fast prompts", () => { + it("documents explicit-request-only workflow routing in standard and fast prompts", () => { + const required = ["## Workflow Routing", "Keep the project default workflow", "unless the user explicitly requested a specific workflow", "Do NOT call `fn_workflow_select` or pass `workflow_id`", "If the user explicitly", "fn_workflow_list", "fn_workflow_select", "workflow_id", "**No commits expected:** true", "builtin:coding"]; + const forbidden = ["use workflow descriptions as the routing signal", "select an appropriate lightweight workflow", "prefer `builtin:quick-fix` or a custom investigation workflow", "Match the task nature to the workflow description", "descriptions are authoritative for routing decisions"]; for (const prompt of [RENDERED_TRIAGE_POLICY_PROMPT, FAST_PLANNING_PROMPT]) { - expect(prompt).toContain("## Workflow Routing"); - expect(prompt).toContain("fn_workflow_list"); - expect(prompt).toContain("fn_workflow_select"); - expect(prompt).toContain("workflow_id"); - expect(prompt).toContain("**No commits expected:** true"); - expect(prompt).toContain("builtin:quick-fix"); - expect(prompt).toContain("builtin:coding"); + for (const text of required) expect(prompt).toContain(text); + for (const text of forbidden) expect(prompt).not.toContain(text); } });