# 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`.
