Skip to content

feat(workflows): choose the sandbox sender in email steps - #131916

Merged
trunk-io[bot] merged 83 commits into
masterfrom
workflows-sandbox/u1-editor-sender-choice
Nov 12, 2026
Merged

trunk-io[bot] merged 83 commits into
masterfrom
workflows-sandbox/u1-editor-sender-choice

Conversation

@Silthus

@Silthus Silthus commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor

Note

👀 Reviewed together with #131834. The team question for this change is there. Once you're happy with #131834, please approve this one too.

Stamp request: StampHog cannot auto-review this PR (2061 substantive lines, over its 1200-line limit; every other gate passed). Agents and the merge gate did the bug review, so it needs a stamp from someone on team-workflows.

Problem

  • Teams that can't verify a domain stall at the email sender step of a workflow.
  • The email owner asked for sandbox email to stay fully isolated from ordinary email.
  • #131840 provisions the sandbox sender, but the editor can't choose it.

Replaces #128947, #128950, #128951, #129063 (UI part), #129064, #129065, #129066, #129067.

Caution

🔴 Merge risk: high · one-way door once workflows-sandbox-sender turns on: adoption stores sandbox sender integrations and converted email_sandbox steps, and both stay after the flag turns off

  • Workflow editors in both regions: email step validation, the From picker, and the test panel change on deploy. Unit tests cover them; no base-versus-HEAD run does. A bug there blocks saving an email step or sending a test email.
  • Live-edit hosts (workflow email steps, broadcasts): closing the editor or switching the sender now flushes a pending canvas edit through one action. Logic tests cover it; a bug there drops or blanks an email body.
  • A hog function destination's email editor is unchanged: a shadow diff of edit, save, reopen, discard and test saved identical values on base and HEAD.
  • First run and step insertion with the flag off: one extra status request, and a failed request falls back to the base outcome. First run also reads every page of email senders, where the base read one page of all integrations. A project whose project default or only verified sender sat past that page now gets it preselected; one with a second verified sender past it no longer gets the first preselected. A logic test covers the first case; a bug there preselects the wrong sender, which the person can change.
  • Channels page (MessageChannels.tsx:30, SandboxEmailSenderRow.tsx:20): every visitor in both regions sends one extra status request. The sandbox sender row shows only for a team with a sandbox sender, which needs the flag; a failed request hides it. No test or base-versus-HEAD run covers it; a bug there breaks the Channels page.
  • Workflow metrics (WorkflowMetrics.tsx:58): teams with sandbox sends, only once the flag is on, see six new metric labels. No test covers them; a bug there mislabels a metric.
  • Over 400 production lines raise the grade while rows stay uncovered.
  • Switch-off: workflows-sandbox-sender (server side) stops new sandbox senders and steps. Validation, the picker, the test panel, and the close flush are live on deploy: fix forward.

Rollout

Changes

  • The email step's From picker lists the sandbox sender below the project's own senders. Templates, other products' workflows, and steps whose ID the sandbox rejects (such as an API-created welcome.email) never offer it.
  • A sandbox step keeps the same email form, without Reply-To, CC, BCC, or a custom sender. Picking an own sender there switches back.
  • Switching asks first when Reply-To, CC/BCC, a custom From, turned-off tracking, or UTM tags would be lost. A new or template email that sets any of those itself stays on an own sender. UTM tags that match the team default don't count.
  • A sandbox step whose sender isn't set up offers to set it up, also after a reload. When the organization blocks sandbox email, or the project can't use it, the step says so instead.
  • Switching the sender in the open editor keeps a canvas edit made in the last 500 ms. Before, the email body was wiped: the debounced export ran against the remounted, still-empty editor.
  • Sandbox test runs send to a chosen verified member and explain the outcome. With no verified member, the test says so; while members load, it waits. A result clears when the step changes sender.
  • Messaging channels list the sandbox sender.
  • API and MCP editing of sandbox steps lands in #132585, stacked on this PR.
  • Mechanical: the email_sandbox integration kind, metrics names, and typegen.
Before (flag off, unchanged) After (flag on)
From picker, flag off From picker, flag on
Switch confirmation Sandbox step
Switch confirmation Sandbox step
Sender not set up Organization blocked
Sender not set up Organization blocked
Sandbox test run Messaging channels
Sandbox test Channels row

Sandbox sender isolation, U1 highlighted

This PR builds the parts outlined in blue: the email step's sender choice and the email_sandbox step it saves.

How did you test this code?

Test rationale: each new test guards one contract no older test checks.

  • Not checked: a live send or a real backend. Screenshots use Storybook with mocked APIs.
  • A Storybook walk at 8f0ad2b switches senders both ways, with settled and pending canvas edits. Every journey keeps the subject and the body.
  • A shadow diff runs a hog function destination's email editor on base and HEAD: edit, save, reopen, discard with and without the confirm dialog, test, and save. The saved values and test payloads match; only the test panel's random sample ids differ.
  • Not tested automatically: workflow variables in the sandbox form's field autocomplete, which runs in a code editor jsdom can't render.
Tests
  • emailTemplaterLogic.test.ts: closing or switching the sender mid-debounce, then a blank editor mounting, leaves the parent holding the edited design and text. Failed before the fix. A second case edits the canvas while a sender switch's export is still pending; the parent ends with the newer design. It failed before a83b55e. The other live-change tests assert the parent's stored email, not onChange calls.
  • emailStepVariants.test.ts: conversions keep only sandbox fields, an editor edit keeps the recipient, and a draft without one reads as empty.
  • SandboxSenderChoiceProvider.test.tsx: the real From picker on a stored step asks before dropping settings, switches both ways from the open editor, which stays open and keeps a canvas edit still inside the export debounce, and hides the sandbox sender without adoption. Mutation-checked.
  • emailSenderControlLogic.test.ts: the confirm and cancel paths, and when the choice shows.
  • workflowLogic.emailValidation.test.ts: a sandbox step checks content, never a sender, and a draft saved without a recipient asks for one. Mutation-checked.
  • hogFlowEditorLogic.test.ts and workflowLogic.sandboxSender.test.ts: a new email step picks the sandbox sender only once the project is known to have no verified sender, also when the team turns UTM tags on by default, never in another product's workflow, and a template email with its own UTM values keeps them. Mutation-checked.
  • sandboxSenderLogic.test.ts and workflowLogic.sandboxSender.test.ts, against a sandbox sender fake: setup goes to the selected environment when its id differs from its project, the step reports a sender never set up, being set up, failed, blocked (also after setup), or unavailable, and a template email with a Reply-To stays on an own sender. Mutation-checked.
  • testResultBanner.test.ts: the sandbox result copy, a mocked run, and other steps reading as before. It covers a suspended project, a paused workflow, a suspension check that timed out, a rate-limited send, an unreachable sandbox sender, and a step ID the sender can't tag, which a composed UI walk with the Node PR had shown as a raw code. An unknown reason shows its code.
  • With P2's runtime setting, from #131840 at b9fe013, a local sandbox test send also needs WORKFLOWS_SANDBOX_EMAIL_RUNTIME_ENABLED=true in Django. This PR's own UI walk ran on an earlier base that had no such setting.
  • hogFlowEditorNotificationTestLogic.test.ts: a sandbox test goes only to the verified member the user confirmed, sends nothing when members load late or fail, waits for members before judging, says why it can't run with no verified member, and records its event after the selection moves on without showing that result on the next step. Mutation-checked.
  • stepFacts.test.ts, workflowStepCatalog.test.ts and HogFlowSteps.test.ts: the canvas names a sandbox step Email and previews it, also without a recipient. Mutation-checked.

Release status

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

Docs update

  • None.

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

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

Skills: /writing-ui-components, /writing-tests, /writing-user-facing-copy, /writing-pr-descriptions, /merge-risk

More context for AI agents
  • Decisions: this PR lands only together with feat(workflows): edit and choose the sandbox sender through the api and mcp #132585, by enqueueing the top of the stack, and the flag stays off until both are live; that closes the API and MCP parity gap for converted steps. Sender status and provisioning live in Channels/sandboxSenderLogic, shared by the editor and channels, not in the step logic. The sandbox option reaches the shared From picker through SandboxSenderChoiceContext; without its provider, hog function destinations render as before.
  • Follow-ups: the one-click all-step switch and its banner, sandbox test sends from the template library, and email_sandbox support in the email patch API and the AI context.
  • Review: a full QA swarm (rounds 15 and 16: nine lenses across Claude Opus 5.5 and GPT-6.1 Sol) found a mistyped test call, automatic adoption dropping own-only settings, a lost set-up action after reload, a dead end with no verified member, missing workflow variables in the sandbox form, and tests asserting call counts and mock arguments; all are fixed. Round 16 found that the team's UTM default blocked adoption, the setup banner vanished while setting up and offered setup a blocked organization can't use, and the test read unloaded members as none; all are fixed. Final reads found that the UTM exemption dropped a template's own UTM values, and Fleet's judge that a test finishing after the selection moved showed its result on the next step and that an organization blocked after setup got no explanation; all are fixed, and the last final read found nothing. Rejected with reasons in the proof ledger: the editor closing on a switch (a test now proves it stays open), a repeated setup event, step ID validation, and two refactors. Follow-up: the email patch API and AI context for sandbox steps. Before that, GPT-6.1 Sol reviewed in fourteen rounds. Round 13, on the From picker rework, found that a sender switch dropped a canvas edit still inside the export debounce, and that the picker tests stubbed the selects; both are fixed. Round 1 found one high and six medium issues, round 2 two missing tests, round 5 a selection race in the test event, round 7 two missing tests, round 9 a stale Python enum copy. All are fixed; rounds 3, 4, 6, 8, 10, 11 and 12 found nothing. Rounds 7 to 12 ran past Fleet's cap under the standing review rule. Fleet's judge also flagged that the switch dropped turned-off tracking and UTM tags without saying so; the confirmation now lists both. A Storybook walk at cee27c3 found that a sender switch inside the canvas debounce wiped the email body; fixed in 8f0ad2b, and final read 10 at 8f0ad2b found nothing.
  • PostHog Review (at 5b6e6eb): a draft without a recipient broke the canvas (fixed). The missing executor is N1's (rollout gated). A sandbox metrics overview is out of scope (labels only).
  • CI report: the TypeScript complexity rows are functions over the limit before this PR. Where this PR adds a sandbox branch to one, the branch lives in a helper: withSandboxSenderOnInsert for onDrop (51 on the base, 52 now), senderErrors and isEmailStep for the save validator (42 on the base, 40 now), and withRecipientEmail for the test submit. Three rows still grow: getIntegrationNameFromKind (27 to 28) gains one switch case for the new kind, ownOnlySettings (12) makes one check per setting the sandbox sender drops, and NativeEmailIntegrationChoice goes from 13 to 17 for four sandbox decisions: the empty state, the rotation picker, Custom sender, and the hint. Its option building lives in sandboxSenderOptions.tsx. The report at 7c8815b shows the bundle up 10.4 KiB: the workflow editor chunk (+6.3 KiB) and render-query (+3.6 KiB). Not traced: which import carries this PR's changes into render-query. The eager graph grows 786 B on the events, web analytics, dashboard, AI-first home and replay paths. Master already loads EmailTemplater eagerly on those paths, and this PR adds the sandbox sender choice to it. Moving EmailTemplater off those paths is a change of its own. Today home and the paths that include it grow 58 B, the email_sandbox icon and name in lib/integrations/utils.ts. No root crosses its budget, and the flagged logged-out boot path shows no change, because master already fills it. The duplication scans could not run at 85bd58e and again at 7c8815b, because jscpd ran out of memory (exit 137). Each rerun found Python clean. Most of the 25 TypeScript blocks are kea typegen interfaces whose unions gained email_sandbox. The largest pair, 3667 tokens in hogFlowEditorLogic.tsx and workflowLogic.ts, is the HogFlow union that typegen writes twice for loadWorkflowSuccess, as its parameter and its return type. Master already repeats that union at 888 lines; the new variant makes it 941, so the scan counts it as new. The test-result view shared by the two test panels was duplicated before this PR, which changed one line inside it. The email_sandbox zod schema in steps/types.ts repeats Node's schema/hogflow.ts, as every action type does, since the two packages share no imports. The frontend copy also accepts null categories, which the backend allows. The PR sits in the backend Python lane only because the generated Python copy of IntegrationKind gained email_sandbox. Backend coverage reports every changed line covered. The Hogbox preview is optional. Its workflow runs at 7c8815b and a83b55e passed every job, though the report shows the build failed. The flaky Playwright test at a83b55e is Delete a person property in playwright/e2e/persons/persons.spec.ts. On the first attempt, the property added through the UI did not reach the persons API within the test's 10-second poll, so the delete step never started. The retry passed, and this PR changes no persons code. At 0fbdc60 it was password-protected insight sharing, where the shared page failed to fetch the lazy ExporterInsightScene chunk; this PR changes no sharing, insight or exporter code.
  • Read closely: NativeEmailIntegrationChoice in EmailTemplater.tsx, emailSenderControlLogic.ts, the insert path in hogFlowEditorLogic.tsx, and workflowLogic.ts validation.

🤖 Generated with Claude Code

Silthus and others added 14 commits November 9, 2026 11:37
Add the email_sandbox integration kind with credentials as its only auth
type, and the two tables the sandbox sender reads: a mirror of the shared
SES tenant's sending status and a staff-set organization block. Nothing
reads them yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds the email_sandbox step type and its server-side contract: an
allowlisted config that cannot name a sender or delivery settings, an
adoption flag for new steps with stored steps grandfathered, and a
refusal in broadcasts, other products' workflows and templates.

Adds the project's sandbox sender endpoints (status and provision), the
minute poll that mirrors the sandbox SES tenant status, a staff admin
for organization blocks, and the activation exclusion for workflows
whose only messages go through the sandbox. Ordinary email steps can no
longer newly pick a sender row that is not an email sender.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Keep the sandbox action type in the hog flow model module so the
  workflows facade stays off the Django startup import path.
- Grandfather the wrong-kind sender rule only from the live workflow; a
  lenient web draft never raised it, so its draft value must not pass
  publish unchecked.
- Compile sandbox Hog templates with the warehouse record alias when a
  warehouse table triggers the workflow.
- Serialize the sender status DTO directly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A web draft save tolerates unfinished steps, so the sender-kind rule never
ran there. The sender then reached the workflow's live actions and was
grandfathered when it published. A wrong-kind sender is never an unfinished
edit, so every save now refuses it.

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

A sandbox email step now refuses a null recipient name, subject, preheader,
text or HTML, which the sender's renderer cannot take. A test run's
configuration override on a workflow another product owns is now refused
like a save, because the ownership check reads the flow from the context.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A test run's configuration override could claim no owning product and
send a sandbox step for a workflow another product owns. The owner is
set on create and never changes, so the saved value now decides.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A web draft save with malformed function inputs crashed the sender-kind
check before the serializer could tolerate them. The check now leaves
such inputs to the serializer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The draft sender check now reaches cdp through its presentation
re-exports, as the facade contract requires. The tenant poll is marked
exempt from the team scope audit, because its model is platform state
with no team.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The block admin prefills the staff member on the add form instead of
overriding save_model, and the sender lookup returns a frozen dataclass
instead of a (kind, domain) tuple.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Email steps get a sender control that lists verified own senders and,
when the project can adopt it, the sandbox sender. Choosing a sender
replaces the step with the matching stored type in one change, and
asks first when own-only settings would be dropped.

New workflows and inserted email steps use the sandbox sender when no
verified own sender exists. Sandbox steps get their own panel, content
validation, a verified-member test recipient, readable test results,
a Channels row, and metric labels.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…u1-editor-sender-choice

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Silthus Silthus added hogbox-preview Spin up a per-PR PostHog preview on a hogland hogbox run-ci-frontend Force ci-storybook's full visual-regression matrix to run even on a draft PR labels Nov 9, 2026
@Silthus Silthus self-assigned this Nov 9, 2026
@github-actions

github-actions Bot commented Nov 9, 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) — 18 functions above the limit (max 52)

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
onDrop products/workflows/frontend/Workflows/hogflows/hogFlowEditorLogic.tsx:2699 52 10
saveWorkflowSuccess products/workflows/frontend/Workflows/workflowLogic.ts:4937 45 10
runSave products/workflows/frontend/Workflows/workflowLogic.ts:3806 42 10
<anonymous> products/workflows/frontend/Workflows/workflowLogic.ts:4361 40 10
getIntegrationNameFromKind frontend/src/lib/integrations/utils.ts:146 28 10
handleOauthCallback frontend/src/lib/integrations/integrationsLogic.ts:1270 27 10
EmailActionTestContent products/workflows/frontend/Workflows/hogflows/panel/testing/HogFlowEditorNotificationPanelTest.tsx:36 24 10
HogFlowEditorPanel products/workflows/frontend/Workflows/hogflows/panel/HogFlowEditorPanel.tsx:32 21 10
NativeEmailIntegrationChoice frontend/src/scenes/hog-functions/email-templater/EmailTemplater.tsx:257 17 10
WorkflowRunMetrics products/workflows/frontend/Workflows/WorkflowMetrics.tsx:98 16 10
NativeEmailTemplaterForm frontend/src/scenes/hog-functions/email-templater/EmailTemplater.tsx:588 15 10
presentationFacts products/workflows/frontend/Workflows/hogflows/editor/tile-canvas/stepFacts.ts:212 14 10
triggerFacts products/workflows/frontend/Workflows/hogflows/editor/tile-canvas/stepFacts.ts:274 13 10
<anonymous> frontend/src/scenes/hog-functions/email-templater/emailTemplaterLogic.tsx:1080 12 10
BatchJobMetrics products/workflows/frontend/Workflows/WorkflowMetrics.tsx:299 12 10
ownOnlySettings products/workflows/frontend/Workflows/hogflows/steps/email/emailStepVariants.ts:109 12 10
getTriggerPreviews products/workflows/frontend/Workflows/hogflows/steps/HogFlowSteps.tsx:83 11 10
submit products/workflows/frontend/Workflows/workflowLogic.ts:4000 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) — 25 new duplicated blocks (worst 3667 tokens)

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.

First copy Second copy Lines Tokens
products/workflows/frontend/Workflows/hogflows/hogFlowEditorLogic.tsx:267 products/workflows/frontend/Workflows/hogflows/hogFlowEditorLogic.tsx:1211 942 3667
products/workflows/frontend/Workflows/workflowLogic.ts:610 products/workflows/frontend/Workflows/workflowLogic.ts:1554 942 3667
products/workflows/frontend/Workflows/hogflows/steps/stepWaitUntilTimeWindowLogic.ts:439 products/workflows/frontend/Workflows/workflowLogic.ts:2509 343 1265
products/workflows/frontend/Workflows/hogflows/steps/stepDelayLogic.ts:513 products/workflows/frontend/Workflows/workflowLogic.ts:2945 341 1261
products/workflows/frontend/Workflows/hogflows/steps/stepWaitUntilTimeWindowLogic.ts:101 products/workflows/frontend/Workflows/hogflows/steps/stepWaitUntilTimeWindowLogic.ts:442 339 1257
products/workflows/frontend/Workflows/hogflows/steps/stepDelayLogic.ts:176 products/workflows/frontend/Workflows/hogflows/steps/stepWaitUntilTimeWindowLogic.ts:102 337 1252
products/workflows/frontend/Workflows/hogflows/steps/stepDelayLogic.ts:228 products/workflows/frontend/Workflows/hogflows/steps/stepDelayLogic.ts:573 66 253
frontend/src/lib/integrations/integrationsLogic.ts:386 frontend/src/scenes/settings/organization/organizationIntegrationsLogic.ts:86 62 164
frontend/src/scenes/settings/organization/organizationIntegrationsLogic.ts:86 frontend/src/scenes/settings/organization/organizationIntegrationsLogic.ts:149 62 164
frontend/src/lib/integrations/integrationsLogic.ts:386 frontend/src/lib/integrations/integrationsLogic.ts:453 61 161
products/workflows/frontend/Workflows/hogflows/hogFlowEditorLogic.tsx:354 products/workflows/frontend/Workflows/hogflows/hogFlowEditorLogic.tsx:679 31 133
products/workflows/frontend/Workflows/workflowLogic.ts:671 products/workflows/frontend/Workflows/workflowLogic.ts:936 31 133
frontend/src/lib/integrations/integrationsLogic.ts:741 frontend/src/scenes/settings/organization/organizationIntegrationsLogic.ts:219 52 114
frontend/src/lib/integrations/integrationsLogic.ts:136 frontend/src/scenes/settings/organization/organizationIntegrationsLogic.ts:16 51 107
frontend/src/lib/integrations/integrationsLogic.ts:136 frontend/src/lib/integrations/integrationsLogic.ts:742 51 106
products/workflows/frontend/Workflows/hogflows/panel/testing/HogFlowEditorNotificationPanelTest.tsx:372 products/workflows/frontend/Workflows/hogflows/panel/testing/HogFlowEditorPanelTest.tsx:152 19 102
frontend/src/lib/integrations/integrationsLogic.ts:258 products/data_warehouse/frontend/shared/logics/destinationModalLogic.ts:123 50 100
frontend/src/lib/integrations/integrationsLogic.ts:259 frontend/src/lib/integrations/integrationsLogic.ts:397 48 96
frontend/src/lib/integrations/integrationsLogic.ts:259 frontend/src/lib/integrations/integrationsLogic.ts:525 48 96
frontend/src/lib/integrations/integrationsLogic.ts:592 frontend/src/lib/integrations/integrationsLogic.ts:644 48 96
frontend/src/lib/integrations/integrationsLogic.ts:259 frontend/src/lib/integrations/integrationsLogic.ts:592 48 95
frontend/src/lib/integrations/integrationsLogic.ts:138 frontend/src/lib/integrations/integrationsLogic.ts:260 47 94
products/workflows/frontend/Workflows/hogflows/steps/stepDelayLogic.ts:271 products/workflows/frontend/Workflows/workflowLogic.ts:705 22 85
frontend/src/lib/integrations/integrationsLogic.ts:150 frontend/src/lib/integrations/integrationsLogic.ts:756 38 77
products/workflows/frontend/Workflows/hogflows/panel/testing/hogFlowEditorNotificationTestLogic.ts:222 products/workflows/frontend/Workflows/hogflows/panel/testing/hogFlowEditorTestLogic.ts:295 17 75
⚠️ Bundle size — 🔺 +10.4 KiB (+0.0%)

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

Total: 79.10 MiB · 🔺 +10.4 KiB (+0.0%)

File Size Δ vs base
exporter/_parent/products/workflows/frontend/Workflows/Workflow.js 211.1 KiB 🔺 +6.3 KiB (+3.1%)
render-query/src/render-query/render-query.js 22.20 MiB 🔺 +3.6 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.05 MiB · 25 files no change █████████░ 91.6% of 1.14 MiB
logged-out boot: index + App + bootApp (preloaded by every page, including /login)
src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
2.87 MiB · 538 files no change ██████████ 99.1% of 2.89 MiB
authenticated shell (every logged-in page)
src/scenes/AuthenticatedShell.tsx
3.89 MiB · 1,237 files no change ██████████ 99.5% of 3.91 MiB
dashboard scene
src/scenes/dashboard/Dashboard.tsx
7.84 MiB · 3,026 files 🔺 +844 B (+0.0%) ██████████ 99.1% of 7.92 MiB
today home path
src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
4.88 MiB · 1,872 files 🔺 +58 B (+0.0%) ██████████ 99.9% of 4.88 MiB
AI-first home path
src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx
6.10 MiB · 2,297 files 🔺 +844 B (+0.0%) ██████████ 99.5% of 6.13 MiB
events scene
src/scenes/activity/explore/EventsScene.tsx
6.83 MiB · 2,568 files 🔺 +786 B (+0.0%) ██████████ 98.8% of 6.91 MiB
web analytics scene
src/scenes/web-analytics/WebAnalyticsScene.tsx
7.92 MiB · 2,973 files 🔺 +786 B (+0.0%) ██████████ 99.5% of 7.96 MiB
replay detail scene
src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
7.01 MiB · 2,622 files 🔺 +844 B (+0.0%) ██████████ 98.9% of 7.09 MiB

🟢 node_modules/monaco-editor/ stays out of src/index.tsx
🟢 products/product_analytics/frontend/insights/activityDescriptions 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/lib/lemon-ui/LemonTable/LemonTable.tsx stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 node_modules/@dnd-kit/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/layout/navigation-3000/navigationLogic.tsx stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/scenes/dashboard/dashboardLogic.tsx stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/lemon-ui/LemonMarkdown/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/components/RichContentEditor/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/components/CodeSnippet/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/taxonomy/core-filter-definitions-by-group.json stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 node_modules/zod/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/logic/billing/billingLogic.tsx stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/components/ProductEmptyState/productSetupPreloadLogic.ts stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 node_modules/kea-test-utils/ 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
🟢 products/product_analytics/frontend/insights/activityDescriptions stays out of src/scenes/AuthenticatedShell.tsx
🟢 node_modules/kea-test-utils/ 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
🟢 src/layout/panel-layout/ProjectTree/menus/SessionReplayMenuItems.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/taxonomy/core-filter-definitions-by-group.json stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/layout/navigation/projectNoticeLogic.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/layout/navigation/ImpersonationNotice/ImpersonationNotice.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/scenes/cohorts/cohortSavedToast.ts stays out of src/scenes/AuthenticatedShell.tsx
🟢 products/wizard/frontend/runs/WizardRunDetailsDrawer.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/layout/today/TodayShell.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/layout/today/TodayContextPanelFloating.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/layout/today/TodaySidePanel.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/layout/today/TodayTopBar.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/layout/today/todayRailItems.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 products/subscriptions/frontend/components/Subscriptions/exportNudge/exportNudgeLogic.ts stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/scenes/billing/paymentEntryLogic.ts stays out of src/scenes/AuthenticatedShell.tsx
🟢 products/conversations/frontend/components/SidePanel/sidepanelTicketsLogic.ts stays out of src/scenes/AuthenticatedShell.tsx
🟢 node_modules/zod/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/scenes/authentication/auth/loginLogic.ts stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/scenes/authentication/shared/passkeyLogic.ts stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/scenes/cohorts/CohortFilters/constants.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 products/persons/frontend/logics/personsLogic.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/scenes/surveys/constants.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 node_modules/@tiptap/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 node_modules/prosemirror- stays out of src/scenes/AuthenticatedShell.tsx
🟢 node_modules/re2js/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 node_modules/react-markdown/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/lib/components/Command/Command.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 packages/quill/packages/ 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
🟢 packages/quill/packages/quill/dist/ stays out of src/scenes/dashboard/Dashboard.tsx
🟢 node_modules/@tiptap/ stays out of src/scenes/dashboard/Dashboard.tsx
🟢 node_modules/prosemirror- stays out of src/scenes/dashboard/Dashboard.tsx
🟢 node_modules/marked/ stays out of src/scenes/dashboard/Dashboard.tsx
🟢 node_modules/frimousse/ stays out of src/scenes/dashboard/Dashboard.tsx
🟢 src/scenes/session-recordings/playlist/SessionRecordingsPlaylist.tsx stays out of src/scenes/dashboard/Dashboard.tsx
🟢 src/scenes/web-analytics/tiles/WebAnalyticsTile.tsx stays out of src/scenes/dashboard/Dashboard.tsx
🟢 src/queries/validators.js stays out of src/scenes/dashboard/Dashboard.tsx
🟢 src/queries/web-analytics-validators.js stays out of src/scenes/dashboard/Dashboard.tsx
🟢 node_modules/re2js/ stays out of src/scenes/dashboard/Dashboard.tsx
🟢 node_modules/kea-test-utils/ stays out of src/scenes/dashboard/Dashboard.tsx
🟢 src/scenes/debug/HogDebug.tsx stays out of src/scenes/dashboard/Dashboard.tsx
🟢 src/queries/QueryEditor/QueryEditor.tsx stays out of src/scenes/dashboard/Dashboard.tsx
🟢 packages/quill/packages/quill/dist/ stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
🟢 src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
🟢 src/scenes/project-homepage/today/TodayReportPage.tsx stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
🟢 src/queries/Query/Query.tsx stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
🟢 packages/quill/packages/charts/ stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
🟢 packages/quill/packages/quill/dist/ stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx
🟢 products/posthog_ai/frontend/components/tool/widgets/VisualizationWidget.tsx stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx
🟢 products/posthog_ai/frontend/components/tool/widgets/RecordingsWidget.tsx stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx
🟢 src/queries/Query/Query.tsx stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx
🟢 products/posthog_ai/frontend/api/primitives.ts stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx
🟢 src/scenes/notebooks/Notebook/notebookLogic.ts stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx
🟢 packages/quill/packages/quill/dist/ stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 node_modules/@tiptap/ stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 node_modules/prosemirror- stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 node_modules/marked/ stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 node_modules/frimousse/ stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 src/scenes/session-recordings/playlist/SessionRecordingsPlaylist.tsx stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 src/scenes/web-analytics/tiles/WebAnalyticsTile.tsx stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 src/queries/validators.js stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 src/queries/web-analytics-validators.js stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 node_modules/re2js/ stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 node_modules/kea-test-utils/ stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 src/queries/nodes/InsightViz/InsightViz.tsx stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 src/queries/nodes/DataVisualization/DataVisualization.tsx stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 src/queries/nodes/WebOverview/WebOverview.tsx stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 src/scenes/debug/HogDebug.tsx stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 src/queries/QueryEditor/QueryEditor.tsx stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 packages/quill/packages/quill/dist/ stays out of src/scenes/web-analytics/WebAnalyticsScene.tsx
🟢 node_modules/@tiptap/ stays out of src/scenes/web-analytics/WebAnalyticsScene.tsx
🟢 node_modules/prosemirror- stays out of src/scenes/web-analytics/WebAnalyticsScene.tsx
🟢 node_modules/marked/ stays out of src/scenes/web-analytics/WebAnalyticsScene.tsx
🟢 node_modules/frimousse/ stays out of src/scenes/web-analytics/WebAnalyticsScene.tsx
🟢 src/scenes/web-analytics/LiveMetricsDashboard/LiveWebAnalyticsMetrics.tsx stays out of src/scenes/web-analytics/WebAnalyticsScene.tsx
🟢 products/product_analytics/frontend/insights/trends/WorldMap/countryVectors.tsx stays out of src/scenes/web-analytics/WebAnalyticsScene.tsx
🟢 src/queries/validators.js stays out of src/scenes/web-analytics/WebAnalyticsScene.tsx
🟢 node_modules/re2js/ stays out of src/scenes/web-analytics/WebAnalyticsScene.tsx
🟢 node_modules/kea-test-utils/ stays out of src/scenes/web-analytics/WebAnalyticsScene.tsx
🟢 src/scenes/debug/HogDebug.tsx stays out of src/scenes/web-analytics/WebAnalyticsScene.tsx
🟢 src/queries/QueryEditor/QueryEditor.tsx stays out of src/scenes/web-analytics/WebAnalyticsScene.tsx
🟢 packages/quill/packages/quill/dist/ stays out of src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
🟢 node_modules/@tiptap/ stays out of src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
🟢 node_modules/prosemirror- stays out of src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
🟢 node_modules/marked/ stays out of src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
🟢 src/scenes/settings/SettingsMap.tsx stays out of src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
🟢 @jspm/core/nodelibs/browser/fs stays out of src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
🟢 node_modules/re2js/ stays out of src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
🟢 node_modules/kea-test-utils/ stays out of src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
🟢 node_modules/d3/src/ stays out of src/scenes/session-recordings/detail/SessionRecordingDetail.tsx

Largest files eagerly shipped from src/index.tsx
Size File
126.8 KiB ../node_modules/.pnpm/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.7 KiB ../node_modules/.pnpm/@jspm+core@2.1.0/node_modules/@jspm/core/nodelibs/browser/process.js
4.0 KiB ../node_modules/.pnpm/scheduler@0.23.2/node_modules/scheduler/cjs/scheduler.production.min.js
1.8 KiB src/lib/utils/bootTiming.ts
1.7 KiB ../node_modules/.pnpm/base64-js@1.5.1/node_modules/base64-js/index.js
1.7 KiB src/index.tsx
1.2 KiB src/RootErrorBoundary.tsx
1.1 KiB src/lib/utils/deferredAppContext.ts
Largest files eagerly shipped from src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
Size File
363.5 KiB ../node_modules/.pnpm/posthog-js@1.447.13_@types+react@18.3.31_react@18.3.1/node_modules/posthog-js/dist/module.mjs
224.1 KiB ../node_modules/.pnpm/@posthog+icons@0.39.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
108.1 KiB src/products.tsx
93.2 KiB src/lib/api.ts
69.0 KiB src/lib/lemon-ui/icons/icons.tsx
36.4 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.4 KiB src/lib/constants.tsx
24.8 KiB ../node_modules/.pnpm/fuse.js@7.3.0/node_modules/fuse.js/dist/fuse.mjs
24.6 KiB ../node_modules/.pnpm/buffer@6.0.3/node_modules/buffer/index.js
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx
Size File
363.5 KiB ../node_modules/.pnpm/posthog-js@1.447.13_@types+react@18.3.31_react@18.3.1/node_modules/posthog-js/dist/module.mjs
224.1 KiB ../node_modules/.pnpm/@posthog+icons@0.39.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
108.1 KiB src/products.tsx
93.2 KiB src/lib/api.ts
69.0 KiB src/lib/lemon-ui/icons/icons.tsx
40.3 KiB ../node_modules/.pnpm/@dnd-kit+core@6.3.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@dnd-kit/core/dist/core.esm.js
36.4 KiB ../node_modules/.pnpm/kea@4.0.0-pre.6_patch_hash=139b8d1f1304f9d9da452a9a1244c94ea679dbcb85687d8999563146879fb6f5_react@18.3.1/node_modules/kea/lib/index.cjs.js
32.6 KiB src/lib/utils/eventUsageLogic.ts
29.4 KiB src/lib/constants.tsx
Largest files eagerly shipped from src/scenes/dashboard/Dashboard.tsx
Size File
363.5 KiB ../node_modules/.pnpm/posthog-js@1.447.13_@types+react@18.3.31_react@18.3.1/node_modules/posthog-js/dist/module.mjs
224.1 KiB ../node_modules/.pnpm/@posthog+icons@0.39.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
116.4 KiB ../node_modules/.pnpm/posthog-js@1.447.13_@types+react@18.3.31_react@18.3.1/node_modules/posthog-js/dist/surveys-preview.js
112.7 KiB ../packages/quill/packages/primitives/dist/index.js
108.1 KiB src/products.tsx
98.2 KiB ../packages/quill/packages/components/dist/index.js
93.2 KiB src/lib/api.ts
78.8 KiB src/scenes/dashboard/dashboardLogic.tsx
69.0 KiB src/lib/lemon-ui/icons/icons.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
363.5 KiB ../node_modules/.pnpm/posthog-js@1.447.13_@types+react@18.3.31_react@18.3.1/node_modules/posthog-js/dist/module.mjs
224.1 KiB ../node_modules/.pnpm/@posthog+icons@0.39.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
112.7 KiB ../packages/quill/packages/primitives/dist/index.js
108.1 KiB src/products.tsx
93.2 KiB src/lib/api.ts
69.0 KiB src/lib/lemon-ui/icons/icons.tsx
68.5 KiB ../products/posthog_ai/frontend/logics/runStreamLogic.ts
40.3 KiB ../node_modules/.pnpm/@dnd-kit+core@6.3.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@dnd-kit/core/dist/core.esm.js
36.4 KiB ../node_modules/.pnpm/kea@4.0.0-pre.6_patch_hash=139b8d1f1304f9d9da452a9a1244c94ea679dbcb85687d8999563146879fb6f5_react@18.3.1/node_modules/kea/lib/index.cjs.js
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx
Size File
363.5 KiB ../node_modules/.pnpm/posthog-js@1.447.13_@types+react@18.3.31_react@18.3.1/node_modules/posthog-js/dist/module.mjs
224.1 KiB ../node_modules/.pnpm/@posthog+icons@0.39.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
112.7 KiB ../packages/quill/packages/primitives/dist/index.js
108.1 KiB src/products.tsx
93.2 KiB src/lib/api.ts
69.0 KiB src/lib/lemon-ui/icons/icons.tsx
68.5 KiB ../products/posthog_ai/frontend/logics/runStreamLogic.ts
41.7 KiB src/scenes/hog-functions/sub-templates/sub-templates.ts
40.3 KiB ../node_modules/.pnpm/@dnd-kit+core@6.3.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@dnd-kit/core/dist/core.esm.js
Largest files eagerly shipped from src/scenes/activity/explore/EventsScene.tsx
Size File
363.5 KiB ../node_modules/.pnpm/posthog-js@1.447.13_@types+react@18.3.31_react@18.3.1/node_modules/posthog-js/dist/module.mjs
224.1 KiB ../node_modules/.pnpm/@posthog+icons@0.39.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
112.7 KiB ../packages/quill/packages/primitives/dist/index.js
108.1 KiB src/products.tsx
98.2 KiB ../packages/quill/packages/components/dist/index.js
93.2 KiB src/lib/api.ts
78.8 KiB src/scenes/dashboard/dashboardLogic.tsx
69.0 KiB src/lib/lemon-ui/icons/icons.tsx
68.5 KiB ../products/posthog_ai/frontend/logics/runStreamLogic.ts
Largest files eagerly shipped from src/scenes/web-analytics/WebAnalyticsScene.tsx
Size File
363.5 KiB ../node_modules/.pnpm/posthog-js@1.447.13_@types+react@18.3.31_react@18.3.1/node_modules/posthog-js/dist/module.mjs
224.1 KiB ../node_modules/.pnpm/@posthog+icons@0.39.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
116.4 KiB ../node_modules/.pnpm/posthog-js@1.447.13_@types+react@18.3.31_react@18.3.1/node_modules/posthog-js/dist/surveys-preview.js
112.7 KiB ../packages/quill/packages/primitives/dist/index.js
108.1 KiB src/products.tsx
98.2 KiB ../packages/quill/packages/components/dist/index.js
93.2 KiB src/lib/api.ts
78.8 KiB src/scenes/dashboard/dashboardLogic.tsx
69.0 KiB src/lib/lemon-ui/icons/icons.tsx
Largest files eagerly shipped from src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
Size File
363.5 KiB ../node_modules/.pnpm/posthog-js@1.447.13_@types+react@18.3.31_react@18.3.1/node_modules/posthog-js/dist/module.mjs
329.8 KiB ../node_modules/.pnpm/posthog-js@1.447.13_@types+react@18.3.31_react@18.3.1/node_modules/posthog-js/dist/rrweb.js
224.1 KiB ../node_modules/.pnpm/@posthog+icons@0.39.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
112.7 KiB ../packages/quill/packages/primitives/dist/index.js
108.1 KiB src/products.tsx
98.2 KiB ../packages/quill/packages/components/dist/index.js
93.2 KiB src/lib/api.ts
69.0 KiB src/lib/lemon-ui/icons/icons.tsx
68.5 KiB ../products/posthog_ai/frontend/logics/runStreamLogic.ts

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

✅ Frontend layers — no new upward imports, 0 removed

Static imports from a lower frontend layer into a higher one (layers, lowest first: kernel, shell, query, features). Compared with the base branch, so an import that a PR also adds to layer-baseline.txt still shows here. Sizes are the source bytes on the eager path of every logged-in page.

Layer Eager source bytes Δ vs base
kernel 3.01 MiB 🔺 +21 B (+0.0%)
shell 2.42 MiB no change
query 56.9 KiB no change
features 274.3 KiB no change

Download the interactive layer graph for this PR.

Posted automatically by check-layers

✅ Toolbar bundle — eager 2.45 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.45 MiB · 19 files no change ████░░░░░░ 42.8% of 5.72 MiB
Deferred (lazy) 2.64 MiB · 43 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
985.3 KiB dist/toolbar/toolbar-app-WRRY4DD6.css
739.3 KiB dist/toolbar/chunk-chunk-HTZUGHV7.js
290.5 KiB dist/toolbar/chunk-chunk-E2SUTX3R.js
137.6 KiB dist/toolbar/chunk-chunk-VDQTCFXU.js
131.8 KiB dist/toolbar/chunk-chunk-FQJO25M6.js
75.7 KiB dist/toolbar/toolbar-app-VVJSXHEF.js
69.0 KiB dist/toolbar/chunk-chunk-BFAXZMC5.js
33.8 KiB dist/toolbar/chunk-chunk-QPDUWEQB.js
21.9 KiB dist/toolbar/chunk-chunk-2JRYAEFH.js
6.8 KiB dist/toolbar/chunk-chunk-RVLGRPCH.js

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

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

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

Total: 1012.68 MiB · 🔺 +358.8 KiB (+0.0%)

ℹ️ MCP UI apps size — 35 app(s), 37011.6 KB JS

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

App JS CSS
debug 1067.3 KB 225.1 KB
explain-chart 1351.3 KB 225.1 KB
action 994.5 KB 225.1 KB
action-list 1058.3 KB 225.1 KB
cohort 993.5 KB 225.1 KB
cohort-list 1057.3 KB 225.1 KB
email-template 993.4 KB 225.1 KB
error-details 998.4 KB 225.1 KB
error-issue 995.5 KB 225.1 KB
error-issue-list 1059.5 KB 225.1 KB
experiment 1055.4 KB 225.1 KB
experiment-list 1059.1 KB 225.1 KB
experiment-results 1057.4 KB 225.1 KB
feature-flag 1057.7 KB 225.1 KB
feature-flag-list 1061.4 KB 225.1 KB
feature-flag-testing 996.8 KB 225.1 KB
inline-scan 994.0 KB 225.1 KB
insight-actors 1056.8 KB 225.1 KB
llm-costs 1054.0 KB 225.1 KB
session-recording 995.8 KB 225.1 KB
survey 995.1 KB 225.1 KB
survey-global-stats 1054.1 KB 225.1 KB
survey-list 1059.0 KB 225.1 KB
survey-stats 1054.1 KB 225.1 KB
trace-span 993.9 KB 225.1 KB
trace-span-list 1058.2 KB 225.1 KB
vision-observation-list 1057.4 KB 225.1 KB
workflow 993.9 KB 225.1 KB
workflow-list 1057.6 KB 225.1 KB
workflow-setup-status 993.6 KB 225.1 KB
query-results 1320.7 KB 225.1 KB
render-ui 1427.2 KB 225.1 KB
visual-review-snapshots 998.4 KB 225.1 KB
workflow-data-suggestions 996.2 KB 225.1 KB
workflow-sending-rules 994.9 KB 225.1 KB
⚠️ Playwright — 1 flaky

🎭 Playwright report · View test results →

⚠️ 1 flaky test:

  • Delete a person property (chromium)

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

✅ Backend coverage — all changed backend lines covered

🧪 Backend test coverage

Patch coverage — changed backend lines (products + core): ████████████████████ 100.0% (1 / 1)

All changed backend lines are covered ✅

Per-product line coverage (touched products)
Product Coverage Lines
product_analytics ███████████████████░ 95.8% 31,522 / 32,913

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

✅ Django migration risk — no migrations to analyze

No Django migrations need risk analysis.

❌ Hogbox preview — build failed

The preview didn't come up for commit a83b55e. See the build log for the failing step. It'll retry on the next push.

Previews are optional and never block merging. A failure here is often a hogland or tailnet hiccup rather than anything in your PR, so the check stays green and this section is the status.

- Status and provisioning requests use the selected environment, not its project.
- A new email step falls back to the sandbox sender only when the project has no verified sender, not while senders load or when several exist without a default.
- Templates and workflows another product owns no longer offer the sandbox sender.
- A sandbox test sends to the chosen member even when the step names a fixed address, and the picker always shows the address it sends to.
- A mocked sandbox test no longer reads as sent.
- The canvas names a sandbox step Email and previews its content.

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

Silthus commented Nov 9, 2026

Copy link
Copy Markdown
Contributor Author

@PostHog review

@posthog

posthog Bot commented Nov 9, 2026

Copy link
Copy Markdown
Contributor

@Silthus PostHog Review is reviewing this pull request.

@posthog posthog Bot 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.

PostHog Review · Standard · reviewed 5b6e6eb: 1 Must fix, 2 Should fix.

See this review and its findings in PostHog Review. Comment @posthog review --deep for a Deep review. A Deep review takes longer and looks deeper than a Standard review.

Silthus and others added 4 commits November 9, 2026 16:01
Cover status, provisioning and first-run setup in an environment whose
id differs from its project, and the test recipient select replacing a
value that is not a verified member.

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

The generated hogFlowsInvocationsCreate returns void, and the test panel
needs the invocation result, as broadcastTestSendLogic already notes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The test submit grew past the complexity limit with the sandbox
recipient override and the sandbox test event. Both now live beside the
other sandbox step helpers, and the recipient override leaves the
workflow untouched unless the tested step is a sandbox step.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The sandbox test event read the selected step after the request
finished, so selecting another step mid-test dropped it. The submit now
keeps the tested step from before the request.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The API saves a sandbox draft without a To, so the canvas preview and
the step form now read the recipient as optional instead of failing to
load the workflow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	products/workflows/backend/facade/api.py
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Base automatically changed from workflows-sandbox/p2-validate-provision to master November 11, 2026 17:27
@trunk-io

trunk-io Bot commented Nov 11, 2026 •

Copy link
Copy Markdown

😎 This pull request was merged.

Silthus and others added 3 commits November 11, 2026 17:52
…ions

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…itor-sender-choice

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ategories on sandbox steps

The first-run sender check read only the first page of integrations, so a
project whose verified sender sat past it got its template email steps
switched to the sandbox sender. It now pages through the email senders.

An API save may store a sandbox email step with null message categories,
which the backend accepts. The editor schema now accepts null for both, so
the step no longer shows as invalid and blocks enabling.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Silthus and others added 2 commits November 11, 2026 19:57
…tegories

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

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Silthus and others added 2 commits November 11, 2026 20:18
…test result

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings in #133989, which stops the starter dashboard logging an update on creation; the organization and team-deletion activity-logging tests fail without it.

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

@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 yet — waiting on the conditions below.

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

stamphog declined to auto-review this pull request because it failed the size gate. It has 2061 substantive lines changed (2062 across 40 files, or 3466 across 57 once docs, generated files and snapshots are counted), and the ceiling is 1200. The other gates passed, so size alone is what blocked it.

The author can ask a human reviewer to take it, which the description already suggests by pairing it with #131834. Alternatively, the work could be split into smaller pull requests. One natural split is the sandbox sender picker and email step variants, with the test panel, Channels page row and workflow metrics changes in separate ones, each under the ceiling.

  • 1 of the 57 changed files are governed by products/desktop/AGENT_APPROVALS.md.
Gate mechanics and policy version
Gate Result
prerequisites ✓ all clear
deny-list ✓ no deny categories matched
size ✗ too large for auto-review (2061L substantive in global — ceiling is 1200L; 2062L, 40F total, 3466L/57F incl. docs/generated/snapshots)
tier ✓ T1-agent / T1d-complex (3466L, 57F, cross-cutting, feat)
stamphog 2.8.0 .stamphog/policy.yml @ unknown · reviewed head 7c8815b

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Silthus
Silthus added this pull request to stack #134737 November 12, 2026 15:43
@trunk-io
trunk-io Bot merged commit 0e3d847 into master Nov 12, 2026
324 checks passed
@trunk-io
trunk-io Bot deleted the workflows-sandbox/u1-editor-sender-choice branch November 12, 2026 16:49
@trunk-io

trunk-io Bot commented Nov 12, 2026

Copy link
Copy Markdown

This pull request was merged into master as part of stacked PR 132585.

@deployment-status-posthog

deployment-status-posthog Bot commented Nov 12, 2026 •

Copy link
Copy Markdown

Deploy status

Environment Status Deployed At Workflow
dev ✅ Deployed 2026-11-12 17:58 UTC Run
prod-us ✅ Deployed 2026-11-12 18:21 UTC Run
prod-eu ✅ Deployed 2026-11-12 18:24 UTC Run

This table shows the posthog release only. Hogstation shows every service that this PR reaches, Kargo services included.

This branch had an error being deployed

1 failed deployment
hogbox-preview — a83b55e4 Deployed Nov 12, 2026 by github-actions[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

hogbox-preview Spin up a per-PR PostHog preview on a hogland hogbox run-ci-backend Force ci-backend's full test matrices to run even on a draft PR run-ci-frontend Force ci-storybook's full visual-regression matrix to run even on a draft PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants