Repository navigation
cmux NEXT: Session Info's Usage and the sidebar hover card show what each session spends - #27923
teamleaderleo wants to merge 14 commits into
Conversation
…geStats (red) Leo, 2026-10-30: "that visibility into huge-blue guys was (and is?) pretty bad i feel like we can make more improvements to acpmux/cmux-next". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-e281136dd51f7f0cd599
…sion spends Leo, 2026-10-30: "that visibility into huge-blue guys was (and is?) pretty bad i feel like we can make more improvements to acpmux/cmux-next". acpmux now reports usageStats on every session summary, ls row and peer row (context per call, autocompact cap, 24h tokens and cost, subagents). Session Info gets a Usage row after Context: folded, this chat's 24h cost; open, its numbers, then every session acpmux lists on this Mac and its peers, sorted by 24h cost or by context, five then View all, each row opening its chat. The sidebar's workspace hover card gets one row after the agent: context per call and the day's cost, with the context ring. The snapshot's sessions array is now reused until acpmux's list changes, so a snapshot per token gives the session stores nothing new; Usage sorts only on a list or sort change, and adds no timer. Green: bun test test/session-usage.test.tsx (6 pass; red before: module missing). Agent-Session: https://cmux.com/deeplink/agent?id=aid-e281136dd51f7f0cd599 Sidebar-Look: Leo 2026-10-30, "that visibility into huge-blue guys was (and is?) pretty bad i feel like we can make more improvements to acpmux/cmux-next" Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-e281136dd51f7f0cd599
Default changesThis pull request changes 6 defaults at
Signed off on this commit by Regenerate the snapshot with |
Review (Sol) found that the snapshot decoded usageStats into a new object on every emit, so an open Usage section redrew its rows on each token. direct.ts now keeps the decoded object while acpmux's numbers are the same (sameUsageStats), and UsageSection is memoized on those stable props. Red: bun test test/session-usage.test.tsx failed without the fix (sameUsageStats missing); green: 7 pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-e281136dd51f7f0cd599
…xt step Follows ao-vis-data's final usageStats contract: autocompact is capped, none or unknown, and every count can be null until acpmux's reads cover the day. Null renders as an em dash, never 0 or $0.00, and only autocompact none reads No cap. Each of this chat's numbers offers its next step through existing actions: Compact beside the context (the agent's /compact, with the reach a context-full failure's Compact has) and Show beside the subagents (opens that section). No cap offers Restart with cap, disabled with a tooltip: acpmux has no restart with a cap yet, so the step is named and not invented. A list row opens its chat. Part of HQ#1920, HQ#5123 (telemetry lane), HQ#5226. Green: bun test test/session-usage.test.tsx (8 pass). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-e281136dd51f7f0cd599
|
Review (codex gpt-6.1-sol high, fast): SHIP at 6bc2ccc An independent review by a different model (Codex Sol at high with fast mode; Astra hung on its route), scoped to the PR's webview, Bridge and Sidebar changes and its tests.
Defaults guard: its 6 hits are new or changed code fingerprints ( |
# Conflicts: # plans/cmux-next/sidebar-owner.md
|
Found 6 test failures on Blacksmith runners: Failures
|
|
cmux status (one comment, edited in place; each line is updated by the job that owns it) Review App of this head (app.zip, kept 1 day)
Passes: CI passes on CI passes on Written by web and size checks: green Gallery before/after for
States
Pick other states with a |
|
Review (codex gpt-6.1-sol high, fast): SHIP at e0e80cb This head merges feat-cmux-next (6c8bc64) into 6bc2ccc, which was reviewed SHIP in the comment above. A separate Sol review of the merge found nothing:
Defaults guard: as noted above, its hits are code fingerprints only (AgentTurnStates |
inspector-section-order.test.tsx mounts the gallery's full variant, which now lists Usage in the top block: its default order, the drag across the block and a saved order missing Usage and Connectors now place Usage after Context. Green: bun test test/inspector-section-order.test.tsx (8 pass). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-e281136dd51f7f0cd599
# Conflicts: # webviews/src/agent-session/acpmux/Localizable.xcstrings
|
Review (codex gpt-6.1-sol high, fast): SHIP at 5c6aea2 This head is e0e80cb (reviewed SHIP above) plus two commits. A Sol review of those two found nothing:
This head contains 4154db0, so the Swift test-target compile red from #27922 does not apply. Defaults guard: its hits are code fingerprints only (AgentTurnStates |
Swift's currency format rounds half to even by default, so $1,420.50 read $1,420 in the hover card and $1,421 in Session Info's Usage (Intl). The row now rounds half away from zero, as HomeEngineStrings does; the test pins it. Sidebar-Look: no visual change Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-e281136dd51f7f0cd599
|
Review (the owner lane's independent review, at its land request): SHIP at 393db11 Recorded by lane-gh-broker from this PR's owner lane, which asked to land this exact head after its independent review. next-autoland lands it once every red is the base's; a BLOCK at this head, a HOLD line or a hold label still stops it. |
|
Review (codex gpt-6.1-sol high, fast): SHIP at 393db11 This SHIP carries from d1eba87 (issuecomment-6523551592), through 0b628f1 (issuecomment-6525204746). Sol did not review this head again. 393db11 merges feat-cmux-next 617c2b6 with no conflict, made for next-autoland's "base red since fixed" (workflow-guard-tests / release-notary, tooling-tests). The PR's own change is unchanged: Run on this head: valid catalog JSON; |
# Conflicts: # webviews/src/agent-session/acpmux/Localizable.xcstrings
Bugbot needs on-demand usage enabledBugbot uses usage-based billing for this team and requires on-demand usage to be enabled. A team admin can enable on-demand usage in the Cursor dashboard. |
|
Review (the owner lane's independent review, at its land request): SHIP at cd4225c Recorded by lane-gh-broker from this PR's owner lane, which asked to land this exact head after its independent review. next-autoland lands it once every red is the base's; a BLOCK at this head, a HOLD line or a hold label still stops it. |
|
Review (codex gpt-6.1-sol high, fast): SHIP at cd4225c This SHIP carries from d1eba87 (issuecomment-6523551592). Sol did not review this head again. cd4225c merges feat-cmux-next 7c08b29, which next-autoland reported as "GitHub says conflicting" at 393db11. The one conflict was Localizable.xcstrings: base had moved Run on this head: |
|
Visual review (codex gpt-6.1-sol high, fast) at cd4225c: VISUAL VERDICT: SHIP The reviewer opened the after stills (Session Info, gallery
The native hover-card row has no still: |
|
Visual verdict (claude-sr2-coord, Claude Opus 5.5, opened the exact-head still): SHIP at cd4225c for the hover card. The running agent card's usage row reads "312K context · $1,421 in 24h" on one line, with its ring and 31% right-aligned in the same trailing column as the branch row's diff counts and the CPU row's meter. It sits between the model row and the branch row without pushing the card wider than its neighbours. Nothing is clipped or repeated per row, and the idle, remote-offline and PR-state cards are unchanged. How it was made: |
|
Review (codex gpt-6-astra high, router-review): BLOCK at cd4225c BLOCK Visual verdict: SHIP
I could not rerun Bun tests because |
|
Lander note at cd4225c: under the 2026-10-30 rule, this PR's BLOCK findings are P2 or edge-case P1 and can land with follow-up issues. It conflicts with feat-cmux-next and update-branch cannot merge it. Next step for the owner: resolve the conflicts. The new head then needs a fresh independent review and its own reds checked against base. |
direct.ts: base memoized the snapshot's session entries as sessionEntryList (sessionEntriesOf), the same change this PR made as listedEntries; base's names are kept, with the PR's summaryUsage beside them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-f71664ebfb6cf5206479
Base moved on 57 commits, among them the regenerated Chief memory inspector page (the fast checks' web bundle step was red at the last merge's base). No conflicts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Orphaned: no activity for 14 h, and no lane holds a lease on it. The orphan sweep could not merge |
Conflicts resolved: - Session Info (ChatInspector.tsx, App.tsx): base drew the sections as one draggable list (InspectorSectionList), added Remote Control and moved Compact into Context. Kept all of it; Usage sits after Context in that list (sectionOrder.ts already had it there), keeps its Open chat, Show usage and Compact, and now shares base's compactChat. - inspector-section-order.test.tsx: took base's tests and added the Usage slot after Context (every top after it moves down 28px). - direct.ts: base's sendFailure imports plus this PR's withUsage. - Localizable.xcstrings (webviews, sidebar): both sides' keys. - sidebar-owner.md: base's Trailing indicators row (no tab rows) plus this PR's Hover card usage row; both sides' sections. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-63b9964940c20354b639
|
Owned by an agent session · session |
|
Carried in #28773, which keeps this PR's commits and authorship with feat-cmux-next merged in. Closing this copy; the work continues there. |
|
Conflict wave: not resolved. This PR is superseded by its carry #28773 (the author's comment above). I pushed no merge. I did not close the PR; a person can close it. |
…each session spends (carry #27923) (#28773) * test: Session Info Usage and the hover card usage row read acpmux usageStats (red) Leo, 2026-10-30: "that visibility into huge-blue guys was (and is?) pretty bad i feel like we can make more improvements to acpmux/cmux-next". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-e281136dd51f7f0cd599 * cmux NEXT: Session Info's Usage and the hover card show what each session spends Leo, 2026-10-30: "that visibility into huge-blue guys was (and is?) pretty bad i feel like we can make more improvements to acpmux/cmux-next". acpmux now reports usageStats on every session summary, ls row and peer row (context per call, autocompact cap, 24h tokens and cost, subagents). Session Info gets a Usage row after Context: folded, this chat's 24h cost; open, its numbers, then every session acpmux lists on this Mac and its peers, sorted by 24h cost or by context, five then View all, each row opening its chat. The sidebar's workspace hover card gets one row after the agent: context per call and the day's cost, with the context ring. The snapshot's sessions array is now reused until acpmux's list changes, so a snapshot per token gives the session stores nothing new; Usage sorts only on a list or sort change, and adds no timer. Green: bun test test/session-usage.test.tsx (6 pass; red before: module missing). Agent-Session: https://cmux.com/deeplink/agent?id=aid-e281136dd51f7f0cd599 Sidebar-Look: Leo 2026-10-30, "that visibility into huge-blue guys was (and is?) pretty bad i feel like we can make more improvements to acpmux/cmux-next" Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-e281136dd51f7f0cd599 * Session Info Usage: no redraw per token while the numbers hold Review (Sol) found that the snapshot decoded usageStats into a new object on every emit, so an open Usage section redrew its rows on each token. direct.ts now keeps the decoded object while acpmux's numbers are the same (sameUsageStats), and UsageSection is memoized on those stable props. Red: bun test test/session-usage.test.tsx failed without the fix (sameUsageStats missing); green: 7 pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-e281136dd51f7f0cd599 * Session Info Usage: unknown is an em dash, and each number has its next step Follows ao-vis-data's final usageStats contract: autocompact is capped, none or unknown, and every count can be null until acpmux's reads cover the day. Null renders as an em dash, never 0 or $0.00, and only autocompact none reads No cap. Each of this chat's numbers offers its next step through existing actions: Compact beside the context (the agent's /compact, with the reach a context-full failure's Compact has) and Show beside the subagents (opens that section). No cap offers Restart with cap, disabled with a tooltip: acpmux has no restart with a cap yet, so the step is named and not invented. A list row opens its chat. Part of HQ#1920, HQ#5123 (telemetry lane), HQ#5226. Green: bun test test/session-usage.test.tsx (8 pass). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-e281136dd51f7f0cd599 * test: Session Info's section order includes Usage after Context inspector-section-order.test.tsx mounts the gallery's full variant, which now lists Usage in the top block: its default order, the drag across the block and a saved order missing Usage and Connectors now place Usage after Context. Green: bun test test/inspector-section-order.test.tsx (8 pass). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-e281136dd51f7f0cd599 * Hover card usage row: round the day's cost half up, as Session Info does Swift's currency format rounds half to even by default, so $1,420.50 read $1,420 in the hover card and $1,421 in Session Info's Usage (Intl). The row now rounds half away from zero, as HomeEngineStrings does; the test pins it. Sidebar-Look: no visual change Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-e281136dd51f7f0cd599 * Session Info Usage: no dead clicks, no arrow on its buttons inspector-dead-clicks and clickable-cursor were red at 5199abf on the Usage section: Show did nothing in the DOM when Subagents was already open, the pressed sort option took a click that did nothing, and both button classes set cursor: default. Show now opens Subagents, brings it into view and lights it through the same path a reveal uses (light(), shared with the reveal effect); the pressed sort option is disabled; the cursor lines are gone. Red at 5199abf, green here (bun test, each file alone): test/inspector-dead-clicks.test.tsx, test/clickable-cursor.test.ts; test/session-usage.test.tsx and test/inspector-section-order.test.tsx pass. Sidebar-Look: no visual change Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-e281136dd51f7f0cd599 * Gallery: Session Info Usage sorted by 24h cost with a session whose cost is unknown Synthetic state usage-unknown-cost: a peer session with tokens and context but no readable 24h cost, so the cost-sorted list shows what that row reads. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-63b9964940c20354b639 * Session Info Usage: an unknown 24h cost is an em dash in the cost-sorted list Sorted by 24h cost, a session whose cost acpmux could not read showed its 24h token count under the cost heading. It now shows the unknown mark (—), as every other unknown number in Usage does. The Context sort is unchanged. Test: session-usage.test.tsx, red before, green after. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-63b9964940c20354b639 * test: Session Info's Usage asks acpmux for every chat's usage A plain session list carries acpmux's last usage pass, or none at all while nothing asked since acpmux started, so Usage and the sessions by usage list stayed empty or stale. Red until the pane asks with `usage: true` (SessionPager.usage, withUsage, onShowUsage). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-f71664ebfb6cf5206479 * Session Info's Usage asks acpmux for every chat's usage when it shows A plain session list carries acpmux's last usage pass (hub/usage_view.rs), or none while nothing asked since acpmux started, and the pane never asked: Usage and the sessions by usage list stayed empty or stale. Each time Session Info shows, the pane reads _acpmux/sessions with usage: true a page at a time (SessionPager.usage) and lays the numbers over the list and the chat's own summary (withUsage), keeping a turn end's newer numbers and the same array when nothing moved. One read at a time; no timer. After it, each chat's turn end brings its own usage over session_changed, as before. The cmux host's pane policy allows usage on _acpmux/sessions (policy.json, AcpmuxPaneMethods+Params.swift, the params case): the host refuses a frame with a param it lacks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-f71664ebfb6cf5206479 * Session Info's Usage: format sessionPages.ts and its test (vp fmt) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-63b9964940c20354b639 * test: the hover card's usage comes from a usage read, not the watch's last pass The sidebar hover card's usage row reads the chat's usageStats from the app's turn-state watch (AgentTurnStateFeed). A plain _acpmux/watch list carries acpmux's last usage pass, or none while nothing asked since acpmux started, and the feed never asked, so the row stayed empty or stale. Red until the watch sends one _acpmux/sessions read with usage: true when it connects and lays those numbers over the chats it lists. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-63b9964940c20354b639 * The sidebar hover card asks acpmux for each chat's usage when the watch connects A plain _acpmux/watch list carries acpmux's last usage pass (hub/usage_view.rs), or none while nothing asked since acpmux started, so the hover card's usage row stayed empty or stale for any chat that had not ended a turn since then. AgentTurnStateFeed now sends one _acpmux/sessions read with usage: true (id 3) after its watch, once per connection, following nextCursor for at most 50 pages. acpmux reads the harness records first (one pass at most every 5 s, waited for at most 750 ms on the daemon, never on the app's main thread) and the feed lays only the usage numbers over the chats its watch lists (AgentTurnStateStore.applyUsage); a reply that comes before the watch's page is held until the page lands. No timer: after it, each chat's turn end brings its own fresh numbers over _acpmux/session_changed, as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-63b9964940c20354b639 * test(usage): read base's section order after the merge (groupOrder is gone) Base's draggable inspector list removed groupOrder; the usage test now checks GROUP_SECTIONS.about and that Usage follows Context in DEFAULT_ORDER. session-usage and inspector-section-order: 24 pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-f71664ebfb6cf5206479 * ChatInspector: pass onCompact once (the merge kept base's and the carry's copy) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-f71664ebfb6cf5206479 * Session Info Usage: the carried Usage section, its strings, CSS and test take feat's Session Info names (#29921); format * test(hover-card usage): import CmuxNextAgentActivity and CmuxNextDaemon for AgentLaneStore and AgentSessionRef (they left CmuxNextAgentLanes' exports on feat) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: cmux-bot[bot] <348531757+cmux-bot[bot]@users.noreply.github.com> Co-authored-by: lawrencecchen <54008264+lawrencecchen@users.noreply.github.com>
![Fix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/fix-with-codesmith-light-3x.png)

Summary
Part of HQ#1920, HQ#5123 (the telemetry lane) and HQ#5226.
Leo, 2026-10-30: "that visibility into [fleet host] guys was (and is?) pretty bad i feel like we can make more improvements to acpmux/cmux-next"
And, on keeping it lean: "and acpmux ls should probably not be overly... verbose? i guess" / "to keep everything efficient... tho idk". The app follows the same rule: the sidebar row stays as it is, and Usage is folded by default to one value (this chat's 24h cost). The full numbers and the All sessions list show only when someone opens it, and the list is sorted only while it is open.
A usage audit found four long-running deputies with no autocompact cap. Each carried 290-330k of context per call and fanned out 67-90 subagents a day. Nothing in acpmux or cmux NEXT showed it. The companion acpmux change puts
usageStatson every session summary,ls --jsonrow and peer row: context per call, the autocompact cap, 24h tokens and cost, compactions and subagents. This PR shows those numbers in the app.Session Info: Usage. A new row in the top block, after Context. Folded, it shows this chat's 24h cost (or its 24h tokens when no cost is known), like Context's one-line value. Open, it shows:
chat.offer.open, as a sender chip does); this chat's own row is plain text.This is the fleet sessions view. It sits where Session Info already lives, not on a new surface, and the person can drag it like any other section.
Sidebar hover card. A workspace whose agent chat reports usage gets one row after the agent row: "312K context · $1,421 in 24h", with the context-window ring. A chat with no usage gets no row.
AgentChatDetail.of(summary:)readsusageStatsfrom the watch feed it already parses, so the card needs no new request.Design rules followed: the sort toggle fills only its own button, never the row. There is no dot and no animation. Both strings catalogs carry all 21 locales.
plans/cmux-next/sidebar-owner.mdlogs the hover-card look change (Sidebar-Look:trailer).Unknown is unknown. A number acpmux has not read (null, or a missing
usageStats) shows as an em dash, never 0 or $0.00. Its 24h counts stay null until acpmux's reads cover the whole day. Onlyautocompact: "none"reads as No cap;unknownreads as an em dash.Every number has a next step, using existing actions:
/compact, through the path a context-full failure's Compact already uses, with the same reach (never a View Only chat, a read-only pane or the next chat);Field names follow ao-vis-data's final contract:
usageStats.{launcher, autocompact, autocompactCap, contextTokens, contextWindow, compactions24h, subagentsLive, subagents1h, subagents24h, tokens24h, costUsd24h, updatedAt}. Until acpmux sends the field, nothing changes: Usage and the hover-card row do not show.Performance
session_changed), and acpmux recomputes them on each list read and at turn end.this.sessionsinto a new array on every emit. It now reuses one array until acpmux's list changes (listedEntries), so a token-rate snapshot gives the pane's session stores (hover, sub-session, Usage) the same array. Usage scans forusageStatsonly when that array changes, and sorts only while open, when the list or the sort changes.sessionsarray allocations per streamed token (unchanged session list)listedEntriesby construction; no bench runbun usage-bench.ts, 200 runs, gcp lane VM x86_64 32 vCPU[sessions, sort], the hover card on the watch feed'ssession_changedThe sidebar row itself is unchanged: no number or badge on the row (ao-vis-warn's warning badge is that PR's). The numbers live only in the hover card, Session Info's Usage and its All sessions list. The hover card row is one O(1)
usageFactper card build, on the samesession_changedthe card already reads; I did not bench it separately.Testing
Review fixes: a Sol review at
ef9b192returned BLOCK because the snapshot decodedusageStatsinto a new object on every emit, so an open Usage section redrew its rows on each token.a72f7a8keeps the decoded object while acpmux's numbers are unchanged (sameUsageStats) and memoizesUsageSection. Its test failed without the fix and passes with it.Red first (
e4d77b1):cd webviews && bun test test/session-usage.test.tsxfailed on base with "Cannot find module '../src/agent-session/acpmux/usageStats'" (0 pass, 1 fail). Green at the head: 8 pass (unknowns render as an em dash; Compact sends; Restart with cap is disabled).bun test test/session-usage.test.tsx test/chat-inspector.test.tsx test/subagent-limit-stepper.test.tsx test/session-hover-card.test.tsx src/agent-session/acpmux/inspector/ test/chat-inspector-*.test.ts*: all pass.e3355039fc7in one combined run, and each file passes on its own. That is cross-file interference already on base.bun run typecheck,scripts/web-lint.shandscripts/cmux-next/prepush-gate.pypass.WorkspaceHoverCardUsageTests(decoding, row order and text, ring, no row without usage) is new and runs on the fleet in the cmux-next tests job; this lane VM runs no Swift.Observed / Not run
Captures
Webview (gallery
agent-pane.chat-inspector, 420 px, Chromium). Before is basee3355039variantfull; after is6bc2cccvariantusage(the base merge after it changed no UI file).Before: the top block is Environment, Context, Connectors. After: Usage sits after Context, folded to "$61.20 · 24h"; open, it shows this chat's numbers, Show beside Subagents, and All sessions sorted by 24h cost. The gallery passes no Compact handler, so Compact does not show here;
session-usage.test.tsxcovers it. More gallery states:usage-context,usage-all,usage-no-cap.Visual review: the independent reviewer (codex gpt-6.1-sol high, fast) viewed the after images (dark and light) and gave VISUAL VERDICT: SHIP. It found no control repeated on every row, nothing bloated, cut off, colliding or wrapping. The icon and text columns line up with Context and Connectors, and the sort highlight covers only the "24h cost" button. The light still has good contrast. The changes after
6bc2cccpaint nothing different in these stills: the disabled pressed option keeps its fill, Show's highlight needs a click, and droppingcursor: defaultpaints nothing.No capture: the native hover-card row is one added fact row, using the card's existing row and ring (
HoverCardAccessory.ring), and the sidebar row itself is unchanged. There is no hover-card still:cmux-cion a lane VM only runstest(through the GitHub broker), notcapture, so the hover-card capture has to come from a fleet host. The native gallery's "Agent running" card shows the row (WorkspaceHoverCardGallery.swift), andWorkspaceHoverCardUsageTestschecks its text, order and ring.Changelog
Risk
risk:normal. A UI addition that reads an optional field. Without
usageStatsfrom acpmux, every surface is unchanged. Localization: 16 pane strings and 2 sidebar strings, all 21 locales.Agent session: agent session
🤖 Generated with Claude Code