--- phase: 23 slug: brainstormer-flow status: draft shadcn_initialized: true preset: new-york / neutral / css-variables created: 2026-04-01 --- # Phase 23 — UI Design Contract > Visual and interaction contract for Phase 23: Brainstormer Flow. > Generated by gsd-ui-researcher. Verified by gsd-ui-checker. --- ## Design System | Property | Value | Source | |----------|-------|--------| | Tool | shadcn/ui | `ui/components.json` — unchanged from Phase 21/22 | | Style | new-york | `ui/components.json` | | Base color | neutral | `ui/components.json` | | CSS variables | true | `ui/components.json` | | Component library | Radix UI (via shadcn new-york) | `ui/components.json` | | Icon library | lucide-react ^0.574.0 | `ui/components.json` | | Font | System UI (`font-sans`, inherited) | `ui/src/index.css` | **Existing shadcn components available (no install needed):** `avatar`, `badge`, `button`, `card`, `checkbox`, `collapsible`, `command`, `dialog`, `dropdown-menu`, `input`, `label`, `popover`, `scroll-area`, `select`, `separator`, `sheet`, `skeleton`, `tabs`, `textarea`, `tooltip` **Existing custom components to reuse/extend:** - `ChatMessage.tsx` — extend with `role === "system"` rendering branch for handoff/spec/status-update messages - `ChatPanel.tsx` — extend with Brainstormer default agent selection on new conversation - `AgentIcon` (from `AgentIconPicker.tsx`) — used for Brainstormer identity in all message identity bars - `agentRoleColors` (from `agent-role-colors.ts`) — `general` role maps to `text-slate-600 dark:text-slate-400` for Brainstormer avatar - `issuesApi` — referenced from `ui/src/api/issues` for task creation link-out **New DB migration required:** - Add `message_type` column to `chat_messages` table: `text("message_type")` — values: `null` (normal), `"handoff"`, `"spec_card"`, `"task_created"`, `"status_update"`. Used by Phase 23 system message rendering to determine which specialized card to display. --- ## Layout Contract ### Layout Unchanged The overall layout established in Phase 21 and unmodified in Phase 22 remains: ``` [ CompanyRail ] [ Sidebar ] [
] [ ChatPanel ] [ PropertiesPanel ] ``` Phase 23 adds new UI surfaces **inside** `ChatPanel` and `ChatMessageList` only. No layout-level changes. ### Default Brainstormer Selection (AGENT-01) When the user opens a **new conversation** (no prior messages), the `ChatPanel` auto-selects the workspace agent with `role === "general"` as the default. The `ChatAgentSelector` renders this agent immediately without user action. **Selection precedence:** 1. If a `general` role agent exists in the workspace — select it 2. If multiple `general` agents exist — select the first by `createdAt` ascending 3. If no `general` agent exists — fall back to the first agent alphabetically (same as current behavior) 4. Auto-selection fires only when `activeAgentId === null` and the conversation has zero messages The auto-selected agent is visually indistinguishable from a manually selected agent — the `ChatAgentSelector` shows its icon + name normally. ### Spec Card Layout (AGENT-02) When the Brainstormer completes its questioning flow, it emits a **spec card** as a `system` role message with `message_type: "spec_card"`. The `ChatMessage` component renders a `ChatSpecCard` instead of a markdown message. ``` ┌─────────────────────────────────────────────┐ │ [Brain icon] Brainstormer — Spec Ready │ ← identity bar (standard) ├─────────────────────────────────────────────┤ │ What: {what field text} │ │ Why: {why field text} │ │ Constraints: {constraints field text} │ │ Success: {success field text} │ ├─────────────────────────────────────────────┤ │ [ Send to PM ] [ Edit ] [ Save as Draft ] │ ← action row └─────────────────────────────────────────────┘ ``` - Container: `rounded-lg border border-border bg-card p-4 max-w-[480px]` — uses `bg-card` (secondary 30% surface) to visually distinguish spec from normal prose - Section labels ("What", "Why", "Constraints", "Success"): `text-[11px] font-semibold uppercase tracking-wide text-muted-foreground` — same weight/size pattern as Phase 22 timestamps - Section content: `text-[15px] font-normal text-foreground leading-relaxed` — standard body - Vertical rhythm between sections: `space-y-4` (16px gaps) - Action row: `flex gap-2 pt-4 border-t border-border mt-4` — separated from content with a border - "Send to PM" button: `variant="default" size="sm"` — primary action - "Edit" button: `variant="outline" size="sm"` — secondary action - "Save as Draft" button: `variant="ghost" size="sm"` — tertiary action ### Handoff Indicator Layout (AGENT-05, CHAT-09) When the user clicks "Send to PM", a **handoff message** is inserted as a `system` role message with `message_type: "handoff"`. The `ChatMessage` component renders a `ChatHandoffIndicator`. ``` ┌───────────────────────────────────────────────┐ │ ── Brainstormer → PM: spec handed off ── │ ← separator-style indicator └───────────────────────────────────────────────┘ ``` - Container: `flex items-center gap-3 py-2 text-[13px] text-muted-foreground` - Left and right: `
` — lines flanking the label - Center label: `whitespace-nowrap` — "Brainstormer → PM" + brief description (see Copywriting) - Arrow character: `→` unicode, not a Lucide icon — matches the simple prose style - No background, no border-radius — this is a separator, not a card ### Task Created Notification Layout (AGENT-03, AGENT-06) When the PM agent creates Nexus issues from the spec, a `system` role message with `message_type: "task_created"` appears. The `ChatMessage` component renders a `ChatTaskCreatedBadge`. ``` [ #123 Issue title text → View task ] ``` - Container: `inline-flex items-center gap-2 rounded-md border border-border bg-card px-3 py-1 text-[13px]` - Issue ID badge: `text-[11px] font-semibold text-muted-foreground` — e.g. "T-123" - Issue title: `text-[13px] text-foreground` - "View task" link: `text-primary underline-offset-2 hover:underline` — navigates to the issue detail page - Multiple tasks from one spec: render one `ChatTaskCreatedBadge` per task, stacked vertically with `gap-2` wrapper ### Status Update Notification Layout (AGENT-07) When an Engineer or Generalist completes a task, a `system` role message with `message_type: "status_update"` appears. The `ChatMessage` component renders a `ChatStatusUpdateBadge`. ``` [ ✓ Engineer completed T-123: Issue title ] ``` - Container: `inline-flex items-center gap-2 rounded-md border border-border bg-card px-3 py-1 text-[13px]` - Icon: `CheckCircle2` (lucide), 14×14px, `text-green-500 dark:text-green-400` — indicates completion - Text: `text-[13px] text-foreground` — agent name + action + task reference - Task reference: `text-primary underline-offset-2 hover:underline` — link to issue detail --- ## Spacing Scale Inherited from Phase 21 and Phase 22. No new tokens for Phase 23. | Token | Value | Phase 23 Usage | |-------|-------|----------------| | xs | 4px | Section label letter-spacing, gap within inline badges | | sm | 8px | Action button gap in spec card row (`gap-2`), badge padding | | md | 16px | Spec card padding (`p-4`) | | lg | 24px | (no new usage) | | xl | 32px | (no new usage) | **New spacing values (Phase 23 only):** - Spec card section vertical rhythm: `space-y-4` (16px) — between What/Why/Constraints/Success blocks - Spec card action row top: `pt-4` (16px) — from content to action row border - Task badge height: `py-1` (6px top/bottom) — compact inline badge - Handoff indicator vertical: `py-2` (8px) — matches section separator rhythm --- ## Typography All inherited from Phase 21 and 22. No new type tokens for Phase 23. | Role | Size | Weight | Line Height | Usage | |------|------|--------|-------------|-------| | Body / message text | 15px (0.9375rem) | 400 | 1.6 | Spec card content, chat message prose (unchanged) | | Label / UI chrome | 13px (0.8125rem) | 400 | 1.4 | Task badge text, handoff indicator label, agent selector (unchanged) | | Spec section label | 11px (0.6875rem) | 600 | 1.4 | "What", "Why", "Constraints", "Success" labels in spec card | | Message timestamp | 11px (0.6875rem) | 400 | 1.4 | Identity bar timestamps (Phase 22, unchanged) | **Weights used:** 400 (regular) and 600 (semibold). No additional weights. Same constraint as Phase 21/22. **Spec section label note:** The 11px / 600 uppercase-tracked label pattern matches the existing `text-[11px] text-muted-foreground` timestamp pattern from Phase 22. The semibold weight at 11px + `uppercase tracking-wide` provides adequate differentiation from surrounding 15px prose. No new weight is introduced. --- ## Color All values inherited from Phase 21 CSS variable system. No new color variables introduced. | Role | Catppuccin Mocha | Tokyo Night | Catppuccin Latte | Phase 23 Usage | |------|-----------------|-------------|-----------------|----------------| | Dominant (60%) | `--background` #1e1e2e | `--background` #1a1b26 | `--background` #eff1f5 | Unchanged | | Secondary (30%) | `--card` #181825 | `--card` #16161e | `--card` #e6e9ef | Spec card background, task badge background, status badge background | | Accent (10%) | `--accent` #45475a | `--accent` #3b4261 | `--accent` #bcc0cc | Hovered rows (unchanged) | | Primary | `--primary` | `--primary` | `--primary` | "Send to PM" button, task/status reference links | | Destructive | `--destructive` | `--destructive` | `--destructive` | Not used in Phase 23 | | Muted text | `--muted-foreground` | `--muted-foreground` | `--muted-foreground` | Handoff indicator label, spec section labels, task ID badges | **Accent reserved for (unchanged from Phase 22):** 1. Hovered conversation list row 2. Currently active/selected conversation row 3. Code block toolbar background on hover 4. Input focus-within ring 5. Slash command popover highlighted item **Task completion check icon:** `text-green-500 dark:text-green-400` — same Tailwind semantic color pattern as Phase 22 agent role colors. Sufficient contrast in all three themes. **Brainstormer avatar color:** `text-slate-600 dark:text-slate-400` — mapped from `agentRoleColors["general"]` in the existing `agent-role-colors.ts` utility. No new color needed. **Spec card border:** `border-border` — resolves correctly via CSS variable in all three themes. --- ## Component Inventory New components to build in Phase 23: | Component | shadcn base | Notes | |-----------|-------------|-------| | `ChatSpecCard.tsx` | `button`, `card` | Spec fields (What/Why/Constraints/Success) + action row; rendered inside `ChatMessage` when `messageType === "spec_card"` | | `ChatHandoffIndicator.tsx` | none | Separator-style indicator; `flex items-center gap-3` with flanking `
` elements | | `ChatTaskCreatedBadge.tsx` | none | Inline badge for a single created task; receives `taskId`, `taskTitle`, `taskUrl` props | | `ChatStatusUpdateBadge.tsx` | none | Inline badge for task completion; receives `agentName`, `taskId`, `taskTitle`, `taskUrl` props | | `useBrainstormerDefault.ts` | none | Hook: queries workspace agents, returns the `general` role agent ID for auto-selection on new conversations | **Existing components to modify:** | Component | Change | |-----------|--------| | `ChatMessage.tsx` | Add rendering branch for `messageType` prop: `"spec_card"` → `ChatSpecCard`, `"handoff"` → `ChatHandoffIndicator`, `"task_created"` → `ChatTaskCreatedBadge`, `"status_update"` → `ChatStatusUpdateBadge`, `null` → existing markdown/bubble rendering | | `ChatPanel.tsx` | Wire `useBrainstormerDefault` to set `activeAgentId` when `activeConversationId === null` and `activeAgentId === null` | **DB migration component:** - `server/src/db/migrations/XXXX_add_message_type.ts` — adds `message_type text` nullable column to `chat_messages` table **Icons (lucide-react) — Phase 23 additions:** - `CheckCircle2` — task completion status badge - `Brain` — recommended default icon for the Brainstormer agent (user configures, but `brain` is a valid `AGENT_ICON_NAME`) **All icons from Phase 21 and Phase 22 remain unchanged.** --- ## Interaction Contract ### Brainstormer Default Agent (AGENT-01) | Interaction | Behavior | |-------------|---------| | User opens new conversation (no messages) | `useBrainstormerDefault` resolves `general` role agent; `ChatAgentSelector` reflects that agent immediately | | User changes agent mid-flow | Normal agent selector behavior (Phase 22); no lock-in to Brainstormer | | No `general` agent in workspace | Fall back to first agent alphabetically; no error state; log warning to console | ### Structured Questioning Flow (AGENT-02) The Brainstormer agent's structured questioning flow is entirely **server-side** (system prompt + LLM). The UI has no state machine for question steps — it renders the agent's streamed responses normally via the existing `ChatMessage` + `ChatMarkdownMessage` pipeline. The spec card is produced when the LLM outputs a message with `message_type: "spec_card"` and a structured JSON body in `content`. The server parses this and stores it as a `system` role message. The UI detects `messageType === "spec_card"` and renders `ChatSpecCard`. | Interaction | Behavior | |-------------|---------| | Brainstormer streams a clarifying question | Standard streaming rendering (Phase 22 pipeline); no special UI | | User answers a question | Standard message send; no special UI | | Brainstormer produces spec card | `message_type: "spec_card"` message appears; `ChatSpecCard` renders inline in message thread | ### Spec Card Actions (AGENT-02) | Interaction | Behavior | |-------------|---------| | Click "Send to PM" | Optimistic: spec card action buttons disabled immediately; `ChatHandoffIndicator` appended to thread; POST to `/api/conversations/:id/handoff` with spec content and `targetRole: "pm"` | | Click "Edit" | Spec card enters edit mode: each field (What/Why/Constraints/Success) becomes an editable `