Skip to content

chore(experiments): stop exposing the superseded experiment settings - #104928

Merged
trunk-io[bot] merged 1 commit into
masterfrom
chore/experiments-strip-superseded-settings-readers
Sep 23, 2026
Merged

trunk-io[bot] merged 1 commit into
masterfrom
chore/experiments-strip-superseded-settings-readers

Conversation

@andehen

@andehen andehen commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

Problem

An API consumer reading default_experiment_stats_method from /api/organizations/ gets a value the product ignores, and a consumer writing it changes nothing.

  • refactor(experiments): move experiment settings to team extension model #53674 moved the experiment settings to TeamExperimentsConfig on 2026-04-09.
  • The Organization and Team columns stayed behind with no behavioral reader.
  • Every reader now uses the extension: experiment_service.py, setup_context.py, posthog/api/web_experiment.py, posthog/temporal/experiments/activities.py, the experiments_config action, and experimentsConfigLogic.

This is layer 1 of 2. It takes the dead field off every surface. Layer 2 takes the columns out of Django's model state.

Changes

  • The organization API stops returning and accepting default_experiment_stats_method. The field leaves OrganizationSerializer.
  • The organization activity log stops labelling the field, because no write can reach it.
  • The Postgres-to-ClickHouse ETL stops copying the column. Its column list is explicit, so no other value shifts.
  • The live ClickHouse table keeps its default_experiment_stats_method column. CREATE TABLE IF NOT EXISTS does not alter it, and new rows leave it null.
  • Mechanical: OrganizationType, organizationLogic, verifiedDomainImpactLogic, api.mock.ts, two MCP response fixtures, and the regenerated OpenAPI types.

The settings UI is unaffected. It reads TeamExperimentsConfig through experimentsConfigLogic, which this PR does not touch, so nothing looks different.

Note

Removing a field from a public API response is a breaking change for any client that reads it. This is a straight drop rather than a deprecation window: the column has had no reader since April, so a write is already a no-op and a read already returns a value the product ignores. The alternative shape this repo also uses is is_member_join_email_enabled, kept as a read-only "Legacy field".

How did you test this code?

  • Deleted test_organization_experiment_stats_method_logging. Its subject no longer exists. test_organization_name_change_logging and test_organization_2fa_enforcement_logging still cover the label map.
  • No test added. The removal has no behavior to catch a regression in.
  • Ran locally: posthog/test/activity_logging/test_organization_activity_logging.py, posthog/api/test/test_organization.py, posthog/dags/tests/test_postgres_to_clickhouse_etl.py.
  • Three failures in test_organization.py reproduce on unmodified master. They concern license gating, not this change.
  • kea-typegen confirms the two hand-edited generated blocks.
  • Not checked: the frontend typescript:check run in this worktree reports no error in the touched files, but its unbuilt quill package hides a clean whole-repo result. CI runs the real one.

Automatic notifications

  • Publish to changelog?

Docs update

None. No doc under docs/ documents this field.

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

Agent: Claude Code, Opus 5 (1M context)

Skills invoked: /django-migrations, /improving-drf-endpoints, /stacking-prs, /writing-tests, /writing-pr-descriptions, /reviewing-with-coderabbit.

CodeRabbit CLI pass: 0 findings on this layer.

The removal was verified before it was written, not after. A repo-wide grep over Python, TypeScript, Rust and Go found no behavioral reader of the old columns, and TEAM_CONFIG_FIELDS never carried the three Team fields. TeamExperimentsConfigInline already points at the extension. The 2026-04-09 backfill was migration 0005, not a management command, so there was nothing to retire.

No duplicate: gh pr list --state open --search "default_experiment_stats_method" returns only #99248, a posthog/api/team.py module split with no overlap.

Public artifact: the work drew only on this repository and a local planning note. Nothing in the diff comes from a customer conversation, ticket, or log.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@trunk-io

trunk-io Bot commented Sep 23, 2026 •

Copy link
Copy Markdown

😎 Stack merged successfully - details.

@andehen
andehen added this pull request to stack #104930 September 23, 2026 06:06
@andehen andehen added the skip-agent-review Save $$$, skip auto agent reviews (Greptile) — use for trivial or chore PRs label Sep 23, 2026
@github-actions

github-actions Bot commented Sep 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: 69.38 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
1.56 MiB · 22 files no change ████████░░ 84.6% 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.56 MiB · 628 files no change █████████░ 88.3% of 4.03 MiB
authenticated shell (every logged-in page)
src/scenes/AuthenticatedShell.tsx
8.42 MiB · 2,781 files no change █████████░ 88.6% of 9.51 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

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
301.9 KiB ../node_modules/.pnpm/posthog-js@1.434.4_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
267.7 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
101.4 KiB src/lib/api.ts
83.5 KiB src/products.tsx
68.5 KiB src/lib/lemon-ui/icons/icons.tsx
63.4 KiB src/lib/utils/eventUsageLogic.ts
38.8 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
28.6 KiB src/scenes/scenes.ts
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx
Size File
301.9 KiB ../node_modules/.pnpm/posthog-js@1.434.4_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
268.0 KiB src/taxonomy/core-filter-definitions-by-group.json
267.7 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.8 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
101.4 KiB src/lib/api.ts
98.4 KiB ../packages/quill/packages/quill/dist/index.js
93.3 KiB ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js
90.6 KiB ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js
83.5 KiB src/products.tsx

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.36 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.36 MiB · 19 files no change ████░░░░░░ 41.2% of 5.72 MiB
Deferred (lazy) 2.09 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
784.0 KiB dist/toolbar/toolbar-app-6ZSILWYF.css
649.8 KiB dist/toolbar/chunk-chunk-PHO72TIK.js
483.6 KiB dist/toolbar/chunk-chunk-ZRM62ERU.js
138.1 KiB dist/toolbar/chunk-chunk-CQPUOIWG.js
131.8 KiB dist/toolbar/chunk-chunk-FDH2IBXT.js
75.1 KiB dist/toolbar/toolbar-app-SBMRP3DJ.js
69.0 KiB dist/toolbar/chunk-chunk-TSAL54PB.js
35.6 KiB dist/toolbar/chunk-chunk-TA7IXF2V.js
21.0 KiB dist/toolbar/chunk-chunk-TPHCTPWU.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 — 🟢 -5.3 KiB (-0.0%)

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

Total: 1517.10 MiB · 🟢 -5.3 KiB (-0.0%)

ℹ️ MCP UI apps size — 33 app(s), 17628.2 KB JS

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

App JS CSS
debug 597.8 KB 196.2 KB
action 454.1 KB 196.2 KB
action-list 564.1 KB 196.2 KB
cohort 453.1 KB 196.2 KB
cohort-list 563.1 KB 196.2 KB
email-template 452.9 KB 196.2 KB
error-details 469.1 KB 196.2 KB
error-issue 453.8 KB 196.2 KB
error-issue-list 564.0 KB 196.2 KB
experiment 561.2 KB 196.2 KB
experiment-list 564.9 KB 196.2 KB
experiment-results 566.2 KB 196.2 KB
feature-flag 566.7 KB 196.2 KB
feature-flag-list 570.5 KB 196.2 KB
feature-flag-testing 457.3 KB 196.2 KB
inline-scan 453.6 KB 196.2 KB
insight-actors 562.3 KB 196.2 KB
invite-email-preview 452.3 KB 196.2 KB
llm-costs 559.3 KB 196.2 KB
session-recording 454.9 KB 196.2 KB
survey 454.7 KB 196.2 KB
survey-global-stats 561.8 KB 196.2 KB
survey-list 564.8 KB 196.2 KB
survey-stats 561.8 KB 196.2 KB
trace-span 453.5 KB 196.2 KB
trace-span-list 564.0 KB 196.2 KB
vision-observation-list 563.2 KB 196.2 KB
workflow 453.4 KB 196.2 KB
workflow-list 563.5 KB 196.2 KB
loops-review 457.8 KB 196.2 KB
query-results 774.0 KB 196.2 KB
render-ui 856.5 KB 196.2 KB
visual-review-snapshots 457.9 KB 196.2 KB
✅ Playwright — all passed

All tests passed.

View test results →

@greptile-apps

greptile-apps Bot commented Sep 23, 2026

Copy link
Copy Markdown
Contributor

Retrigger

The behavior change appears safe, but the repository-required desktop API client regeneration must be committed before merging.

Reviews (1) · Last reviewed commit: "chore(experiments): stop exposing the su..."

Comment thread posthog/api/organization.py
@coderabbitai

coderabbitai Bot commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: PostHog/posthog/.coderabbit.yaml

Review profile: QUIET

Plan: Enterprise

Run ID: 53f83910-98c2-4096-8a10-fcd60a6ba1f2

📥 Commits

Reviewing files that changed from the base of the PR and between 6a5ff37 and fbe7213.

⛔ Files ignored due to path filters (5)
  • frontend/src/generated/core/api.schemas.ts is excluded by !**/generated/**
  • products/platform_features/frontend/generated/api.schemas.ts is excluded by !**/generated/**
  • products/platform_features/frontend/generated/api.zod.ts is excluded by !**/generated/**
  • services/mcp/src/generated/platform_features/api.ts is excluded by !**/generated/**
  • services/mcp/src/tools/generated/platform_features.ts is excluded by !**/generated/**
📒 Files selected for processing (11)
  • frontend/src/lib/api.mock.ts
  • frontend/src/scenes/organizationLogic.tsx
  • frontend/src/scenes/settings/organization/VerifiedDomains/verifiedDomainImpactLogic.ts
  • frontend/src/types.ts
  • posthog/api/organization.py
  • posthog/dags/postgres_to_clickhouse_etl.py
  • posthog/models/activity_logging/activity_log.py
  • posthog/test/activity_logging/test_organization_activity_logging.py
  • services/mcp/src/api/generated.ts
  • services/mcp/tests/workers/fixtures/api_organizations_id.json
  • services/mcp/tests/workers/fixtures/api_users__me.json
💤 Files with no reviewable changes (11)
  • posthog/test/activity_logging/test_organization_activity_logging.py
  • posthog/api/organization.py
  • frontend/src/lib/api.mock.ts
  • frontend/src/scenes/organizationLogic.tsx
  • posthog/models/activity_logging/activity_log.py
  • services/mcp/tests/workers/fixtures/api_organizations_id.json
  • services/mcp/tests/workers/fixtures/api_users__me.json
  • frontend/src/types.ts
  • services/mcp/src/api/generated.ts
  • frontend/src/scenes/settings/organization/VerifiedDomains/verifiedDomainImpactLogic.ts
  • posthog/dags/postgres_to_clickhouse_etl.py

Included review availability: Your plan provides up to 12 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

The default experiment statistics method field was removed from frontend organization types and update payloads, the organization serializer, and generated MCP organization interfaces. The mock organization and MCP organization fixtures no longer include the field. The organization ClickHouse mirror no longer selects or defines it. The activity-log display-name override and its field-specific test were removed.

Priority: ➖ Normal

Merge Risk: ⚪ Minimal · up to fbe72

The obsolete organization field is removed as intended. Experiment settings remain available through the project configuration endpoint, and no merge-blocking issue was identified.

🚥 Pre-merge checks | ✅ 1
✅ Passed checks (1 passed)
Check name Status Explanation
Description check ✅ Passed The description covers the problem, user-visible impact, changes, testing, documentation, notifications, and agent context. It also identifies the breaking API change and its scope.
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

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

@posthog

posthog Bot commented Sep 23, 2026

Copy link
Copy Markdown
Contributor

👋 Visual changes detected for this PR.

Review and approve in PostHog Visual Review

If these changes are unexpected, they may be caused by a flaky test or a broken snapshot on master. Don't approve — rerun the job or wait for a fix.

@trunk-io

trunk-io Bot commented Sep 23, 2026 •

Copy link
Copy Markdown

Static Badge   Static Badge   Static Badge

Failed Test Failure Summary Logs
userLogic updateUser failure handling keeps the existing user when the update fails — no silent revert via success The test failed because the actual object did not match the expected object, indicating a mismatch in data content. Logs ↗︎
maxLogic chatTitle selector returns the conversation title when the conversation has a title A test failed because the actual value 'New chat' did not match the expected value 'Testing'. Logs ↗︎
Scenes-App/SidePanels SidePanelNotebooks smoke-test The test timed out while waiting for a loading indicator or spinner to disappear. Logs ↗︎

View Full Report ↗︎ ⋅ Docs

@github-actions

github-actions Bot commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

🦔 Hogbox preview · ✅ ready

▶ 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 fbe7213 · box box-bd3ca84aee12 · ready in 649s (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 September 23, 2026 08:28

@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 — escalated to a human reviewer.

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

This drops a field from the public organization API — risky territory — with zero human or agent-review approvals and cross-team, only-moderate-familiarity authorship, so there's no independent assurance to rely on. Greptile also flagged that the desktop API client's generated file needs regeneration, and a grep confirms products/desktop/packages/api-client/src/generated.ts still references the removed field, so that concern looks unaddressed.

  • Author wrote 4% of the modified lines and has 134 merged PRs in these paths (familiarity MODERATE).
  • 👍 on the PR from greptile-apps[bot].
  • Public API contract change (field removed from OrganizationSerializer) with no top-level reviews or approvals
  • Greptile's unresolved concern that the desktop API client needs regeneration appears valid — products/desktop/packages/api-client/src/generated.ts still contains OrganizationDefaultExperimentStatsMethodEnum/default_experiment_stats_method and was not updated in this diff
  • Author andehen is not on either owning team (@PostHog/team-context-mcp, @PostHog/team-platform-features) and familiarity is only MODERATE, not STRONG, so it doesn't substitute for team review in risky territory
Gate mechanics and policy version
Gate Result
prerequisites ✓ all clear
deny-list ✓ no deny categories matched
size ✓ 10L, 7F substantive, 138L/16F incl. docs/generated/snapshots — within ceiling
tier ✓ T1-agent / T1d-complex (138L, 16F, cross-cutting, chore)
stamphog 2.0.0 .stamphog/policy.yml @ fbe7213 · reviewed head fbe7213

@trunk-io
trunk-io Bot merged commit 4b6e06f into master Sep 23, 2026
502 of 505 checks passed
@trunk-io
trunk-io Bot deleted the chore/experiments-strip-superseded-settings-readers branch September 23, 2026 11:59
@deployment-status-posthog

deployment-status-posthog Bot commented Sep 23, 2026 •

Copy link
Copy Markdown

Deploy status

Environment Status Deployed At Workflow
dev ✅ Deployed 2026-09-23 12:42 UTC Run
prod-us ✅ Deployed 2026-09-23 12:53 UTC Run
prod-eu ✅ Deployed 2026-09-23 12:55 UTC Run

This branch was successfully deployed

1 active deployment
preview-pr-104928 — fbe72137 Deployed Sep 23, 2026 by github-actions[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip-agent-review Save $$$, skip auto agent reviews (Greptile) — use for trivial or chore PRs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants