Libra CodeHub

CedarCopilot/cedar-mail

Branch: staging

fix: atomic scheduled-send claim, guarded merge delete, and a chat stream that stopped costing thousands of Redis requests

merged#2485CedarCopilot

CedarCopilot wants to merge 0 commits into staging from fix/scheduled-send-claim-and-merge-delete

Live on prod, no production signal yetTimeline and evidence
  1. Opened
    Aug 14, 2026, 1:50 PM
  2. Live on staging
    Aug 14, 2026, 7:46 PM
  3. Pipelines steady after this deploy
    Aug 14, 2026, 7:46 PM
  4. Merged
    Aug 14, 2026, 7:46 PM
  5. Live on prod
    Aug 14, 2026, 7:46 PM
  6. Observed 2 days
    Aug 14, 2026, 7:46 PM
  7. Pipelines steady after this deploy
    Aug 14, 2026, 7:46 PM
  8. Unobserved

    Live on prod, no production signal yet

    Aug 17, 2026, 3:28 PM

Behaviors Libra is checking

Removing a calendar event the user does not organize is reported as removing only the user’s copy rather than cancelling the meeting for other attendees.Inconclusivelow confidence

OTEL fallback found no prod spans matching calendar modify-event delete since deploy.

prod, checked Aug 17, 2026, 9:26 AM
Calendar guests can add participants when Google permits invitations, including when the user is not the organizer, while invitations are blocked when guestsCanInviteOthers is explicitly false.Inconclusivelow confidence

OTEL fallback found no prod spans matching EventDetailsPopover / calendar modify-event since deploy.

prod, checked Aug 17, 2026, 10:26 AM
Calendar time, title, location, and similar shared-event edits are allowed only when they will affect all attendees, preventing agents from falsely claiming that a private-copy edit rescheduled a meeting.Inconclusivehigh confidence

Since the 2026-08-15 02:46:15Z deploy, telemetry contains no OTEL spans or structured result logs tied to modify-calendar-event permission outcomes: 0 matches for modify-calendar-event/affectedEveryone in OTEL, and no logs for logged tool-call results, modifyCalendarEventTool.

prod, checked Aug 17, 2026, 10:28 AM
Chat generation checks the cross-instance Redis cancellation flag every three seconds instead of every second and tolerates Redis probe failures without aborting the reply.Inconclusivelow confidence

OTEL fallback found no prod spans matching handleChatStreamRequest runGeneration since deploy.

prod, checked Aug 17, 2026, 11:27 AM
Streaming chat coalesces consecutive text-token events before appending them to Redis, substantially reducing Redis request volume without changing rendered reply content.Inconclusivelow confidence

OTEL fallback found no prod spans matching handleChatStreamRequest runGeneration since deploy.

prod, checked Aug 17, 2026, 11:28 AM
Chat SSE delivery tails stream frames through a resilient shared tailer, preserves Last-Event-ID replay boundaries, and emits a terminal error rather than silently ending a reply when Redis fails.Inconclusivelow confidence

Verification cited only 8 matching post-deploy events, below the 20-event floor for calling a change verified. Nothing is failing; there is not yet enough traffic to confirm it.

prod, checked Aug 17, 2026, 12:28 PM

Libra has verdicts on 0 of 13 tracked behaviors on prod; 13 are still being checked. Libra checks hourly for 3 days after each deploy.

Fixes the two issues Greptile raised on #2478. Both are valid; only one of the prescribed remedies actually works, and this PR says why.

Issue 1 , non-atomic scheduled-send claim (queue-handler.ts)

Valid, fixed properly. The worker read pending_emails_status and then sent , check-then-act over a store that cannot make the pair exclusive. KVStore (runtime/platform.ts) is get/put/delete with no compare-and-swap, which is why the guard's own comment already called itself "best-effort, not a CAS". Two real consequences: cancel-on-reply writes cancelled into the gap and the email goes out after the reply that was meant to stop it; and two deliveries of the same message (SQS is at-least-once, and the cron re-enqueues on a failed KV delete) both read pending and both send.

The decision moves onto the durable scheduled_sends row this subsystem already has, where one conditional UPDATE … SET status='sending' WHERE status='pending' is atomic. Exactly one caller wins, so delivery and cancellation are mutually exclusive rather than merely ordered. No migration , status is plain text with no CHECK constraint.

Three things make it safe rather than just atomic:

  • A missing row means bookkeeping that never landed, not a cancellation , it falls through to the KV guard. Refusing there would turn a lost row into a lost email, inverting the invariant the module is built on.
  • A failed delivery releases the claim, because the queue redelivers and a row stuck on sending could never be re-claimed , the retry would skip it silently.
  • Cancellation reports whether it won. mail.unsend now returns an error rather than a success the client acts on by deleting the draft behind an email already on its way.

Rows abandoned on sending by a worker that died mid-send are collected by the existing stale sweep.

Issue 2 , orphaning window on conversation delete (conversation-repoint.ts)

Valid, but the prescribed fix does not work , and this is the part worth reviewing.

Greptile asked for "one transaction or lock". A transaction does not close this window. The database runs at READ COMMITTED (verified, not assumed): each statement takes its own snapshot, so a document committed after the check is invisible to the check and untouched by the delete. A transaction buys atomicity, not isolation from concurrent inserts.

Closing it outright needs both sides cooperating , SERIALIZABLE on the writers too, or a lock every writer takes , and documents are inserted from ~10 sites across 6 services. Any such scheme is one missed call site away from silently not working. The real fix is a foreign key, which the path-addressing scheme (conversation/{id}/…, no FK column) cannot express today.

What a single statement does buy is removing the gap between the two operations. DELETE … WHERE NOT EXISTS (…) evaluates the predicate and deletes under one snapshot, so the window shrinks from two round-trips , plus whatever the caller does between them , to the statement's own execution, and anything already committed blocks the delete. repointDocumentsAndDeleteConversation then re-points the straggler and retries, which converges; three rounds without converging is not a race and raises rather than deleting.

All four merge/repair paths route through it, so none issues a bare conversation delete any more.

Residual risk, stated plainly: an insert committing during that one statement's execution can still slip through. Eliminating it is a foreign-key project, not a patch.

Test plan

  • 37 new/updated tests, all against real SQL (in-process PGlite), not mocks , the guarantee in both fixes is the SQL predicate, so a mocked db would agree with whatever the implementation asked for and prove nothing.
  • The load-bearing one: 8 concurrent claimants, exactly one wins. Also cancelled-first, sent-already, missing-row, wrong-connection, release-and-re-claim, and cancel-loses-to-a-claimed-send.
Show production surfaces and changed-file mapping

Production surfaces

Libra has not measured any production surfaces for this change yet.

Changed files → surfaces

  • apps/mail/docs/pipeline-tabs-and-canvas-aggregates.mdno production surface mapped
  • apps/mail/docs/url-driven-layout.mdno production surface mapped
  • apps/mail/modules/calendar/components/EventDetailsPopover.tsxno production surface mapped
  • apps/mail/modules/calendar/hooks/use-event-manipulation.tsno production surface mapped
  • apps/mail/modules/calendar/types/calendar-types.tsno production surface mapped
  • apps/mail/modules/cedar-os/src/store/messages/renderers/ProposedConversationEventRenderer.tsxno production surface mapped
  • apps/mail/modules/ux/layout/LayoutUrlSync.tsxno production surface mapped
  • apps/mail/modules/ux/layout/useBackOrUp.tsno production surface mapped
  • apps/mail/tests/modules/ux/layout/artifactEntryOnRouteOpen.test.tsxno production surface mapped
  • apps/mail/tests/modules/ux/layout/backOrClose.test.tsno production surface mapped
  • apps/server/.claude/skills/calendar/SKILL.mdno production surface mapped
  • apps/server/.claude/skills/conversation/field-updating.mdno production surface mapped
  • apps/server/src/crm-admin/cli.tsno production surface mapped
  • apps/server/src/db/scheduled-send-schema.tsno production surface mapped
  • apps/server/src/mastra/routeHandlers/chat/handleChat.tsno production surface mapped
  • apps/server/src/mastra/tools/calendar/__tests__/modifyCalendarEventTool.test.tsno production surface mapped
  • apps/server/src/mastra/tools/calendar/calendarTool.tsno production surface mapped
  • apps/server/src/mastra/tools/calendar/listCalendarEventsTool.tsno production surface mapped
  • apps/server/src/mastra/tools/calendar/modifyCalendarEventTool.tsno production surface mapped
  • apps/server/src/services/chat/chat-stream-store.test.tsno production surface mapped
  • apps/server/src/services/chat/chat-stream-store.tsno production surface mapped
  • apps/server/src/services/chat/chat-stream-tail.test.tsno production surface mapped
  • apps/server/src/services/chat/chat-stream-tail.tsno production surface mapped
  • apps/server/src/services/chat/chat-stream-writer.test.tsno production surface mapped
  • apps/server/src/services/chat/chat-stream-writer.tsno production surface mapped
  • apps/server/src/services/crm/__tests__/conversation-aggregates.test.tsno production surface mapped
  • apps/server/src/services/crm/__tests__/merge-and-events.test.tsno production surface mapped
  • apps/server/src/services/crm/company-merge.tsno production surface mapped
  • apps/server/src/services/crm/conversation-aggregates.tsno production surface mapped
  • apps/server/src/services/crm/conversation-repair.tsno production surface mapped
  • apps/server/src/services/crm/conversations.tsno production surface mapped
  • apps/server/src/services/documents/__tests__/conversation-repoint.test.tsno production surface mapped
  • apps/server/src/services/documents/conversation-repoint.tsno production surface mapped
  • apps/server/src/services/mail/calendar/event-permissions.tsno production surface mapped
  • apps/server/src/services/mail/send/__tests__/scheduled-send-claim.test.tsno production surface mapped
  • apps/server/src/services/mail/send/cancel-on-reply.tsno production surface mapped
  • apps/server/src/services/mail/send/scheduled-send-records.tsno production surface mapped
  • apps/server/src/trpc/routes/crm.tsno production surface mapped
  • apps/server/src/trpc/routes/mail.tsno production surface mapped
  • apps/server/src/worker/queue-handler.tsno production surface mapped