From f4dd67d5954a7c56df2f7d498bb287a150ad447d Mon Sep 17 00:00:00 2001 From: mika kuns Date: Fri, 24 Jul 2026 11:26:19 +0200 Subject: [PATCH] fix(ui): live-refresh child rows on parent planning transitions Finalize/Discard broadcast only the parent's TaskUpdated; the delta path updated the parent row but never recomputed child-derived flags or dropped discarded children, so subtasks stayed "Draft" after finalize and deleted rows lingered after discard until a manual reload. Reconcile the whole list when the updated task is (or owns) a planning subtree. --- .../ViewModels/Islands/TasksIslandViewModel.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/ClaudeDo.Ui/ViewModels/Islands/TasksIslandViewModel.cs b/src/ClaudeDo.Ui/ViewModels/Islands/TasksIslandViewModel.cs index 55cc2ffd..0d8a6b3a 100644 --- a/src/ClaudeDo.Ui/ViewModels/Islands/TasksIslandViewModel.cs +++ b/src/ClaudeDo.Ui/ViewModels/Islands/TasksIslandViewModel.cs @@ -151,6 +151,18 @@ public sealed partial class TasksIslandViewModel : ViewModelBase, IDisposable .Include(t => t.Worktree) .FirstOrDefaultAsync(t => t.Id == taskId); + // A parent transition (finalize/discard) broadcasts only the parent's id, but it + // changes its children's derived state — finalize flips them Draft→Planned, discard + // deletes them. The delta path below only touches the parent row and never recomputes + // the child-derived flags (ParentFinalized, HasPlanningChildren) nor drops deleted + // children, so reconcile the whole list when the updated task is (or owns) a subtree. + if (entity is not null && + (entity.PlanningPhase != PlanningPhase.None || Items.Any(r => r.ParentTaskId == entity.Id))) + { + LoadForList(list); + return; + } + var existing = Items.FirstOrDefault(r => r.Id == taskId); if (entity is null)