docs: add planning UX spec/plan and prompts/mailbox proposals
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
# 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`.
|
||||
Reference in New Issue
Block a user