feat(external-mcp): let set_list_config write the verify command

SetListConfig previously could only pass VerifyCommand through unchanged;
only the UI hub could set it. Add an optional verifyCommand parameter with
matching clear/merge/create-vs-delete handling, and split the list result
into ListConfigDto so the task-only SetTaskConfig/GetTaskConfig DTOs stay
untouched. Also corrects Worker/CLAUDE.md's claim that tasks can override
verify_command — it's list-only.
This commit is contained in:
mika kuns
2026-08-11 08:52:03 +02:00
parent 11103d4d3e
commit 095d216bda
3 changed files with 110 additions and 29 deletions
+80 -3
View File
@@ -116,6 +116,85 @@ public sealed class ConfigMcpToolsTests : IDisposable
_sut.SetListConfig(listId, clearFields: new[] { "bogus" }, cancellationToken: CancellationToken.None));
}
[Fact]
public async Task SetListConfig_SetsVerifyCommand()
{
var listId = await SeedListAsync();
var result = await _sut.SetListConfig(listId, verifyCommand: "dotnet test", cancellationToken: CancellationToken.None);
Assert.Equal("dotnet test", result.Config!.VerifyCommand);
var cfg = await _sut.GetListConfig(listId, CancellationToken.None);
Assert.Equal("dotnet test", cfg.Config!.VerifyCommand);
}
[Fact]
public async Task SetListConfig_OverwritesVerifyCommand()
{
var listId = await SeedListAsync();
await _sut.SetListConfig(listId, verifyCommand: "dotnet test", cancellationToken: CancellationToken.None);
var result = await _sut.SetListConfig(listId, verifyCommand: "dotnet build", cancellationToken: CancellationToken.None);
Assert.Equal("dotnet build", result.Config!.VerifyCommand);
}
[Fact]
public async Task SetListConfig_ClearVerifyCommand_ClearsOnlyThatField()
{
var listId = await SeedListAsync();
await _sut.SetListConfig(listId, "opus", verifyCommand: "dotnet test", cancellationToken: CancellationToken.None);
var result = await _sut.SetListConfig(listId, clearFields: new[] { "verifyCommand" }, cancellationToken: CancellationToken.None);
Assert.Equal("opus", result.Config!.Model);
Assert.Null(result.Config.VerifyCommand);
}
[Fact]
public async Task SetListConfig_ConfigWithOnlyVerifyCommand_IsCreated()
{
var listId = await SeedListAsync();
var result = await _sut.SetListConfig(listId, verifyCommand: "dotnet test", cancellationToken: CancellationToken.None);
Assert.True(result.Ok);
Assert.NotNull(result.Config);
Assert.Equal("dotnet test", result.Config!.VerifyCommand);
Assert.Null(result.Config.Model);
}
[Fact]
public async Task SetListConfig_ClearingEveryOtherField_KeepsConfigWhenVerifyCommandRemains()
{
var listId = await SeedListAsync();
await _sut.SetListConfig(listId, "sonnet", "be terse", "agent.md", 30, "dotnet test", cancellationToken: CancellationToken.None);
var result = await _sut.SetListConfig(
listId, clearFields: new[] { "model", "systemPrompt", "agentPath", "maxTurns" }, cancellationToken: CancellationToken.None);
Assert.True(result.Ok);
Assert.NotNull(result.Config);
Assert.Equal("dotnet test", result.Config!.VerifyCommand);
Assert.Null(result.Config.Model);
}
[Fact]
public async Task SetListConfig_ClearingEveryFieldIncludingVerifyCommand_DeletesConfig()
{
var listId = await SeedListAsync();
await _sut.SetListConfig(listId, "sonnet", verifyCommand: "dotnet test", cancellationToken: CancellationToken.None);
var result = await _sut.SetListConfig(
listId,
clearFields: new[] { "model", "systemPrompt", "agentPath", "maxTurns", "verifyCommand" },
cancellationToken: CancellationToken.None);
Assert.True(result.Ok);
Assert.Null(result.Config);
Assert.Null(await _lists.GetConfigAsync(listId));
}
[Fact]
public async Task SetTaskConfig_PersistsOverrides()
{
@@ -256,13 +335,12 @@ public sealed class ConfigMcpToolsTests : IDisposable
{
ListId = listId,
Model = "sonnet",
VerifyCommand = "dotnet build",
SerializeOnFileOverlap = true,
});
var result = await _sut.SetListConfig(
listId,
clearFields: new[] { "model", "systemPrompt", "agentPath", "maxTurns" },
clearFields: new[] { "model", "systemPrompt", "agentPath", "maxTurns", "verifyCommand" },
cancellationToken: CancellationToken.None);
Assert.True(result.Ok);
@@ -271,7 +349,6 @@ public sealed class ConfigMcpToolsTests : IDisposable
var cfg = await _lists.GetConfigAsync(listId);
Assert.NotNull(cfg);
Assert.Null(cfg!.Model);
Assert.Equal("dotnet build", cfg.VerifyCommand);
Assert.True(cfg.SerializeOnFileOverlap);
}