Libra CodeHub

CedarCopilot/cedar-mail

Branch: staging

fix(chat): route aggregate taxonomy questions away from broken search index

merged#2792CedarCopilot

CedarCopilot wants to merge 1 commit into staging from fix/chat-taxonomy-field-routing

Live on prod, 0 of 7 surfaces degradedTimeline and evidence
  1. Opened
    Sep 15, 2026, 7:50 AM
  2. Merged
    Sep 15, 2026, 8:03 AM
  3. Live on prod
    Sep 15, 2026, 8:03 AM
  4. Observed 3 days, 7 surfaces, 5 requests
    Sep 15, 2026, 8:03 AM
  5. Pipelines steady after this deploy
    Sep 15, 2026, 8:03 AM
  6. Sep 15, 2026, 8:08 AM
  7. Mixed signals

    Live on prod, 0 of 7 surfaces degraded

    Sep 18, 2026, 7:51 AM

Behaviors Libra is checking

After finding a matching taxonomy field, the chat agent queries its extracted values from crm_conversation_field_values through run-sql, scoped by the real organization ID and field ID, instead of depending on the conversation search index.Degradedmedium confidence

Strict CloudWatch fallback found 79 prod failure log lines for [executeExternalCrm] Failed to write snapshot on non-significant sync (Failed query: select \) in the last 24h while checking select, taxonomy-field-routing-eval, shared-chat-context, search, taxonomy, up from 3 in.

prod, checked Sep 18, 2026, 7:51 AM
When a user asks a cross-deal, aggregate, or topic question that may correspond to extracted sales-taxonomy data, the chat agent checks taxonomy-fields with action=list before using semantic content search.Inconclusivelow confidence

Verification reached its 130s outer budget before the verifier returned. Libra is keeping this intent verifying until the next check.

prod, checked Sep 17, 2026, 6:24 PM
Conversation full-text searches use dynamic attribute inclusion so BM25 queries do not fail when optional result attributes are missing from the Turbopuffer namespace schema.Inconclusivelow confidence

Verification reached its 130s outer budget before the verifier returned. Libra is keeping this intent verifying until the next check.

prod, checked Sep 17, 2026, 6:59 PM
Conversation vector searches request whatever attributes exist in each Turbopuffer row instead of explicitly requesting optional attributes that may be absent from a namespace schema.Inconclusivelow confidence

Verification reached its 120s wall-clock budget before a tied verdict. Libra is keeping this intent verifying until the next check.

prod, checked Sep 17, 2026, 7:01 PM
The taxonomy-routing instructions are included only for organizations with brainSkillsEnabled, so organizations without the cedar-brain-mcp capability are not directed toward an unavailable taxonomy-fields tool.Not checked
prod, checked Sep 17, 2026, 6:55 PM

Libra found 7 production surfaces on prod but could not judge any of them yet. 2 surfaces had under 20 requests, so Libra has not judged them; 3 surfaces had no requests at all. Libra checks hourly for 3 days after each deploy.

Summary

  • Turbopuffer conversation search unconditionally requested aopId (and other nullable fields) by name in include_attributes. A namespace where that attribute was only ever written null (e.g. a rep backfilled before AOP-classification ran) never gets a schema entry for it, so naming it explicitly 400s the entire query , vector and FTS alike. Switched to includeAttributes: true so search degrades gracefully instead of failing outright.
  • The chat agent's routing prompt never mentioned the taxonomy-fields tool, so cross-deal aggregate/topic questions ("which companies asked about X?") always went to the analyzer/semantic-search subagent , even though taxonomy-fields is reachable in chat and its own description says "CALL THIS FIRST" for this exact question shape. Added a <taxonomy_field_routing> block to the shared per-request chat context, gated on the same brainSkillsEnabled flag that gates the tool itself, so this is a no-op for orgs without brain access.

Both bugs were found while debugging a real customer (Warp/Thiago) chat session from 2026-09-10, where a "what businesses asked for performance management" question hit the broken search index instead of the structured taxonomy field data that already had the answer.

Test plan

  • Pulled the raw Turbopuffer error from Axiom to confirm the exact failure mode (attribute "aopId" not found in schema) before writing the fix.
  • pnpm --filter @zero/server run types , no new errors in either changed file.
  • Built an eval harness (apps/server/.claude/skills/playbook-instruction-eval/taxonomy-field-routing-eval.ts) that reproduces the real prompt/tool shapes and Thiago's exact question against claude-sonnet-4-6 (the model the affected surface actually runs), 8 trials/variant:
    • Baseline (today's prompt): analyzer called 8/8 trials, taxonomy-fields called first 0/8.
    • With the fix: taxonomy-fields called first 8/8 trials, analyzer never called.
  • No live end-to-end run against a real chat session (would need a deploy) , the eval harness is the verification for the prompt-routing change; the Turbopuffer fix is a direct, low-risk code change confirmed against the real error text.

Greptile Summary

This PR changes conversation search to request all available Turbopuffer attributes and adds brain-gated instructions routing aggregate conversation questions through structured taxonomy data. The search change safely avoids failures when optional attributes are absent from a namespace schema, but the routing change advertises taxonomy-fields on the default granular chat surface where that tool is not registered.

  • Uses includeAttributes: true for vector and full-text conversation searches.
  • Adds taxonomy-first routing guidance to shared chat context.
  • Adds a manual model-routing evaluation harness.

Confidence Score: 4/5

The PR is not yet safe to merge because the new routing instruction can direct the default granular chat agent to a tool it cannot call.

Brain access and family-tool selection are independent flags; the shared context enables taxonomy routing from the former, while taxonomy-fields is only proven available through the latter, leaving ordinary granular requests unable to execute the intended route.

Files Needing Attention: apps/server/src/mastra/workflows/chat/shared-chat-context.ts, apps/server/.claude/skills/playbook-instruction-eval/taxonomy-field-routing-eval.ts

Important Files Changed

FilenameOverview
apps/server/src/mastra/workflows/chat/shared-chat-context.tsAdds taxonomy-first routing, but gates it only on brain access rather than ensuring the selected chat surface exposes the named tool.
apps/server/src/services/turbopuffer/search.tsReplaces brittle attribute projections with retrieval of available namespace attributes for both search modes.
apps/server/.claude/skills/playbook-instructio
Show production surfaces and changed-file mapping

Production surfaces

SurfaceRequestsErrorsp95UsersVerdict
POST /api/trpc/files.searchForLinkno baseline → 4no baseline → 0 (0%)not measured → 3053 ms0Insufficient traffic
4 requests, under the 20 Libra needs
execute_tool search-live-emailsno baseline → 1no baseline → 0 (0%)not measured → 350 ms0Insufficient traffic
1 request, under the 20 Libra needs
/api/trpc/crm.searchConversationsMinimalno baseline → 0no baseline → 0 (0%)not measurednot countedUnavailable
ClickHouse reads are unavailable, so Libra could not measure this surface.
POST /api/trpc/crm.searchConversationsMinimalno baseline → 0no baseline → 0 (0%)not measured0No traffic
No requests recorded since this deploy.
/api/trpc/files.searchForLinkno baseline → 0no baseline → 0 (0%)not measurednot countedUnavailable
ClickHouse reads are unavailable, so Libra could not measure this surface.
trpc.crm.searchConversationsMinimalno baseline → 0no baseline → 0 (0%)not measured0No traffic
No requests recorded since this deploy.
crm.searchConversationsMinimalno baseline → 0no baseline → 0 (0%)not measured0No traffic
No requests recorded since this deploy.

Changed files → surfaces

  • apps/server/src/services/turbopuffer/search.tsPOST /api/trpc/files.searchForLinkexecute_tool search-live-emails/api/trpc/crm.searchConversationsMinimalPOST /api/trpc/crm.searchConversationsMinimal/api/trpc/files.searchForLinktrpc.crm.searchConversationsMinimal+1
  • apps/server/.claude/skills/playbook-instruction-eval/taxonomy-field-routing-eval.tsno production surface mapped
  • apps/server/src/mastra/workflows/chat/shared-chat-context.tsno production surface mapped