docs/user-journeys.md

User journeys and evidence

Use this map to select checks after a change. Test paths identify coverage, not a passing result. Bind each receipt to source and dependencies, then to the installed artifact where applicable. Follow the installed smoke recipe before claiming an installed fix.

JourneyExpected resultFailure branches to preserveFocused synthetic coverage
Connect accountProvider choice opens the correct setup; a successful connection appears in AccountsOAuth unavailable/cancelled, invalid credentials, sync gap; never replace an unreadable keysrc/onboarding.test.tsx, server/sync.test.ts, server/sync-recovery.test.ts
Read and search mailCached mail stays reachable; search respects account/view; opening the selected email shows its contextEmpty results, missing source, incomplete sync, read failure; selection alone does not mark readsrc/mail-search.test.tsx, src/mail-actions.test.tsx, src/list-windowing.test.tsx
Rename accountSave updates sidebar and Settings after reload; blank name restores the addressCancel leaves name unchanged; failed save retains input; privacy still masks addressessrc/navigation.test.tsx (rename cases)
SnoozeMenu opens beside the clicked icon; a preset saves once and moves mail to SnoozedCustom-form growth stays in the viewport without moving input focus; oversized menus scroll; busy/failed save, Escape, unsnooze and expiry; no provider snooze or duplicate action barsrc/snooze.test.tsx, src/context-menu.test.tsx, src/row-actions.test.tsx
Drafts and replyDrafts lists account, envelope, subject, snippet, time and attachments; opening restores content; reply shows original textSave failure, uncertain send, duplicate-submit guard, account change, invalid attachment/drop; never resend automaticallysrc/draft-list.test.tsx, src/draft-recovery.test.tsx, src/compose-layout.test.tsx, server/drafts.test.ts
Today and trackingQuick Track prefills source/title/reason; saved work appears in the chosen group with an inline source readerFailed refresh retains input; thanks does not complete work; separate deliverables close independentlysrc/today-workflow.test.tsx, src/workbench.test.tsx, server/workspace.test.ts
ProjectsChoose a job, read its emails inline, add a linked task, and record a decision with supporting emailsMissing sources, account scope, privacy, stale revisions and unknown saves; combining accounts requires explicit approvalsrc/today-workflow.test.tsx, src/workbench.test.tsx, server/workspace.test.ts
Settings editingSection changes start at the top; unsaved templates and signatures survive section changes and Settings close within the app sessionFailed saves retain text; pending saves cannot overwrite a later draft; application exit discards unsaved Settings editssrc/compose-settings.test.tsx, src/navigation.test.tsx
CalendarDeadlines, timed follow-ups, active snoozes and Emc² events appear on the correct local day; selection opens in the right-hand paneDate-only timezone shifts, DST gaps, multi-day events, cleared/expired snoozes and completed work; snooze and events do not create commitments; pending event fields reject edits; failed or uncertain event saves keep input and reuse one ID; Back/Escape restores entry focus after rendering, and source-reader return focuses event/task details; explicit source unlink permits reassignment after account removal, while Cancel preserves the source; clearing a Meet link survives reload and later invitation preparationsrc/calendar.test.tsx, src/follow-up-presets.test.tsx, src/workbench.test.tsx (calendar events), src/event-panel.test.tsx, server/calendar.test.ts
Schedule meetingOpened email's Schedule meeting prefills subject, people except the user and account; saving adds one Emc² eventInvalid attendees/links, past end, privacy hiding; pending saves guard fields, close and navigation; failure unlocks retained inputs for identical retry; saving alone sends nothing; invitation drafts require a separate actionsrc/today-workflow.test.tsx (Schedule meeting), src/workbench.test.tsx (delayed save), src/calendar.test.tsx
Optional Google CalendarExplicit per-Gmail consent → Sync visible month → choose calendars → Sync; grid/day/agenda and right pane show remote event detailsOrdinary reconnect loses scope; API disabled help; stale cache after failure; empty replacement removes deleted events; account filter/privacy; navigation never syncs Googleserver/google-calendar.test.ts, server/calendar.test.ts, src/calendar.test.tsx, src/workbench.test.tsx
Calendar invitations and RSVPLocal event → prepare REQUEST/update/CANCEL → review recovered draft → ordinary Send; incoming invitation → local RSVP draft or explicit Google own-attendee RSVPWrong account/sender, stale source/sequence, changed revision, unsupported calendar data, unknown Send and Sent-copy warning; preparation never sendsserver/invitations.test.ts, server/ical.test.ts, src/invitations.test.tsx, server/invitation-google.test.ts, src/google-invitations.test.tsx
Explicit Google notificationsLocal event → Create on Google and notify attendees → Review created Google event; incoming matched event → Accept/Maybe/Decline and notify organizerNo synced window, wrong identity, stale source/etag, response loss and remount; persisted request reconciles by read only; local event stays separate; selecting another event replaces the reviewed result and restores its actionsserver/calendar-writes.test.ts, server/invitation-google.test.ts, src/google-invitations.test.tsx
Offer timesReader → save chosen-zone availability → explicitly include busy sources → check → select slots → reviewed reply → explicitly book agreed slot → event details and CalendarMissing consent or any failed/truncated/mismatched busy read blocks results; rejected checks can change; unknown checks/drafts retain inputs; checked offers resume after remount; source/settings/account changes reject stale work; fresh conflicts block booking; removed drafts/events never reappear; no automatic Send or Google writeserver/offers.test.ts, src/offers.test.tsx, src/availability.test.tsx, server/google-calendar.test.ts, existing calendar/draft/mail checks
Assistant setup and reviewSettings owns setup/removal; Agent review owns proposals/activity; BYOK key stays privateMissing/revoked grants, wrong account, stale proposal, provider failure; no automatic grant expansion or sendingsrc/workbench.test.tsx, src/agent-provider.test.tsx, server/mcp.test.ts
Agent connection to TodayAuthenticated assistant reads cached mail, explicitly granted tracking saves local work, Today shows it and opens its sourceReader-only grant denies creation; existing grants stay unchanged; cross-account sources rejectedsrc/agent-journey.test.tsx uses real local MCP HTTP plus mounted App, synthetic data only
Navigation and text sizeBack/Forward stays beside search; Page Up/Down follows mail ordering; Ctrl/Cmd +/−/0 scales textEditor/dialog ownership, deleted source, end of list, privacy; no duplicate history rowsrc/navigation.test.tsx, src/reader-keyboard.test.tsx, src/FormattedMail.test.tsx, desktop/navigation.test.ts
NotificationsPreview shows enabled delivery, details, privacy and sound; new-mail notice opens its exact sourceMultiline notices, Dismiss and counts remain scrollable at bottom and top anchors; disabled delivery, hidden text, missing target, first import, duplicate arrival, audio failure; no premature readsrc/toasts.test.tsx, desktop/notifications.test.ts, server/notifications.test.ts
UpdateDetails show state; valid supported update respects save/send drain and restartmacOS unsupported automatic install, invalid artifact, failed download, active draft, unknown send; keep rollbacksrc/update-lifecycle.test.tsx, desktop/updates.test.ts, server/update-drain.test.ts

Record acceptance at the tested layer

  • Synthetic: temporary encrypted stores, fake mail and provider adapters. A source renderer served by a fixture is also synthetic, even when viewed on a Mac.
  • Installed: the identified packaged executable and its bundled renderer pass startup and the relevant UI journey on that OS. Build or launch exit status alone is insufficient.
  • Real account: separately authorized steps pass against the intended saved account. A successful list_accounts proves only that call, not cached reading, tracking, Today, provider sync or delivery.

Mark each row PASS, FAIL, BLOCKED or UNRUN at each layer. Record evidence and the exact gap. Leave skipped journeys UNRUN; never turn a denial, source review or process launch into workflow acceptance. Keep private account and mail data out of receipts.