Conversation
The experiment page reports each warning it shows, once per experiment load, and each use of a warning's action, under two new events. `experiment launched` now also fires when a create call carries a start date and when an update sets the start date of a draft, with `launch_path` and `flag_age_days`. The experiments list reports `experiments list viewed`, and `experiment viewed` gains `experiment_id` and `experiment_status`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Merging to
After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here |
🤖 CI report
|
| Function | Location | Complexity | Limit |
|---|---|---|---|
Exposures |
frontend/src/scenes/experiments/ExperimentView/Exposures.tsx:128 |
33 | 10 |
refreshExperimentResults |
frontend/src/scenes/experiments/experimentLogic.tsx:2481 |
27 | 10 |
moveMetricsBetweenSections |
frontend/src/scenes/experiments/experimentLogic.tsx:3300 |
23 | 10 |
<anonymous> |
frontend/src/scenes/experiments/experimentLogic.tsx:3939 |
15 | 10 |
setFunnelsMetric |
frontend/src/scenes/experiments/experimentLogic.tsx:1726 |
13 | 10 |
✅ 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.
⚠️ Comment density — 5% of added code lines are comments (42 of 884)
This section warns when comments are more than 3% of the code lines a PR adds, and alerts above 6%. Before agent-assisted PRs, the typical share was about 2%. Only full-line comments count. Docstrings, generated files, snapshots, migrations, and workflow files are left out.
Comments that restate the code, record how the change came about, or narrate the next line add noise for the next reader. Keep the comments that explain a reason the code cannot show, and remove the rest. See .agents/skills/writing-code-comments/SKILL.md for the house rules.
Files with the most added comment lines:
| File | Comment lines | Added lines |
|---|---|---|
products/experiments/frontend/health/experimentHealthFindingEvents.ts |
18 | 117 |
frontend/src/scenes/experiments/experimentLogic.tsx |
7 | 69 |
products/experiments/frontend/health/useHealthFindingReporting.ts |
5 | 49 |
frontend/src/scenes/experiments/ExperimentView/Exposures.tsx |
3 | 29 |
products/experiments/backend/experiment_service.py |
2 | 42 |
products/experiments/frontend/scenes/experimentsLogic.ts |
2 | 36 |
frontend/src/scenes/experiments/Experiment.test.tsx |
1 | 19 |
frontend/src/scenes/experiments/ExperimentView/ExperimentView.tsx |
1 | 11 |
This check does not block merging. It updates on every push and clears when the share drops.
⚠️ Bundle size — 🔺 +2.9 KiB (+0.0%)
Uncompressed size of every built .js bundle, compared against the base branch.
Total: 69.79 MiB · 🔺 +2.9 KiB (+0.0%)
| File | Size | Δ vs base |
|---|---|---|
render-query/src/render-query/render-query.js |
18.77 MiB | 🔺 +2.3 KiB (+0.0%) |
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 |
1.63 MiB · 22 files | no change | █████████░ 88.7% of 1.84 MiB |
logged-out boot: index + App + bootApp (preloaded by every page, including /login)src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts |
3.72 MiB · 662 files | 🔺 +595 B (+0.0%) | █████████░ 92.4% of 4.03 MiB |
authenticated shell (every logged-in page)src/scenes/AuthenticatedShell.tsx |
7.59 MiB · 2,410 files | 🔺 +892 B (+0.0%) | █████████░ 91.0% of 8.34 MiB |
dashboard scenesrc/scenes/dashboard/Dashboard.tsx |
9.67 MiB · 3,393 files | 🔺 +892 B (+0.0%) | ███████░░░ 71.8% of 13.48 MiB |
today home pathsrc/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx |
7.61 MiB · 2,418 files | 🔺 +892 B (+0.0%) | █████████░ 88.6% of 8.58 MiB |
events scenesrc/scenes/activity/explore/EventsScene.tsx |
9.29 MiB · 3,245 files | 🔺 +892 B (+0.0%) | ███████░░░ 73.5% of 12.64 MiB |
replay detail scenesrc/scenes/session-recordings/detail/SessionRecordingDetail.tsx |
12.13 MiB · 4,132 files | 🔺 +2.6 KiB (+0.0%) | ████████░░ 77.2% of 15.72 MiB |
🟢 node_modules/monaco-editor/ stays out of src/index.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/index.tsx
🟢 [object Object] stays out of src/index.tsx
🟢 [object Object] 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/monaco-editor/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/scenes/session-recordings/player/sessionRecordingPlayerLogic.ts stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.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
Largest files eagerly shipped from src/index.tsx
| Size | File |
|---|---|
| 126.8 KiB | ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js |
| 24.6 KiB | ../node_modules/.pnpm/buffer@6.0.3/node_modules/buffer/index.js |
| 6.3 KiB | ../node_modules/.pnpm/react@18.3.1/node_modules/react/cjs/react.production.min.js |
| 4.5 KiB | ../node_modules/.pnpm/@jspm+core@2.1.0/node_modules/@jspm/core/nodelibs/browser/process.js |
| 3.9 KiB | ../node_modules/.pnpm/scheduler@0.23.2/node_modules/scheduler/cjs/scheduler.production.min.js |
| 1.4 KiB | ../node_modules/.pnpm/base64-js@1.5.1/node_modules/base64-js/index.js |
| 1.3 KiB | src/index.tsx |
| 1.3 KiB | src/RootErrorBoundary.tsx |
| 912 B | ../node_modules/.pnpm/ieee754@1.2.1/node_modules/ieee754/index.js |
| 854 B | src/scenes/ChunkLoadErrorBoundary.tsx |
Largest files eagerly shipped from src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
| Size | File |
|---|---|
| 306.2 KiB | ../node_modules/.pnpm/posthog-js@1.435.5_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 220.3 KiB | ../node_modules/.pnpm/@posthog+icons@0.38.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 126.8 KiB | ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js |
| 100.5 KiB | src/lib/api.ts |
| 92.7 KiB | src/products.tsx |
| 69.4 KiB | src/lib/lemon-ui/icons/icons.tsx |
| 40.4 KiB | src/lib/utils/eventUsageLogic.ts |
| 38.7 KiB | ../node_modules/.pnpm/@dnd-kit+core@6.0.8_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@dnd-kit/core/dist/core.esm.js |
| 33.9 KiB | ../node_modules/.pnpm/kea@4.0.0-pre.6_patch_hash=139b8d1f1304f9d9da452a9a1244c94ea679dbcb85687d8999563146879fb6f5_react@18.3.1/node_modules/kea/lib/index.cjs.js |
| 29.0 KiB | ../node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/core/schemas.js |
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx
| Size | File |
|---|---|
| 306.2 KiB | ../node_modules/.pnpm/posthog-js@1.435.5_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 279.9 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 220.3 KiB | ../node_modules/.pnpm/@posthog+icons@0.38.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 153.7 KiB | ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js |
| 126.8 KiB | ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js |
| 110.1 KiB | ../packages/quill/packages/quill/dist/index.js |
| 100.5 KiB | src/lib/api.ts |
| 93.3 KiB | ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js |
| 92.7 KiB | src/products.tsx |
| 90.6 KiB | ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js |
Largest files eagerly shipped from src/scenes/dashboard/Dashboard.tsx
| Size | File |
|---|---|
| 306.2 KiB | ../node_modules/.pnpm/posthog-js@1.435.5_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 279.9 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 220.3 KiB | ../node_modules/.pnpm/@posthog+icons@0.38.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 181.8 KiB | src/queries/validators.js |
| 153.7 KiB | ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js |
| 126.8 KiB | ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js |
| 110.1 KiB | ../packages/quill/packages/quill/dist/index.js |
| 100.5 KiB | src/lib/api.ts |
| 93.3 KiB | ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js |
| 92.7 KiB | src/products.tsx |
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
| Size | File |
|---|---|
| 306.2 KiB | ../node_modules/.pnpm/posthog-js@1.435.5_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 279.9 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 220.3 KiB | ../node_modules/.pnpm/@posthog+icons@0.38.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 153.7 KiB | ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js |
| 126.8 KiB | ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js |
| 110.1 KiB | ../packages/quill/packages/quill/dist/index.js |
| 100.5 KiB | src/lib/api.ts |
| 93.3 KiB | ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js |
| 92.7 KiB | src/products.tsx |
| 90.6 KiB | ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js |
Largest files eagerly shipped from src/scenes/activity/explore/EventsScene.tsx
| Size | File |
|---|---|
| 306.2 KiB | ../node_modules/.pnpm/posthog-js@1.435.5_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 279.9 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 220.3 KiB | ../node_modules/.pnpm/@posthog+icons@0.38.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 181.8 KiB | src/queries/validators.js |
| 153.7 KiB | ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js |
| 126.8 KiB | ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js |
| 110.1 KiB | ../packages/quill/packages/quill/dist/index.js |
| 100.5 KiB | src/lib/api.ts |
| 93.3 KiB | ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js |
| 92.7 KiB | src/products.tsx |
Largest files eagerly shipped from src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
| Size | File |
|---|---|
| 315.5 KiB | ../node_modules/.pnpm/posthog-js@1.435.5_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/rrweb.js |
| 306.2 KiB | ../node_modules/.pnpm/posthog-js@1.435.5_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 279.9 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 220.3 KiB | ../node_modules/.pnpm/@posthog+icons@0.38.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 181.8 KiB | src/queries/validators.js |
| 153.7 KiB | ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js |
| 126.8 KiB | ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js |
| 110.1 KiB | ../packages/quill/packages/quill/dist/index.js |
| 100.5 KiB | src/lib/api.ts |
| 93.3 KiB | ../node_modules/.pnpm/prosemirror-view@1.40.1/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.20 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.20 MiB · 19 files | no change | ████░░░░░░ 38.4% of 5.72 MiB |
| Deferred (lazy) | 2.11 MiB · 44 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 |
|---|---|
| 835.6 KiB | dist/toolbar/toolbar-app-IDXKA4WE.css |
| 657.5 KiB | dist/toolbar/chunk-chunk-BALLB66W.js |
| 259.4 KiB | dist/toolbar/chunk-chunk-7JWMBALG.js |
| 138.2 KiB | dist/toolbar/chunk-chunk-RXJG6CZC.js |
| 131.8 KiB | dist/toolbar/chunk-chunk-FDH2IBXT.js |
| 75.2 KiB | dist/toolbar/toolbar-app-YIYWW6XJ.js |
| 69.0 KiB | dist/toolbar/chunk-chunk-TSAL54PB.js |
| 35.6 KiB | dist/toolbar/chunk-chunk-MM7MZI2L.js |
| 21.0 KiB | dist/toolbar/chunk-chunk-EZFR5QGQ.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 — 🔺 +95.8 KiB (+0.0%)
Total size of the built frontend/dist folder (all assets), compared against the base branch.
Total: 960.52 MiB · 🔺 +95.8 KiB (+0.0%)
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository: PostHog/posthog/.coderabbit.yaml Review profile: QUIET Plan: Enterprise Run ID: 📒 Files selected for processing (2)
💤 Files with no reviewable changes (1)
Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 11 remain after this review. 📝 WalkthroughWalkthroughThe change adds frontend analytics for experiment health findings, actions, exposure properties, and list views. Experiment-view events now include the experiment ID and status. The backend reports launch paths, launch dates, and feature-flag age for launches through the endpoint, creation with a start date, and draft updates that set a start date. Tests cover these reporting paths and event properties. Priority: ➖ Normal Merge Risk: 🔵 Low · up to Some experiment analytics can still associate a list response with the wrong filter or a refresh with the wrong exposure snapshot. These bounded reporting risks remain for the owner to address or accept before merging. Security Architecture ReviewSecurity architecture risk: 🔵 Low · up to The visible changes center on analytics, with deliberately limited health-event payloads and reporting failures isolated from saved launches. No introduced security issue was established. Launch authorization, concurrent transition behavior, and production telemetry access remain incompletely verified. Retained concerns Security review detailsSecurity Blast Radius
Trust Boundaries and Controls
Resilience and Maintainability Implications
🚥 Pre-merge checks | ✅ 1✅ Passed checks (1 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Note
Quiet mode is enabled, so only the most important comments were posted inline. Other review comments are grouped below.
🟡 Other comments (1)
products/experiments/frontend/scenes/experimentsLogic.ts-620-620 (1)
620-620: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winReport the status filter used by the completed request.
If a user changes the status filter while a request is pending, that response can finish during the 300 ms debounce before the next
loadExperimentsstarts. The loader breakpoint does not reject that response yet. This line then reports the previous result count with the newvalues.filters.status, which mislabels the event.Snapshot the filters before
api.get, return that snapshot with the response, and read its status here.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository: PostHog/posthog/.coderabbit.yaml
Review profile: QUIET
Plan: Enterprise
Run ID: 80889752-21db-49eb-9b6b-db96ce9181d0
📒 Files selected for processing (14)
frontend/src/lib/utils/eventUsageLogic.tsfrontend/src/scenes/experiments/Experiment.test.tsxfrontend/src/scenes/experiments/ExperimentView/ExperimentView.tsxfrontend/src/scenes/experiments/ExperimentView/ExperimentWarningBanners.tsxfrontend/src/scenes/experiments/ExperimentView/Exposures.tsxfrontend/src/scenes/experiments/ExperimentView/MultiVariantBiasWarning.tsxfrontend/src/scenes/experiments/experimentLogic.test.tsfrontend/src/scenes/experiments/experimentLogic.tsxproducts/experiments/backend/experiment_service.pyproducts/experiments/backend/test/test_experiment_service.pyproducts/experiments/frontend/health/experimentHealthFindingEvents.tsproducts/experiments/frontend/health/useHealthFindingReporting.tsproducts/experiments/frontend/scenes/experimentsLogic.test.tsproducts/experiments/frontend/scenes/experimentsLogic.ts
Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 11 remain after this review.
|
[Medium risk] Adds event tracking for experiment health findings and user actions. The PR appears safe to merge; no outstanding review finding was identified. Reviews (2) · Last reviewed commit: "fix(experiments): report the flag age at..." |
|
The zero-exposure finding fired from the collapsed Exposures panel, where "No exposures yet" is not rendered. It now fires while the open panel shows that state. `experiments list viewed` reads the status filter of the request that answered, so a filter change during the request does not relabel it. A click test covers the four warning actions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- `experiment health finding opened`: a reader opens the Exposures panel on a sample ratio mismatch or on zero exposures, or follows the documentation link of the bias banner. - `experiment health finding acted on` for "Add primary metric" and "Add secondary metric" under "No metrics defined". The code is `no_metric`, because the warning shows only for an experiment with no metric of either kind. - `experiment results refresh completed` carries `exposures_total`, `has_srm` and `has_bias_risk`. The exposure warnings render on one tab only, so this gives the exposure state for every load of a launched experiment. - `experiment launched` carries `flag_age_seconds`, and a failed launch report no longer fails a launch that is already saved. - `experiments list viewed` carries `page`, `has_search` and `archived`. - The tests assert the events that are sent, and cover the sample ratio emitter and a flag older than a day. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Note
Quiet mode is enabled, so only the most important comments were posted inline. Other review comments are grouped below.
🟡 Other comments (1)
frontend/src/scenes/experiments/experimentLogic.tsx-2583-2583 (1)
2583-2583: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winBind exposure health properties to the refresh that produced them.
In the legacy refresh path, exposure and metric requests run concurrently. Refresh A can finish exposure loading while it still waits for metrics. If refresh B then updates
values.exposures, refresh A emits B's exposure properties with A'srefresh_idand trigger. Criteria and date changes can start overlapping refreshes.Store the exposure response in a refresh-local variable and pass it to
exposureHealthEventProperties. Add a regression test with overlapping refreshes and different exposure responses.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository: PostHog/posthog/.coderabbit.yaml
Review profile: QUIET
Plan: Enterprise
Run ID: 40d9fe88-ff62-4cd3-952a-cc49287a6752
📒 Files selected for processing (18)
frontend/src/lib/utils/eventUsageLogic.test.tsfrontend/src/lib/utils/eventUsageLogic.tsfrontend/src/scenes/experiments/Experiment.test.tsxfrontend/src/scenes/experiments/ExperimentForm/MetricsPanel/EmptyMetricsPanel.tsxfrontend/src/scenes/experiments/ExperimentView/ExperimentView.tsxfrontend/src/scenes/experiments/ExperimentView/ExperimentWarningBanners.tsxfrontend/src/scenes/experiments/ExperimentView/Exposures.tsxfrontend/src/scenes/experiments/ExperimentView/MultiVariantBiasWarning.tsxfrontend/src/scenes/experiments/ExperimentView/healthFindingReporting.test.tsxfrontend/src/scenes/experiments/experimentLogic.test.tsfrontend/src/scenes/experiments/experimentLogic.tsxproducts/experiments/backend/experiment_service.pyproducts/experiments/backend/test/test_experiment_service.pyproducts/experiments/frontend/health/experimentHealthFindingEvents.tsproducts/experiments/frontend/health/exposureHealth.tsproducts/experiments/frontend/health/useHealthFindingReporting.tsproducts/experiments/frontend/scenes/experimentsLogic.test.tsproducts/experiments/frontend/scenes/experimentsLogic.ts
Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 11 remain after this review.
`experiment results refresh completed` carries `exposures_multiple`, the count of the `$multiple` variant in the exposure answer. No other place records it: the stored metric results drop that variant. The property is empty under "first seen" handling. The exposure query then gives each person their first variant and counts no `$multiple`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`experiment launched` carried `flag_age_days` next to `flag_age_seconds`. Nothing reads the days value. The seconds give the same fact, and they tell a flag made by the launching request from one made hours earlier. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Risk: No findings This change is analytics-only: it adds telemetry events for experiment health findings (shown/opened/acted on), fires Sentinel reviewed |
🦔 Hogbox preview · ✅ ready▶ Open the preview
commit |
HostHog preview —
|
Problem
experiment launchedmisses two of the three ways to launch: a create call with a start date, and an update that starts a draft.Changes
experiment health finding shownfor each warning on screen, once per experiment load.experiment health finding openedwhen a person opens the Exposures panel on a warning, or follows the bias banner's documentation link.experiment health finding acted onwhen a person uses the action a warning offers.experiment results refresh completedgains the exposure state, because the exposure warnings render on one tab only.experiment launchedfires on all three launch paths, withlaunch_pathandflag_age_seconds.experiments list viewed, andexperiment viewedgainsexperiment_idandexperiment_status.Note
Counts of
experiment launchedstep up when this deploys. Filter onlaunch_path = launch_endpointfor the old series.How did you test this code?
experimentLogic.test.ts: one event per finding per load, "shown" before "opened", and the exposure state on the refresh event.healthFindingReporting.test.tsx: the rendered warnings send "shown", and a click on each action, link and panel sends its event.Experiment.test.tsx: a running experiment without metrics reports its warnings and both add-metric clicks, and a draft reports none.experimentsLogic.test.ts: the list reports a view on its own tab only, with the filters of the request that answered.test_experiment_service.py: each launch path reports once with its flag age, and a failing report leaves the launch saved.Test rationale: The regressions are a warning, an action or a launch path that stops reporting, and a finding that reports twice in one load. The closest tests,
test_lifecycle_action_emits_exact_event_nameand theexperimentWarningblock, assert an event name or a selector only.Release status
Automatic notifications
Docs update
None. The events are internal telemetry.
🤖 Agent context
Autonomy: Human-driven (agent-assisted)
Agent: Claude Code, Opus 5.5 (
claude-opus-5-5)/placing-product-frontend-code,/writing-ui-components,/writing-kea-logics,/writing-tests,/writing-code-comments,/simplify,/reviewing-with-coderabbit,/writing-pr-descriptions.🤖 Generated with Claude Code