diff --git a/packages/core/src/__tests__/builtin-workflows.test.ts b/packages/core/src/__tests__/builtin-workflows.test.ts index ecc49eda94..14bbbfb57f 100644 --- a/packages/core/src/__tests__/builtin-workflows.test.ts +++ b/packages/core/src/__tests__/builtin-workflows.test.ts @@ -393,6 +393,26 @@ describe("built-in workflows", () => { expect(ids.indexOf("merge")).toBeLessThan(ids.indexOf("document")); }); + it("compound-engineering runs plan/code-review/document in coding mode and carries skillName onto compiled steps (U1/U4)", () => { + const ce = getBuiltinWorkflow("builtin:compound-engineering")!; + const byId = (id: string) => ce.ir.nodes.find((n) => n.id === id); + // U4: fan-out steps (plan, code-review) need coding so fn_spawn_agent is + // available for persona fan-out; document needs coding to WRITE docs/solutions. + expect(byId("plan")?.config?.toolMode).toBe("coding"); + expect(byId("code-review")?.config?.toolMode).toBe("coding"); + expect(byId("document")?.config?.toolMode).toBe("coding"); + // U1: the compiler carries each node's skillName onto the materialized step so + // the step session can actually LOAD the skill (not just name it in prompt text). + const steps = compileWorkflowToSteps(ce.ir); + const plan = steps.find((s) => s.name === "Plan"); + expect(plan?.skillName).toBe("compound-engineering:ce-plan"); + expect(plan?.toolMode).toBe("coding"); + const codeReview = steps.find((s) => s.skillName === "compound-engineering:ce-code-review"); + expect(codeReview?.toolMode).toBe("coding"); + const document = steps.find((s) => s.skillName === "compound-engineering:ce-compound"); + expect(document?.toolMode).toBe("coding"); + }); + describe("store integration", () => { const harness = createTaskStoreTestHarness(); let store: ReturnType; diff --git a/packages/core/src/builtin-workflows.ts b/packages/core/src/builtin-workflows.ts index 26b0562cfd..936c33f403 100644 --- a/packages/core/src/builtin-workflows.ts +++ b/packages/core/src/builtin-workflows.ts @@ -187,6 +187,10 @@ export const BUILTIN_WORKFLOWS: WorkflowDefinition[] = [ name: "Plan", executor: "skill", skillName: "compound-engineering:ce-plan", + // Coding mode so ce-plan can fan out to its research subagents via + // fn_spawn_agent (registered only for coding-mode steps). It is not + // meant to write — see the accepted write-capability posture (Risk-1). + toolMode: "coding", prompt: "Produce a short implementation plan for this task before any code is written.", }, }, @@ -213,6 +217,10 @@ export const BUILTIN_WORKFLOWS: WorkflowDefinition[] = [ executor: "skill", skillName: "compound-engineering:ce-code-review", gateMode: "gate", + // Coding mode so ce-code-review can fan out to its reviewer-persona + // subagents via fn_spawn_agent. As a gate step it still emits the + // verdict JSON (KTD-6); it is not meant to write the tree (Risk-1). + toolMode: "coding", prompt: "Run a structured code review of the changes. Block merge on P0/P1 findings.", }, }, @@ -253,6 +261,9 @@ export const BUILTIN_WORKFLOWS: WorkflowDefinition[] = [ name: "Document learnings", executor: "skill", skillName: "compound-engineering:ce-compound", + // Coding mode so ce-compound can WRITE the learning doc into + // docs/solutions (readonly would strip write tools). + toolMode: "coding", prompt: "Capture any reusable learnings from this task into docs/solutions.", }, },