From 99c6a71e4c807a09eef1e8bca2421c399d650fb8 Mon Sep 17 00:00:00 2001 From: mika kuns Date: Thu, 23 Apr 2026 23:03:42 +0200 Subject: [PATCH] feat(worker): MCP tools update_planning_task and finalize --- .../Repositories/TaskRepository.cs | 17 ++++++++++++ .../Planning/PlanningMcpService.cs | 15 +++++++++++ .../Planning/PlanningMcpServiceTests.cs | 27 +++++++++++++++++++ 3 files changed, 59 insertions(+) diff --git a/src/ClaudeDo.Data/Repositories/TaskRepository.cs b/src/ClaudeDo.Data/Repositories/TaskRepository.cs index d746589..232f00d 100644 --- a/src/ClaudeDo.Data/Repositories/TaskRepository.cs +++ b/src/ClaudeDo.Data/Repositories/TaskRepository.cs @@ -267,6 +267,23 @@ public sealed class TaskRepository return child; } + public async Task UpdatePlanningTaskAsync( + string taskId, + string? title, + string? description, + CancellationToken ct = default) + { + var entity = await _context.Tasks.AsNoTracking().FirstOrDefaultAsync(t => t.Id == taskId, ct) + ?? throw new InvalidOperationException("Planning task not found."); + if (title is not null) entity.Title = title; + if (description is not null) entity.Description = description; + await _context.Tasks + .Where(t => t.Id == taskId) + .ExecuteUpdateAsync(s => s + .SetProperty(t => t.Title, entity.Title) + .SetProperty(t => t.Description, entity.Description), ct); + } + public async Task SetPlanningStartedAsync( string taskId, string sessionToken, diff --git a/src/ClaudeDo.Worker/Planning/PlanningMcpService.cs b/src/ClaudeDo.Worker/Planning/PlanningMcpService.cs index 2bb1a34..f22feb1 100644 --- a/src/ClaudeDo.Worker/Planning/PlanningMcpService.cs +++ b/src/ClaudeDo.Worker/Planning/PlanningMcpService.cs @@ -82,4 +82,19 @@ public sealed class PlanningMcpService await _tasks.DeleteAsync(taskId, cancellationToken); } + + public async Task UpdatePlanningTask( + PlanningMcpContext ctx, + string? title, + string? description, + CancellationToken cancellationToken) + { + await _tasks.UpdatePlanningTaskAsync(ctx.ParentTaskId, title, description, cancellationToken); + } + + public Task Finalize( + PlanningMcpContext ctx, + bool queueAgentTasks, + CancellationToken cancellationToken) + => _tasks.FinalizePlanningAsync(ctx.ParentTaskId, queueAgentTasks, cancellationToken); } diff --git a/tests/ClaudeDo.Worker.Tests/Planning/PlanningMcpServiceTests.cs b/tests/ClaudeDo.Worker.Tests/Planning/PlanningMcpServiceTests.cs index fdc0505..6a9fe5e 100644 --- a/tests/ClaudeDo.Worker.Tests/Planning/PlanningMcpServiceTests.cs +++ b/tests/ClaudeDo.Worker.Tests/Planning/PlanningMcpServiceTests.cs @@ -104,4 +104,31 @@ public sealed class PlanningMcpServiceTests : IDisposable Assert.Null(await _tasks.GetByIdAsync(c.Id)); } + + [Fact] + public async Task UpdatePlanningTask_SetsTitleAndDescription() + { + var parent = await SeedPlanningParentAsync(); + + await _sut.UpdatePlanningTask(Ctx(parent.Id), "new title", "new desc", CancellationToken.None); + + var loaded = await _tasks.GetByIdAsync(parent.Id); + Assert.Equal("new title", loaded!.Title); + Assert.Equal("new desc", loaded.Description); + } + + [Fact] + public async Task Finalize_PromotesDraftsAndInvalidatesToken() + { + var parent = await SeedPlanningParentAsync(); + await _tasks.CreateChildAsync(parent.Id, "c1", null, null, null); + await _tasks.CreateChildAsync(parent.Id, "c2", null, null, null); + + var count = await _sut.Finalize(Ctx(parent.Id), true, CancellationToken.None); + + Assert.Equal(2, count); + var loaded = await _tasks.GetByIdAsync(parent.Id); + Assert.Equal(TaskStatus.Planned, loaded!.Status); + Assert.Null(loaded.PlanningSessionToken); + } }