Skip to content

🤖 perf: load the agent interface status view only with the view - #7515

Merged
ThomasK33 merged 3 commits into
mainfrom
perf/7510-lazy-status-view
Oct 25, 2026
Merged

ThomasK33 merged 3 commits into
mainfrom
perf/7510-lazy-status-view

Conversation

@ThomasK33

@ThomasK33 ThomasK33 commented Oct 25, 2026 •

Copy link
Copy Markdown
Member

Fixes #7510

Summary

With the Agent interface view off (the default), the workspace page no longer downloads the artifact frame code. ChatPane now loads AgentInterfaceStatusView through a module-level React.lazy inside LazyFeature, and renders it only when the view is "status". The page's static chunk set drops by 22,389 B brotli. Nothing changes when the experiment is on.

Background

#7455 added <AgentInterfaceStatusView> to ChatPane with a static import. The view returns null unless the view is "status", but the import still pulled ArtifactViewer, SandboxedArtifactFrame and the artifact renderers into the page's static closure. Since #7455, the VM Lighthouse seeded-desktop LCP median rose from 1560-1570 ms to 1600-1651 ms.

Implementation

  • ChatPane.tsx: the import becomes React.lazy(() => import(".../AgentInterfaceStatusView")) at module top level. A small LazyStatusView component in ChatPane.tsx holds the open condition (view === "status") and the LazyFeature, so a closed view never fetches the chunk (AGENTS.md "Module Imports" exception). The condition sits in that component and not in ChatPaneContent, because one more branch there fails Quality / CRAP (CC 233 -> 234). The view keeps its place before the scrollport, so Tab still reaches the page before the composer. It still gets key, view, dockRef and composerApiRef.
  • AgentInterfaceStatusView.tsx is unchanged. Its own view !== "status" check is now always false, and I kept it to avoid touching a file outside the clearance.
  • WorkspaceMenuBar.tsx is unchanged. Its AgentInterfaceViewToggle does not reach the frame: the head build's page set has no SandboxedArtifactFrame source.

Validation

Method: I built each tree the same way on one host (bun 1.4.3: make src/version.ts, bun x vite build, bun scripts/precompress-static.ts dist). The page chunk set is main-*.js plus the chunk that holds AIView.tsx (App.tsx starts it on boot), closed over static import … from "./x.js" edges between built chunks. Each chunk counts its .br size, or its raw size when precompress-static skipped a tiny file.

tree commit chunks sum (br) mermaid-LQXJBOYN-*.js (br) SandboxedArtifactFrame in set
before #7455 61e9f05 16 823,290 B 238,977 B no
merge-base fbbce35 18 851,463 B 252,078 B yes (13,862 B chunk)
this PR b88f2ef 17 829,074 B 241,420 B no

Gates (declared by the perf owner before measurement):

  1. PASS. The page chunk set no longer contains SandboxedArtifactFrame sources. Base set: 18 chunks, including SandboxedArtifactFrame-*.js. Head set: 17 chunks, without it. 35 sources left the set and none were added. A new 2,732 B artifacts-*.js chunk now holds artifactDocument.ts and its helpers. The page already loaded them inside the frame chunk, and agentInterfaceView.ts still needs them.
  2. PASS. The sum is 22,389 B lower (gate: at least 10,000 B). Without the mermaid chunk it is 11,731 B lower.
  3. PASS. ChatPane has 0 React Compiler errors at base (5 functions compiled) and head (6, the new LazyStatusView included). make check-react-compiler passes.
  4. PASS. The ChatPane, ArtifactsTab and first-load bun tests pass (457), and tests/ui/chat/agentInterfaceStatusView.test.ts passes.

Guard: the first commit adds the workspace page's static imports do not reach the artifact frame to src/browser/rendererFirstLoad.test.ts. It fails on main (main has the bug) and passes with the fix. Mutation: when ChatPane imports AgentInterfaceStatusView statically again, the guard fails.

Mermaid chunk attribution: mermaid-LQXJBOYN-*.js is a Rollup shared chunk that also holds ChatPane and WorkspaceMenuBar, and the page loads it statically. From 61e9f05 to the merge-base it gained 28 sources, mostly the artifact viewer stack that AgentInterfaceStatusView pulled in (ArtifactViewer, the Code/Csv/Diff/Image/Json/Markdown renderers, useArtifactInteractions, diffParser). This PR removes that stack, so the chunk drops by 10,658 B. It stays 2,443 B above pre-#7455. That remainder is code the page uses (AgentInterfaceViewToggle, agentInterfaceView.ts, useArtifactsRefreshTick) plus unrelated later growth in MessageRenderer.tsx, machineTurnPrompts.ts and ChatPane. It needs no change here.

Dogfood: with the experiment off nothing is visible, and the bytes above are the proof. With the experiment on, I started make dev-server-sandbox, created a local workspace, turned on artifacts and artifacts-agent-interface, and wrote a status.html artifact. The status view appeared at 1800 px and 390 px. Switching to Chat unmounted it, and switching to Status mounted it again.

Status view, experiment on, 1800 px

Status view, experiment on, 390 px

Risks

Low. The first switch to the status view in a session now waits for one small chunk. The transcript is already invisible then, so the pane is blank for that load instead of showing the view's own "Loading…" line. A failed chunk load shows LazyFeature's Reload message in place of the page.


Generated with xum • Model: anthropic:claude-opus-5-5 • Thinking: high • Cost: $5.47

Fails on main: ChatPane statically imports AgentInterfaceStatusView, which
reaches ArtifactViewer and SandboxedArtifactFrame. The next commit fixes it.
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-25T19:17:04.227245Z b88f2ef Manual request
🔒 Security Review ✅ Completed 2026-10-25T19:17:47.549077Z b88f2ef Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actions

github-actions Bot commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

🟢 e2e stories (Haiku): 14 passed

27 agent steps · 12 replayed from cache · 15 model calls · 45.8k tokens (26% cached)
Spend: $0.09 of the $1.00 cap (proxy ledger)

All 14 tests in 9 files
Test Agent Time
🟢 chatRestart.e2e.ts · 1 passed 2 steps · 1 call 7.1s
🟢 a chat survives a restart of the server 2 steps · 1 call 7.1s
🟢 compaction.e2e.ts · 1 passed 3 steps · 1 call 9.6s
🟢 /compact replaces the old chat with a summary 3 steps · 1 call 9.6s
🟢 pluginTrustRestart.e2e.ts · 1 passed 4 steps · 2 calls 11.3s
🟢 a trusted plugin hook stays trusted after the server restarts 4 steps · 2 calls 11.3s
🟢 settingsRoundTrip.e2e.ts · 1 passed 3 steps · 1 call 11.6s
🟢 a chat survives trips through Settings 3 steps · 1 call 11.6s
🟢 sidebarPerWorkspace.e2e.ts · 1 passed 4 steps · 1 call 4.6s
🟢 a new workspace starts with its right sidebar collapsed while another keeps it open 4 steps · 1 call 4.6s
🟢 smoke.e2e.ts · 1 passed 2 steps · 1 call 2.4s
🟢 the agent opens the playground workspace 2 steps · 1 call 2.4s
🟢 streamErrors.e2e.ts · 1 passed 1 step · 1 call 6.5s
🟢 stream errors show in the chat, and the chat recovers 1 step · 1 call 6.5s
🟢 todoNudge.e2e.ts · 1 passed 2 steps · 1 call 2.8s
🟢 the agent finishes open TODO items after the turn-end nudge 2 steps · 1 call 2.8s
🟢 touchAlignment.e2e.ts · 6 passed 6 steps · 6 calls 22.0s
🟢 the Settings close button is level with the title on a touch screen 390px wide 1 step · 1 call 3.9s
🟢 the Settings close button is level with the title on a touch screen 768px wide 1 step · 1 call 4.4s
🟢 Backup settings checkboxes are small and level with their labels on a touch phone 1 step · 1 call 4.6s
🟢 the heartbeat checkbox is small and level with its label on a touch phone 1 step · 1 call 2.9s
🟢 a reply's model and time stay on one line on a touch phone 1 step · 1 call 2.9s
🟢 the workspace actions menu stays on the title row on a touch phone 1 step · 1 call 3.3s

e2e 0.20.0 · 1m 21s · web · run artifacts

🟢 e2e Electron stories (Haiku): 3 passed

3 agent steps · 3 model calls · 8.0k tokens (22% cached)
Spend: $0.02 of the $1.00 cap (proxy ledger)

All 3 tests in 3 files
Test Agent Time
🟢 electron/deepLink.e2e.ts · 1 passed 1 step · 1 call 5.2s
🟢 a deep link of a second launch starts a chat in the running app 1 step · 1 call 5.2s
🟢 electron/menuBar.e2e.ts · 1 passed 1 step · 1 call 5.3s
🟢 the workspace menu bar is the desktop title bar 1 step · 1 call 5.3s
🟢 electron/smoke.e2e.ts · 1 passed 1 step · 1 call 8.4s
🟢 Xum Electron opens the playground workspace 1 step · 1 call 8.4s

e2e 0.20.0 · 20.9s · electron · run artifacts

🟢 e2e agent repros (Haiku): no tests selected

Spend: $0.00 of the $1.00 cap (proxy ledger)

e2e 0.20.0 · 5.3s · 2 targets (web, phone) · run artifacts

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

b88f2ef moves the status view's open condition from ChatPaneContent into a small LazyStatusView component in ChatPane.tsx, because one more branch in ChatPaneContent failed Quality / CRAP. Behavior is the same as f36669d.

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: b88f2ef1d2

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

Retry: the code review on b88f2ef has shown "Running" since 18:15Z. The head is unchanged.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🚀

Reviewed commit: b88f2ef1d2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: b88f2ef1d2

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@ThomasK33

Copy link
Copy Markdown
Member Author

Perf owner: merge record for #7515 (fixes #7510).

  1. Final commit: b88f2ef1d2. Required, Codex Comments and Quality / CRAP pass on it. Codex code review ("Didn't find any major issues", reviewed b88f2ef1d2) and security review are clean. 0 review threads. Codex rounds: 3 (round 2 hung, round 3 was a bare retry on the same head).
  2. Gates: the frame chunk (SandboxedArtifactFrame) leaves the workspace page's static closure. Page static chunks: 851,463 -> 829,074 B brotli (-22,389 B, target -10,000 B). ChatPane: 0 React Compiler errors at base and head. 457 bun tests plus tests/ui/chat/agentInterfaceStatusView.test.ts pass. Screenshots at 1800 px and 390 px are in the PR body.
  3. Pixel / Review is pending ("1 snapshot awaiting review"). It is not required. No story renders the status view (git grep finds none), and test-only PRs 🤖 tests: close the four clock lint gaps of the agent-loop ratchet #7490 and 🤖 refactor: skill-tool refinement rows and refine's journal reads use the session's layers #7507 show the same pending state today, so I do not treat it as caused by this change.
  4. Independent advisor (clean context): behavior equal (the view returned null unless view === "status" before, too). It raised Pixel (see 3) and one follow-up.
  5. Follow-up, not a blocker: the lazy view has a null Suspense fallback, so on the first switch to Status the status section is absent until the chunk loads (one chunk fetch). Owner: perf owner. Trigger: next change to AgentInterfaceStatusView or a user report of a blank first open; fix = a fallback that matches StatusPage's loading box.
  6. After merge I check the next VM Lighthouse cycle for the desktop seeded LCP level (ref 1607.3 ms).

Generated with xum • Model: anthropic:claude-opus-5-5 • Thinking: high

@ThomasK33
ThomasK33 added this pull request to the merge queue Oct 25, 2026
Merged via the queue into main with commit 47d2e4d Oct 25, 2026
63 of 66 checks passed
@ThomasK33
ThomasK33 deleted the perf/7510-lazy-status-view branch October 25, 2026 19:43
yermakoffivan pushed a commit to yermakoffivan/mux that referenced this pull request Oct 26, 2026
…equests) (coder#7521)

## Summary

Reverts `coder#7515`. A same-session VM Lighthouse A/B shows it made the
seeded workspace page slower on desktop: median LCP +72.5 ms (1615.0 ->
1687.5 ms, 6+6 ABBA, all runs quiet). The limit is +40 ms.

## Background

`coder#7515` made the status view lazy so the workspace page would stop
loading the artifact frame (`coder#7510`). The seeded page also loads the
right sidebar, and the right sidebar still imports the artifact stack
(`McpAppFrame.tsx:59` imports a constant from `SandboxedArtifactFrame`;
RightSidebar shares `useArtifactInteractions` and the viewers). So the
frame code still loads, only later: in the right-sidebar wave at about
335-380 ms instead of the early wave at about 150 ms, plus three new
shared chunks (33 -> 36 requests, +5.8 KB script). LCP equals TTI in
every run, so the later graph end moves LCP.

Details and per-run numbers:
coder#7510 (comment)

## Implementation

`git revert 47d2e4d`. ChatPane imports `AgentInterfaceStatusView`
statically again, and the `rendererFirstLoad.test.ts` guard added by
`coder#7515` goes too (on main the guard is false again, so it would fail).
`coder#7510` is reopened; the next attempt fixes the sidebar importers first
and gates on the seeded page's real request list plus a VM A/B.

## Validation

- `make static-check` passes locally.
- Expected VM result after merge: seeded desktop back to the
`cf7b78bd55` level (about 1604-1615 ms), 33 requests.

## Risks

Low. This restores the code that was on main until 19:43Z today. The
status view (experiment-gated) behaves the same either way.

---

_Generated with `xum` • Model: `anthropic:claude-opus-5-5` • Thinking:
`high` • Cost: `$1855.40`_

<!-- mux-attribution: model=anthropic:claude-opus-5-5 thinking=high
costs=1855.40 -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

🤖 perf: the workspace page loads the artifact frame chunk since #7455 (seeded desktop LCP +40 ms)

1 participant