CedarCopilot wants to merge 2 commits into staging from fix/ambiguous-aop-meeting-prep-floor
Live on prod, no production signal yet
Verification reached its 130s outer budget before the verifier returned. Libra is keeping this intent verifying until the next check.
Verification reached its 120s wall-clock budget before a tied verdict. Libra is keeping this intent verifying until the next check.
Unable to complete the verification because the telemetry loop did not return a final verdict.
Strict CloudWatch fallback found 177 prod failure log lines for [SCHEDULED] Failed to enrich unenriched calendar event (Failed query: select \), but the failure is not tied to this intent.
Libra found 1 production surface on prod but could not judge any of them yet. 1 surface had no requests at all. Libra checks hourly for 3 days after each deploy.
A conversation can land on Cedar's "Non-deal professional relationships" catch-all AOP from a
single thin, early, ambiguous email (e.g. "nice talking, let's catch up next week") and then
never get re-classified. That AOP has no playbook manifest by design (it's a no-op bucket), so
scheduleBeforeMeetingAutomations silently skips pre-meeting prep for every subsequent
meeting on that conversation , including one that's obviously a real external engagement ,
with no execution/log trace at the skip point itself.
Real case: Vooma / Jason Conlow's "Run Logistics" conversation (rlsqinc.com) scored 0.85 confidence (HIGH band) into this AOP from that one thin email, then got zero pre-meeting prep for a real discovery call 17 days later ("sign you up tomorrow," $50K/year, specific integration requirements). A calendar invite existed days ahead of the call, so this wasn't a missing-signal problem , the invite existed, prep was just never scheduled because of the AOP misclassification.
When the manifest lookup comes back empty in scheduleBeforeMeetingAutomations, and the
resolved AOP is specifically this one catch-all, and the calendar event carries a real
(non-internal) external attendee, retry once under the user's own "Deals" AOP so prep still
fires. New logic lives in before-meeting-prep-floor.ts, exposing one entry point
(resolveAmbiguousAopPrepFallback).
Scoped ONLY to "Non-deal professional relationships." I scoped production data across two real orgs before writing this: no-op-AOP-classified meetings account for 4-19% of a given week's meetings, but the overwhelming majority of those hits (e.g. 4 of 6 at one org) were Vendor notification correctly catching an internal recurring calendar entry (Fathom's own "Start/End of Week" notices) , genuinely correct classification that must NOT get forced prep. Spam, Vendor notification, Recruiting, and Inbound cold pitch are left untouched.
docs/design/ambiguous-aop-classification-escalation.md claims a fleet-wide rename from
"Non-deal professional relationships" to "Professional relationships" was already shipped
(2026-08-17). Live production data (pulled this week) still shows the old name, and the
canonical constant in services/aop/types.ts (AopName.NonDealProfessionalRelationships = 'Non-deal professional relationships') , which is also what the account-setup seeding script
still writes , confirms the old name is still the actual ground truth in code today. This PR
matches against that stable enum value rather than a raw string, so it's correct regardless of
which name is live for a given org, and unaffected if that rename is completed later (the enum's
value would need updating too, at which point this code updates for free).
getAop() opens its own DB connection (open + close) rather than accepting the caller's
existing connection , pre-existing behavior, already used this way elsewhere in
calendar-events.ts for participant AOP remapping. My new floor-guarantee path reuses it the
same way. This only fires on the failure/no-manifest path (not the common happy path), so the
extra connection cost is low-frequency. Fixing getAop to accept an existing connection would
be a separate, broader refactor , out of scope here.
calendar-events.ts was already 1,623 lines before this branch (well past the project's
1,000-line guideline). Rather than growing it further, the new floor-guarantee logic (plus the
three small helpers it needs) lives in a new before-meeting-prep-floor.ts module. Net effect
on calendar-events.ts is +6 lines, not the +83 a naive inline addition would have been.
ambiguous-aop-meeting-prep-floor.test.ts (4 cases): falls back to Deals
prep when the ambiguous AOP has a real external attendee; does NOT force prep when there's
no real external attendee; does NOT force prep f| Surface | Requests | Errors | p95 | Users | Verdict |
|---|---|---|---|---|---|
| execute_tool list-calendar-events | 0 → 0 | 0 → 0 (0%) | not measured | 0 | No traffic No requests recorded since this deploy. |