Repository navigation
feat(flags): link the announcement from the hidden flag called message - #114251
Conversation
Searching an event picker for $feature_flag_called on flag_evaluations_mode 1 or 2 ends the "isn't available here" text with a "Learn more" link when the flag-called-move-notices flag is on and its payload url is an https URL. Claude-Session: https://claude.ai/code/session_016Fnbg3yrGJagVnC2wEfHNG
|
😎 Merged successfully - details. |
🤖 CI report✅ Trunk lane — non-backend laneThis PR is assigned to the non-backend lane. It does not run backend Python tests and may merge in parallel with PRs in other lanes.
|
| Function | Location | Complexity | Limit |
|---|---|---|---|
InfiniteListRow |
frontend/src/lib/components/TaxonomicFilter/InfiniteList.tsx:439 |
44 | 10 |
renderItemContents |
frontend/src/lib/components/TaxonomicFilter/InfiniteList.tsx:203 |
38 | 10 |
MenuFilterCombobox |
frontend/src/lib/components/TaxonomicFilter/menu/Combobox.tsx:196 |
38 | 10 |
InfiniteListEmptyState |
frontend/src/lib/components/TaxonomicFilter/InfiniteList.tsx:709 |
26 | 10 |
<anonymous> |
frontend/src/lib/components/TaxonomicFilter/menu/Combobox.tsx:347 |
17 | 10 |
<anonymous> |
frontend/src/lib/components/TaxonomicFilter/menu/Combobox.tsx:724 |
17 | 10 |
InfiniteList |
frontend/src/lib/components/TaxonomicFilter/InfiniteList.tsx:884 |
16 | 10 |
Row |
frontend/src/lib/components/TaxonomicFilter/menu/Combobox.tsx:1316 |
16 | 10 |
<anonymous> |
frontend/src/lib/components/TaxonomicFilter/menu/Combobox.tsx:559 |
12 | 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.
⚠️ Bundle size — 🔺 +363 B (+0.0%)
Uncompressed size of every built .js bundle, compared against the base branch.
Total: 76.77 MiB · 🔺 +363 B (+0.0%)
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 |
1.65 MiB · 23 files | no change | █████████░ 89.8% 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.80 MiB · 675 files | no change | █████████░ 94.3% of 4.03 MiB |
authenticated shell (every logged-in page)src/scenes/AuthenticatedShell.tsx |
7.74 MiB · 2,457 files | 🔺 +192 B (+0.0%) | █████████░ 92.8% of 8.34 MiB |
dashboard scenesrc/scenes/dashboard/Dashboard.tsx |
9.97 MiB · 3,539 files | 🔺 +192 B (+0.0%) | █████████░ 91.3% of 10.92 MiB |
today home pathsrc/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx |
7.76 MiB · 2,467 files | 🔺 +192 B (+0.0%) | █████████░ 90.4% of 8.58 MiB |
events scenesrc/scenes/activity/explore/EventsScene.tsx |
9.60 MiB · 3,390 files | 🔺 +192 B (+0.0%) | █████████░ 91.3% of 10.51 MiB |
replay detail scenesrc/scenes/session-recordings/detail/SessionRecordingDetail.tsx |
12.29 MiB · 4,186 files | 🔺 +192 B (+0.0%) | ████████░░ 78.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
🟢 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/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
🟢 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/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
🟢 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
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 |
| 839 B | src/scenes/ChunkLoadErrorBoundary.tsx |
Largest files eagerly shipped from src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
| Size | File |
|---|---|
| 316.7 KiB | ../node_modules/.pnpm/posthog-js@1.438.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 220.8 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 |
| 99.8 KiB | src/lib/api.ts |
| 93.1 KiB | src/products.tsx |
| 69.0 KiB | src/lib/lemon-ui/icons/icons.tsx |
| 40.7 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 |
|---|---|
| 316.7 KiB | ../node_modules/.pnpm/posthog-js@1.438.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 281.0 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 220.8 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 |
| 112.1 KiB | ../packages/quill/packages/quill/dist/index.js |
| 99.8 KiB | src/lib/api.ts |
| 93.3 KiB | ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js |
| 93.1 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 |
|---|---|
| 316.7 KiB | ../node_modules/.pnpm/posthog-js@1.438.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 281.0 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 220.8 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.9 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 |
| 112.1 KiB | ../packages/quill/packages/quill/dist/index.js |
| 99.8 KiB | src/lib/api.ts |
| 93.3 KiB | ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js |
| 93.1 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 |
|---|---|
| 316.7 KiB | ../node_modules/.pnpm/posthog-js@1.438.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 281.0 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 220.8 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 |
| 112.1 KiB | ../packages/quill/packages/quill/dist/index.js |
| 99.8 KiB | src/lib/api.ts |
| 93.3 KiB | ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js |
| 93.1 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 |
|---|---|
| 316.7 KiB | ../node_modules/.pnpm/posthog-js@1.438.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 281.0 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 220.8 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.9 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 |
| 112.1 KiB | ../packages/quill/packages/quill/dist/index.js |
| 99.8 KiB | src/lib/api.ts |
| 93.3 KiB | ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js |
| 93.1 KiB | src/products.tsx |
Largest files eagerly shipped from src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
| Size | File |
|---|---|
| 316.7 KiB | ../node_modules/.pnpm/posthog-js@1.438.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 316.0 KiB | ../node_modules/.pnpm/posthog-js@1.438.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/rrweb.js |
| 281.0 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 220.8 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.9 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 |
| 112.1 KiB | ../packages/quill/packages/quill/dist/index.js |
| 99.8 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.24 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.24 MiB · 19 files | no change | ████░░░░░░ 39.1% of 5.72 MiB |
| Deferred (lazy) | 2.19 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 |
|---|---|
| 861.3 KiB | dist/toolbar/toolbar-app-G6HPIREX.css |
| 669.8 KiB | dist/toolbar/chunk-chunk-ZOWCBXZV.js |
| 259.4 KiB | dist/toolbar/chunk-chunk-YKNMISGG.js |
| 138.2 KiB | dist/toolbar/chunk-chunk-PE5DZ2WQ.js |
| 131.8 KiB | dist/toolbar/chunk-chunk-FDH2IBXT.js |
| 75.2 KiB | dist/toolbar/toolbar-app-HEV2GVJR.js |
| 69.0 KiB | dist/toolbar/chunk-chunk-TSAL54PB.js |
| 35.6 KiB | dist/toolbar/chunk-chunk-AVVBLJY4.js |
| 21.7 KiB | dist/toolbar/chunk-chunk-43RGLDYQ.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 — 🔺 +8.6 KiB (+0.0%)
Total size of the built frontend/dist folder (all assets), compared against the base branch.
Total: 1010.27 MiB · 🔺 +8.6 KiB (+0.0%)
✅ Hogbox preview — ready, open the preview
▶ Open the preview
| 🔑 Login | test@posthog.com / 12345678 (demo data) |
| 🧩 Running | this PR's backend and frontend, on the PostHog :master base |
| 🔗 Link | stable across rebuilds: a re-push swaps the box underneath, the URL stays |
| 🔒 Access | tailnet only (PostHog VPN) |
| 🛠️ Admin | inspect & debug state in hogland |
| 💤 Idle | sleeps after ~30 min idle (snapshot to S3, zero node cost) and wakes on your next visit in ~30s, behind a brief "waking up" screen |
commit cbe2166 · box box-607c84bcd146 · ready in 1077s (push → usable) · build log · rebuilds on every push, torn down on close
|
Risk: No findings This PR adds a "Learn more" link (driven by the flag-called-move-notices feature-flag payload) to the hidden-event explanation shown by both event pickers, moving the shared copy into a new HiddenEventExplanation component. The only externally-controlled value — the announcement URL — is validated with isHttpsUrl, trimmed before use, rendered through React-escaped attributes, and doubly guarded by Link's dangerous-scheme rejection, so I found no exploitable path. Sentinel reviewed |
There was a problem hiding this comment.
Approved.
Contained frontend change with targeted tests and no outstanding substantive concerns. Copilot's quota-limit comment does not provide independent review assurance, but none is required for this change.
- Author wrote 93% of the modified lines and has 11 merged PRs in these paths (familiarity STRONG).
- copilot-pull-request-reviewer[bot] reviewed the current head.
Gate mechanics and policy version
| Gate | Result | |
|---|---|---|
| prerequisites | ✓ | all clear |
| deny-list | ✓ | no deny categories matched |
| size | ✓ | 40L, 4F substantive, 141L/6F incl. docs/generated/snapshots — within ceiling |
| tier | ✓ | T1-agent / T1c-medium (141L, 6F, single-area, feat) |
| stamphog 2.4.1 | .stamphog/policy.yml @ cbe2166 · reviewed head cbe2166 |
|

Problem
flag_evaluations_mode1 and 2, event pickers hide$feature_flag_called(feat(flags): hide $feature_flag_called in pickers past events mode #111148).flag-called-move-noticesflag payload. This message did not.Changes
flag-called-move-noticesis on and its payloadurlis https, the message ends with a "Learn more" link to that URL.{ "url": null }, the message reads exactly as before.TAXONOMIC_FILTER_MENU_REBUILD, internal opt-in).HiddenEventExplanationrenders the existing copy plus the link, so the copy now lives in one place.emptyState.bodywidens fromstringtoReactNode. It stays truthy, so the recovery buttons and the empty-result telemetry stay suppressed.isHttpsUrlfromlib/utils/url.isHttpsUrlaccepts a leading space, butLinkturns that value into an in-app path.FLAG_CALLED_MOVE_NOTICESline inconstants.tsxis identical to the one in feat(flags): block new action steps and cohort criteria on $feature_flag_called #114061, feat(flags): move the flag called warning into a flag-gated notice #114172 and feat(flags): show rebuild banners on artifacts that read flag calls #113691, so the PRs merge in any order.Legacy picker, flag on with a URL:
Rebuilt menu, flag on with a URL:
Without the flag or URL, both pickers look as they do on master.
How did you test this code?
Test rationale: The existing hidden-event test in each picker (
TaxonomicFilter.test.tsx,menu/Combobox.test.tsx) became anit.eachover three states: flag on with a URL, flag on with{ url: null }, flag off with a URL. Each row still asserts the original message, and the rebuilt-menu rows still assert the recovery buttons stay hidden. A mutation that ignores the flag fails the flag-off row in both files. The rebuilt-menu table adds a row for a URL with a leading space, which failed with/project/997/ https://…before the trim.Manual check: both pickers rendered in a scratch Storybook story with the flag on, mode 1 and a payload URL (screenshots above). A real click on the link in the rebuilt menu reached the anchor without the combobox cancelling it. The scratch story is not committed.
Not checked: the running app with a real flag payload.
Release status
Docs update
None.
🤖 Agent context
Autonomy: Human-driven (agent-assisted)
Agent: Claude Code, Claude Opus 5.5 (claude-opus-5-5); Claude Sonnet 5.5 for the comment cleanup pass
example.com.https://claude.ai/code/session_016Fnbg3yrGJagVnC2wEfHNG