Skip to content

Commit 340dfba

Browse files
committed
fix: prevent child delegation start after parent metadata failure
1 parent e7b7b58 commit 340dfba

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
@@ -2869,7 +2869,9 @@ export class ClineProvider
28692869
})
28702870

28712871
await this.addClineToStack(task)
2872-
task.start()
2872+
if (options.startTask !== false) {
2873+
task.start()
2874+
}
28732875

28742876
this.log(
28752877
`[createTask] ${task.parentTask ? "child" : "parent"} task ${task.taskId}.${task.instanceId} instantiated`,
@@ -3267,6 +3269,7 @@ export class ClineProvider
32673269
(err as Error)?.message ?? String(err)
32683270
}`,
32693271
)
3272+
throw err
32703273
}
32713274

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

0 commit comments

Comments
 (0)