diff --git a/.planning/phases/23-brainstormer-flow/23-UI-SPEC.md b/.planning/phases/23-brainstormer-flow/23-UI-SPEC.md new file mode 100644 index 00000000..baedd2f0 --- /dev/null +++ b/.planning/phases/23-brainstormer-flow/23-UI-SPEC.md @@ -0,0 +1,422 @@ +--- +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-3` (12px gaps) +- Action row: `flex gap-2 pt-3 border-t border-border mt-3` — 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.5 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.5 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-3` (12px) — between What/Why/Constraints/Success blocks +- Spec card action row top: `pt-3` (12px) — from content to action row border +- Task badge height: `py-1.5` (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 `