fix(worker): allow the done toggle from any non-Running status

MarkDoneAsync was Idle-only, so a finished task (typically a list-handler
run with no worktree to merge) could not be ticked off. Guard on Running
instead and cover the other statuses with tests.
This commit is contained in:
mika kuns
2026-08-26 10:27:56 +02:00
parent d71c0ceaef
commit f80af122e9
4 changed files with 47 additions and 3 deletions
@@ -98,6 +98,21 @@ public sealed class TaskDoneDequeueHubTests : IDisposable
Assert.Equal(TaskStatus.Running, reloaded!.Status);
}
// Regression: the guard was Idle-only, so a finished task (typically a list-handler run,
// which has no worktree to merge) could no longer be ticked off from the task card.
[Fact]
public async Task SetTaskDone_FromWaitingForReview_TransitionsToDone()
{
var listId = await SeedListAsync();
var task = await SeedTaskAsync(listId, TaskStatus.WaitingForReview);
var hub = CreateHub();
await hub.SetTaskDone(task.Id);
var reloaded = await _tasks.GetByIdAsync(task.Id);
Assert.Equal(TaskStatus.Done, reloaded!.Status);
}
// ── UnsetTaskDone ──
[Fact]
@@ -504,6 +504,24 @@ public sealed class TaskStateServiceTests : IDisposable
Assert.Equal(TaskStatus.Running, await GetStatusAsync(id));
}
// The done toggle is a manual affordance and must work from any non-Running status --
// notably WaitingForReview, where it deliberately skips the merge.
[Theory]
[InlineData(TaskStatus.Queued)]
[InlineData(TaskStatus.WaitingForReview)]
[InlineData(TaskStatus.WaitingForChildren)]
[InlineData(TaskStatus.Failed)]
[InlineData(TaskStatus.Cancelled)]
public async Task MarkDoneAsync_FromNonRunningStatus_TransitionsToDone(TaskStatus from)
{
var id = await SeedTaskAsync(from);
var result = await _sut.MarkDoneAsync(id, DateTime.UtcNow, default);
Assert.True(result.Ok);
Assert.Equal(TaskStatus.Done, await GetStatusAsync(id));
}
[Fact]
public async Task UnmarkDoneAsync_FromDone_TransitionsToIdle()
{