using ClaudeDo.Worker.Hub; using ClaudeDo.Worker.Lifecycle; using ClaudeDo.Worker.Tests.Infrastructure; using Microsoft.Extensions.Logging.Abstractions; namespace ClaudeDo.Worker.Tests.Lifecycle; public sealed class PlanningLineageRecoveryTests : IDisposable { private readonly DbFixture _db = new(); public void Dispose() => _db.Dispose(); [Fact] public async Task StartAsync_SessionsDirMissing_BroadcastsStartupRecoveryProgress() { var missingRoot = Path.Combine(Path.GetTempPath(), $"claudedo_planning_sessions_{Guid.NewGuid():N}"); var hubContext = new CapturingHubContext(); var sut = new PlanningLineageRecovery( _db.CreateFactory(), missingRoot, new HubBroadcaster(hubContext), NullLogger.Instance); await sut.StartAsync(CancellationToken.None); await sut.StopAsync(CancellationToken.None); Assert.Contains(hubContext.Proxy.Calls, c => c.Method == "OperationProgress" && (string)c.Args[0]! == "startup-recovery"); } [Fact] public async Task StartAsync_NoSessionFolders_BroadcastsStartupRecoveryProgress() { var root = Path.Combine(Path.GetTempPath(), $"claudedo_planning_sessions_{Guid.NewGuid():N}"); Directory.CreateDirectory(root); try { var hubContext = new CapturingHubContext(); var sut = new PlanningLineageRecovery( _db.CreateFactory(), root, new HubBroadcaster(hubContext), NullLogger.Instance); await sut.StartAsync(CancellationToken.None); Assert.Contains(hubContext.Proxy.Calls, c => c.Method == "OperationProgress" && (string)c.Args[0]! == "startup-recovery"); } finally { if (Directory.Exists(root)) Directory.Delete(root, recursive: true); } } }