Merge claudedo/81b054800dc4446598685fd04fefddb5

This commit is contained in:
mika kuns
2026-08-06 13:45:15 +02:00
3 changed files with 55 additions and 11 deletions
@@ -456,6 +456,25 @@ public sealed class TaskStateServiceTests : IDisposable
Assert.StartsWith("[stale] ", t.Result);
}
[Fact]
public async Task RecoverStaleRunningAsync_ResolvesBlockedSuccessor_AndAdvancesParent()
{
var parent = await SeedTaskAsync(TaskStatus.WaitingForChildren, phase: PlanningPhase.Finalized);
var c0 = await SeedTaskAsync(TaskStatus.Running, parentId: parent, sortOrder: 0);
var c1 = await SeedTaskAsync(TaskStatus.Queued, parentId: parent, sortOrder: 1, blockedBy: c0);
var count = await _sut.RecoverStaleRunningAsync("worker restart", default);
Assert.Equal(1, count);
Assert.Equal(TaskStatus.Failed, await GetStatusAsync(c0));
// c1 was blocked on the crashed task; the chain coordinator resolves it (cancels it,
// since the predecessor didn't finish successfully) instead of leaving it Queued with
// a dangling BlockedByTaskId that the picker would skip forever.
Assert.Equal(TaskStatus.Cancelled, await GetStatusAsync(c1));
// Both children are now terminal, so the WaitingForChildren parent advances.
Assert.Equal(TaskStatus.WaitingForReview, await GetStatusAsync(parent));
}
// ─── Child terminal → chain advance ───────────────────────────────────
[Fact]