Merge branch 'claudedo/c1d2a92d8d8c4705ac93d5f0b2cacaa0'

This commit is contained in:
mika kuns
2026-08-06 11:38:32 +02:00
5 changed files with 198 additions and 10 deletions
@@ -142,6 +142,24 @@ public sealed class BatchMcpToolsTests : IDisposable
Assert.Equal(2, inList.Count);
}
[Fact]
public async Task BatchAddTasks_SimilarTitleInSameList_ReportsPossibleDuplicate()
{
var listId = await SeedListAsync();
await SeedTaskAsync(listId, "MaxTurnsCeiling ohne Bedienoberflaeche im Settings-Modal", TaskStatus.Idle);
var sut = BuildSut();
var results = await sut.BatchAddTasks(listId, new[]
{
new BatchAddTaskInput("Settings: MaxTurnsCeiling editierbar machen"),
}, cancellationToken: CancellationToken.None);
var result = Assert.Single(results);
Assert.True(result.Ok);
Assert.NotNull(result.PossibleDuplicates);
Assert.Single(result.PossibleDuplicates!);
}
[Fact]
public async Task BatchGetTasks_MissingId_IsFoundFalseNotError()
{
@@ -1556,7 +1556,7 @@ public sealed class ExternalMcpServiceTests : IDisposable
var dto = await sut.AddTask(listId, "t", cancellationToken: CancellationToken.None);
var loaded = await _tasks.GetByIdAsync(dto.Id);
var loaded = await _tasks.GetByIdAsync(dto.Task.Id);
Assert.Null(loaded!.Model);
}
@@ -1568,7 +1568,7 @@ public sealed class ExternalMcpServiceTests : IDisposable
var dto = await sut.AddTask(listId, "t", model: "HAIKU", cancellationToken: CancellationToken.None);
var loaded = await _tasks.GetByIdAsync(dto.Id);
var loaded = await _tasks.GetByIdAsync(dto.Task.Id);
Assert.Equal("haiku", loaded!.Model);
}
@@ -1582,6 +1582,80 @@ public sealed class ExternalMcpServiceTests : IDisposable
() => sut.AddTask(listId, "t", model: "gpt4", cancellationToken: CancellationToken.None));
}
// ── AddTask possible-duplicate check ────────────────────────────────────────
[Fact]
public async Task AddTask_SimilarOpenTitleInSameList_IsReportedAsPossibleDuplicate()
{
// The exact pair that motivated this check (bf4cd901 vs f3718cd8, see task write-up).
var listId = await SeedListAsync();
var existing = await SeedTaskAsync(
listId, "MaxTurnsCeiling ohne Bedienoberflaeche im Settings-Modal", TaskStatus.WaitingForReview);
var sut = NewService();
var result = await sut.AddTask(
listId, "Settings: MaxTurnsCeiling editierbar machen", cancellationToken: CancellationToken.None);
var dup = Assert.Single(result.PossibleDuplicates);
Assert.Equal(existing.Id, dup.TaskId);
Assert.Equal(existing.Title, dup.Title);
Assert.Equal("WaitingForReview", dup.Status);
}
[Fact]
public async Task AddTask_StillCreatesTheTask_EvenWhenAPossibleDuplicateIsFound()
{
var listId = await SeedListAsync();
await SeedTaskAsync(listId, "MaxTurnsCeiling ohne Bedienoberflaeche im Settings-Modal", TaskStatus.Idle);
var sut = NewService();
var result = await sut.AddTask(
listId, "Settings: MaxTurnsCeiling editierbar machen", cancellationToken: CancellationToken.None);
Assert.NotEmpty(result.PossibleDuplicates);
Assert.NotNull(await _tasks.GetByIdAsync(result.Task.Id));
}
[Fact]
public async Task AddTask_SimilarTitle_ButExistingTaskIsTerminal_IsNotReported()
{
var listId = await SeedListAsync();
await SeedTaskAsync(listId, "MaxTurnsCeiling ohne Bedienoberflaeche im Settings-Modal", TaskStatus.Done);
var sut = NewService();
var result = await sut.AddTask(
listId, "Settings: MaxTurnsCeiling editierbar machen", cancellationToken: CancellationToken.None);
Assert.Empty(result.PossibleDuplicates);
}
[Fact]
public async Task AddTask_ClearlyDifferentTitle_IsNotReported()
{
var listId = await SeedListAsync();
await SeedTaskAsync(listId, "Refactor GitService worktree cleanup", TaskStatus.Idle);
var sut = NewService();
var result = await sut.AddTask(
listId, "Add dark mode toggle to the settings page", cancellationToken: CancellationToken.None);
Assert.Empty(result.PossibleDuplicates);
}
[Fact]
public async Task AddTask_MoreThanThreeMatches_CapsPossibleDuplicatesAtThree()
{
var listId = await SeedListAsync();
for (var i = 0; i < 5; i++)
await SeedTaskAsync(listId, $"Fix flaky queue picker test number {i}", TaskStatus.Idle);
var sut = NewService();
var result = await sut.AddTask(
listId, "Fix flaky queue picker test number extra", cancellationToken: CancellationToken.None);
Assert.Equal(3, result.PossibleDuplicates.Count);
}
// ── ContinueTask validation ───────────────────────────────────────────────
[Fact]