Skip to content

feat(flags): block new action steps and cohort criteria on $feature_flag_called - #114061

Merged
trunk-io[bot] merged 8 commits into
masterfrom
haacked/flag-called-block-new-uses
Oct 8, 2026
Merged

trunk-io[bot] merged 8 commits into
masterfrom
haacked/flag-called-block-new-uses

Conversation

@haacked

@haacked haacked commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Problem

  • Organizations can still build new actions and cohorts on $feature_flag_called.
  • Each one stops matching once its organization reaches flag_evaluations_mode 2, because ingestion stops writing the event to events.
  • Every new one adds a saved object that has to be migrated. This change blocks new ones once an organization reads flag_evaluations (mode 1 or 2), where the pickers already hide the event.

Part of #88126.

Changes

  • On mode 1 and 2, the actions and cohorts APIs reject a save that adds a $feature_flag_called step or criterion. The error code is hidden_event, and the MCP tools use the same serializers.
  • The pickers need no change. Since feat(flags): hide $feature_flag_called in pickers past events mode #111148 they hide the event on mode 1 and 2, and searching for it shows an "isn't available here" explanation.
  • Mode 0 organizations can still save these. Once the flag-called-move-notices flag is on for them, an action step or cohort criterion on the event shows a warning that new ones won't save after the move starts. The flag stays off until the move is announced, because the warning describes it.
  • When the flag's payload holds an https url, the warning shows a "Learn more" button that opens it. With {"url": null}, it shows no button.
Action step on mode 0, notices on Cohort criterion on mode 0, notices on
Action step move notice Cohort criterion move notice
  • The check reads the same mode as the team API's flag_evaluations_mode, so FLAG_EVALUATIONS_READS_FORCE_EVENTS lifts the block together with the reads.
  • An existing action or cohort still saves. A save may keep, edit or drop the references it already has. Only a count above the stored count fails.
  • Cohorts count a behavioral criterion's event, its sequence event, and the legacy groups[].event_id.
  • An experiment's "Create exposure cohort" still works. It passes a serializer context key that skips the cohort check, because that cohort counts the same event as the experiment's default exposure.
  • On mode 1 and 2, "Create action from event" in the events table is disabled on $feature_flag_called rows, with a tooltip that gives the reason.
  • The blocked set comes from the taxonomy's hidden_in_query_builders marker, which the pickers already read.
  • Unchanged: destination and workflow filters.

On mode 1 and 2, these now return a 400 by design, because each creates a new object that breaks on mode 2:

  • "Copy action", "Duplicate as dynamic cohort" and the cohort editor's copy-row button, on an object that already uses the event.
  • Copying a flag to another project when the flag targets an old behavioral cohort on the event.

Not blocked:

  • Resource transfer between projects, which copies actions and cohorts through the ORM.
  • A cohort criterion that points at an action with a $feature_flag_called step. Migrating that action fixes every cohort that uses it.

How did you test this code?

Test rationale:

  • test_added_hidden_event covers the counting rule as a pure function: a new reference, a second reference, a kept reference and a dropped one.
  • The action and cohort API tests allow a create on mode 0 and reject it on mode 1. On mode 1 they reject adding a first or a second reference on update, and allow editing an existing one. They catch a check that ignores the mode, runs only on create, or ignores the stored object.
  • test_create_exposure_cohort_for_experiment now runs on mode 1, so it guards the exposure cohort exemption. It fails when the exemption key is removed.
  • hiddenEvents.test.ts covers when the notice shows (mode 0 with the flag on, not with the flag off or on mode 1) and which payload URLs become a link (https with a host only, so an http or javascript: URL never renders).

The notices were rendered in Storybook with a scratch story kept out of the commit, with the flag on and off. Not checked: the disabled menu item, and a running app.

👉 Stay up-to-date with PostHog coding conventions for a smoother review.

Release status

  • No feature flag controls this change

Docs update

None.

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

Agent: Claude Code, Opus 5.5 (claude-opus-5-5)

  • Skills: /improving-drf-endpoints, /writing-tests, /writing-user-facing-copy, /modifying-taxonomic-filter, /writing-code-comments, /simplify, /comment-cleanup, /writing-pr-descriptions, /reviewing-with-coderabbit.
  • The first version blocked every organization, mode 0 included, and hid the event in the action and cohort pickers on every mode. After the PR opened, the block moved to mode 1 and above, so it reaches each organization with its move to mode 1 and the comms for it. The per-picker exclusions and their Storybook screenshots were removed, because feat(flags): hide $feature_flag_called in pickers past events mode #111148 already hides the event on those modes.
  • A code review pass found that no test rejected a reference added on update. The update tests above came from that.
  • CodeRabbit CLI ran with --deep and reported one finding: a static cohort whose filters is a JSON array crashed the new check with a 500. Fixed with a type guard. The same request still returns a 500 from Cohort.save on master, which is a separate bug.

https://claude.ai/code/session_012rGhDjtKCS47JbyFu5gMQz

…lag_called

The action and cohort APIs reject a save that adds a reference to an event
marked hidden_in_query_builders. Existing references can be kept, edited or
dropped. The action step and cohort criteria pickers no longer offer the
event, and the events table disables "Create action from event" for it.

An experiment's exposure cohort keeps its $feature_flag_called criterion.

Claude-Session: https://claude.ai/code/session_012rGhDjtKCS47JbyFu5gMQz
@haacked haacked self-assigned this Oct 8, 2026
@trunk-io

trunk-io Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

😎 Merged successfully - details.

@haacked haacked added the reviewhog ($$$) Reviews pull requests before humans do label Oct 8, 2026
@haacked
haacked requested a balanced review from Copilot October 8, 2026 16:30

Copilot AI left a comment

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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@posthog

posthog Bot commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

🦔 PostHog Review reviewed this pull request

Found 0 must fix, 1 should fix, 0 consider.

Published 1 finding (view the review).

Resolved comments: 1 fixed, 1 declined

@posthog posthog Bot removed the reviewhog ($$$) Reviews pull requests before humans do label Oct 8, 2026
The actions and cohorts APIs reject a new reference to $feature_flag_called
only when the organization reads flag_evaluations (mode 1 or 2). That is the
same mode check that already hides the event in the pickers, so the pickers
need no exclusion of their own and mode 0 organizations see no change.

Claude-Session: https://claude.ai/code/session_012rGhDjtKCS47JbyFu5gMQz
…l move

An action step or cohort criterion on $feature_flag_called shows a warning
on mode 0 when the flag-called-move-notices flag is on. The warning says new
ones won't save once the organization starts the move. The save still goes
through, because only mode 1 and 2 refuse it. The flag stays off until the
move is announced.

Claude-Session: https://claude.ai/code/session_012rGhDjtKCS47JbyFu5gMQz
The flag-called-move-notices payload can carry the announcement's URL. When
it holds an http or https link, the action and cohort editor warnings show a
"Read the announcement" button that opens it. Without one, they show no
button.

Claude-Session: https://claude.ai/code/session_012rGhDjtKCS47JbyFu5gMQz
haacked added a commit that referenced this pull request Oct 8, 2026
…er move warnings

The announcement link accepts http and https, matching #114061. A banner without its own button shows "Read the announcement" as its button. The insight banner, which has "Edit insight", ends its text with the link instead.

Claude-Session: https://claude.ai/code/session_016eViLND7jv5WUi2FwYKkPJ
… https

The action and cohort editor warnings label the announcement link "Learn
more", like the SQL editor warning and the description notice. Only an https
URL with a host becomes a link.

Claude-Session: https://claude.ai/code/session_012rGhDjtKCS47JbyFu5gMQz
…-block-new-uses

# Conflicts:
#	products/actions/backend/api/action.py
@haacked
haacked marked this pull request as ready for review October 8, 2026 20:54
@haacked haacked added the reviewhog ($$$) Reviews pull requests before humans do label Oct 8, 2026
@parameterai

parameterai Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

Risk: No findings

This increment fixes the previously reported 500 on malformed static-cohort filters: validate_filters only bypasses parsing for structurally empty filters, and _flat_properties returns [] for non-dict or value-less stored filters, so both the scalar-values and JSON-array payloads now produce a 400 and no crash path remains.

Sentinel reviewed 438f611 · Review settings

@github-actions
github-actions Bot requested a deployment to preview-pr-114061 October 8, 2026 20:54 In progress
@github-actions

github-actions Bot commented Oct 8, 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) — 5 functions above the limit (max 19)

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.

Function Location Complexity Limit
ActionStep products/actions/frontend/components/ActionStep.tsx:54 19 10
EventRowActionsDropdown frontend/src/queries/nodes/DataTable/EventRowActions.tsx:49 13 10
CohortCriteriaRowBuilder frontend/src/scenes/cohorts/CohortFilters/CohortCriteriaRowBuilder.tsx:36 11 10
ScreenNameField products/actions/frontend/components/ActionStep.tsx:465 11 10
submit products/actions/frontend/logics/actionEditLogic.tsx:256 11 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 — 🔺 +2.5 KiB (+0.0%)

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

Total: 76.77 MiB · 🔺 +2.5 KiB (+0.0%)

File Size Δ vs base
posthog-app/_parent/products/signals/frontend/inbox/InboxScene.js 447.7 KiB 🔺 +1.4 KiB (+0.3%)

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 🔺 +52 B (+0.0%) █████████░ 94.3% of 4.03 MiB
authenticated shell (every logged-in page)
src/scenes/AuthenticatedShell.tsx
7.74 MiB · 2,456 files 🔺 +1.3 KiB (+0.0%) █████████░ 92.8% of 8.34 MiB
dashboard scene
src/scenes/dashboard/Dashboard.tsx
9.97 MiB · 3,538 files 🔺 +1.5 KiB (+0.0%) █████████░ 91.3% of 10.92 MiB
today home path
src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
7.76 MiB · 2,466 files 🔺 +1.3 KiB (+0.0%) █████████░ 90.4% of 8.58 MiB
events scene
src/scenes/activity/explore/EventsScene.tsx
9.60 MiB · 3,389 files 🔺 +1.5 KiB (+0.0%) █████████░ 91.3% of 10.51 MiB
replay detail scene
src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
12.29 MiB · 4,185 files 🔺 +1.3 KiB (+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 🔺 +52 B (+0.0%) ████░░░░░░ 39.1% of 5.72 MiB
Deferred (lazy) 2.18 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-3BYDU66B.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 — 🔺 +59.7 KiB (+0.0%)

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

Total: 1010.26 MiB · 🔺 +59.7 KiB (+0.0%)

✅ Playwright — all passed

All tests passed.

View test results →

✅ 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 438f611 · box box-2a8ebd50788d · ready in 1582s (push → usable) · build log · rebuilds on every push, torn down on close

@pr-assigner-resolver-posthog
pr-assigner-resolver-posthog Bot requested review from a team October 8, 2026 20:55
Comment thread posthog/api/cohort.py Outdated
@posthog

posthog Bot commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

PostHog Review alpha 🦔 If you find any issues helpful - please reply "valid", "invalid", etc., for evaluation purposes 🙏

Comment thread products/actions/backend/api/action.py
@posthog posthog Bot removed the reviewhog ($$$) Reviews pull requests before humans do label Oct 8, 2026
@trunk-io

trunk-io Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

Static Badge   Static Badge   Static Badge

Failed Test Failure Summary Logs
Scenes-Other/Startup program NeedsBillingDetails smoke-test The test timed out while waiting for loading indicators or spinners to disappear. Logs ↗︎
Scenes-App/Experiments ExperimentWithHealthFindings play-test The test failed because it couldn't find an element with the text 'Why?', likely due to the element being broken up or not rendered. Logs ↗︎
Scenes-App/Project Homepage ProjectHomepage smoke-test The test timed out while waiting for loading indicators or spinners to disappear. Logs ↗︎
Scenes-App/Notebooks/Nodes/Customer Journey AllStepsCompleted smoke-test The test timed out while waiting for an element with the class '.react-flow__node' to become visible. Logs ↗︎

... and 1 more

View Full Report ↗︎ ⋅ Docs

The action editor now shows the API's hidden_event error as a toast and keeps the unsaved form values, so a user who copies an action with a $feature_flag_called step sees why the save fails.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Generated-By: PostHog Desktop
Task-Id: a7a0b84e-9fef-4772-a2e0-3e0569419ee1

@stamphog stamphog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Not approved — this change needs a human reviewer.

Re-add the stamphog label to request another review once you have addressed this.

The author's owning-team membership supplies assurance, but @parameterai[bot]'s substantive concern in posthog/api/cohort.py is still reproducible from the current code. Address that static-cohort validation crash and add a regression test before re-requesting.

  • Author wrote 0% of the modified lines and has 35 merged PRs in these paths (familiarity MODERATE).
  • @parameterai[bot], posthog/api/cohort.py: the reported static-cohort crash remains present. validate_filters accepts static filters with a non-list values field; the new _flat_properties helper passes a properties dictionary containing type OR and integer values to parse_property_group_data. posthog/models/property/parse.py then iterates that integer in parse_property_group_list, raising an uncaught TypeError before the organization-mode check. Validate the properties structure or safely handle this static-cohort shape, and add a regression test before re-requesting.
Gate mechanics and policy version
Gate Result
prerequisites ✓ all clear
deny-list ✓ no deny categories matched
size ✓ 189L, 11F substantive, 428L/16F incl. docs/generated/snapshots — within ceiling
tier ✓ T1-agent / T1d-complex (428L, 16F, cross-cutting, feat)
stamphog 2.4.1 .stamphog/policy.yml @ 16a3a34 · reviewed head 16a3a34

@stamphog stamphog Bot removed the stamphog Request AI approval (no full review) label Oct 8, 2026
A static cohort with no criteria in its filters skipped filter validation,
so any JSON got through. Filters whose values field isn't a list crashed the
flag call check with a TypeError, and non-object filters crashed the save.
Both now return the existing 400 about the filters' shape. The flag call
check also skips stored filters with no list of values, so a static cohort
saved with malformed filters still updates.

Claude-Session: https://claude.ai/code/session_012rGhDjtKCS47JbyFu5gMQz

@stamphog stamphog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Approved.

The disclosed API-contract changes have owning-team authorship assurance, though no current-head reviews are present. Parameter Sentinel's scalar-values crash concern is fixed: the current helper requires list values before parsing, and serializer validation rejects malformed submissions.

  • Author wrote 0% of the modified lines and has 35 merged PRs in these paths (familiarity MODERATE).
Gate mechanics and policy version
Gate Result
prerequisites ✓ all clear
deny-list ✓ no deny categories matched
size ✓ 199L, 11F substantive, 454L/16F incl. docs/generated/snapshots — within ceiling
tier ✓ T1-agent / T1d-complex (454L, 16F, cross-cutting, feat)
stamphog 2.4.1 .stamphog/policy.yml @ 438f611 · reviewed head 438f611

@trunk-io
trunk-io Bot merged commit db16796 into master Oct 8, 2026
305 checks passed
@trunk-io
trunk-io Bot deleted the haacked/flag-called-block-new-uses branch October 8, 2026 22:59
@deployment-status-posthog

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

Copy link
Copy Markdown

Deploy status

Environment Status Deployed At Workflow
dev ✅ Deployed 2026-10-08 23:22 UTC Run
prod-us ✅ Deployed 2026-10-08 23:34 UTC Run
prod-eu ✅ Deployed 2026-10-08 23:35 UTC Run

This branch was successfully deployed

1 active deployment
preview-pr-114061 — 438f611f Deployed Oct 8, 2026 by github-actions[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature/feature-flags Feature Tag: Feature flags stamphog Request AI approval (no full review) team/feature-flags

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants