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)
733 lines
42 KiB
Markdown
733 lines
42 KiB
Markdown
# 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: **N**ew). Scoped to task list focus.
|
|
- `E` for edit (mnemonic: **E**dit). 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 |
|