diff --git a/docs/workflow-editor.md b/docs/workflow-editor.md index c2ac92a64e..15d61cfdcc 100644 --- a/docs/workflow-editor.md +++ b/docs/workflow-editor.md @@ -170,7 +170,7 @@ Fusion ships built-in workflows as read-only references: - `builtin:quick-fix` — a short path for trivial or no-commit/decision work. - `builtin:review-heavy` — a standard execute/review/merge path with an additional gated security review. - `builtin:compound-engineering` — a plugin-gated Compound Engineering pipeline: `/ce-plan` writes the CE plan doc, optional `ce-doc-review` can pressure-test plans (markdown gets autofix/Open Questions write-back; HTML uses DOM-safe helper mutations, including canonical checklist repair, only when safety is proven and otherwise report-only with no write), `/ce-work` implements, `/ce-code-review` gates merge, and autoMerge-off projects route through the CE PR/feedback skills before Fusion's manual merge seam. -- `builtin:stepwise-coding` — Coding (per-step review): a graph variant with optional Plan Review before execution and per-step parse, execute, review, and rework structure. +- `builtin:stepwise-coding` — Coding (per-step review): a graph variant with optional Plan Review before execution, per-step parse/execute/review/rework, and optional final Code Review before the final review/merge region. - `builtin:design` — a UI-heavy work path with a gated design/UX review before standard review and merge. Built-ins can be viewed, exported, and used as templates, but their graph, columns, field declarations, and setting declarations are not editable. Their per-project setting **values** are editable from the Settings panel's Values tab. Selectable built-ins all use a capacity-released queue column (`todo` or a workflow-specific backlog) that dispatches to the active WIP column through the standard hold/release sweep. diff --git a/docs/workflow-steps.md b/docs/workflow-steps.md index 6a93540f73..8dbb3c1f11 100644 --- a/docs/workflow-steps.md +++ b/docs/workflow-steps.md @@ -50,7 +50,7 @@ Decision-only or investigation tasks can also declare `noCommitsExpected` / `**N | Review-heavy | `builtin:review-heavy` | Standard execute/review/merge path with an additional gated security review. | | Marketing | `builtin:marketing` | Content pipeline with custom Ideation, Backlog, Drafting, Editorial review, Published, and Archived columns plus structured marketing brief/draft/editorial prompts; drafts are persisted as task documents for review while the workflow reuses standard lifecycle traits and merge primitives. | | Compound engineering | `builtin:compound-engineering` | Plugin-gated CE workflow that invokes `/ce-plan`, optional advisory `ce-doc-review` (markdown autofix; HTML DOM-safe mutation with report-only fallback), `/ce-work`, merge-blocking `/ce-code-review`, CE PR/feedback skills, Fusion merge, and learnings capture. | -| Coding (per-step review) | `builtin:stepwise-coding` | Graph-executor workflow with default-on Plan Review before execution and per-step parse/execute/review/rework. | +| Coding (per-step review) | `builtin:stepwise-coding` | Graph-executor workflow with default-on Plan Review before execution, per-step parse/execute/review/rework, and an optional final Code Review gate. | | Design | `builtin:design` | UI-heavy work path that implements, persists a user-facing design preview task document, runs a gated design/UX review, then performs the standard review and merge. | | PR lifecycle | `builtin:pr-workflow` | Reusable PR lifecycle graph fragment (create PR → await review → respond → gate → merge); it is a fragment, not directly selectable as a task workflow. | | Lead generation | `builtin:lead-generation` | Selectable business workflow for sourcing, qualifying, enriching, and contacting leads with custom lead fields, stage columns, and reviewable enrichment/outreach task documents; requires the workflow graph executor for custom board columns. | @@ -184,7 +184,7 @@ The default built-in catalog entry `builtin:coding` is backed by a Stepwise-deri `builtin:legacy-coding` is backed by the original monolithic `BUILTIN_CODING_WORKFLOW_IR`: `planning` → `execute` → optional quality gates → `review` → merge region. -`builtin:stepwise-coding` displays as Coding (per-step review). It is backed by `BUILTIN_STEPWISE_CODING_WORKFLOW_IR`; it keeps the same lifecycle columns/traits while adding the default-on optional Plan Review before `parse-steps` and modeling per-step parse/execute/review/rework as authored graph structure. +`builtin:stepwise-coding` displays as Coding (per-step review). It is backed by `BUILTIN_STEPWISE_CODING_WORKFLOW_IR`; it keeps the same lifecycle columns/traits while adding the default-on optional Plan Review before `parse-steps`, modeling per-step parse/execute/review/rework as authored graph structure, and retaining the post-foreach optional Code Review gate before its final review/merge region. `builtin:marketing` is a non-coding content workflow with marketing-specific columns (`ideation`, `backlog`, `drafting`, `editorial-review`, `published`, `archived`) and prompt seams for content brief, draft, and editorial review. Its draft stage saves the primary content deliverable as a task document for human review, while the workflow uses the same lifecycle traits (`intake`, `hold`, `wip`, `merge-blocker`, `human-review`, `complete`, `archived`) and the same merge-gate/branch-group/merge-attempt primitive region as coding workflows, so scheduler, capacity, review blocking, and merge orchestration behavior remain standard. @@ -346,7 +346,7 @@ Built-in optional gates ship as inlined IR builders, not as a template catalog: - `builtin:coding` carries the `browser-verification` optional-group node (`builtin-browser-verification-group.ts`), default-off, so browser verification runs only for tasks whose `enabledWorkflowSteps` includes `browser-verification`. - `builtin:coding` and `builtin:stepwise-coding` carry the `plan-review` optional-group node (`builtin-plan-review-group.ts`), default-on, before `parse-steps` so the plan can be reviewed before execution begins. -- The `code-review` optional-group node (`builtin-code-review-group.ts`) is the inlined code-review gate. On default `builtin:coding`, this is the only final review surface before merge; disabling it lets the graph continue from implementation/verification to the merge gate. +- The `code-review` optional-group node (`builtin-code-review-group.ts`) is the inlined code-review gate. On default `builtin:coding`, this is the only final review surface before merge; disabling it lets the graph continue from implementation/verification to the merge gate. On `builtin:stepwise-coding`, it remains a post-foreach optional final review gate before the workflow's final review seam. - A workflow (for example compound-engineering) can add a **post-merge** optional-group node via the generic `postMergeOptionalGroupNode(...)` builder (`builtin-post-merge-group.ts`) — e.g. a `document` step that runs after merge. Create-time optional-step controls appear in the quick-add action row and the **New Task** dialog inline quick buttons for the active workflow. They resolve the workflow's optional-group nodes (plus plugin-contributed palette templates, see [Plugin-Contributed Steps](#plugin-contributed-steps)) into toggleable rows. Workflows with no optional groups render no trigger, and the selected node ids are submitted through `enabledWorkflowSteps` when the task is created. Unknown or removed ids are skipped during resolution so stale selections never render blank controls or break workflow loading. diff --git a/packages/core/src/__tests__/builtin-workflows.test.ts b/packages/core/src/__tests__/builtin-workflows.test.ts index 20e5f8dff5..0996b0bc29 100644 --- a/packages/core/src/__tests__/builtin-workflows.test.ts +++ b/packages/core/src/__tests__/builtin-workflows.test.ts @@ -86,6 +86,11 @@ describe("built-in workflows", () => { expect(ir.nodes.some((n) => n.id === "plan-review" && n.kind === "optional-group")).toBe(true); expect(ir.edges.some((edge) => edge.from === "plan" && edge.to === "plan-review")).toBe(true); expect(ir.edges.some((edge) => edge.from === "plan-review" && edge.to === "parse")).toBe(true); + expect(ir.nodes.some((n) => n.id === "browser-verification" && n.kind === "optional-group")).toBe(true); + expect(ir.nodes.some((n) => n.id === "code-review" && n.kind === "optional-group")).toBe(true); + expect(ir.edges.some((edge) => edge.from === "steps" && edge.to === "browser-verification" && edge.condition === "success")).toBe(true); + expect(ir.edges.some((edge) => edge.from === "browser-verification" && edge.to === "code-review" && edge.condition === "success")).toBe(true); + expect(ir.edges.some((edge) => edge.from === "code-review" && edge.to === "review" && edge.condition === "success")).toBe(true); const foreach = ir.nodes.find((n) => n.kind === "foreach"); expect(foreach).toBeDefined(); const template = ( @@ -130,6 +135,15 @@ describe("built-in workflows", () => { expect(template.edges.some((edge) => edge.kind === "rework")).toBe(false); }); + it("all coding built-ins expose Browser Verification as an optional group", () => { + for (const workflowId of ["builtin:coding", "builtin:legacy-coding", "builtin:stepwise-coding"]) { + const workflow = getBuiltinWorkflow(workflowId)!; + const browserVerification = workflow.ir.nodes.find((node) => node.id === "browser-verification"); + expect(browserVerification?.kind, workflowId).toBe("optional-group"); + expect(browserVerification?.config?.defaultOn, workflowId).toBe(false); + } + }); + it("includes the PR lifecycle built-in wiring the PR nodes end to end (U9)", () => { const pr = getBuiltinWorkflow("builtin:pr-workflow"); expect(pr).toBeDefined(); diff --git a/packages/engine/src/__tests__/workflow-graph-task-runner.test.ts b/packages/engine/src/__tests__/workflow-graph-task-runner.test.ts index d170340870..8f34fb9e09 100644 --- a/packages/engine/src/__tests__/workflow-graph-task-runner.test.ts +++ b/packages/engine/src/__tests__/workflow-graph-task-runner.test.ts @@ -287,7 +287,7 @@ describe("WorkflowGraphTaskRunner (CU-U2)", () => { const calls: string[] = []; const getWorkflowDefinition = vi.fn(async () => undefined); const store: WorkflowGraphRunnerStore = { - getTaskWorkflowSelection: () => ({ workflowId: "builtin:coding", stepIds: [] }), + getTaskWorkflowSelection: () => ({ workflowId: "builtin:legacy-coding", stepIds: [] }), getWorkflowDefinition, }; const runner = new WorkflowGraphTaskRunner({ @@ -299,8 +299,10 @@ describe("WorkflowGraphTaskRunner (CU-U2)", () => { const result = await runner.run(task, flagOn); expect(result.disposition).toBe("completed"); - // U6: the coding built-in no longer carries a `workflow-step` seam; its - // pre-merge browser-verification optional-group is default-OFF and bypassed. + // FNXC:WorkflowBuiltins 2026-06-28-23:29: + // Use Legacy coding here because default Coding is now stepwise and requires + // parse/foreach task-step context. This still proves built-in registry fallback + // works when the store intentionally does not return a persisted definition. expect(calls).toEqual(["planning", "execute", "review", "merge"]); expect(result.reason).toBeUndefined(); expect(getWorkflowDefinition).not.toHaveBeenCalled();