Skip to main content

The AI Executive view

/executive is a cross-survey, AI-powered leadership summary. It is deterministic-first: every number, anomaly, forecast and risk is computed from the existing reporting aggregates, and an AI narrative is layered on top — so the page never fails when the model is down.

Where it lives​

  • Service — api/src/domains/insights.ts → ExecutiveInsightsService(db, ai).
  • Routes — api/src/routes/executive.ts: GET /v1/executive/insights (the payload) and POST /v1/executive/ask (natural-language Q&A grounded in the same snapshot). Gated on the executive.view permission and the executive feature flag.
  • Page — frontend/src/pages/ExecutivePage.tsx.

How a report is built​

  1. Gather one deterministic snapshot in a single tenant transaction, reusing existing reporting methods (npsSummaryAll, metricAll, volumeByDayAll, channelBreakdown, surveyPortfolio, leaderboard, alertStatusCounts/alertTotalsByRule, verbatim.sentimentBreakdown, keyDrivers) over a current + prior window (the ReportFilter has no prior-period field — two windows are computed). No new SQL was added.
  2. Compute deterministic insights: KPI deltas, an NPS forecast (least-squares projection), anomalies, a risk radar and an alerts digest.
  3. Enrich with one constrained-JSON Gemini call (ai.completeJson) → headline, summary, emerging themes, recommended actions, agent coaching, driver storyline, forecast framing. On failure the deterministic payload is returned with ai.available = false.

Caching​

The full payload is cached server-side for 12 hours per (client_account, period/scope) in system.executive_insight_cache (owner connection, account-keyed; Database.get/setExecInsightCache). Repeat views and multiple viewers reuse it instead of re-running ~25 aggregates + the Gemini call. The Refresh button forces a recompute (?refresh=1); an AI-down result is not cached (so the next view retries). cachedAt drives the "Updated …" indicator.

Filtering​

The Executive filter bar shows only the time period, defaulting to the last 30 days; the report uses that window. Survey/channel scope still applies for a scoped member (it's part of the cache key).