feat(ui): richer diff viewer + surface child roadblocks on parents
All checks were successful
Changelog / changelog (push) Successful in 1s
Release / release (push) Successful in 38s

- UnifiedDiffParser detects added/deleted/renamed/binary files; diff
  modal shows a file list, binary/empty placeholders, and can diff a
  merged task by commit range after its worktree is gone
- DetailsIslandViewModel flags children needing attention (failed,
  cancelled, awaiting review, or with roadblocks) on the parent
- GitService gains worktree head-commit/range support; planning chain,
  merge orchestration, and session manager tweaks with updated tests
- refresh app/installer/worker icons

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
mika kuns
2026-06-09 16:40:59 +02:00
parent c300f8c313
commit f21c65be18
28 changed files with 509 additions and 119 deletions

View File

@@ -124,6 +124,20 @@ public sealed class GitService
return await GetDiffAsync(worktreePath, ct);
}
/// <summary>
/// Diff between two commits, run in any repo that can reach them. Used to view a
/// task's changes after its worktree has been merged away (the commits survive on
/// the target branch even though the worktree directory and branch ref are gone).
/// </summary>
public async Task<string> GetCommitRangeDiffAsync(string repoDir, string baseCommit, string headCommit, CancellationToken ct = default)
{
var (exitCode, stdout, stderr) = await RunGitAsync(repoDir,
["diff", $"{baseCommit}..{headCommit}"], ct);
if (exitCode != 0)
throw new InvalidOperationException($"git diff {baseCommit}..{headCommit} failed (exit {exitCode}): {stderr}");
return stdout;
}
public async Task<string> DiffStatAsync(string worktreePath, string baseCommit, string headCommit, CancellationToken ct = default)
{
var (exitCode, stdout, stderr) = await RunGitAsync(worktreePath,