Libra CodeHub

CedarCopilot/cedar-mail

Branch: staging

A lost chat turn keeps the question, a new chat drops the last one's deal, and meeting presence stops scanning the table

merged#2896CedarCopilot

CedarCopilot wants to merge 3 commits into staging from feat/inbox-client-composed-feed

What Libra verified

  • Switching chats does not commit the page’s ambient conversation

    Libra ran this behavior against the change and confirmed the check detects when it breaks.

    Technical evidence
    • the page conversation is recognized as ambient only for the destination chat that LayoutUrlSync marked
    • a deliberate conversation opening is not treated as an ambient page display and remains eligible to be committed

    Changed code: EmbeddedCedarChat.tsx.

Live on prod, 2 of 10 surfaces working, 2 days leftTimeline and evidence
  1. Opened
    Sep 23, 2026, 12:06 AM
  2. Merged
    Sep 23, 2026, 1:01 AM
  3. Live on prod
    Sep 23, 2026, 1:01 AM
  4. Observed 1 hour, 10 surfaces, 14,428 requests
    Sep 23, 2026, 1:01 AM
  5. Watching

    Live on prod, 2 of 10 surfaces working, 2 days left

    Sep 23, 2026, 1:01 AM
  6. Pipelines steady after this deploy
    Sep 23, 2026, 1:01 AM
  7. Sep 23, 2026, 1:07 AM

Behaviors Libra is checking

Adding, editing, moving, or archiving a board card invalidates cached card lists so an open board refreshes without a remount or manual reload.Not checked
prod
A board created by the agent automatically opens beside the transcript when no other artifact panel is open, following the existing written-document behavior.Not checked
prod
A successful board create_board tool result renders as a board badge that opens the newly created board when its document ID is available.Not checked
prod
Board tool calls display action-specific descriptions for creating, adding, updating, moving, archiving, commenting on, configuring, reading, and listing boards.Not checked
prod
An artifact automatically reasserted by the page while switching chats is not promoted as that chat's primary conversation or persisted as the chat's remembered display artifact.Not checked
prod
Removing the active conversation context clears the active conversation identifier so subsequent messages are no longer scoped to the removed conversation.Not checked
prod

Libra measured 2 of 10 production surfaces on prod. 3 surfaces had under 20 requests, so Libra has not judged them; 4 surfaces had no requests at all. Libra checks hourly for 3 days after each deploy.

Summary

Five pieces of work, plus what three review gates turned up on them.

Chat durability. A turn persisted its transcript once, at the end , so a process death between the question and the answer took the whole conversation with it, leaving a titled thread holding nothing and no log line anywhere. The user's message is now written the moment the turn starts (same row id, so the end-of-turn compile upserts rather than duplicates), and a turn that ends without persisting says so.

Switching chats no longer hands the new chat the last chat's deal. An artifact the app puts on a chat (LayoutUrlSync keeping the page's deal on screen through a tab switch) is marked ambient, so it earns no committed primary and no server-side display memory.

Cross-mailbox drafts fail honestly. A thread living in another connected mailbox has no RFC822 message to pair against, so the existing recovery ladder always misses it and the composer told the user to try again , forever. It now says the thread lives in a different mailbox and that retrying won't help. Retrying the write on the owning connection was built and then removed during review: createDraft returns only a provider draft id, so autosave, send and delete all resolve the active connection again , the draft saved into the other mailbox and then couldn't be sent from the one you were writing in. A failure that looks like success is worse than an honest one; carrying the effective connection through the draft lifecycle is its own change.

Agent-created documents attach to chat context via one shared server-side helper, replacing a frontend hack special-cased on a tool name. Boards get a field-level default, so a card filed with no status is a Backlog card on disk rather than one that merely draws there.

listMeetingProviderPresence got an indexed path. crm_meeting_events carries no user_id, so Postgres scanned the whole table and looked each row back up in crm_events. Adding the redundant-on-results eventType predicate gives the planner a second selective index: 865 ms → 6.2 ms, 94,097 buffers → 354 on the heaviest account. Verified against production that all 22,977 rows are event_type = 'meeting', so it drops nothing.

Review

GateOutcome
/review2 blocking, 2 should-fix, 4 broken suites , all fixed (5bda47d6d)
/thermo-review1 structural regression, 2 false invariants, 1 missed reuse , all fixed (9b070ca1b)
Greptile CLI (local)Did not run , service-side failure on 3 attempts, each stuck on a stale base sha
Greptile (PR review)6 P1 + 2 P2 → 5 fixed, 1 declined with reason, 2 were other sessions' commits (efccd8141, 09fd56d0a)

The two blocking findings were both in the chat-switch fix, and both let the bug it targets survive:

  • EmbeddedCedarChat cleared the ambient mark from the commit before the one that reads it. LayoutUrlSync is a sibling whose effects flush first, but its store write isn't visible until the next render , so the promote effect saw an unwritten slot, wiped the mark, and then committed the app's deal as the chat's own. The slot is now read uncollapsed: undefined (never written) no longer clears; null (displaying nothing) still does.
  • applyOwnThreadContext's conversation branch never wrote the display slot, so chatStillHolds read a deliberate tab switch as hydration and re-asserted the previous chat's deal over the one the chat owns.

Thermo found the consolidation had taken the attach half out of three tools and left the detach half inline in documentTool, carrying both of the same bugs , createStructuredLog formats a line without emitting one, so failures were invisible, and the DB handle sat outside the guard. boardTool had no detach at all, so archiving a card add_card had filed as a chip left a tombstone the agent is handed on every later turn. Both directions now share one plumbing path.

It also caught a regression against sta

Show production surfaces and changed-file mapping

Production surfaces

SurfaceRequestsErrorsp95UsersVerdict
/23970 → 133622 → 0 (0%)20026 ms → 20029 ms0Working
13,362 requests since the deploy with 0 errors (2 errors in the 23,970-request baseline before it). p95 20029 ms, was 20026 ms.
db.insert919 → 10600 → 0 (0%)34 ms → 35 ms0Working
1,060 requests since the deploy with 0 errors (0 errors in the 919-request baseline before it). p95 35 ms, was 34 ms.
/api/trpc/documents.getDoc0 → 30 → 0 (0%)not measured → 200 ms0Insufficient traffic
3 requests, under the 20 Libra needs
POST /api/trpc/documents.getDoc0 → 20 → 0 (0%)not measured → 200 ms0Insufficient traffic
2 requests, under the 20 Libra needs
trpc.documents.getDoc0 → 10 → 0 (0%)not measured → 177 ms1Insufficient traffic
1 request, under the 20 Libra needs
execute_tool read-document0 → 00 → 0 (0%)not measured0No traffic
No requests recorded since this deploy.
execute_tool write-document0 → 00 → 0 (0%)not measured0No traffic
No requests recorded since this deploy.
execute_tool list-documents0 → 00 → 0 (0%)not measured0No traffic
No requests recorded since this deploy.
/api/trpc/boards.listCards0 → 00 → 0 (0%)not measured0No traffic
No requests recorded since this deploy.
/home chat tabs and thread pickerno baseline → 0no baseline → 0 (0%)not measurednot countedUnavailable
ClickHouse reads are unavailable, so Libra could not measure this surface.

Changed files → surfaces

  • apps/server/src/mastra/tools/document/boardTool.ts/api/trpc/boards.listCards
  • apps/server/src/mastra/tools/document/documentTool.ts/api/trpc/documents.getDocPOST /api/trpc/documents.getDoctrpc.documents.getDocexecute_tool read-documentexecute_tool write-documentexecute_tool list-documents
  • apps/server/src/mastra/tools/document/tableTool.ts/db.insert
  • apps/mail/modules/cedar-os/__tests__/__mocks__/trpc.tsno production surface mapped
  • apps/mail/modules/cedar-os/src/cedar-os-components/chatComponents/EmbeddedCedarChat.tsxno production surface mapped
  • apps/mail/modules/cedar-os/src/components/renderers/messageRenderers.tsxno production surface mapped
  • apps/mail/modules/cedar-os/src/components/renderers/toolCallDetails.tsno production surface mapped
  • apps/mail/modules/cedar-os/src/store/agentConnection/responseProcessors/toolResultResponseProcessor.tsno production surface mapped
  • apps/mail/modules/cedar-os/src/store/messages/ambientOpen.tsno production surface mapped
  • apps/mail/modules/cedar-os/src/store/messages/messagesSlice.tsno production surface mapped
  • apps/mail/modules/company/components/CompanyExplorer.tsxno production surface mapped
  • apps/mail/modules/conversations/components/LeftSidebarContent.tsxno production surface mapped
  • apps/mail/modules/documents/board/BoardCardTile.tsxno production surface mapped
  • apps/mail/modules/documents/board/BoardDocumentView.tsxno production surface mapped
  • apps/mail/modules/documents/board/CardDocumentView.tsxno production surface mapped
  • apps/mail/modules/documents/board/CardFieldList.tsxno production surface mapped
  • apps/mail/modules/documents/board/CardFieldValue.tsxno production surface mapped
  • apps/mail/modules/documents/board/utils/invalidate-board-cards.tsno production surface mapped
  • apps/mail/modules/drafting/utils/save-draft-error.tsno production surface mapped
  • apps/mail/modules/home/components/FileArtifactPanel.tsxno production surface mapped
  • apps/mail/modules/sharing/__tests__/links.test.tsxno production surface mapped
  • apps/mail/modules/sharing/components/LinkSection.tsxno production surface mapped
  • apps/mail/modules/sharing/types.tsno production surface mapped
  • apps/mail/modules/ux/layout/LayoutUrlSync.tsxno production surface mapped
  • apps/mail/modules/ux/layout/enterChatThread.tsno production surface mapped
  • apps/mail/tests/modules/documents/board/CardFieldList.test.tsxno production surface mapped
  • apps/mail/tests/modules/drafting/saveDraftError.test.tsno production surface mapped
  • apps/mail/tests/modules/home/DisplayArtifactPanel.test.tsxno production surface mapped
  • apps/mail/tests/modules/home/fileArtifactPanelRows.test.tsxno production surface mapped
  • apps/mail/tests/modules/ux/layout/chatSwitchReleasesUrlArtifact.test.tsxno production surface mapped
  • apps/server/docs/agent-tool-calls-retention.mdno production surface mapped
  • apps/server/docs/chat-messages-not-persisted.mdno production surface mapped
  • apps/server/docs/sharing.mdno production surface mapped
  • apps/server/src/mastra/tools/document/__tests__/boardTool.test.tsno production surface mapped
  • apps/server/src/mastra/tools/document/writeDocumentTool.tsno production surface mapped
  • apps/server/src/mastra/utils/__tests__/chat-turn-durability.test.tsno production surface mapped
  • apps/server/src/mastra/utils/chat-message-persistence.tsno production surface mapped
  • apps/server/src/mastra/utils/context-items/attach-on-write.test.tsno production surface mapped
  • apps/server/src/mastra/utils/context-items/attach-on-write.tsno production surface mapped
  • apps/server/src/mastra/workflows/chat/chat-workflow.tsno production surface mapped
  • apps/server/src/services/agent-workspace/__tests__/meeting-recorders.test.tsno production surface mapped
  • apps/server/src/services/agent-workspace/meeting-providers.tsno production surface mapped
  • apps/server/src/services/documents/board/__tests__/board-view.test.tsno production surface mapped
  • apps/server/src/services/documents/board/board-ops.tsno production surface mapped
  • apps/server/src/services/documents/board/board-templates.tsno production surface mapped
  • apps/server/src/services/documents/board/board-types.tsno production surface mapped
  • apps/server/src/services/drafting/__tests__/create-draft-cross-mailbox-recovery.test.tsno production surface mapped
  • apps/server/src/services/drafting/thread-id-recovery.tsno production surface mapped