Skip to content

Commit 65cf706

Browse files
committed
fix(delegation): guard concurrent rollback pop and add transition tests
1 parent c45f039 commit 65cf706

1 file changed

Lines changed: 8 additions & 1 deletion

File tree

src/core/webview/ClineProvider.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3552,7 +3552,11 @@ export class ClineProvider
35523552
}`,
35533553
)
35543554
try {
3555-
await this.removeClineFromStack({ skipDelegationRepair: true })
3555+
// Only pop the stack if the child we just created is still on top.
3556+
// A concurrent delegation could have pushed another child since we created ours.
3557+
if (this.getCurrentTask()?.taskId === child.taskId) {
3558+
await this.removeClineFromStack({ skipDelegationRepair: true })
3559+
}
35563560
} catch (cleanupError) {
35573561
this.log(
35583562
`[delegateParentAndOpenChild] Failed to close paused child ${child.taskId} during rollback: ${
@@ -3757,6 +3761,9 @@ export class ClineProvider
37573761

37583762
// 3) Persist parent metadata before closing the child. If persistence fails,
37593763
// the delegated child remains active and can retry completion.
3764+
// NOTE: steps 3 and 5 are still two separate writes — this is a known gap
3765+
// (reviewed finding #3). Story 2.2 (#365) will replace them with a single
3766+
// atomicUpdatePair() call so no intermediate state is ever persisted.
37603767
const childIds = Array.from(new Set([...(historyItem.childIds ?? []), childTaskId]))
37613768
if (historyItem.status !== "active") {
37623769
assertValidTransition(historyItem.status, "active")

0 commit comments

Comments
 (0)