Repository navigation
cmux NEXT session rail: a Background tasks card - #22368
Conversation
…equests Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The rail grows a Changes card with the first pull request the chat opened: newest first, title, repo #N, line counts and checks where the App read them (Failing, or a dot), Merged/Closed, five then Show more. Each row opens the pull request. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ail-changes-card # Conflicts: # webviews/src/agent-session/acpmux/Localizable.xcstrings
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A close the chat ran wins until the App reads a state other than the one it had at the close; after that the App's reads do. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A close the chat ran wins until the App reports the pull request in a state it first read after the close, so a reopen survives hiding the rail or folding the card. The gallery no longer shows line counts the App doesn't send yet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…cess registry Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The rail grows a Background tasks card once the chat has a background process. It reads acpmux's process registry (process/list when the rail shows, then each process_update), so Claude Code's background shells and Codex's background terminals both show. Running commands come newest first with how long each has run and a Stop (process/kill); the header counts the running ones and the card says how many finished. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A reconnect makes a new acpmux client; the rail's process source now changes with it, so the card subscribes there and lists again. Commands use the rail's own font. Tests cover an update before the list, a refused list, a chat switch, a new client and a refused Stop. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Correctness review (independent subagent, Claude Opus 5.5, for owner teamleaderleo) of cedcd7d; fixes in e383a01 (exact head). Findings and resolution:
Checked and fine: wire shape (camelCase, ids |
|
Bead |
[Medium impact] The changes reach the cmux NEXT session rail and its selected chat’s background commands. Fix the repeated history scans and missed process recovery before merging. Findings
SummaryAdds a Background tasks card to the session rail, backed by acpmux's process registry.
DiagramsequenceDiagram
participant Rail as Session rail
participant Client as Direct client
participant Registry as acpmux registry
Rail->>Client: Watch processes and list session
Client->>Registry: _acpmux/process/list
Registry-->>Rail: Process records
Registry-->>Client: _acpmux/process_update
Client-->>Rail: Merge process record
Rail->>Client: Stop process
Client->>Registry: _acpmux/process/kill
Registry-->>Client: End update or refusal
Note over Client,Rail: Lag recovery does not refresh process records
Reviews (1) · Last reviewed commit: "cmux-next: Background tasks follow a rec..." · Reviewed by Greptile |
| const running = processes.filter(isRunning).sort((a, b) => b.startedAt - a.startedAt); | ||
| const finished = processes.length - running.length; | ||
| const now = useNow(running.length > 0); |
There was a problem hiding this comment.
RailTasks filters the full process history and sorts the running commands on every one-second tick, even when processes has not changed. The registry keeps finished processes without a history limit, and showing five rows does not bound this work. This violates the repository rule against repeatedly filtering or sorting growing collections in hot UI paths. Cache the running list by processes so timer ticks only update elapsed times.
Rule Used: Flag production code that adds nested full-collection scans, per-target rescans for batch actions, repeated sort/filter/map work in hot UI/socket/search/process paths, in-memory joins that belong in the data store, or unbenchmarked slower algorithms ... (source)
| else if (notification.method === "_acpmux/process_update") | ||
| for (const listener of this.processListeners) listener(notification.params?.process); |
There was a problem hiding this comment.
Finished commands stay running
The new process listeners miss changes dropped during _acpmux/lagged. The existing recovery path fetches transcript events, but neither replay nor resyncAfterLag refreshes these listeners. If a command ends in the dropped window, the card keeps showing it as running until the rail is reopened or the connection changes. Refresh the process list after a lag, or replay the missed process records into the same store.
| }; | ||
| if (JSON.stringify(next) === JSON.stringify(current)) return; | ||
| const pr = next.pullRequest; | ||
| if (pr && stateSince.get(pr.url)?.state !== pr.state) stateSince.set(pr.url, { state: pr.state, at: Date.now() }); |
There was a problem hiding this comment.
Reopened pull requests stay closed
stateSince only advances when the reported state changes. If a chat closes and reopens a pull request between native reads, both reads report open, so since stays older than closedAt. closedState then keeps showing Closed and hides the checks despite later fresh reads. Track when the status was actually read, rather than when its state first changed, and cover a close/reopen without an intervening closed report.
|
Orphaned: no activity for 14 h, and no lane holds a lease on it. The orphan sweep could not merge |
|
owner: 01a15bc8-eca6-7bb3-b8eb-4327d0930566 |
…t-rail-tasks-card # Conflicts: # webviews/src/agent-session/acpmux/Localizable.xcstrings # webviews/src/agent-session/acpmux/direct.ts
…ge formatting The type check the base runs now has no Array.prototype.with on readonly arrays (TS2339). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bc8-eca6-7bb3-b8eb-4327d0930566&host=cosmic-gray
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. |
|
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)
Unclear: CI failed on
Failures:
Matched log linesNot re-run automatically: Written by red: web / Web status; base red: the same failure on the base 52a1a09; does not block
Agents: Tour of |
|
Found 28 test failures on Blacksmith runners: Failures
...and 18 more test failures. View all on Blacksmith
|
|
Adopted and merged. Base merge at bddf2ff: a conflict in Follow-ups from review, not done here:
|
Base's session rail work (#22368 Background tasks card, its RailTasks, RailChanges and sessionProcesses) is already carried by the Inspector (inspector/TasksSection, ChangesSection, processes.ts), so the rail files base modified or added are removed with the rail, and App.tsx, direct.ts, sessionSummary.ts and summary.css keep the Inspector's side. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bd2-60d2-70e1-8179-d3aa717c8828&host=cosmic-gray
…y are allowed tooltip-rules also fails on base for the saved environment's folder face (#22406, full path behind a short name), the rail's checks mark and background task command (#22368, text for screen readers only / cut with an ellipsis) and the stats day cell (#22954, date and working time behind a short label). Each title says what the visible text does not, so each gets tooltip-allow. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15d18-a2fb-7ac0-84d5-432ffea53b8b&host=cosmic-gray
…ay why) (#23053) * fix(webviews): Send now's help tooltip is allowed (tooltip-rules red on base) #22834 gave the waiting steer's Send now button a title; tooltip-rules fails on it because the button shows its own text. The title says what the text does not (it stops only the current step, the turn goes on), so it is marked tooltip-allow with that reason. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15d18-a2fb-7ac0-84d5-432ffea53b8b&host=cosmic-gray * fix(webviews): four more tooltips red on base are marked with why they are allowed tooltip-rules also fails on base for the saved environment's folder face (#22406, full path behind a short name), the rail's checks mark and background task command (#22368, text for screen readers only / cut with an ellipsis) and the stats day cell (#22954, date and working time behind a short label). Each title says what the visible text does not, so each gets tooltip-allow. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15d18-a2fb-7ac0-84d5-432ffea53b8b&host=cosmic-gray --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
|
Shipped in:
|
* test(cmux-next): session rail Changes card lists the session's pull requests Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next: session rail Changes card with the session's pull requests The rail grows a Changes card with the first pull request the chat opened: newest first, title, repo #N, line counts and checks where the App read them (Failing, or a dot), Merged/Closed, five then Show more. Each row opens the pull request. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(cmux-next): a reopened pull request leaves the rail's Closed state Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next: a reopened pull request leaves the rail's Closed state A close the chat ran wins until the App reads a state other than the one it had at the close; after that the App's reads do. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(cmux-next): a reopen survives hiding the rail Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next: decide a closed row by when the App read the pull request A close the chat ran wins until the App reports the pull request in a state it first read after the close, so a reopen survives hiding the rail or folding the card. The gallery no longer shows line counts the App doesn't send yet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(cmux-next): session rail Background tasks card from acpmux's process registry Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next: session rail Background tasks card The rail grows a Background tasks card once the chat has a background process. It reads acpmux's process registry (process/list when the rail shows, then each process_update), so Claude Code's background shells and Codex's background terminals both show. Running commands come newest first with how long each has run and a Stop (process/kill); the header counts the running ones and the card says how many finished. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next: Background tasks follow a reconnect's new client A reconnect makes a new acpmux client; the rail's process source now changes with it, so the card subscribes there and lists again. Commands use the rail's own font. Tests cover an update before the list, a refused list, a chat switch, a new client and a refused Stop. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux NEXT: the Inspector, the chat's right-hand panel The session rail becomes the Inspector, opened by the chat header's top-right toggle in every agent chat, Chief included. Top to bottom, each section folds: Environment (machine by name, folder with its full path on hover, repository, branch or worktree, and Save and Remote Control when the App offers them), Context (percent with a bar, then the tokens), Connectors (connected and to reconnect), Changes (every pull request the chat opened or touched, with line counts split by kind, failing checks with the ones already on base dimmed, the owner and a menu), Servers (dev servers with their ports and Stop), Subagents (an avatar row with live counts that opens into the list), Background tasks (running with elapsed time and Stop, then N finished, folded) and Outputs (files, artifacts and links). It pushes the chat aside and the chat reflows, or lies over it when the pane is too narrow or Settings > Agent Chat > Inspector says Overlay. Its left edge drags to resize it. Open, width and folds hold across chat tabs. Lists scroll; there is no "Show more" cap. Debug Settings agent.inspector (was agent.sessionRail) is on by default; off brings back the summary card. Folds in the Changes card (#22327) and the Background tasks card (#22368). Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=e8f63fd9-94e8-4878-bcd4-704659aba1f2&host=cosmic-gray * cmux NEXT: the Inspector's highlight opens a new agent chat (release-notary needs an action or docs link) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bab-4ee1-7ab3-b16e-81d10ae7872e&host=cosmic-gray * cmux NEXT Inspector: the running line's subagent and command counts open it With the Inspector on, the summary card's panel is never drawn, so a count of several called card.show() and nothing happened. The counts now open the Inspector with Subagents or Background tasks unfolded; with it off they still open the summary card. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bab-4ee1-7ab3-b16e-81d10ae7872e&host=cosmic-gray * cmux NEXT Inspector: the agent pane page loads inspector.css build-agent-pane-web.sh refused the bundle: the pane imports inspector/inspector.css but the script did not add it to the page's styles. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bab-4ee1-7ab3-b16e-81d10ae7872e&host=cosmic-gray * cmux NEXT Inspector: a pull request named only in quoted text is not the one a command touched; Swift tests for the toggle and the placement setting From the Inspector's first author (their unpushed follow-ups): touched() drops quoted --body / --title text before matching, so 'gh pr comment 12 -R acme/a --body "dup of .../acme/b/pull/9"' lists a#12, not b#9 (test added). AgentPaneInspectorHeaderTests: agent.inspector is on by default and the header JSON's inspector key follows it. AgentPaneDisplaySettingTests: rows for agentPane.display.inspector.placement (push default, overlay accepted, page-writable). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bab-4ee1-7ab3-b16e-81d10ae7872e&host=cosmic-gray * cmux NEXT Inspector: a PR row's owner chip truncates only when its row is full chip-fixed-width.test.ts: an ellipsized chip may not cap at a fixed length. The owner chip's 72px cap becomes 40% of its row. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bab-4ee1-7ab3-b16e-81d10ae7872e&host=cosmic-gray * acpmux: restore base's App.tsx changes the Inspector base merge dropped The merge took the PR's whole App.tsx instead of only its conflicting hunks, losing #22724's repository folding in the New Tab pickers, the Chief context Copy button and Retry's model release labels. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bd2-60d2-70e1-8179-d3aa717c8828&host=cosmic-gray * cmux NEXT Inspector: lies over the chat by default; empty sections hide Opening, closing or updating the Inspector no longer reflows the chat (Leo, 2026-10-20): Overlay is the default placement and Push is the setting. Context hides until the harness reports usage and Outputs until the chat produced something, instead of a dash and "None". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bd2-60d2-70e1-8179-d3aa717c8828&host=cosmic-gray * cmux NEXT Inspector highlight: fit the 240-character summary Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bd2-60d2-70e1-8179-d3aa717c8828&host=cosmic-gray * cmux NEXT Inspector: tests and gallery follow the overlay default and hidden empty sections Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bd2-60d2-70e1-8179-d3aa717c8828&host=cosmic-gray * cmux NEXT Inspector: its own class names, apart from the ACP debug Inspector's The chat's panel reused .acpmux-inspector and its -row/-list/-name children, which the ACP debug Inspector (Inspector.tsx) already styles, so each sheet restyled the other's panel. The chat's are now acpmux-chat-inspector*. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bd2-60d2-70e1-8179-d3aa717c8828&host=cosmic-gray --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Summary
Claude desktop's session panel has a Background tasks card: running commands with how long each has run, a stop button, and how many finished. The cmux NEXT session rail (Debug Settings
agent.sessionRail) had no such card.Now the rail grows a Background tasks card once the chat has a background process. It reads acpmux's process registry (cmux-tui/crates/acpmux/docs/background-processes.md):
_acpmux/process/list {sessionId}when the rail shows, then each_acpmux/process_update. The registry holds Claude Code's background shells and Codex's background terminals, so the card is the same for both harnesses._acpmux/process/kill). A refused Stop says so and can be tried again; otherwise the row stays until the registry reports the end.2 running); the card ends with3 finished.Stacked on #22327 (the Changes card). Until that merges this PR's diff includes its commits; the commits for this card start at 9da29f3.
The gallery entry now covers RailChanges.tsx and RailTasks.tsx (the gallery coverage test listed both as missing).
Testing
bun test test/session-rail-tasks.test.tsx test/session-rail.test.tsxon Huge Blue: the new test file fails on the test commit 9da29f3 (module missing) and all 14 pass on the head. It covers the wire parsing, merging updates, the card (order, elapsed time, Stop, finished count), an update that arrives before the list, a refused list, a chat switch, a new client, and a refused Stop.bunx vp checkon Huge Blue: clean.check:type-scale,check:status-glyphs,check:system-bluepass.check:dialog-keysfails on base (Swift files, not this PR).rail.running,rail.finished) with all 21 agent-pane locales; reusedsummary.backgroundTasks,subagents.stop/stopFailed,prDock.more/less.Changelog
Added: The cmux NEXT session rail shows a Background tasks card with each running background command, how long it has run and a Stop button.
Proof
New
tasksvariant of theagent-pane.session-railgallery entry (two running, three finished), rendered from head e383a01 in Playwright WebKit on a fleet Mac (macOS system font). It's a gallery story, not the running app.🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need.Summary by cubic
Updates the cmux NEXT session rail with two cards matching Claude desktop's panel: Background tasks (running commands with elapsed time and Stop, plus a finished count) and Changes (pull requests the chat opened, newest first, with checks, line counts, and Merge/Close state).
The Background tasks card reads acpmux's process registry (
_acpmux/process/listwhen the rail shows, then each_acpmux/process_update), so it works the same for Claude Code and Codex background processes. The Changes card combines the chat's pull requests with what the App reads of the chat folder's current one, so checks and a close-then-reopen show correctly; a close the chat ran wins until a later App read. Both cards show five rows with the rest behind Show more._acpmux/process/kill); a refused Stop says so and can be retried. The header counts running commands (2 running) and the card ends with3 finished.Array.withfor the base's type check.Written for commit bddf2ff. Summary will update on new commits.