module SomhairlesDream.Server.Tests.CoordinatorTests open System open System.IO open System.Threading open Xunit open SomhairlesDream.Modeling open SomhairlesDream.Server open SomhairlesDream.Shared let private ids : RunIds = { ProjectId = "heritage-001" RunId = "run-20260920-001" BaseId = "heritage" TargetId = "heritage-001" } let private withTempDirectory action = let path = Path.Combine(Path.GetTempPath(), "somhairles-dream-server-" + Guid.NewGuid().ToString("N")) Directory.CreateDirectory(path) |> ignore try action path finally if Directory.Exists(path) then Directory.Delete(path, true) type private TestBridge() = interface IArtifactBridge with member _.Export(request, _) = File.WriteAllBytes(request.GlbPath, [| 0x67uy; 0x6Cuy; 0x54uy; byte request.Step.Index |]) Directory.CreateDirectory(Path.GetDirectoryName(request.LogPath)) |> ignore File.WriteAllText(request.LogPath, $"bridge log for {request.Step.StepId}") Ok { BlenderVersion = "5.0.1" ExportedAt = DateTimeOffset.Parse("2026-09-20T12:00:05Z") ObjectIds = request.Step.ObjectIds VerifiedObjectIds = request.Step.ObjectIds GlbBytes = 4L RenderPath = None RenderedAt = None } let private waitFor predicate = let deadline = DateTime.UtcNow.AddSeconds(5.) let mutable matched = predicate () while not matched && DateTime.UtcNow < deadline do Thread.Sleep(10) matched <- predicate () matched [] let ``coordinator starts one shared pipeline and publishes its manifest`` () = withTempDirectory (fun root -> let clock () = DateTimeOffset.Parse("2026-09-20T12:00:00Z") let coordinator = ArtifactRunCoordinator( root, (fun () -> TestBridge() :> IArtifactBridge), clock, TimeSpan.FromSeconds 15. ) match coordinator.Start(ids, false) with | Error message -> failwith message | Ok(Accepted snapshot) -> Assert.Equal(ids.ProjectId, snapshot.ProjectId) Assert.Equal(ids.RunId, snapshot.RunId) | Ok(Conflict _) -> failwith "expected the first start to be accepted" let completed = waitFor (fun () -> coordinator.TryFind(ids.ProjectId, ids.RunId) |> Option.exists (fun store -> store.Snapshot().Status = "complete")) Assert.True(completed) match coordinator.Manifest(ids.ProjectId, ids.RunId) with | Error failure -> failwith $"manifest lookup failed: {failure}" | Ok manifest -> Assert.Equal("complete", manifest.Status) Assert.Equal(3, manifest.Steps.Length))