feat(mcp): allow Done via update_task_status with worktree guard
External tasks finished outside a ClaudeDo run had no way to close out their tracking task; update_task_status now permits Done alongside Idle/Queued/Cancelled, refusing it when the task has an active worktree so review_task stays the only path that merges.
This commit is contained in:
+18
-2
@@ -264,10 +264,12 @@ public sealed class ExternalMcpService
|
||||
}
|
||||
|
||||
[McpServerTool, Description(
|
||||
"Update a task's status. Only 'Idle', 'Queued' and 'Cancelled' are permitted externally — " +
|
||||
"Update a task's status. Only 'Idle', 'Queued', 'Cancelled' and 'Done' are permitted externally — " +
|
||||
"use run_task_now for execution control, and review_task to act on a WaitingForReview task. " +
|
||||
"Settable: Idle (reset to editable), Queued (enqueue for execution), " +
|
||||
"Cancelled (retire the task without deleting it; it can be reset to Idle later). " +
|
||||
"Cancelled (retire the task without deleting it; it can be reset to Idle later), " +
|
||||
"Done (mark complete; refused if the task has an active worktree — use review_task to approve " +
|
||||
"and merge that worktree instead). " +
|
||||
"Full lifecycle: Idle → Queued → Running → WaitingForReview → Done | Failed | Cancelled.")]
|
||||
public async Task<TaskDto> UpdateTaskStatus(
|
||||
string taskId,
|
||||
@@ -300,6 +302,20 @@ public sealed class ExternalMcpService
|
||||
throw new InvalidOperationException(cancelResult.Reason ?? "Cannot cancel task.");
|
||||
break;
|
||||
|
||||
case TaskStatus.Done:
|
||||
await using (var ctx = await _dbFactory.CreateDbContextAsync(cancellationToken))
|
||||
{
|
||||
var wt = await new WorktreeRepository(ctx).GetByTaskIdAsync(taskId, cancellationToken);
|
||||
if (wt is not null && wt.State == WorktreeState.Active)
|
||||
throw new InvalidOperationException(
|
||||
"Task has an active worktree — use review_task to approve and merge instead.");
|
||||
}
|
||||
|
||||
var doneResult = await _state.ForceSetStatusAsync(taskId, TaskStatus.Done, cancellationToken);
|
||||
if (!doneResult.Ok)
|
||||
throw new InvalidOperationException(doneResult.Reason ?? "Cannot set task to Done.");
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new InvalidOperationException(
|
||||
$"Status '{target}' is not settable externally. Use run_task_now or review_task.");
|
||||
|
||||
Reference in New Issue
Block a user