diff --git a/src/ClaudeDo.Worker/Planning/PlanningMergeOrchestrator.cs b/src/ClaudeDo.Worker/Planning/PlanningMergeOrchestrator.cs index 643b9a5..6c46750 100644 --- a/src/ClaudeDo.Worker/Planning/PlanningMergeOrchestrator.cs +++ b/src/ClaudeDo.Worker/Planning/PlanningMergeOrchestrator.cs @@ -96,11 +96,23 @@ public sealed class PlanningMergeOrchestrator var current = state.CurrentSubtaskId; var result = await _merge.ContinueMergeAsync(current, ct); - if (result.Status != TaskMergeService.StatusMerged) + + if (result.Status == TaskMergeService.StatusConflict) { await _broadcaster.PlanningMergeConflict(planningTaskId, current, result.ConflictFiles); return; } + + if (result.Status != TaskMergeService.StatusMerged) + { + _logger.LogWarning( + "Planning continue blocked on subtask {Subtask}: {Msg}", + current, result.ErrorMessage); + _states.TryRemove(planningTaskId, out _); + await _broadcaster.PlanningMergeAborted(planningTaskId); + return; + } + await _broadcaster.PlanningSubtaskMerged(planningTaskId, current); state.CurrentSubtaskId = null; @@ -144,11 +156,11 @@ public sealed class PlanningMergeOrchestrator if (result.Status != TaskMergeService.StatusMerged) { - await _broadcaster.PlanningMergeConflict( - planningTaskId, subtaskId, - new[] { result.ErrorMessage ?? "merge blocked" }); - keepState = true; - return; + _logger.LogWarning( + "Planning merge blocked on subtask {Subtask}: {Msg}", + subtaskId, result.ErrorMessage); + await _broadcaster.PlanningMergeAborted(planningTaskId); + return; // keepState stays false → finally removes the state entry } await _broadcaster.PlanningSubtaskMerged(planningTaskId, subtaskId);