FN-6832: preserve default workflow routing

Preserve the default workflow unless users explicitly request workflow routing changes.

- Update triage and fast-planning prompt guidance to stop inferring alternate workflows from task type or no-commit markers.
- Refresh workflow docs and prompt tests to assert explicit-request-only workflow selection.
- Add a patch changeset for the published CLI package.

Files changed:
 .changeset/fn-6832-workflow-routing.md               |  5 +++++
 docs/workflow-steps.md                               |  5 ++++-
 packages/core/src/agent-prompts.ts                   | 20 +++++++++++++-------
 .../src/__tests__/triage-threshold-settings.test.ts  |  7 +++++--
 packages/engine/src/__tests__/triage.test.ts         | 13 +++++--------
 5 files changed, 32 insertions(+), 18 deletions(-)

Fusion-Task-Id: FN-6832

Fusion-Task-Lineage: 5a7ad103-2081-4c4c-ac32-fd5e4f6adfda
This commit is contained in:
gsxdsm
2026-06-21 08:01:47 -07:00
parent f13aaa1a99
commit c7b56a5ab7
5 changed files with 32 additions and 18 deletions

View File

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

View File

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

View File

@@ -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.
<!--
FNXC:WorkflowRouting 2026-06-20-22:08:
Fast triage must keep tasks on the project default workflow unless the user explicitly asked for a specific workflow. The no-commits header remains a PROMPT.md marker only; it is not permission to select a lightweight workflow automatically.
-->
## 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.
<!--
FNXC:WorkflowRouting 2026-06-20-22:08:
Standard triage must not infer workflow changes from task type. Agents preserve the project default unless the user names or explicitly requests a workflow; no-commit decisions use the header marker without automatic workflow selection.
-->
## 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

View File

@@ -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("{{");
});

View File

@@ -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);
}
});