feat(ui): wire merge-aware approve and preview into the worker client
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -37,7 +37,9 @@ public interface IWorkerClient : INotifyPropertyChanged
|
|||||||
Task<ListConfigDto?> GetListConfigAsync(string listId);
|
Task<ListConfigDto?> GetListConfigAsync(string listId);
|
||||||
Task UpdateTaskAgentSettingsAsync(UpdateTaskAgentSettingsDto dto);
|
Task UpdateTaskAgentSettingsAsync(UpdateTaskAgentSettingsDto dto);
|
||||||
Task SetTaskStatusAsync(string taskId, TaskStatus status);
|
Task SetTaskStatusAsync(string taskId, TaskStatus status);
|
||||||
Task ApproveReviewAsync(string taskId);
|
Task<MergeResultDto?> ApproveReviewAsync(string taskId, string targetBranch);
|
||||||
|
Task<MergePreviewDto?> PreviewMergeAsync(string taskId, string targetBranch);
|
||||||
|
Task<MergeResultDto> MergeTaskAsync(string taskId, string targetBranch, bool removeWorktree, string commitMessage);
|
||||||
Task RejectReviewToQueueAsync(string taskId, string feedback);
|
Task RejectReviewToQueueAsync(string taskId, string feedback);
|
||||||
Task RejectReviewToIdleAsync(string taskId);
|
Task RejectReviewToIdleAsync(string taskId);
|
||||||
Task CancelReviewAsync(string taskId);
|
Task CancelReviewAsync(string taskId);
|
||||||
|
|||||||
@@ -396,10 +396,11 @@ public partial class WorkerClient : ObservableObject, IAsyncDisposable, IWorkerC
|
|||||||
await _hub.InvokeAsync("SetTaskStatus", taskId, status.ToString());
|
await _hub.InvokeAsync("SetTaskStatus", taskId, status.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task ApproveReviewAsync(string taskId)
|
public Task<MergeResultDto?> ApproveReviewAsync(string taskId, string targetBranch)
|
||||||
{
|
=> TryInvokeAsync<MergeResultDto>("ApproveReview", taskId, targetBranch);
|
||||||
await _hub.InvokeAsync("ApproveReview", taskId);
|
|
||||||
}
|
public Task<MergePreviewDto?> PreviewMergeAsync(string taskId, string targetBranch)
|
||||||
|
=> TryInvokeAsync<MergePreviewDto>("PreviewMerge", taskId, targetBranch);
|
||||||
|
|
||||||
public async Task RejectReviewToQueueAsync(string taskId, string feedback)
|
public async Task RejectReviewToQueueAsync(string taskId, string feedback)
|
||||||
{
|
{
|
||||||
@@ -529,6 +530,7 @@ public sealed record AppSettingsDto(
|
|||||||
public sealed record WorktreeCleanupDto(int Removed);
|
public sealed record WorktreeCleanupDto(int Removed);
|
||||||
public sealed record WorktreeResetDto(int Removed, int TasksAffected, bool Blocked, int RunningTasks);
|
public sealed record WorktreeResetDto(int Removed, int TasksAffected, bool Blocked, int RunningTasks);
|
||||||
public record MergeResultDto(string Status, IReadOnlyList<string> ConflictFiles, string? ErrorMessage);
|
public record MergeResultDto(string Status, IReadOnlyList<string> ConflictFiles, string? ErrorMessage);
|
||||||
|
public record MergePreviewDto(string Status, IReadOnlyList<string> ConflictFiles, int ChangedFileCount);
|
||||||
public record MergeTargetsDto(string DefaultBranch, IReadOnlyList<string> LocalBranches);
|
public record MergeTargetsDto(string DefaultBranch, IReadOnlyList<string> LocalBranches);
|
||||||
public sealed record UpdateListDto(string Id, string Name, string? WorkingDir, string DefaultCommitType);
|
public sealed record UpdateListDto(string Id, string Name, string? WorkingDir, string DefaultCommitType);
|
||||||
public sealed record UpdateListConfigDto(string ListId, string? Model, string? SystemPrompt, string? AgentPath, int? MaxTurns = null);
|
public sealed record UpdateListConfigDto(string ListId, string? Model, string? SystemPrompt, string? AgentPath, int? MaxTurns = null);
|
||||||
|
|||||||
@@ -1365,7 +1365,7 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase
|
|||||||
// The hub rejects (HubException) if the task is no longer WaitingForReview
|
// The hub rejects (HubException) if the task is no longer WaitingForReview
|
||||||
// — e.g. after "Merge all" folded the parent. Swallow it; the TaskUpdated
|
// — e.g. after "Merge all" folded the parent. Swallow it; the TaskUpdated
|
||||||
// broadcast reconciles the UI. An unhandled command exception would crash.
|
// broadcast reconciles the UI. An unhandled command exception would crash.
|
||||||
try { await _worker.ApproveReviewAsync(Task.Id); }
|
try { await _worker.ApproveReviewAsync(Task.Id, SelectedMergeTarget ?? ""); }
|
||||||
catch { /* stale review action; broadcast reconciles */ }
|
catch { /* stale review action; broadcast reconciles */ }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -647,7 +647,7 @@ public sealed partial class TasksIslandViewModel : ViewModelBase
|
|||||||
private async Task ApproveReviewAsync(TaskRowViewModel? row)
|
private async Task ApproveReviewAsync(TaskRowViewModel? row)
|
||||||
{
|
{
|
||||||
if (row is null || !row.IsWaitingForReview || _worker is null) return;
|
if (row is null || !row.IsWaitingForReview || _worker is null) return;
|
||||||
try { await _worker.ApproveReviewAsync(row.Id); }
|
try { await _worker.ApproveReviewAsync(row.Id, ""); }
|
||||||
catch { /* offline; broadcast reconciles on return */ }
|
catch { /* offline; broadcast reconciles on return */ }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,9 @@ public abstract class StubWorkerClient : IWorkerClient
|
|||||||
public virtual Task<ListConfigDto?> GetListConfigAsync(string listId) => Task.FromResult<ListConfigDto?>(null);
|
public virtual Task<ListConfigDto?> GetListConfigAsync(string listId) => Task.FromResult<ListConfigDto?>(null);
|
||||||
public virtual Task UpdateTaskAgentSettingsAsync(UpdateTaskAgentSettingsDto dto) => Task.CompletedTask;
|
public virtual Task UpdateTaskAgentSettingsAsync(UpdateTaskAgentSettingsDto dto) => Task.CompletedTask;
|
||||||
public virtual Task SetTaskStatusAsync(string taskId, TaskStatus status) => Task.CompletedTask;
|
public virtual Task SetTaskStatusAsync(string taskId, TaskStatus status) => Task.CompletedTask;
|
||||||
public virtual Task ApproveReviewAsync(string taskId) => Task.CompletedTask;
|
public virtual Task<MergeResultDto?> ApproveReviewAsync(string taskId, string targetBranch) => Task.FromResult<MergeResultDto?>(null);
|
||||||
|
public virtual Task<MergePreviewDto?> PreviewMergeAsync(string taskId, string targetBranch) => Task.FromResult<MergePreviewDto?>(null);
|
||||||
|
public virtual Task<MergeResultDto> MergeTaskAsync(string taskId, string targetBranch, bool removeWorktree, string commitMessage) => Task.FromResult(new MergeResultDto("merged", System.Array.Empty<string>(), null));
|
||||||
public virtual Task RejectReviewToQueueAsync(string taskId, string feedback) => Task.CompletedTask;
|
public virtual Task RejectReviewToQueueAsync(string taskId, string feedback) => Task.CompletedTask;
|
||||||
public virtual Task RejectReviewToIdleAsync(string taskId) => Task.CompletedTask;
|
public virtual Task RejectReviewToIdleAsync(string taskId) => Task.CompletedTask;
|
||||||
public virtual Task CancelReviewAsync(string taskId) => Task.CompletedTask;
|
public virtual Task CancelReviewAsync(string taskId) => Task.CompletedTask;
|
||||||
|
|||||||
@@ -74,8 +74,8 @@ public class DetailsIslandPlanningTests : IDisposable
|
|||||||
private sealed class ThrowingReviewWorkerClient : StubWorkerClient
|
private sealed class ThrowingReviewWorkerClient : StubWorkerClient
|
||||||
{
|
{
|
||||||
public override bool IsConnected => true;
|
public override bool IsConnected => true;
|
||||||
public override Task ApproveReviewAsync(string taskId) =>
|
public override Task<MergeResultDto?> ApproveReviewAsync(string taskId, string targetBranch) =>
|
||||||
Task.FromException(new InvalidOperationException("Task is not waiting for review; cannot approve."));
|
Task.FromException<MergeResultDto?>(new InvalidOperationException("Task is not waiting for review; cannot approve."));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static SubtaskRowViewModel MakeSubtask(TaskStatus status, WorktreeState wt = WorktreeState.Active) =>
|
private static SubtaskRowViewModel MakeSubtask(TaskStatus status, WorktreeState wt = WorktreeState.Active) =>
|
||||||
|
|||||||
@@ -42,7 +42,9 @@ sealed class FakeWorkerClient : IWorkerClient
|
|||||||
public Task<ListConfigDto?> GetListConfigAsync(string listId) => Task.FromResult<ListConfigDto?>(null);
|
public Task<ListConfigDto?> GetListConfigAsync(string listId) => Task.FromResult<ListConfigDto?>(null);
|
||||||
public Task UpdateTaskAgentSettingsAsync(UpdateTaskAgentSettingsDto dto) => Task.CompletedTask;
|
public Task UpdateTaskAgentSettingsAsync(UpdateTaskAgentSettingsDto dto) => Task.CompletedTask;
|
||||||
public Task SetTaskStatusAsync(string taskId, TaskStatus status) => Task.CompletedTask;
|
public Task SetTaskStatusAsync(string taskId, TaskStatus status) => Task.CompletedTask;
|
||||||
public Task ApproveReviewAsync(string taskId) => Task.CompletedTask;
|
public Task<MergeResultDto?> ApproveReviewAsync(string taskId, string targetBranch) => Task.FromResult<MergeResultDto?>(null);
|
||||||
|
public Task<MergePreviewDto?> PreviewMergeAsync(string taskId, string targetBranch) => Task.FromResult<MergePreviewDto?>(null);
|
||||||
|
public Task<MergeResultDto> MergeTaskAsync(string taskId, string targetBranch, bool removeWorktree, string commitMessage) => Task.FromResult(new MergeResultDto("merged", System.Array.Empty<string>(), null));
|
||||||
public Task RejectReviewToQueueAsync(string taskId, string feedback) => Task.CompletedTask;
|
public Task RejectReviewToQueueAsync(string taskId, string feedback) => Task.CompletedTask;
|
||||||
public Task RejectReviewToIdleAsync(string taskId) => Task.CompletedTask;
|
public Task RejectReviewToIdleAsync(string taskId) => Task.CompletedTask;
|
||||||
public Task CancelReviewAsync(string taskId) => Task.CompletedTask;
|
public Task CancelReviewAsync(string taskId) => Task.CompletedTask;
|
||||||
|
|||||||
Reference in New Issue
Block a user