Repository navigation
Warn on runaway agent sessions: sidebar badge and acpmux ls WARN column - #27899
Conversation
…ext, subagents/h) A session whose usage breaks a rule gets `usageWarnings` on its summary, decided by acpmux from `usageStats` and the new `usageWarnings` config section (contextTokens 400000, subagentsPerHour 40, autocompactCap true; 0/false turns a rule off). `acpmux ls` shows a WARN column while any row has one; the cmux NEXT sidebar row draws a small warning triangle, apart from the working spinner, whose tooltip says each rule and its number. Gallery stills (AAUsageWarningGalleryTests) show it before and after. Sidebar-Look: Leo 2026-10-30, "that visibility into [one agent host's] 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-3b79c5cbd715a3cc84ce
00ca6e0 to
4e3fb0a
Compare
Sidebar-Look: no visual change Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3b79c5cbd715a3cc84ce
Default changesThis pull request changes 6 defaults at
Signed off on this commit by Merge receipt: merged as Regenerate the snapshot with |
…-warn # Conflicts: # plans/cmux-next/sidebar-owner.md
|
Found 4 test failures on Blacksmith runners: Failures
|
|
Review (codex-review-box/gpt-6-astra high, lane-place): BLOCK at 70d34d2 BLOCK
Rust/Swift toolchains were unavailable, so compilation was assessed statically. BLOCK at 70d34d2: warning configuration is omitted from reload and replaced by defaults during lock contention |
reload_catalog copies the section (a later daemon save keeps it), and summaries read a snapshot of the limits the Hub keeps from start and each reload, so a writer holding the config lock never swaps in the defaults. Review of #27899 at 70d34d2. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3b79c5cbd715a3cc84ce
Leo 2026-10-30: "acpmux ls should probably not be overly... verbose? i guess". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3b79c5cbd715a3cc84ce
…ge for captures A capture tour cannot know a row's window point; this target points at the topmost shown badge so the tour shows its tooltip. Debug builds only. Sidebar-Look: no visual change Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3b79c5cbd715a3cc84ce
|
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)
web and size checks: green |
Warn noAutocompactCap only on usageStats.autocompact "none" (ao-vis-data's three states: capped, none, unknown); an unknown cap or a null count never raises or clears a warning. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3b79c5cbd715a3cc84ce
No cap: rotate onto a capped profile (lane-place rotate NAME, still to come: session restart keeps the launch, so it adds no cap). A large context: compact it (acpmux send NAME /compact, Claude Code's own command, which the Claude adapter already runs as a prompt). Many subagents: open the session, and acpmux session cancel NAME to stop its turn. Nothing runs on its own. The tooltip text ends in the action; ls --wide names the command; a number acpmux does not have shows as ?, never 0. Part of HQ#1920, HQ#5226, HQ#5123. Sidebar-Look: no visual change Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3b79c5cbd715a3cc84ce
|
Reds at 46be2bf, classified (no rerun):
|
A fleet capture of #27899 hovered the badge to show its tooltip, but the row's hover controls (⋯, ×) covered it. Since row hover always comes first, nobody could point at the badge. This test hovers the row and expects the badge shown, clear of the controls. It fails at this commit: the badge fades under the overlay. Sidebar-Look: no visual change Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3b79c5cbd715a3cc84ce
When the row is hovered, the badge moves to just left of the overlay controls (⋯, ×, pin) and never fades under them. The title, the subtitle and the marks it covers give way to it as they do to the controls. At rest nothing changes. This fixes theBadgeStaysBesideTheHoverControls. Sidebar-Look: Leo 2026-10-30 "that visibility into [one agent host's] guys was (and is?) pretty bad"; the badge must stay readable on hover Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3b79c5cbd715a3cc84ce
…d row puts it Hovering a row moves its warning badge left of the row's hover controls. So the point read before the hover was the badge's resting place, which is now under the ⋯ button. The capture hovered ⋯ and showed no tooltip. The hook now hovers there, lays the window out, reads the badge's frame again and moves the pointer onto it. Debug builds only. Sidebar-Look: no visual change Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3b79c5cbd715a3cc84ce
|
Review (codex gpt-6.1-sol high, review-router): SHIP at 891176a No correctness or compile findings. This replaces the receipt at 46be2bf. The diff reviewed was the PR from the merge base (
Reviewer's notes:
Astra (gpt-6-astra) through the router timed out twice on reconnects with no verdict, so this review ran on Sol, as acpmux-owner directed. |
…-warn # Conflicts: # cmux-tui/crates/acpmux/docs/acpmux-schema.json # plans/cmux-next/sidebar-owner.md
|
Review (codex gpt-6.1-sol high, review-router): SHIP at 722f4ad No findings. This replaces the receipt at 891176a. The new head merges feat-cmux-next at 214b514 into the branch, bringing in #28015, so Reviewer's notes:
|
|
Shipped in:
|
Keeps both sidebar-owner.md entries (the single-member group and #27899's runaway badge). Sidebar-Look: no visual change Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-61ad9dd1285c751bce87
AgentActivityLane: base added usageWarnings (#27899) and sidebarRequiresOpen (#29742); the PR's turnPrompt, turnActivity and turnPlanStep follow them in the init and in of(summary:). sidebar-owner.md: base's entries, then the PR's. The tab-row deletion (8a3af6b) touches none of this PR's code; its row title resolver still applies. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-63b9964940c20354b639
![Fix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/fix-with-codesmith-light-3x.png)
Leo, 2026-10-30: "that visibility into [one agent host's] guys was (and is?) pretty bad i feel like we can make more improvements to acpmux/cmux-next"
Leo, on
acpmux ls: "and acpmux ls should probably not be overly... verbose? i guess" / "to keep everything efficient... tho idk"Part of HQ#1920, HQ#5226 and the HQ#5123 telemetry lane (row d: "Show unknown, never a synthesized zero. A metric must trigger an action."). Related: HQ#5266 (a revived session keeps its autocompact cap); this PR never warns on such a session's unknown cap.
A usage audit found four long-running Claude sessions with no autocompact cap carrying 290-330k of context per call and starting 67-90 Opus subagents. Nothing in acpmux or cmux NEXT showed it; finding it took a hand audit of
pslines and transcripts. This PR is the visible warning: a person sees a mark, not a log line.What changes
acpmux decides the warnings, once. A session summary gets
usageWarnings: [{rule, value, limit, text}], computed when the summary is read from itsusageStats(the fields from the companion acpmux usage-stats PR) and the thresholds:noAutocompactCap: a Claude session (familyclaude) whoseusageStats.autocompactisnone.contextTokens:usageStats.contextTokensis above the limit.subagentsPerHour:usageStats.subagents1his above the limit.The warning list is empty for a closed session or one with no
usageStatsyet, so until the usage-stats PR lands nothing shows.Unknown stays unknown. A count acpmux could not read is null, never 0. An
autocompactofunknown(an adopted or revived chat whose launch acpmux never saw, or a setting it could not read) never raises or clears a warning. A value it lacks shows as?, never 0.Each warning names the action that answers it (
action: {label, command, available}). The tooltip line ends with it, and nothing runs automatically:lane-place rotate NAME(coming:session restartkeeps the launch settings, so it adds no cap)acpmux send NAME /compact(Claude Code's own command; the Claude adapter already runs it as a prompt, seecompact_ends_its_prompt_and_reports_the_compaction)acpmux session cancel NAMEOne declared place for the thresholds: the new
usageWarningssection of acpmuxconfig.json,{"contextTokens": 400000, "subagentsPerHour": 40, "autocompactCap": true}. Those are the defaults (config/usage_warnings.rs), and 0 or false turns a rule off. Documented in the acpmux README anddocs/acpmux-schema.json.acpmux lsstays compact. Defaultlsgets a WARN column holding the single wordwarnper flagged row, shown only while some row has one; with no warnings the output is unchanged. The reasons and commands (ctx 412k: acpmux send NAME /compact; 90 sub/h: acpmux session cancel NAME) go to--wide, which the companion usage-stats PR adds.--jsonrows carry the wholeusageWarnings. Computing the warning reads only the already-cachedusageStatson the summary, and no transcript is read for it.The cmux NEXT sidebar row gets a small warning triangle (
exclamationmark.triangle.fill, theme attention color) in the trailing cluster beside the muted bell. It is its own view, not the working-state spinner. Its tooltip lists each warning'stext, e.g. "90 subagents started in the last hour, above 40", and the row's accessibility label includes them. It is on for everyone: it does not depend on thesidebar.laneStatus/rowStatus/nowLinetoggles. The Debugsidebar.laneFixtureworking sample now carries warnings, so captures show the badge.How N was chosen (subagents per hour)
The rate is the peak count of
Agent/Tasktool calls in any sliding 60-minute window, measured per main transcript across every Claude transcript on this agent host (63 sessions, the last ~3 days):N = 40 sits above every ordinary session, with headroom over the busiest coordinator (27), and well below the runaway deputies. It is a config value, so it can move without a release.
The context limit of 400k is about where sr2's managed
--autocompactwindow sits (380k-420k), so a session that compacts normally never reaches it. Five of the 63 sessions here peaked above 400k; all five are long-lived coordinators with no cap, which is the case this warning is for.Tests
hub/usage_warnings_tests.rscovers:cli/ls_table_tests.rs:warn_is_one_word_and_shows_only_while_a_row_has_one. The defaultlsshows onewarnword;--wideshows each rule's short form and its commands.SidebarUsageWarningTestscovers:usageWarnings;laneStatuson and off;theBadgeStaysBesideTheHoverControls). This test was committed red first, in 527848c, and the fix is 84e7b01. The first fleet capture showed the hover controls covering it.AAUsageWarningGalleryTests(CMUX_TEST_REQUIRE_GUI=1, artifactusage-warning-gallery.tar): the real sidebar list drawn light and dark, before (no warnings) and after (the working chat breaks all three rules). Each still is also printed base64 to the log.plans/cmux-next/sidebar-owner.md) logs the look change, and the commit carries aSidebar-Look:trailer.Observed / Not run
cargo clippy -p acpmux --all-targets --locked -- -D warningsis clean, andcargo test -p acpmux --lib -- usage_warn ls_table protocol_ir_is_current catalog_reload a_cell_without remote_summary peer_cachepasses 32/32.scripts/cmux-next/prepush-gate.pypasses at the head.indexing_slicing 700 > 693,string_slice 98 > 94, the same at merge base e863077) and cmux-next checks. The latter's one counted red is String tables, withcheck-l10n.shoutput the same at e863077; its sidebar-trailer annotation names three base commits, and this PR's range has 0.SidebarUsageWarningTests, the galleryAAUsageWarningGalleryTests). CI'scmux-next swift testjob waits on a fast-tier runner label that has started nothing, and this lane VM cannot build Swift.Captures
Fleet captures from a build of the head, driven on a capture mini, checked by eye. The stills will be linked here once pr-media uploads work again.
TooltipPanel), centered under the badge and clamped to the screen's visible frame (TooltipPresenter.origin, covered byThemedTooltipTests). So a person sees it whole, and the crop is the roughly 700 pt wide tooltip running past the window's left edge.~/.cache/pr-capture/84e7b01d/steps-ac9b6932cf/, B:~/.cache/pr-capture/891176a8/steps-87a9bbecf9/) until pr-media uploads work.No capture: the stills above exist (A at 84e7b01, B at 891176a, both matched by eye), but pr-media uploads are blocked for now; the image links will replace this line.
Performance
_acpmux/sessionslatency (whatacpmux lscalls), from the companion usage-stats PR's benchls_latency: 30 fake-Claude chats that each ran a turn, 50 timed calls per mode, each on a new connection, on one 32-vCPU CI runner. Before is the companion branchb9c165d; after is the same tree plus this PR's daemon and config changes, sousageStatsis present and every row's warnings are computed. Both were built once and run alternately (before, after, before, after); each figure is the mean of the two rounds. Command:cargo test -p acpmux --test hub_integration ls_latency -- --ignored --nocapture.acpmux ls(no usage read) p50acpmux ls(no usage read) p95acpmux ls --wide/--json(usage read) p50acpmux ls --wide/--json(usage read) p95The deltas are within the spread between the two "before" rounds (p50 21.7 vs 22.0 ms; p95 25.9 vs 27.2 ms). Computing the warnings reads only the
usageStatsalready on the summary: no transcript read, no new timer, no lock wait.Changelog
warnmark inacpmux ls.Agent session: agent session
🤖 Generated with Claude Code