Elnor Repo Reader

CHAT_PANEL_COMPREHENSIVE_REFERENCE_FOR_WORKSPACE_INTEGRATION.md

Design Mockups/Archived Mockups/DOC20 Mockups and Design/DOC20 Current Mockups/CHAT_PANEL_COMPREHENSIVE_REFERENCE_FOR_WORKSPACE_INTEGRATION.md

Short text page c397aa4d8cc0. Generated 2026-06-09T01:23:58.539Z from commit dbaa25962edc11ab30e8d4ca1715f9ae5bf77331. Worktree: clean.

Open readable HTML page · Open raw txt · Open path URL

ELNOR REPO READER TEXT MIRROR
Original path: Design Mockups/Archived Mockups/DOC20 Mockups and Design/DOC20 Current Mockups/CHAT_PANEL_COMPREHENSIVE_REFERENCE_FOR_WORKSPACE_INTEGRATION.md
Source repo: /Users/OpenClaw1/Elnor/Elnor Specs
Git branch: main
Git commit: dbaa25962edc11ab30e8d4ca1715f9ae5bf77331
Generated: 2026-06-09T01:23:58.539Z

---

# Right Chat Panel — Comprehensive Reference for Workspace Integration

**Purpose:** This document captures EVERYTHING about the current chat panel implementation so it can be integrated into the Q Unified Workspace mockup (V7.3). Hand this to the other Claude window along with the workspace mockup JSX.

**Integration target:** The chat panel renders as a 320px column at the app's far-right edge, toggled by the bottom icon on the left nav rail. It is INDEPENDENT of the Ask Agent panel (which opens within the workspace content area).

---

## 1. LAYOUT STRUCTURE

The right chat panel is a vertical column with these zones from top to bottom:

```
┌─────────────────────────────────┐
│  TAB BAR (horizontal scroll)    │  ← Conversation tabs
├─────────────────────────────────┤
│  HEADER BAR                     │  ← Model badge, search, options, controls
├─────────────────────────────────┤
│  AGENT/MODEL PICKER ROW         │  ← Agent selector, model, think level, multi-agent chips
├─────────────────────────────────┤
│                                 │
│  MESSAGE AREA (scrollable)      │  ← Messages with markdown rendering
│                                 │
│                                 │
├─────────────────────────────────┤
│  REPLY QUOTE BLOCK (if active)  │  ← Quoted message with remove button
├─────────────────────────────────┤
│  ATTACHMENT PILLS (if any)      │  ← File attachment badges
├─────────────────────────────────┤
│  INPUT TOOLBAR ROW              │  ← Attachment, memory, autonumber, mic, TTS
├─────────────────────────────────┤
│  TEXTAREA + SEND                │  ← Multi-line input with send button
└─────────────────────────────────┘
```

**Width:** 320px fixed (per DOC20 §6.20.17)
**Background:** `c.bgChat` (dark, slightly different from main bg)
**Toggle:** Left nav rail bottom icon (chat bubble icon, ⌘+Shift+C or similar)
**Border:** 1px left border `c.borderLight`

---

## 2. TAB BAR (Conversation Tabs)

Horizontal scrollable row of conversation tabs. Each tab is a small pill.

**Tab structure:**
```jsx
{ id: string, label: string, pinned: boolean }
```

**Default tab:** `{ id: "gen", label: "General Chat", pinned: true }` — always present, cannot be closed.

**Tab behavior:**
- Click → switch active conversation
- Double-click → open rename modal
- Middle-click or X button → close tab (if not pinned and not the last tab)
- Pin icon toggle → pin/unpin

**Tab appearance:**
- Active: `bg: c.bgPanel`, `color: c.textPri`, bottom 2px accent border
- Inactive: `bg: transparent`, `color: c.textSec`
- Pinned: small pin icon before label
- Max visible: ~4 tabs, then horizontal scroll with overflow hidden

**Split view:** A button in the header can enable split-pane mode, showing two conversations side by side with a 3px resizable divider between them.

---

## 3. HEADER BAR

A single row below the tabs with controls. Background: `c.bgPanelAlt`.

**Contents (left to right):**
1. **Tab label** — current conversation name, ellipsis on overflow, scrollable
2. **Model badge** — small pill showing selected model (e.g., "Gemini 2.5 Pro") or "auto"
3. **"Session Start" toggle** — button to toggle session context injection
4. **Multi-Copy button** — opens dropdown menu:
   - "Copy last N messages" with count input
   - "Select messages to copy" → enters checkbox selection mode
5. **Search button** (magnifying glass icon) — toggles search bar
6. **More options button** (three dots) — opens chat options modal (mute, clear, export, pin, archive)

**Search bar (when active):**
- Absolute positioned below header
- Input field: "Search messages..."
- Navigation: Previous (left chevron), Next (right chevron), Close (X)
- Display: "3/12" match count
- Keyboard: Escape closes, Enter/Shift+Enter navigates
- Match highlighting: yellow background `c.accentLight`, current match with 2px blue outline

---

## 4. AGENT/MODEL PICKER ROW

A wrapping row below the header with agent configuration.

**Contents:**
1. **Primary agent dropdown** — select from available agents (Elnor, Nova, Prism, Atlas, Sage, etc.)
2. **Model dropdown** — select specific model or "auto" for system default
3. **Think level toggle** — cycles through: off → minimal → low → medium → high → xhigh. Shows current level as text badge.
4. **Multi-agent chips** — when multiple agents are active, each secondary agent shows as a chip with:
   - Agent name
   - Mute toggle (bell icon)
   - Model picker (three dots → dropdown)
   - Remove button (X)
5. **Add Agent button** — "+" to add another agent to the conversation
6. **Incognito toggle** — eye-slash icon, toggles private mode for this conversation

---

## 5. MESSAGE AREA

Scrollable area showing conversation messages. No virtual scrolling — uses pagination.

**Pagination:**
- Constant: `CHAT_RENDER_PAGE_SIZE = 40`
- "Show older messages" button at top when more messages exist
- Auto-scrolls to bottom on new messages

### 5.1 Message Row Layout

Each message is a horizontal flex row:

```
┌─────────────────────────────────────────┐
│ [Avatar 26px]  Name  ·  12:34 PM        │
│                                         │
│   [Optional: Degraded feature warning]  │
│   [Optional: Freshness badge]           │
│                                         │
│   Message body (markdown rendered)      │
│                                         │
│   [Optional: Document attachment]       │
│                                         │
│   [Hover: Copy | Reply buttons]         │
└─────────────────────────────────────────┘
```

**Avatar:** 26px circle, left-aligned. Right-click opens avatar customization menu (color picker, icon picker).

**Name header:** Agent/user name (bold), followed by "·" separator, then timestamp (textTer color, smaller font).

**Multi-copy checkbox mode:** When active, a checkbox appears left of each message. Selected messages get a highlight. Action bar shows "Copy Selected" and "Cancel".

### 5.2 Markdown Rendering

Uses a dedicated `<MarkdownRenderer>` component (memo-wrapped for performance).

**Libraries:** `react-markdown` + `remark-gfm` + `remark-breaks` + `rehype-highlight`

**Supported rendering:**
- **Code blocks** with language label badge (top-right), syntax highlighting, monospace font, dark background
- **Inline code** with subtle background
- **Tables** with striped rows (odd rows slightly lighter), cell padding, border
- **Task list checkboxes** (GFM checkboxes with accent color)
- **Blockquotes** with left border in accent color
- **Links** open in new tab (`target="_blank"`)
- **Images** constrained to `maxWidth: 100%`
- **Headings, bold, italic, lists** — standard markdown
- **Line breaks** preserved (remark-breaks)

**Link parsing:** Custom parser handles `[text](url)` links and `q://` protocol links (internal navigation). Results cached in `messageTokenCacheRef` (max 2500 entries).

### 5.3 Message Actions (Hover)

On hover over a message row, two small buttons appear (top-right of message, fade in):

1. **Copy** (clipboard icon, 12px) — copies message text to clipboard, shows "Copied" toast
2. **Reply** (chevron-right icon, 12px) — opens reply quote block in input area with first 120 chars

**Additional action component: `MessageTaskActionsBar`**
- Appears below assistant messages
- Actions: Save as Task, Convert to Chain, Learn From This, Upvote/Downvote feedback

### 5.4 Freshness Indicators (Assistant Messages)

Some assistant messages show a freshness badge below the name:
- **Stale** — warning color badge, "Stale" text
- **Verified** — accent color badge, "Verified" text with timestamp
- **Pending** — secondary color badge

Expandable details section shows: search usage, verification reasons, evidence refs. "Verify now" button triggers re-verification.

### 5.5 System Messages

Collapsible system messages (e.g., session start context, capability warnings). Click to expand/collapse. Muted styling (smaller font, textTer color, subtle background).

### 5.6 Thinking Indicator

When the agent is processing:
- Animated shimmer dots
- Shows: Agent name + model + "Thinking..." text
- Metadata: elapsed time (seconds), live cost accumulator
- **Stop button** (red) to cancel the in-progress response
- Auto-scrolls to keep visible

### 5.7 Text Selection Popup

When user selects text within a message:
- Small popup appears above selection
- Action: "Reply to this" — quotes selected text in the reply block

### 5.8 Document Attachments in Messages

Messages with attachments show a document preview card:
- DOCX badge (blue background)
- Filename + file size
- Actions: Download, Share, Copy

---

## 6. REPLY QUOTE BLOCK

When the user clicks Reply on a message, a quote block appears above the input area:

```
┌─ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ─┐
│ 3px accent left border          │
│ "First 120 chars of message..." │
│ — Author name · 12:34 PM    [X]│
└─ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ─┘
```

- Left border: 3px solid `c.accent`
- Max text: first 120 characters, then "..."
- Remove button: X icon (top-right)
- On send: message is prepended with quoted context

---

## 7. ATTACHMENT AREA

When files are attached, they appear as horizontal pills above the input:

```
[📄 report.pdf (2.1 MB) ✕]  [📄 notes.docx (45 KB) ✕]
```

- Each pill: icon + filename + size + remove button (X)
- Multiple files supported
- Annotation `[Attached: filename (size)]` appended to sent message

---

## 8. INPUT TOOLBAR ROW

A row of icon buttons above the textarea:

| # | Icon | Action | Details |
|---|---|---|---|
| 1 | PlusCircle (18px) | Attach file | Opens native file picker, multiple files |
| 2 | Brain (16px) | Memory composer | Toggle panel to store facts to Memory (Core/Active/Archived tier selector + textarea) |
| 3 | ListOrd (16px) | Auto-numbering | Toggles auto-numbered list input mode. Enter continues number, empty line sends. |
| 4 | Mic (16px) | Voice input | Push-to-talk voice transcription |
| 5 | Sound (16px) | Text-to-speech | Reads last assistant message aloud |

---

## 9. TEXTAREA AND SEND BUTTON

**Textarea:**
- Placeholder: "Message Elnor..." (or agent name). When auto-numbering active: "1. Start typing a list..."
- Min height: 44px
- Rows: 2 (initial)
- Auto-grows with content (using requestAnimationFrame-based resize at ~70ms intervals)
- `spellCheck={false}`, `autoCorrect="off"`, `autoCapitalize="off"`
- Background: `c.bgPanel`, text color: `c.textPri`

**Keyboard shortcuts:**
- `Enter` → Send message
- `Shift+Enter` → New line
- Auto-numbering mode: `Enter` on empty numbered line sends the list

**Send button:**
- Size: 28x28px circle
- Background: `c.accentBtn` (blue)
- Icon: ArrowUp (14px, white)
- Border radius: full circle
- Positioned: bottom-right of input area

---

## 10. SIDEBAR CHAT ORGANIZATION (Nav Tab Integration)

In the DOC20 Unified Workspace, the Browser column's Nav tab shows conversations:

**Conversation groups:**
1. **General Chat** — always at top, pinned
2. **Starred Chats** — collapsible, max 4 shown
3. **Projects** — grouped by project name, collapsible tree
4. **Recent Chats** — collapsible, max 4 shown

**Chat item row:** Color dot + name + preview text snippet + timestamp
- Single click: Opens in chat column
- Double click: Rename
- Context menu: Star, Archive, Rename

---

## 11. SPLIT VIEW

Two conversations side-by-side within the chat column:

- Toggle: Button in header for split view
- Layout: Two `renderChatPane()` instances with different tabIds
- Divider: 3px wide, `c.border` color, `cursor: col-resize`
- Both panes independently scrollable with their own messages, input, and controls

---

## 12. CHAT OPTIONS MODAL

Accessible from the three-dots menu in the header:

- Mute notifications
- Clear history
- Export transcript
- Pin chat
- Archive

---

## 13. API ENDPOINTS

| Method | Endpoint | Purpose |
|---|---|---|
| POST | `/api/chat/send` | Send chat message |
| POST | `/api/chat/teach` | Teach feature |
| POST | `/api/chat/golden-turn` | Golden turn routing |
| POST | `/api/chat/provider-status` | Model status check |
| POST | `/api/chat/model-policy` | Policy check |
| POST | `/api/freshness/verify-now` | Verify fact freshness |
| POST | `/api/learning/signal` | Learning signals (feedback, memory) |

---

## 14. MESSAGE DATA STRUCTURE

```typescript
interface ChatMessage {
  id: string;
  role: "user" | "assistant" | "system";
  text: string;
  time: string;                    // formatted display time
  message_id?: string;             // server-assigned
  client_message_id?: string;      // client-generated
  created_at?: string;             // ISO timestamp
  model?: string;                  // which model responded
  localOnly?: boolean;             // not yet synced to backend
  localConversationId?: string;
  freshness_meta?: FreshnessMeta | null;
  capability_watermark?: object;
  degraded_warning?: string;
  hasDoc?: boolean;                // has document attachment
  docName?: string;
  docSize?: string;
}
```

---

## 15. KEY CONSTANTS

```typescript
CHAT_RENDER_PAGE_SIZE = 40          // messages per page
CHAT_MAX_MESSAGES_TOTAL = 1600      // total message cap
CHAT_MAX_MESSAGES_PER_CONVERSATION = 220
CHAT_HISTORY_CACHE_KEY = "chatHistoryCache"  // localStorage key
```

---

## 16. COLOR TOKENS (from theme)

The chat panel uses these theme tokens:
- `c.bgChat` — chat background (slightly different from main bg)
- `c.bgPanel` — input/header backgrounds
- `c.bgPanelAlt` — alternate panel background
- `c.textPri` — primary text
- `c.textSec` — secondary text (timestamps, labels)
- `c.textTer` — tertiary text (muted elements)
- `c.accent` — accent color (links, active states, reply border)
- `c.accentBtn` — accent button (send button bg)
- `c.accentLight` — search highlight background
- `c.borderLight` — borders
- `c.warnText` — warning/stale badges

---

## 17. WORKSPACE INTEGRATION NOTES (for mockup builder)

**Position in workspace layout:**
```
[Nav Rail 44px] [Browser Column ~250px] [Main Content flex] [Ask Panel ~350px?] [Chat Column 320px]
```

- The chat column is the RIGHTMOST element in the app
- It is SEPARATE from the Ask Agent panel
- Both can be open simultaneously
- Chat column toggles independently via the bottom nav rail icon
- When collapsed, the main content area expands to fill the space
- The chat column has its own conversations, independent of the Ask panel's "Send in" selector

**What the workspace mockup already has (V7.3):**
- Left nav rail with 6 icons (the bottom one should be the chat toggle)
- Browser column with 4 modes
- Tab bar with content tabs
- Main content area
- Ask Agent panel (right panel within workspace)

**What needs to be added:**
- The 320px chat column at the far right edge
- With all the features described above
- The column should show a General Chat conversation by default
- The toggle animation should feel like a panel sliding in/out from the right

---

## 18. CRITICAL IMPLEMENTATION DETAILS

1. **The chat column is NOT the same as the Ask Agent panel.** Ask Agent (§6.20.19) is for asking about the current tab's content. The chat column is for general-purpose conversation.

2. **Conversation selector:** The chat column has a dropdown to switch between conversations, matching DOC20 §6.20.17's "chat selector: dropdown showing current conversation name with color dot."

3. **Per DOC20 §6.20.17 spec requirements:**
   - Width: 320px, collapsible
   - Header: "Chat" label with MsgCircle icon and close button
   - Chat selector dropdown with color dot
   - Messages: avatar (18px per spec, 26px in current impl — use 18px for workspace), author, time, body
   - Input: text input + send (accentBtn, Spark icon per spec)

4. **The current implementation has MORE features than the DOC20 spec defines.** The spec (§6.20.17) is minimal. The implementation includes: tabs, split view, multi-agent, search, multi-copy, memory composer, voice input, TTS, auto-numbering, freshness badges, attachment support, thinking indicator, and markdown rendering. All of these should be in the mockup.

5. **Message limits:** Max 220 messages per conversation, 1600 total across all conversations, 40 rendered at a time with pagination.

---

## 19. CONVERSATION BRANCHING

Branching lets the user fork a conversation at any message, creating a new independent conversation that inherits history up to the fork point. The original conversation continues unchanged. This keeps context clean when the user wants to explore a tangent, switch topics, or dig deep into a sub-issue without garbling the original thread.

### 19.1 Trigger

A **branch icon** (git-branch or split icon, 12px) appears on hover over any message, alongside the existing Copy and Reply buttons in the `MsgActions` component. Clicking it opens the Branch Modal.

The branch icon appears on ALL messages (user and assistant). Branching from a user message means "I want to continue from the question I asked." Branching from an assistant message means "I want to explore what Elnor just said further."

### 19.2 Branch Modal

A centered modal (400px wide) with the following fields:

```
┌─────────────────────────────────────────────────┐
│  Branch Conversation                        [X] │
├─────────────────────────────────────────────────┤
│                                                 │
│  Branching from message 28 of 43                │
│  ┌─────────────────────────────────────────┐    │
│  │ "Draft the Henderson opposition with…"  │    │
│  │ — Elnor · 2:34 PM                       │    │
│  └─────────────────────────────────────────┘    │
│                                                 │
│  Branch name                                    │
│  ┌─────────────────────────────────────────┐    │
│  │ Henderson spec — confidence model       │    │
│  └─────────────────────────────────────────┘    │
│  Auto-generated from last few messages.         │
│  Editable.                                      │
│                                                 │
│  ── History ──────────────────────────────────   │
│                                                 │
│  ○ Full history (messages 1–28)                 │
│    All context preserved. Best for short        │
│    conversations.                               │
│                                                 │
│  ○ Summary + recent messages                    │
│    Summarize older messages, keep recent         │
│    verbatim. Best for long conversations.       │
│                                                 │
│    Recent messages to keep:                     │
│    ┌──────┐                                     │
│    │  10  │  ← number input, default 10,        │
│    └──────┘    min 3, max N (branch point)       │
│                                                 │
│  ── Agent ────────────────────────────────────   │
│                                                 │
│  Agent: [▾ Elnor          ]  ← dropdown,        │
│                               defaults to        │
│                               current agent      │
│                                                 │
│  Model: [▾ Same as parent ]  ← dropdown,        │
│                               "Same as parent"   │
│                               or specific model  │
│                                                 │
│  Think level: [▾ Same as parent ]               │
│                                                 │
│                                                 │
│              [Cancel]  [Create Branch]           │
│                                                 │
└─────────────────────────────────────────────────┘
```

### 19.3 Modal Field Details

**Branch name:**
- Auto-generated by taking the last 2-3 messages and producing a short descriptive label. Format: "{parent_name} — {topic}" (e.g., "Henderson spec — confidence model").
- Editable text input, max 80 characters.
- If the user clears it, falls back to "{parent_name} (branch)".

**History mode — radio selection:**

| Mode | What happens | When to use |
|---|---|---|
| **Full history** (default for conversations ≤ 50 messages) | Messages 1 through N copied verbatim into the new conversation. The LLM sees the complete thread on the next turn. | Short-to-medium conversations where full context matters. |
| **Summary + recent** (default for conversations > 50 messages) | EC calls the LLM to summarize messages 1 through (N minus recent_count) into a single system message. Messages (N minus recent_count + 1) through N are copied verbatim. The summary becomes the first message in the branch (role: "system", tagged as branch summary). | Long conversations where full copy would consume too much context window. |

**Recent messages count:**
- Only visible when "Summary + recent" is selected.
- Number input, default: 10. Min: 3. Max: the branch point index N.
- Stepping: increment/decrement by 1.

**Agent selector:**
- Dropdown listing all available agents (Elnor, Nova, Prism, Atlas, Sage, custom agents).
- Default: same agent as the parent conversation.
- Changing the agent changes who responds in the branch. The copied history still shows the original agent's name on old messages.

**Model selector:**
- Dropdown: "Same as parent" (default), or any specific model.
- "Same as parent" inherits `chatMetaByConversation[parentId].model`.

**Think level selector:**
- Dropdown: "Same as parent" (default), off, minimal, low, medium, high, xhigh.

### 19.4 What Happens on "Create Branch"

1. **EC creates a new conversation** with a new UUID.

2. **History is populated** based on the selected mode:
   - **Full history:** Messages 1-N are bulk-inserted into the new conversation. Each copied message retains its original `role`, `text`, `time`, `model`, `freshness_meta`, and attachments. The `message_id` is regenerated (new IDs for the copies). A `copied_from` field links each copied message to its original for provenance.
   - **Summary + recent:** EC dispatches a summarization call to the configured model. The summary is inserted as the first message:
     ```typescript
     {
       role: "system",
       text: "Branch summary of prior conversation:\n\n{summary_text}",
       branch_summary: true,  // flag for rendering
       summarized_message_count: N - recent_count,
       source_conversation_id: parentConversationId
     }
     ```
     Then messages (N - recent_count + 1) through N are copied verbatim.

3. **Branch metadata is stored:**
   ```typescript
   // On the new conversation
   {
     branched_from: {
       conversation_id: string,      // parent conversation ID
       message_index: number,        // which message was the fork point (1-indexed)
       message_id: string,           // the specific message ID forked from
       branch_mode: "full" | "summary_recent",
       recent_count: number | null,  // only for summary_recent
       created_at: string            // ISO timestamp
     }
   }
   ```

4. **Parent conversation is annotated:**
   - The message at the fork point gets a `branches` array appended to it:
     ```typescript
     {
       branches: [
         {
           branch_conversation_id: string,
           branch_name: string,
           created_at: string
         }
       ]
     }
     ```
   - The message row in the parent conversation renders a small branch indicator below the message: a subtle git-branch icon with the branch name as a clickable link.

5. **Agent/model config is set:**
   ```typescript
   chatMetaByConversation[newConversationId] = {
     model: selectedModel === "same_as_parent" ? parentMeta.model : selectedModel,
     think_level: selectedThinkLevel === "same_as_parent" ? parentMeta.think_level : selectedThinkLevel,
     agent: selectedAgent,  // may differ from parent
     title: branchName
   }
   ```

6. **A new tab opens** in the chat column for the branch conversation. The tab label shows the branch name. The tab is auto-activated (switches to the new branch). The parent tab remains open.

7. **Backend persistence:**
   - `POST /api/chats` creates the new conversation.
   - `POST /api/chats/:id/messages/bulk` inserts the copied messages.
   - `PATCH /api/chats/:parentId/messages/:messageId` annotates the parent message with the branch link.
   - `persistChatMeta()` saves the branch metadata and agent/model config.

### 19.5 Branch Indicator on Parent Messages

When a message has been branched from, a small visual indicator appears below the message content:

```
┌────────────────────────────────────────────┐
│ [Elnor avatar]  Elnor  ·  2:34 PM          │
│                                            │
│ "Here's my analysis of the confidence      │
│  model for procedures..."                  │
│                                            │
│ ─── ⑂ Henderson spec — confidence model    │  ← branch indicator
│     ⑂ Henderson spec — app volatility      │  ← second branch (if exists)
└────────────────────────────────────────────┘
```

- Icon: git-branch (⑂), 11px, `c.textTer` color
- Branch name: clickable link, `c.accent` color, 11px
- Clicking the branch name switches to that branch's tab (opens it if not already open)
- Multiple branches from the same message stack vertically
- Max visible: 3 branches inline, then "+N more" with expand

### 19.6 Branch Summary Message Rendering

When a branch was created with "Summary + recent" mode, the first message in the branch is a system message with special rendering:

```
┌────────────────────────────────────────────┐
│ ⑂  Branch summary (28 messages summarized) │
│ ┌────────────────────────────────────────┐ │
│ │ The conversation covered Henderson v.  │ │
│ │ City of LA opposition strategy. Key    │ │
│ │ points discussed: loss causation       │ │
│ │ theory, Judge Chen's prior rulings,    │ │
│ │ expert report deadlines...             │ │
│ └────────────────────────────────────────┘ │
│ [View original conversation →]             │
└────────────────────────────────────────────┘
```

- Collapsible (click to expand/collapse the summary text)
- Muted styling: `c.textSec`, slightly smaller font, subtle background
- "View original conversation" link opens the parent conversation tab
- The summary is followed by the verbatim copied recent messages

### 19.7 Branch Navigation

**From branch → parent:**
- The branch's tab header shows a small "⑂ from {parent_name}" subtitle below the branch name
- Clicking it opens the parent conversation, scrolled to the fork point message

**From parent → branch:**
- Branch indicators on the fork point message (§19.5) are clickable links

**In the Nav tab / Chats management page:**
- Branches appear as indented children under their parent conversation
- Branch icon (⑂) before the name distinguishes them from top-level conversations
- Branches inherit the parent's star/project association by default

### 19.8 Constraints and Limits

- **Max branch depth:** 3 levels (a branch of a branch of a branch). Beyond that, the "Branch" icon still appears but the modal shows a note: "Max branch depth reached. This will create a top-level conversation with copied history instead of a nested branch."
- **Max branches per message:** No hard limit. UI shows first 3 inline, "+N more" for additional.
- **Summary LLM call:** Uses the same model as the parent conversation. If the model is unavailable, falls back to the system default. Summary target: 500-800 tokens covering key topics, decisions, and open questions.
- **Branch conversations are full conversations.** They can be starred, archived, renamed, assigned to projects, or branched again (up to depth limit). They are not second-class objects.
- **Deleting a parent conversation:** Branches become orphaned top-level conversations. The `branched_from` metadata is preserved but the "View original" link shows "Original conversation deleted."
- **Merging branches back:** Not supported in V1. If the user wants to bring branch insights back to the parent, they copy/paste or reference. This is a future capability.

### 19.9 Keyboard Shortcut

- `Cmd+Shift+B` with a message selected (or cursor in the message area) opens the Branch Modal for the most recent assistant message.
- No shortcut for branching from a specific older message — use the hover icon.

### 19.10 Schema Additions

```typescript
// Addition to conversation metadata
interface ConversationBranchMeta {
  branched_from?: {
    conversation_id: string;
    message_index: number;
    message_id: string;
    branch_mode: "full" | "summary_recent";
    recent_count: number | null;
    created_at: string;
  };
  branch_depth: number;  // 0 = top-level, 1 = branch, 2 = branch of branch
}

// Addition to message structure
interface BranchAnnotation {
  branch_conversation_id: string;
  branch_name: string;
  created_at: string;
}

// Extended message type
interface ChatMessage {
  // ... existing fields ...
  branches?: BranchAnnotation[];     // messages that were branched from this one
  branch_summary?: boolean;          // true if this is a generated branch summary
  summarized_message_count?: number; // how many messages were summarized
  source_conversation_id?: string;   // parent conversation ID (on summary messages)
  copied_from?: string;              // original message_id (on copied messages)
}
```

### 19.11 API Routes

| Method | Endpoint | Purpose |
|---|---|---|
| POST | `/api/chats/:parentId/branch` | Create branch conversation. Body: `{ message_index, branch_name, mode: "full" \| "summary_recent", recent_count?, agent_id?, model?, think_level? }`. Returns: `{ conversation_id, tab_label }`. |
| POST | `/api/chats/:id/messages/bulk` | Bulk insert copied messages into new conversation. |
| GET | `/api/chats/:id/branches` | List all branches of a conversation (for Nav tab tree rendering). |

### 19.12 DOC20 Cross-Reference

This feature integrates with DOC20 §6.20.17 (Right chat column) and §6.20.18 (Chats management page). Branches appear in the Chats page as indented children. The Nav tab's conversation list shows branch relationships. The chat column's tab bar accommodates branch tabs with the same UX as regular conversation tabs.