Cockpit Inbox Design
Cockpit Inbox Design Date: 2026 04 27 Status: Approved Branch: feature/marketing agents Overview Replace the "Exec Inbox" section in the cockpit right sidebar with a nav level inbox badge and a 40% width slide in drawer. The drawer provides a two pane interface for reading messages, approving exec gates, replying to agents, and composing ad hoc messages to a...
Date: 2026-04-27 Status: Approved Branch: feature/marketing-agents
---
Replace the "Exec Inbox" section in the cockpit right sidebar with a nav-level inbox badge and a 40%-width slide-in drawer. The drawer provides a two-pane interface for reading messages, approving exec gates, replying to agents, and composing ad hoc messages to any agent.
---
A ✉ N badge is added to the nav bar between the "testnet" badge and the clock.
- Count = unread
inboxrows whereto_agent = 'justin'andprocessed = false+agent_tasksrows whererole = 'exec'andstatus = 'assigned' - Badge pulses amber when count > 0
- Clicking the badge toggles the drawer open/closed
- Badge shows
is-openstyling when drawer is open - The existing "Exec Inbox" label and container in the right sidebar are removed
---
- Width: 40% of viewport
- Position: Fixed to the right edge, full height below the nav
- Behavior: Slides in with a 200ms ease transition; clicking the overlay or pressing Escape closes it
- Border: Left edge uses
--color-accentto signal it is an interactive layer above the cockpit - A semi-transparent overlay covers the rest of the cockpit when the drawer is open (does not block interaction — just visual depth)
``
✉ Inbox · N unread [+ Compose] [✕]
``
- Title shows live unread count
+ Composebutton opens the compose form in the right pane; it gets anis-activestyle while compose is open✕closes the drawer
---
The drawer body is split into two columns:
| Column | Width | Content | |--------|-------|---------| | Message list | 38% | Scrollable list of all inbox items | | Detail pane | 62% | Selected message body + action area |
Messages are ordered: exec gate tasks first (green), then unread inbox messages by created_at desc, then read/processed messages dimmed at the bottom.
- From agent name (amber for regular; green for exec gates) + unread dot if unprocessed
- Subject (truncated to one line)
- Meta:
message_type · ref_id · time ago
Clicking an item selects it (amber border) and loads it in the detail pane. Read messages are dimmed (opacity 0.55).
- From → To header
message_type · ref_id · timestamp- Subject line
- Full message body (scrollable)
- HashScan link for the ref topic_id
- Action area pinned to the bottom (see below)
---
Action area shows two buttons:
- Posts
{ type: 'task.complete', task_id: topicId, agent: 'justin', output: 'Approved via cockpit' }to the task'stopic_idviaPOST /post-hcs-message - Button changes to
✓ Approved(green) on success - Re-renders the message list after 2 seconds
- Clicking Block expands a reason text input inline (replaces the button row)
- User types a reason; a
Confirm Blockbutton posts{ type: 'task.blocked', task_id: topicId, agent: 'justin', error_message: reason }to the task'stopic_idvia HCS - Cancel collapses back to Approve/Block buttons
Action area shows a reply textarea:
``
Reply to <agent>
[textarea — placeholder: "Type your reply…"]
sends as justin → <agent> via HCS [Dismiss] [Send]
``
- Looks up the sender agent's
inbound_topic_idfromagent_definitions - Posts
{ type: 'inbox.message', from: 'justin', to: senderAgent, subject: 'Re: ' + originalSubject, body: replyText, ref_id: originalRefId, ref_type: originalRefType }viaPOST /post-hcs-message - Listener picks up the HCS message and writes it to the
inboxtable - On success: textarea clears, message item dims (marked read)
- Patches
inboxrowprocessed = truedirectly via Supabase REST (no HCS needed — just clears the unread state) - Message dims in the list; badge count decrements
---
Clicking + Compose replaces the detail pane with a compose form. Cancelling returns to the previously selected message.
Fields:
| Field | Type | Options |
|-------|------|---------|
| To | Dropdown | All agents from AGENT_DEPT map |
| Type | Dropdown | question, feedback, fyi, decision.needed, review.request |
| Subject | Text input | One-line summary |
| Message | Textarea | Full message body |
- Looks up the selected agent's
inbound_topic_idfromagent_definitions - Posts
{ type: 'inbox.message', from: 'justin', to: selectedAgent, message_type: selectedType, subject, body }viaPOST /post-hcs-message - Listener writes to
inboxtable on receipt - On success: compose form clears, drawer shows empty detail pane with "Message sent" confirmation
Cancel — returns to previously selected message (or empty detail if none was selected)
---
```js // Inbox messages sb.from('inbox') .select('id, from_agent, message_type, subject, payload, ref_id, ref_type, priority, processed, created_at') .eq('to_agent', 'justin') .order('created_at', { ascending: false }) .limit(50)
// Exec gate tasks sb.from('agent_tasks') .select('topic_id, brief, project_id, created_at') .eq('role', 'exec') .eq('status', 'assigned') .order('created_at', { ascending: true }) ```