From ca8326c4c55e29e4014bd42c2ccb68395fbde7e8 Mon Sep 17 00:00:00 2001 From: mika kuns Date: Tue, 9 Jun 2026 10:36:26 +0200 Subject: [PATCH] fix(mcp): merge_task marks the task Done after a successful merge merge_task only flipped the worktree to Merged; it never transitioned the task status. With allowWaitingForReview this left a merged task stuck in WaitingForReview. Approve it to Done on a successful merge (a Done task is already terminal). Mirrors the ApproveAndMergeAsync review flow. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../External/ExternalMcpService.cs | 6 ++++++ .../External/ExternalMcpServiceTests.cs | 21 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/src/ClaudeDo.Worker/External/ExternalMcpService.cs b/src/ClaudeDo.Worker/External/ExternalMcpService.cs index 8e13557..e943ee2 100644 --- a/src/ClaudeDo.Worker/External/ExternalMcpService.cs +++ b/src/ClaudeDo.Worker/External/ExternalMcpService.cs @@ -468,6 +468,12 @@ public sealed class ExternalMcpService if (result.Status == TaskMergeService.StatusMerged) { + // MergeAsync only flips the worktree to Merged; a merged task must also + // reach Done. If it was still awaiting review, approve it now (a Done task + // is already terminal and needs no transition). + if (task.Status == TaskStatus.WaitingForReview) + await _state.ApproveReviewAsync(taskId, cancellationToken); + string? mergeCommit = null; try { diff --git a/tests/ClaudeDo.Worker.Tests/External/ExternalMcpServiceTests.cs b/tests/ClaudeDo.Worker.Tests/External/ExternalMcpServiceTests.cs index 5523c1b..65cbc82 100644 --- a/tests/ClaudeDo.Worker.Tests/External/ExternalMcpServiceTests.cs +++ b/tests/ClaudeDo.Worker.Tests/External/ExternalMcpServiceTests.cs @@ -708,6 +708,27 @@ public sealed class ExternalMcpServiceTests : IDisposable Assert.Null(result.MergeCommit); } + [Fact] + public async Task MergeTask_WaitingForReview_WithFlag_MarksTaskDone() + { + if (!GitAvailable) { Assert.True(true, "git not available -- skipping"); return; } + + var (task, list, wt) = await SeedWorktreeAsync(TaskStatus.WaitingForReview); + File.WriteAllText(Path.Combine(wt.WorktreePath, "added.txt"), "content"); + var cfg = new WorkerConfig { WorktreeRootStrategy = "sibling" }; + var mgr = new WorktreeManager(new GitService(), _db.CreateFactory(), cfg, NullLogger.Instance); + await mgr.CommitIfChangedAsync(wt, task, list, CancellationToken.None); + + var target = await new GitService().GetCurrentBranchAsync(list.WorkingDir, CancellationToken.None); + var sut = BuildSut(CreateQueue()); + + var result = await sut.MergeTask(task.Id, target, true, dryRun: false, allowWaitingForReview: true, CancellationToken.None); + + Assert.True(result.Merged); + var reloaded = await new TaskRepository(_db.CreateContext()).GetByIdAsync(task.Id); + Assert.Equal(TaskStatus.Done, reloaded!.Status); + } + // ── ContinueTask validation ─────────────────────────────────────────────── [Fact]