Skip to content

cmux NEXT: a subagent's pane is named after the subagent, not its parent chat - #28497

Merged
teamleaderleo merged 7 commits into
feat-cmux-nextfrom
lane/ux-subagent-tab-name
Oct 31, 2026
Merged

teamleaderleo merged 7 commits into
feat-cmux-nextfrom
lane/ux-subagent-tab-name

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 30, 2026 •

Copy link
Copy Markdown
Collaborator

Leo, 2026-10-30:

"subagents shouldn't be tab-named the exact same as the parent. and we dont want that subtitle text"

And, when asked which subtitle he meant (20:05Z):

"i mean the sidebar tab shouldn't just be named claude sr2 coord if you can just say it's SUbagent of sr2 coord / and yes ofc remove the second line a)"

This PR is the tab names: a subagent's pane is named after the subagent, else "Subagent of ", never the chat's bare name. The second line is #28510.

What was wrong

A subagent's pane is an agent tab on its chat's own acpmux session (AgentSubagentPanes). The tab strip and the sidebar's tab rows name an agent tab by its session (TabTitleResolver → AgentChatTabTitle), so the subagent's tab got exactly the chat's name, e.g. two "claude-sr2-coord" tabs.

What changes

  • The page sends the subagent's name with chat.subagentPane (title): its own (Subagent.name: its task, which for the Agent tool is the call's description), else "Subagent of " from the page's already-translated subagents.of label (subagentTabTitle).
  • The name follows what the pane shows. A pane opened on a subagent shows the chat's other subagents in place, and its "Subagent of" pill goes back to the chat. The page reports each change (chat.subagentShown, only once it has that subagent's rows), and the tab takes that subagent's name, or the chat's again.
  • The app keeps it per tab (SubagentTabTitles, CmuxNextAgentPane). It's recorded by session and subagent id when the request arrives, then bound to the tab once that tab is created.
  • TabTitleResolver.untitled reads it before the chat's title. A name the person gives the tab still wins, because displayTitle is read first. The strip and the sidebar's tab rows share that rule, so both change together.
  • An older page that sends no name leaves the tab as before. The openSubagent hook keeps its signature.
  • A subagent tab restored after a relaunch shows its whole chat, so it's named like the chat again.

Nothing else is removed or restyled. The "Subagent of …" pill and the sidebar subtitle are unchanged here.

Tests

  • SubagentTabTitleTests:
    • the subagent's tab reads its own name while the chat keeps its own (before: identical);
    • the name follows what the pane shows, and clears back on the chat;
    • blank, unnamed, other-session, over-long and closed-tab cases;
    • both requests decode.
  • webviews/test/subagent-pane-tab-title.test.ts: the request carries the name; a subagent with no name of its own gets "Subagent of ". 2 pass on cmux-ci, and lint passes.

Screenshots

Capture state scripts/cmux-next/media/states/subagents-four-panes.json (four fixture subagents opened beside a chat). Both sides carry #28213's debug open_subagent action and fixture agents count, which a showcase capture needs to open a subagent pane at all:

Light Dark
Before: every subagent's tab ("Right c…") and sidebar row ("Agent") reads like its chat before light before dark
After: sidebar rows Reviewer, Auditor, Helper 1, Helper 2; tabs Review…, Audito…, Helper, Helper after light after dark

Each subagent's sidebar row reads its own name (Reviewer, Auditor, Helper 1, Helper 2); the chat keeps its own row. The tab strip shows the same names, cut at this pane width. Nothing else in the window changes.

Viewed after image: yes
Visual verdict: SHIP: each subagent's row and tab carry its own name, as Leo would expect next to ChatGPT or Claude.

Not this PR: at this pane width the tab chips cut "Helper 1" and "Helper 2" to the same "Helper" (base cut "Right column" to "Right c" the same way). A tab-strip follow-up should keep a trailing number or truncate in the middle.

Agent session: agent session

🤖 Generated with Claude Code

…ent chat

Leo, 2026-10-30: "subagents shouldn't be tab-named the exact same as the
parent."

A subagent's pane is an agent tab on its chat's own acpmux session, so
the tab strip and the sidebar's tab rows, which name an agent tab by its
session (TabTitleResolver -> AgentChatTabTitle), named it exactly like the
chat. The page now sends the subagent's own name with chat.subagentPane
(Subagent.name: its task, the Agent tool's description), and the app keeps
it per tab (SubagentTabTitles: recorded by session and subagent when the
request arrives, bound to the tab once it is created). The title rule
reads it before the chat's title, after any name the person gave the tab.
No name (an older page, a workflow agent) leaves the tab as before.

The openSubagent hook keeps its signature. A restored subagent tab after a
relaunch shows its chat in full, so it is named like the chat again.

Tests: SubagentTabTitleTests (the subagent's tab reads its own name while
the chat keeps its own; blank, unnamed, other-session, over-long and
closed-tab cases; the request decodes with and without `title`) and
webviews/test/subagent-pane-tab-title.test.ts (the request carries it).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-0c8df2029ad2a028c4e7
@github-actions github-actions Bot added the risk:normal Risk tier (docs/ci/risk-tiers.md) label Oct 30, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-0c8df2029ad2a028c4e7
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

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

BLOCK

Visual verdict: BLOCK — no after screenshots were supplied, so the required visual review cannot be completed.

  1. [P2] Tab titles become incorrect after navigating within a subagent pane. TabTitleResolver.swift:77 always prefers the name cached when the tab opened. Existing navigation can show another subagent or return to the parent chat (App.tsx:6640, 6752) without updating or clearing that cache. Open “Reviewer,” then return through “Subagent of …”: both tab labels still say “Reviewer” while displaying the parent chat. Synchronize the override with the displayed subagent and clear it when returning to the chat.

  2. Required visual evidence is missing. review/pr.body:32 says stills remain pending; review/images/ contains no screenshots. Supply the after images for comparison, and have the landing lane record in the PR body that it viewed them.

Tests could not run: this Linux box has neither Bun nor Swift installed.

@teamleaderleo teamleaderleo removed the risk:normal Risk tier (docs/ci/risk-tiers.md) label Oct 30, 2026
@github-actions github-actions Bot added the risk:normal Risk tier (docs/ci/risk-tiers.md) label Oct 30, 2026
…nt of" the chat when it has no name

- SubagentTabTitles.swift: `public import Observation`. A public
  @observable class needs it under InternalImportsByDefault (the fleet
  compile of the stills build failed there).
- Review of #28497 at 995299f (router-review, P2): a subagent pane shows
  the chat's other subagents in place, and its "Subagent of" pill goes back
  to the chat, but the tab kept the name it got at open. The page now sends
  chat.subagentShown {subagent?, title?} whenever the pane it opened on a
  subagent shows another one, or the chat again (only after its first
  subagent has shown, so the open-time name never flashes away). The app
  sets or clears the tab's name (header hook showsSubagent ->
  SubagentTabTitles.show).
- Leo, 2026-10-30: "the sidebar tab shouldn't just be named claude sr2
  coord if you can just say it's SUbagent of sr2 coord". A subagent with no
  name of its own (only its id) is named "Subagent of <chat>", from the
  page's already-translated subagents.of label (subagentTabTitle). The tab
  strip and the sidebar's tab rows both read it.

Tests: SubagentTabTitleTests (the name follows what the pane shows; the
request decodes) and webviews/test/subagent-pane-tab-title.test.ts (own
name, else "Subagent of" the chat).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-0c8df2029ad2a028c4e7
…t subagent's rows

A pane's page loads its subagent's rows after it opens (and a showcase
fixture's rows live only in the chat's page): until then it would report
the "Subagent of" fallback over the name the chat's page gave the tab.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-0c8df2029ad2a028c4e7
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

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

BLOCK

Visual verdict: BLOCK — no after screenshot is available (review/images/README.txt:1-2; PR body still says “Viewed after image: pending”).

  1. Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/AgentPaneModel.swift:495 does not handle the new .subagentShown enum case. The exhaustive Swift switch therefore fails to compile.

  2. Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/AgentPageProvider.swift:38 omits chat.subagentShown from AgentPageOps.methods. The page’s call at webviews/src/agent-session/acpmux/App.tsx:6673-6676 is rejected as an unknown native operation, so titles cannot follow pane navigation even after fixing the compile error.

@teamleaderleo teamleaderleo removed the risk:normal Risk tier (docs/ci/risk-tiers.md) label Oct 30, 2026
…he page's method list

Fleet build of the #28497 stills (ae1c050) failed: AgentPaneModel.respond's
switch over AgentPaneRequest was not exhaustive without .subagentShown.
It joins the header requests (respondToHeader) and the passive ones that
do not mark the pane as touched by the person. AgentPageProvider.methods
also lists chat.subagentShown, or the page's report would never reach the
pane.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-0c8df2029ad2a028c4e7
@github-actions github-actions Bot added the risk:high Risk tier (docs/ci/risk-tiers.md) label Oct 30, 2026
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

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

BLOCK

Visual verdict: BLOCK — no after screenshot was provided (review/images/README.txt says none; PR body leaves the visual verdict pending), so the required UI review cannot be completed.

  1. review/pr.body (Screenshots section): the landing lane has not viewed or supplied the after image for this UI change.

@teamleaderleo teamleaderleo removed the risk:high Risk tier (docs/ci/risk-tiers.md) label Oct 30, 2026
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Visual verdict (Claude Opus 5.5, independent, opened the after stills): SHIP at 9d12f81 — the four subagent rows and tabs now carry their own names (Reviewer, Auditor, Helper 1, Helper 2) where before every one read the chat's ("Agent" rows, "Right c…" tabs), and nothing else in the window changes.

One follow-up, not this PR's: at this pane width the tab chips clip, so "Helper 1" and "Helper 2" both read "Helper" in the tab bar (the sidebar shows them in full). The same clipping cut "Right column" to "Right c" before. Worth a tab-bar follow-up (middle truncation, or keeping the trailing number), since two equal-looking tabs is what Leo complained about.

Fleet stills, state scripts/cmux-next/media/states/subagents-four-panes.json: before at 23db08c, after at e2bd98e (9d12f81 + #28213 + the stills-only naming line):

light dark
before (23db08c) before light before dark
after (e2bd98e) after light after dark

@github-actions github-actions Bot added the risk:high Risk tier (docs/ci/risk-tiers.md) label Oct 30, 2026
….session is optional)

Fleet compile-check of #28497 at 9d12f81: CmuxNextAppTests failed on
passing ref.session (String?) where String is needed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-0c8df2029ad2a028c4e7
@teamleaderleo
teamleaderleo marked this pull request as ready for review October 30, 2026 20:32
@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 dfa690a: 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=pr28497 -f ref=lane/ux-subagent-tab-name -f platform=macos -f backend_mode=local

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

gh run download 41124020648 -R manaflow-ai/cmux -n gallery-advisory-28497-dfa690a5ce55ca9822b5495942be0d0bbb5a441d (then read gallery-review.json)

States
State Theme Status Diff Picked by
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
agent-pane.composer-edge/wide-edge Apple System Colors Light unchanged 0% own App.tsx
agent-pane.composer-edge/wide-edge Apple System Colors unchanged 0% own App.tsx
agent-pane.composer-edge/no-edge Apple System Colors Light unchanged 0% own App.tsx
agent-pane.composer-edge/no-edge Apple System Colors unchanged 0% own App.tsx
agent-pane.composer-floats/scrolled-to-end Apple System Colors Light unchanged 0% own App.tsx
agent-pane.composer-floats/scrolled-to-end Apple System Colors unchanged 0% own App.tsx
agent-pane.composer-floats/composer-grown Apple System Colors Light unchanged 0% own App.tsx
agent-pane.composer-floats/composer-grown Apple System Colors unchanged 0% own App.tsx
agent-pane.continuation-spacing/shipped Apple System Colors Light unchanged 0% own App.tsx
agent-pane.continuation-spacing/shipped Apple System Colors unchanged 0% own App.tsx
agent-pane.continuation-spacing/two-thirds Apple System Colors Light unchanged 0% own App.tsx
agent-pane.continuation-spacing/two-thirds Apple System Colors unchanged 0% own App.tsx
agent-pane.continuation-spacing/half-tucked Apple System Colors Light unchanged 0% own App.tsx
agent-pane.continuation-spacing/half-tucked Apple System Colors unchanged 0% own App.tsx
agent-pane.continuation-spacing/before Apple System Colors Light unchanged 0% own App.tsx
agent-pane.continuation-spacing/before Apple System Colors unchanged 0% own App.tsx
agent-pane.copy-controls/output Apple System Colors Light unchanged 0% own App.tsx
agent-pane.copy-controls/output Apple System Colors unchanged 0% own App.tsx
agent-pane.docked-chat/new-chat Apple System Colors Light unchanged 0% own App.tsx
agent-pane.docked-chat/new-chat Apple System Colors unchanged 0% own App.tsx
agent-pane.docked-chat/after-turn Apple System Colors Light unchanged 0% own App.tsx
agent-pane.docked-chat/after-turn Apple System Colors unchanged 0% own App.tsx
agent-pane.docked-chat/working Apple System Colors Light unchanged 0% own App.tsx
agent-pane.docked-chat/working Apple System Colors unchanged 0% own App.tsx

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

Passes: CI passes on dfa690a5ce.

CI passes on dfa690a5ce (run 41123928102 attempt 3).

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

Shipped in:

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex, router-review): SHIP at dfa690a

SHIP

Visual verdict: SHIP — viewed both after screenshots; no visual regressions.

  1. No blocking findings. The targeted Bun test could not run because bun is unavailable in the review environment.

This branch was previously deployed

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

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant