Feature docs

Inbox

RELEASED

The conversation-led view of Contacts. One place to triage the thread list, read the full activity feed, reply across every channel, and see who you are talking to — without opening a second tab.

The Inbox exists to kill the context-switching between list, timeline and compose. It is the first real View; the others follow it. The feed inside it is the same feed as the customer profile, repackaged rather than forked, so a message looks and behaves identically wherever you read it.

Two failures it is deliberately built to prevent: missing an incoming message, and a human and DAISI replying to the same customer at the same time.

Rulings ledger

DateRuling
08-06Nothing is pre-selected when the Inbox opens — the detail side holds an empty select-a-customer state until a row is chosen, so the first thing a rep reads is their own triage decision, not an arbitrary thread.
08-06The unread badge counts incoming call, SMS and email only — logs and other non-incoming types never count, because the badge answers "who is waiting on me", not "what happened".
08-06The unread dot is visually distinct from the customer-status colors — two signals that mean different things must never be read as one.
08-06The row timestamp is the last call, text or email in either direction — not the last activity of any kind, so a system update never makes a cold thread look warm.
08-06The row shows a generalized actor — Customer, Dealer, DAISI or Automation rather than a proper name, because at list density the class of sender is what triages the row.
08-06The mobile row opens a quick view inside the Sales tab (now CRM) — only View Customer leaves for the full profile, keeping the triage loop intact on a phone.
08-06Customer Details opens by default on desktop when width allows, and is a closed drawer on mobile — context is free where there is room and on demand where there is not.
08-06Task creation is not in this composer — tasks live in the Agenda flow; the composer sends messages.
08-06Switching DAISI from Agent to Assistant or Off cancels the autoresponder and any active run — the anti-double-talk rule, and the reason the control exists at all.
08-06When an Assistant pause expires the autoresponder wakes again — a pause is a pause, not a silent mode change.
08-06Every outbound path respects the customer's opt-out flags — DAISI Agent mode does not bypass them.
08-06Vehicle of interest is the primary deal, defined as the most recently updated deal — one rule, so the panel and the row never disagree.
09-02Opening a conversation marks it read (the mail-client model), and unread stays dealership-wide — one shared timestamp on the customer; the first opener clears it for the whole team, no per-user tracking.
09-02View Customer lands on the customer's activity feed, not the profile — the customer name in the conversation header performs the same action; the vehicle/deal reference opens the deal; collapsed details sections toggle from the whole header row.
09-02The customer Activity section adopts the Inbox pattern — canonical screen: comp-activity-feed-shell.html. The activity filter strip never hides on scroll; the fade-out treatment is retired.
09-02DAISI Mode menu cleanup — equal row anatomy specced on the atom, Reset-to-Default retired for an X close, pause options visible in all modes, enabled only in Agent (a pause = a timed demotion to Assistant that auto-reverts), and the light-mode yellow ruling: dark ink on any yellow fill (≈10.2:1 AAA vs white's ≈1.5:1 fail).
09-02Email subject is required on send — the composer draws the Subject row already; validation blocks a subject-less send.
10-08Scheduled messages return to the composer (CPO) — a caret beside send on Text and Email; the scheduling logic is unchanged.
10-09The Schedule message menu follows the time of day (CPO) — the same every day of the week, with Tomorrow always offered; dealers are always on the clock.

Anatomy map

Conversation rowThe list row — actor, snippet, status, unread semantics. Desktop tri-paneViews + list + activity with the composer, and Customer Details. Mobile screenList, quick view, drawer details, half-sheet views. Activity feedEvery message, call and record state the feed renders. Activity header stripName, deals line, and the async next-step directive. Customer DetailsSummary, team, communications, next action, vehicle. Customer activity shellThe customer Activity section on the Inbox pattern — pinned filter strip, docked composer, details open. Composer + DAISIChannels, collapse, opt-out, Call mode, DAISI modes.

The conversation list

What a row carries, and how an unread thread announces itself.

Inbox — conversation list
Tamika Jefferson2
Customer
Is the 2023 BMW 530i still available for a test drive this weekend?
37 sec ago
Robert Cook
Customer
Sounds good — I'll see you Saturday at 11. Thanks for holding it for me.
2:14 PM
Berald Jones1
Customer
Missed call — no voicemail left
Yesterday
Marcus Webb
Automation
Service reminder: your lease ends in 45 days. Let's talk about your options.
Mon
Priya Anand
Sales
Congrats again on the Defender! I've emailed your finance paperwork over.
Jun 12
Nadia Sole3
Customer
Is the Rubicon still on the lot? Chatting from your site.
2 min ago
Wes Colby
DAISI
Thanks for reaching out! A specialist will be with you shortly.
18 min ago
R2 leading icon = last ACTIVITY/CHANNEL type (text=comment · call=phone · email=envelope), WHITE by default; a MISSED call is the only colored case (red phone-slash, e.g. Berald Jones). Actor word (Customer/Sales/Automation/DAISI) + direction arrow (incoming ↙ / outgoing ↗) follow. Independent axes: selected (row 2, gray-07 .is-selected) · unread (leading blue-01 dot + blue .sb-marker count) · fully-read. .sb-statusdd footer left (with caret) + time bottom-anchored right. Each row carries the customer name, the customer status pill, channel/actor-type iconography, a generalized actor — Customer, Dealer, DAISI or Automation, never a proper name — a snippet of the last relevant message, and a timestamp of the last call, text or email in either direction, anchored consistently in the row.
A blue dot marks an unread thread. The numeric badge counts unread incoming activities only — call, SMS and email — and excludes logs and every other non-incoming type. The unread dot is deliberately distinct from the customer-status color cues so the two are never confused. Read model (CPO ruling, 09-02 — the mail-client model). Opening a conversation marks it read. Unread is dealership-wide: one shared timestamp on the customer, so the first person to open the thread clears it for the whole team — there is no per-user read tracking.

The screens

The same feature at two densities. Desktop is a tri-pane — views, the conversation list, and the activity feed with the composer, plus Customer Details alongside when width allows. Mobile is progressive disclosure — the list first, then a quick view of the conversation, with details arriving as a drawer. Both are live, interactive screens; open them rather than reading a squashed copy here.

Desktop tri-paneViews + list + activity with the composer, and Customer Details. Mobile screenList, quick view, drawer details, half-sheet views.

The activity feed

The shared feed and the strip that sits above it.

1 · Message lifecycle — sent · received · collapsed↔expanded · scheduled · failed · canceled
Sent · outbound (pill right) — collapsed ("Show")
Karla Sellers@ 9:05 AM
Text SentSMSShow
Sent · same item — expanded ("Hide")
Karla Sellers@ 9:05 AM
Text SentSMSHide
Absolutely — I have Saturday at 11 open. Want me to hold it?
Received · inbound (pill left)
Lincoln Buyers@ 9:02 AM
Text ReceivedSMSHide
Is it still available for a test drive this weekend?
Scheduled · dashed + countdown chip ("Show")
Karla Sellers@ 9:00 AM
Email Scheduledon Jun 18 at 9:00 AM24h 20mShow
Failed · red dashed ("Show")
Karla Sellers@ 9:06 AM
Text FailedUndeliveredShow
Canceled · gray muted ("Show")
Karla Sellers@ 9:07 AM
Email CanceledScheduled send canceledShow
2 · Channels — color = channel (DAISI = actor, not a color)
Text · blue
Karla Sellers@ 9:05 AM
Text SentSMS
Want me to hold Saturday at 11 for a test drive?
Chat Received · inbound (pill left) · pink
Lincoln Buyers@ 9:41 AM
Chat ReceivedWebsite
Chat ReceivedFacebookShow
Is the Rubicon still on the lot?
Chat Sent · outbound (pill right) · pink
Karla Sellers@ 9:44 AM
Chat SentFacebook
It is — want me to hold it for you today?
Chat Sent · Instagram sub-channel
DAISI Auto Responder@ 9:46 AM
Chat SentInstagram
Thanks for reaching out! A specialist will be with you shortly.
CHAT-B · grouped transcript — per-actor grouping, AI/human authorship, and the handoff marker at the seam
Lincoln Buyers@ 9:41 AM
Chat ReceivedFacebookShow
Is the Rubicon still on the lot?
Chat ReceivedFacebookShow
The white one with the black wheels
Chat ReceivedFacebookShow
Can I come by today?
DAISI Auto Responder@ 9:41 AM
Chat SentFacebookShow
It is! It's still available.
Chat SentFacebookShow
A specialist can hold it — one moment.
Karla Sellers@ 9:43 AM
Chat SentFacebookShow
Hi Lincoln! Yes, come by at 11 and I'll have it up front.
DAISI Auto Responder@ 5:02 PM
Chat SentFacebookShow
Reminder: your appointment is tomorrow at 11:00 AM.
CHAT-E · anonymous → identified — the transcript that began before the customer existed
Website Visitor@ 8:41 AM
Chat ReceivedWebsiteShow
Do you still have the white Land Cruiser?
Chat ReceivedWebsiteShow
And what would payments look like?
DAISI Auto Responder@ 8:41 AM
Chat SentWebsiteShow
We do! I can pull exact numbers — what's the best number to text them to?
Website Visitor@ 8:49 AM
Chat ReceivedWebsiteShow
555-0192
Identified as Marcus Delgado — phone collected
DAISI Auto Responder@ 8:49 AM
Chat SentWebsiteShow
Thanks, Marcus! Sending those payment options now.
Email · purple
Karla Sellers@ 9:10 AM
Email SentHide
Your financing options
Attached are three pre-qualified payment plans.
Note · orange — internal (no direction)
Karla Sellers@ 9:12 AM
Internal NoteHide
Cross-shopping the Bronco — pull a trade quote before Saturday.
Log · indigo — manual event
Karla Sellers@ 9:14 AM
Call Logged05:00 PM
Left voicemail about the new Land Cruiser allocation.
DAISI as actor · Text (blue) — actor = "DAISI Auto Responder"
DAISI Auto Responder@ 9:16 AM
Text SentAuto
Just confirming your appointment tomorrow at 4:00 PM — reply C to confirm.
DAISI as actor · Email (purple)
DAISI Auto Responder@ 9:18 AM
Email SentAuto
Following up on the Land Cruiser
Saw you were looking — happy to answer any questions.
3 · Calls — audio player (play · scrubber · time · View Transcript)
Call Made · green · outbound ↗
Karla Sellers@ 9:20 AM
Call Made2:14Hide
Call Received by Karla Sellers · green · inbound ↙ (answering dealer named)
Lincoln Buyers@ 9:22 AM
Call Received by Karla Sellers2:38Hide
Call Missed · red · inbound ↙ (voicemail player)
Lincoln Buyers@ 9:24 AM
Call MissedVoicemailHide
Call In Progress · green (.sb-bubble--live · header-only)
Karla Sellers@ 9:26 AM
Call In Progress01:24
Call Failed · red dashed (no connection)
Karla Sellers@ 9:28 AM
Call FailedNo answer
4 · Record rows — neutral .sb-ind (status = bare colored text · edit = .sb-diff)
Deal Created · Fresh (orange text)
Karla Sellers@ 9:00 AM
Deal CreatedDefender (#1234) Fresh
Deal Updated · collapsed ("Show") · status Finance (blue text)
Karla Sellers@ 9:20 AM
Deal UpdatedDefender (#1234) FinanceShow
Deal Updated · EXPANDED ("Hide") · GitHub-style field diff (.sb-diff)
Karla Sellers@ 9:20 AM
Deal UpdatedDefender (#1234) FinanceHide
Any Misc. Meta Data Can Go Here.
- Selling Price: $68,500
+ Selling Price: $66,900
- Status: Working
+ Status: Finance
Deal Moved · status (indigo text)
Karla Sellers@ 9:24 AM
Deal MovedDefender (#1234) Working
Deal Deleted · red text (delete/expire reserves red)
Karla Sellers@ 9:30 AM
Deal DeletedDefender (#1234) Deleted
Task Updated · Call (green text)
Karla Sellers@ 9:32 AM
Task UpdatedCall Jordan · Due Fri CallShow
Appointment · Scheduled (indigo text)
Karla Sellers@ 9:34 AM
Appointment SetSat Jun 21 · 11:00 AM Scheduled
Trade-in · added
Karla Sellers@ 9:36 AM
Trade-in Added2019 Ford Bronco (est. $24,500)
Customer · created (New, orange text)
Karla Sellers@ 8:58 AM
Customer CreatedLincoln Buyers New
Website Session · neutral bubble + step list (collapsed)
Jenifer Burton@ 07/20/2026 9:26 am
Website Session0:01:31Show
The Inbox feed and the customer-profile feed are the same feed and the same templates — repackaged, never forked. Channel color language: text blue · email purple · call green · failure red · neutral gray. Long rows expand with an explicit Show / Hide control, not a bare chevron. Incoming and outgoing keep their alignment, and the accent bar follows the channel or state. Pending and cancelled rows use the dashed treatment.
1 · Loaded — "Finalize appointment"
Lincoln Buyers
2022 Jeep Wrangler Rubicon+2
On the page now
Finalize appointmentDetails
Name (t-title) + compact phone/kebab icon-buttons (.sb-msel) · deal summary (regular vehicle text + "+2", no icon) · divider · async AI action-summary (regular, orange-01 circle-exclamation + directive + blue Details). Header band gray-07; bottom hairline divides header from feed.
2 · Skeleton — next-step loading (async)
Lincoln Buyers
2022 Jeep Wrangler Rubicon+2
Details
The directive is AI-generated and loads after the conversation opens → the phrase is a .sb-skeleton shimmer line until ready. Details stays live.
3 · Variant — "Send pricing"
Tamika Jefferson
2023 BMW 530i+1
Send pricingDetails
Same strip, different async directive. Directive stays 2–3 words; the row truncates before crowding Details.
The strip carries the customer name plus the deals line, and a short next-step directive of two or three words (for example “Finalize appointment”). That directive loads asynchronously and shows a skeleton while it resolves.

The composer

How a reply gets written, and what happens when a channel is unavailable.

1 · Channels — seven colors (full composer)
Text · blue (.sb-composer--text) — schedule caret
Agent
Compose a message or use a Template
Chat · Website — presence cell renders (we host the widget)
Agent
On the page now
Reply in the chat thread…
Chat · Facebook — NO presence cell (Meta exposes no presence signal)
Agent
Reply in the chat thread…
Email · purple (.sb-composer--email) — subject row · schedule caret
Note · orange (.sb-composer--note) — internal
Agent
Leave an Internal Note….
Log · indigo (.sb-composer--log) — event row
Agent
04/22/2026
Describe the event…
DAISI · yellow (.sb-composer--daisi)
Assist5m 36s
Tell DAISI to do something for this customer…
Email subject is required on send (validation ruling, 09-02): the Subject row is drawn as-is; the send button stays disabled until the subject carries text — an email with no subject never leaves the composer.
2 · Mobile collapse — Insert toolbar hidden until focus
collapsed — tabs + mode pill + field + send (no Insert row)
Agent
Compose a message or use a Template
focus field
focused — Insert toolbar revealed (:focus-within)
Agent
Saturday at 11 works great — see you then.
On mobile the Insert toolbar is hidden until the compose field is focused (:focus-within).
opt-out — the Call tab stays selectable; the body explains instead of dialing
Agent
Do Not ContactThis customer has opted out of phone calls.
The opt-out check runs before the phone check. The Call tab keeps its normal phone icon and stays selectable. The view is untinted: the host's background, presumed --white (UNVERIFIED per host). About 84 tall. Text and Email opt-out are not covered by this specimen; how the app handles them is UNVERIFIED (not audited).
no phone — Add Phone for users who can edit the customer
Agent
No PhoneTo call this customer add a phone number to their profile.
Add Phone shows only with permission to edit the customer; without it, it is hidden, not disabled. Tapping it loads the customer and opens Edit Customer Info. About 132 tall.

Calls

Calls start from the composer's Call mode — one green button — and run in the floating call card; Log records calls made off the system.

Call mode — one green button that dials; no fields, no toolbar, no send
Agent
hover / pressed
Agent
mobile width (390)
Agent
The label is "Call " + the number, masked +1 (###) ###-####. Runtime output is UNVERIFIED. Button: green-01 fill with a --white label (white in light, #1E1E1E in dark); 40 tall, pad 8/20, r5; a 12px phone glyph in a 24 box. Hover / pressed: green-02 fill + 1px green-01 border + green-01 text. The body is 80 (pad 20/16) on the green-02 wash, with no fields, toolbar or send. With Twilio, one tap starts the call in the floating call card (comp-phone-call-states.html). With GoTo on mobile, the tap opens the GoTo dialer. Otherwise a confirm opens: "CALL +1 (313) 555-0198?" / "This will open your device's phone app to make the call." / CALL · NEVERMIND, then tel:. With no dialer: "No apps found on your device that can make a phone call." The composer never changes after the tap: no live state, no wrap-up, no switch to Log. The only motion is the composer's 200ms height change when switching modes.
1 · One card for every live call (CANONICAL — mirrors QA 1395973)
  • Every live call runs in ONE floating card (PhoneCallOverlay, phone_call_overlay.dart). That covers a call placed from the composer's Call button or any call button, and a received call.
  • The card sits above every page, dialog and sheet (the Transfer sheet included). It also sits above the loading, maintenance, update and confirmation overlays. Clicks outside the card reach the screen underneath.
  • The card is independent of the composer. The composer never holds a live call and the card never docks into it. Tapping Call does not change the composer.
  • Ending a call has no wrap-up step and does not switch the composer to Log. Log stays the manual backup for calls made off the system.
  • No motion anywhere. The card appears and disappears instantly, and its height (72↔120) and colours swap instantly. It refreshes every second (the timer).
  • Desktop and mobile web: an incoming call rings in the card.
  • Native iOS/Android: the phone's own call screen rings, and the card first appears when the call connects.
  • The in-call keypad (draft PR #2087) is not in QA and not part of this spec.
  • Retired 2026-09-29 (supersedes ds_v276 / ds_v280): the Call Pill — green fill, 2px border, waveform, Dialing and Reconnecting states, the desktop audio-device picker, tooltips, the busy-disabled Call tab and "docks into the composer".
LOG — the manual backup (type=Call)
Agent
04/22/2026 05:03 PM
Confirmed the 36/10k terms — sending the quote after we hang up. Call 2m 41s.

DAISI

The mode control that keeps a human and the AI from talking over each other.

3 · DAISI mode — pill lifecycle (.sb-daisi-pill)
Off (gray)
Off
enable assist
Assist (orange) · countdown
Assist5m 36s
switch to agent
Agent (green) · idle
Agent
run starts
Agent · red run-dot (click to cancel)
Agent
Three modes — Agent, Assistant and Off — mapping to the backend values full, internal and disabled. Assistant can be paused for a set duration and the badge shows a live countdown. An in-progress run shows an indicator whose tooltip explains DAISI is working in the background; clicking it cancels the run. Switching from Agent to Assistant or Off cancels the autoresponder and any active agent run — the anti-double-talk rule, and the reason this control exists. When an Assistant pause expires the autoresponder wakes again. The whole surface respects the DAISI and background-agent feature flags.
.sb-daisi-menu — mode dropdown
DAISI Mode
Equal row anatomy (CPO ruling 2026-09-02). Every mode row — Agent Mode, Assistant Mode, AI Off — is one .sb-daisi-mode with identical padding: 10px vertical · 12px horizontal, 10px icon gap, 18px icon column; the header band is 9px/12px. The padding lives on the atom, so the app's AI-Off-row inconsistency cannot recur. Reset-to-Default is RETIRED — the header carries an X close instead. Color = mode: green = Agent · orange = Assist (internal-only) · gray = Off. The pill's left dot goes red & pulsing while an agent run is processing — click it to cancel. Pauses render in ALL modes but are ENABLED ONLY in Agent Mode (superseding ruling, Taylor → Stas, 2026-09-02). A pause = a timed step-down from Agent to Assistant that auto-reverts to Agent at 0 — so from Assistant or AI Off the rows sit disabled (reduced ink, no hover, not clickable): pausing only means something from Agent. There is no new "Paused" state — the badge and menu read Assist during a window, exactly as today. While a window runs the pause section shows Resume Now (Nm Ns left) — below.
assistant / off — pause rows disabled
DAISI Mode
Assistant active: the three pause rows render in the standard disabled treatment (.sb-menuitem.is-disabled — reduced ink, no hover, not clickable). AI Off reads identically.
pause window running — Resume Now
DAISI Mode
A 5-minute pause running from Assistant: the pause rows collapse to one Resume Now row carrying the live remainder.
light mode — trigger pill · menu · DAISI channel
Agent Assist5m 36s
DAISI Mode
Tell DAISI to do something for this customer…
THE YELLOW RULING (CPO, 2026-09-02). DAISI keeps yellow-01/yellow-02 as its accents in both themes, but in LIGHT mode any text sitting on a yellow fill is dark ink, never white — the selected DAISI channel tab flips to a yellow-01 fill with light-theme gray-00 (#272727) text. Measured WCAG on yellow-01 #F9D230: white ink ≈ 1.5:1 (fails AA) · dark ink #272727 ≈ 10.2:1 (passes AAA). The same 1.5:1 failure is why bare yellow-01 TEXT on white is never used for labels in light mode. Yellow-02 tint surfaces (#FEFBEB) keep normal ink and are unaffected. Dark theme is unchanged.

Customer Details

The context panel beside the conversation.

Summary
Location Traffic Source Lead Source

Here is a summary of the customer that is roughly 2 to 3 sentences. It explains the status of the customer, what is needed, blockers and what the next move is for them.

Hot
Destinations (CPO ruling, 09-02). View Customer lands on the customer’s ACTIVITY FEED (comp-activity-feed-shell.html), not the profile; the customer name in the conversation header performs the same action. The vehicle/deal reference opens the deal. Collapsed details sections toggle from the whole header row, not just the caret.
Suggested Next ActionText

Send the customer a text message with three vehicle suggestions based on their budget constraints and preferences.

Recent Communications
Lincoln BuyersText
Hey, I got your message.. thanks for the link...
Karla SellersCall
Summary: Carla reached out and offered Lincoln several buying options and talked about financing.
DAISI AgentEmail
Great to hear. By the way did you see we did a price drop on this x5?
View the 2023 BMW X5
Automations
None

The customer activity screen

Where View Customer lands: the customer's Activity section rebuilt on the Inbox pattern — the same feed, composer and details panel, under the unchanged profile header. Canonical screen: comp-activity-feed-shell.html.

Optimistic drop (PRESCRIPTIVE engineering contract). Pressing Action DAISI inserts the note into the feed IMMEDIATELY, before the backend confirms: the item renders at reduced opacity (.sb-activity.is-pending) with a thin shimmer progress bar inside the bubble, then settles to the normal item on confirm. A send refreshes the feed, the conversation preview, and the summary together — and never loses the user's scroll position.

Engineering scope

What the Inbox needs from the backend, and what it already has.

Open questions. What is the exact Inbox inclusion predicate? Do the other Views ship disabled, or wired with real counts? Is the next-step directive AI-generated or rules-derived? Does an Assistant pause persist per user and device, or on the customer record? And at what breakpoint does the composer collapse?

Composed under the Atomic documentation LAW — narrative + rulings ledger + anatomy map + @dsEmbed transclusions (the build inlines them with provenance links) + eng scope notes. Every embedded fact is owned by the spec page it comes from.