Repository navigation
Conversation
🤖 CI report✅ Complexity (TypeScript) — cleanCyclomatic 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. ✅ Bundle size — no changeUncompressed size of every built Total: 75.13 MiB · no change No file changed by more than 1000 B. Posted automatically by build-bundle-size-report · uncompressed bytes from dist-report ✅ Eager graph — within budgetHow 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
🟢 Largest files eagerly shipped from
|
| 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.7 KiB | src/index.tsx |
| 1.7 KiB | ../node_modules/.pnpm/base64-js@1.5.1/node_modules/base64-js/index.js |
| 1.7 KiB | src/lib/utils/bootTiming.ts |
| 1.2 KiB | src/RootErrorBoundary.tsx |
| 949 B | src/scenes/ChunkLoadErrorBoundary.tsx |
Largest files eagerly shipped from src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
| Size | File |
|---|---|
| 325.0 KiB | ../node_modules/.pnpm/posthog-js@1.443.0_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 217.5 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 |
| 102.9 KiB | src/products.tsx |
| 86.6 KiB | src/lib/api.ts |
| 67.9 KiB | src/lib/lemon-ui/icons/icons.tsx |
| 41.9 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 |
| 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 |
| 27.0 KiB | ../node_modules/.pnpm/tailwind-merge@2.2.2/node_modules/tailwind-merge/dist/bundle-mjs.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 |
|---|---|
| 325.0 KiB | ../node_modules/.pnpm/posthog-js@1.443.0_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 286.4 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 239.9 KiB | ../packages/quill/packages/quill/dist/index.js |
| 217.5 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 |
| 153.8 KiB | ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js |
| 126.8 KiB | ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js |
| 102.9 KiB | src/products.tsx |
| 94.5 KiB | ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js |
| 92.5 KiB | ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js |
| 86.6 KiB | src/lib/api.ts |
Largest files eagerly shipped from src/scenes/dashboard/Dashboard.tsx
| Size | File |
|---|---|
| 325.0 KiB | ../node_modules/.pnpm/posthog-js@1.443.0_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 286.4 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 239.9 KiB | ../packages/quill/packages/quill/dist/index.js |
| 217.5 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 |
| 153.8 KiB | ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js |
| 144.1 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 |
| 102.9 KiB | src/products.tsx |
| 94.5 KiB | ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js |
| 92.5 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 |
|---|---|
| 325.0 KiB | ../node_modules/.pnpm/posthog-js@1.443.0_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 286.4 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 239.9 KiB | ../packages/quill/packages/quill/dist/index.js |
| 217.5 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 |
| 153.8 KiB | ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js |
| 126.8 KiB | ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js |
| 102.9 KiB | src/products.tsx |
| 94.5 KiB | ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js |
| 92.5 KiB | ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js |
| 86.6 KiB | src/lib/api.ts |
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 |
|---|---|
| 325.0 KiB | ../node_modules/.pnpm/posthog-js@1.443.0_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 286.4 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 239.9 KiB | ../packages/quill/packages/quill/dist/index.js |
| 217.5 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 |
| 153.8 KiB | ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js |
| 144.1 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 |
| 102.9 KiB | src/products.tsx |
| 94.5 KiB | ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js |
| 92.5 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 |
|---|---|
| 325.0 KiB | ../node_modules/.pnpm/posthog-js@1.443.0_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 286.4 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 239.9 KiB | ../packages/quill/packages/quill/dist/index.js |
| 217.5 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 |
| 153.8 KiB | ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js |
| 144.1 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 |
| 102.9 KiB | src/products.tsx |
| 94.5 KiB | ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js |
| 92.5 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 |
|---|---|
| 325.0 KiB | ../node_modules/.pnpm/posthog-js@1.443.0_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 286.4 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 239.9 KiB | ../packages/quill/packages/quill/dist/index.js |
| 217.5 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 |
| 187.9 KiB | src/queries/validators.js |
| 153.8 KiB | ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js |
| 144.1 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 |
| 102.9 KiB | src/products.tsx |
| 94.5 KiB | ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js |
Largest files eagerly shipped from src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
| Size | File |
|---|---|
| 325.0 KiB | ../node_modules/.pnpm/posthog-js@1.443.0_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 316.5 KiB | ../node_modules/.pnpm/posthog-js@1.443.0_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/rrweb.js |
| 286.4 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 239.9 KiB | ../packages/quill/packages/quill/dist/index.js |
| 217.5 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 |
| 153.8 KiB | ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js |
| 126.8 KiB | ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js |
| 102.9 KiB | src/products.tsx |
| 94.5 KiB | ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js |
| 92.5 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.33 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.33 MiB · 19 files | no change | ████░░░░░░ 40.8% of 5.72 MiB |
| Deferred (lazy) | 2.11 MiB · 42 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 |
|---|---|
| 941.7 KiB | dist/toolbar/toolbar-app-UY2NCWYC.css |
| 695.8 KiB | dist/toolbar/chunk-chunk-OU5JIGRB.js |
| 261.2 KiB | dist/toolbar/chunk-chunk-T5DKNJQU.js |
| 131.8 KiB | dist/toolbar/chunk-chunk-FDH2IBXT.js |
| 130.4 KiB | dist/toolbar/chunk-chunk-H2B6C5E4.js |
| 75.7 KiB | dist/toolbar/toolbar-app-SI4MRMOT.js |
| 69.0 KiB | dist/toolbar/chunk-chunk-TSAL54PB.js |
| 33.8 KiB | dist/toolbar/chunk-chunk-FR2SFTP5.js |
| 21.7 KiB | dist/toolbar/chunk-chunk-SFGY4JKG.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 — 🔺 +399 B (+0.0%)
Total size of the built frontend/dist folder (all assets), compared against the base branch.
Total: 966.34 MiB · 🔺 +399 B (+0.0%)
ℹ️ MCP UI apps size — 35 app(s), 29120.8 KB JS
Built size of each MCP UI app (main.js + styles.css).
| App | JS | CSS |
|---|---|---|
| debug | 844.3 KB | 211.6 KB |
| explain-chart | 1117.7 KB | 211.6 KB |
| action | 767.7 KB | 211.6 KB |
| action-list | 835.3 KB | 211.6 KB |
| cohort | 766.7 KB | 211.6 KB |
| cohort-list | 834.3 KB | 211.6 KB |
| email-template | 766.6 KB | 211.6 KB |
| error-details | 771.6 KB | 211.6 KB |
| error-issue | 768.9 KB | 211.6 KB |
| error-issue-list | 836.8 KB | 211.6 KB |
| experiment | 832.4 KB | 211.6 KB |
| experiment-list | 836.1 KB | 211.6 KB |
| experiment-results | 834.3 KB | 211.6 KB |
| feature-flag | 834.7 KB | 211.6 KB |
| feature-flag-list | 838.4 KB | 211.6 KB |
| feature-flag-testing | 770.0 KB | 211.6 KB |
| inline-scan | 767.2 KB | 211.6 KB |
| insight-actors | 833.8 KB | 211.6 KB |
| llm-costs | 831.1 KB | 211.6 KB |
| session-recording | 769.0 KB | 211.6 KB |
| survey | 768.3 KB | 211.6 KB |
| survey-global-stats | 831.1 KB | 211.6 KB |
| survey-list | 836.0 KB | 211.6 KB |
| survey-stats | 831.1 KB | 211.6 KB |
| trace-span | 767.1 KB | 211.6 KB |
| trace-span-list | 835.2 KB | 211.6 KB |
| vision-observation-list | 834.4 KB | 211.6 KB |
| workflow | 767.1 KB | 211.6 KB |
| workflow-list | 834.7 KB | 211.6 KB |
| workflow-setup-status | 766.7 KB | 211.6 KB |
| query-results | 1089.6 KB | 211.6 KB |
| render-ui | 1193.5 KB | 211.6 KB |
| visual-review-snapshots | 771.6 KB | 211.6 KB |
| workflow-data-suggestions | 769.4 KB | 211.6 KB |
| workflow-sending-rules | 768.1 KB | 211.6 KB |
ℹ️ MCP agent API — agent-facing tool changes
What this PR changes for agents, from the tool schema snapshots and tool definitions.
Tools changed (3):
| Tool | Params | Scopes | Annotations | Schema chars |
|---|---|---|---|---|
workflows-patch-email-template |
description changed | |||
workflows-update-email-template |
+key |
description changed | 4,433 -> 4,903 | |
workflows-upload-email-template |
+if_code_managed |
2,009 -> 2,420 |
… code A template managed by code now refuses edits in PostHog with `403 immutable` until someone releases it with `managed_by: gui`, which captures a `message template released` usage event. A template made in PostHog moves into code when someone gives it a `key`: the next upload under that key keeps its id, workflow and sender, and takes over the code sends under the key from then on. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
4512563 to
e8fff1d
Compare
… template Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e-lock-adopt # Conflicts: # products/messaging/backend/tests/api/test_template_upload.py
…a key change Adopting a key now needs editor access to the workflow that already sends under it, so a later upload can't move those sends to a template the member controls. A new key on a code-managed template now answers key_already_set instead of the lock's refusal, whose fix would not have helped. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e-lock-adopt Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… in posthog An upload that sets if_code_managed now answers 409 template_edited_in_posthog when its key names a template that code does not manage, and changes nothing. The check runs first, before if_not_superseded, because the SDK sends both flags and a superseded answer would hide that people edit the template in PostHog. An upload without the flag still takes the template over. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Moved to PostHog#127172. |
Part of the code-first rebuild of the email send stack; the third of three PRs split out of #573 (schema, upload, lock and adopt).
Problem
Changes
403 immutable, until someone releases it withmanaged_by: gui. A release captures amessage template releasedusage event.key. The next upload under that key keeps its id, workflow and sender, and takes over the code sends under the key.403.400 key_already_set, before the lock check.if_code_managed: true, as both SDKs send, refuses a template edited in PostHog with409 template_edited_in_posthogand changes nothing. Thefixsays to upload without the flag to manage it in code again. A new key, or a template managed by code, uploads as before.if_not_superseded. A template edited in PostHog keeps the code's old content on its superseded list, so the other order answerssupersededand the SDK sends the PostHog edit.403and the edit stays unsaved.How did you test this code?
Test rationale:
test_code_managed_template_lock.py: a PostHog edit that overwrites a code-managed template, and a release that does not unlock it.test_template_adoption.py: an upload that makes a new template instead of adopting the keyed one, and code sends that move before an upload claims the key.test_template_upload.py: an upload that adopts a template under a key whose workflow the member can't edit, and goes through. It takes the key's code sends. Without the adoption check this row fails.test_an_upload_if_code_managed_refuses_a_template_edited_in_posthog: an SDK upload that adopts a template made or edited in PostHog, or answerssupersededfor it. The new-key and code-managed rows guard the uploads that must still go through.test_refuses_a_key_whose_code_send_workflow_the_member_cannot_edit: a member who takes over code sends they cannot edit by giving a template their key.test_a_new_key_for_a_code_managed_template_is_refused_as_a_key_change: a key change answered as a lock refusal, which points the member at the wrong fix.Proofs (saved with
fleet proof); the live run and shadow diff ran onc9db420and still hold, becauseif_code_manageddefaults to off:f9abed0, maildev as the sink. 21 requests through the public API. An edit in PostHog of an uploaded or adopted template answers403 immutablewithwhyandfix, and the next send keeps the uploaded content.5304e8d, which contains this fix: posthog-node (feat(node): upload local email templates by hash on send posthog-js#7) and posthog-python (feat: send email content from code with posthog.emails.send posthog-python#2) upload a new key and send it. Onto a template edited in PostHog, both get409 template_edited_in_posthog, send nothing, and leave the template as it was.43333f8. Beyond feat(messaging): upload email templates from code by key #573's differences, only the403 immutableanswers and the send after them differ, as the goal names.Release status
Docs update
🤖 Agent context
Autonomy: Human-driven (agent-assisted)
Agent: Claude Code, Claude Opus 5.5 (claude-opus-5-5)
Skills:
/qa-swarm,/improving-drf-endpoints,/implementing-mcp-tools,/writing-tests,/stacking-prs,/pr-description,/writing-pr-descriptionsif_code_managed?409 template_edited_in_posthog. Replaces ignoring the fieldif_not_superseded, so an edited template is never answeredsupersededFollow-ups: the
TemplateWriteIntentaction strings as a type, and one shared wording for the adopt and upload403.Involvement: one brief from Michael; QA swarm on 2026-11-01 with two panel rounds (GPT-6.1 Sol review, Opus 5.5 fresh eyes): 3 findings fixed, 4 rejected; a GPT-6.1 Sol fix round (correctness and systems) on
d090f43found nothing; live, SDK and shadow-diff proof captured.🤖 Generated with Claude Code