diff --git a/src/ClaudeDo.Worker/Hub/WorkerHub.cs b/src/ClaudeDo.Worker/Hub/WorkerHub.cs index 959957c..96c4003 100644 --- a/src/ClaudeDo.Worker/Hub/WorkerHub.cs +++ b/src/ClaudeDo.Worker/Hub/WorkerHub.cs @@ -54,6 +54,7 @@ public record WorktreeOverviewDto( public record ForceRemoveResultDto(bool Removed, string? Reason); public record MergeResultDto(string Status, IReadOnlyList ConflictFiles, string? ErrorMessage); +public record MergePreviewDto(string Status, IReadOnlyList ConflictFiles, int ChangedFileCount); public record MergeTargetsDto(string DefaultBranch, IReadOnlyList LocalBranches); public record UpdateListDto(string Id, string Name, string? WorkingDir, string DefaultCommitType); public record UpdateListConfigDto(string ListId, string? Model, string? SystemPrompt, string? AgentPath, int? MaxTurns = null); @@ -320,6 +321,13 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub return new MergeTargetsDto(t.DefaultBranch, t.LocalBranches); }); + public Task PreviewMerge(string taskId, string targetBranch) + => HubGuard(async () => + { + var p = await _mergeService.PreviewAsync(taskId, targetBranch ?? "", CancellationToken.None); + return new MergePreviewDto(p.Status, p.ConflictFiles, p.ChangedFileCount); + }); + public async Task UpdateList(UpdateListDto dto) { using var ctx = _dbFactory.CreateDbContext(); @@ -384,11 +392,14 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub if (!result.Ok) throw new HubException(result.Reason ?? "set status failed"); } - public async Task ApproveReview(string taskId) - { - var result = await _state.ApproveReviewAsync(taskId, Context.ConnectionAborted); - if (!result.Ok) throw new HubException(result.Reason ?? "approve failed"); - } + public Task ApproveReview(string taskId, string targetBranch) + => HubGuard(async () => + { + var r = await _mergeService.ApproveAndMergeAsync(taskId, targetBranch ?? "", CancellationToken.None); + if (r.Status == TaskMergeService.StatusBlocked) + throw new HubException(r.ErrorMessage ?? "approve failed"); + return new MergeResultDto(r.Status, r.ConflictFiles, r.ErrorMessage); + }); public async Task RejectReviewToQueue(string taskId, string feedback) {