feat(worker): report worktree-creation phase on OperationProgress

Fills the silent gap between Queued and the first agent output: WorktreeManager
now broadcasts a "creating_worktree" phase (before the initial git worktree add
and again for the self-heal retry section) through the existing OperationProgress
channel, and the task row shows it via the pre-existing but unused
ops.worker.creatingWorktree locale key until the next entity refresh clears it.

Confirmed the 2026-08-07 triage finding still holds: TaskRunner already
broadcasts WorktreeUpdated right after WorktreeManager.CreateAsync
(TaskRunner.cs:342-346, :501) -- no second broadcast added there.
This commit is contained in:
mika kuns
2026-08-21 13:35:26 +02:00
parent dcda067b48
commit eba0d842b5
6 changed files with 156 additions and 1 deletions
@@ -41,6 +41,7 @@ sealed class FakeWorkerClient : IWorkerClient
public void RaiseTaskUpdated(string taskId) => TaskUpdatedEvent?.Invoke(taskId);
public void RaiseWorktreeUpdated(string taskId) => WorktreeUpdatedEvent?.Invoke(taskId);
public void RaiseTaskMessage(string taskId, string line) => TaskMessageEvent?.Invoke(taskId, line);
public void RaiseOperationProgress(string opKey, string phase, int current, int total) => OperationProgressEvent?.Invoke(opKey, phase, current, total);
public Task RunNowAsync(string taskId) => Task.CompletedTask;
public Task ContinueTaskAsync(string taskId, string followUpPrompt) => Task.CompletedTask;
@@ -277,6 +278,32 @@ public class TasksIslandViewModelPlanningTests
Assert.Equal(("t1", false), raised);
}
[Fact]
public void OperationProgress_CreatingWorktreePhase_SetsOnlyMatchingRow()
{
var row1 = MakeRow("t1", TaskStatus.Running);
var row2 = MakeRow("t2", TaskStatus.Running);
var (_, worker) = VmFactory.Create([row1, row2]);
worker.RaiseOperationProgress("t1", "creating_worktree", 0, 0);
Assert.True(row1.HasCreationPhase);
Assert.False(row2.HasCreationPhase);
}
[Fact]
public void OperationProgress_UnrelatedPhase_DoesNotSetCreationPhase()
{
// Same channel carries TaskMergeService's merge phases (opKey is also the task id) --
// the row must only react to its own creation-phase token, not any phase for its id.
var row = MakeRow("t1", TaskStatus.Running);
var (_, worker) = VmFactory.Create([row]);
worker.RaiseOperationProgress("t1", "merging", 0, 0);
Assert.False(row.HasCreationPhase);
}
[Fact]
public void ToggleExpand_TogglesParentExpansion()
{