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:
+9
-4
@@ -703,16 +703,21 @@ public sealed class ExternalMcpService
|
||||
// externallyDriven: true — this call came from an MCP session, not the UI's
|
||||
// Approve button. A unit-merge conflict must not auto-open the in-app resolver;
|
||||
// the driving session resolves it via continue_merge/abort_merge instead.
|
||||
await _planningMerge.StartAsync(taskId, targetBranch ?? "", cancellationToken, externallyDriven: true, progress);
|
||||
var parentDone = (await _tasks.GetByIdAsync(taskId, cancellationToken))!.Status == TaskStatus.Done;
|
||||
mergeStatus = parentDone ? TaskMergeService.StatusMerged : TaskMergeService.StatusConflict;
|
||||
if (!parentDone)
|
||||
var startResult = await _planningMerge.StartAsync(taskId, targetBranch ?? "", cancellationToken, externallyDriven: true, progress);
|
||||
if (startResult.Status == TaskMergeService.StatusBlocked)
|
||||
throw new InvalidOperationException(startResult.Reason ?? "approve failed");
|
||||
mergeStatus = startResult.Status;
|
||||
if (startResult.Status == TaskMergeService.StatusConflict)
|
||||
{
|
||||
var list = await _lists.GetByIdAsync(task.ListId, cancellationToken);
|
||||
repoPath = list?.WorkingDir;
|
||||
mergeMessage = "unit merge paused on a conflict — markers left in the working tree; " +
|
||||
"resolve them then call continue_merge with the parent task id, or abort_merge to cancel";
|
||||
}
|
||||
else if (startResult.Status != TaskMergeService.StatusMerged)
|
||||
{
|
||||
mergeMessage = startResult.Reason;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user