fix(worker): propagate unit-merge failures instead of reporting success
A child merge that came back blocked/verify_failed/untracked_collision during a parent/children unit merge used to vanish: DrainAsync only logged it server-side, PlanningMergeAborted carried no reason, and ApproveReview/review_task always reported StatusMerged for a task with children regardless of the real outcome, so a failed unit merge left the parent stuck with no visible error. - PlanningMergeOrchestrator.StartAsync/ContinueAsync/DrainAsync now return a PlanningMergeResult(Status, Reason) instead of void, and PlanningMergeAborted carries that reason to the UI. - WorkerHub.ApproveReview and ExternalMcpService.ReviewTask's approve branch propagate the real status/reason for a parent with children instead of hardcoding "merged" (or masking a non-conflict failure as "conflict"). - StartAsync now requires the parent to already be WaitingForReview for improvement parents too, not just planning ones, so a stale caller can no longer trigger a partial child merge. - HasActiveMerge now also covers the window between the last child merging and FinalizeParentDoneAsync completing, closing a gap where a concurrent Cancel could race the parent's own approve-to-Done transition. - IslandsShellViewModel.OnPlanningMergeAborted flashes the reason via FlashFooterError instead of only clearing the external-merge banner.
This commit is contained in:
@@ -54,7 +54,9 @@ public interface IWorkerClient : INotifyPropertyChanged
|
||||
/// is true when an MCP session (not the UI) started the unit merge — the resolver must not
|
||||
/// auto-open in that case.</summary>
|
||||
event Action<string, string, IReadOnlyList<string>, bool>? PlanningMergeConflictEvent;
|
||||
event Action<string>? PlanningMergeAbortedEvent;
|
||||
/// <summary>(planningTaskId, reason). reason is set when the merge stopped on a real failure
|
||||
/// (blocked/verify_failed/untracked_collision) rather than a deliberate abort.</summary>
|
||||
event Action<string, string?>? PlanningMergeAbortedEvent;
|
||||
event Action<string>? PlanningCompletedEvent;
|
||||
|
||||
event Action<PrimeFiredEvent>? PrimeFired;
|
||||
|
||||
@@ -70,7 +70,7 @@ public partial class WorkerClient : ObservableObject, IAsyncDisposable, IWorkerC
|
||||
public event Action<string, string>? PlanningMergeStartedEvent;
|
||||
public event Action<string, string>? PlanningSubtaskMergedEvent;
|
||||
public event Action<string, string, IReadOnlyList<string>, bool>? PlanningMergeConflictEvent;
|
||||
public event Action<string>? PlanningMergeAbortedEvent;
|
||||
public event Action<string, string?>? PlanningMergeAbortedEvent;
|
||||
public event Action<string>? PlanningCompletedEvent;
|
||||
|
||||
public event Action<PrimeFiredEvent>? PrimeFired;
|
||||
@@ -199,9 +199,9 @@ public partial class WorkerClient : ObservableObject, IAsyncDisposable, IWorkerC
|
||||
Dispatcher.UIThread.Post(() => PlanningMergeConflictEvent?.Invoke(planningTaskId, subtaskId, conflictedFiles, externallyDriven));
|
||||
});
|
||||
|
||||
_hub.On<string>("PlanningMergeAborted", planningTaskId =>
|
||||
_hub.On<string, string?>("PlanningMergeAborted", (planningTaskId, reason) =>
|
||||
{
|
||||
Dispatcher.UIThread.Post(() => PlanningMergeAbortedEvent?.Invoke(planningTaskId));
|
||||
Dispatcher.UIThread.Post(() => PlanningMergeAbortedEvent?.Invoke(planningTaskId, reason));
|
||||
});
|
||||
|
||||
_hub.On<string>("PlanningCompleted", planningTaskId =>
|
||||
|
||||
Reference in New Issue
Block a user