Repository navigation
feat(warehouse-suggestions): suggested models strip and catalog suggested rows - #113447
Conversation
🤖 CI report
|
| Function | Location | Complexity | Limit |
|---|---|---|---|
describerFor |
frontend/src/lib/components/ActivityLog/describers.tsx:56 |
53 | 10 |
CertificationSuggestionRow |
products/warehouse_suggestions/frontend/components/CertificationSuggestionRow.tsx:27 |
14 | 10 |
MaterializeSuggestionModal |
products/warehouse_suggestions/frontend/components/MaterializeSuggestionModal.tsx:25 |
14 | 10 |
changedRefreshOptions |
products/warehouse_suggestions/frontend/warehouseSuggestionsLogic.ts:126 |
12 | 10 |
<anonymous> |
products/warehouse_suggestions/frontend/warehouseSuggestionsLogic.ts:651 |
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) — 1 new duplicated block (worst 138 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/warehouse_suggestions/frontend/components/MaterializeSuggestionRow.tsx:31 |
products/warehouse_suggestions/frontend/components/UnmaterializeSuggestionRow.tsx:36 |
32 | 138 |
⚠️ Bundle size — 🔺 +16.9 KiB (+0.0%)
Uncompressed size of every built .js bundle, compared against the base branch.
Total: 76.17 MiB · 🔺 +16.9 KiB (+0.0%)
| File | Size | Δ vs base |
|---|---|---|
posthog-app/_parent/products/data_modeling/frontend/ModelsScene.js |
83.6 KiB | 🔺 +9.8 KiB (+13.3%) |
posthog-app/_parent/products/data_catalog/frontend/DataCatalogScene.js |
38.6 KiB | 🔺 +5.1 KiB (+15.1%) |
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 |
1017.3 KiB · 24 files | 🔺 +933 B (+0.1%) | █████████░ 86.8% 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.92 MiB · 620 files | 🔺 +1.0 KiB (+0.0%) | ██████████ 96.2% of 3.03 MiB |
authenticated shell (every logged-in page)src/scenes/AuthenticatedShell.tsx |
7.28 MiB · 2,543 files | 🔺 +1.2 KiB (+0.0%) | ██████████ 97.2% of 7.50 MiB |
dashboard scenesrc/scenes/dashboard/Dashboard.tsx |
9.67 MiB · 3,706 files | 🔺 +1.3 KiB (+0.0%) | ██████████ 96.5% of 10.01 MiB |
today home pathsrc/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx |
7.45 MiB · 2,635 files | 🔺 +1.2 KiB (+0.0%) | ██████████ 96.3% of 7.74 MiB |
AI-first home pathsrc/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx |
7.53 MiB · 2,616 files | 🔺 +1.2 KiB (+0.0%) | ████████░░ 84.0% of 8.96 MiB |
events scenesrc/scenes/activity/explore/EventsScene.tsx |
9.14 MiB · 3,497 files | 🔺 +1.2 KiB (+0.0%) | ██████████ 95.3% of 9.59 MiB |
web analytics scenesrc/scenes/web-analytics/WebAnalyticsScene.tsx |
10.00 MiB · 3,715 files | 🔺 +1.2 KiB (+0.0%) | █████████░ 92.3% of 10.83 MiB |
replay detail scenesrc/scenes/session-recordings/detail/SessionRecordingDetail.tsx |
8.21 MiB · 3,077 files | 🔺 +1.2 KiB (+0.0%) | █████████░ 86.7% 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
🟢 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
🟢 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
🟢 packages/quill/packages/charts/ 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/[email protected][email protected]/node_modules/react-dom/cjs/react-dom.production.min.js |
| 24.6 KiB | ../node_modules/.pnpm/[email protected]/node_modules/buffer/index.js |
| 6.3 KiB | ../node_modules/.pnpm/[email protected]/node_modules/react/cjs/react.production.min.js |
| 4.5 KiB | ../node_modules/.pnpm/@[email protected]/node_modules/@jspm/core/nodelibs/browser/process.js |
| 3.9 KiB | ../node_modules/.pnpm/[email protected]/node_modules/scheduler/cjs/scheduler.production.min.js |
| 1.4 KiB | ../node_modules/.pnpm/[email protected]/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/[email protected]/node_modules/ieee754/index.js |
Largest files eagerly shipped from src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
| Size | File |
|---|---|
| 322.5 KiB | ../node_modules/.pnpm/[email protected]_@[email protected][email protected]/node_modules/posthog-js/dist/module.mjs |
| 220.9 KiB | ../node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 126.8 KiB | ../node_modules/.pnpm/[email protected][email protected]/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/@[email protected][email protected][email protected][email protected]/node_modules/@dnd-kit/core/dist/core.esm.js |
| 33.9 KiB | ../node_modules/.pnpm/[email protected]_patch_hash=139b8d1f1304f9d9da452a9a1244c94ea679dbcb85687d8999563146879fb6f5_react@18.3.1/node_modules/kea/lib/index.cjs.js |
| 29.4 KiB | src/scenes/scenes.ts |
| 27.2 KiB | src/lib/constants.tsx |
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx
| Size | File |
|---|---|
| 322.5 KiB | ../node_modules/.pnpm/[email protected]_@[email protected][email protected]/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/@[email protected][email protected][email protected][email protected]/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 153.7 KiB | ../node_modules/.pnpm/[email protected]/node_modules/re2js/build/index.esm.js |
| 126.8 KiB | ../node_modules/.pnpm/[email protected][email protected]/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/[email protected]/node_modules/prosemirror-view/dist/index.js |
| 90.6 KiB | ../node_modules/.pnpm/@[email protected]_@[email protected]/node_modules/@tiptap/core/dist/index.js |
Largest files eagerly shipped from src/scenes/dashboard/Dashboard.tsx
| Size | File |
|---|---|
| 322.5 KiB | ../node_modules/.pnpm/[email protected]_@[email protected][email protected]/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/@[email protected][email protected][email protected][email protected]/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 153.7 KiB | ../node_modules/.pnpm/[email protected]/node_modules/re2js/build/index.esm.js |
| 143.2 KiB | ../packages/quill/packages/primitives/dist/index.js |
| 126.8 KiB | ../node_modules/.pnpm/[email protected][email protected]/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/[email protected]/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 |
|---|---|
| 322.5 KiB | ../node_modules/.pnpm/[email protected]_@[email protected][email protected]/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/@[email protected][email protected][email protected][email protected]/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 153.7 KiB | ../node_modules/.pnpm/[email protected]/node_modules/re2js/build/index.esm.js |
| 126.8 KiB | ../node_modules/.pnpm/[email protected][email protected]/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/[email protected]/node_modules/prosemirror-view/dist/index.js |
| 90.6 KiB | ../node_modules/.pnpm/@[email protected]_@[email protected]/node_modules/@tiptap/core/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 |
|---|---|
| 322.5 KiB | ../node_modules/.pnpm/[email protected]_@[email protected][email protected]/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/@[email protected][email protected][email protected][email protected]/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 153.7 KiB | ../node_modules/.pnpm/[email protected]/node_modules/re2js/build/index.esm.js |
| 126.8 KiB | ../node_modules/.pnpm/[email protected][email protected]/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/[email protected]/node_modules/prosemirror-view/dist/index.js |
| 90.6 KiB | ../node_modules/.pnpm/@[email protected]_@[email protected]/node_modules/@tiptap/core/dist/index.js |
Largest files eagerly shipped from src/scenes/activity/explore/EventsScene.tsx
| Size | File |
|---|---|
| 322.5 KiB | ../node_modules/.pnpm/[email protected]_@[email protected][email protected]/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/@[email protected][email protected][email protected][email protected]/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 153.7 KiB | ../node_modules/.pnpm/[email protected]/node_modules/re2js/build/index.esm.js |
| 143.2 KiB | ../packages/quill/packages/primitives/dist/index.js |
| 126.8 KiB | ../node_modules/.pnpm/[email protected][email protected]/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/[email protected]/node_modules/prosemirror-view/dist/index.js |
Largest files eagerly shipped from src/scenes/web-analytics/WebAnalyticsScene.tsx
| Size | File |
|---|---|
| 322.5 KiB | ../node_modules/.pnpm/[email protected]_@[email protected][email protected]/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/@[email protected][email protected][email protected][email protected]/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 183.2 KiB | src/queries/validators.js |
| 153.7 KiB | ../node_modules/.pnpm/[email protected]/node_modules/re2js/build/index.esm.js |
| 143.2 KiB | ../packages/quill/packages/primitives/dist/index.js |
| 126.8 KiB | ../node_modules/.pnpm/[email protected][email protected]/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 |
|---|---|
| 322.5 KiB | ../node_modules/.pnpm/[email protected]_@[email protected][email protected]/node_modules/posthog-js/dist/module.mjs |
| 316.1 KiB | ../node_modules/.pnpm/[email protected]_@[email protected][email protected]/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/@[email protected][email protected][email protected][email protected]/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 153.7 KiB | ../node_modules/.pnpm/[email protected]/node_modules/re2js/build/index.esm.js |
| 126.8 KiB | ../node_modules/.pnpm/[email protected][email protected]/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/[email protected]/node_modules/prosemirror-view/dist/index.js |
Posted automatically by check-eager-graph · sizes are eager output bytes (shipped, post-tree-shake) from the esbuild metafile · part of #32479
✅ Toolbar bundle — eager 2.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 | 🔺 +979 B (+0.0%) | ████░░░░░░ 40.0% 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 |
|---|---|
| 902.3 KiB | dist/toolbar/toolbar-app-M4RZCOGY.css |
| 692.2 KiB | dist/toolbar/chunk-chunk-72MXZPGR.js |
| 260.7 KiB | dist/toolbar/chunk-chunk-L6XVLVLY.js |
| 131.8 KiB | dist/toolbar/chunk-chunk-FDH2IBXT.js |
| 130.4 KiB | dist/toolbar/chunk-chunk-C5NTA2OX.js |
| 74.8 KiB | dist/toolbar/toolbar-app-3CZKXE2Y.js |
| 69.0 KiB | dist/toolbar/chunk-chunk-TSAL54PB.js |
| 35.6 KiB | dist/toolbar/chunk-chunk-HSGY7DL5.js |
| 21.7 KiB | dist/toolbar/chunk-chunk-VFPSU72W.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 — 🔺 +454.2 KiB (+0.0%)
Total size of the built frontend/dist folder (all assets), compared against the base branch.
Total: 1022.85 MiB · 🔺 +454.2 KiB (+0.0%)
⚠️ Playwright — 1 flaky
🎭 Playwright report · View test results →
- create experiment via wizard, add metrics, and launch (chromium)
These issues are not necessarily caused by your changes.
Annoyed by this section? Help fix flakies and failures and it will go green!
✅ Django migration risk — no migrations to analyze
No Django migrations need risk analysis.
|
[Medium risk] Adds warehouse suggestions UI and feature flag. Fix the missing suggestions, failed-status recovery, dismissal race, and repository-rule violations before merging. Reviews (1) · Last reviewed commit: "chore(frontend): sort the feature flag t..." · Reviewed by Greptile |
|
📝 Walkthrough
Priority: ⬇️ Low Merge Risk: 🔵 Low · up to
|
There was a problem hiding this comment.
Note
Quiet mode is enabled, so only the most important comments were posted inline. Other review comments are grouped below.
🟡 Other comments (3)
products/warehouse_suggestions/frontend/components/MaterializeSuggestionModal.tsx (1)
23-25: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winBlock modal dismissal while the accept request is in flight.
The Cancel button is disabled while
inFlightis true. Esc, an overlay click, and the X button still callcloseMaterializeModal. If the request then fails with a refused schedule,materializeErroris set on a modal that is already closed, and the user never sees it. Passclosable={!inFlight}toLemonModal.products/warehouse_suggestions/frontend/suggestionCopy.ts (1)
42-47: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winHandle the case where both savings are zero.
If
saves_seconds_per_monthis below 60 andsaves_bytes_per_monthis 0,humanizeBytes(0)returns "0 bytes". The card then says "saves about 0 bytes of scanning". Fall back to "under a minute of query time", or hide the saving clause.products/warehouse_suggestions/frontend/warehouseSuggestionsLogic.ts (1)
218-238: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winLoad every proposed suggestion page.
The list endpoint caps each response at 100 items. The loader requests one page and keeps only
results. If an enabled team has more than 100 proposed suggestions, later actionable suggestions do not reachsurfaceSuggestions, so users cannot see or act on them.Suggested fix
- loadSuggestions: async () => - (await warehouseSuggestionsList(projectId(), { status: 'proposed' })).results, + loadSuggestions: async () => { + const suggestions: WarehouseSuggestionApi[] = [] + let offset = 0 + let page + do { + page = await warehouseSuggestionsList(projectId(), { + status: 'proposed', + offset, + }) + suggestions.push(...page.results) + offset += page.results.length + } while (page.results.length > 0 && suggestions.length < page.count) + return suggestions + },
ℹ️ Review info
⚙️ Run configuration
- Configuration used: Repository: PostHog/posthog/.coderabbit.yaml
- Review profile: QUIET
- Plan: Enterprise
- Run ID:
b48924da-4d65-4223-9629-e927e3c7ae37
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (19)
frontend/src/lib/components/ActivityLog/describers.tsxfrontend/src/lib/constants.tsxfrontend/src/types.tsproducts/data_catalog/frontend/tabs/CertificationsTab.tsxproducts/data_modeling/frontend/ViewsTab.tsxproducts/warehouse_suggestions/frontend/components/DismissSuggestionMenu.tsxproducts/warehouse_suggestions/frontend/components/MaterializeSuggestionCard.tsxproducts/warehouse_suggestions/frontend/components/MaterializeSuggestionModal.tsxproducts/warehouse_suggestions/frontend/components/SuggestedCertificationsTable.stories.tsxproducts/warehouse_suggestions/frontend/components/SuggestedCertificationsTable.tsxproducts/warehouse_suggestions/frontend/components/SuggestedModelsStrip.stories.tsxproducts/warehouse_suggestions/frontend/components/SuggestedModelsStrip.tsxproducts/warehouse_suggestions/frontend/components/WhyThisSuggestion.tsxproducts/warehouse_suggestions/frontend/refreshIntervals.tsproducts/warehouse_suggestions/frontend/suggestionCopy.tsproducts/warehouse_suggestions/frontend/warehouseSuggestionActivityDescriber.tsxproducts/warehouse_suggestions/frontend/warehouseSuggestionsLogic.test.tsproducts/warehouse_suggestions/frontend/warehouseSuggestionsLogic.tsproducts/warehouse_suggestions/package.json
Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 9 remain after this review.
a2acd1d to
0814268
Compare
0814268 to
916c49e
Compare
There was a problem hiding this comment.
Note
Quiet mode is enabled, so only the most important comments were posted inline. Other review comments are grouped below.
🟡 Other comments (1)
products/warehouse_suggestions/frontend/suggestionCopy.ts (1)
63-74: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winFix
spokenDurationfor values that are not whole multiples of the units.When
parts.lengthreachesmaxUnits, the loop keeps iterating. This is harmless for output. But a duration with a remainder below one minute, such as 90 seconds, prints "1 minute". The 30 seconds are dropped without any rounding. Example:freshnessSentencewithfreshness_after_secondsof 3659 prints "1 hour" for a value that is 59 seconds over. This understates the age of the data by up to 59 seconds, and by up to a full unit whenmaxUnitscuts off a lower unit. Use ceiling rounding for the last kept unit, or state the value as "about". The copy "up to X old" is an upper bound. Truncation therefore shows a bound that is too low.Also, the input
0or a value under 60 seconds returns 'under a minute'. ForfreshnessSentence,spokenDuration(payload.refresh_interval_seconds, 1)then reads "Refreshes every under a minute". Handle this case in the sentence.
ℹ️ Review info
⚙️ Run configuration
- Configuration used: Repository: PostHog/posthog/.coderabbit.yaml
- Review profile: QUIET
- Plan: Enterprise
- Run ID:
9ce3612c-ed3e-404d-b91c-048c781e31f3
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (2)
products/warehouse_suggestions/frontend/components/MaterializeSuggestionModal.tsxproducts/warehouse_suggestions/frontend/suggestionCopy.ts
Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 9 remain after this review.
916c49e to
a2ab980
Compare
a277878 to
4d51206
Compare
4d51206 to
4deba8e
Compare
4deba8e to
8920252
Compare
8920252 to
360e7c9
Compare
360e7c9 to
4fbb9d4
Compare
4fbb9d4 to
0558044
Compare
0558044 to
6be3abc
Compare
…ng it After a materialize accept, the views list reloaded once, but the view's is_materialized flip lands asynchronously. A reload that came too early kept the view labeled as a plain view, without Sync now. suggestionAccepted(viewId, startsMaterializing) replaces reloadViews. For a materialize accept it adds the view to dataWarehouseViewsLogic's materializingViewIds before reloading, which is the polling flow the materialize button already uses: the list reloads every 5 s until the view reports it is materialized. An unmaterialize accept only reloads, because its revert is synchronous. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Accepting a certify or deprecate suggestion reloaded only the
certifications list. Badges elsewhere read certification state from
the shared schema in databaseTableListLogic, so they kept the old
status, such as Certified after a deprecation.
A suggestionAccepted action now reloads the list and forces a schema
refresh with loadDatabase({ force: true }), the same as the existing
certification review and revoke actions.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
…s, recover from 404s
Catalog edit access
- can_act describes access to the subject. Accepting a certify or
deprecate suggestion also needs data_catalog editor access
(_require_catalog_edit_access in the facade), so a catalog viewer
saw an enabled Certify button that always returned 403.
- The accept button now also checks userHasAccess for data_catalog at
editor level. Dismiss still only needs subject access.
- data_catalog is in the backend's ACCESS_CONTROL_RESOURCES, so the app
context already carries its level. The frontend
AccessControlResourceType enum gains DataCatalog, and the Storybook
app context gains a data_catalog level so stories render enabled
buttons.
Pending dialogs
- Escape, the overlay and the close icon closed the materialize dialog
while its accept was in flight. A refused option then set an error in
a hidden dialog, and reopening cleared it. The materialize,
deprecate and stop-materializing dialogs set closable={!inFlight}.
404 on accept, dismiss or undo
- When a view or table is deleted after the list loads, the backend
answers 404. Only 409 reloaded the list, so the row stayed
actionable and every retry failed. isStale now covers 404 and 409,
and a 404 explains that the suggestion or its subject is gone.
Table preview link
- escapePropertyAsHogQLIdentifier passes a name through when it starts
and ends with a quote, so a stored table name like
"x" UNION SELECT ... --" changed the preview query. subjectUrl now
escapes each dot-separated part with
escapeRawPropertyAsHogQLIdentifier, so demo.orders still resolves
and a quoted name stays one identifier. It moves out of the row
component so it can be tested directly.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
…tification A catalog opened from a ?tab=certifications&table=... link kept the table parameter through the highlight navigation. The urlToAction handler reapplies it as a search filter on the next URL change, so it hid a certification for another table right after highlightCertification cleared the filters. The highlight now removes table along with the sort parameter. Co-Authored-By: Claude Opus 5.5 <[email protected]>
… is ineligible When the incremental check said a view can no longer refresh incrementally, IncrementalConfigOptions showed the ineligible banner and a full refresh, but the draft kept the incremental proposal. Materialize then sent no refresh_mode, accept applied the old incremental config, and the backend answered 409. The check handler now sets the draft to full refresh under the same condition the component uses (not eligible, or no key candidates), so Materialize sends refresh_mode: full. The test file now resets the saved query and check mocks before each test. clearAllMocks keeps implementations, so one test's ineligible check leaked into the tests after it. Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
🕓 This approval covered an earlier revision. There are new visual changes to review in the newer comment below. ✅ Visual changes approved by @thiagosalvatore — baseline updated in 8 changed, 4 new. Install the Visual Review Chrome extension to see visual review results at the top of your pull requests. |
12 updated Run: 088af3ff-396b-43c5-90c6-cabe2408bb86 Co-authored-by: thiagosalvatore <[email protected]>
|
@PostHog review --deep |
|
@thiagosalvatore PostHog Review is reviewing this pull request. |
PostHog Review · Deep · reviewed
|
| Step | Status | Result |
|---|---|---|
| Prepare the diff | done | 36 files, 7 chunks |
| Pick perspectives | done | 3 perspectives |
| Run review passes | done | 13 issues (+2 blind-spot) |
| Merge overlapping findings | done | 15 → 11 |
| Validate findings | done | 5 kept, 6 dismissed |
| Publish | done | 5 posted (view review) |
Accepting a suggestion can move a view out of the active type filter. With eleven views under the Views filter on page 2, materializing the one on page 2 leaves ten. currentPage stayed 2, visibleViews was empty, and LemonTable, which does not clamp controlled pagination, showed "No views match your filters." Unmaterializing under Materialized views did the same. After every saved-query reload, the logic now moves to the last page of filteredViews when the current page is past it. This also covers a delete or a polling reload that shrinks the list. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…s and check guards Not now - "Suggested again if reads grow" was wrong for most kinds. A not-now dismissal returns when its score reaches a multiple of the score at dismissal (_earns_reproposal), and each kind scores something else: certify scores reads, materialize and unmaterialize score the saving, and deprecate scores refresh cost. - notNowCondition(kind) now gives the menu label and the toast the condition for that kind. It does not name the multiple, because that is a backend rule. - "All caught up" no longer says new suggestions come "as reads build up", for the same reason. Undo after unmount - Switching tabs after a dismiss unmounted the logic while the toast stayed. Undo dispatched to a logic with no listener, so nothing ran and the suggestion stayed dismissed. - The toast button now calls resumeDismissedSuggestion with the project id taken when the toast was made. It sends the resume request on its own, and updates suggestion state only through a logic that is still mounted (findMounted). Focus after the last suggestion - Handling the last suggestion removes the banner and its Review button, so the dialog returned focus to a detached button and focus fell to the page body. - The review dialog now renders a focus anchor beside itself. On onAfterClose, if focus is on the body, the anchor takes it, so the next Tab continues from the surface. Incremental check in flight - Materialize was enabled while the incremental check loaded. A refusal could arrive first, and the check's draft seeding then cleared it through setRefreshDraft. - materializeDisabledReason is now "Checking whether it can refresh incrementally" while the check loads, and confirmMaterialize already refuses while it is set. Tests that confirm now wait for the check. Co-Authored-By: Claude Opus 5.5 <[email protected]>
sinan-ku
left a comment
There was a problem hiding this comment.
Really exciting!! Got some nits but happy to ship!
…efetch The backend evaluates warehouse-suggestions for the organization (logic/flags.py) and answers 403 unless the result is True. The flag is released per organization, so the frontend and backend normally agree, but they can still differ: a flag-service timeout makes feature_enabled return None on the backend, and a personal override in the toolbar turns the frontend on alone. Either way a 403 became a permanent "Couldn't load..." error, and Retry could never succeed. - A 403 from the list or status request now sets featureForbidden, and stripState is "hidden". - The error state now shows only while the list or status has never loaded. A failed background reload, such as the one after a 409 or 404, keeps the current list, so it no longer unmounts an open review or materialize dialog. - A successful load clears loadError, not only reload. Co-Authored-By: Claude Opus 5.5 <[email protected]>
featureForbidden took the value of each failure on its own. When the status request answered 403 and the list request then failed with a 500, the second failure reset featureForbidden to false, and both surfaces showed "Couldn't load…" while the flag was off. The reducer now keeps a 403 until Retry, and the test pairs a 403 with a 500. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…ehouse-suggestions-frontend
…ures Master made realized_seconds_saved_per_month and realized_bytes_saved_per_month required on WarehouseSuggestionApi, so the typecheck of this branch merged with master failed on the story and logic test fixtures. Both fields are null until a suggestion is accepted, so the fixtures set them to null. Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
👋 Visual changes detected for this PR. Review and approve in PostHog Visual Review If these changes are unexpected, they may be caused by a flaky test or a broken snapshot on master. Don't approve — rerun the job or wait for a fix. Install the Visual Review Chrome extension to see visual review results at the top of your pull requests. |
…t succeeds e6db462 made loadSuggestionsSuccess and loadStatusSuccess clear loadError. When the list request failed and the status request succeeded after it, the success cleared the error while the list was still null, so stripState stayed "loading" and the strip rendered nothing, with no notice and no Retry. Visual review caught it in the LoadFailed story. The error screen already shows only while the list or the status has never loaded, so clearing on success is not needed. A failed background reload still keeps the loaded list. The error test now covers either request failing, with the other one settling after the failure. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…ehouse-suggestions-frontend
…1.438.21 Master bumped posthog-js to 1.438.21 in #122426. That bump rewrote the lockfile entry of every importer already on master, but not this branch's products/warehouse_suggestions importer. The merge queue builds this PR merged with master, so its Storybook build failed with ERR_PNPM_OUTDATED_LOCKFILE and the queue removed the PR. The importer now resolves the same posthog-js version as the other importers. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Problem
/modelsand the certifications tab in the data catalog.Changes
Behind the
warehouse-suggestionsflag:keep_materialized: true, so a person can deprecate a view and keep it materialized. A table deprecation stays one click.created_asset.stopped_materialization: "…and stopped its refreshes" when it did, otherwise "Marked X as deprecated."refresh_interval_basis): sources sync no faster, people read no more often, it is the fastest schedule, or it is the shortest one that saves more than it costs. A shorter pick shows a warning with the same reason.IncrementalConfigOptionsfrom the SQL editor, starting from the proposed mode, key, unique key and lookback. It runscheck_incrementalon the view's query to list the key candidates.refresh_interval_secondsplus only the refresh options that differ from the proposal, so an unchanged suggestion is accepted as proposed.<key>" in the row.resumeendpoint, so a dismiss is never delayed and closing the tab never loses it.warehouse suggestion review opened(banner to dialog), andwarehouse suggestion confirm openedandwarehouse suggestion confirm cancelledfor the deprecate and stop-materializing dialogs.backend/logic/candidates/materialize.py(interval plus today's source age). If the backend changes it,dataAgeLabelneeds the same change.evidenceand noscore, the refresh mode and accept overrides, then the deprecate stop and the unmaterialize kind from feat(warehouse-suggestions): stop refreshes when accepting a deprecate #121459 and feat(warehouse-suggestions): suggest unmaterializing rarely read views #121460), and lockfile syncs of this package's importer to master's catalog versions.How did you test this code?
Test rationale:
warehouseSuggestionsLogic.test.ts, extended. Each new case guards one regression:suggestionCopy.test.ts(new): data age for known, live and unscheduled sources, and a hint for each interval reason.certificationsLogic.test.ts: View for a row on page 2 opens page 2 of the certifications table, with the filters and sort cleared.dismissed, thenproposed), the schedule warning, certify then View with a filter on, and the last row from the keyboard. The rows and actions are unchanged since; the banner and review dialog were checked in Storybook only.Release status
Docs update
None.
🤖 Agent context
Autonomy: Human-driven (agent-assisted)
Agent: Claude Code, Claude Opus 5.5
/plan-design-review(20 decisions) and/plan-eng-review(4 decisions, plus a Codex outside voice) shaped the plan. The eng review found theresumeendpoint, so Undo needs no delayed send, and the outside voice found the toast dedupe and the last-row unmount./writing-ui-components,/writing-user-facing-copy,/writing-tests,/using-kea-disposables,/browse,/plan-design-review,/plan-eng-review,/writing-pr-descriptions.🤖 Generated with Claude Code