Repository navigation
Conversation
|
Merging to
After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here |
🤖 CI report🚨 Trunk lane — universal laneThis PR is assigned to the universal lane. It cannot merge in parallel with other PRs, so it can take longer to merge. Ask dev-ex if you think this is wrong.
|
| Function | Location | Complexity | Limit |
|---|---|---|---|
ChatSheet |
products/mobile/src/features/chat/ChatSheet.tsx:95 |
47 | 10 |
followRun |
products/mobile/src/features/handoff/useTaskRun.ts:238 |
47 | 10 |
actionBarStateFor |
products/mobile/src/features/handoff/actionBarState.ts:6 |
44 | 10 |
reduceFrame |
products/mobile/src/features/handoff/runStream.ts:324 |
40 | 10 |
useInsightScreen |
products/mobile/src/features/views/viewHooks.ts:364 |
39 | 10 |
useSession |
products/mobile/src/features/chat/session/useSession.ts:557 |
36 | 10 |
insightSnapshot |
products/mobile/src/model/adapters/insightSnapshot.ts:444 |
35 | 10 |
<anonymous> |
products/mobile/src/features/chat/session/useSession.ts:1109 |
34 | 10 |
<anonymous> |
products/mobile/src/features/chat/session/useSession.ts:1276 |
34 | 10 |
ActionBar |
products/mobile/src/features/handoff/ActionBar.tsx:36 |
32 | 10 |
ChartPin |
products/mobile/src/features/views/list/PinCard.tsx:261 |
29 | 10 |
reduceNotification |
products/mobile/src/features/handoff/runStream.ts:248 |
28 | 10 |
ViewsBody |
products/mobile/src/features/views/list/ViewsScreen.tsx:148 |
28 | 10 |
InsightTile |
products/mobile/src/features/views/dashboard/DashboardTile.tsx:66 |
27 | 10 |
activityText |
products/mobile/src/model/adapters/report.ts:384 |
27 | 10 |
formatInsightValue |
products/mobile/src/model/adapters/insightFormatting.ts:103 |
26 | 10 |
reduceSessionUpdate |
products/mobile/src/features/handoff/runStream.ts:175 |
25 | 10 |
<anonymous> |
products/mobile/src/features/chat/session/useSession.ts:777 |
24 | 10 |
toolCallUpdate |
products/mobile/src/features/chat/session/sessionReducer.ts:582 |
23 | 10 |
followSessionRun |
products/mobile/src/features/chat/session/useSession.ts:474 |
23 | 10 |
<anonymous> |
products/mobile/src/features/chat/session/useSession.ts:1446 |
23 | 10 |
mergeLiveRun |
products/mobile/src/features/handoff/liveReport.ts:73 |
23 | 10 |
parsePermissionRequest |
products/mobile/src/features/handoff/permissionRequest.ts:92 |
23 | 10 |
shouldPresent |
products/mobile/src/features/notifications/notificationPresentation.ts:13 |
23 | 10 |
syncOnce |
products/mobile/src/features/notifications/pushRegistration.ts:110 |
23 | 10 |
SqlTable |
products/mobile/src/ui/chart/SqlTable.tsx:134 |
23 | 10 |
ErrorsListBody |
products/mobile/src/features/errors/ErrorsListScreen.tsx:71 |
22 | 10 |
useLiveReport |
products/mobile/src/features/report/hooks.ts:32 |
22 | 10 |
SignInScreen |
products/mobile/src/auth/SignInScreen.tsx:33 |
21 | 10 |
<anonymous> |
products/mobile/src/features/chat/objectTags.ts:122 |
21 | 10 |
applyFrame |
products/mobile/src/features/chat/session/sessionReducer.ts:841 |
21 | 10 |
accept |
products/mobile/src/features/handoff/runStream.ts:460 |
21 | 10 |
openFromNotification |
products/mobile/src/features/notifications/useNotificationRouting.ts:18 |
21 | 10 |
ReplayListBody |
products/mobile/src/features/replay/ReplayListScreen.tsx:60 |
21 | 10 |
sessionListRows |
products/mobile/src/features/replay/sessionAdapters.ts:433 |
21 | 10 |
SettingsScreen |
products/mobile/src/features/settings/SettingsScreen.tsx:30 |
20 | 10 |
DayCell |
products/mobile/src/features/views/range/RangeCalendar.tsx:204 |
20 | 10 |
<anonymous> |
products/mobile/src/features/chat/objectTags.ts:150 |
19 | 10 |
IssueAssigneeSheet |
products/mobile/src/features/errors/IssueAssigneeSheet.tsx:31 |
19 | 10 |
PushStatusGroup |
products/mobile/src/features/settings/PushStatusGroup.tsx:49 |
19 | 10 |
<anonymous> |
products/mobile/src/features/chat/session/useSession.ts:715 |
18 | 10 |
handoffErrorMessage |
products/mobile/src/features/handoff/kickoff.ts:184 |
18 | 10 |
usePullRequestChecks |
products/mobile/src/features/handoff/usePullRequestChecks.ts:51 |
18 | 10 |
shouldShowWhileActive |
products/mobile/src/features/notifications/foregroundNotifications.ts:46 |
18 | 10 |
NumberPin |
products/mobile/src/features/views/list/PinCard.tsx:209 |
18 | 10 |
runQuery |
products/mobile/src/api/query.ts:79 |
17 | 10 |
Composer |
products/mobile/src/features/chat/Composer.tsx:82 |
17 | 10 |
summarizeTools |
products/mobile/src/features/chat/session/sessionDisplay.ts:62 |
17 | 10 |
TabsHeader |
products/mobile/src/features/tabs/TabsHeader.tsx:57 |
17 | 10 |
aboutContent |
products/mobile/src/features/views/about/aboutContent.ts:234 |
17 | 10 |
RetentionGrid |
products/mobile/src/ui/chart/RetentionGrid.tsx:92 |
17 | 10 |
taskRunError |
products/mobile/src/features/chat/chatErrors.ts:35 |
16 | 10 |
toChatError |
products/mobile/src/features/chat/chatErrors.ts:61 |
16 | 10 |
useLiveChatList |
products/mobile/src/features/chats/hooks.ts:25 |
16 | 10 |
IssueLoaded |
products/mobile/src/features/errors/IssueScreen.tsx:215 |
16 | 10 |
sameLive |
products/mobile/src/features/handoff/liveReport.ts:116 |
16 | 10 |
<anonymous> |
products/mobile/src/demo/views.ts:521 |
15 | 10 |
sessionThreadReducer |
products/mobile/src/features/chat/session/sessionReducer.ts:905 |
15 | 10 |
sendConfigOption |
products/mobile/src/features/chat/session/useSession.ts:264 |
15 | 10 |
PullRequestCard |
products/mobile/src/features/handoff/PullRequestCard.tsx:27 |
15 | 10 |
pullRequestChecksStatus |
products/mobile/src/features/handoff/usePullRequestChecks.ts:24 |
15 | 10 |
<anonymous> |
products/mobile/src/features/inbox/hooks.ts:355 |
15 | 10 |
ProjectSheet |
products/mobile/src/features/projects/ProjectSheet.tsx:55 |
15 | 10 |
AssigneeSheet |
products/mobile/src/features/reviewers/AssigneeSheet.tsx:70 |
15 | 10 |
AboutBody |
products/mobile/src/features/views/about/AboutSheet.tsx:52 |
15 | 10 |
webLinkTarget |
products/mobile/src/lib/deepLinkKind.ts:105 |
15 | 10 |
numberParts |
products/mobile/src/model/adapters/insightSnapshot.ts:366 |
15 | 10 |
reportView |
products/mobile/src/model/adapters/report.ts:612 |
15 | 10 |
<anonymous> |
products/mobile/src/auth/authStore.ts:200 |
14 | 10 |
checkAiApproval |
products/mobile/src/features/ai/aiApproval.ts:108 |
14 | 10 |
observe |
products/mobile/src/features/chat/session/sessionTurn.ts:51 |
14 | 10 |
HandoffSheet |
products/mobile/src/features/handoff/HandoffSheet.tsx:59 |
14 | 10 |
deliverAnswer |
products/mobile/src/features/handoff/hooks.ts:87 |
14 | 10 |
<anonymous> |
products/mobile/src/features/handoff/hooks.ts:210 |
14 | 10 |
<anonymous> |
products/mobile/src/features/handoff/useTaskRun.ts:179 |
14 | 10 |
planKeyframes |
products/mobile/src/features/hedgehog/choreography.ts:213 |
14 | 10 |
entryText |
products/mobile/src/features/replay/sessionAdapters.ts:207 |
14 | 10 |
<anonymous> |
products/mobile/src/features/views/InsightVisual.tsx:161 |
14 | 10 |
blockedState |
products/mobile/src/features/views/freshness.ts:140 |
14 | 10 |
FullScreenBody |
products/mobile/src/features/views/fullScreen/FullScreenChart.tsx:83 |
14 | 10 |
usePins |
products/mobile/src/features/views/pinHooks.ts:92 |
14 | 10 |
<anonymous> |
products/mobile/src/features/views/useViewRefresh.ts:341 |
14 | 10 |
parseMermaidMessage |
products/mobile/src/lib/mermaid.ts:42 |
14 | 10 |
formatMetricValue |
products/mobile/src/model/adapters/metric.ts:41 |
14 | 10 |
cohortView |
products/mobile/src/model/adapters/retention.ts:29 |
14 | 10 |
sqlScalar |
products/mobile/src/model/adapters/sqlVisualization.ts:105 |
14 | 10 |
sqlResultDisplay |
products/mobile/src/model/adapters/sqlVisualization.ts:324 |
14 | 10 |
refreshOnce |
products/mobile/src/auth/authStore.ts:492 |
13 | 10 |
human |
products/mobile/src/features/chat/session/sessionReducer.ts:449 |
13 | 10 |
applySessionUpdate |
products/mobile/src/features/chat/session/sessionReducer.ts:806 |
13 | 10 |
<anonymous> |
products/mobile/src/features/chat/session/useSession.ts:1530 |
13 | 10 |
<anonymous> |
products/mobile/src/features/chat/useChatDraft.ts:92 |
13 | 10 |
highlightStart |
products/mobile/src/features/errors/issueModel.ts:118 |
13 | 10 |
emptyCopy |
products/mobile/src/features/errors/issueModel.ts:336 |
13 | 10 |
planAnswer |
products/mobile/src/features/handoff/permissionRequest.ts:206 |
13 | 10 |
resolveToolCall |
products/mobile/src/features/handoff/toolPolicy.ts:77 |
13 | 10 |
InboxScreen |
products/mobile/src/features/inbox/InboxScreen.tsx:34 |
13 | 10 |
ReportContextMenu |
products/mobile/src/features/inbox/ReportContextMenu.tsx:98 |
13 | 10 |
useLiveInboxItems |
products/mobile/src/features/inbox/hooks.ts:119 |
13 | 10 |
SessionBody |
products/mobile/src/features/replay/SessionScreen.tsx:176 |
13 | 10 |
parseCustomSnooze |
products/mobile/src/features/snooze/snoozeTimes.ts:60 |
13 | 10 |
BrowseList |
products/mobile/src/features/views/browse/BrowseListScreen.tsx:98 |
13 | 10 |
InsightBody |
products/mobile/src/features/views/insight/InsightScreen.tsx:107 |
13 | 10 |
writeTiles |
products/mobile/src/features/views/items.ts:324 |
13 | 10 |
TileOption |
products/mobile/src/features/views/list/ChooseTileSheet.tsx:215 |
13 | 10 |
<anonymous> |
products/mobile/src/features/views/list/ViewsScreen.tsx:461 |
13 | 10 |
authResultError |
products/mobile/src/auth/oauth.ts:155 |
12 | 10 |
authorize |
products/mobile/src/auth/oauth.ts:179 |
12 | 10 |
InsightCard |
products/mobile/src/features/chat/InsightCard.tsx:12 |
12 | 10 |
progress |
products/mobile/src/features/chat/session/sessionReducer.ts:667 |
12 | 10 |
useIssuesList |
products/mobile/src/features/errors/hooks.ts:95 |
12 | 10 |
ModelPage |
products/mobile/src/features/handoff/ModelPage.tsx:67 |
12 | 10 |
handoffFailureReason |
products/mobile/src/features/handoff/kickoff.ts:150 |
12 | 10 |
<anonymous> |
products/mobile/src/features/hedgehog/choreography.ts:313 |
12 | 10 |
RowActions |
products/mobile/src/features/inbox/InboxRowActions.tsx:94 |
12 | 10 |
SessionContent |
products/mobile/src/features/replay/SessionScreen.tsx:74 |
12 | 10 |
Header |
products/mobile/src/features/replay/SessionScreen.tsx:360 |
12 | 10 |
tileMeta |
products/mobile/src/features/views/dashboard/DashboardTile.tsx:213 |
12 | 10 |
rangeLabel |
products/mobile/src/features/views/rangePresets.ts:156 |
12 | 10 |
<anonymous> |
products/mobile/src/features/views/useViewRefresh.ts:382 |
12 | 10 |
kindLabelOf |
products/mobile/src/model/adapters/insightSnapshot.ts:151 |
12 | 10 |
<anonymous> |
products/mobile/src/model/adapters/report.ts:345 |
12 | 10 |
webOverviewSnapshot |
products/mobile/src/model/adapters/webOverview.ts:53 |
12 | 10 |
ChartOverlay |
products/mobile/src/ui/chart/ChartOverlay.tsx:38 |
12 | 10 |
send |
products/mobile/src/api/client.ts:150 |
11 | 10 |
<anonymous> |
products/mobile/src/auth/authStore.ts:285 |
11 | 10 |
validateHost |
products/mobile/src/auth/regions.ts:70 |
11 | 10 |
AiApprovalDialog |
products/mobile/src/features/ai/AiApprovalDialog.tsx:14 |
11 | 10 |
ChatAccessGate |
products/mobile/src/features/chat/ChatAccessGate.tsx:19 |
11 | 10 |
queueReducer |
products/mobile/src/features/chat/messageQueue.ts:48 |
11 | 10 |
matchTag |
products/mobile/src/features/chat/objectTags.ts:35 |
11 | 10 |
SessionThread |
products/mobile/src/features/chat/session/SessionThread.tsx:54 |
11 | 10 |
userAttachment |
products/mobile/src/features/chat/session/sessionReducer.ts:147 |
11 | 10 |
noteAttachment |
products/mobile/src/features/chat/session/sessionReducer.ts:479 |
11 | 10 |
<anonymous> |
products/mobile/src/features/chat/session/useSession.ts:413 |
11 | 10 |
IssueListRow |
products/mobile/src/features/errors/IssueListRow.tsx:27 |
11 | 10 |
sampleSessions |
products/mobile/src/features/errors/issueModel.ts:236 |
11 | 10 |
ProjectSwitcher |
products/mobile/src/features/settings/ProjectSwitcher.tsx:18 |
11 | 10 |
TabsChrome |
products/mobile/src/features/tabs/TabsLayout.tsx:90 |
11 | 10 |
<anonymous> |
products/mobile/src/features/views/list/ModeSegment.tsx:38 |
11 | 10 |
<anonymous> |
products/mobile/src/features/views/list/ViewsScreen.tsx:342 |
11 | 10 |
formatRangeSpan |
products/mobile/src/features/views/rangePresets.ts:124 |
11 | 10 |
<anonymous> |
products/mobile/src/features/views/useViewRefresh.ts:257 |
11 | 10 |
<anonymous> |
products/mobile/src/features/views/useViewRefresh.ts:305 |
11 | 10 |
<anonymous> |
products/mobile/src/features/views/useViewRefresh.ts:426 |
11 | 10 |
sqlValuePresentation |
products/mobile/src/model/adapters/sqlVisualization.ts:280 |
11 | 10 |
<anonymous> |
products/mobile/src/ui/chart/gestures/useChartGestures.ts:127 |
11 | 10 |
formatSqlCell |
products/mobile/src/ui/chart/sqlCellFormat.ts:42 |
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) — 30 new duplicated blocks (worst 627 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/desktop/packages/core/src/inbox/objectKinds.generated.ts:5 |
products/mobile/src/features/chat/objectKinds.generated.ts:5 |
174 | 627 |
products/mobile/src/features/chat/session/sessionDisplay.ts:78 |
products/posthog_ai/frontend/utils/toolRunSummary.ts:36 |
24 | 264 |
products/mobile/src/features/chat/attachments/attachmentRules.ts:6 |
products/posthog_ai/frontend/utils/attachments.ts:10 |
48 | 189 |
products/mobile/src/features/chat/ContextChip.tsx:43 |
products/mobile/src/features/chat/ObjectContextChip.tsx:30 |
38 | 171 |
products/mobile/src/features/chat/useChatDraft.test.tsx:99 |
products/mobile/src/features/chat/useChatDraft.test.tsx:143 |
14 | 167 |
products/mobile/src/features/errors/listPagination.test.tsx:18 |
products/mobile/src/features/replay/listPagination.test.tsx:20 |
16 | 154 |
products/mobile/src/features/chat/session/sessionDisplay.ts:47 |
products/posthog_ai/frontend/utils/toolRunSummary.ts:4 |
13 | 109 |
products/mobile/src/features/priority/PrioritySheet.tsx:124 |
products/mobile/src/features/snooze/SnoozeSheet.tsx:134 |
29 | 108 |
products/mobile/src/features/inbox/ReportContextMenu.tsx:121 |
products/mobile/src/features/views/list/ViewsMenu.tsx:43 |
19 | 95 |
products/mobile/src/features/errors/IssueAssigneeSheet.tsx:115 |
products/mobile/src/features/verdict/VerdictSheet.tsx:152 |
24 | 94 |
products/mobile/src/ui/chart/ChartTooltip.tsx:114 |
products/mobile/src/ui/chart/RangeTooltip.tsx:55 |
23 | 92 |
products/mobile/src/features/projects/ProjectSheet.tsx:234 |
products/mobile/src/features/reviewers/AssigneeSheet.tsx:302 |
24 | 88 |
products/mobile/src/features/views/insight/InsightScreen.tsx:146 |
products/mobile/src/features/views/webAnalytics/WebAnalyticsScreen.tsx:117 |
19 | 87 |
products/mobile/src/features/chat/ChatMarkdown.tsx:124 |
products/mobile/src/features/report/details/ReportMarkdown.tsx:86 |
25 | 84 |
products/mobile/src/features/chat/session/sessionReducer.ts:167 |
products/posthog_ai/frontend/logics/runStreamLogic.ts:480 |
12 | 84 |
products/mobile/src/features/projects/ProjectSheet.tsx:205 |
products/mobile/src/features/reviewers/AssigneeSheet.tsx:243 |
23 | 84 |
products/mobile/src/features/chat/InsightCard.tsx:51 |
products/mobile/src/features/chat/QueryCard.tsx:38 |
15 | 83 |
products/mobile/src/features/errors/ErrorsListScreen.tsx:313 |
products/mobile/src/features/replay/ReplayListScreen.tsx:251 |
23 | 83 |
products/mobile/src/features/handoff/actionBarState.ts:7 |
products/mobile/src/features/handoff/liveReport.ts:87 |
11 | 83 |
products/mobile/src/features/inbox/useRowMenuTrigger.ts:21 |
products/mobile/src/features/views/list/useMenuTrigger.ts:14 |
13 | 83 |
products/mobile/src/features/errors/IssueActionBar.tsx:104 |
products/mobile/src/features/handoff/ActionPill.tsx:51 |
21 | 82 |
nodejs/src/ingestion/common/persons/batch-writing-person-store.model.test.ts:591 |
products/mobile/src/features/hedgehog/choreography.ts:102 |
12 | 81 |
products/mobile/src/features/snooze/CustomSnoozePicker.tsx:97 |
products/mobile/src/features/snooze/CustomSnoozePicker.web.tsx:81 |
23 | 81 |
products/mobile/src/features/errors/IssueAssigneeSheet.tsx:113 |
products/mobile/src/features/errors/SuppressSheet.tsx:56 |
20 | 79 |
products/mobile/src/features/report/ReportScreen.tsx:163 |
products/mobile/src/features/report/details/ReportDetailsScreen.tsx:89 |
11 | 76 |
products/mobile/src/features/chats/ChatRow.tsx:84 |
products/mobile/src/features/errors/IssueListRow.tsx:77 |
21 | 75 |
products/mobile/src/features/chat/attachments/AttachMenuSheet.tsx:48 |
products/mobile/src/features/views/screen/ViewMoreSheet.tsx:59 |
19 | 71 |
products/mobile/src/features/chat/session/sessionDisplay.ts:62 |
products/posthog_ai/frontend/utils/toolRunSummary.ts:19 |
14 | 70 |
products/mobile/src/features/chats/ChatRow.tsx:90 |
products/mobile/src/features/inbox/InboxRow.tsx:161 |
19 | 70 |
products/mobile/src/features/snooze/CustomSnoozePicker.tsx:61 |
products/mobile/src/features/snooze/CustomSnoozePicker.web.tsx:42 |
11 | 70 |
✅ Bundle size — no change
Uncompressed size of every built .js bundle, compared against the base branch.
Total: 77.01 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 — 1 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 | no change | █████████░ 87.9% 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.97 MiB · 620 files | no change | ██████████ 98.0% of 3.03 MiB |
authenticated shell (every logged-in page)src/scenes/AuthenticatedShell.tsx |
7.50 MiB · 2,563 files | no change | ██████████ 100.0% of 7.50 MiB |
dashboard scenesrc/scenes/dashboard/Dashboard.tsx |
9.95 MiB · 3,730 files | no change | ██████████ 99.3% of 10.01 MiB |
today home pathsrc/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx |
7.68 MiB · 2,656 files | no change | ██████████ 99.2% 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.92 MiB · 2,649 files | no change | ██████████ 100.2% of 7.91 MiB |
events scenesrc/scenes/activity/explore/EventsScene.tsx |
9.39 MiB · 3,512 files | no change | ██████████ 97.9% of 9.59 MiB |
web analytics scenesrc/scenes/web-analytics/WebAnalyticsScene.tsx |
10.33 MiB · 3,763 files | no change | ██████████ 95.3% of 10.83 MiB |
replay detail scenesrc/scenes/session-recordings/detail/SessionRecordingDetail.tsx |
8.41 MiB · 3,088 files | no change | █████████░ 88.8% 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/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 | ../node_modules/.pnpm/base64-js@1.5.1/node_modules/base64-js/index.js |
| 1.6 KiB | src/lib/utils/bootTiming.ts |
| 1.6 KiB | src/index.tsx |
| 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 |
|---|---|
| 322.9 KiB | ../node_modules/.pnpm/posthog-js@1.438.23_@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.1 KiB | src/products.tsx |
| 86.1 KiB | src/lib/api.ts |
| 68.3 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 |
|---|---|
| 322.9 KiB | ../node_modules/.pnpm/posthog-js@1.438.23_@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.1 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.1 KiB | src/lib/api.ts |
Largest files eagerly shipped from src/scenes/dashboard/Dashboard.tsx
| Size | File |
|---|---|
| 322.9 KiB | ../node_modules/.pnpm/posthog-js@1.438.23_@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.1 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 |
|---|---|
| 322.9 KiB | ../node_modules/.pnpm/posthog-js@1.438.23_@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.1 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.1 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 |
|---|---|
| 322.9 KiB | ../node_modules/.pnpm/posthog-js@1.438.23_@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.1 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 |
|---|---|
| 322.9 KiB | ../node_modules/.pnpm/posthog-js@1.438.23_@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.1 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 |
|---|---|
| 322.9 KiB | ../node_modules/.pnpm/posthog-js@1.438.23_@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 |
| 182.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.1 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 |
|---|---|
| 322.9 KiB | ../node_modules/.pnpm/posthog-js@1.438.23_@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.23_@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.1 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 #32479
✅ Toolbar bundle — eager 2.30 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.30 MiB · 18 files | no change | ████░░░░░░ 40.2% 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 |
|---|---|
| 912.8 KiB | dist/toolbar/toolbar-app-5QWAE5P2.css |
| 694.7 KiB | dist/toolbar/chunk-chunk-ZOYRVWMI.js |
| 259.9 KiB | dist/toolbar/chunk-chunk-ONRHJSKR.js |
| 131.8 KiB | dist/toolbar/chunk-chunk-FDH2IBXT.js |
| 130.4 KiB | dist/toolbar/chunk-chunk-O6NJ623V.js |
| 74.8 KiB | dist/toolbar/toolbar-app-PAZXMELH.js |
| 69.0 KiB | dist/toolbar/chunk-chunk-TSAL54PB.js |
| 35.6 KiB | dist/toolbar/chunk-chunk-ZA2V5YRY.js |
| 21.7 KiB | dist/toolbar/chunk-chunk-PW4LOT2W.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 — 🔺 +156 B (+0.0%)
Total size of the built frontend/dist folder (all assets), compared against the base branch.
Total: 970.95 MiB · 🔺 +156 B (+0.0%)
⚠️ Playwright — 1 flaky
🎭 Playwright report · View test results →
- Save view (chromium)
These issues are not necessarily caused by your changes.
Annoyed by this section? Help fix flakies and failures and it will go green!
HostHog preview —
|
|
[High impact] Adds a new mobile app as a standalone workspace. Fix the missing CI dependency and the push-registration race before merging, and satisfy the repository's missing-result rule. Reviews (1) · Last reviewed commit: "Merge commit 'cd3e77c84bcc0166cf8a90ebcc..." · Reviewed by Greptile |
There was a problem hiding this comment.
PostHog Review · Standard · reviewed fb2a704: 5 Must fix, 15 Should fix. This pull request is large, so the review ran in 4 parts with less depth than usual.
This is the only automatic review while this pull request is a draft. Comment @posthog review to review new changes sooner. Otherwise, a review of the new changes runs when you mark it ready for review.
| {isEmpty ? <Text style={styles.quiet}>The agent hasn't said anything yet.</Text> : null} | ||
| {displayItems.map(renderItem)} | ||
| {pullRequests.length > 0 ? <PullRequestCard pullRequests={pullRequests} /> : null} |
There was a problem hiding this comment.
P2 · Virtualize the session transcript
Opening a long resumed chat renders its entire history through displayItems.map inside a ScrollView. Every offscreen Markdown tree and Mermaid WebView stays mounted, and offscreen InsightCard components start requests immediately. Memory and initial rendering work grow with the full conversation. Use a virtualized transcript with a bounded render window.
| if (!compareAllowed(dateFrom)) { | ||
| return null | ||
| } | ||
| return { ...source, compareFilter: { compare: true }, dateRange } |
There was a problem hiding this comment.
P2 · Restrict comparison requests to query types that support comparison
Enabling comparison on a SQL or lifecycle insight adds compareFilter to its source unconditionally. HogQLQuery also rejects dateRange, and both schemas forbid unknown fields, so POST query/ rejects the request and the insight shows an error instead of data. Gate comparison by source kind and disable the control for unsupported queries.
| export function projectWebUrl(path: string): string | undefined { | ||
| try { | ||
| return apiUrl(projectPath(path).replace(/^\/api\/projects\//, '/project/')) | ||
| } catch { | ||
| return undefined |
There was a problem hiding this comment.
projectWebUrl deliberately returns undefined when no account or project is available. The repository requires null for an intended lack of result. Return null and update the return type before merging. Apply the same change to fetchInsightByShortId, which also uses undefined for a missing result.
Rule Used: Use 'null' instead of 'undefined' to indicate an intended lack of result in functions. (source)
Learned From
PostHog/posthog#32556
Prompt To Fix With AI
This is a comment left during a code review.
Path: products/mobile/src/api/client.ts
Line: 111-115
Comment:
**Missing results use undefined**
`projectWebUrl` deliberately returns `undefined` when no account or project is available. The repository requires `null` for an intended lack of result. Return `null` and update the return type before merging. Apply the same change to `fetchInsightByShortId`, which also uses `undefined` for a missing result.
**Rule Used:** Use 'null' instead of 'undefined' to indicate an intended lack of result in functions. ([source](https://app.greptile.com/posthog-org-19734/-/custom-context?memory=0631667e-2260-42be-a589-0d8da9ef007d))
**Learned From**
[PostHog/posthog#32556](https://github.com/PostHog/posthog/pull/32556)
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
|
The mobile Chats list showed Signals scout runs beside real conversations. The list request now sends exclude_origin_product=signals_scout, the same filter the web PostHog AI task list uses, so no backend change is needed.
gantoine
left a comment
There was a problem hiding this comment.
everything outside products/mobile looks good 👍🏼
|
Risk: No findings This delta hardens the mobile release pipeline (OTA manifest signing with a GitHub-secret private key verified against a pinned certificate, gated build workflow) and tightens two privacy/device semantics: push tokens now transfer device ownership between users atomically under an advisory lock, and analytics only include the user's email when they have explicitly opted out of anonymization while stripping the launch URL from lifecycle events. All changes fail closed where a secret or certificate is missing, and no new vulnerability was found. Sentinel reviewed |
👀 Auto-assigned reviewersThese owners were selected because this PR adds a new path where
Soft owners come from each directory's |
| const host = useAuthStore((state) => state.host) | ||
| const signedIn = status === 'signed_in' && userUuid !== null | ||
|
|
||
| useEffect(() => addSignOutTask(unregisterPush), []) |
There was a problem hiding this comment.
P1 · Expire push subscriptions when their account session ends
When OAuth refresh expires, endSession('expired') skips signOutTasks, so this cleanup never runs. Signing into another account overwrites registeredFor while the backend retains both (user, token) rows. The device continues receiving the previous user's private task and report titles. Bind subscription revocation to session expiry and account replacement.
feliperalmeida
left a comment
There was a problem hiding this comment.
🤖 Automated security review (Claude) covering CI/CD, OAuth and tokens, mobile platform surface, rendering and AI chat, and data handling. Inline: 1 high, 1 medium, 1 low, and 3 hardening notes. Everything else checked out, including the mermaid WebView, markdown links, deep links, push routing, widgets, token storage, PKCE/state, and workflow triggers.
| './plugins/withIosSceneLifecycle', | ||
| '@bacons/apple-targets', | ||
| ], | ||
| updates: { |
There was a problem hiding this comment.
🤖 Automated security review: High. OTA updates are unsigned, and a branch can run code with the Expo token.
mobile-build.ymlisworkflow_dispatchon any ref. It runsscripts/eas-build.shfrom that ref withsecrets.EXPO_TOKENand no environment.- A person with write access (or a leaked write token) can change the script on a branch to run
eas update --channel production. Devices accept the update because it is not signed. - Before this PR, the token could only build and submit. With
expo-updates, it can push JS to every production install.
Fix: turn on update code signing (updates.codeSigningCertificate and codeSigningMetadata). Keep the private key only in the mobile-production environment, and sign in scripts/releases/release.mjs. Also consider moving the Expo token into environment secrets so only gated jobs can read it.
There was a problem hiding this comment.
🤖 Automated reply by Codex.
Implemented the code checks in 2db630183999. Production OTA releases require signatures. Internal builds require master and separate environment credentials. All 15 release tests pass.
This thread stays open until signing credentials are configured and the old Expo token is retired.
| | Name | PostHog mobile | | ||
| | Client type | Public | | ||
| | Authorization grant type | Authorization code | | ||
| | Redirect URIs | `posthog://callback`, plus `posthog-dev://callback` and `posthog-preview://callback` for internal builds | |
There was a problem hiding this comment.
🤖 Automated security review: Medium. Please don't register posthog-dev://callback and posthog-preview://callback on the production first-party apps.
First-party apps skip the consent screen. Store builds never claim these schemes, so another app on the device can claim them, receive the authorization code, and redeem it with its own PKCE verifier. Use a separate non-first-party app for internal builds, like the local dev app.
There was a problem hiding this comment.
🤖 Automated reply by Codex.
Updated in 2db630183999. Internal builds now require separate OAuth client IDs, with no production fallback. Tests pass.
This thread stays open until non-first-party clients are configured and production registrations exclude internal callback schemes.
There was a problem hiding this comment.
PostHog Review · Standard · reviewed f4bd948: 1 Must fix. This pull request is large, so the review ran in 4 parts with less depth than usual.
This is review round 3 on this pull request. When findings keep coming back in the same code, the approach is usually the problem. Before the next fix, check whether a different design would remove the whole class of findings.
| if (pending.kind === 'plan') { | ||
| return { id: record.requestId, question: 'Approve the plan?', options: planOptions(record) } | ||
| } | ||
| const subject = record.title ?? record.toolName | ||
| return { | ||
| id: record.requestId, | ||
| question: subject ? `Allow ${subject}?` : 'Allow this action?', | ||
| options: record.options.map((option) => ({ id: option.optionId, title: optionTitle(option) })), |
There was a problem hiding this comment.
P1 · Show the requested action before granting permission
For connected-project or external MCP approvals, decisionQuestionFor drops rawToolCall.input and shows only an agent-supplied title; plan approvals likewise discard input.plan. Users authorize operations without seeing the target, arguments, or proposed plan, so an innocuous title can conceal a destructive call. Include the payload in the approval view.
There was a problem hiding this comment.
PostHog Review · Standard · reviewed 74b1ab9: 2 Must fix. This pull request is large, so the review ran in 4 parts with less depth than usual.
This is review round 4 on this pull request. When findings keep coming back in the same code, the approach is usually the problem. Before the next fix, check whether a different design would remove the whole class of findings.
| controller.abort() | ||
| deliveries.delete(reportId) | ||
| useHandoffStore.getState().setAnswer(reportId, undefined) | ||
| track('mobile_decision_undone', { report_id: reportId }) |
There was a problem hiding this comment.
P1 · Make approval Undo operate before command dispatch
When Undo is tapped after permission_response reaches the server but before its reply arrives, controller.abort() only stops the client wait. The server still delivers the approval, while setAnswer(undefined) presents it as withdrawn. The agent can execute an action the user thinks they cancelled; delay dispatch until Undo expires or remove Undo once dispatched.
| const notificationId = await scheduleSnoozeReminder({ | ||
| reportId, | ||
| projectId: scope.projectId, | ||
| title: cachedTitle(queryClient, scope, reportId), | ||
| until, | ||
| }).catch(() => undefined) | ||
| useSnoozeStore.getState().put(key, { |
There was a problem hiding this comment.
P1 · Cancel pending snooze reminders when their session ends
If sign-out completes while scheduleSnoozeReminder is pending, session cleanup finds no entry to cancel. snoozeUntil then stores the notification after cleanup, leaving the previous account's report title scheduled on the device, including its lock screen after another user signs in. Bind scheduling to the originating session and cancel late results.
|
⏭️ Security review skipped — this PR is too large — 1252 files, 113357 lines and 105 commits exceeds the review limit (100 files or 10,000 lines, combined with more than 20 commits). A pull request this size is usually the result of a bad merge or rebase rather than a change this large. This PR has not been reviewed — treat it as unreviewed, not as clean. If the size is genuine and you want a review, split it, or ask Add the |
There was a problem hiding this comment.
PostHog Review · Standard · reviewed 99a45d6: 3 Must fix. This pull request is large, so the review ran in 4 parts with less depth than usual.
This pull request reached its limit of 20 automatic review findings, so this review left out 1 lower-priority finding. Must-fix findings still post. Comment @posthog review --deep for a review without the limit.
This is review round 5 on this pull request. When findings keep coming back in the same code, the approach is usually the problem. Before the next fix, check whether a different design would remove the whole class of findings.
| if (isExec) { | ||
| if (innerToolName !== undefined && isConnectedProjectSubTool(innerToolName)) { | ||
| return 'prompt' | ||
| } | ||
| return 'auto_allow' |
There was a problem hiding this comment.
P1 · Preserve approval prompts for destructive PostHog operations
When an interactive run in Auto requests feature-flag-delete, the agent server explicitly relays that destructive operation for approval. defaultPermissionDecision instead returns auto_allow, so viewing the run authorizes deletion without a user choice, violating the mode's live-data approval guarantee. Keep these relayed approvals manual outside full auto.
| const fullAuto = isFullAutoMode(context.mode) && !record.questions?.length && !isConnectedProjectTool(record) | ||
| const decision = fullAuto ? 'auto_allow' : defaultPermissionDecision(record) |
There was a problem hiding this comment.
P1 · Require explicit approval for relayed external MCP tools
When mobile follows a desktop run in bypassPermissions, fullAuto automatically approves external MCP requests. The agent server deliberately relays these requests regardless of mode because they execute on the user's machine with local privileges. Opening the run therefore bypasses that explicit-consent boundary. Exclude external MCP tools from automatic approval.
| const last = useRef<T | undefined>(value) | ||
| if (value !== undefined) { | ||
| last.current = value | ||
| } | ||
| if (value !== undefined || error) { | ||
| return { value, held: false } | ||
| } | ||
| return { value: last.current, held: last.current !== undefined } |
There was a problem hiding this comment.
P1 · Clear retained chart snapshots when the account changes
When session expiry replaces a screen above an insight with sign-in, the insight stays mounted. Another user's sign-in clears the query cache but leaves last.current intact, so navigating back displays the previous user's chart, indefinitely while offline. Bind retained snapshots to the session, host, project and insight, and clear them when that identity changes.
feliperalmeida
left a comment
There was a problem hiding this comment.
Things still to do outside the PR:
- Secrets aren't set up yet.
MOBILE_BUILD_EXPO_TOKEN,MOBILE_PRODUCTION_EXPO_TOKENandMOBILE_OTA_SIGNING_KEYneed to be added as environment secrets. - The old org
EXPO_TOKENis still there. Make sure its Expo account has no role on the new EAS project (4eb57b2f…). Otherwise a writer could still start builds or submissions for the new app. Unsigned OTA updates are blocked either way once signing is on.
Problem
PostHog users need to triage reports, respond to agents, and inspect their dashboards from iOS and Android.
Mobile Sessions and Errors can delay initial results while optional recommendations or list chart data load.
Changes
A mobile companion to the core PostHog experience, intended to complement workflows for users that are on the go.
It will not handle the long-tail of user actions that are possible in the PostHog web experience.