Skip to content

cmux NEXT: Session Info's Usage and the sidebar hover card show what each session spends - #27923

Closed
teamleaderleo wants to merge 14 commits into
feat-cmux-nextfrom
lane/ao-vis-ui
Closed

teamleaderleo wants to merge 14 commits into
feat-cmux-nextfrom
lane/ao-vis-ui

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 30, 2026 •

Copy link
Copy Markdown
Collaborator

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 usageStats on every session summary, ls --json row 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:

    • this chat's numbers: cost and tokens in the last 24h, context per call against its window, the autocompact cap ("No cap" when there is none), compactions, subagents (live, last hour, last 24h) and the launcher;
    • All sessions: every session acpmux lists on this Mac and its peers, sorted by 24h cost or Context with a two-option toggle (24h cost first). Each row shows its harness mark, title, host and the sorted value. Five rows show, then View all. A row opens that chat (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:) reads usageStats from 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.md logs 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. Only autocompact: "none" reads as No cap; unknown reads as an em dash.

  • Every number has a next step, using existing actions:

    • context per call → Compact: the agent's own /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);
    • subagents → Show: opens the Subagents section;
    • no cap → Restart with cap: shown disabled, with a tooltip, because acpmux cannot restart a session with an autocompact cap yet. The step is named here rather than built as a new subsystem;
    • a session in All sessions → clicking its row opens that chat;
    • the hover card's usage row → the card already opens its workspace on click, and from there Session Info's Usage has the actions above. The hover card itself gets no buttons.

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

  • No new timer, observer or animation loop. The numbers refresh on the session list acpmux already sends (watch and session_changed), and acpmux recomputes them on each list read and at turn end.
  • No per-token O(rows) work. Building the snapshot used to map this.sessions into 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 for usageStats only when that array changes, and sorts only while open, when the list or the sort changes.
metric before after delta harness or run link
snapshot sessions array allocations per streamed token (unchanged session list) 1 0 -1 direct.ts listedEntries by construction; no bench run
Usage list sort, 100 sessions (p50 / p95), on a list or sort change only n/a (no list) 0.011 / 0.021 ms new bun usage-bench.ts, 200 runs, gcp lane VM x86_64 32 vCPU
Usage list sort, 500 sessions (p50 / p95) none on base (no Usage list) 0.032 / 0.041 ms new same
Usage list sort, 2,000 sessions (p50 / p95 / max) none on base (no Usage list) 0.184 / 0.298 / 0.949 ms new same
work per streamed token for Usage and the hover card row none on base (no Usage list) 0 (no timer; the sessions array is the same object) none by construction: Usage recomputes on [sessions, sort], the hover card on the watch feed's session_changed

The 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) usageFact per card build, on the same session_changed the card already reads; I did not bench it separately.

Testing

Review fixes: a Sol review at ef9b192 returned BLOCK because the snapshot decoded usageStats into a new object on every emit, so an open Usage section redrew its rows on each token. a72f7a8 keeps the decoded object while acpmux's numbers are unchanged (sameUsageStats) and memoizes UsageSection. Its test failed without the fix and passes with it.

Red first (e4d77b1): cd webviews && bun test test/session-usage.test.tsx failed 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.
  • Direct-client tests run together (30 files): 233 pass, 11 fail. The same 11 fail the same way on the base e3355039fc7 in one combined run, and each file passes on its own. That is cross-file interference already on base.
  • bun run typecheck, scripts/web-lint.sh and scripts/cmux-next/prepush-gate.py pass.
  • Swift: 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

  • Observed: the webview tests, type check, web lint and the pre-push gate above.
  • Not run here: the Swift suites and a DEV build (no fleet client on this host). They run in CI.

Captures

Webview (gallery agent-pane.chat-inspector, 420 px, Chromium). Before is base e3355039 variant full; after is 6bc2ccc variant usage (the base merge after it changed no UI file).

before after
dark before dark after dark
light not captured: the job died on the shared API quota (no rerun, by the quota rule); the dark before shows the same layout after light

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.tsx covers 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 6bc2ccc paint nothing different in these stills: the disabled pressed option keeps its fill, Show's highlight needs a click, and dropping cursor: default paints 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-ci on a lane VM only runs test (through the GitHub broker), not capture, so the hover-card capture has to come from a fleet host. The native gallery's "Agent running" card shows the row (WorkspaceHoverCardGallery.swift), and WorkspaceHoverCardUsageTests checks its text, order and ring.

Changelog

  • Added: Session Info's Usage shows a chat's 24h cost, context per call, autocompact cap and subagents, plus every session on this Mac and its peers sorted by 24h cost or context. The sidebar's workspace hover card shows the agent chat's context and 24h cost.

Risk

risk:normal. A UI addition that reads an optional field. Without usageStats from acpmux, every surface is unchanged. Localization: 16 pane strings and 2 sidebar strings, all 21 locales.

Agent session: agent session

🤖 Generated with Claude Code

teamleaderleo and others added 2 commits October 30, 2026 03:46
…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
@github-actions

github-actions Bot commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Default changes

This pull request changes 6 defaults at 393db115dc90 (what everyone gets without configuring anything):

  • tunable-source.CmuxNextBridge/AgentTurnStates.swift:of: (none) -> "7979e505dd3f3a1b3e636b9f0ff7dce38ee14d023aa2d3e745881d4280a8617c"
  • tunable-source.CmuxNextBridge/AgentTurnStates.swift:of#: (none) -> "4fe0fd295a3d532ec8485939ba12d565699678372270f6ab11dc540e83599c03"
  • tunable-source.CmuxNextSidebar/Logic/WorkspaceHoverCardContent.swift:facts: "a4eddf6873407642f1d8d7244429e9f2b6cea0064e5c60c30892d040db03292f" -> "a33343ec1ac2bd353548a4fe91b02029f9a35936cb87fb52589398dca7285750"
  • tunable-source.CmuxNextSidebar/Logic/WorkspaceHoverCardContent.swift:usageFact: (none) -> "047135be601f3081743deae61de1bedf38350a8c753c019ea4b19242028c53fc"
  • tunable-source.CmuxNextSidebar/Strings.swift:usageContext: (none) -> "c506e575713a3f5b33c18fc98529ab89711ca882f6586301dab0fa6c246992c4"
  • tunable-source.CmuxNextSidebar/Strings.swift:usageCost: (none) -> "668db3b1916e5acb7ba49659ab02ad3ad79bcac99b9a3a320a65d6695cd32dfc"

Signed off on this commit by review (codex gpt-6.1-sol high, fast).

Regenerate the snapshot with python3 scripts/ci/defaults_guard.py snapshot.

@github-actions github-actions Bot added the risk:normal Risk tier (docs/ci/risk-tiers.md) label Oct 30, 2026
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
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

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.

  • At ef9b192: BLOCK, one finding. The snapshot decoded usageStats into a new object on every emit, so an open Usage section redrew its rows on each token. Fixed in a72f7a8: sameUsageStats keeps the decoded object while the numbers are unchanged, and UsageSection is memoized. A red/green test covers it.
  • At 6bc2ccc (that fix, plus ao-vis-data's final contract: autocompact capped|none|unknown, null counts render as an em dash, and the next-step actions Compact, Show and a disabled Restart with cap): no correctness findings. The focused tests pass 8/8. The reviewer could not run the type check in its read-only checkout; it passes locally at this head.

Defaults guard: its 6 hits are new or changed code fingerprints (AgentChatDetail.of, WorkspaceHoverCardContent.facts and usageFact, and two Strings helpers). No setting, tunable, flag or key default changed.

# Conflicts:
#	plans/cmux-next/sidebar-owner.md
@blacksmith-sh

blacksmith-sh Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

Found 6 test failures on Blacksmith runners:

Failures

Test View Logs
main.DeveloperIdAppTests.test_download_prints_the_active_profile_only/
test_download_prints_the_active_profile_only
View Logs
stubs: /System/Library/Frameworks/Security.framework/Versions/A/Security has no stub/
Security has no stub
View Logs
stubs: CoreFoundation.tbd: install-name /System/Library/Frameworks/
CoreFoundation.framework/Versions/A/CoreFoundation, missing 1: ['_CFRetain']/
CoreFoundation, missing 1: ['_CFRetain']
View Logs
stubs: CoreFoundation.tbd: install-name /System/Library/Frameworks/
CoreFoundation.framework/Versions/A/CoreFoundation, missing 1: ['_log2']/
CoreFoundation, missing 1: ['_log2']
View Logs
test_every_listed_hook_is_one_glaeda_released_with_the_check (main.SigningHooksInSt
epWithGlaedaTests.test_every_listed_hook_is_one_glaeda_released_with_the_check)/
test_every_listed_hook_is_one_glaeda_released_with_the_check (main.SigningHooksInSt
epWithGlaedaTests.test_every_listed_hook_is_one_glaeda_released_with_the_check)
View Logs
test_the_repository_highlights_validate (main.DigestTests.test_the_repository_highl
ights_validate)/
test_the_repository_highlights_validate (main.DigestTests.test_the_repository_highl
ights_validate)
View Logs

Fix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

@github-actions

github-actions Bot commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

cmux status (one comment, edited in place; each line is updated by the job that owns it)

Review d1eba87: HQ feed card · gallery before/after runs · checks

App of this head (app.zip, kept 1 day)

gh workflow run reload-build.yml -R manaflow-ai/cmux --ref feat-cmux-next -f tag=pr27923 -f ref=lane/ao-vis-ui -f platform=macos -f backend_mode=local

Passes: CI passes on cd4225c365.

CI passes on cd4225c365 (run 41088481532 attempt 1).

Written by scripts/ci/classify_failures.py (ci-failure-attribution.yml); signatures are its SIGNATURES table. A machine verdict is the runner's fault, not this PR's; yours means the failing file is one this PR changes, also red on main that main's latest full suite fails the same way, seen on other PRs that it failed on another pull request's run lately.

web and size checks: green

Gallery before/after for cd4225c: 16 states rendered, 16 images differ, 2502 more touched states not rendered. Images are in the run's artifact, not on this public PR.

gh run download 41088481494 -R manaflow-ai/cmux -n gallery-advisory-27923-cd4225c365ffdf977ce810d309d446740b632016 (then read gallery-review.json)

States
State Theme Status Diff Picked by
agent-pane.chat-inspector/usage Apple System Colors Light new 0% own ChatInspector.gallery.tsx
agent-pane.chat-inspector/usage Apple System Colors new 0% own ChatInspector.gallery.tsx
agent-pane.chat-inspector/usage-no-cap Apple System Colors Light new 0% own ChatInspector.gallery.tsx
agent-pane.chat-inspector/usage-no-cap Apple System Colors new 0% own ChatInspector.gallery.tsx
agent-pane.chat-inspector/usage-context Apple System Colors Light new 0% own ChatInspector.gallery.tsx
agent-pane.chat-inspector/usage-context Apple System Colors new 0% own ChatInspector.gallery.tsx
agent-pane.chat-inspector/usage-all Apple System Colors Light new 0% own ChatInspector.gallery.tsx
agent-pane.chat-inspector/usage-all Apple System Colors new 0% own ChatInspector.gallery.tsx
agent-pane.chat-inspector/full Apple System Colors Light changed 7.62% own ChatInspector.gallery.tsx
agent-pane.chat-inspector/full Apple System Colors changed 7.54% own ChatInspector.gallery.tsx
agent-pane.chat-inspector/workflow-running Apple System Colors Light changed 4.71% own ChatInspector.gallery.tsx
agent-pane.chat-inspector/workflow-running Apple System Colors changed 4.64% own ChatInspector.gallery.tsx
agent-pane.chat-inspector/workflow-finished Apple System Colors Light changed 4.47% own ChatInspector.gallery.tsx
agent-pane.chat-inspector/workflow-finished Apple System Colors changed 4.4% own ChatInspector.gallery.tsx
agent-pane.chat-inspector/workflow-agent-row-compact Apple System Colors Light changed 4.62% own ChatInspector.gallery.tsx
agent-pane.chat-inspector/workflow-agent-row-compact Apple System Colors changed 4.54% own ChatInspector.gallery.tsx
agent-pane.chat-inspector-surfaces/transcript Apple System Colors Light unchanged 0% own ChatInspector.tsx
agent-pane.chat-inspector-surfaces/transcript Apple System Colors unchanged 0% own ChatInspector.tsx
agent-pane.chat-inspector-surfaces/diff-in-place Apple System Colors Light unchanged 0% own ChatInspector.tsx
agent-pane.chat-inspector-surfaces/diff-in-place Apple System Colors unchanged 0% own ChatInspector.tsx
agent-pane.chat-inspector-surfaces/document-beside Apple System Colors Light unchanged 0% own ChatInspector.tsx
agent-pane.chat-inspector-surfaces/document-beside Apple System Colors unchanged 0% own ChatInspector.tsx
agent-pane.chat-inspector-surfaces/diff-closed Apple System Colors Light unchanged 0% own ChatInspector.tsx
agent-pane.chat-inspector-surfaces/diff-closed Apple System Colors unchanged 0% own ChatInspector.tsx
agent-pane.chat-width/standard Apple System Colors Light unchanged 0% own App.tsx
agent-pane.chat-width/standard Apple System Colors unchanged 0% own App.tsx
agent-pane.chat-width/wide Apple System Colors Light unchanged 0% own App.tsx
agent-pane.chat-width/wide Apple System Colors unchanged 0% own App.tsx
agent-pane.chat-width/wide-blocks Apple System Colors Light unchanged 0% own App.tsx
agent-pane.chat-width/wide-blocks Apple System Colors unchanged 0% own App.tsx
agent-pane.composer-edge/short-edge Apple System Colors Light unchanged 0% own App.tsx
agent-pane.composer-edge/short-edge Apple System Colors unchanged 0% own App.tsx

Pick other states with a Gallery: entry.id, entry.id/variant line in the PR body.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

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:

  • the only conflict was plans/cmux-next/sidebar-owner.md, and the resolution keeps the base's two sections followed by this PR's section;
  • the PR's diff against the new base covers the same 22 files as the reviewed diff;
  • the catalogs parse with no duplicate keys, changed imports resolve, and no conflict markers remain.

Defaults guard: as noted above, its hits are code fingerprints only (AgentTurnStates of, WorkspaceHoverCardContent facts and usageFact, Strings usageContext and usageCost). No setting, tunable, flag or key default changed.

teamleaderleo and others added 2 commits October 30, 2026 08:29
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
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

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:

  • 27f6e66 changes a test only: inspector-section-order.test.tsx now expects Usage after Context. That matches sectionOrder.ts (defaults environment, context, usage, connectors, and its rule for inserting a missing section), and the drag test's coordinates cross Context at 114, Usage at 142 and Connectors at 170.
  • The feat-cmux-next merge: git diff-tree --cc shows only App.tsx, model.ts and the pane's Localizable.xcstrings changed on both sides. The App and model changes merged without overlap and keep the PR's Usage additions. The catalog has both sides' keys (newTab.row.run and chatInspector.usage.*), parses as JSON and has no duplicate keys.

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 of, WorkspaceHoverCardContent facts and usageFact, Strings usageContext and usageCost). No setting, tunable, flag or key default changed.

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
@teamleaderleo

teamleaderleo commented Oct 30, 2026 •

Copy link
Copy Markdown
Collaborator Author

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.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

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: git diff HEAD^2 HEAD has the same added and removed lines as at d1eba87 and 0b628f1 (23 files, +1439/−39).

Run on this head: valid catalog JSON; inspector-dead-clicks, clickable-cursor, session-usage and inspector-section-order pass; web lint passes in full (base fixed chatOpenTrips in #28320); the prepush gate finds no new violations. tooling-tests' registry entry tests/test_cmux_tui_owned_mini_caches.py: linux-guard lane is not run by any workflow is still red on base tip 617c2b6 when run locally, and this PR touches no file under tests/, scripts/ or .github/.

# Conflicts:
#	webviews/src/agent-session/acpmux/Localizable.xcstrings
@cursor

cursor Bot commented Oct 30, 2026

Copy link
Copy Markdown

Bugbot needs on-demand usage enabled

Bugbot 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.

@teamleaderleo

teamleaderleo commented Oct 30, 2026 •

Copy link
Copy Markdown
Collaborator Author

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.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

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 newTab.row.run and messages.group.* from the top of "strings" to elsewhere in the file. The resolution keeps base's placement and this PR's 19 chatInspector.usage.* keys. The JSON is valid, and each of those base keys appears once. The PR's own change is unchanged: git diff HEAD^2 HEAD has the same added and removed lines as at d1eba87 (23 files, +1439/−39).

Run on this head: inspector-dead-clicks, clickable-cursor, session-usage and inspector-section-order pass; web lint passes; the prepush gate finds no new violations; no conflict with feat-cmux-next.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Visual review (codex gpt-6.1-sol high, fast) at cd4225c: VISUAL VERDICT: SHIP

The reviewer opened the after stills (Session Info, gallery agent-pane.chat-inspector variant usage, 420 px, dark and light: after-usage-dark.webp, after-usage-light.webp in the body) and found:

  • No control repeated on every row, and nothing bloated, cut off, colliding or wrapping in Usage.
  • The session icons and text line up with Context and Connectors, and the values on the right are aligned.
  • The sort highlight covers only the "24h cost" button. The light theme has good contrast, and the pressed fill is clear but restrained.
  • The changes since the stills (6bc2ccc) paint nothing different: the disabled pressed option keeps its fill, Show's highlight needs a click, and dropping cursor: default paints nothing.

The native hover-card row has no still: cmux-ci on a lane VM only runs test, not capture, so that capture has to come from a fleet host. WorkspaceHoverCardUsageTests checks its text, order and ring.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Visual verdict (claude-sr2-coord, Claude Opus 5.5, opened the exact-head still): SHIP at cd4225c for the hover card.

hover card session cards at cd4225c3

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: cmux-ci capture cd4225c3 --state <hover-card tour cut after its 'Session cards' gallery step> on a fleet mini (fixture data only). Caveat: the tour pins the Soft Blue (dark) theme, so both of the capture's appearance stills came out dark. No light still of the hover card exists at this head. Session Info's light and dark stills already have Sol's visual SHIP (issuecomment-6529246767).

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex gpt-6-astra high, router-review): BLOCK at cd4225c

BLOCK

Visual verdict: SHIP

  1. webviews/src/agent-session/acpmux/inspector/UsageSection.tsx:94-97 — In the “24h cost” sort, sessions with unknown costUsd24h fall back to displaying tokens24h. This shows a token count under a cost metric and violates the stated rule that unknown values render as an em dash. Use UNKNOWN for missing cost; the folded summary’s cost-to-tokens fallback should remain separate.

I could not rerun Bun tests because bun is unavailable in this environment.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

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.

teamleaderleo added a commit that referenced this pull request Oct 31, 2026
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
teamleaderleo added a commit that referenced this pull request Oct 31, 2026
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>
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Orphaned: no activity for 14 h, and no lane holds a lease on it. The orphan sweep could not merge feat-cmux-next in: conflicts in Packages/macOS/CmuxNext/Sources/CmuxNextSidebar/Resources/Localizable.xcstrings, plans/cmux-next/sidebar-owner.md, webviews/src/agent-session/acpmux/App.tsx, webviews/src/agent-session/acpmux/Localizable.xcstrings, webviews/src/agent-session/acpmux/direct.ts, webviews/src/agent-session/acpmux/inspector/ChatInspector.gallery.tsx, webviews/src/agent-session/acpmux/inspector/ChatInspector.tsx, webviews/test/inspector-section-order.test.tsx. Listed for a lane to resolve.

teamleaderleo added a commit that referenced this pull request Oct 31, 2026
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
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Owned by an agent session · session

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Carried in #28773, which keeps this PR's commits and authorship with feat-cmux-next merged in. Closing this copy; the work continues there.

@lawrencecchen

Copy link
Copy Markdown
Contributor

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.

teamleaderleo added a commit that referenced this pull request Nov 1, 2026
…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>

This branch was previously deployed

1 inactive deployment
ci-routing-agent — cd4225c3 Deployed Oct 30, 2026 by teamleaderleo via namespace autofix #8176
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk:normal Risk tier (docs/ci/risk-tiers.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants