CedarCopilot wants to merge 2 commits into staging from fix/drafter-post-meeting-notify
Live on prod, no production signal yet
Since deploy, telemetry shows 84 runs with notify-user logging: 75 runs had exactly one call, but 9 runs had duplicates (6 runs with 2 calls, 2 with 3, and 1 with 4), totaling 97 calls. This violates the exactly-one requirement; duplicate calls are tied to concrete execution.
Unable to complete verification because the available telemetry query returned no drafter spans and the runtime identifier mapping was not finished.
Verification reached its budget before a verdict.
No production execution evidence for `pnpm tsx scripts/backfill-drafter.ts notify` was found in staging after 2026-09-03T00:16:57Z. CloudWatch returned 0 matches for `drafterNotifyPatch`, `backfill-drafter`, `drafter-notify`, post-meeting notification terms, and exact report.
In staging, since 2026-09-03T00:16:57Z, CloudWatch returned 0 rows for backfill-drafter, drafterNotifyPatch, acknowledgeFleetWideActivation, and fleet-wide signals, and OTEL returned 0 matching spans for drafter routes/operations/attributes. There is therefore no positive.
Verification reached its 120s wall-clock budget before a tied verdict. Libra is keeping this intent verifying until the next check.
internal_only
internal_only
internal_only
internal_only
internal_only
internal_only
internal_only
internal_only
Libra has verdicts on 0 of 8 tracked behaviors on prod; 8 are still being checked. Libra checks hourly for 3 days after each deploy.
PR #2664 moved the post-meeting draft notification off a hardcoded programmatic DM onto a notify-user call driven by prose in each user's subagents/drafter.md. Two defects followed it, and neither fix reaches anyone without the third change here.
Rebased onto
stagingafter #2648 (drafter Stage 5) and #2645 landed. What that changed is at the bottom, under Rebase notes , including a live dry run that caught a real defect in this branch.
The deleted code fired on inputData.taskType === 'post-meeting' , 100% deterministically. The shipped prose notified on 2/8 and 3/6 post-meeting runs across two runs of the eval harness at apps/server/.claude/skills/playbook-instruction-eval/, while drafting on 8/8. Two structural causes:
The document contradicted itself. The mandatory preamble ended with a bullet telling the model not to compensate for a skip by "notifying the user that you decided not to write", while the closing section told it to send exactly one notification. A model reading both resolves it the cheap way and sends nothing. That single paragraph is the whole of the first fix, and on its own it moved the measured rate 2/8 → 5/8, negatives unchanged (scheduled-task 0/8, inbound-email 0/8), drafting still 8/8.
The notification read as an afterthought. ## Telling the user the recap is waiting, placed after "What is not yours", says what to send but never that the run is unfinished without it. agent-defaults/daily-agenda.ts gets reliable delivery from the opposite framing , it names the notification "Stage E , Tell the user" and says "Finish with one notify-user call". The section is now ## Last step , tell the user and opens by saying a post-meeting run has two outputs.
A stronger "MANDATORY + ordered tool sequence" variant was measured and rejected: it raised the rate but produced duplicate notifications and runs that never drafted at all. That approach is not reintroduced here, and the constant's docblock records why so the next person does not try it again.
formatPostMeetingDraftMessage, deleted by #2664, was asymmetric on purpose , its own comment: // Slack draft notification , include commentary and full draft body so the user can read it verbatim in the DM. It rendered *Draft:*\n${escapedDraft} with &, <, > escaped and linked to CedarRoute.PipelineConversation (the deal, not a thread); the email variant deliberately omitted the body. The migration flattened that to "Not the draft itself" for both channels, which removed the one case where the notification IS the product: a Slack message short enough to approve on sight without opening anything.
The section is channel-specific again , email says do NOT include the body, Slack says DO, verbatim, under a *Draft:* heading, with &/</> escaped, linking to the deal and the destination channel.
Verified read-only against production, dry run, on the current branch: every drafter.md in the active cohort already exists (57 playbooks / 57 users) and NOT ONE contains a notification section. Post-meeting notifications are off fleet-wide. backfill-drafter.ts document cannot turn them on: seedFile short-circuits on an existing document, which is exactly what preserves user edits.
A --force flag would fix that by overwriting the body. That is the wrong trade twice over , these are documents people have edited, not identical seed copies; and an overwrite leaves nothing afterwards that can say what was there.
So: a third subcommand, backfill-drafter.ts notify, which patches two named regions in place and leaves every other byte alone.
pnpm tsx scripts/backfill-drafter.ts notify --all # survey
pnpm tsx scripts/backfill-drafter.ts notify --email <email> --apply # write
Same scoping as the other two subco
Libra has not measured any production surfaces for this change yet.