CedarCopilot wants to merge 0 commits into staging from feat/jev-aop-selection
Live on prod, watching, 2 days left
Libra has verdicts on 0 of 15 tracked behaviors on prod; 15 are still being checked. Libra checks hourly for 3 days after each deploy.
Adds a second selectAopForConversation path (apps/server/src/services/aop/jev-aop-selection.ts) that routes AOP classification through TypeSafe AI's Jev "Choice" model instead of GPT-4o/Sol, gated by a new PostHog flag. Both paths return the exact same AopSelectionOutput shape, so every downstream consumer , confidence bands, the ambiguity-ping decision, logToolCall , works unchanged regardless of which model produced the result.
aop-selection.ts now tries Jev first (only when the flag is on for that user); if Jev returns a result, the GPT-4o Agent is never constructed. If Jev is off, or on but fails/times out/returns something unusable, it falls straight through to the existing GPT-4o/Sol path , unchanged from before this PR.
A 60-row sample of real production MEDIUM-band classifications, replayed with the exact same full conversation context GPT-4o's own prompt is built from (formatHydratedConversationForAgent): 47.4% raw agreement between Jev and GPT-4o (n=57 reconstructable).
A rigorous 15-case manual audit of the disagreements , checked against each org's own selectionProcedure text and the real conversation content, not assumptions carried over from other orgs:
GPT-4o showed multiple distinct real failure modes in that sample:
reasoning field argued for one category while selectedAop named a different one (a reasoning/output self-contradiction bug)GPT-4o costs ~$214.91/month for this call site today (Understudy billing, aop-selection workload, 30-day window: 14,283 requests, ~92.6M input + 3.6M output tokens). Projected Jev cost at the same volume, using the measured real average of 3,515 input tokens/call from the full-context test, is ~$2.01/month. Not the primary motivation , accuracy is , but real.
type: 'choice' forces a pick among the given options. A customer-support-ticket conversation with no good category match got a confidently-wrong pick in testing for exactly this reason. Rather than invent a synthetic "none of the above" option (which would need a real no-op AOP to route to , not every org has one), a low top-choice confidence is treated the same way GPT-4o's own LOW band already is: as the abstain signal, mapped into the SAME AOP_CONFIDENCE_BANDS thresholds already used for GPT-4o.
AOP selection is a required step , every conversation needs one. Unlike jev-action-gate.ts (where fail-open means "skip the check, run the orchestrator as normal" is safe), a Jev failure here falls all the way back to running the existing GPT-4o/Sol agent for that call, never to "no AOP." selectAopWithJev never throws; every failure mode (HTTP error, timeout via AbortSignal.timeout(8000), malformed response, unresolvable choice, missing API key, zero candidates) returns null, and the caller treats null as "run GPT-4o."
Every Jev evaluation is logged via createStructuredLog under jev-aop-selection.evaluated (reaches Axiom), with outcome of selected | fallback_error | fallback_malformed_response | not_configured | no_candidates, carrying user/conversation ids and (when present) the caller's tracingContext for correlation.
New PostHog flag cedar-aop-selection-jev (
Libra has not measured any production surfaces for this change yet.