Fix workflow step execution wiring

This commit is contained in:
gsxdsm
2026-04-05 22:28:22 -07:00
parent ef3136d601
commit 6ff6e69e60
9 changed files with 414 additions and 11 deletions

View File

@@ -5474,6 +5474,168 @@ describe("Workflow Steps Execution", () => {
expect(store.moveTask).toHaveBeenCalledWith("FN-001", "in-review");
});
it("runs browser verification workflow steps with coding tools", async () => {
const store = createMockStore();
store.getTask.mockResolvedValue({
id: "FN-001",
title: "Browser task",
description: "Verify browser behavior",
column: "in-progress",
dependencies: [],
steps: [{ name: "Preflight", status: "pending" }],
currentStep: 0,
log: [],
enabledWorkflowSteps: ["WS-001"],
prompt: "# test\n## Steps\n### Step 0: Preflight\n- [ ] check",
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
});
store.getWorkflowStep.mockResolvedValue({
id: "WS-001",
templateId: "browser-verification",
name: "Browser Verification",
description: "Verify with browser automation",
mode: "prompt",
toolMode: "coding",
prompt: "Use browser automation to verify the app.",
enabled: true,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
});
let callIdx = 0;
mockedCreateHaiAgent.mockImplementation((async (opts: any) => {
callIdx++;
if (callIdx === 1) {
const customTools = opts.customTools || [];
const session = {
prompt: vi.fn().mockImplementation(async () => {
const taskDoneTool = customTools.find((t: any) => t.name === "task_done");
if (taskDoneTool) await taskDoneTool.execute("tool-1", {});
}),
dispose: vi.fn(),
subscribe: vi.fn(),
on: vi.fn(),
sessionManager: { getLeafId: vi.fn().mockReturnValue("leaf-1") },
state: {},
};
return { session };
}
return {
session: {
prompt: vi.fn().mockResolvedValue(undefined),
dispose: vi.fn(),
subscribe: vi.fn(),
on: vi.fn(),
state: {},
},
};
}) as any);
const executor = new TaskExecutor(store, "/tmp/test");
await executor.execute({
id: "FN-001",
title: "Browser task",
description: "Verify browser behavior",
column: "in-progress",
dependencies: [],
steps: [{ name: "Preflight", status: "pending" }],
currentStep: 0,
log: [],
enabledWorkflowSteps: ["WS-001"],
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
});
expect(mockedCreateHaiAgent).toHaveBeenCalledTimes(2);
const secondCall = mockedCreateHaiAgent.mock.calls[1];
expect(secondCall[0].tools).toBe("coding");
});
it("runs QA workflow steps with coding tools", async () => {
const store = createMockStore();
store.getTask.mockResolvedValue({
id: "FN-001",
title: "QA task",
description: "Verify tests pass",
column: "in-progress",
dependencies: [],
steps: [{ name: "Preflight", status: "pending" }],
currentStep: 0,
log: [],
enabledWorkflowSteps: ["WS-001"],
prompt: "# test\n## Steps\n### Step 0: Preflight\n- [ ] check",
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
});
store.getWorkflowStep.mockResolvedValue({
id: "WS-001",
templateId: "qa-check",
name: "QA Check",
description: "Run tests and verify they pass",
mode: "prompt",
toolMode: "coding",
prompt: "Run the test suite and report results.",
enabled: true,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
});
let callIdx = 0;
mockedCreateHaiAgent.mockImplementation((async (opts: any) => {
callIdx++;
if (callIdx === 1) {
const customTools = opts.customTools || [];
const session = {
prompt: vi.fn().mockImplementation(async () => {
const taskDoneTool = customTools.find((t: any) => t.name === "task_done");
if (taskDoneTool) await taskDoneTool.execute("tool-1", {});
}),
dispose: vi.fn(),
subscribe: vi.fn(),
on: vi.fn(),
sessionManager: { getLeafId: vi.fn().mockReturnValue("leaf-1") },
state: {},
};
return { session };
}
return {
session: {
prompt: vi.fn().mockResolvedValue(undefined),
dispose: vi.fn(),
subscribe: vi.fn(),
on: vi.fn(),
state: {},
},
};
}) as any);
const executor = new TaskExecutor(store, "/tmp/test");
await executor.execute({
id: "FN-001",
title: "QA task",
description: "Verify tests pass",
column: "in-progress",
dependencies: [],
steps: [{ name: "Preflight", status: "pending" }],
currentStep: 0,
log: [],
enabledWorkflowSteps: ["WS-001"],
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
});
expect(mockedCreateHaiAgent).toHaveBeenCalledTimes(2);
const secondCall = mockedCreateHaiAgent.mock.calls[1];
expect(secondCall[0].tools).toBe("coding");
});
it("skips workflow steps with no prompt", async () => {
const store = createMockStore();

View File

@@ -1902,6 +1902,7 @@ export class TaskExecutor {
worktreePath: string,
settings: Settings,
): Promise<{ success: boolean; output?: string; error?: string }> {
const toolMode: "coding" | "readonly" = workflowStep.toolMode || "readonly";
const systemPrompt = `You are a workflow step agent executing: ${workflowStep.name}
Task Context:
@@ -1937,7 +1938,7 @@ If issues are found that need attention, describe them clearly.`;
const { session } = await createKbAgent({
cwd: worktreePath,
systemPrompt,
tools: "readonly",
tools: toolMode,
defaultProvider: stepProvider,
defaultModelId: stepModelId,
fallbackProvider: settings.fallbackProvider,

View File

@@ -1539,6 +1539,7 @@ async function executePostMergePromptStep(
rootDir: string,
settings: Settings,
): Promise<{ success: boolean; output?: string; error?: string }> {
const toolMode: "coding" | "readonly" = workflowStep.toolMode || "readonly";
const systemPrompt = `You are a post-merge workflow step agent executing: ${workflowStep.name}
Task Context:
@@ -1567,7 +1568,7 @@ If issues are found that need attention, describe them clearly.`;
const { session } = await createKbAgent({
cwd: rootDir,
systemPrompt,
tools: "readonly",
tools: toolMode,
defaultProvider: stepProvider,
defaultModelId: stepModelId,
fallbackProvider: settings.fallbackProvider,