feat(worker): add PlanningAggregator.GetAggregatedDiffAsync

Returns per-subtask diff entries (title, branch, base/head commit, DiffStat, unified diff) for all children of a Planning task in SortOrder order.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
mika kuns
2026-04-24 16:08:56 +02:00
parent 6bdfa73150
commit a1727b647c
2 changed files with 192 additions and 0 deletions

View File

@@ -0,0 +1,73 @@
using ClaudeDo.Data;
using ClaudeDo.Data.Git;
using ClaudeDo.Data.Models;
using Microsoft.EntityFrameworkCore;
namespace ClaudeDo.Worker.Planning;
public sealed record SubtaskDiff(
string SubtaskId,
string Title,
string BranchName,
string BaseCommit,
string HeadCommit,
string? DiffStat,
string UnifiedDiff);
public sealed record CombinedDiffSuccess(string IntegrationBranch, string UnifiedDiff);
public sealed record CombinedDiffFailure(string FirstConflictSubtaskId, IReadOnlyList<string> ConflictedFiles);
public abstract record CombinedDiffResult
{
public sealed record Ok(CombinedDiffSuccess Value) : CombinedDiffResult;
public sealed record Failed(CombinedDiffFailure Value) : CombinedDiffResult;
}
public sealed class PlanningAggregator
{
private readonly IDbContextFactory<ClaudeDoDbContext> _dbFactory;
private readonly GitService _git;
private readonly ILogger<PlanningAggregator> _logger;
public PlanningAggregator(
IDbContextFactory<ClaudeDoDbContext> dbFactory,
GitService git,
ILogger<PlanningAggregator> logger)
{
_dbFactory = dbFactory;
_git = git;
_logger = logger;
}
public async Task<IReadOnlyList<SubtaskDiff>> GetAggregatedDiffAsync(
string planningTaskId, CancellationToken ct)
{
using var ctx = _dbFactory.CreateDbContext();
var children = await ctx.Tasks
.Include(t => t.Worktree)
.Where(t => t.ParentTaskId == planningTaskId)
.OrderBy(t => t.SortOrder)
.ToListAsync(ct);
var result = new List<SubtaskDiff>();
foreach (var child in children)
{
if (child.Worktree is null) continue;
var wt = child.Worktree;
var head = wt.HeadCommit ?? await _git.RevParseHeadAsync(wt.Path, ct);
string unified;
try
{
unified = await _git.GetBranchDiffAsync(wt.Path, wt.BaseCommit, ct);
}
catch (Exception ex)
{
_logger.LogWarning(ex, "diff failed for subtask {Id}", child.Id);
unified = "";
}
result.Add(new SubtaskDiff(
child.Id, child.Title, wt.BranchName, wt.BaseCommit, head, wt.DiffStat, unified));
}
return result;
}
}