Repository navigation
Conversation
|
Important Review skippedToo many files! This PR contains 175 files, which is 25 over the limit of 150. To get a review, reduce the PR to 150 files or fewer by splitting it into smaller PRs or changing its base branch. Upgrade to a paid plan to raise the limit. This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry.
|
Maple review🟡 Confidence 6/10 · needs attention Splits every page into a small
Findings🟠 Warning · F1 ·
|
| Issue | Service | Occurrences | File |
|---|---|---|---|
| @maple/mcp/errors/McpQueryError | maple-chat | 429 | apps/web/src/page/registry.ts |
| @maple/mcp/errors/McpQueryError | maple-ai | 226 | apps/web/src/page/registry.ts |
| @maple/mcp/errors/McpQueryError | maple-chat | 222 | apps/web/src/page/registry.ts |
| @maple/mcp/errors/McpQueryError | maple-chat | 75 | apps/web/src/page/registry.ts |
| @maple/mcp/errors/McpQueryError | maple-ai | 63 | apps/web/src/page/registry.ts |
| @maple/mcp/errors/McpQueryError | maple-ai | 36 | apps/web/src/page/registry.ts |
| @maple/mcp/errors/McpQueryError | maple-chat | 30 | apps/web/src/page/registry.ts |
| @maple/mcp/errors/McpQueryError | maple-chat | 24 | apps/web/src/page/registry.ts |
| @maple/mcp/errors/McpQueryError | maple-ai | 24 | apps/web/src/page/registry.ts |
| @maple/mcp/errors/McpQueryError | maple-ai | 20 | apps/web/src/page/registry.ts |
After this merges, Maple checks whether they stop.
Production traffic of the changed files (last 7 days)
| File | Calls/day | Busiest operations |
|---|---|---|
apps/web/src/page/settings/mcp-page/implementation.ts |
15k | POST /mcp 6.9k/day, 0.0% errPOST /mcp 6.9k/day, 0.0% errGET /mcp 443/day, 0.0% err |
apps/web/src/page/settings/mcp-page/index.ts |
15k | POST /mcp 6.9k/day, 0.0% errPOST /mcp 6.9k/day, 0.0% errGET /mcp 443/day, 0.0% err |
apps/web/src/platform/telemetry.ts |
66 | LoadClerk 66/day, 0.0% err |
apps/web/src/page/traces/detail/implementation.ts |
18 | FetchSpanHierarchy 18/day, 0.0% err |
apps/web/src/page/traces/detail/index.ts |
18 | FetchSpanHierarchy 18/day, 0.0% err |
Telemetry this change adds and removes (2)
- ➕ attribute
maple.page.id·apps/web/src/command.ts:111 - ➕ attribute
maple.page.code_for_preload·apps/web/src/command.ts:112
What was checked
- All 174 changed files read; page
routes/keyand spec content match main, with 8 widget/boot modules (chat/sheet, span-panel, timeline, waterfall, sign-in, onboarding) kept inline LoadPageCode'stryPromisemaps any chunk rejection toPageLoadError, so a stale chunk reachesPageCode.Failedwith Reload instead of dying- Slot restart compares page, key, org, instance and the Subscription's own dependencies (
registry.ts:451);parkPageskeeps parked pages whenenteredis null
Files not reviewed (22)
The review ended before it read these diffs, so nothing above vouches for them.
apps/web/src/page/agent-sessions/session/index.tsapps/web/src/page/agent-sessions/tool/implementation.tsapps/web/src/page/agent-sessions/tool/index.tsapps/web/src/page/alerts/editor/implementation.tsapps/web/src/page/alerts/editor/index.tsapps/web/src/page/alerts/hub/implementation.tsapps/web/src/page/alerts/hub/index.tsapps/web/src/page/alerts/incident/implementation.tsapps/web/src/page/alerts/incident/index.tsapps/web/src/page/chat/page/implementation.tsapps/web/src/page/chat/page/index.tsapps/web/src/page/code-review/implementation.tsapps/web/src/page/code-review/index.tsapps/web/src/page/dashboards/list/implementation.tsapps/web/src/page/dashboards/list/index.tsapps/web/src/page/security/run/implementation.tsapps/web/src/page/security/run/index.tsapps/web/src/page/security/run/run.scene.test.tsapps/web/src/page/security/tabs/implementation.tsapps/web/src/page/security/tabs/index.tsapps/web/src/page/service-map/implementation.tsapps/web/src/page/service-map/index.ts
2b63ff8 · Updated on every push. Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.
🍁 Maple PR previewNote Preview resources were removed when the preview label came off. Final commit |
The app evaluated every page module before init. Each page now keeps only its schemas, routes and key in index.ts; the rest moves to implementation.ts, which loads on first entry or link intent. The route's page code loads at init beside the session check, and the open page's Subscriptions run in fixed registry slots.
…e page code loads
…undle The page chunk only started downloading after init, so on a real network a cold load showed the skeleton for its round trip. boot.ts now imports the route's page code right after Clerk starts. Every page entry loads through the same shared import in page/code.ts, so the registry's loadPageCode picks up the started load instead of fetching again.
2b63ff8 to
021c2bb
Compare
Maple review🟡 Confidence 6/10 · needs attention Every page splits into a lazy
Before merge
Fixed since the last review
Production impactOpen errors in the changed files
After this merges, Maple checks whether they stop. Production traffic of the changed files (last 7 days)
What was checked
Observability coverage: 2 of 2 changes observable
Files not reviewed (3)The review ended before it read these diffs, so nothing above vouches for them.
|
Chrome holds a dynamic import of a module that the app's own graph also imports until that whole graph has loaded. On the preview the route's page chunk was requested at about 1.04 s at 4x CPU, after init, the same as with no early start. A static import puts page/code.ts in boot's own graph, so the page chunk starts beside the app bundle.
Maple review🟢 Confidence 10/10 · safe to merge Since the last review the only change is
Production impactOpen errors in the changed files
After this merges, Maple checks whether they stop. Production traffic of the changed files (last 7 days)
What was checked
Observability coverage: 1 of 1 changes observable
|
Problem
In prd every cold dashboard load spends about 0.7 s (p50) to 2.4 s (p90) after the HTML before the app's
initruns (maple.pageload.init_ms: p50 805 ms, p75 1339 ms, p90 2472 ms, 179 loads, 2026-10-27 to 2026-10-29). Every data read waits forinit.Cause
apps/web/src/page/registry.ts:18-92(on main) statically imports all 75 page modules. Eachindex.tsimports the page's update, view, commands and subscriptions. So the startup graph holds every page: 307 chunks, 2724 KB gzip, 10.0 MB raw.init. Locally that is 231 ms at 1x CPU and 1247 ms at 4x.Fix
index.tsnow holds only its entry:definePage(id, { Model, Message }, { routes, key })andentry.lazy(pageCode.<Id>)(the shared import inpage/code.ts).implementation.ts(implementPage(entry, spec)). This is option (c) ofdocs/foldkit-decisions/s2-bundle.md. 74 pages were split by a codemod and/mcpby hand.loadPageCode(page/registry.ts).updateandviewread the loaded code; a page slot exists only once its code is loaded.update.tsloadPage): when the route's page code is missing, the open page is left and the code loads once (Model.pageCode:Ready | Loading | Failed). The skeleton shows meanwhile; the page enters when the code arrives.boot.ts(index.html's first script) starts the route's page code right after Clerk, beside the app bundle.page/code.tsholds every page's import and a path table that mirrorsroute/routers.ts. Each page'sindex.tsregisters its loader there, so the registry'sloadPageCodereuses the import boot started and never fetches twice.import()of a module the app's own graph also imports until that whole graph has loaded. With a dynamic import the page chunk was requested at about 1.04 s at 4x CPU on the preview, after init, the same as with no early start. Static, it is requested at about 0.4 s.init(main.ts) still asks for the route's page code besideLoadClerk/CheckSession; that picks up the started import.page.0...page.23), slot i for the page's i-th Subscription. Restart and keep-alive rules are the same per Subscription. A page with more Subscriptions than slots fails to load, so it cannot drop one silently (max today: 15).LoadPageCodeis kept as a span withmaple.page.idandmaple.page.code_for_preload.init.Before / After
Bundle (local, production
vite build, static graph fromindex.htmlandboot, measured before the rebase):Local, signed-in Home. Production builds served from disk with gzip. Self-hosted session stubbed, other API calls 503. Headless Chrome, 9 runs per row (7 for warm 4x), interleaved, medians. "init" is the app's first render; "page" is when the Home page body replaces the skeleton. Local numbers, no network latency.
boot.ts. Locally the page gained less than init because the page chunk's fetch was on the critical path after init.page/code.ts(about 30 KB gzip with the Clerk boot code). It downloads in parallel with the Schema chunk (58 KB gzip) boot already needed.Preview (not prd). Cold, signed-in loads on app-pr-1946 (head 8e82ad5) against a fresh baseline preview of main at 0827fd4 (#1963, an empty commit, closed after the runs). Headless Chrome, a new browser context per load (no cache, saved session), CPU throttled with CDP, real network. Interleaved, 8 loads per row, medians. 0 failed loads of 96. "init" is
maple.pageload.init_mson thepageload <Page>spans in Maple (deployment.environment=pr-<n>), matched to each load by time, all 96 matched. "first render" is whenmain#main-contentfirst exists. "body shows" is when it stops being the loading skeleton.How to verify after deploy
Boot timing per release, prd (expect
init_p50to drop with the release):The page code load on the boot path (when it ends relative to the pageload):
Tests
apps/web/src/page/code.test.ts, against the real route parser and registry:page/code.ts, andloadPageCodereuses the import boot started.apps/web/src/page-code.test.ts, with a fresh registry:initasks for the route's page code beside the session check.loadEveryPage). That also enforces the slot count.Follow-ups
route/routers.ts.code.test.tsfails if a page route maps elsewhere or a page has no path; a second route added to an existing page without a path only loses the early start.@maple/domain/httpschema construction is still about 180 ms of eval at 4x CPU, because the API clients need the whole contract at start.indexand pull its update and view back into startup. Examples:logs/list/message.ts→logs/detail,traces/detail/model.ts→span-panel,service-map/message.ts→service-map/map, and onboarding quick-start →integrations/embed. Pointing them at the child'smodel/messagemodules would shrink startup further.import.meta.hot) loads every page before start, because a restored Model skipsinit. So the Loading and Failed paths only run in builds and tests.🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need.