Skip to content

feat(signals): add anomaly-search and anomaly-insight-get endpoints - #122849

Merged
trunk-io[bot] merged 7 commits into
masterfrom
posthog/anomaly-search-endpoints
Oct 25, 2026
Merged

trunk-io[bot] merged 7 commits into
masterfrom
posthog/anomaly-search-endpoints

Conversation

@posthog

@posthog posthog Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Problem

  • Users, their agents and the anomaly scout cannot ask which saved insights were anomalous in a date range.
  • The scoring tick writes one $anomaly_score event per series and bucket, but nothing reads them back.
  • A correct reader must keep the latest result per bucket, drop warm-up rows, and never compare raw scores across series. Every caller would have to hand-roll that HogQL.

Why: a self-driving inbox report picked up the spec in #122393, so the scoring output becomes usable.

Refs #122393

Origin

  • Issues: #122393
  • Scout: a custom scout
  • First signal: 2026-10-22
  • Inbox report: open
  • Task started by: a person, from the inbox

Changes

  • Agents get two new MCP tools, anomaly-search and anomaly-insight-get, gated by the existing anomalies-search flag.
  • GET /api/projects/:id/signals/anomalies/search/ returns the anomaly rate per series (or per insight with group_by=insight), with baseline_rate, coverage, scored_through and up to 5 flagged points.
  • GET /api/projects/:id/signals/anomalies/insight/ returns every series of one insight with its buckets oldest first. Unscored buckets come back as scored: false with null values, never 0.
  • Both actions return 404 when the flag is off, need insight:read, and drop insights the user cannot read.
  • An empty search says why in message: scoring is off for the project, nothing was scored in range, or nothing flagged among insights_scored_in_range of watched_insights.
  • Ranking uses anomaly_rate - baseline_rate, each smoothed by 10 buckets toward the baseline (or the project prior). So 3 flagged of 10 beats 1 of 1, and a usually quiet series beats an always noisy one. Raw scores never cross series.
  • The read layer is one HogQL scan with LIMIT 1 BY series_key, bucket_start on the newest $anomaly_scored_at, using ClickHouseUser.DEFAULT and the default workload. The scan covers the range plus the 30-day baseline.
  • Riskiest part: anomaly_scores/read.py and the rate rules in search.py. The product_analytics facade gains viewable_insights, a bulk access-filtered insight lookup.
  • Reads capture an anomaly search read event (endpoint, via_mcp, row counts) to measure adoption.
  • Mechanical: regenerated OpenAPI types, MCP tool definitions and two schema snapshots.

How did you test this code?

Test rationale: test_anomaly_search.py builds the cases live data lacks: a bucket rescored with a different flag, a warm-up bucket and an unscored gap. Pure SimpleTestCases cover the two ranking rules and the summed rollup. ClickHouse-backed API tests cover search counts, insight buckets oldest first, series_key narrowing, warm-up display, the 404 for another team's insight, the 404 with the flag off, and scoring_enabled: false outside the payload. The nearest existing test (TestScoredBuckets in test_anomaly_scoring_tick.py) covers only the tick's read of the newest bucket.

  • The series_key test caught a real bug while writing: {filters} is a reserved HogQL placeholder and silently dropped the scope filter. The read layer now uses {scope}.
  • The new test file is added to .github/new-events-schema-targets.txt, because it reads event properties.
  • Not checked: calls against real project data with the flag on, and repo-wide mypy (only the changed files were type-checked).

Release status

  • This change is behind a feature flag and is not available to users

Docs update

None. No existing doc covers anomaly scoring.

🤖 Agent context

Autonomy: Fully autonomous

Agent: PostHog Desktop (Claude Code), claude-opus-5-5

  • Started from a self-driving inbox report on issue feat(signals): add anomaly-search and anomaly-insight-get endpoints and MCP tools #122393. A PR search for anomaly-search, anomaly-insight-get and 122393 found no open PR.
  • Skills invoked: /improving-drf-endpoints, /implementing-mcp-tools, /writing-dataclasses, /writing-tests, /writing-user-facing-copy, /writing-pr-descriptions.
  • The ranking prior (10 buckets, with a 0.05 default rate when no series has a baseline) is a judgment call. A smaller prior let 1 flagged of 1 outrank 3 of 10, which the spec rules out.
  • Out of scope, as the issue says: grouping flags into incidents, and the anomaly scout reading these tools.

Created with PostHog Desktop from an inbox report

🤖 Generated with Claude Code

@posthog posthog Bot added the self-driving label Oct 23, 2026
@posthog
posthog Bot marked this pull request as ready for review October 23, 2026 19:31
@trunk-io

trunk-io Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

😎 Merged directly without going through the merge queue, as the queue was empty and the PR was up to date with the target branch - details.

@posthog
posthog Bot requested review from rnegron and webjunkie October 23, 2026 19:31
@parameterai

parameterai Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Risk: No findings

This increment is a rebase plus regenerated MCP/OpenAPI artifacts; the PR's own code (anomaly-search and anomaly-insight-get read endpoints) is unchanged in substance. Authorization is fail-closed throughout: both actions require insight:read, gate on the anomalies-search flag, and drop insights the caller cannot view via the team-scoped, access-filtered viewable_insights lookup. HogQL reads bind every value as a constant and date ranges are capped at 366 days, so I found no new exploitable surface in this increment.

Sentinel reviewed f111a25 · Review settings

@pr-assigner-resolver-posthog
pr-assigner-resolver-posthog Bot requested review from a team October 23, 2026 19:32
@pr-assigner-resolver-posthog

Copy link
Copy Markdown

👀 Auto-assigned reviewers

These soft owners were skipped because they only have minor changes here. Nothing blocks merge, so self-assign if you'd like a look:

  • @PostHog/team-context-and-mcp (services/mcp/tests/owners.yaml)

Soft owners come from each directory's owners.yaml and each product's product.yaml (resolved nearest-file-wins). For a skipped owner, the locator is the file that decided it. Generated files and lockfiles are ignored when deciding ownership.

@github-actions

github-actions Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

🤖 CI report

⚠️ Trunk lane — backend Python lane

This PR is assigned to the backend Python lane. It runs backend Python tests and may merge in parallel with PRs in other lanes.

✅ Complexity (TypeScript) — clean

Cyclomatic complexity above the limit in changed typescript files (10 for production files, 15 for test files). Warn only: worth simplifying when you next touch these functions.

✅ Duplication (Python) — clean

New Python code duplication introduced by this branch. Fails at 70+ tokens in app code, or 150+ tokens when both copies live in test files. Advisory while the gate proves itself: extract a shared helper instead of copying.

✅ Duplication (TypeScript) — clean

New TypeScript code duplication introduced by this branch. Fails at 70+ tokens in app code, or 150+ tokens when both copies live in test files. Advisory while the gate proves itself: extract a shared helper instead of copying.

✅ Bundle size — no change

Uncompressed size of every built .js bundle, compared against the base branch.

Total: 76.61 MiB · no change

No file changed by more than 1000 B.

Posted automatically by build-bundle-size-report · uncompressed bytes from dist-report

✅ Eager graph — within budget

How much code each root ships on the eager path — downloaded and parsed before the surface is interactive. Measured from the esbuild output chunks (post-tree-shake, static imports only); lazy import() / React.lazy chunks are not counted.

Root Eager (shipped) Δ vs base Budget
entry (logged-out pages, app bootstrap)
src/index.tsx
1019.4 KiB · 24 files no change █████████░ 87.0% of 1.14 MiB
logged-out boot: index + App + bootApp (preloaded by every page, including /login)
src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
2.95 MiB · 620 files no change ██████████ 97.4% of 3.03 MiB
authenticated shell (every logged-in page)
src/scenes/AuthenticatedShell.tsx
7.44 MiB · 2,549 files no change ██████████ 99.2% of 7.50 MiB
dashboard scene
src/scenes/dashboard/Dashboard.tsx
9.89 MiB · 3,716 files no change ██████████ 98.8% of 10.01 MiB
today home path
src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
7.61 MiB · 2,641 files no change ██████████ 98.4% of 7.74 MiB
AI-first home path
src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx
7.86 MiB · 2,633 files no change ██████████ 99.4% of 7.91 MiB
events scene
src/scenes/activity/explore/EventsScene.tsx
9.34 MiB · 3,503 files no change ██████████ 97.4% of 9.59 MiB
web analytics scene
src/scenes/web-analytics/WebAnalyticsScene.tsx
10.25 MiB · 3,735 files no change █████████░ 94.6% of 10.83 MiB
replay detail scene
src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
8.38 MiB · 3,084 files no change █████████░ 88.5% of 9.47 MiB

🟢 node_modules/monaco-editor/ stays out of src/index.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/index.tsx
🟢 node_modules/@posthog/brand/dist/generated/hoggies/svg/ stays out of src/index.tsx
🟢 node_modules/@posthog/brand/dist/generated/hoggies/components/ stays out of src/index.tsx
🟢 node_modules/monaco-editor/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/layout/navigation-3000/navigationLogic.tsx stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/scenes/dashboard/dashboardLogic.tsx stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/lemon-ui/LemonMarkdown/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/components/RichContentEditor/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/components/CodeSnippet/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/taxonomy/core-filter-definitions-by-group.json stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 node_modules/zod/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/scenes/billing/billingLogic.tsx stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/components/ProductEmptyState/productSetupPreloadLogic.ts stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 node_modules/monaco-editor/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/scenes/AuthenticatedShell.tsx
🟢 products/dashboards/frontend/widgets/previews/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/scenes/session-recordings/player/sessionRecordingPlayerLogic.ts stays out of src/scenes/AuthenticatedShell.tsx
🟢 products/wizard/frontend/runs/WizardRunDetailsDrawer.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/layout/today/TodayShell.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/layout/today/TodayContextPanelFloating.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/layout/today/TodaySidePanel.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/layout/today/TodayTopBar.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/layout/today/todayRailItems.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 zod/v4/locales/de.js stays out of src/scenes/AuthenticatedShell.tsx
🟢 node_modules/@posthog/brand/dist/generated/hoggies/svg/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 node_modules/@posthog/brand/dist/generated/hoggies/components/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/scenes/session-recordings/playlist/SessionRecordingsPlaylist.tsx stays out of src/scenes/dashboard/Dashboard.tsx
🟢 src/scenes/web-analytics/tiles/WebAnalyticsTile.tsx stays out of src/scenes/dashboard/Dashboard.tsx
🟢 src/queries/validators.js stays out of src/scenes/dashboard/Dashboard.tsx
🟢 src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
🟢 src/scenes/project-homepage/today/TodayReportPage.tsx stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
🟢 src/queries/Query/Query.tsx stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
🟢 packages/quill/packages/charts/ stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
🟢 products/posthog_ai/frontend/components/tool/widgets/VisualizationWidget.tsx stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx
🟢 products/posthog_ai/frontend/components/tool/widgets/RecordingsWidget.tsx stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx
🟢 src/queries/Query/Query.tsx stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx
🟢 products/posthog_ai/frontend/api/primitives.ts stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx
🟢 src/scenes/notebooks/Notebook/notebookLogic.ts stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx
🟢 src/scenes/session-recordings/playlist/SessionRecordingsPlaylist.tsx stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 src/scenes/web-analytics/tiles/WebAnalyticsTile.tsx stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 src/queries/validators.js stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 src/scenes/web-analytics/LiveMetricsDashboard/LiveWebAnalyticsMetrics.tsx stays out of src/scenes/web-analytics/WebAnalyticsScene.tsx
🟢 products/product_analytics/frontend/insights/trends/WorldMap/countryVectors.tsx stays out of src/scenes/web-analytics/WebAnalyticsScene.tsx
🟢 src/scenes/settings/SettingsMap.tsx stays out of src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
🟢 @jspm/core/nodelibs/browser/fs stays out of src/scenes/session-recordings/detail/SessionRecordingDetail.tsx

Largest files eagerly shipped from src/index.tsx
Size File
126.8 KiB ../node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom.production.min.js
24.6 KiB ../node_modules/.pnpm/[email protected]/node_modules/buffer/index.js
6.3 KiB ../node_modules/.pnpm/[email protected]/node_modules/react/cjs/react.production.min.js
4.7 KiB ../node_modules/.pnpm/@[email protected]/node_modules/@jspm/core/nodelibs/browser/process.js
4.0 KiB ../node_modules/.pnpm/[email protected]/node_modules/scheduler/cjs/scheduler.production.min.js
1.7 KiB ../node_modules/.pnpm/[email protected]/node_modules/base64-js/index.js
1.6 KiB src/index.tsx
1.3 KiB src/lib/utils/bootTiming.ts
1.2 KiB src/RootErrorBoundary.tsx
949 B src/scenes/ChunkLoadErrorBoundary.tsx
Largest files eagerly shipped from src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
Size File
322.5 KiB ../node_modules/.pnpm/[email protected]_@[email protected][email protected]/node_modules/posthog-js/dist/module.mjs
215.9 KiB ../node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@posthog/icons/dist/posthog-icons.es.js
126.8 KiB ../node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom.production.min.js
99.8 KiB src/products.tsx
86.2 KiB src/lib/api.ts
68.2 KiB src/lib/lemon-ui/icons/icons.tsx
41.9 KiB ../node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@dnd-kit/core/dist/core.esm.js
36.4 KiB ../node_modules/.pnpm/[email protected]_patch_hash=139b8d1f1304f9d9da452a9a1244c94ea679dbcb85687d8999563146879fb6f5_react@18.3.1/node_modules/kea/lib/index.cjs.js
27.0 KiB ../node_modules/.pnpm/[email protected]/node_modules/tailwind-merge/dist/bundle-mjs.mjs
24.6 KiB ../node_modules/.pnpm/[email protected]/node_modules/buffer/index.js
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx
Size File
322.5 KiB ../node_modules/.pnpm/[email protected]_@[email protected][email protected]/node_modules/posthog-js/dist/module.mjs
285.9 KiB src/taxonomy/core-filter-definitions-by-group.json
239.8 KiB ../packages/quill/packages/quill/dist/index.js
215.9 KiB ../node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@posthog/icons/dist/posthog-icons.es.js
153.8 KiB ../node_modules/.pnpm/[email protected]/node_modules/re2js/build/index.esm.js
126.8 KiB ../node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom.production.min.js
99.8 KiB src/products.tsx
94.5 KiB ../node_modules/.pnpm/@[email protected]_@[email protected]/node_modules/@tiptap/core/dist/index.js
92.5 KiB ../node_modules/.pnpm/[email protected]/node_modules/prosemirror-view/dist/index.js
86.2 KiB src/lib/api.ts
Largest files eagerly shipped from src/scenes/dashboard/Dashboard.tsx
Size File
322.5 KiB ../node_modules/.pnpm/[email protected]_@[email protected][email protected]/node_modules/posthog-js/dist/module.mjs
285.9 KiB src/taxonomy/core-filter-definitions-by-group.json
239.8 KiB ../packages/quill/packages/quill/dist/index.js
215.9 KiB ../node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@posthog/icons/dist/posthog-icons.es.js
153.8 KiB ../node_modules/.pnpm/[email protected]/node_modules/re2js/build/index.esm.js
144.1 KiB ../packages/quill/packages/primitives/dist/index.js
126.8 KiB ../node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom.production.min.js
99.8 KiB src/products.tsx
94.5 KiB ../node_modules/.pnpm/@[email protected]_@[email protected]/node_modules/@tiptap/core/dist/index.js
92.5 KiB ../node_modules/.pnpm/[email protected]/node_modules/prosemirror-view/dist/index.js
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
Size File
322.5 KiB ../node_modules/.pnpm/[email protected]_@[email protected][email protected]/node_modules/posthog-js/dist/module.mjs
285.9 KiB src/taxonomy/core-filter-definitions-by-group.json
239.8 KiB ../packages/quill/packages/quill/dist/index.js
215.9 KiB ../node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@posthog/icons/dist/posthog-icons.es.js
153.8 KiB ../node_modules/.pnpm/[email protected]/node_modules/re2js/build/index.esm.js
126.8 KiB ../node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom.production.min.js
99.8 KiB src/products.tsx
94.5 KiB ../node_modules/.pnpm/@[email protected]_@[email protected]/node_modules/@tiptap/core/dist/index.js
92.5 KiB ../node_modules/.pnpm/[email protected]/node_modules/prosemirror-view/dist/index.js
86.2 KiB src/lib/api.ts
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx
Size File
322.5 KiB ../node_modules/.pnpm/[email protected]_@[email protected][email protected]/node_modules/posthog-js/dist/module.mjs
285.9 KiB src/taxonomy/core-filter-definitions-by-group.json
239.8 KiB ../packages/quill/packages/quill/dist/index.js
215.9 KiB ../node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@posthog/icons/dist/posthog-icons.es.js
153.8 KiB ../node_modules/.pnpm/[email protected]/node_modules/re2js/build/index.esm.js
144.1 KiB ../packages/quill/packages/primitives/dist/index.js
126.8 KiB ../node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom.production.min.js
99.8 KiB src/products.tsx
94.5 KiB ../node_modules/.pnpm/@[email protected]_@[email protected]/node_modules/@tiptap/core/dist/index.js
92.5 KiB ../node_modules/.pnpm/[email protected]/node_modules/prosemirror-view/dist/index.js
Largest files eagerly shipped from src/scenes/activity/explore/EventsScene.tsx
Size File
322.5 KiB ../node_modules/.pnpm/[email protected]_@[email protected][email protected]/node_modules/posthog-js/dist/module.mjs
285.9 KiB src/taxonomy/core-filter-definitions-by-group.json
239.8 KiB ../packages/quill/packages/quill/dist/index.js
215.9 KiB ../node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@posthog/icons/dist/posthog-icons.es.js
153.8 KiB ../node_modules/.pnpm/[email protected]/node_modules/re2js/build/index.esm.js
144.1 KiB ../packages/quill/packages/primitives/dist/index.js
126.8 KiB ../node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom.production.min.js
99.8 KiB src/products.tsx
94.5 KiB ../node_modules/.pnpm/@[email protected]_@[email protected]/node_modules/@tiptap/core/dist/index.js
92.5 KiB ../node_modules/.pnpm/[email protected]/node_modules/prosemirror-view/dist/index.js
Largest files eagerly shipped from src/scenes/web-analytics/WebAnalyticsScene.tsx
Size File
322.5 KiB ../node_modules/.pnpm/[email protected]_@[email protected][email protected]/node_modules/posthog-js/dist/module.mjs
285.9 KiB src/taxonomy/core-filter-definitions-by-group.json
239.8 KiB ../packages/quill/packages/quill/dist/index.js
215.9 KiB ../node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@posthog/icons/dist/posthog-icons.es.js
182.9 KiB src/queries/validators.js
153.8 KiB ../node_modules/.pnpm/[email protected]/node_modules/re2js/build/index.esm.js
144.1 KiB ../packages/quill/packages/primitives/dist/index.js
126.8 KiB ../node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom.production.min.js
99.8 KiB src/products.tsx
94.5 KiB ../node_modules/.pnpm/@[email protected]_@[email protected]/node_modules/@tiptap/core/dist/index.js
Largest files eagerly shipped from src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
Size File
322.5 KiB ../node_modules/.pnpm/[email protected]_@[email protected][email protected]/node_modules/posthog-js/dist/module.mjs
316.1 KiB ../node_modules/.pnpm/[email protected]_@[email protected][email protected]/node_modules/posthog-js/dist/rrweb.js
285.9 KiB src/taxonomy/core-filter-definitions-by-group.json
239.8 KiB ../packages/quill/packages/quill/dist/index.js
215.9 KiB ../node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@posthog/icons/dist/posthog-icons.es.js
153.8 KiB ../node_modules/.pnpm/[email protected]/node_modules/re2js/build/index.esm.js
126.8 KiB ../node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom.production.min.js
99.8 KiB src/products.tsx
94.5 KiB ../node_modules/.pnpm/@[email protected]_@[email protected]/node_modules/@tiptap/core/dist/index.js
92.5 KiB ../node_modules/.pnpm/[email protected]/node_modules/prosemirror-view/dist/index.js

Posted automatically by check-eager-graph · sizes are eager output bytes (shipped, post-tree-shake) from the esbuild metafile · part of #32479

✅ Toolbar bundle — eager 2.29 MiB within budget

What the toolbar ships to customer pages, measured from the esbuild output (minified, post-tree-shake). The eager set is the entry plus everything statically imported from it — fetched before any feature runs; deferred chunks load lazily. The eager guardrail is 5.72 MiB. Each output file must also stay below 10 MB, where CloudFront stops compressing it. The module boundary is enforced separately by check-toolbar-graph.

Metric Size Δ vs base Budget
Eager (shipped)
entry + static imports
2.29 MiB · 18 files no change ████░░░░░░ 40.0% of 5.72 MiB
Deferred (lazy) 2.11 MiB · 40 files no change n/a — loads on demand
Loader dist/toolbar.js 1.2 KiB no change █░░░░░░░░░ 6.0% of 19.5 KiB
Largest eagerly-shipped chunks
Size File
902.2 KiB dist/toolbar/toolbar-app-CRD3W4A7.css
692.2 KiB dist/toolbar/chunk-chunk-KZJS3INZ.js
260.7 KiB dist/toolbar/chunk-chunk-L6XVLVLY.js
131.8 KiB dist/toolbar/chunk-chunk-FDH2IBXT.js
130.4 KiB dist/toolbar/chunk-chunk-LD5GP6L7.js
74.8 KiB dist/toolbar/toolbar-app-TXKYX4J5.js
69.0 KiB dist/toolbar/chunk-chunk-TSAL54PB.js
35.6 KiB dist/toolbar/chunk-chunk-WFB7UOXI.js
21.7 KiB dist/toolbar/chunk-chunk-CRQXLGRI.js
6.8 KiB dist/toolbar/chunk-chunk-DV7IWQNF.js

Posted automatically by check-toolbar-size · sizes are toolbar output bytes (shipped, post-tree-shake) from the esbuild metafile

✅ Dist folder size — 🔺 +46.7 KiB (+0.0%)

Total size of the built frontend/dist folder (all assets), compared against the base branch.

Total: 964.85 MiB · 🔺 +46.7 KiB (+0.0%)

ℹ️ MCP UI apps size — 34 app(s), 27969.1 KB JS

Built size of each MCP UI app (main.js + styles.css).

App JS CSS
debug 844.3 KB 209.1 KB
action 767.7 KB 209.1 KB
action-list 835.3 KB 209.1 KB
cohort 766.7 KB 209.1 KB
cohort-list 834.3 KB 209.1 KB
email-template 766.6 KB 209.1 KB
error-details 771.6 KB 209.1 KB
error-issue 768.9 KB 209.1 KB
error-issue-list 836.7 KB 209.1 KB
experiment 832.4 KB 209.1 KB
experiment-list 836.1 KB 209.1 KB
experiment-results 834.9 KB 209.1 KB
feature-flag 834.7 KB 209.1 KB
feature-flag-list 838.4 KB 209.1 KB
feature-flag-testing 770.0 KB 209.1 KB
inline-scan 767.2 KB 209.1 KB
insight-actors 833.8 KB 209.1 KB
llm-costs 831.1 KB 209.1 KB
session-recording 768.9 KB 209.1 KB
survey 768.3 KB 209.1 KB
survey-global-stats 831.1 KB 209.1 KB
survey-list 836.0 KB 209.1 KB
survey-stats 831.1 KB 209.1 KB
trace-span 767.1 KB 209.1 KB
trace-span-list 835.2 KB 209.1 KB
vision-observation-list 834.4 KB 209.1 KB
workflow 767.0 KB 209.1 KB
workflow-list 834.7 KB 209.1 KB
workflow-setup-status 766.7 KB 209.1 KB
query-results 1086.5 KB 209.1 KB
render-ui 1162.4 KB 209.1 KB
visual-review-snapshots 771.6 KB 209.1 KB
workflow-data-suggestions 769.4 KB 209.1 KB
workflow-sending-rules 768.0 KB 209.1 KB
ℹ️ MCP agent API — agent-facing tool changes

What this PR changes for agents, from the tool schema snapshots and tool definitions.

Tools added (2): anomaly-insight-get (952 chars), anomaly-search (1,265 chars)

⚠️ Playwright — 2 flaky

🎭 Playwright report · View test results →

⚠️ 2 flaky tests:

  • Redirect to appropriate place after login (chromium)
  • Creating a SQL insight with a variable and overriding it on a dashboard (chromium)

These issues are not necessarily caused by your changes.
Annoyed by this section? Help fix flakies and failures and it will go green!

⚠️ Backend coverage — 83.0% of changed backend lines covered — 113 uncovered

🧪 Backend test coverage

Patch coverage — changed backend lines (products + core): █████████████████░░░ 83.0% (575 / 688)

File Patch Uncovered changed lines
products/product_analytics/backend/facade/api.py 16.7% 233–236, 239
products/product_analytics/backend/facade/contracts.py 40.0% 151–152, 154
products/signals/backend/anomaly_scores/search.py 73.5% 70–71, 82–85, 87, 96–99, 104–109, 111, 116–118, 126–127, 129, 138–140, 142–149, 192–194, 196, 205, 219, 259–262, 267–268, 349–350, 367–368, 374
products/signals/backend/anomaly_scores/read.py 75.4% 103–105, 112–119, 121–125, 127, 129, 150–151, 156–157, 159, 170–171, 176–177, 184–190, 197–201, 223, 226–227, 279, 392, 412
products/signals/backend/presentation/anomalies.py 95.8% 48–49, 361–362, 365, 367, 402–403

🤖 Agents: add a test only if an uncovered line exposes a realistic regression that existing tests miss. Otherwise explain why no new test is needed under "How did you test this code?". Gap list: the patch-coverage artifact on this run (gh run download 317554461519494 -n patch-coverage), or the coverage-data block at the end of this comment.

Per-product line coverage (touched products)
Product Coverage Lines
platform_features ██░░░░░░░░░░░░░░░░░░ 12.1% 7 / 58
demo ███████████░░░░░░░░░ 56.4% 1,542 / 2,736
data_tools ████████████░░░░░░░░ 60.9% 95 / 156
warehouse_sources_queue █████████████░░░░░░░ 65.2% 2,157 / 3,306
authorization ████████████████░░░░ 79.7% 181 / 227
batch_exports ████████████████░░░░ 81.6% 22,910 / 28,069
apm █████████████████░░░ 84.1% 1,306 / 1,553
engineering_analytics █████████████████░░░ 85.0% 11,463 / 13,482
commands █████████████████░░░ 85.5% 1,618 / 1,893
mcp_analytics █████████████████░░░ 86.2% 5,720 / 6,638
ml_inference █████████████████░░░ 86.3% 524 / 607
posthog_ai ██████████████████░░ 87.9% 4,296 / 4,886
notebooks ██████████████████░░ 88.5% 15,330 / 17,321
dashboards ██████████████████░░ 88.6% 7,709 / 8,703
warehouse_suggestions ██████████████████░░ 88.6% 3,047 / 3,438
mcp_registry ██████████████████░░ 89.0% 1,596 / 1,794
webmcp ██████████████████░░ 89.6% 240 / 268
cohorts ██████████████████░░ 89.6% 8,568 / 9,559
product_tours ██████████████████░░ 89.7% 1,355 / 1,510
signals ██████████████████░░ 89.8% 85,663 / 95,418
visual_review ██████████████████░░ 90.6% 9,858 / 10,875
tasks ██████████████████░░ 90.7% 80,867 / 89,128
managed_warehouse ██████████████████░░ 91.0% 12,234 / 13,441
data_warehouse ██████████████████░░ 91.1% 15,286 / 16,781
canvas ██████████████████░░ 91.1% 7,998 / 8,776
aeo ██████████████████░░ 91.2% 1,602 / 1,756
today ██████████████████░░ 91.2% 3,798 / 4,163
data_modeling ██████████████████░░ 91.4% 10,577 / 11,573
autoresearch ██████████████████░░ 91.4% 11,618 / 12,705
cdp ██████████████████░░ 91.5% 10,251 / 11,206
business_knowledge ██████████████████░░ 91.6% 10,017 / 10,934
metrics ██████████████████░░ 91.7% 10,625 / 11,588
slack_app ██████████████████░░ 91.7% 21,398 / 23,330
wizard ██████████████████░░ 91.7% 6,870 / 7,490
streamlit_apps ██████████████████░░ 91.9% 3,139 / 3,415
error_tracking ██████████████████░░ 92.1% 18,833 / 20,454
conversations ██████████████████░░ 92.2% 30,216 / 32,776
review_hog ██████████████████░░ 92.2% 17,749 / 19,244
stamphog ███████████████████░ 92.6% 8,814 / 9,519
early_access_features ███████████████████░ 92.6% 1,339 / 1,446
managed_migrations ███████████████████░ 92.6% 1,630 / 1,760
alerts_platform ███████████████████░ 92.8% 7,619 / 8,211
notifications ███████████████████░ 93.0% 1,199 / 1,289
web_analytics ███████████████████░ 93.3% 26,048 / 27,923
ai_training ███████████████████░ 93.3% 598 / 641
alerts ███████████████████░ 93.3% 9,488 / 10,167
surveys ███████████████████░ 93.4% 6,918 / 7,406
cross_project_dashboards ███████████████████░ 93.4% 880 / 942
approvals ███████████████████░ 93.4% 4,576 / 4,898
exports ███████████████████░ 93.6% 4,161 / 4,447
ai_gateway ███████████████████░ 93.6% 787 / 841
billing_alerts ███████████████████░ 93.7% 2,093 / 2,233
context_layer ███████████████████░ 93.8% 3,981 / 4,244
messaging ███████████████████░ 93.8% 4,705 / 5,015
marketing_analytics ███████████████████░ 93.9% 21,191 / 22,562
mcp_store ███████████████████░ 93.9% 9,144 / 9,735
ai_observability ███████████████████░ 93.9% 29,066 / 30,938
customer_analytics ███████████████████░ 94.1% 27,892 / 29,651
workflows ███████████████████░ 94.2% 22,860 / 24,267
logs ███████████████████░ 94.4% 19,281 / 20,434
legal_documents ███████████████████░ 94.4% 2,313 / 2,451
replay_vision ███████████████████░ 94.5% 32,001 / 33,863
actions ███████████████████░ 94.7% 1,004 / 1,060
reminders ███████████████████░ 94.8% 760 / 802
growth ███████████████████░ 94.9% 11,347 / 11,959
endpoints ███████████████████░ 94.9% 9,394 / 9,899
annotations ███████████████████░ 95.1% 1,095 / 1,151
skills ███████████████████░ 95.3% 7,440 / 7,810
uptime_monitoring ███████████████████░ 95.3% 306 / 321
experiments ███████████████████░ 95.4% 39,202 / 41,090
access_control ███████████████████░ 95.5% 8,105 / 8,491
subscriptions ███████████████████░ 95.6% 13,598 / 14,225
data_catalog ███████████████████░ 95.6% 4,582 / 4,791
product_analytics ███████████████████░ 95.8% 29,875 / 31,196
revenue_analytics ███████████████████░ 95.9% 1,877 / 1,958
feature_flags ███████████████████░ 95.9% 28,362 / 29,585
data_quality ███████████████████░ 96.0% 8,523 / 8,878
tracing ███████████████████░ 96.4% 4,360 / 4,524
warehouse_sources ███████████████████░ 96.5% 475,873 / 493,192
security ███████████████████░ 96.7% 1,549 / 1,602
account_audits ███████████████████░ 96.7% 770 / 796
pulse ███████████████████░ 97.1% 2,023 / 2,083
analytics_platform ████████████████████ 98.0% 2,798 / 2,855
groups ████████████████████ 98.2% 1,838 / 1,871
field_notes ████████████████████ 99.4% 172 / 173

Report-only. Patch coverage = changed backend lines covered vs origin/master. Sorted lowest first.
Known gaps: lines covered only by Temporal tests show as uncovered; core line numbers may drift if master changed the same file.

@andrewm4894

Copy link
Copy Markdown
Member

/trunk merge

@trunk-io

trunk-io Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Static Badge   Static Badge   Static Badge

Failed Test Failure Summary Logs
Auth › Redirect to appropriate place after login The browser navigation to the activity events page was aborted. Logs ↗︎
Dashboards › Creating a SQL insight with a variable and overriding it on a dashboard The test failed because the expected element was not visible. Logs ↗︎

View Full Report ↗︎ ⋅ Docs

@andrewm4894

Copy link
Copy Markdown
Member

/trunk merge

posthog Bot added 6 commits October 25, 2026 08:37
Read $anomaly_score events back as anomaly rates per series: the latest result per bucket, warm-up rows excluded, a 30-day baseline, and expected buckets for coverage. A read-only viewset serves search and insight history behind the anomalies-search flag and the insight:read scope, with matching MCP tools.

Refs #122393

Generated-By: PostHog Desktop
Task-Id: 831c73ea-3ecf-414f-9517-f1828a156c55
Only read rows with an interval the scorer writes (hour, day, week, month). A captured row with a `second` interval made bucket stepping run for hours on a long range.

Also replace two tuple returns with frozen dataclasses (semgrep), drop the TrendsQuery fixture query that the model-crossing ratchet counted, add the new flag to the MCP flag list test, and reformat the test file.

Generated-By: PostHog Desktop
Task-Id: 831c73ea-3ecf-414f-9517-f1828a156c55
Return at most the 50 series the scorer can write per insight, and trim each series to its share of the 2,000-bucket cap as it is built. The old trim divided the cap by the series count, so more than 2,000 captured series gave a share of 0, and `[-0:]` kept every bucket.

Generated-By: PostHog Desktop
Task-Id: 831c73ea-3ecf-414f-9517-f1828a156c55
The "presentation must use facade" import contract broke the Repo checks job, which cancels the rest of Backend CI. The anomaly viewset now calls `search_anomalies` and `get_anomaly_insight_history` on the signals facade, which re-exports the filter and choice types under `Anomaly*` names.

Generated-By: PostHog Desktop
Task-Id: 831c73ea-3ecf-414f-9517-f1828a156c55
@posthog
posthog Bot force-pushed the posthog/anomaly-search-endpoints branch from ed1dae4 to 2f55a15 Compare October 25, 2026 08:38
Co-Authored-By: Claude Opus 5.5 <[email protected]>

Generated-By: PostHog Desktop
Task-Id: 8ceded3b-3822-45ca-8aec-383ef9e51b60
@trunk-io
trunk-io Bot merged commit fdc068f into master Oct 25, 2026
267 checks passed
@trunk-io
trunk-io Bot deleted the posthog/anomaly-search-endpoints branch October 25, 2026 09:03
@deployment-status-posthog

deployment-status-posthog Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

Deploy status

Environment Status Deployed At Workflow
dev ✅ Deployed 2026-10-25 18:05 UTC Run
prod-us ✅ Deployed 2026-10-25 18:19 UTC Run
prod-eu ✅ Deployed 2026-10-25 18:19 UTC Run

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant