Files
Codewalkers/docs/wireframes/v2/inbox.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

27 KiB

Inbox Page (v2)

Route: /inbox

Source: packages/web/src/routes/inbox.tsx


v1 -> v2 Changes

Aspect v1 v2
List error state None [AlertCircle] + "Failed to load conversations" + [Retry]
Detail error state None [AlertCircle] + "Failed to load conversation" + [Retry]
Action buttons 3 buttons: Cancel, Dismiss, Send Answers 2 buttons: [ Stop Agent ] (destructive, LEFT-isolated) + [ Send Answers ] (primary, RIGHT)
Conversation states No visual distinction Orange dot = pending, Grey dot = answered, filterable tabs
Batch answers N/A "Apply to similar" option when multiple agents ask same question type
Submit feedback None Button shows [spinner] Sending... during mutation
Submit error Toast only Inline red text below buttons: "Failed to send. Try again."
Empty state Basic text Centered empty state with description

Default State (with conversations)

+=============================================================================+
| [CW]  Initiatives  Agents *3  [*Inbox*] (2)  Settings   [cmd-k]  [sun]  * |
+=============================================================================+
|                                                                             |
|  Inbox (2)                                                    [ Refresh ]  |
|                                                                             |
|  [Pending (2)] [Answered]  |  Question from blue-fox-7              [<>]   |
|  --------------------------+  min 400px, resizable                          |
|  +------------------------+|                                                |
|  | ! blue-fox-7      2m   ||  Task: Implement OAuth PKCE flow              |
|  |   Auth System Overhaul  ||  Phase: Authentication . 2 minutes ago        |
|  |   BLOCKING              ||                                                |
|  +------------------------+|  "Should I use PKCE or implicit flow           |
|  | ? green-bear-1    5m   ||   for the browser client? The spec             |
|  |   API Redesign          ||   recommends PKCE but the existing             |
|  +------------------------+|   code uses implicit."                          |
|                             |                                                |
|                             |  [v] Previous Q&A with blue-fox-7 (1)         |
|                             |                                                |
|                             |  Your Answer                   [Snooze v]     |
|                             |  +--------------------------------------------+|
|                             |  | Use PKCE. We're deprecating implicit       ||
|                             |  | flow per OAuth 2.1 security BCP.           ||
|                             |  |                                            ||
|                             |  +--------------------------------------------+|
|                             |  Markdown supported. `code`, **bold**, ```    |
|                             |                                                |
|                             |  [ Stop Agent ]          [ Send Answers ⌘⏎ ] |
+=============================================================================+

Layout notes:

  • Filter tabs (Pending / Answered) at top of conversation list allow switching views
  • ! (urgent dot, purple) = conversation linked to a blocked task; ? (warning dot, orange) = standard pending
  • BLOCKING badge uses status-urgent tokens — surfaces task-blocking conversations first
  • Detail panel minimum 400px, draggable resize handle [<>], or click to toggle full-width
  • [Snooze v] dropdown: 15m, 1h, 4h, Tomorrow — removes from pending list temporarily
  • [ Stop Agent ] is LEFT-aligned, [ Send Answers ] is RIGHT-aligned — maximum spatial separation
  • Previous Q&A collapsible section shows conversation history with this agent
  • Textarea hint line confirms markdown support
  • Cmd+Enter shortcut shown on Send button; R global shortcut focuses textarea

Conversation Card (in left list)

Blocking (urgent — task is blocked waiting for this answer)

+-------------------------------+
| ! blue-fox-7            2m    |    <-- status dot (purple, pulsing) + name + time
|   Auth System Overhaul        |    <-- initiative name
|   BLOCKING                    |    <-- badge: bg-status-urgent-bg text-status-urgent-fg
+-------------------------------+

Waiting for response (standard)

+-------------------------------+
| ? green-bear-1          5m    |    <-- status dot (orange) + name + time
|   API Redesign                |    <-- initiative name
+-------------------------------+

Snoozed

+-------------------------------+
| z pink-owl-3           45m    |    <-- status dot (muted) + name + time
|   Data Migration              |    <-- initiative name
|   Snoozed until 3:00 PM       |    <-- snooze info, text-muted-foreground
+-------------------------------+

Answered

+-------------------------------+
| ✓ green-bear-1         1h    |    <-- status dot (green) + name + time
|   API Redesign                |    <-- initiative name, dimmed
+-------------------------------+
  • Purple ! dot (pulsing) = linked task is blocked — uses status-urgent-dot token. Sorted first always.
  • Orange ? dot = pending conversation, standard priority — uses status-warning-dot token
  • Muted z dot = snoozed — hidden from Pending tab by default, shown in a collapsed "Snoozed (1)" section at bottom
  • Green checkmark = answered — uses status-success-dot token. Visible only on Answered tab.
  • Click selects conversation and shows detail panel
  • Selected card gets bg-accent highlight (indigo tint, not grey)
  • Up/Down arrow keys navigate list; Enter selects; R focuses answer textarea
  • Sort order within Pending tab: blocking first, then by createdAt ascending (oldest unanswered first)

Detail Panel (min 400px right, resizable)

Header

+----------------------------------------------+
|  Question from blue-fox-7              [<>]   |
|  Task: Implement OAuth PKCE flow              |
|  Phase: Authentication  .  2 minutes ago      |
+----------------------------------------------+
  • [<>] toggle: click to expand detail panel to full width (hides conversation list). Click again to restore split. Keyboard shortcut: F to toggle full-width.
  • Task and phase names are clickable links (navigate to initiative detail at that task/phase).
  • Panel is resizable via drag handle on the left border. Min 400px, max 70% of viewport.

Conversation History (collapsible)

+----------------------------------------------+
|  [v] Previous Q&A with blue-fox-7 (1)        |
|  +------------------------------------------+|
|  |  Q (1h ago): "Should I store tokens in   ||
|  |   localStorage or httpOnly cookies?"      ||
|  |  A: "httpOnly cookies. See OWASP          ||
|  |   session management cheatsheet."         ||
|  +------------------------------------------+|
+----------------------------------------------+
  • Collapsed by default. Shows count of prior conversations with this agent (same fromAgentId).
  • Each historical entry shows the question, your answer, and relative timestamp.
  • Query: findByAgentPair(fromAgentId, toAgentId)requires new repository method (schema supports it, query doesn't exist yet).

Question Display

+----------------------------------------------+
|  "Should I use PKCE or implicit flow          |
|   for the browser client? The spec            |
|   recommends PKCE but the existing            |
|   code uses implicit."                        |
+----------------------------------------------+
  • Question text rendered in a bg-muted rounded-lg p-4 block with font-mono text-sm for code-heavy questions.
  • If the question contains markdown fences, render them with syntax highlighting (use the terminal token palette).

Suggested Answers (conditional)

+----------------------------------------------+
|  Suggested                                    |
|  +------------------------------------------+|
|  | [Use approach A: PKCE flow (recommended  ||
|  |  by spec)]                     [ Use ^ ] ||
|  +------------------------------------------+|
|  +------------------------------------------+|
|  | [Use approach B: Keep implicit flow      ||
|  |  (existing code)]              [ Use ^ ] ||
|  +------------------------------------------+|
+----------------------------------------------+
  • Shown only when the agent's question contains recognizable choice patterns ("should I use A or B", "which approach", option lists).
  • Parsed from the question text client-side — extracts options and presents as one-click answer buttons.
  • [ Use ^ ] populates the answer textarea with that option (does NOT auto-send). User can edit before sending.
  • If no pattern detected, this section is hidden entirely. No server-side AI inference needed.

Answer Form

+----------------------------------------------+
|  Your Answer                   [Snooze v]     |
|  +------------------------------------------+|
|  | Use PKCE. We're deprecating implicit     ||
|  | flow per OAuth 2.1 security BCP.         ||
|  |                                          ||
|  | ```ts                                    ||
|  | // See RFC 7636 for PKCE spec            ||
|  | ```                                      ||
|  +------------------------------------------+|
|  Markdown supported. `code`, **bold**, ```   |
|                                               |
|  [ Stop Agent ]          [ Send Answers ⌘⏎ ] |
+----------------------------------------------+
  • Textarea: min-h-[120px], auto-grows. Supports markdown with a hint line below. Rendered preview is NOT shown (this is a response to an agent, not a document — raw markdown is fine). Fenced code blocks (```) get font-mono styling in the textarea via CSS.
  • Snooze dropdown: [Snooze v] next to "Your Answer" label. Options: 15 minutes, 1 hour, 4 hours, Tomorrow, Custom. Snoozed conversations move to collapsed "Snoozed" section at bottom of Pending list. Snooze is client-side only (localStorage timer) — no schema change needed. When snooze expires, conversation reappears in the Pending list with a brief highlight animation.
  • Keyboard: R from anywhere on the page focuses the textarea. Cmd+Enter (Mac) / Ctrl+Enter (Win) sends. Escape from textarea returns focus to the conversation list.

Batch Answer (when applicable)

+----------------------------------------------+
|  [i] 2 other agents asked similar questions   |
|      [ Apply this answer to all 3 ]           |
+----------------------------------------------+
  • Shown below the answer textarea when multiple pending conversations contain similar question text.
  • Similarity detection: simple keyword overlap heuristic on question text (no ML needed). E.g., if 3 agents all ask about "PKCE vs implicit", they cluster.
  • [ Apply this answer to all 3 ] sends the same answer to all matched conversations. Uses a batch answerConversation call — requires new tRPC batch mutation or sequential calls.
  • If no similar questions exist, this section is hidden.

Button anatomy

  • [ Stop Agent ] -- variant="destructive" size="sm", LEFT-aligned in the button row. Stops the asking agent via stopAgent mutation. Confirmation: window.confirm("Stop agent blue-fox-7? This will terminate the agent process.") includes the agent name in the message. Shift+click bypasses confirmation per project convention. Visual separation: positioned flush-left while Send is flush-right, creating maximum distance. Uses outline style (not filled) to further reduce visual weight vs. the primary Send button. Updated: variant="outline" with text-destructive border-destructive hover:bg-destructive hover:text-destructive-foreground.
  • [ Send Answers ⌘⏎ ] -- variant="default" (primary, filled indigo), RIGHT-aligned. Sends the response via answerConversation mutation then resumeAgent mutation. Disabled until answer textarea is non-empty. Shows keyboard shortcut hint ⌘⏎ in the button label. After successful send, auto-advances to next pending conversation in the list.

Submit In Progress

|  [ Stop Agent ]                   [ [spinner] Sending... ]     |
  • [ Send Answers ] button shows a Loader2 spinner + "Sending..." text
  • Button is disabled during mutation
  • [ Stop Agent ] is also disabled during mutation to prevent conflicting actions
  • Textarea becomes readonly with opacity-50 during mutation
  • On success: toast "Answer sent to blue-fox-7", auto-advance to next pending conversation

Submit Error

|                                                            |
|  [ Stop Agent ]                      [ Send Answers ⌘⏎ ] |
|                                                            |
|                      Failed to send. Try again.            |
+------------------------------------------------------------+
  • Error text: text-sm text-destructive, right-aligned below the buttons
  • Shown when answerConversationMutation.isError or resumeAgentMutation.isError is true
  • Cleared on next submit attempt
  • Textarea remains editable so the user can retry without re-typing

Empty Inbox

+=============================================================================+
|                                                                             |
|  Inbox (0)                                                    [ Refresh ]  |
|                                                                             |
|  +-----------------------------------------------------------------------+  |
|  |                                                                       |  |
|  |                         [inbox]                                       |  |
|  |                  No pending questions                                 |  |
|  |   Agents will ask questions here when they need input.                |  |
|  |                                                                       |  |
|  +-----------------------------------------------------------------------+  |
|                                                                             |
+=============================================================================+
  • [inbox] icon: Inbox from Lucide, h-8 w-8 text-muted-foreground
  • Title: text-sm font-medium
  • Description: text-sm text-muted-foreground
  • Keyboard hint below: text-xs text-muted-foreground — "Press R to reply when a question arrives"

List Loading State (skeleton rows)

+=============================================================================+
|                                                                             |
|  Inbox                                                        [ Refresh ]  |
|                                                                             |
|  Conversations             |                                                |
|  --------------------------+  400px                                         |
|  +------------------------+|                                                |
|  | [.] ░░░░░░░░░░  ░░░  ||                                                |
|  |   ░░░░░░░░░░░░░░░░░   ||     Select an agent to view details           |
|  +------------------------+|                                                |
|  +------------------------+|                                                |
|  | [.] ░░░░░░░░░░  ░░░  ||                                                |
|  |   ░░░░░░░░░░░░░░░░░   ||                                                |
|  +------------------------+|                                                |
|  +------------------------+|                                                |
|  | [.] ░░░░░░░░░░  ░░░  ||                                                |
|  |   ░░░░░░░░░░░░░░░░░   ||                                                |
|  +------------------------+|                                                |
|  +------------------------+|                                                |
|  | [.] ░░░░░░░░░░  ░░░  ||                                                |
|  |   ░░░░░░░░░░░░░░░░░   ||                                                |
|  +------------------------+|                                                |
+=============================================================================+

Skeleton cards mirror conversation card anatomy: status dot placeholder, name + time line, initiative name line. Shimmer animation sweeps left-to-right on a 1.5s loop.


List Error State

+=============================================================================+
|                                                                             |
|  Inbox                                                        [ Refresh ]  |
|                                                                             |
|  Conversations             |                                                |
|  --------------------------+  400px                                         |
|                             |                                                |
|    [AlertCircle]            |     Select an agent to view details           |
|    Failed to load           |                                                |
|    conversations            |                                                |
|                             |                                                |
|    [ Retry ]                |                                                |
|                             |                                                |
+=============================================================================+
  • [AlertCircle] icon: h-6 w-6 text-destructive
  • Error message: text-sm text-destructive
  • [ Retry ] button: variant="outline" size="sm", calls agentsQuery.refetch() + messagesQuery.refetch()

Detail Error State

+=============================================================================+
|                                                                             |
|  Inbox (2)                                                    [ Refresh ]  |
|                                                                             |
|  Conversations             |                                                |
|  --------------------------+  400px                                         |
|  +------------------------+|                                                |
|  | ? blue-fox-7      2m   ||       [AlertCircle]                            |
|  |   Auth System Overhaul  ||  Failed to load conversation                   |
|  +------------------------+|                                                |
|  | ? green-bear-1    5m   ||       [ Retry ]                                |
|  |   API Redesign          ||                                                |
|  +------------------------+|                                                |
|                             |                                                |
+=============================================================================+
  • Shown when questionsQuery.isError is true for the selected agent
  • [ Retry ] button calls questionsQuery.refetch()

Keyboard Shortcuts

Key Context Action
R Anywhere on page Focus answer textarea for selected conversation
Up / Down Conversation list focused Navigate between conversations
Enter Conversation list focused Select highlighted conversation
Cmd+Enter / Ctrl+Enter Answer textarea focused Send answer
Escape Answer textarea focused Return focus to conversation list
F Anywhere on page Toggle detail panel full-width
J / K Anywhere on page Next / previous conversation (vim-style)
S Conversation selected, textarea empty Open snooze dropdown

Shortcuts are disabled when a dialog (confirm, etc.) is open. Documented in a ? tooltip in the page header.


Schema / Backend Requirements

Changes needed to support v2 Inbox features:

Feature Requirement Scope
Conversation history findByAgentPair(fromAgentId, toAgentId) repository method New query in ConversationRepository
Blocking detection Join conversation's taskId to tasks table, check status === 'blocked' Query enrichment in tRPC getPendingConversations or client-side join
Batch answer Either a batchAnswerConversations tRPC mutation or sequential answerConversation calls New mutation (preferred) or client loop
Snooze Client-side only (localStorage timers) No schema change
Suggested answers Client-side question text parsing No schema change

Source

  • packages/web/src/routes/inbox.tsx
  • packages/web/src/components/InboxList.tsx
  • packages/web/src/components/InboxDetailPanel.tsx
  • packages/web/src/components/InboxConversationHistory.tsx (new)
  • packages/web/src/components/InboxSuggestedAnswers.tsx (new)
  • packages/web/src/components/InboxBatchAnswer.tsx (new)
  • packages/web/src/components/MessageCard.tsx
  • packages/web/src/components/QuestionForm.tsx
  • packages/web/src/hooks/useInboxKeyboard.ts (new — keyboard shortcut handler)
  • packages/web/src/hooks/useSnooze.ts (new — localStorage snooze timers)

Design Review Notes

What's solid

The 2-button simplification from v1's 3-button layout is the right call. The error states (list, detail, submit) are thorough — most wireframes skip these. The skeleton loading state mirrors card anatomy correctly. The empty state has personality without being cute.

What was fixed

1. Stop Agent proximity hazard. The original spec placed [ Stop Agent ] immediately left of [ Send Answers ]. This is a catastrophic misclick waiting to happen — you're about to click "Send" and you hit "Stop" instead, killing an agent mid-task. Fix: buttons are now flush-left and flush-right respectively, creating maximum spatial separation. Additionally, [ Stop Agent ] was downgraded from variant="destructive" (filled red) to an outline style with destructive text color. The filled primary button now has overwhelming visual dominance. The window.confirm() dialog now includes the agent name for clarity.

2. No answered/pending filtering. The original list showed both states mixed together with only a dot color difference. When you have 15+ conversations, this becomes noise. Fix: added [Pending (2)] [Answered] filter tabs at the top of the conversation list. Pending is the default view. Answered is an archive you visit when you need to reference past decisions.

3. No urgency signal. All pending conversations looked identical — whether the agent's task is blocked and the entire initiative is stalled, or it's a low-priority research question. Fix: conversations linked to blocked tasks get a purple pulsing ! dot and a BLOCKING badge, using the existing status-urgent tokens from the theme spec. These always sort first.

4. Detail panel too narrow for code. 400px is fine for prose questions, but agents frequently include code snippets, file paths, and stack traces. Fix: panel is now min 400px, resizable with a drag handle, plus a full-width toggle (F key or [<>] button) that hides the conversation list entirely.

5. No conversation history. Without context, you're answering each question in isolation. The agent might have asked a related question 20 minutes ago that your current answer should be consistent with. Fix: collapsible "Previous Q&A with [agent]" section above the answer form. Requires a new findByAgentPair() repository method — the schema supports it, the query just doesn't exist yet.

6. Plain text textarea. Agents process markdown. Users think in markdown. Not supporting it means answers with code references are hard to write clearly. Fix: textarea now accepts markdown with a hint line ("Markdown supported. code, bold, ```"). No live preview — this is a reply to an agent, not a document editor. The overhead of a preview pane isn't justified here.

7. No snooze. Not every question is urgent. Sometimes you need to think, or you're deep in another conversation. Without snooze, the question just sits there adding visual noise to your pending list. Fix: [Snooze v] dropdown with preset durations. Snoozed items collapse into a "Snoozed" section at the bottom of the Pending tab. Implemented client-side only (localStorage timers) — no schema change, no migration, no backend work.

8. No keyboard shortcuts. For a keyboard-first tool managing 10+ agents, requiring mouse clicks to answer questions is slow. Fix: full keyboard shortcut table added. R to reply from anywhere, J/K for vim-style navigation, Cmd+Enter to send, F for full-width toggle.

9. No suggested answers. When an agent asks "should I use A or B?", the system could extract those options and present them as one-click buttons. Fix: client-side pattern matching on question text extracts choice options. [ Use ^ ] populates (not sends) the textarea. No AI inference, no API cost — just regex on common question patterns.

10. No batch answers. When 3 agents ask "which auth library should we use?", answering each individually is tedious. Fix: similarity detection (keyword overlap) clusters similar pending questions. "Apply this answer to all 3" button sends the same answer to all matched conversations.

Open questions for implementation

  1. Snooze persistence across sessions. localStorage is fine for single-session use, but if the user closes the tab and reopens, snoozed items reappear immediately (timer lost). Is this acceptable, or should snooze state be persisted server-side? Recommendation: start with localStorage, add server-side if users complain.

  2. Batch answer atomicity. If one of the 3 batch answers fails, should the other 2 still succeed? Recommendation: yes — use sequential calls, show partial success/failure. Don't make the user redo the ones that worked.

  3. Conversation history query performance. findByAgentPair will scan by fromAgentId index. For workspaces with hundreds of conversations, consider adding a composite index on (fromAgentId, toAgentId) to the schema.

  4. Blocking detection accuracy. The current approach joins taskId to check task.status === 'blocked'. But a task could be blocked for reasons unrelated to this conversation. Consider adding a isBlocking field to conversations, or determining blocking status from whether the agent itself is waiting_for_input.