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:
73
src/ClaudeDo.Worker/Planning/PlanningAggregator.cs
Normal file
73
src/ClaudeDo.Worker/Planning/PlanningAggregator.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user