Files
ClaudeDo/docs/superpowers/specs/2026-04-24-planning-ux-and-sequential-subtasks-design.md
mika kuns 615c1da665 docs: add planning UX spec/plan and prompts/mailbox proposals
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 09:37:32 +02:00

6.0 KiB

Planning UX Polish + Sequential Subtask Queue

Status: design Date: 2026-04-24 Scope: three small UX changes + one feature — sequential execution of planning subtasks triggered from the context menu.

Goals

  1. Collapse the children of a finished planning-parent row in the task list by default.
  2. Allow the user to collapse the Description section in the Details pane.
  3. Halve the width of the GridSplitters between islands.
  4. Let the user queue all subtasks of a planning parent so they run one after another, with a new Waiting status for pending siblings.

1. Auto-collapse done planning parents

Rule for "done": a planning parent is "done" when every one of its children has Status == Done.

Changes:

  • TaskRowViewModel: add UI-only [ObservableProperty] bool _areChildrenExpanded. Default computed from status — false when the row is a done planning parent, else true. Not persisted.
  • Add [RelayCommand] void ToggleChildrenExpanded().
  • TasksIslandView.axaml (or TaskRowView.axaml): chevron button on the planning-parent row, visible only when IsPlanningParent && HasPlanningChildren. Bound to the toggle command.
  • TasksIslandViewModel.Regroup(): before adding child rows to OpenItems/CompletedItems, check each child's parent row in Items. If the parent's AreChildrenExpanded == false, skip the child.
  • When a planning parent flips from "not done" → "done" in OnWorkerTaskUpdated, call Regroup() so the collapse takes effect.

No DB changes.

2. Collapsible description in Details pane

Changes:

  • DetailsIslandViewModel: [ObservableProperty] bool _isDescriptionExpanded = true + [RelayCommand] void ToggleDescriptionExpanded().
  • DetailsIslandView.axaml: wrap the existing description TextBox in a StackPanel; add a thin header row with the label "Description" and a chevron button. Body's IsVisible binds to the flag.
  • State is per ViewModel instance — reset to true whenever a different task is loaded.

No persistence.

3. Narrower GridSplitters

MainWindow.axaml lines 158 and 170: Width="5"Width="3" on both GridSplitter elements.

That's the whole change.

4. Sequential subtask queue

Data

  • ClaudeDo.Data/Models/TaskStatus.cs: add a new enum value Waiting (lowercase serialized form waiting, matching existing convention).
  • Verify status is stored as string (it should be based on existing patterns). If stored as int, ensure new value gets a stable numeric slot at the end of the enum to avoid breaking existing rows. No EF migration beyond what the enum emits automatically.

Worker

  • New SignalR hub method: QueuePlanningSubtasksAsync(string parentTaskId) : Task.
    • Loads all children of the parent, ordered by SortOrder.
    • Validates: parent must be a planning parent, children must currently all be in Manual or Planned (reject if any child is already Queued/Running/Done/Failed, surface a friendly error).
    • First child → Queued. All other children → Waiting. Save.
    • Emit TaskUpdated for each affected task.
  • Chain progression — hook into the existing finish/complete path that already fires TaskFinished:
    • On a child task finishing with status Done and its parent has waiting siblings: find the next sibling by (ParentTaskId == parent.Id && Status == Waiting) ordered by SortOrder, flip to Queued, emit TaskUpdated, and let the existing queue pickup loop pick it up.
    • On Failed: do nothing. Remaining Waiting siblings stay waiting. (A toast for failed tasks will be added in a later spec.)

This logic lives in a new PlanningChainCoordinator service (or similar) in ClaudeDo.Worker/Planning/, registered as a singleton and wired into whatever already emits task-finished events.

UI

  • TaskRowView — add context menu entry "Queue subtasks sequentially":
    • IsVisible bound to IsPlanningParent && HasPlanningChildren.
    • IsEnabled when all children are in Manual / Planned state (new property on TaskRowViewModel: CanQueueSubtasksSequentially).
    • Calls WorkerClient.QueuePlanningSubtasksAsync(Id).
  • TaskRowViewModel:
    • Add IsWaiting => Status == TaskStatus.Waiting and extend StatusChipClass switch to return a new class "waiting".
    • Add CanQueueSubtasksSequentially (computed; requires access to children).
  • StatusColorConverter — add a muted color for Waiting (proposed: the existing TextMuteBrush or a faint cyan).
  • Task list — planning parent continues to appear in virtual:queued because it has a Queued child (existing logic). Extend the virtual:queued match predicate in TasksIslandViewModel.TaskMatchesList so a task matches when Status == Queued || Status == Waiting. This ensures all sibling subtasks (the queued one + the waiting ones) render under the parent in that list.

Client

  • IWorkerClient / WorkerClient: add QueuePlanningSubtasksAsync(string parentTaskId) that calls the hub method.

Out of scope

  • Toast notifications on subtask failure (separate follow-up spec).
  • Retrying a stopped chain from a failed task (user does it manually via existing actions).
  • Persisting the collapse state of planning parents or the Description across sessions.
  • Drag-to-reorder of waiting subtasks (execution order = SortOrder at the moment the chain starts).

Validation plan

Manual:

  • Plan a task with 3 subtasks. Context-menu → Queue subtasks sequentially. Confirm first = Queued, others = Waiting. Watch the first run to Done, confirm the second flips Queued → Running automatically.
  • Force-fail subtask 2 (cancel or make it fail). Confirm subtask 3 stays Waiting; no further dispatch.
  • Once all three are Done, confirm the planning parent auto-collapses in the list.
  • Toggle the Description chevron in the Details pane on an arbitrary task.
  • Eyeball the narrower GridSplitter — still resizable, still hittable.

Automated (minimal — only where cheap):

  • Worker-level unit test for PlanningChainCoordinator: happy-path chain advance on Done; no advance on Failed; correct ordering by SortOrder.