diff --git a/src/ClaudeDo.Ui/ViewModels/Islands/TaskRowViewModel.cs b/src/ClaudeDo.Ui/ViewModels/Islands/TaskRowViewModel.cs
index b5c16431..57b52327 100644
--- a/src/ClaudeDo.Ui/ViewModels/Islands/TaskRowViewModel.cs
+++ b/src/ClaudeDo.Ui/ViewModels/Islands/TaskRowViewModel.cs
@@ -58,6 +58,12 @@ public sealed partial class TaskRowViewModel : ViewModelBase
// Set by the custom drag while this row is being dragged — drives the "grabbed" row style.
[ObservableProperty] private bool _isDragging;
+ // Transient: set from HubBroadcaster's OperationProgress while the worker is still creating
+ // this task's worktree (the silent gap between Queued and the first agent output). Cleared
+ // by the next entity refresh — UpdateFromEntity always reflects a settled state, so there's
+ // nothing left to show past that point.
+ [ObservableProperty] private string? _creationPhase;
+
// True while a drag is hovering this row (i.e. it would show a drop-hint gap). Used to
// suppress the ordinary hover highlight/transitions so they don't fight the hint.
public bool IsDropTarget => DropHintAbove || DropHintBelow;
@@ -145,6 +151,16 @@ public sealed partial class TaskRowViewModel : ViewModelBase
? "1 roadblock reported during the run — see details"
: $"{RoadblockCount} roadblocks reported during the run — see details";
+ /// Mirrors WorktreeManager.PhaseCreatingWorktree — a hub payload token, not a display string.
+ private const string PhaseCreatingWorktree = "creating_worktree";
+
+ public bool HasCreationPhase => CreationPhase is not null;
+ public string? CreationPhaseLabel => CreationPhase switch
+ {
+ PhaseCreatingWorktree => Loc.T("ops.worker.creatingWorktree"),
+ _ => null,
+ };
+
// True for every Failed task, even one that predates this field — FailureReasonLabel then
// falls back to "unknown" instead of leaving the tooltip blank.
public bool HasFailureReason => Status == TaskStatus.Failed;
@@ -345,6 +361,11 @@ public sealed partial class TaskRowViewModel : ViewModelBase
partial void OnRoadblockCountChanged(int value) { OnPropertyChanged(nameof(HasRoadblock)); OnPropertyChanged(nameof(RoadblockTooltip)); }
partial void OnDropHintAboveChanged(bool value) => OnPropertyChanged(nameof(IsDropTarget));
partial void OnDropHintBelowChanged(bool value) => OnPropertyChanged(nameof(IsDropTarget));
+ partial void OnCreationPhaseChanged(string? value)
+ {
+ OnPropertyChanged(nameof(HasCreationPhase));
+ OnPropertyChanged(nameof(CreationPhaseLabel));
+ }
public void RefreshLocalized()
{
@@ -363,6 +384,9 @@ public sealed partial class TaskRowViewModel : ViewModelBase
public void UpdateFromEntity(TaskEntity t)
{
+ // Any entity-backed refresh reflects a settled state, so the transient creation-phase
+ // banner (set from the OperationProgress broadcast) has nothing left to announce.
+ CreationPhase = null;
var (add, del) = ParseDiffStat(t.Worktree?.DiffStat);
Number = t.Number;
Title = t.Title;
diff --git a/src/ClaudeDo.Ui/ViewModels/Islands/TasksIslandViewModel.cs b/src/ClaudeDo.Ui/ViewModels/Islands/TasksIslandViewModel.cs
index 0b5fb0a2..17d1920f 100644
--- a/src/ClaudeDo.Ui/ViewModels/Islands/TasksIslandViewModel.cs
+++ b/src/ClaudeDo.Ui/ViewModels/Islands/TasksIslandViewModel.cs
@@ -188,6 +188,7 @@ public sealed partial class TasksIslandViewModel : ViewModelBase, IDisposable
_worker.ConnectionRestoredEvent += () => LoadForList(_currentList);
_worker.RefineStartedEvent += OnRefineStarted;
_worker.RefineFinishedEvent += OnRefineFinished;
+ _worker.OperationProgressEvent += OnWorkerOperationProgress;
}
_langChangedHandler = (_, _) => RefreshLocalizedText();
Loc.LanguageChanged += _langChangedHandler;
@@ -1563,6 +1564,18 @@ public sealed partial class TasksIslandViewModel : ViewModelBase, IDisposable
if (row is not null) row.IsRefining = false;
}
+ // OperationProgress is a generic channel shared with merge phases (TaskMergeService), whose
+ // opKey is also the task id — filter on the phase token so a merge in flight can't clobber
+ // this row's creation-phase banner.
+ private const string CreationPhaseCreatingWorktree = "creating_worktree";
+
+ private void OnWorkerOperationProgress(string opKey, string phase, int current, int total)
+ {
+ if (phase != CreationPhaseCreatingWorktree) return;
+ var row = Items.FirstOrDefault(r => r.Id == opKey);
+ if (row is not null) row.CreationPhase = phase;
+ }
+
partial void OnSelectedTaskChanged(TaskRowViewModel? value)
{
foreach (var i in Items) i.IsSelected = ReferenceEquals(i, value);
diff --git a/src/ClaudeDo.Ui/Views/Islands/TaskRowView.axaml b/src/ClaudeDo.Ui/Views/Islands/TaskRowView.axaml
index 07af2efa..928b059e 100644
--- a/src/ClaudeDo.Ui/Views/Islands/TaskRowView.axaml
+++ b/src/ClaudeDo.Ui/Views/Islands/TaskRowView.axaml
@@ -143,6 +143,12 @@
+
+
+
+
+