fix(worker): preview_merge braucht einen runVerify-Parameter wie preview_merge_set

preview_merge baute bisher immer, sobald die Liste ein Verify-Kommando
konfiguriert hatte -- anders als das Geschwister-Tool preview_merge_set,
dessen runVerify-Parameter per Default false ist. Ein einzelnes preview_merge
im Merge-Helper-Recheck stiess dadurch einen ungewollten Scratch-Build an.

runVerify (Default false) jetzt symmetrisch bei preview_merge ergaenzt,
Description-Text und die Merge-Helper-Prompt-Doku angepasst.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Mika Kuns
2026-09-16 15:43:37 +02:00
committed by mika kuns
co-authored by Claude Sonnet 5
parent c874bf7e52
commit 7452f6cfe4
4 changed files with 59 additions and 27 deletions
+39 -11
View File
@@ -793,7 +793,7 @@ public sealed class MergeMcpToolsTests : IDisposable
var headBefore = await git.RevParseHeadAsync(list.WorkingDir!, CancellationToken.None);
var sut = BuildSut(CreateQueue());
var result = await sut.PreviewMerge(task.Id, target, CancellationToken.None);
var result = await sut.PreviewMerge(task.Id, target, cancellationToken: CancellationToken.None);
Assert.Equal(TaskMergeService.PreviewClean, result.Status);
Assert.Empty(result.ConflictFiles);
@@ -815,7 +815,7 @@ public sealed class MergeMcpToolsTests : IDisposable
var target = await new GitService().GetCurrentBranchAsync(list.WorkingDir!, CancellationToken.None);
var sut = BuildSut(CreateQueue());
var result = await sut.PreviewMerge(task.Id, target, CancellationToken.None);
var result = await sut.PreviewMerge(task.Id, target, cancellationToken: CancellationToken.None);
Assert.Equal(TaskMergeService.PreviewClean, result.Status);
Assert.Equal(0, result.ChangedFileCount);
@@ -843,7 +843,7 @@ public sealed class MergeMcpToolsTests : IDisposable
}
var sut = BuildSut(CreateQueue());
var result = await sut.PreviewMerge(task.Id, null, CancellationToken.None);
var result = await sut.PreviewMerge(task.Id, null, cancellationToken: CancellationToken.None);
Assert.Equal(TaskMergeService.PreviewClean, result.Status);
Assert.Equal(0, result.ChangedFileCount);
@@ -875,7 +875,7 @@ public sealed class MergeMcpToolsTests : IDisposable
}
var sut = BuildSut(CreateQueue());
var result = await sut.PreviewMerge(task.Id, null, CancellationToken.None);
var result = await sut.PreviewMerge(task.Id, null, cancellationToken: CancellationToken.None);
Assert.Equal(TaskMergeService.PreviewClean, result.Status);
Assert.Equal(1, result.ChangedFileCount);
@@ -893,7 +893,7 @@ public sealed class MergeMcpToolsTests : IDisposable
var headBefore = await git.RevParseHeadAsync(list.WorkingDir!, CancellationToken.None);
var sut = BuildSut(CreateQueue());
var result = await sut.PreviewMerge(task.Id, target, CancellationToken.None);
var result = await sut.PreviewMerge(task.Id, target, cancellationToken: CancellationToken.None);
Assert.Equal(TaskMergeService.PreviewConflict, result.Status);
Assert.Contains("README.md", result.ConflictFiles);
@@ -910,7 +910,7 @@ public sealed class MergeMcpToolsTests : IDisposable
var sut = BuildSut(CreateQueue());
await Assert.ThrowsAsync<InvalidOperationException>(
() => sut.PreviewMerge(task.Id, null, CancellationToken.None));
() => sut.PreviewMerge(task.Id, null, cancellationToken: CancellationToken.None));
}
[Fact]
@@ -928,7 +928,7 @@ public sealed class MergeMcpToolsTests : IDisposable
var sut = BuildSut(CreateQueue());
var ex = await Assert.ThrowsAsync<InvalidOperationException>(
() => sut.PreviewMerge(task.Id, null, CancellationToken.None));
() => sut.PreviewMerge(task.Id, null, cancellationToken: CancellationToken.None));
Assert.Contains("working directory", ex.Message, StringComparison.OrdinalIgnoreCase);
}
@@ -952,7 +952,7 @@ public sealed class MergeMcpToolsTests : IDisposable
var fakeVerify = new FakeVerifyCommandRunner { Result = new VerifyCommandResult(0, false, "ok") };
var sut = BuildSut(CreateQueue(), fakeVerify);
var result = await sut.PreviewMerge(task.Id, target, CancellationToken.None);
var result = await sut.PreviewMerge(task.Id, target, runVerify: true, cancellationToken: CancellationToken.None);
Assert.Equal(TaskMergeService.PreviewClean, result.Status);
Assert.Equal(0, result.VerifyExitCode);
@@ -962,6 +962,34 @@ public sealed class MergeMcpToolsTests : IDisposable
Assert.False(await git.HasChangesAsync(list.WorkingDir!, CancellationToken.None));
}
[Fact]
public async Task PreviewMerge_DefaultRunVerifyFalse_NeverInvokesRunnerEvenWithCommandConfigured()
{
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<WorktreeManager>.Instance);
await mgr.CommitIfChangedAsync(wt, task, list, CancellationToken.None);
using (var ctx = _db.CreateContext())
await new ListRepository(ctx).SetConfigAsync(new ListConfigEntity { ListId = list.Id, VerifyCommand = "dotnet build" });
var git = new GitService();
var target = await git.GetCurrentBranchAsync(list.WorkingDir!, CancellationToken.None);
var fakeVerify = new FakeVerifyCommandRunner { Result = new VerifyCommandResult(0, false, "ok") };
var sut = BuildSut(CreateQueue(), fakeVerify);
var result = await sut.PreviewMerge(task.Id, target, cancellationToken: CancellationToken.None);
Assert.Equal(TaskMergeService.PreviewClean, result.Status);
Assert.Null(result.VerifyExitCode);
Assert.Null(result.VerifyDurationMs);
Assert.Null(result.VerifyOutputTail);
Assert.Null(fakeVerify.CapturedCommand);
}
[Fact]
public async Task PreviewMerge_TargetChangedSameFileSinceFork_ReportsStaleFiles()
{
@@ -982,7 +1010,7 @@ public sealed class MergeMcpToolsTests : IDisposable
GitRepoFixture.RunGit(repo.RepoDir, "commit", "-m", "main also touched shared.txt");
var sut = BuildSut(CreateQueue());
var result = await sut.PreviewMerge(task.Id, "main", CancellationToken.None);
var result = await sut.PreviewMerge(task.Id, "main", cancellationToken: CancellationToken.None);
Assert.Equal(1, result.Behind);
Assert.NotNull(result.StaleFiles);
@@ -1010,7 +1038,7 @@ public sealed class MergeMcpToolsTests : IDisposable
GitRepoFixture.RunGit(repo.RepoDir, "commit", "-m", "main touched something else");
var sut = BuildSut(CreateQueue());
var result = await sut.PreviewMerge(task.Id, "main", CancellationToken.None);
var result = await sut.PreviewMerge(task.Id, "main", cancellationToken: CancellationToken.None);
Assert.Equal(1, result.Behind);
Assert.NotNull(result.StaleFiles);
@@ -1042,7 +1070,7 @@ public sealed class MergeMcpToolsTests : IDisposable
}
var sut = BuildSut(CreateQueue());
var result = await sut.PreviewMerge(task.Id, null, CancellationToken.None);
var result = await sut.PreviewMerge(task.Id, null, cancellationToken: CancellationToken.None);
Assert.NotNull(result.StaleFiles);
Assert.Empty(result.StaleFiles!);