fix(worker,ui): block cancelling a task while its unit merge is draining
TaskStateService.CancelAsync allowed cancelling a WaitingForReview task even while PlanningMergeOrchestrator was mid-drain on it: ApproveReview awaits the whole multi-subtask merge synchronously, so a concurrent CancelReview (UI or MCP) could flip the parent to Cancelled while the orchestrator kept merging children onto the target branch, then FinalizeParentDoneAsync would find the parent no longer WaitingForReview and give up - leaving the merged diffs stranded with no rollback. CancelAsync now rejects with a clear reason when HasActiveMerge(taskId) is true. TaskStateService can't take PlanningMergeOrchestrator as a direct constructor dependency (circular back to ITaskStateService), so it takes a lazily-resolved Func<IActiveMergeState> instead, mirroring the existing Func<ITaskStateService> cycle-break already used for PlanningChainCoordinator. UI polish: DetailsIslandViewModel.IsMergeDraining gates CancelReviewCommand's CanExecute (same shape as WorktreesOverviewModalViewModel.IsMerging), and the command's catch now raises ErrorReported instead of swallowing the rejection silently.
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
namespace ClaudeDo.Worker.Planning;
|
||||
|
||||
// Lets TaskStateService guard CancelAsync against an in-progress unit merge without a
|
||||
// hard constructor cycle back to PlanningMergeOrchestrator (which itself depends on
|
||||
// ITaskStateService) — TaskStateService takes a Func<IActiveMergeState> instead, resolved
|
||||
// lazily so both singletons can finish constructing before either calls into the other.
|
||||
public interface IActiveMergeState
|
||||
{
|
||||
bool HasActiveMerge(string taskId);
|
||||
}
|
||||
Reference in New Issue
Block a user