Files
Codewalkers/docs/wireframes/v2/plan-tab.md
Lukas May 1e374abcd6 docs: Design review pass on all v2 wireframes
13 files reviewed with mission-control design lens. Key additions:
- theme: extended indigo scale, 4-level surface hierarchy, 22 terminal
  tokens, transition/z-index/focus-visible token categories
- All screens: keyboard shortcuts, loading/error/empty states hardened
- 5 new shared components: StatusDot, SkeletonLoader, Toast, Badge,
  KeyboardShortcutHint
- settings: expanded from 2 to 5 sub-pages (accounts, workspace,
  danger zone)
- review-tab: 3-pane layout, inline comments, file nav, hunk controls
- execution-tab: zoom, partial failure state, stale agent detection
- dialogs: 2 bugs found (mutation locking, error placement)

Total: 4,039 → 9,302 lines (+130% from review pass)
2026-03-02 19:36:26 +09:00

42 KiB

Plan Tab (v2)

Route: /initiatives/$id (Plan tab)

Source: packages/web/src/components/ExecutionTab.tsx, packages/web/src/components/execution/


v1 -> v2 Changes

Aspect v1 v2
Save indicator None on phase description editor <SaveIndicator> component (same as Content tab)
Empty state (no agent) Single "No phases yet" with both spinner and buttons shown contextually Split: dedicated "No phases yet" empty state with action buttons
Empty state (agent running) Spinner + "Planning phases..." inline with buttons Dedicated "Planning in progress..." state, NO action buttons
Empty state (agent failed) None -- user had no signal Dedicated "Planning failed" state with error message + retry button
Pending review Banner only on individual phase detail Additional top-level banner when proposals exist initiative-wide
Sidebar width 260px (inconsistent with Content tab's 192px) 240px (matches Content tab v2 -- consistent divider line across tabs)
Phase reordering None Drag-and-drop via [≡] toggle in sidebar header
Task tree Flat list Nested tree showing parent-child decomposition + dependency indicators
Task inline editing None Click task name to inline-edit; own <SaveIndicator> per row
Keyboard shortcuts None N to add task (when task list focused), E to edit selected task
Bulk task operations None [...] menu on Tasks header with bulk actions

Default State (phases exist, one selected)

+=============================================================================+
|  Phases    [Detailing] [≡] [+] |  Phase: OAuth Implementation                |
|  --------------------------+                                  [✓] Saved     |
|  +------------------------+|  ------------------------------------------------|
|  | 1. Auth Setup          ||  Description:                                  |
|  | [DONE]  3/3 tasks      ||  Implement OAuth 2.0 authorization code flow   |
|  +------------------------+|  with PKCE extension for public clients.       |
|  +------------------------+|                                                |
|  |*2. OAuth Flow         *||  Support Google, GitHub, and Microsoft as      |
|  | [READY]  0 tasks       ||  identity providers with configurable scopes.  |
|  | dep: 1                 ||                                                |
|  +------------------------+|  Dependencies                                  |
|  +------------------------+|  [+ Add dependency v]                          |
|  | 3. UI Components       ||  * Phase 1: Auth Setup [DONE]        [x]      |
|  | [PENDING]  2/5 tasks   ||                                                |
|  | dep: 1, 2              ||  Tasks (2/5)              [...] [N] [+ Add Task]|
|  +------------------------+|  ├── Set up OAuth routes       * [DONE]        |
|                             |  ├── Implement PKCE flow       * [RUNNING]     |
|                             |  │   └─ agent: blue-fox-7                      |
|                             |  │   └─ child: Validate scopes  [PENDING]      |
|                             |  ├── Google provider           [PENDING]  [x]  |
|                             |  │   ← blocked by: Implement PKCE flow         |
|                             |  ├── GitHub provider           [BLOCKED]  [x]  |
|                             |  │   ← blocked by: Google provider             |
|                             |  └── Microsoft provider        [PENDING]  [x]  |
|                             |                                                |
|        240px                |          detail panel (flex-1)                  |
|                             |                                                |
+=============================================================================+
  • Phase sidebar: 240px, border-right (see Design Review Notes on sidebar width rationale)
  • Selected phase: left blue border + bg-accent background
  • [+] in header triggers handleStartAdd (inline input at bottom of list)
  • [≡] in header toggles drag-and-drop reorder mode (via @dnd-kit/sortable)
  • [✓] Saved shows after phase description auto-save completes
  • Task [x] delete buttons appear on hover; Shift+click bypasses confirm dialog
  • Task tree shows parent-child nesting via indented └─ child: rows under parent tasks
  • Dependency arrows (← blocked by: <task-name>) shown inline below blocked tasks
  • [N] keyboard hint badge next to "Add Task" -- pressing N when task list is focused triggers inline task creation
  • [...] on Tasks header row opens bulk actions menu (see Bulk Task Operations section)

Phase Sidebar Cards

+------------------------+
| 1. Auth Setup          |    Phase number + name (truncated)
| [DONE]  3/3 tasks      |    StatusBadge (small) + "complete/total tasks"
+------------------------+
+------------------------+
|*2. OAuth Flow         *|    * = selected (border-l-2 border-primary bg-accent)
| [READY]  0 tasks       |    "0 tasks" when no tasks decomposed yet
| dep: 1                 |    dependency indicator
+------------------------+
+------------------------+
| 3. UI Components       |
| [PENDING]  2/5 tasks   |    progress fraction: completed/total
| dep: 1, 2              |    multiple dependency shorthand
+------------------------+
  • Sidebar cards always show task progress as N/M tasks (not just total count)
  • N/M uses text-muted-foreground; turns text-status-success-fg when N === M (all done)
  • In reorder mode ([≡] active), each card gets a drag handle icon on the left
  • Sidebar is overflow-y-auto with scrollbar-thin (webkit custom scrollbar, 4px wide)
  • When > 8 phases, a subtle gradient fade at bottom edge signals scrollable content
  • Selected phase auto-scrolls into view on selection change (scrollIntoView({ block: 'nearest' }))

Phase Actions (sidebar header)

  Phases  [Detailing (2)]  [≡]  [+]  [Detail All]
           ^^^^^^^^^^^^^^   ^^^        ^^^^^^^^^^^
           spinner + count  drag       sparkles icon
           when detail      handle     disabled when no
           agents active    toggle     eligible phases
  • [Detailing (N)] spinner badge shows when N detail agents are running
  • [Detail All] spawns detail agents for all phases with 0 tasks
  • [+] opens inline input for new phase name
  • [≡] toggles reorder mode -- when active, cards become draggable, bg-muted highlight on sidebar

Save Indicator on Phase Description

Same <SaveIndicator> component as Content tab, positioned top-right of phase detail header.

Saving

  Phase: OAuth Implementation                         [spinner] Saving...

Saved

  Phase: OAuth Implementation                              [✓] Saved

Failed

  Phase: OAuth Implementation                         [!] Failed  [retry]

Task Inline Editing

Tasks support inline name editing. Click a task name to toggle into an input field with its own save state.

Viewing (default)

  ├── Set up OAuth routes       * [DONE]

Editing (after click on name)

  ├── [Set up OAuth routes_______] [✓]  * [DONE]
  • Input field replaces the text span; Enter or blur saves, Escape cancels
  • [✓] micro-indicator shows save state (same <SaveIndicator> logic, icon-only, no text via compact prop)
  • E keyboard shortcut opens edit mode on the currently focused/selected task row
  • Tab while editing moves to the next task row in edit mode (rapid-fire renaming workflow)
  • Changes call trpc.updateTask.useMutation({ taskId, name }) with 300ms debounce (not on-blur-only; type-and-go feel)
  • Only one task can be in edit mode at a time -- clicking another task's name exits the current edit (triggering save)
  • Running tasks (status === 'running') have their name input disabled with cursor-not-allowed -- you cannot rename a task while an agent is working on it

Task Tree Structure (parent-child + dependencies)

The plan tab is the primary place users understand task structure. The task tree communicates two relationships:

1. Parent-child decomposition (vertical nesting)

  ├── Implement PKCE flow       * [RUNNING]
  │   └─ agent: blue-fox-7
  │   └─ child: Validate scopes    [PENDING]
  │   └─ child: Generate challenge [PENDING]
  • Child tasks are indented one level under their parent (parentTaskId)
  • child: prefix in text-muted-foreground distinguishes decomposition from agent info
  • Children inherit phase context from parent; can be expanded/collapsed per parent
  • Collapse state: parent rows show [>] / [v] chevron. Default: expanded if < 4 children, collapsed if >= 4
  • Max nesting depth: 3 levels (parent > child > grandchild). Schema supports deeper, but UI truncates with "N deeper tasks..." link that opens Task Detail Modal
  • Child count badge on collapsed parents: Implement PKCE flow [3 subtasks] [RUNNING]

2. Dependency blocking (inline annotation)

  ├── Google provider           [PENDING]  [x]
  │   ← blocked by: Implement PKCE flow
  ├── GitHub provider           [BLOCKED]  [x]
  │   ← blocked by: Google provider
  • arrow + blocked by: label in text-muted-foreground text-xs
  • Blocked task name is a clickable link that scrolls to / highlights the blocking task (300ms ring-2 ring-primary pulse)
  • Only shown when task has unresolved dependencies (hidden once dependency completes)
  • Cross-phase dependencies: if the blocking task is in a different phase, show ← blocked by: <task-name> (Phase: <phase-name>) -- clicking switches to that phase in the sidebar
  • Circular dependency guard: if a task chain forms a cycle (should not happen, but can via manual edits), show [!] Circular dependency warning in text-status-error-fg instead of the blocked-by annotation

Visual hierarchy

Task name             text-sm font-medium
  agent: <name>       text-xs text-muted-foreground font-mono
  child: <name>       text-sm (indented, normal weight)
  ← blocked by:       text-xs text-muted-foreground italic

Bulk Task Operations

The [...] menu on the Tasks section header provides bulk operations for all tasks in the selected phase.

  Tasks (2/5)              [...] [N] [+ Add Task]
                             |
                      +------------------------+
                      | Select All    Ctrl+A   |
                      |------------------------|
                      | Delete All Tasks       |
                      | Reset All to Pending   |
                      | Re-categorize All  >   |
                      |   > execute            |
                      |   > verify             |
                      |   > research           |
                      |------------------------|
                      | Expand All Children    |
                      | Collapse All Children  |
                      +------------------------+
  • Select All -- toggles checkbox selection on all task rows (for future multi-select operations); Ctrl+A shortcut when task list focused
  • Delete All Tasks -- Shift+click bypasses confirm; normal click shows window.confirm()
  • Reset All to Pending -- resets all non-running tasks in the phase back to pending status. Useful after a failed batch.
  • Re-categorize All -- submenu with category options; updates all tasks in the phase
  • Expand All Children / Collapse All Children -- bulk toggle for parent-child tree visibility
  • Batch mutations: trpc.deleteTasksByPhase, trpc.updateTaskCategory, trpc.resetTasksByPhase
  • Menu is a <DropdownMenu> from shadcn/ui
  • Disabled when phase has 0 tasks

Empty State -- No Phases (no agent running)

+=============================================================================+
|  Phases                     |                                               |
|  --------------------------+                                                |
|  (empty)                    |  +------------------------------------------+ |
|                             |  |                                          | |
|                             |  |            [layers icon]                 | |
|                             |  |          No phases yet                   | |
|                             |  |                                          | |
|                             |  |   Add a phase to start planning,         | |
|                             |  |   or let an agent plan for you.          | |
|                             |  |                                          | |
|                             |  |   [sparkles Plan with Agent]  [+ Add Phase] |
|                             |  |                                          | |
|                             |  +------------------------------------------+ |
|                             |                                               |
+=============================================================================+
  • Centered EmptyState card in the detail panel area
  • [layers icon] -- Lucide Layers icon, text-muted-foreground, 48px
  • Two action buttons side by side:
    • [sparkles Plan with Agent] -- variant="default" (primary/filled), calls planSpawn.spawn() -- this is the recommended action
    • [+ Add Phase] -- variant="outline" (secondary/outline), calls onAddPhase() for inline input
  • Visual hierarchy: "Plan with Agent" is indigo filled button (primary CTA), "Add Phase" is outline (secondary)
  • Only shown when: phasesLoaded && phases.length === 0 && !isPlanRunning && !planFailed

Empty State -- Planning in Progress (agent running)

+=============================================================================+
|  Phases                     |                                               |
|  --------------------------+                                                |
|  (empty)                    |  +------------------------------------------+ |
|                             |  |                                          | |
|                             |  |            [spinner]                     | |
|                             |  |       Planning in progress...            | |
|                             |  |                                          | |
|                             |  |   Agent is analyzing the initiative      | |
|                             |  |   and creating phases.                   | |
|                             |  |                                          | |
|                             |  +------------------------------------------+ |
|                             |                                               |
+=============================================================================+
  • [spinner] -- Loader2 with animate-spin, 32px, text-primary
  • "Planning in progress..." -- text-base font-medium
  • Subtext -- text-sm text-muted-foreground
  • NO action buttons -- prevents user from adding phases while agent works
  • Shown when: phasesLoaded && phases.length === 0 && isPlanRunning

Empty State -- Planning Failed (agent crashed)

+=============================================================================+
|  Phases                     |                                               |
|  --------------------------+                                                |
|  (empty)                    |  +------------------------------------------+ |
|                             |  |                                          | |
|                             |  |         [AlertTriangle icon]             | |
|                             |  |         Planning failed                  | |
|                             |  |                                          | |
|                             |  |   The planning agent crashed before      | |
|                             |  |   creating any phases.                   | |
|                             |  |                                          | |
|                             |  |   [sparkles Retry Planning]  [View Log]  | |
|                             |  |                                          | |
|                             |  +------------------------------------------+ |
|                             |                                               |
+=============================================================================+
  • [AlertTriangle icon] -- Lucide AlertTriangle, 48px, text-status-error-fg
  • "Planning failed" -- text-base font-medium text-status-error-fg
  • Subtext -- text-sm text-muted-foreground; shows truncated error reason if available from agent's last output (e.g., "API rate limit exceeded", "Account exhausted")
  • Two action buttons:
    • [sparkles Retry Planning] -- variant="default" (primary), calls planSpawn.spawn() again
    • [View Log] -- variant="outline", opens AgentOutputViewer for the crashed agent
  • Shown when: phasesLoaded && phases.length === 0 && !isPlanRunning && planAgent?.status === 'crashed'
  • Detection: query the most recent plan-category agent for this initiative; check status === 'crashed'
  • Edge case -- partial failure: if the agent created some phases before crashing, this empty state does NOT show (phases exist). Instead, show a dismissible AlertBanner at the top of the detail panel: "Planning agent crashed after creating N phases. Some phases may be incomplete. [Retry] [Dismiss]"

Pending Review Banner (top-level)

+=============================================================================+
|  +---------------------------------------------------------------------+   |
|  | [sparkles] 5 proposals ready for review       [Go to Review ->]     |   |
|  +---------------------------------------------------------------------+   |
|  Phases               [+]  |  Phase: OAuth Implementation                  |
|  --------------------------+                                  [✓] Saved     |
|  ...                        |  ...                                          |
+=============================================================================+
  • Full-width banner above the sidebar+detail grid
  • [sparkles] -- Lucide Sparkles icon, text-amber-500
  • Shows proposal count: "N proposals ready for review" (not generic "Agent has proposals")
  • Background: bg-amber-50 dark:bg-amber-950/20 border border-amber-200 dark:border-amber-800
  • [Go to Review ->] -- text button that navigates to ?tab=review
  • Shown when: proposals with status === 'pending' exist for this initiative
  • Query: trpc.listProposals.useQuery({ initiativeId, status: 'pending' })
  • Count derived from pendingProposals.data?.length

Phase Detail Header

+------------------------------------------------------------------------+
|  Phase 2: OAuth Implementation            [READY]  [git] branch  [...] |
|                                                         |          |    |
|                                                    branch badge    v    |
|                                                   +--------------------+
|                                                   | Detail with Agent  |
|                                                   | Duplicate Phase    |
|                                                   |--------------------|
|                                                   | Delete Phase       |
|                                                   +--------------------+
+------------------------------------------------------------------------+
  • Phase name is inline-editable (click to toggle input); same <SaveIndicator compact> pattern as task names
  • [...] dropdown:
    • Detail with Agent -- spawns a detail agent for this phase (disabled if detail agent already running or phase has tasks)
    • Duplicate Phase -- deep-copies phase + tasks with "(copy)" suffix; useful for templating similar phases
    • Delete Phase -- destructive, red text. Shift+click bypasses confirm. Normal click: window.confirm()
  • [git] branch badge shows initiative branch when set; clicking copies branch name to clipboard (toast: "Copied to clipboard")

Detailing In Progress (per-phase)

+------------------------------------------------------------------------+
|  Phase 2: OAuth Implementation            [READY]  [spinner] Detailing |
+------------------------------------------------------------------------+
  • Shown in phase detail header when a detail agent is active for this phase
  • [spinner] -- Loader2 with animate-spin

Empty State -- Phase Selected, No Tasks

+------------------------------------------------------------------------+
|  Phase 2: OAuth Implementation            [READY]              [...]   |
|------------------------------------------------------------------------|
|  Description:                                                          |
|  Implement OAuth 2.0 authorization code flow...                        |
|                                                                        |
|  Tasks (0)                                            [+ Add Task]     |
|  +------------------------------------------------------------------+  |
|  |                                                                  |  |
|  |                  [ListTodo icon]                                  |  |
|  |              No tasks in this phase                              |  |
|  |                                                                  |  |
|  |   Add tasks manually, or let an agent                            |  |
|  |   decompose this phase into tasks.                               |  |
|  |                                                                  |  |
|  |   [sparkles Detail with Agent]  [+ Add Task]                     |  |
|  |                                                                  |  |
|  +------------------------------------------------------------------+  |
+------------------------------------------------------------------------+
  • Only appears inside the Tasks section of the detail panel (NOT a full-panel takeover like the no-phases empty state)
  • [sparkles Detail with Agent] -- variant="default" (primary CTA), spawns a detail agent for this phase
  • [+ Add Task] -- variant="outline" (secondary), opens inline task input
  • [ListTodo icon] -- Lucide ListTodo, 36px, text-muted-foreground
  • Distinct from the top-level "No phases yet" empty state -- this one is scoped to the Tasks area of an existing phase

Per-Phase Pending Review Banner

+------------------------------------------------------------------------+
|  [!] 3 proposals pending review. Go to the Review tab to review.       |
+------------------------------------------------------------------------+
  • Shown below phase header when phase-specific proposals are pending
  • [!] -- AlertCircle icon, text-amber-500
  • Shows count: "N proposals pending review" (not generic text)
  • Distinct from top-level banner (this is phase-scoped)

Task Row Hover & Focus States

Default:
  ├── Google provider           [PENDING]

Hover:
  ├── Google provider           [PENDING]  [play] [x]
       ^^^^^^^^^^^^^                        ^^^^^  ^^^
       bg-muted/50 row bg                   queue  delete
       cursor-pointer                       (on hover only)

Focused (keyboard nav):
  ├── Google provider           [PENDING]  [play] [x]
  ^^^^
  ring-1 ring-primary/50 outline on row

Selected (Space toggle):
  ├── [✓] Google provider       [PENDING]  [play] [x]
       ^^^
       checkbox visible when any task selected
  • Hover reveals action buttons ([play] to queue, [x] to delete) at the right edge of the row
  • [play] button: variant="ghost" size="icon" -- Lucide Play icon, calls trpc.dispatchTask
  • [x] button: variant="ghost" size="icon" -- Lucide X icon, text-destructive on hover
  • Running tasks replace [play] with [square] (stop button) and hide [x] (cannot delete running task)
  • Focus ring uses ring-1 ring-primary/50 (subtle, not aggressive -- this is keyboard nav, not a call to action)
  • Hover and focus states stack: hovering a focused row shows both bg-muted/50 and focus ring

Task Detail Modal (overlay)

+----------------------------------------------------------+
|  Set up OAuth routes                              [x]    |
|                                                          |
|  Status      [PENDING]     |  Category     execute       |
|  Phase       2. OAuth Flow |  Priority     normal        |
|  Agent       (none)        |  Parent Task  (none)        |
|                                                          |
|  Description                                             |
|  Create Express routes for /auth/login, /auth/callback,  |
|  and /auth/logout with proper middleware chain.           |
|                                                          |
|  Child Tasks                                             |
|  (none -- will be created during decomposition)          |
|                                                          |
|  Dependencies                                            |
|  * DB Schema Migration  [DONE]                           |
|                                                          |
|  Blocks                                                  |
|  * GitHub provider adapter  [BLOCKED]                    |
|                                                          |
|                    [ Queue Task ]  [ Stop Task ]         |
+----------------------------------------------------------+
  • Opened by clicking any task row (or pressing Enter on focused row)
  • [x] close button top-right; Escape also closes
  • Parent Task field shows the parent task name (clickable) if parentTaskId is set, otherwise "(none)"
  • Child Tasks section lists decomposed children if any exist; each child is clickable to open its own modal
  • Dependencies section shows blocking tasks with status; [+ Add] button to add a new dependency (dropdown of other tasks in same phase)
  • Blocks section shows downstream tasks that depend on this one (read-only, informational)
  • Description is a multi-line <textarea> with auto-resize; auto-saves with 500ms debounce + <SaveIndicator>
  • [ Queue Task ] dispatches the task; [ Stop Task ] kills the running agent
  • [ Queue Task ] is disabled with tooltip "Blocked by N tasks" when task has unresolved dependencies
  • [ Delete Task ] -- variant="ghost" text-destructive, bottom-left of modal. Shift+click bypasses confirm.
  • Shared component via <TaskModal> in ExecutionContext

Keyboard Shortcuts (Plan Tab)

Key Context Action
N Task list focused Open inline "Add Task" input at bottom of list
E Task row focused Toggle inline name editing on focused task
Tab Inline edit active Save current edit, move to next task in edit mode
Delete / Backspace Task row focused Delete task (with confirm unless Shift held)
Arrow Up / Arrow Down Task list Navigate between task rows
Arrow Right Collapsed parent focused Expand children
Arrow Left Expanded parent focused Collapse children
Arrow Left Child task focused Jump focus to parent task
Enter Task row focused Open Task Detail Modal
Space Task row focused Toggle task selection (for future multi-select)
Escape Inline edit active Cancel edit, restore original value
Ctrl+A Task list focused Select all tasks
? Plan tab focused, no input active Show keyboard shortcut overlay
  • Shortcuts are scoped to the task list container (onKeyDown handler on the task list wrapper)
  • Only active when no other input/textarea is focused (check document.activeElement.tagName)
  • Discoverable via tooltip on [+ Add Task] button: "Add task (N)"
  • ? shortcut opens a shadcn <Dialog> listing all shortcuts -- same pattern as GitHub's ? key

Source

  • packages/web/src/components/ExecutionTab.tsx (Plan tab = ExecutionTab with sidebar+detail layout)
  • packages/web/src/components/execution/PlanSection.tsx
  • packages/web/src/components/execution/PhaseSidebarItem.tsx
  • packages/web/src/components/execution/PhaseDetailPanel.tsx
  • packages/web/src/components/execution/PhaseActions.tsx
  • packages/web/src/components/execution/TaskModal.tsx
  • packages/web/src/components/execution/BulkTaskMenu.tsx (new)
  • packages/web/src/components/execution/TaskTree.tsx (new -- replaces flat list)
  • packages/web/src/components/execution/TaskRowInlineEdit.tsx (new -- extracted edit mode)
  • packages/web/src/components/execution/PhaseEmptyTasks.tsx (new -- per-phase empty state)
  • packages/web/src/components/execution/PlanTabSkeleton.tsx (new -- loading skeleton)
  • packages/web/src/components/KeyboardShortcutOverlay.tsx (new -- ? key dialog, reusable)
  • packages/web/src/components/TaskRow.tsx
  • packages/web/src/hooks/useAutoSave.ts

Design Review Notes

Critique and rationale for all v2 Plan Tab design decisions. Each item maps to a review criterion.

1. Sidebar Width: 240px (consistent across tabs)

Problem: Content tab v1 used 192px for the page tree. Plan tab v1 was 260px. The 68px discrepancy means the divider line jumps when switching tabs -- jarring in a tabbed layout sharing the same viewport.

Resolution: Both Content tab and Plan tab now use 240px. The divider line is stable across tab switches. Rationale:

  • Phase cards carry status badges, task counts, and dependency indicators. 192px was too cramped.
  • Content tab v2 independently moved to 240px to accommodate deep nesting + breadcrumb truncation.
  • The convergence at 240px is incidental but correct -- both sidebars have similar information density now.
  • 240px is the canonical sidebar width for all tabbed views within initiative detail. Any future tabs with sidebars should use 240px unless there is a strong reason to deviate.

2. Three-Way Empty State Split (no phases / planning / planning failed)

Problem: v1 had no way to tell the user "planning failed." The agent could crash silently, leaving the user staring at a "No phases yet" screen with no signal.

Resolution: Added a third empty state -- "Planning failed" with AlertTriangle icon, error message, [Retry Planning] primary button, and [View Log] outline button. Detection: query the most recent plan-category agent for this initiative, check status === 'crashed'.

The three states form a clean state machine:

  • !isPlanRunning && !planFailed && phases.length === 0 -> "No phases yet" (with action buttons)
  • isPlanRunning && phases.length === 0 -> "Planning in progress..." (no action buttons)
  • !isPlanRunning && planFailed && phases.length === 0 -> "Planning failed" (retry + log buttons)

Partial failure edge case: If the agent crashes after creating some phases, the empty states do not apply (phases exist). Instead, a dismissible AlertBanner appears at the top of the detail panel: "Planning agent crashed after creating N phases. [Retry] [Dismiss]". This is critical -- without it, partial failures are invisible.

Error context: The failed empty state now shows a truncated error reason extracted from the agent's last output (e.g., "API rate limit exceeded"). This saves the user from having to click "View Log" just to understand why it failed.

3. Task Tree: Parent-Child + Dependency Visualization

Problem: The v1 flat task list gave no signal about task structure. Users managing 10+ agents need to understand the DAG at a glance -- which tasks decompose into subtasks, which tasks block other tasks.

Resolution: The task tree now communicates two distinct relationships:

  • Parent-child decomposition: Indented rows under parent tasks (uses parentTaskId from the schema). Collapsible per parent. The child: prefix distinguishes these from agent assignment lines.
  • Dependency blocking: ← blocked by: <task-name> annotations below blocked tasks. The blocking task name is a clickable link that scrolls to and highlights the blocking task.
  • Cross-phase dependencies: When a blocking task lives in a different phase, the annotation includes the phase name and clicking it switches the sidebar selection.
  • Collapse behavior: Parents with >= 4 children default to collapsed, showing a child count badge. This prevents the tree from becoming unwieldy in heavily-decomposed phases.

What this is NOT: This is not a full DAG graph. The Plan tab shows a tree (hierarchical nesting + inline annotations), not a topological graph with SVG arrows. That is the Execution tab's job. The Plan tab's job is editing the structure, not visualizing execution order. The inline ← blocked by: annotations are sufficient for understanding dependency relationships during planning; the full pipeline visualization belongs to the Execution tab.

Known limitation: The tree representation cannot fully express a DAG with convergent dependencies (task C depends on both A and B, which are not parent-child related). The inline annotations handle this for display, but visually it is not as clear as a graph. This is an acceptable tradeoff -- the Plan tab prioritizes editability over visualization fidelity.

4. Button Hierarchy: "Plan with Agent" (primary) vs "Add Phase" (outline)

Problem: Both buttons were visually ambiguous about which action is recommended.

Resolution: Explicit variant assignment:

  • Plan with Agent -- variant="default" (indigo filled, primary CTA). This is the happy path. New users should click this first.
  • Add Phase -- variant="outline" (secondary). This is for power users who want manual control.

The sparkles icon on "Plan with Agent" already signals "AI-powered," and making it the filled button reinforces it as the recommended action. The outline variant for "Add Phase" correctly communicates "alternative path."

5. Review Banner: Proposal Count

Problem: "Agent has proposals ready for review" is vague. Is it 1 proposal or 50? The user can't gauge urgency without switching tabs.

Resolution: Show the count: "5 proposals ready for review." Both the top-level banner and the per-phase banner now include counts. The count comes from pendingProposals.data?.length which is already fetched by the query.

6. Phase Reordering (drag-and-drop)

Problem: No way to reorder phases after creation. If the user adds phases manually or the agent creates them in the wrong order, there's no recourse.

Resolution: Added [≡] toggle button in the sidebar header. When active:

  • Phase cards become draggable (via @dnd-kit/sortable)
  • Sidebar gets a subtle bg-muted highlight to indicate mode change
  • Drag handles appear on each card
  • Drop triggers trpc.updatePhaseSortOrder mutation
  • Toggle off returns to normal selection behavior

The toggle approach (vs. always-draggable) is intentional: drag-and-drop interferes with click-to-select in a sidebar this narrow. You don't want accidental drags when you're trying to navigate.

7. Phase Status Summary in Sidebar Cards

Problem: Sidebar cards showed task count but not progress. "5 tasks" tells you nothing about completion state.

Resolution: Changed to N/M tasks format (e.g., "2/5 tasks", "3/3 tasks"). When all tasks are complete (N === M), the text switches from text-muted-foreground to text-status-success-fg for a visual "done" signal without adding another badge.

8. Bulk Task Operations

Problem: No way to operate on all tasks in a phase at once. If the agent decomposes a phase poorly, the user has to delete tasks one by one.

Resolution: [...] dropdown menu on the Tasks section header, expanded to include:

  • "Select All" (Ctrl+A) -- enables checkbox mode for future multi-select operations
  • "Delete All Tasks" -- nukes all tasks in the phase. window.confirm() unless Shift held.
  • "Reset All to Pending" -- resets all non-running tasks back to pending. Essential after a batch failure where some tasks are stuck in error states.
  • "Re-categorize All" -- submenu to change the category of all tasks in the phase.
  • "Expand All Children" / "Collapse All Children" -- tree visibility toggles for heavily decomposed phases.

The Select All + checkbox mode lays groundwork for future multi-select operations (bulk delete selected, bulk re-categorize selected) without building the full multi-select UI now.

9. Task Inline Editing + Save State

Problem: The <SaveIndicator> existed for phase descriptions but not for task names. If users can edit task names inline, they need feedback that the edit persisted.

Resolution: Each task row gets its own micro save indicator (icon-only <SaveIndicator> -- checkmark or spinner, no text label). The indicator appears inline next to the task name input during editing and disappears after save completes. This uses the same <SaveIndicator> component with a compact prop that renders icon-only.

10. Keyboard Shortcut for Add Task (and friends)

Problem: In a keyboard-first mission control UI, requiring a mouse click to add a task is a friction point. Power users managing dozens of tasks want to stay on the keyboard.

Resolution: Full keyboard shortcut table added (see "Keyboard Shortcuts" section). Key decisions:

  • N for new task (mnemonic: New). Scoped to task list focus.
  • E for edit (mnemonic: Edit). Opens inline editing on the focused row.
  • Tab during inline edit advances to the next task in edit mode (rapid-fire renaming).
  • Delete/Backspace for delete. With confirm unless Shift held (consistent with mouse Shift+click pattern).
  • Arrow Up/Down for row navigation. Arrow Left/Right for tree expand/collapse (borrowed from VS Code tree behavior).
  • Space toggles task selection (multi-select mode). Ctrl+A selects all.
  • Enter to open modal.
  • ? opens a shortcut overlay dialog (GitHub-style discoverability).
  • All shortcuts are scoped to the task list container and disabled when an input is focused.
  • The [N] badge hint next to "Add Task" button makes the primary shortcut discoverable. The ? overlay covers the rest.

11. Missing: Per-Phase Empty State (phase exists, no tasks)

Problem caught in review: The spec documented empty states for "no phases" and "planning in progress/failed," but NOT for the case where a phase exists with zero tasks. The user selects a phase, sees the description, and then... a blank Tasks section with just the "Add Task" button. No guidance.

Resolution: Added "Empty State -- Phase Selected, No Tasks" section. The Tasks area (not full panel) shows a small inline empty state with two CTAs: "Detail with Agent" (primary, spawns decomposition) and "Add Task" (outline, manual). This mirrors the plan-level empty state pattern: AI-first is primary, manual is secondary.

12. Missing: Task Row Hover & Focus States

Problem caught in review: The spec defined keyboard shortcuts and inline editing but never documented what happens on mouse hover or keyboard focus. In a dense list UI, hover states are not cosmetic -- they communicate interactivity and reveal action affordances.

Resolution: Added "Task Row Hover & Focus States" section. Key decisions:

  • Hover reveals [play] (queue) and [x] (delete) action buttons at row's right edge. Hidden by default to keep the list clean.
  • Running tasks swap [play] for [square] (stop) and hide [x] (cannot delete running tasks).
  • Keyboard focus uses a subtle ring-1 ring-primary/50 outline (not ring-2 -- that's too aggressive for navigation).
  • Hover and focus states stack visually (both can be active on the same row).

13. Missing: Phase Detail Header Actions

Problem caught in review: The original phase header dropdown only had "Delete Phase." That is one action in a dropdown -- just use a button. A dropdown implies a menu with multiple options.

Resolution: Expanded the [...] dropdown to three actions:

  • "Detail with Agent" -- spawns task decomposition for the selected phase
  • "Duplicate Phase" -- deep-copies phase + tasks, appends "(copy)" suffix. Useful for templating similar phases (e.g., duplicating "Google OAuth" to create "GitHub OAuth" with the same task structure).
  • "Delete Phase" -- destructive, red text, bottom of menu with separator above.

Now the dropdown earns its existence.

14. Concern: Task Description Editing in Modal Only

The current spec puts task description editing exclusively in the Task Detail Modal. For quick edits, opening a modal is friction. Consider adding expandable inline description editing (click to expand a 2-line textarea below the task row) in a future iteration. Not adding it now because the tree is already vertically dense and expandable descriptions would make it harder to scan. But log this as a known future improvement.

15. Concern: No Loading / Skeleton States Documented

The spec documents empty states comprehensively but says nothing about what the user sees while phases are loading. On a slow connection or large initiative, there is a flash of empty state before data arrives. The plan tab should show:

  • Sidebar: 3 skeleton cards (pulsing bg-muted animate-pulse, matching card dimensions)
  • Detail panel: skeleton lines for title + description + task list

This prevents the "No phases yet" empty state from flashing before the actual phases load, which would be confusing.

16. Implementation Note: Component Boundary Map

New or modified components for v2 Plan Tab:

Component Path (proposed) New?
PhaseSidebarItem packages/web/src/components/execution/PhaseSidebarItem.tsx Modified -- add task progress, dep indicator, drag handle
PhaseActions packages/web/src/components/execution/PhaseActions.tsx Modified -- add [≡] toggle, [Detail All], detailing badge
TaskTree packages/web/src/components/execution/TaskTree.tsx New -- replaces flat task list with nested tree
TaskRow packages/web/src/components/TaskRow.tsx Modified -- add inline edit, hover actions, focus state, child indent
TaskRowInlineEdit packages/web/src/components/execution/TaskRowInlineEdit.tsx New -- extracted edit mode for TaskRow
BulkTaskMenu packages/web/src/components/execution/BulkTaskMenu.tsx New
PhaseEmptyTasks packages/web/src/components/execution/PhaseEmptyTasks.tsx New -- per-phase "no tasks" empty state
PlanTabSkeleton packages/web/src/components/execution/PlanTabSkeleton.tsx New -- loading skeleton
KeyboardShortcutOverlay packages/web/src/components/KeyboardShortcutOverlay.tsx New -- ? key dialog, reusable across tabs