From d6e09532931fd648631c867decc6c3ba7189f499 Mon Sep 17 00:00:00 2001 From: mika kuns Date: Tue, 9 Jun 2026 11:44:18 +0200 Subject: [PATCH] feat(worker): allow cancelling a WaitingForChildren parent Add WaitingForChildren to the CancelAsync guard so a parent waiting on its children can be cancelled. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/ClaudeDo.Worker/State/TaskStateService.cs | 3 ++- .../WaitingForChildrenLifecycleTests.cs | 21 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/ClaudeDo.Worker/State/TaskStateService.cs b/src/ClaudeDo.Worker/State/TaskStateService.cs index fe48954..61088bf 100644 --- a/src/ClaudeDo.Worker/State/TaskStateService.cs +++ b/src/ClaudeDo.Worker/State/TaskStateService.cs @@ -219,7 +219,8 @@ public sealed class TaskStateService : ITaskStateService var affected = await ctx.Tasks .Where(t => t.Id == taskId && (t.Status == TaskStatus.Running || t.Status == TaskStatus.Queued - || t.Status == TaskStatus.WaitingForReview)) + || t.Status == TaskStatus.WaitingForReview + || t.Status == TaskStatus.WaitingForChildren)) .ExecuteUpdateAsync(s => s .SetProperty(t => t.Status, TaskStatus.Cancelled) .SetProperty(t => t.FinishedAt, finishedAt), ct); diff --git a/tests/ClaudeDo.Worker.Tests/WaitingForChildrenLifecycleTests.cs b/tests/ClaudeDo.Worker.Tests/WaitingForChildrenLifecycleTests.cs index c84bb7c..bb634d7 100644 --- a/tests/ClaudeDo.Worker.Tests/WaitingForChildrenLifecycleTests.cs +++ b/tests/ClaudeDo.Worker.Tests/WaitingForChildrenLifecycleTests.cs @@ -162,6 +162,27 @@ public sealed class WaitingForChildrenLifecycleTests : IDisposable } } + [Fact] + public async Task WaitingForChildren_parent_can_be_cancelled() + { + using (var ctx = _db.CreateContext()) + { + ctx.Lists.Add(new ListEntity { Id = "l1", Name = "L", CreatedAt = DateTime.UtcNow }); + ctx.Tasks.Add(new TaskEntity { Id = "par", ListId = "l1", Title = "Parent", + Status = TaskStatus.WaitingForChildren, CreatedAt = DateTime.UtcNow }); + await ctx.SaveChangesAsync(); + } + + var result = await _built.State.CancelAsync("par", DateTime.UtcNow, default); + + Assert.True(result.Ok); + using (var ctx = _db.CreateContext()) + { + var par = await new TaskRepository(ctx).GetByIdAsync("par"); + Assert.Equal(TaskStatus.Cancelled, par!.Status); + } + } + // ─── FinalizePlanningAsync ──────────────────────────────────────────── private async Task SeedActivePlanningParentAsync(string id = "par")