feat(mission-control): give the list handler its own review task
"Let Claude handle it" now creates one ClaudeDo task per run to host the ConPTY session (Idle/IsManual, never queued) instead of an untracked ad-hoc tile, so the run has a real title, diff, and review outcome. Since the handler merges its own changes straight into the list's working dir, the task never gets a WorktreeEntity; its review range lives as new HandlerBaseCommit/HandlerHeadCommit columns on TaskEntity instead, reusing the existing commit-range diff machinery and keeping it out of the worktrees overview entirely.
This commit is contained in:
@@ -523,23 +523,47 @@ public class MissionControlViewModelTests : IDisposable
|
||||
=> throw new InvalidOperationException("spec failed");
|
||||
}
|
||||
|
||||
private sealed class ThrowingCreateMergeHelperTaskWorker : StubWorkerClient
|
||||
{
|
||||
public override Task<string> CreateMergeHelperTaskAsync(
|
||||
IReadOnlyList<string> taskIds, string listId, string title, string descriptionHeader, CancellationToken ct = default)
|
||||
=> throw new InvalidOperationException("create failed");
|
||||
}
|
||||
|
||||
private sealed class FixedTaskIdMergeHelperWorker : StubWorkerClient
|
||||
{
|
||||
public string TaskId { get; } = "fixed-handler-task";
|
||||
public int CreateCallCount { get; private set; }
|
||||
public override Task<string> CreateMergeHelperTaskAsync(
|
||||
IReadOnlyList<string> taskIds, string listId, string title, string descriptionHeader, CancellationToken ct = default)
|
||||
{
|
||||
CreateCallCount++;
|
||||
return Task.FromResult(TaskId);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task OpenMergeHelperConPtySessionAsync_AddsAdHocPane()
|
||||
public async Task OpenMergeHelperConPtySessionAsync_AddsTaskBasedPane()
|
||||
{
|
||||
var worker = new FakeWorker();
|
||||
using var vm = BuildVm(worker);
|
||||
|
||||
await vm.OpenMergeHelperConPtySessionAsync("L1", new[] { "t1", "t2" });
|
||||
|
||||
Assert.Single(vm.ConPtySessions);
|
||||
Assert.Null(vm.ConPtySessions[0].TaskId);
|
||||
var pane = Assert.Single(vm.ConPtySessions);
|
||||
Assert.NotNull(pane.TaskId);
|
||||
Assert.True(pane.IsTaskBased);
|
||||
Assert.Single(vm.Panes);
|
||||
Assert.Same(vm.ConPtySessions[0], vm.Panes[0]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task OpenMergeHelperConPtySessionAsync_TwoRuns_NeverDeduped()
|
||||
public async Task OpenMergeHelperConPtySessionAsync_TwoRuns_EachGetsItsOwnTaskAndPane()
|
||||
{
|
||||
// Each run creates a brand-new handler task (the stub returns a fresh Guid per call),
|
||||
// so two runs still yield two distinct, non-deduped panes -- but for a different reason
|
||||
// than the old ad-hoc pane (never deduped by construction): dedup is now by TaskId, and
|
||||
// there simply is no shared TaskId across separate runs.
|
||||
var worker = new FakeWorker();
|
||||
using var vm = BuildVm(worker);
|
||||
|
||||
@@ -547,6 +571,22 @@ public class MissionControlViewModelTests : IDisposable
|
||||
await vm.OpenMergeHelperConPtySessionAsync("L1", new[] { "t1" });
|
||||
|
||||
Assert.Equal(2, vm.ConPtySessions.Count);
|
||||
Assert.NotEqual(vm.ConPtySessions[0].TaskId, vm.ConPtySessions[1].TaskId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task OpenMergeHelperConPtySessionAsync_SameHandlerTaskId_FocusesExistingPane_NoDuplicate()
|
||||
{
|
||||
var worker = new FixedTaskIdMergeHelperWorker();
|
||||
using var vm = BuildVm(worker);
|
||||
|
||||
await vm.OpenMergeHelperConPtySessionAsync("L1", new[] { "t1" });
|
||||
var firstPane = Assert.Single(vm.ConPtySessions);
|
||||
|
||||
await vm.OpenMergeHelperConPtySessionAsync("L1", new[] { "t1" });
|
||||
|
||||
Assert.Single(vm.ConPtySessions);
|
||||
Assert.Same(firstPane, vm.FocusedPane);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -577,6 +617,21 @@ public class MissionControlViewModelTests : IDisposable
|
||||
Assert.NotNull(error);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task OpenMergeHelperConPtySessionAsync_TaskCreationThrows_RaisesErrorReported_NoPaneCreated()
|
||||
{
|
||||
var worker = new ThrowingCreateMergeHelperTaskWorker();
|
||||
using var vm = BuildVm(worker);
|
||||
string? error = null;
|
||||
vm.ErrorReported += msg => error = msg;
|
||||
|
||||
await vm.OpenMergeHelperConPtySessionAsync("L1", new[] { "t1" });
|
||||
|
||||
Assert.Empty(vm.ConPtySessions);
|
||||
Assert.Empty(vm.Panes);
|
||||
Assert.NotNull(error);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToggleLayoutCommand_FlipsIsFocusMode()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user