Libra CodeHub

CedarCopilot/cedar-mail

Branch: staging

fix(before-meeting): tell meeting-prep which calendar event it's for

merged#2688CedarCopilot

CedarCopilot wants to merge 3 commits into staging from fix/sherlock-before-meeting-ambiguous-target-20260904-150852

Live on prod, 1 of 6 behaviors degradedTimeline and evidence
  1. Opened
    Sep 4, 2026, 3:16 PM
  2. Sep 6, 2026, 11:23 AM
  3. Merged
    Sep 6, 2026, 11:51 AM
  4. Live on prod
    Sep 6, 2026, 11:51 AM
  5. Observed 3 days
    Sep 6, 2026, 11:51 AM
  6. Pipelines steady after this deploy
    Sep 6, 2026, 11:51 AM
  7. Mixed signals

    Live on prod, 1 of 6 behaviors degraded

    Sep 9, 2026, 11:47 AM

Behaviors Libra is checking

When before-meeting reference resolution returns no dispatchable refs, the system recovers the seeded meeting-prep subagent and runs its real agent and instructions instead of dispatching to a synthetic SHA-256 hash agent.Degradedmedium confidence

Strict CloudWatch fallback found 26 prod failure log lines for [executeExternalCrm] Post-execution deal link failed (non-critical) (Failed query: update \) in the last 24h while checking runplaybooksectionexecution, handleexecutescheduledexecution, sha-256, is present, the.

prod, checked Sep 9, 2026, 11:47 AM
Before-meeting prep tells the meeting-prep agent the exact calendar event title, start time, and timezone associated with the trigger, instructing it not to reuse prep from another meeting in the same conversation.Workingmedium confidence

Production telemetry shows 54 successful '[executeScheduledExecution] Firing playbook before-meeting' operations across 8 worker streams from 2026-09-06 22:30:00Z through 2026-09-08 07:30:02Z. The firing logs include matching google_event_id and target_meeting_title for the.

prod, checked Sep 8, 2026, 12:48 AM
A queued before-meeting execution is canceled without dispatch when its trigger is no longer configured for the current conversation stage or participant/owner context.Inconclusivelow confidence

Strict CloudWatch fallback found 1 recent prod failure log lines for Failed to create execution for task (Failed to execute task: Failed query: update \), but the same failure had 19 log lines in the comparable pre-deploy baseline. Libra is not blaming this PR intent without a.

prod, checked Sep 7, 2026, 6:47 AM
If the before-meeting dedupe key or calendar lookup cannot resolve a target event, execution continues without target-meeting instructions and participant RSVP gating fails open.Inconclusivelow confidence

Strict CloudWatch fallback found 1 recent prod failure log lines for Failed to create execution for task (Failed to execute task: Failed query: update \), but the same failure had 19 log lines in the comparable pre-deploy baseline. Libra is not blaming this PR intent without a.

prod, checked Sep 7, 2026, 7:48 AM
The legacy before-meeting fallback appends per-execution context such as the target meeting instructions to the recovered meeting-prep instructions instead of silently dropping it.Inconclusivelow confidence

Unable to complete a production verification: post-deploy telemetry showed scheduled/automation spans, but no spans or logs tied specifically to the before-meeting execution, legacy recovery, or overrideInstructions behavior. The evidence is therefore insufficient to establish.

prod, checked Sep 7, 2026, 8:49 AM
Before-meeting firing telemetry identifies the calendar event used for the execution so operators can correlate prep runs with the intended meeting.Inconclusivelow confidence

Verification cited only 7 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 Sep 8, 2026, 1:48 AM

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

What was wrong

A Cedar conversation can hold several real meetings on the same day , most commonly when multiple contacts at one company share a domain and get merged into one Cedar conversation (e.g. several Meta contacts all landing on one "Meta" deal). The before-meeting trigger correctly scheduled one execution per calendar event, but at fire time gave the meeting-prep subagent nothing beyond conversationId and a generic prompt ("Meeting preparation , before-meeting trigger"). Left to guess which of the conversation's upcoming meetings it was for, the subagent converged on whichever was chronologically nearest "now" and re-delivered that meeting's (already-sent) prep instead of writing one for its actual target.

Traced via Sherlock for Willem/Listen Labs (2026-09-04): three same-day Meta meetings (Emma 11:35am, Charlie 12:00pm, Shubha 1:30pm) shared one Cedar conversation. The trigger scheduled 2 hours ahead of Shubha's 1:30pm call fired on time, but re-posted Emma's 11:35am prep to Slack a third time and never wrote anything for Shubha , reported as "meeting hasn't loaded."

handleExecuteScheduledExecution.ts already parsed the calendar event's googleEventId out of the dedupe key ({googleEventId}:before-meeting:playbook:...), but only used it for a participant RSVP-decline check, then discarded it before dispatching the subagent.

What changed

  • handleExecuteScheduledExecution.ts: consolidated the googleEventId parse + calendar-event lookup into one unconditional query (previously gated behind the participant-only RSVP check), and used it to build explicit target-meeting instructions (title, start time, timezone) for every before-meeting execution, not just participant ones.
  • Threaded that context into runPlaybookSectionExecution's existing additionalInstructions hook (already used by daily-agenda's fan-out for the same purpose , per-execution caller context appended to the dispatched subagent's instructions).
  • playbook-execution-triggers.ts: also joined additionalInstructions into the legacy (non-ref) dispatch path's overrideInstructions , without this it would have silently vanished for any account still on that fallback path.
  • Updated before-meeting-execution-rsvp-gate.test.ts's mock to match the new query shape (this caught a real bug during review: the unconditional query crashed on undefined.toISOString() against the old mock, which only modeled rsvp/orgAopId), and added two new tests: the target-meeting text is forwarded, and the change fails open (no additionalInstructions, execution still proceeds) when no calendar event resolves.

How to test

  • pnpm --filter @zero/server exec vitest run src/mastra/routeHandlers/event-execution/__tests__/before-meeting-execution-rsvp-gate.test.ts , 7/7 passing.
  • For Willem specifically: his next Meta meetings are Sep 7 (Holly), Sep 9 (Amit), and Sep 11 (Emma demo), all on the same shared conversation. After this deploys, check agent_tool_calls for the run-subagent/meeting-prep run scheduled ~2h before each , the fetch-conversation step should be followed by a brief specific to that contact rather than a re-delivery of a different one, and #weewee-meetingprep should show one correct post per meeting, not duplicates.

Verification run

  • pnpm --filter @zero/server run types , clean
  • pnpm --filter @zero/server exec eslint on all 3 changed files , clean
  • pnpm deps:check , 0 violations, 1735 modules cruised
  • Scoped vitest: the changed test file (7/7) plus 9 adjacent playbook/crm/meetings suites (87/87) , all passing
  • Reviewed via /thermo-review: šŸ”“ 0, 🟔 0, 🟢 2 nits (no missing legacy-path test, ISO-string readability) , both non-blocking

šŸ¤– Generated with Claude Code

https://claude.ai/code/session_01NCrzpfdSkCgjvtgmUGbEjQ

Greptile Summary

This PR resolves the calendar event associated with each before-me

Show production surfaces and changed-file mapping

Production surfaces

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

Changed files → surfaces

  • apps/server/src/mastra/routeHandlers/event-execution/__tests__/before-meeting-execution-rsvp-gate.test.tsno production surface mapped
  • apps/server/src/mastra/routeHandlers/event-execution/handleExecuteScheduledExecution.tsno production surface mapped
  • apps/server/src/services/playbook/__tests__/before-meeting-legacy-meeting-prep-recovery.test.tsno production surface mapped
  • apps/server/src/services/playbook/playbook-execution-triggers.tsno production surface mapped