Skip to content

feat(workflows): offer a switch from the sandbox sender - #456

Closed
Silthus wants to merge 1 commit into
workflows-sandbox/first-run-senderfrom
workflows-sandbox/switch-banner
Closed

Silthus wants to merge 1 commit into
workflows-sandbox/first-run-senderfrom
workflows-sandbox/switch-banner

Conversation

@Silthus

@Silthus Silthus commented Oct 12, 2026 •

Copy link
Copy Markdown
Owner

Problem

Workflow authors need a clear way to replace the sandbox sender after verifying their own sender.

Supersedes PostHog#112032 (left open as the original draft).

Stack: layer 12 of 12, stacked on #455. Top of the stack.

This fork PR moves to an upstream PostHog/posthog PR after review.

Warning

🟡 Merge risk: medium · two-way door (merge-risk rubric)

  • Switching changes the sender for sandbox email steps in the edited workflow.
  • Only verified own senders appear, and normal workflow saving and publishing still apply.

Changes

  • Workflows using the sandbox sender offer a banner to switch their email steps to a verified own sender.
  • A single sender has a direct button. Multiple senders have a picker.
  • The banner sizes to its content in constrained scenes, including a 520px scene with the editor panel open.
  • The switch preserves email content and leaves steps using other senders alone.
  • Switching pauses while the workflow syncs. Active workflows receive a reminder to publish the sender change.
  • Viewers cannot switch senders.
  • The banner logic reports the banner shown event through a subscription on its own visibility and no longer connects workflowLogic's load action. This removes about 1,860 lines of inline kea typegen, and the file drops to 236 lines. The ask was a separate generated type file. The repo sets inline: true in .kearc and ignores *Type.ts files, so this PR removes the cause instead.

UI walk at 8ac8853cc82. Captures from a local preview of the stack tip 8ac8853cc82, flag workflows-sandbox-sender on, demo data. This walk covers the banner after the round 4 change to how the logic reports it.

Switch banner at 1280px with two verified own senders

At 1280px with two verified own senders: the banner sits above the tabs and offers Switch sender.

Narrow: banner wraps and Switch sender stacks below the text

Narrow (side panel open, banner about 515px wide): the text wraps and Switch sender stacks below it. Nothing clips. Opening the side panel does not report the banner again.

No banner without a verified own sender

Without a verified own sender, the workflow on the sandbox sender shows no banner.

After switching: saved, no banner

After picking an own sender and the autosave: no banner, and the email step now uses the own sender.

The walk counted workflows sandbox switch banner shown per mount, both as captured by posthog-js and as sent on the network:

Mount Captured Sent
No verified own sender (no banner) 0 0
First load with the banner 1 1
After a page reload 1 1
A separate load for the narrow render 1 1

UI walk at fa33d78fb36. Captures from a local preview of the stack tip fa33d78fb36, flag workflows-sandbox-sender, demo data. Flag off is the before. Real SES is unreachable in this preview, so sends stop at the SES call, shown as ECONNREFUSED.

Before: no banner on a sandbox workflow

Before (flag off): a workflow whose step still uses the sandbox sender shows no banner, even with a verified own sender.

After: switch banner with one verified sender

After (flag on): the banner says the workflow still sends from the sandbox sender and offers Switch to hello@own-sender.example.com.

After: switch menu with two verified senders

With two verified own senders, Switch sender opens a menu.

Narrow: banner wraps with the side panel open

Narrow (side panel open, about 547px of scene): the text wraps and the button stacks below it.

After switch: toast and no banner

After Switch: a toast confirms the update, the banner is gone, and the workflow autosaves.

Earlier captures. Each caption names the commit it was taken at.

Switch banner with its full text and a sender menu

A workflow that still uses the sandbox sender shows the switch banner with its full text. The project has two verified senders here, so Switch sender opens a menu. Taken at 77ecdc99d50 in the combined live preview of both stacks.

Workflow after switching to the project's own sender

After Switch, the banner is gone and the workflow autosaves with the project's sender. Taken at 3d5024de1c3 in the combined live preview of both stacks.

How did you test this code?

Current evidence, 2026-10-24, head 8ac8853cc82.

Owed proofs:

  • Live run: rerun at this layer's head, the stack tip 8ac8853cc82. The stack's cdp-api sent through the workflow test-run endpoint to a local SES fake that records each request. 9 of 9 cases pass. 12 of 13 recorded cases match the run at fa33d78fb36. Case 2c (an unverified member on To) now shows the verify-your-email guidance with reason recipient_unverified, and makes no SES request. Case 1 covers delivery from a step on the sandbox sender. The UI walk shows the banner and the switch.
  • UI walk: local preview of the stack tip 8ac8853cc82, flag workflows-sandbox-sender on, demo data. Round 4 walked only the surfaces it changed: the banner, its switch action, and the banner shown event per mount. The captures and the event counts sit in Changes, above the fa33d78fb36 captures.

Changes in this layer since the 2026-10-19 heads (restacked onto fork master 448d802: no conflict in this layer):

  • Round 1: no change in this layer.
  • No change in this layer since round 2.
  • Final read: GPT-6.1 Sol read the G5 layer range-diffs and found nothing.
  • Round 4 fixed (typegen): the roughly 1,860 lines of inline kea typegen are gone from workflowSandboxSwitchBannerLogic.ts, which drops from 1,992 to 236 lines. The logic no longer connects workflowLogic's loadWorkflowSuccess, whose payload type expanded inline, and reports the banner shown event through a kea-subscriptions subscription on bannerVisible (the 15 banner logic tests pass unchanged, and the UI walk counts the event per mount).
  • Final read 2: GPT-6.1 Sol read the round 4 range-diffs per group and found nothing.
Local gate at the stack tip 8ac8853cc82, shared by every layer

Test seams: real workflow edits, sender eligibility, editor permissions, and browser layout with the actual banner markup and built CSS.

Test rationale: Existing cases protect switching and permissions. Constrained wide/narrow stories protect sizing; the browser render reproduced clipping before the fix.

Gaps: real AWS SES delivery and the AWS-side tenant pause (every proof uses a local SES fake or an unreachable SES), clustered Valkey, the production data shape (prod-shape gap until production read access on 2026-11-02), and fork CI, which fails during setup: path selection fails without a GitHub App client ID, and the Security aggregate rejects its fork-skipped path-filter job. Application CI is a verification gap. The UI walk could not create an own sender through the UI, because SES was unreachable; it seeded own senders in the database instead.

Earlier evidence (superseded heads)

Round 3 heads, 2026-10-23. This layer's head: fa33d78fb36. Stack tip fa33d78fb36.

Whole-stack QA swarm, 2026-10-19. Reviewed tip cfee7e148ae. This layer's head: cfee7e148ae.

  • Live run at b9bd346ed0e (this stack's cdp-api against a local SES fake, workflow test-run endpoint): a sandbox send to a verified member went out from the fixed identity through the sandbox tenant and configuration set. The step's From name, From address and Reply-To were ignored with a log line. A non-member on CC and an unverified member were blocked with the clear message. A paused tenant state skipped sandbox sends while own-sender sends continued.
  • Shadow diff: an own-sender send produced the same SES request and the same stored message on master and on this stack.
  • Cross-version: a worker on master reports a sandbox send as sent without calling SES. See the deploy order in feat(workflows): provision a managed sandbox email sender #426's merge risk.
  • Checks at the tip (Node suites at 1a0fe3663c2; later fixes touch no Node code): Node CDP messaging, members and rate limiter suites (including email-tracking.service.test.ts, which now runs), the cdp-api suite, the Python sandbox, tenant, tier, reputation and validation suites, the frontend Jest suites of this stack, ruff, and the strict pre-push preflight: pass.
  • Gaps: real AWS SES delivery, clustered Valkey, and the production data shape (no production read access yet). Fork CI still fails during setup.

Rebased onto master 734468db6f9 (2026-10-19), head b9bd346ed0e.

  • Drift: Master added the AI email draft status to WorkflowScene and gates the suggestions notice on suggestionsAvailable.
  • Adapted: The switch banner sits after master's AI draft status. Master's suggestions gate is kept.
  • This layer: Jest for workflowSandboxSwitchBannerLogic passes at the tip (below).
  • Gaps at modernize time: email-tracking.service.test.ts did not run then. It runs now; see the QA swarm block above. Fork CI still fails during setup, as noted below. Real AWS delivery and clustered Valkey remain unchecked.
Checks at the stack tip

Stack tip b9bd346ed0e (#456), shared by every layer:

  • Python, 354 passed: sandbox sender, sender validation, CDP validation, reputation, SES tenant state and events, sending tier.
  • Node CDP messaging, managers, and rate limiter: 17 suites, 599 passed.
  • Frontend Jest, 37 suites, 487 passed. Five suites timed out under host load in the batch run and passed when rerun alone.
  • Frontend tsgo: no errors. Node tsgo: no errors in CDP. The 23 errors it reports are all in session replay files that need the unbuilt Rust @posthog/replay-anonymizer module.
  • ruff, oxfmt, oxlint, prettier, eslint, product:lint (workflows, cdp), IDOR coverage, hogli build:openapi (no diff), and the strict pre-push preflight: pass.
  • Review: GPT-6.1 Sol read every conflict resolution in the stack and found no issues.
Observed constrained banner sizing
1280px viewport, 1017px scene:
  Before: banner 48px, content 44px plus 18px padding/border; flex-shrink 1; clipped true
  After: banner 62px; flex-shrink 0; clipped false; horizontal overflow false
1280px viewport, 520px scene:
  Before: banner 48px, content 107px plus 18px padding/border; clipped true
  After: banner 125px; clipped false; horizontal overflow false

The scoped render uses the actual React component and LemonUI DOM with fixture state and matching built CSS. Live preview media refresh remains pending.

Observed targeted verification after QA fixes
workflowSandboxSwitchBannerLogic.test.ts: 15 passed
Frontend typecheck: No errors reported by tsgo.
ci:preflight --strict --against workflows-sandbox/first-run-sender: failures 0
Observed gates (Node and mypy results reused from the preceding QA pass)
Node.js typecheck and build: exit 0
Frontend typecheck and build: exit 0
Success: no issues found in 23388 source files
product:lint workflows: All checks passed
ci:preflight --strict: 121 changed files, failures 0

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

Release status

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

Docs update

No existing document covers the sender-switch interaction. The policy is described in Changes above; the sending-tiers document keeps its delivery scope.

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

Decisions

Question Answer Who Where
Inline kea typegen in the switch banner logic Take the roughly 1,860 lines of inline typegen out of the logic file 👤 Human decision comment
How the typegen bloat leaves The logic no longer connects workflowLogic's loadWorkflowSuccess, whose payload type produced the bloat, and reports the banner through a subscription on bannerVisible. The file drops to 236 lines. Alternative: a separate generated type file, which breaks the repo's inline typegen setting (.kearc inline: true) 🤖 Agent decision comment
Named return type for loadWorkflow (G5-5) Follow-up, because it changes master's loader. This PR no longer connects the loader 🤖 Agent decision comment

Involvement: restack onto fork master 448d802 on 2026-10-23; round 1 with GPT-6.1 Sol lanes plus Claude Opus 5.5 fresh eyes for group G5; round 2 on the fix diff; final read 1 by GPT-6.1 Sol per group, with no findings; proofs captured; final read 2 by GPT-6.1 Sol on the round 4 decisions, with no findings; the round 4 live run and a UI walk of the two changed surfaces. Before that: the 2026-10-19 whole-stack QA swarm and the modernize rebase (see Earlier evidence). No review bots run on the fork.

Agent: Codex with GPT-6.1 Sol (gpt-6.1-sol) built the original layers, orchestrated by Claude Code with Claude Opus 5.5 (claude-opus-5-5). Restack, review fixes and this description refresh: Claude Opus 5.5 (claude-opus-5-5). Review: GPT-6.1 Sol (gpt-6.1-sol). Fresh eyes: Claude Opus 5.5 (claude-opus-5-5).

Skills: tdd, pr, writing-pr-descriptions, stacking-prs, merge-risk, qa-swarm, writing-kea-logics, writing-ui-components, running-ci-preflight, writing-voice, writing-user-facing-copy, and writing-tests. The description refresh used pr-description, writing-pr-descriptions, writing-voice and merge-risk.

The banner uses LemonUI and container-based layout. Public source and invented fixtures only.

🤖 Generated with Claude Code

@Silthus
Silthus added this pull request to stack #429 October 12, 2026 18:18
@Silthus Silthus self-assigned this Oct 12, 2026
@Silthus
Silthus force-pushed the workflows-sandbox/switch-banner branch from 3d5024d to c06934b Compare October 12, 2026 23:16
@Silthus
Silthus force-pushed the workflows-sandbox/switch-banner branch from c06934b to 901417d Compare October 12, 2026 23:54
@Silthus
Silthus force-pushed the workflows-sandbox/switch-banner branch from 901417d to 77ecdc9 Compare October 13, 2026 04:02
@Silthus
Silthus force-pushed the workflows-sandbox/switch-banner branch from 77ecdc9 to b9bd346 Compare October 19, 2026 10:58
@Silthus
Silthus force-pushed the workflows-sandbox/switch-banner branch 2 times, most recently from 1a0fe36 to cfee7e1 Compare October 19, 2026 13:36
@Silthus
Silthus force-pushed the workflows-sandbox/switch-banner branch from cfee7e1 to fa33d78 Compare October 23, 2026 16:26
@github-actions

github-actions Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

🤖 CI report

⚠️ Complexity (TypeScript) — 1 function above the limit (max 33)

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
WorkflowScene products/workflows/frontend/Workflows/WorkflowScene.tsx:69 33 10
⚠️ Bundle size — 🔺 +5.6 KiB (+0.0%)

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

Total: 76.03 MiB · 🔺 +5.6 KiB (+0.0%)

File Size Δ vs base
posthog-app/_parent/products/workflows/frontend/Workflows/WorkflowScene.js 120.7 KiB 🔺 +3.4 KiB (+2.9%)

Posted automatically by build-bundle-size-report · uncompressed bytes from dist-report

⚠️ Eager graph — 2 over 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.01 MiB · 24 files 🔺 +92 B (+0.0%) █████████░ 88.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.94 MiB · 620 files 🔺 +211 B (+0.0%) ██████████ 96.9% of 3.03 MiB
🟡 authenticated shell (every logged-in page)
src/scenes/AuthenticatedShell.tsx
7.65 MiB · 2,633 files 🟢 -445 B (-0.0%) ██████████ 102.1% of 7.50 MiB
dashboard scene
src/scenes/dashboard/Dashboard.tsx
9.68 MiB · 3,703 files 🟢 -1.0 KiB (-0.0%) ██████████ 96.7% of 10.01 MiB
🟡 today home path
src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
8.06 MiB · 2,977 files 🟢 -445 B (-0.0%) ██████████ 104.2% of 7.74 MiB
AI-first home path
src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx
7.90 MiB · 2,706 files 🟢 -445 B (-0.0%) █████████░ 88.2% of 8.96 MiB
events scene
src/scenes/activity/explore/EventsScene.tsx
9.15 MiB · 3,495 files 🟢 -408 B (-0.0%) ██████████ 95.4% of 9.59 MiB
web analytics scene
src/scenes/web-analytics/WebAnalyticsScene.tsx
10.01 MiB · 3,713 files 🟢 -408 B (-0.0%) █████████░ 92.4% of 10.83 MiB
replay detail scene
src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
8.23 MiB · 3,075 files 🟢 -340 B (-0.0%) █████████░ 86.9% of 9.47 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/zod/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/scenes/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/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
🟢 products/wizard/frontend/runs/WizardRunDetailsDrawer.tsx 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/queries/validators.js 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
🟢 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
🟢 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/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/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

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.4 KiB src/index.tsx
1.3 KiB src/RootErrorBoundary.tsx
1.3 KiB src/lib/utils/bootTiming.ts
912 B ../node_modules/.pnpm/ieee754@1.2.1/node_modules/ieee754/index.js
Largest files eagerly shipped from src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
Size File
321.9 KiB ../node_modules/.pnpm/posthog-js@1.438.18_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
220.9 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
106.3 KiB src/products.tsx
98.9 KiB src/lib/api.ts
69.4 KiB src/lib/lemon-ui/icons/icons.tsx
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.4 KiB src/scenes/scenes.ts
27.0 KiB src/lib/constants.tsx
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx
Size File
321.9 KiB ../node_modules/.pnpm/posthog-js@1.438.18_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
286.8 KiB src/taxonomy/core-filter-definitions-by-group.json
238.5 KiB ../packages/quill/packages/quill/dist/index.js
220.9 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
143.2 KiB ../packages/quill/packages/primitives/dist/index.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
106.3 KiB src/products.tsx
98.9 KiB src/lib/api.ts
93.3 KiB ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js
Largest files eagerly shipped from src/scenes/dashboard/Dashboard.tsx
Size File
321.9 KiB ../node_modules/.pnpm/posthog-js@1.438.18_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
286.8 KiB src/taxonomy/core-filter-definitions-by-group.json
238.5 KiB ../packages/quill/packages/quill/dist/index.js
220.9 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
143.2 KiB ../packages/quill/packages/primitives/dist/index.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
106.3 KiB src/products.tsx
98.9 KiB src/lib/api.ts
93.3 KiB ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
Size File
321.9 KiB ../node_modules/.pnpm/posthog-js@1.438.18_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
286.8 KiB src/taxonomy/core-filter-definitions-by-group.json
238.5 KiB ../packages/quill/packages/quill/dist/index.js
220.9 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
143.2 KiB ../packages/quill/packages/primitives/dist/index.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
106.3 KiB src/products.tsx
98.9 KiB src/lib/api.ts
93.3 KiB ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.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
321.9 KiB ../node_modules/.pnpm/posthog-js@1.438.18_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
286.8 KiB src/taxonomy/core-filter-definitions-by-group.json
238.5 KiB ../packages/quill/packages/quill/dist/index.js
220.9 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
143.2 KiB ../packages/quill/packages/primitives/dist/index.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
106.3 KiB src/products.tsx
98.9 KiB src/lib/api.ts
93.3 KiB ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js
Largest files eagerly shipped from src/scenes/activity/explore/EventsScene.tsx
Size File
321.9 KiB ../node_modules/.pnpm/posthog-js@1.438.18_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
286.8 KiB src/taxonomy/core-filter-definitions-by-group.json
238.5 KiB ../packages/quill/packages/quill/dist/index.js
220.9 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
143.2 KiB ../packages/quill/packages/primitives/dist/index.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
106.3 KiB src/products.tsx
98.9 KiB src/lib/api.ts
93.3 KiB ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js
Largest files eagerly shipped from src/scenes/web-analytics/WebAnalyticsScene.tsx
Size File
321.9 KiB ../node_modules/.pnpm/posthog-js@1.438.18_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
286.8 KiB src/taxonomy/core-filter-definitions-by-group.json
238.5 KiB ../packages/quill/packages/quill/dist/index.js
220.9 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
183.2 KiB src/queries/validators.js
153.7 KiB ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js
143.2 KiB ../packages/quill/packages/primitives/dist/index.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
106.3 KiB src/products.tsx
98.9 KiB src/lib/api.ts
Largest files eagerly shipped from src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
Size File
321.9 KiB ../node_modules/.pnpm/posthog-js@1.438.18_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
316.1 KiB ../node_modules/.pnpm/posthog-js@1.438.18_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/rrweb.js
286.8 KiB src/taxonomy/core-filter-definitions-by-group.json
238.5 KiB ../packages/quill/packages/quill/dist/index.js
220.9 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
106.3 KiB src/products.tsx
98.9 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 PostHog#32479

✅ Toolbar bundle — eager 2.29 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.29 MiB · 18 files 🔺 +92 B (+0.0%) ████░░░░░░ 39.9% of 5.72 MiB
Deferred (lazy) 2.11 MiB · 40 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
899.5 KiB dist/toolbar/toolbar-app-FAZMT3U3.css
691.5 KiB dist/toolbar/chunk-chunk-P2Q5W6MF.js
260.7 KiB dist/toolbar/chunk-chunk-HRRIOF34.js
131.8 KiB dist/toolbar/chunk-chunk-FDH2IBXT.js
130.4 KiB dist/toolbar/chunk-chunk-56VOFFKM.js
74.8 KiB dist/toolbar/toolbar-app-Y5KIAIV6.js
69.0 KiB dist/toolbar/chunk-chunk-TSAL54PB.js
35.6 KiB dist/toolbar/chunk-chunk-3KUCHJRN.js
21.7 KiB dist/toolbar/chunk-chunk-PKO5KPTA.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 — 🔺 +48.4 KiB (+0.0%)

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

Total: 1020.94 MiB · 🔺 +48.4 KiB (+0.0%)

@Silthus
Silthus force-pushed the workflows-sandbox/switch-banner branch from fa33d78 to 8ac8853 Compare October 24, 2026 13:11
@Silthus

Silthus commented Oct 24, 2026

Copy link
Copy Markdown
Owner Author

Note

🤖 Claude Opus 5.5 responding on behalf of Michael

Decision lines for this PR. The Decisions table in the description links each row here.

  • 👤 Inline kea typegen in the switch banner logic Take the roughly 1,860 lines of inline typegen out of the logic file.
  • 🤖 How the typegen bloat leaves The logic no longer connects workflowLogic's loadWorkflowSuccess, whose payload type produced the bloat, and reports the banner through a subscription on bannerVisible. The file drops to 236 lines. Alternative: a separate generated type file, which breaks the repo's inline typegen setting (.kearc inline: true).
  • 🤖 Named return type for loadWorkflow (G5-5) Follow-up, because it changes master's loader. This PR no longer connects the loader

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

Silthus commented Oct 27, 2026

Copy link
Copy Markdown
Owner Author

Replaced by the re-sliced fork stack: #625. Tracked in Silthus/personal#71.

@Silthus Silthus closed this Oct 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant