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...
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...
No explicit evidence field yet. Require tests, screenshots, linked PRs, or reviewed outputs before marking complete.
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 }) ```