Skip to content

Commit 8b0d830

Browse files
committed
fix: prevent child delegation start after parent metadata failure
1 parent 22831e5 commit 8b0d830

2 files changed

Lines changed: 54 additions & 1 deletion

File tree

src/__tests__/provider-delegation.spec.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,4 +142,54 @@ describe("ClineProvider.delegateParentAndOpenChild()", () => {
142142
// Verify ordering: createTask → updateTaskHistory → child.start
143143
expect(callOrder).toEqual(["createTask", "updateTaskHistory", "child.start"])
144144
})
145+
146+
it("does not start the child when parent delegation metadata cannot be persisted", async () => {
147+
const parentTask = { taskId: "parent-1", emit: vi.fn() } as any
148+
const childStart = vi.fn()
149+
const persistError = new Error("history write failed")
150+
151+
const providerEmit = vi.fn()
152+
const updateTaskHistory = vi.fn().mockRejectedValue(persistError)
153+
const removeClineFromStack = vi.fn().mockResolvedValue(undefined)
154+
const createTask = vi.fn().mockResolvedValue({ taskId: "child-1", start: childStart })
155+
const handleModeSwitch = vi.fn().mockResolvedValue(undefined)
156+
const getTaskWithId = vi.fn().mockResolvedValue({
157+
historyItem: {
158+
id: "parent-1",
159+
task: "Parent",
160+
tokensIn: 0,
161+
tokensOut: 0,
162+
totalCost: 0,
163+
childIds: [],
164+
},
165+
})
166+
167+
const provider = {
168+
emit: providerEmit,
169+
getCurrentTask: vi.fn(() => parentTask),
170+
removeClineFromStack,
171+
createTask,
172+
getTaskWithId,
173+
updateTaskHistory,
174+
handleModeSwitch,
175+
log: vi.fn(),
176+
} as unknown as ClineProvider
177+
178+
await expect(
179+
(ClineProvider.prototype as any).delegateParentAndOpenChild.call(provider, {
180+
parentTaskId: "parent-1",
181+
message: "Do something",
182+
initialTodos: [],
183+
mode: "code",
184+
}),
185+
).rejects.toThrow("history write failed")
186+
187+
expect(createTask).toHaveBeenCalledWith("Do something", undefined, parentTask, {
188+
initialTodos: [],
189+
initialStatus: "active",
190+
startTask: false,
191+
})
192+
expect(childStart).not.toHaveBeenCalled()
193+
expect(providerEmit).not.toHaveBeenCalledWith(RooCodeEventName.TaskDelegated, "parent-1", "child-1")
194+
})
145195
})

src/core/webview/ClineProvider.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2866,7 +2866,9 @@ export class ClineProvider
28662866
})
28672867

28682868
await this.addClineToStack(task)
2869-
task.start()
2869+
if (options.startTask !== false) {
2870+
task.start()
2871+
}
28702872

28712873
this.log(
28722874
`[createTask] ${task.parentTask ? "child" : "parent"} task ${task.taskId}.${task.instanceId} instantiated`,
@@ -3264,6 +3266,7 @@ export class ClineProvider
32643266
(err as Error)?.message ?? String(err)
32653267
}`,
32663268
)
3269+
throw err
32673270
}
32683271

32693272
// 6) Start the child task now that parent metadata is safely persisted.

0 commit comments

Comments
 (0)