Skip to content

feat(insights): investigation pipeline overhaul#459

Merged
izadoesdev merged 16 commits into
stagingfrom
izadoesdev/intelligence-investigation-pipeline
May 27, 2026
Merged

feat(insights): investigation pipeline overhaul#459
izadoesdev merged 16 commits into
stagingfrom
izadoesdev/intelligence-investigation-pipeline

Conversation

@izadoesdev
Copy link
Copy Markdown
Member

@izadoesdev izadoesdev commented May 27, 2026

Summary

  • Overhaul investigation pipeline: detection, enrichment, tools, actions, model routing
  • Add scrape_page (Firecrawl), search_console (GSC), per-table SQL column validation
  • Shared createToolkit() across chat agent, insights pipeline, and MCP
  • Actions pipeline: code_fix for cursor/claude-code, investigate_further, add_custom_event, create_annotation
  • Smart model routing: GPT 5.4-mini (fast), Sonnet 4.6 (balanced), Opus 4.7 (deep/critical)
  • Detection: median/MAD z-score, error/revenue/vitals/custom event WoW signals
  • Enrichment: vitals context, queryPeriodPair helper, GitHub commit correlation
  • Dashboard: rootCause, evidence, investigationDepth, action pills on insight cards
  • GSC integration row on settings page
  • Insights digest email template

Test plan

  • Run insights generation on 4+ sites, verify 0 false alarms
  • Verify GSC integration connects with proper scopes
  • Verify insight cards show rootCause, evidence, and action pills
  • Verify code_fix action copies prompt to clipboard
  • Run bun test in apps/insights (61 tests)
  • Run bun test in packages/db (43 SQL validation tests)

Summary by cubic

Overhauled the insights investigation pipeline with stronger detection, richer enrichment, and shared investigation tools. Adds GSC/GitHub/scrape support, actionable insight pills, org-scoped OAuth, and an instant Slack “thinking” card.

  • New Features

    • Shared createToolkit() with scrape, search_console, and GitHub tools for both chat and insights; includes mutation tools (annotations/goals/funnels).
    • Smarter detection (MAD z-score + WoW, incl. 0→N error spikes) across errors, revenue, vitals, and custom events; enrichment adds vitals p75 and GitHub deploy correlations.
    • Actionable insights: emits code_fix, investigate_further, add_custom_event, create_annotation; dashboard shows action pills, copies prompts, and includes root cause + investigation evidence.
    • Org settings: GSC and GitHub rows with a shared OAuth connect flow.
  • Refactors

    • Extracted prompts and unified tools via createToolkit(); updated DB/RPC schemas (insight actions, evidence, rootCause, investigationDepth) and tightened SQL validator with per-table alias/column checks.
    • Added shared OAuth helpers getOAuthToken/createCachedTokenFn with org-scoped lookup, 45‑min cache, and 5‑min negative-result cache when no account is connected; deduped GitHub/GSC/RPC; agent context now includes organizationId.
    • Cleaned up Slack streaming (eager task_update, early abort handling, fallback); aligned ai to ^6.0.188; added Search Console tests and refreshed detection/enrichment tests, including a fix to check previous-period sample size for vitals.

Written for commit 6ab5526. Summary will update on new commits. Review in cubic

izadoesdev added 14 commits May 27, 2026 13:36
…ation

- Extract getOAuthToken + createCachedTokenFn into shared oauth-token.ts,
  replacing identical copy-pasted token-fetch logic in search-console.ts,
  github-tools.ts, and generation.ts
- Extract getUserProviderToken in RPC integrations router, deduplicating
  the token lookup in checkSearchConsoleAccess and listGitHubRepos
- Extract useOAuthConnect hook in dashboard integrations UI, deduplicating
  the linkSocial mutation between GSC and GitHub rows
- Extract querySearchAnalytics as a standalone testable function
- Move ALWAYS_ON_TOOLS set to module scope in generation.ts
- Add 8 unit tests for search console query mapping, error handling, and
  request shape
Start the Slack stream eagerly with a task_update chunk (status:
in_progress) before the agent produces output, so users see the
animated thinking card instead of just a reaction emoji. Resolves
thinking to "complete" on first text flush and "error" on failures.

Also desloppified respond.ts: removed dead lazy-start logic
(tryStartStream, shouldStream, streamStartAttempted), extracted
flushAndStop/recoverFromError/logStreamError helpers, added early
bail-out for pre-aborted signals, and added a streaming-unavailable
fallback test.
Replace BAD_EVENTS_COLUMN_REPLACEMENTS blocklist with proper
AGENT_TABLE_COLUMNS schema map. Validates alias.column patterns
against the actual table schema — catches cross-table misuse like
es.browser_name on error_spans before it hits ClickHouse.
…eadability

- Extract prompt builders and data fetchers into prompts.ts (266 lines)
- generation.ts: 1076 → 804 lines
- detection.ts: replace if/else filter chain with METRIC_FILTERS lookup
- detection.ts: deduplicate 5 signals.push() blocks with makeWowSignal()
- detection.ts: 584 → 510 lines
- validate.ts: replace inline array with SENTIMENT_DIVERGENCE_TYPES Set
- Share OrgWebsiteRow interface between generation and prompts
- Extract isEnabled() for tool filter readability
…grade

- createInvestigationTools() shared across insights pipeline and chat agent
- Chat agent now has scrape, GSC, and GitHub tools (was scrape only)
- AgentContext gains organizationId for OAuth token lookups
- Add actions schema to insights (fix_goal, add_custom_event, etc.)
- Add actions column to analytics_insights table
- Chat agent prompt updated with investigation tool guidance
Add InsightAction type and render action buttons on insight cards.
Actions include fix_goal, add_custom_event, create_funnel, etc.
Currently shows a toast on click — wire to actual mutations next.
- createToolkit() assembles tools from capabilities (analytics,
  investigation, mutations, memory, dashboard)
- Chat agent simplified from 12 imports to one createToolkit() call
- Insights pipeline gains mutation tools (create_annotation, fix_goal,
  create_funnel) for executing actions during investigation
- Fix all lint errors (block statements, formatting)
…actions

- Add session query types to web_metrics description (interesting_sessions,
  session_list, session_flow, session_pages)
- Investigation prompt now guides agent to use session-level queries for
  user behavior analysis (step 6 in strategy)
- Agent told it can execute mutations directly (create_annotation with
  confirmed=true, update_goal for target mismatches)
- Verified: agent generates specific add_custom_event actions with exact
  event names, elements, and pages
- Add code_fix action type with prompt, file_hint, error_message params
- Dashboard copies code_fix prompt to clipboard on click
- investigate_further also copies prompt to clipboard
- Agent generates cursor-ready prompts with exact files, changes, and
  error context from GitHub search results
Deduplicate period-pair query boilerplate in enrichSegments and
enrichErrors. Both functions called queryFn 4 times with nearly
identical params differing only in date range. The helper creates
a curried function that handles the current/previous split.
@vercel
Copy link
Copy Markdown

vercel Bot commented May 27, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
databuddy-status Ready Ready Preview, Comment May 27, 2026 10:41pm
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
dashboard Skipped Skipped May 27, 2026 10:41pm
documentation Skipped Skipped May 27, 2026 10:41pm

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 27, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 286044af-79fb-44e1-a8f5-38ec1b98f65a

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch izadoesdev/intelligence-investigation-pipeline

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@unkey-deploy
Copy link
Copy Markdown

unkey-deploy Bot commented May 27, 2026

The latest updates on your projects. Learn more about Unkey Deploy

Name Status Preview Inspect Updated (UTC)
api (preview) Ready Visit Preview Inspect May 27, 2026 10:42pm

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 27, 2026

Greptile Summary

This PR overhauled the investigation pipeline end-to-end: detection now covers errors, revenue, web vitals, and custom events via WoW signals on top of the existing z-score path; enrichment adds a vitals context block and a queryPeriodPair helper; generation is refactored around a shared createToolkit() factory with smart model routing, early-stop logic, and an actions pipeline (code_fix, investigate_further, etc.) surfaced as pill buttons on insight cards.

  • Detection expanded: 5× more parallel ClickHouse queries per WoW run (summary + errors + revenue + vitals + custom events), new passesImpactFilter dispatch table, and all magic numbers extracted to named constants.
  • New tools: search_console (GSC integration), scrape-page Redis singleton refactor, createToolkit() shared across agents and MCP, per-table column validation in sql-validation.ts.
  • Schema & API: actions, rootCause, evidence, and investigationDepth added to analyticsInsights; dashboard insight cards render root cause, evidence, and action pills from these fields.

Confidence Score: 3/5

Not safe to merge as-is: insight generation writes will break in production without a DB migration for the new actions column, and the action pills the UI was built for will never render because the field is dropped before leaving the RPC layer.

Two independent issues affect the production path: the actions jsonb column is written by insightRow() on every generation run but no migration ships with the PR (PostgreSQL will reject the INSERT/UPDATE), and actions is fetched in getInsightsFromDb but omitted from both the return mapping and websiteInsightSchema, so action pills remain permanently empty even after the migration is applied. The rest of the change — detection expansion, toolkit refactor, GSC tool, column validation — is well-structured and low-risk.

packages/rpc/src/routers/insights.ts (actions field dropped from output), packages/db/src/drizzle/schema/analytics.ts (missing migration), and apps/dashboard/app/(main)/insights/_components/insight-card.tsx (action handlers unimplemented for most types).

Important Files Changed

Filename Overview
packages/rpc/src/routers/insights.ts Adds rootCause, evidence, investigationDepth, and actions to DB selects, but actions is never mapped into the return object or declared in websiteInsightSchema — action pills will silently not appear in the dashboard.
packages/db/src/drizzle/schema/analytics.ts New jsonb actions column added to analyticsInsights with no migration file included; any deployment without the migration will break insight generation writes.
apps/insights/src/detection.ts Significantly expanded: median/MAD z-score, WoW signals now cover errors, revenue, vitals, and custom events. Detection thresholds extracted to named constants. Logic appears sound.
apps/insights/src/generation.ts Major refactor: prompt helpers moved to prompts.ts, shared toolkit replaces ad-hoc tool construction, smart model routing added, early-stop when enough insights collected. Safe overall.
packages/ai/src/ai/tools/toolkit.ts New shared createToolkit() factory consolidates tool assembly across agents; clean capability-flag design with no logic issues.
packages/ai/src/ai/tools/utils/oauth-token.ts New OAuth helper with org-scoped fallback ordered by member role; cached token fn has no TTL which could cause stale token issues for long-lived tool instances.
packages/ai/src/ai/tools/search-console.ts New GSC tool wraps the searchAnalytics/query endpoint cleanly; proper error handling, timeout, and row capping at 25.
packages/db/src/clickhouse/sql-validation.ts Adds per-table column allowlists and qualified-column validation; replaces simple bad-column string replacements with a proper alias-resolution pass. Solid improvement.
apps/insights/src/prompts.ts Extracted prompt-building helpers from generation.ts; adds dismissed-patterns context and vitals block. Minor: uses
apps/dashboard/app/(main)/insights/_components/insight-card.tsx Adds rootCause, evidence, and action-pill sections to insight cards. Most action types click-through to no-op toasts; action data won't arrive until the RPC router is fixed.
packages/rpc/src/routers/integrations.ts New checkSearchConsoleAccess endpoint and getUserProviderToken helper; GitHub token fetch refactored to reuse the helper. Clean and correct.

Sequence Diagram

sequenceDiagram
    participant W as Insights Worker
    participant D as detection.ts
    participant E as enrichment.ts
    participant G as generation.ts
    participant TK as toolkit.ts
    participant AI as LLM (smart routing)
    participant DB as PostgreSQL
    participant CH as ClickHouse

    W->>D: detectSignals(websiteId)
    D->>CH: z-score (events_by_date)
    D->>CH: WoW x10 parallel (summary, errors, revenue, vitals, custom_events)
    D-->>W: DetectedSignal[]

    W->>E: enrichSignals(signals)
    E->>CH: segments + errors + vitals + annotations (parallel per signal)
    E->>DB: GitHub commits/PRs (via OAuth token)
    E-->>W: EnrichedSignal[]

    W->>G: analyzeWebsite(enrichedSignals)
    G->>DB: annotations + recentInsights + dismissedPatterns + siteContext
    G->>TK: createToolkit(investigation + mutations)
    TK-->>G: "scrape_page + search_console + github_* + annotation/goal tools"
    G->>AI: ToolLoopAgent (model by tier + critical-signal flag)
    AI->>CH: web_metrics / execute_sql
    AI->>TK: "search_console / scrape_page / github_*"
    AI-->>G: emit_insight (rootCause, evidence, actions)
    G->>DB: INSERT/UPDATE analyticsInsights (with actions column)
Loading

Comments Outside Diff (1)

  1. packages/rpc/src/routers/insights.ts, line 225-235 (link)

    P1 actions field selected but never returned

    actions is added to the getInsightsFromDb SELECT (line 205 in the new file), but the return-mapping block only adds rootCause, evidence, and investigationDepthactions is omitted. The websiteInsightSchema also has no actions field, so the ORPC output-validation layer will strip it even if it leaks through parseInsightShape. The same omission exists in the history endpoint's SELECT and mapping (lines 503–534). As a result, InsightActionPill components will never receive data and the action-pill UI will be permanently empty.

Reviews (1): Last reviewed commit: "feat(insights): add vitals context to en..." | Re-trigger Greptile

Comment on lines 236 to 238
investigationDepth: text("investigation_depth").$type<
"surface" | "investigated" | "deep"
>(),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 New actions column has no accompanying migration

analyticsInsights gains a jsonb actions column. Without a Drizzle migration applied before deploying, every INSERT/UPDATE that references this column (which insightRow() in generation.ts now always does via actions: insight.actions ?? null) will throw a PostgreSQL "column does not exist" error and break insight generation entirely. Ensure the migration is generated and included in the deployment runbook.

Comment on lines +396 to +415
return;
}
if (action.type === "investigate_further" && action.params.prompt) {
navigator.clipboard.writeText(action.params.prompt);
toast.success("Copied investigation prompt");
return;
}
toast.info(`${action.label}`);
};

return (
<button
className="inline-flex items-center gap-1 rounded-md border border-border/60 bg-background px-2 py-1 text-foreground/80 text-xs transition-colors hover:bg-accent hover:text-foreground"
onClick={handleClick}
type="button"
>
{ACTION_ICONS[action.type]}
{action.label}
</button>
);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Unimplemented action types silently no-op

fix_goal, create_funnel, add_custom_event, create_annotation, update_config, and add_tracking all fall through to toast.info(action.label) with no actual effect. Users who click these pills will see a toast that implies action but nothing will happen. Either wire them to real handlers or guard against rendering them until they're implemented.

Comment on lines +155 to +158
const targetCount = Math.max(
1,
Math.min(10, config.maxInsightsPerWebsite || 2)
);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 config.maxInsightsPerWebsite || 2 treats 0 as falsy and silently replaces it with 2. Use ?? so only null/undefined trigger the fallback.

Suggested change
const targetCount = Math.max(
1,
Math.min(10, config.maxInsightsPerWebsite || 2)
);
const targetCount = Math.max(
1,
Math.min(10, config.maxInsightsPerWebsite ?? 2)
);

Comment on lines +42 to +60
}

export function createCachedTokenFn(
providerId: string,
organizationId: string,
preferUserId?: string
): () => Promise<string | null> {
let cached: string | undefined;
return async () => {
if (cached !== undefined) {
return cached;
}
const token = await getOAuthToken(providerId, organizationId, preferUserId);
if (token) {
cached = token;
}
return token;
};
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 createCachedTokenFn caches tokens without a TTL

The closure caches the first non-null token indefinitely. OAuth access tokens (Google's in particular) expire in ~1 hour. If the same tool-instance is ever reused across agent runs that span the token's lifetime, all subsequent Search Console calls will receive 401 errors that surface as unhelpful tool-level failures. Consider storing a fetch-time timestamp and re-fetching after a safe TTL (e.g. 50 minutes).

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

13 issues found across 43 files

Confidence score: 2/5

  • There is high merge risk due to a concrete auth-scoping bug in packages/ai/src/ai/tools/utils/oauth-token.ts: token lookup is not organization-scoped, which can return another org’s user token and is user-impacting/security-sensitive.
  • apps/insights/src/prompts.ts introduces prompt-safety risk because user-provided annotation text is embedded without sanitization, and dismissed-pattern limiting lacks explicit ordering, so prompt behavior can be manipulated or inconsistent.
  • Several medium-severity runtime/reliability issues increase regression risk, including expired-token reuse in packages/ai/src/ai/tools/utils/oauth-token.ts, over-limit truncation in packages/ai/src/ai/insights/validate.ts, and schema mismatch in packages/ai/src/ai/schemas/smart-insights-output.ts that can reject valid non-string action params.
  • Pay close attention to packages/ai/src/ai/tools/utils/oauth-token.ts, apps/insights/src/prompts.ts, packages/ai/src/ai/schemas/smart-insights-output.ts, and packages/ai/src/ai/tools/toolkit.ts - these contain the highest-impact auth, prompt-safety, validation, and capability-gating risks.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/insights/src/prompts.ts">

<violation number="1" location="apps/insights/src/prompts.ts:49">
P1: Sanitize annotation text before embedding it in prompts to reduce prompt-injection/control-content risk from user-provided annotations.</violation>
</file>

<file name="packages/ai/src/ai/tools/github-tools.ts">

<violation number="1" location="packages/ai/src/ai/tools/github-tools.ts:34">
P2: Using `createCachedTokenFn` here drops negative-result caching, causing repeated DB token lookups when no GitHub account is connected.</violation>
</file>

<file name="packages/ai/src/ai/tools/search-console.ts">

<violation number="1" location="packages/ai/src/ai/tools/search-console.ts:11">
P2: Enforce `YYYY-MM-DD` date format in the input schema instead of relying on description text only.</violation>
</file>

<file name="packages/ai/src/ai/tools/toolkit.ts">

<violation number="1" location="packages/ai/src/ai/tools/toolkit.ts:58">
P2: Fail fast when `investigation` capability is requested without required `domain`/`organizationId` instead of silently omitting those tools.</violation>
</file>

<file name="packages/ai/src/ai/schemas/smart-insights-output.ts">

<violation number="1" location="packages/ai/src/ai/schemas/smart-insights-output.ts:148">
P2: `actions.params` is typed as `Record<string, string>`, but documented and existing action payloads need non-string values (e.g. funnel steps arrays, booleans). This makes valid actions fail schema validation.</violation>
</file>
Architecture diagram
sequenceDiagram
    participant UI as Dashboard UI
    participant API as API Route
    participant Agent as Agent Config
    participant Toolkit as createToolkit()
    participant Detection as detection.ts
    participant Enrichment as enrichment.ts
    participant Generation as generation.ts
    participant LLM as LLM (GPT/Sonnet/Opus)
    participant DB as Database
    participant Ext as External Services
    participant Slack as Slack Client

    Note over UI,Slack: Investigation Pipeline Overhaul - Runtime Flow

    UI->>API: Fetch insights for website
    API->>Generation: generateInsights(orgId, websiteId, config)

    Generation->>DB: fetchDismissedPatterns()
    DB-->>Generation: patterns marked "not helpful"

    Generation->>DB: fetchRecentAnnotations()
    DB-->>Generation: annotation timeline

    Generation->>DB: fetchRecentInsightsForPrompt()
    DB-->>Generation: recent insight titles

    Note over Detection,Generation: Detection Phase

    Generation->>Detection: detectSignals(params, queryFn)
    Detection->>Detection: z-score analysis on daily data
    Detection->>Detection: WoW analysis on summary_metrics
    Detection->>Detection: WoW error_summary, revenue_overview
    Detection->>Detection: WoW vitals_overview p75 values
    Detection->>Detection: WoW custom_events_discovery
    Detection->>Detection: Filter by MIN_THRESHOLD constants
    Detection-->>Generation: DetectedSignal[]

    Note over Enrichment,Generation: Enrichment Phase

    Generation->>Enrichment: enrichSignals(signals, queryFn, annotationQueryFn)
    Enrichment->>Enrichment: computeWindow() - full lookback for WoW
    Enrichment->>Enrichment: enrichSegments() - top movers by dimension
    Enrichment->>Enrichment: enrichErrors() - top new error types
    Enrichment->>Enrichment: enrichVitals() - p75 comparisons
    Enrichment->>Enrichment: enrichAnnotations() - timeline events
    Enrichment->>Ext: enrichGitHub() - commits/PRs matching keywords
    Enrichment-->>Generation: EnrichedSignal[]

    Note over Generation,Slack: Investigation & Generation Phase

    Generation->>LLM: Build investigation prompt with signals, org context
    Generation->>Toolkit: createToolkit({capabilities: [...]})

    Toolkit->>Toolkit: Compose tools by capability flags
    Toolkit->>Toolkit: Add analytics tools (get_data, execute_sql)
    Toolkit->>Toolkit: Add investigation tools (scrape_page, search_console, github)
    Toolkit->>Toolkit: Add mutation tools (create_annotation, create_funnel)
    Toolkit->>Toolkit: Add memory/dashboard tools

    LLM->>Agent: Execute toolkit tools during generation
    Agent->>Agent: Model routing: quick/balanced/deep based on config + critical signals
    alt hasCriticalSignals AND tier is balanced
        Agent->>Agent: Upgrade to Opus (deep model)
    end

    Agent->>Ext: scrape_page() via Firecrawl API
    Agent->>Ext: search_console() via Google Search Console API
    Agent->>Ext: github_commits/PRs via GitHub API
    Ext-->>Agent: Results

    Agent->>Agent: Call emit_insight with rootCause, evidence, investigationDepth
    Agent->>Agent: Call create_annotation to mark deploys
    Agent-->>Generation: ParsedInsight[] with actions

    Note over Generation,UI: Validation & Storage

    Generation->>Generation: validateInsight() - truncates description/suggestion >300 chars
    Generation->>DB: Store insight with actions, evidence, rootCause
    DB-->>Generation: insight ID

    Generation->>UI: Return insight data
    UI->>UI: toInsightCardViewModel() - separate metrics vs investigationEvidence
    UI->>UI: Render action pills (code_fix, investigate_further, etc.)

    alt code_fix action clicked
        UI->>UI: navigator.clipboard.writeText(prompt)
        UI->>UI: toast("Copied for Cursor/Claude Code")
    end

    Note over Slack,Agent: Slack Thinking Experience

    Slack->>Agent: streamAgentToSlack(run)
    Agent->>Slack: startThinkingStream() - immediate "thinking" card
    Slack->>Slack: Show task_update "in_progress" with plan mode
    Agent->>Agent: Stream agent response chunks
    alt Thinking resolved
        Agent->>Slack: appendStream() with chunk + task_update "complete"
    else Error encountered
        Agent->>Slack: appendStream() with task_update "error" + error text
    end
    Agent->>Slack: stopStream() with final markdown_text

    alt Streaming unavailable
        Agent->>Slack: say() fallback with agent error message
    end

    Note over UI,DB: Settings Integration

    UI->>API: checkSearchConsoleAccess()
    API->>Ext: GET /webmasters/v3/sites
    Ext-->>API: 200 OK
    API-->>UI: { hasAccess: true }

    UI->>API: linkSocial("google", GSC_SCOPES)
    API->>API: OAuth flow with Google Search Console scope
    API-->>UI: Connection established
Loading

Shadow auto-approve: would not auto-approve because issues were found.
Tip: instead of fixing issues one by one fix them all with cubic

Re-trigger cubic

const lines = rows.map((row) => {
const date = dayjs(row.xValue).format("YYYY-MM-DD");
const tags = row.tags?.length ? ` [${row.tags.join(", ")}]` : "";
return `- ${date}: ${row.text}${tags}`;
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot May 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Sanitize annotation text before embedding it in prompts to reduce prompt-injection/control-content risk from user-provided annotations.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/insights/src/prompts.ts, line 49:

<comment>Sanitize annotation text before embedding it in prompts to reduce prompt-injection/control-content risk from user-provided annotations.</comment>

<file context>
@@ -0,0 +1,288 @@
+	const lines = rows.map((row) => {
+		const date = dayjs(row.xValue).format("YYYY-MM-DD");
+		const tags = row.tags?.length ? ` [${row.tags.join(", ")}]` : "";
+		return `- ${date}: ${row.text}${tags}`;
+	});
+
</file context>
Fix with Cubic

Comment thread packages/ai/src/ai/tools/utils/oauth-token.ts
Comment thread packages/ai/src/ai/tools/utils/oauth-token.ts
Comment thread apps/insights/src/prompts.ts
Comment thread packages/ai/src/ai/insights/validate.ts Outdated
Comment thread apps/insights/src/detection.ts
Object.assign(tools, ANALYTICS_TOOLS);
}

if (caps.has("investigation") && params.domain && params.organizationId) {
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot May 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Fail fast when investigation capability is requested without required domain/organizationId instead of silently omitting those tools.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/ai/src/ai/tools/toolkit.ts, line 58:

<comment>Fail fast when `investigation` capability is requested without required `domain`/`organizationId` instead of silently omitting those tools.</comment>

<file context>
@@ -0,0 +1,82 @@
+		Object.assign(tools, ANALYTICS_TOOLS);
+	}
+
+	if (caps.has("investigation") && params.domain && params.organizationId) {
+		Object.assign(
+			tools,
</file context>
Fix with Cubic

Comment thread apps/insights/src/enrichment.ts Outdated
]),
label: z.string().describe("Button label (e.g. 'Fix goal target')"),
params: z
.record(z.string(), z.string())
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot May 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: actions.params is typed as Record<string, string>, but documented and existing action payloads need non-string values (e.g. funnel steps arrays, booleans). This makes valid actions fail schema validation.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/ai/src/ai/schemas/smart-insights-output.ts, line 148:

<comment>`actions.params` is typed as `Record<string, string>`, but documented and existing action payloads need non-string values (e.g. funnel steps arrays, booleans). This makes valid actions fail schema validation.</comment>

<file context>
@@ -121,21 +123,41 @@ export const insightSchema = z.object({
+				]),
+				label: z.string().describe("Button label (e.g. 'Fix goal target')"),
+				params: z
+					.record(z.string(), z.string())
+					.describe(
+						"Action-specific parameters. code_fix: {prompt, file_hint, error_message} — generates a cursor/claude-code-ready prompt."
</file context>
Suggested change
.record(z.string(), z.string())
.record(z.string(), z.unknown())
Fix with Cubic

Comment thread apps/dashboard/app/(main)/insights/_components/insight-card.tsx
- OAuth token: scope preferUserId lookup to org membership (P1)
- OAuth token: add 45-min TTL to cached tokens (P2)
- Error detection: catch 0→N error spikes (P2)
- Prompts: use ?? instead of || for maxInsights (P2)
- Prompts: order dismissed patterns by recency (P2)
- Validate: fix truncation overflow (P2)
- Dashboard: handle clipboard write failures (P2)
@izadoesdev izadoesdev force-pushed the izadoesdev/intelligence-investigation-pipeline branch from 34446f4 to 031291c Compare May 27, 2026 22:18
@vercel vercel Bot temporarily deployed to Preview – documentation May 27, 2026 22:18 Inactive
- Vitals enrichment: check previous-period sample size too (P2)
- OAuth cache: negative-result caching with 5-min TTL to avoid
  repeated DB lookups when no account connected (P2)
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 issues found across 3 files (changes from recent commits).

Shadow auto-approve: would not auto-approve. Auto-approval blocked by 5 unresolved issues from previous reviews.

Re-trigger cubic

@izadoesdev izadoesdev merged commit e034fae into staging May 27, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant