Skip to content

cmux-next: open a chat in a new window from its menu - #17611

Merged
teamleaderleo merged 31 commits into
feat-cmux-nextfrom
feat-cmux-next-chat-new-window
Oct 8, 2026
Merged

teamleaderleo merged 31 commits into
feat-cmux-nextfrom
feat-cmux-next-chat-new-window

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 6, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

The agent chat's "..." menu gets Open in new window, as in the Codex desktop app. It sits after Move to new workspace.

  • The row runs the app's existing tab.moveToNewWindow on the chat's tab, the same action as the tab's own context menu. It joins the header's allowed actions (AgentPaneModel.headerActions).
  • The keycap comes from the action catalog when the user binds one. No key is added.
  • Quick Chat keeps its own Open in window. Its panel is not a tab, so its menu has no tab rows.
  • String: chatMenu.newWindow in all 21 locales.

Inventory: manaflow-ai/cmuxterm-hq#1417 (item 3 of the follow-ups).

Testing

  • The red commit (302efde) adds theMenuOpensTheChatInANewWindow in AgentPaneHeaderActionTests and a HEADER_ACTIONS.newWindow case in ChatHeaderTools.test.tsx. Recorded locally with bun test src/agent-session/acpmux/header/ChatHeaderTools.test.tsx: at the red commit 302efde, 6 pass and 1 fail (the menu opens the chat in a new window through the app's own action); at 3ff94f5, 7 pass and 0 fail.
  • The agent pane bundle and generated/strings.json are regenerated.
  • The Swift and web suites run on CI and the fleet; the local checkout has no web dependencies.
  • 3ff94f5 rebuilds the pane catalog as the merge base's text plus this branch's keys; the base merge had rewritten its layout (792 lines). The strings are unchanged.
  • Visible change: the agent chat's "..." menu has an Open in new window row after Move to new workspace.

Changelog

  • Added: Open a chat in a new window from its "..." menu.

🤖 Generated with Claude Code


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


Summary by cubic

Brings default-browser sign-in (ASWebAuthenticationSession) to cmux-next, adds Open in new window to the agent chat's "..." menu, and renders Codex accounts with the ChatGPT brand mark in both themes.

Default-browser sign-in
When cmux is the default browser, macOS routes every sign-in another app starts through a new session broker into a dedicated popup panel with a Chromium tab; ephemeral sessions use off-the-record profiles. The CEF shim cancels matching callback navigations before they load (cmux_shim_set_auth_callback / CMUX_SHIM_AUTH_CALLBACK), so OAuth codes never reach the network or another app, and the system's matcher confirms the callback. The capability key stays out of Info.plist until macOS delivers requests reliably, leaving the handler inert in current builds.

Agent chat and accounts
The "..." menu gains Open in new window, running the existing tab.moveToNewWindow (registered in header actions and shortcuts) with the string in all 21 locales; Quick Chat keeps its own Open in window. Codex rows show the ChatGPT brand mark with theme-aware colorScheme.

Written for commit 3ff94f5. Summary will update on new commits.

View guided diff Turn on auto-fix


Note

High Risk
New OAuth/sign-in interception in the CEF shim and session broker affects authentication callbacks and navigation policy; incorrect matching could break third-party logins or leak callback URLs.

Overview
Adds default-browser sign-in handling so other apps’ ASWebAuthenticationSession flows open in cmux-owned panels, complete on the callback URL, and cancel when the tab closes. A new Swift stack (WebAuthSessionHandler, broker, ephemeral off-the-record profiles) wires into the CEF shim via cmux_shim_set_auth_callback and a new CMUX_SHIM_AUTH_CALLBACK event that cancels main-frame navigations to the session callback before they load (matching custom schemes or https host/path in shared auth_callback_policy.h). CI gains test-auth-callback-policy-cpp.sh; broker and callback behavior are covered by new tests.

Agent chat “…” menu gets Open in new window (tab.moveToNewWindow), registered in AgentPaneModel.headerActions, shortcuts, acpmux header menu, and chatMenu.newWindow across locales.

Accounts UI: Codex rows use the ChatGPT brand mark with palette-driven color scheme; AccountsPalette exposes isDark.

Reviewed by Cursor Bugbot for commit 3ff94f5. Bugbot is set up for automated code reviews on this repo. Configure here.

teamleaderleo and others added 2 commits October 6, 2026 10:50
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The chat menu's Open in new window runs the app's tab.moveToNewWindow on
the chat's tab, after Move to new workspace. The string is in all 21
locales; the keycap comes from the action catalog when one is bound.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration
  • Configuration used: Repository: manaflow-ai/cmux/.coderabbit.yaml
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: f8b33533-0af6-4c86-b0b7-befcf5f62ae9

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Unclear: web / react-apps-check failed: no known signature; failed step: Check webviews (Oxlint, Oxfmt, type check).

CI failed on 3ff94f51cc (run 37849152094 attempt 1): 1 unknown.
macOS jobs did not run: compile and app tests were skipped: Fast static checks skipped.

Job Verdict Why
web / react-apps-check unknown no known signature; failed step: Check webviews (Oxlint, Oxfmt, type check)

Not re-run automatically: web / react-apps-check is not a machine failure.

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.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Batch queue: green. Batch stack b034a977a4d8 on feat-cmux-next d4056375d08d with #17537 #17597 #17599 #17602 #17604 #17609 #17611 #17613. Fleet production build: job 24360b4ae2a093d871aa1591 (cmux-ci artifact 24360b4ae2a093d871aa1591 (job 24360b4ae2a093d871aa1591, tag nb-local-20261006-180248-1)). heavy tier did not run on this branch (run); your PR's own checks are the tests. Validated this PR at de29bdeb7c2d.

Next: land it yourself with gh-merge-green on this receipt.

…ext-chat-new-window

# Conflicts:
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/ar.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/bs.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/da.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/de.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/en.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/es.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/fr.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/it.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/ja.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/km.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/ko.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/nb.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/pl.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/pt-BR.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/ru.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/th.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/tr.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/uk.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/vi.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/zh-Hans.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/zh-Hant.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/pane.js
…ext-chat-new-window

# Conflicts:
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/ar.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/bs.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/da.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/de.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/en.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/es.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/fr.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/it.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/ja.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/km.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/ko.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/nb.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/pl.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/pt-BR.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/ru.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/th.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/tr.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/uk.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/vi.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/zh-Hans.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/zh-Hant.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/pane.js
AgentPaneShortcuts.actions lists every header action, so the menu row
shows tab.moveToNewWindow's binding when the user sets one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Batch queue: green. Batch stack ed71230a0e11 on feat-cmux-next ff267c4b41d1 with #17541 #17611 #17624 #17625. Fleet production build: job 362a7927afa7714ace3f1b33 (cmux-ci artifact 362a7927afa7714ace3f1b33 (job 362a7927afa7714ace3f1b33, tag nb-local-20261006-190840-1)). heavy tier did not run on this branch (run); your PR's own checks are the tests. Validated this PR at 2a0aa075695c.

Next: land it yourself with gh-merge-green on this receipt.

…ext-chat-new-window

# Conflicts:
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/ar.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/bs.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/da.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/de.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/en.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/es.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/fr.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/it.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/ja.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/km.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/ko.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/nb.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/pl.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/pt-BR.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/ru.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/th.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/tr.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/uk.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/vi.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/zh-Hans.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/zh-Hant.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/pane.js
@cursor

cursor Bot commented Oct 6, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Reviewed the menu, allowed action, shortcut projection and Quick Chat exclusion. Open in new window uses the existing tab.moveToNewWindow action. No concrete correctness findings.

Merged feat-cmux-next through 36f2e07; head 3e60c34b621. This update only brings in base changes, with no conflict resolutions or changes to this PR’s behavior. The published fleet captures were inspected; they cover the earlier implementation, not this exact head. No new capture was taken for this base sync. Exact-head CI is running.

…ext-chat-new-window

# Conflicts:
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/ar.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/bs.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/da.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/de.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/en.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/es.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/fr.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/it.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/ja.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/km.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/ko.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/nb.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/pl.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/pt-BR.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/ru.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/th.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/tr.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/uk.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/vi.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/zh-Hans.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/zh-Hant.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/pane.js
…ext-chat-new-window

# Conflicts:
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/ar.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/bs.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/da.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/de.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/en.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/es.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/fr.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/it.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/ja.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/km.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/ko.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/nb.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/pl.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/pt-BR.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/ru.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/th.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/tr.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/uk.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/vi.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/zh-Hans.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/zh-Hant.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/pane.js
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Batch queue: green. Batch stack 05ed5a19dcf3 on feat-cmux-next 8096756a8d2c with #17609 #17611. Fleet production build: job cc4f4533d25cc5fc04a39a6f (cmux-ci artifact cc4f4533d25cc5fc04a39a6f (job cc4f4533d25cc5fc04a39a6f, tag nb-local-20261006-234630-1)). heavy tier did not run on this branch (run); your PR's own checks are the tests. Validated this PR at 23f3d597f422.

Next: land it yourself with gh-merge-green on this receipt.

lawrencecchen and others added 12 commits October 8, 2026 10:50
WebAuthSessionBrokerTests: a sign-in (ASWebAuthenticationSession) opens in
a tab, ends with its custom-scheme or https callback exactly once, is
cancelled when the tab closes, closes its tab when the system cancels, and
ephemeral sessions ask for a non-persistent profile. The shim's C++
callback rule (auth_callback_policy_test.cpp) cancels only the session's
own callback navigation.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…(cx-q3y7)

macOS hands the default browser every ASWebAuthenticationSession another
app starts once the browser declares
ASWebAuthenticationSessionWebBrowserSupportCapabilities and installs a
session handler. cmux now does both:
- WebAuthSessionHandler (installed at launch) passes each request to
  WebAuthSessionBroker, the one owner of pending sessions: each opens in
  its own sign-in panel (the popup panel: title, origin, close, Escape)
  with a Chromium page, ends once with its callback URL (the panel
  closes), and is cancelled when the person closes the panel; a system
  cancel closes the panel without an answer.
- The shim stops the callback before it loads
  (cmux_shim_set_auth_callback, auth_callback_policy.h: custom scheme, or
  https host and path; event AUTH_CALLBACK), so the code never reaches the
  network or another app. The system's matcher confirms it; observing the
  page URL is the last line when the callback could not be read.
- Ephemeral sessions use an off-the-record profile that ends with the
  panel; normal ones use the default profile (an existing sign-in stays).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… requests (cx-q3y7)

Live test on cmux-lawrence-2 (macOS 27.0.1) with a test app starting an
ASWebAuthenticationSession while cmux DEV was the default browser: the
system sent the session's Apple event and cmux's framework reported the
request, but SafariLaunchAgent never handed it over, so the handler was
not called. Chrome as the default browser fails the same way on that host
(no sign-in page), which points at the system (FB21939656 reports the same
on macOS 26.2). With the key declared, a sign-in would hang instead of
using Safari, so the key stays out; the handler stays installed and is
inert without it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ty is declared

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- A stopped https URL the system's matcher rejects loads once with the
  shim callback cleared (no stop-reload loop); a rejected custom-scheme
  link from a sign-in page does not open another app; a late event after
  the session ended does nothing.
- The callback opened in a new tab (target=_blank, window.open) still
  ends the session instead of leaking to a normal tab.
- A system cancel that arrives before its begin opens nothing; a repeated
  begin opens one panel.
- A log line when the callback could not be read.
- WebAuthSessionHandler.install installs only with the capability key
  (test: theHandlerInstallsOnlyWithTheCapabilityKey).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…oker file

CEFSignInCallbacks holds the sign-in tabs (set, re-applied on attach,
AUTH_CALLBACK routed by CEFRuntime), so CEFTab and AppServices stay under
the god-type limit; AppDelegate's WebAuthSessionHandler owns the broker.
WebAuthCallback and the session protocols get their own files.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… and its main-actor hop

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Generated from the published GhosttyKit archive using the standard release packaging and SHA-256 verification path.
* fix(cmux-next): render account registry marks in brand color

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(cmux-next): use theme tone and ChatGPT account mark

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/ar.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/bs.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/da.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/de.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/en.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/es.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/fr.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/it.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/ja.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/km.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/ko.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/nb.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/pl.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/pt-BR.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/ru.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/th.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/tr.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/uk.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/vi.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/zh-Hans.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/locales/zh-Hant.js
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/pane.js
@blacksmith-sh

blacksmith-sh Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

Found 1 test failure on Blacksmith runners:

Failure

Test View Logs
test_every_routed_input_triggers_the_workflow (main.PullRequestTiers.test_every_rou
ted_input_triggers_the_workflow) (path='Resources/bin/x')
View Logs

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

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Updated to 1f52b172f188201b05b0a45e6551e966f9a0c114 with one base merge. Removed generated bundle files and regenerated strings. The touched header web test file passed all 7 tests; fleet AgentPaneHeaderActionTests passed all 4 (job 485a901753ed45a0a184ce8a). Independent review found no correctness defect; the one added string covers all 21 locales. Before/after capture and failing-before native evidence remain missing. Hosted CI is red; this is scoped verification only.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Parked pending before/after capture proof.

teamleaderleo added a commit that referenced this pull request Oct 8, 2026
…, not 100 ms (#17655)

The property is that a full queue answers busy instead of waiting, and a
waiting queue would only answer at the deadline. A 100 ms bound measured
289 ms on a loaded runner (#17611); the bound is now 10 s against a 30 s
deadline.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The base merge rewrote the agent pane catalog's layout (792 lines
removed). Rebuild it as the merge base's text plus this branch's keys;
the strings are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Capture is no longer a merge gate. The behavior proof is the red-to-green test pair already recorded in the body: 302efdeda9f has 6 web tests passing and the new menu behavior failing, while 3ff94f51cc5 has all 7 passing; fleet AgentPaneHeaderActionTests also passes 4/4 (job 485a901753ed45a0a184ce8a). The visible native change is documented in the body: the agent chat ... menu adds Open in new window after Move to new workspace. The capture-only park is cleared.

@teamleaderleo
teamleaderleo merged commit 9ea27b7 into feat-cmux-next Oct 8, 2026
83 of 106 checks passed
@teamleaderleo
teamleaderleo deleted the feat-cmux-next-chat-new-window branch October 8, 2026 22:52
teamleaderleo added a commit that referenced this pull request Oct 8, 2026
…ledgement (cx-utqp) (#18685)

Under the width-6 shared-WebKit load of full CI the off-window spare misses the 50 ms
wall-clock acknowledgement budget, so the claim times out and reloads the document:
lastClaim .timedOut, the probe and the section are gone (#16604 job 113527809956,
#17611 job 113560067490). A manual clock, as cx-vno9 gave the parked-again test,
leaves the acknowledgement as the only way the claim ends.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
teamleaderleo added a commit that referenced this pull request Oct 9, 2026
…he palette (#16614)

* cmux-next agent pane: log every acpmux message and socket change

The agent pane now keeps a log of what it sent to and received from
acpmux: each JSON-RPC request, its reply or error with latency, each
notification, and the socket's lifecycle (connecting, open, close with
code, errors, reconnect delays, a lost daemon and the handshake that
follows). The log survives reconnects, never holds the daemon token, and is
bounded to 2000 entries and about 4 MB of message text.

window.cmuxAcpmuxDebug.acpLog and acpLogExport (JSON Lines) read it, so the
DEBUG debug.agent_pane socket method can fetch it. The inspector panel and
the export action build on this.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* agent-pane: add an ACP inspector panel

A header icon opens a panel over the transcript with the pane's wire log
(every ACP request, reply, notification and socket event, with latency),
the selected session's ACP journal, connection and session state, request
and error counts, latency p50 and max, a filter, expandable JSON rows and
an export as JSON Lines.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* agent-pane: save the ACP log natively and toggle the inspector from the palette

The inspector's Export now asks the host for a save panel (pane.saveLog,
capped at 16 MB) and copies the log only when the host cannot save; a
cancelled panel does nothing. Show ACP Inspector (agentPane.toggleInspector)
toggles the focused agent pane's inspector through the page bridge, and
debug.agent_pane gains an inspector action for dogfood capture.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Test opening the inspector from the current chat menu

* Test inspector journal selection and list isolation

* Open the localized ACP inspector from the chat menu

* Include inspector styles in the shipped agent pane bundle

* Run inspector checks against feat-cmux-next

* red: a workspace any daemon client creates lands at the top by default (cx-8351)

workspaces.newPlacement (top by default) is applied only by the Mac app
today: a plain workspace.create (TUI, CLI, iOS, agents) still gets the
last personal row. The test creates workspaces through the protocol with
Home and a group right below it and expects each new one first below Home,
above the group, stored across a restart.

* fix: the daemon puts every new workspace at workspaces.newPlacement, for every client (cx-8351)

The personal row a workspace gets in the commit that creates it (every
creation path: the app, iOS, the TUI, the CLI, agents) now goes where the
settings file's workspaces.newPlacement says, instead of last: top
(default, also for a missing or unknown value) right after the home
workspace's row, else first, ungrouped, so above every group at that
place; afterCurrent right after the session's active workspace before the
commit, in its group (top when there is none, it has no row, it is Home,
or the new workspace is pinned to another room than the group's); bottom
last. Several workspaces of one commit keep their order. Home always takes
the top; a reopened workspace is created last and then takes its closed
row's place, so no other row moves. The creation's session.events batch
carries each new and moved placement and each group whose top_index moved
(tests replay the events against the store).

Decision: the daemon reads the setting from the app's settings file itself
(new cmux_tui_core::user_settings: CMUX_NEXT_CONFIG_FILE, else
~/.config/cmux/cmux-next.json, else classic cmux.json before the app's
first launch; regular files only, cached by mtime and size; the JSONC
reader moved from the MCP config, which now reads the same file), not from
a field on the create intent: the order is the daemon's state, the file is
the config layer every client on the machine shares, it works while the
app is quit, and no protocol field or binding changes. A caller that wants
another place still sends workspace.place after the creation; that later
write wins. The managed (MDM) layer is not read.

App: the classic-session import names an explicit bottom slot, so its
batch keeps the saved order now that the daemon itself puts new
workspaces on top.

* Route inspector export through the shared page host and declare its action surfaces

* cmux-next: open a chat in a new window from its menu (#17611)

* test(cmux-next): the chat menu opens the chat in a new window (red)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* cmux-next: open a chat in a new window from its menu, Codex-style

The chat menu's Open in new window runs the app's tab.moveToNewWindow on
the chat's tab, after Move to new workspace. The string is in all 21
locales; the keycap comes from the action catalog when one is bound.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* cmux-next: the pane reads Open in new window's key from the catalog

AgentPaneShortcuts.actions lists every header action, so the menu row
shows tab.moveToNewWindow's binding when the user sets one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* cmux-next: red tests for serving other apps' sign-in sessions (cx-q3y7)

WebAuthSessionBrokerTests: a sign-in (ASWebAuthenticationSession) opens in
a tab, ends with its custom-scheme or https callback exactly once, is
cancelled when the tab closes, closes its tab when the system cancels, and
ephemeral sessions ask for a non-persistent profile. The shim's C++
callback rule (auth_callback_policy_test.cpp) cancels only the session's
own callback navigation.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* cmux-next: serve other apps' sign-in sessions as the default browser (cx-q3y7)

macOS hands the default browser every ASWebAuthenticationSession another
app starts once the browser declares
ASWebAuthenticationSessionWebBrowserSupportCapabilities and installs a
session handler. cmux now does both:
- WebAuthSessionHandler (installed at launch) passes each request to
  WebAuthSessionBroker, the one owner of pending sessions: each opens in
  its own sign-in panel (the popup panel: title, origin, close, Escape)
  with a Chromium page, ends once with its callback URL (the panel
  closes), and is cancelled when the person closes the panel; a system
  cancel closes the panel without an answer.
- The shim stops the callback before it loads
  (cmux_shim_set_auth_callback, auth_callback_policy.h: custom scheme, or
  https host and path; event AUTH_CALLBACK), so the code never reaches the
  network or another app. The system's matcher confirms it; observing the
  page URL is the last line when the callback could not be read.
- Ephemeral sessions use an off-the-record profile that ends with the
  panel; normal ones use the default profile (an existing sign-in stays).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* cmux-next: do not declare the sign-in capability until macOS delivers requests (cx-q3y7)

Live test on cmux-lawrence-2 (macOS 27.0.1) with a test app starting an
ASWebAuthenticationSession while cmux DEV was the default browser: the
system sent the session's Apple event and cmux's framework reported the
request, but SafariLaunchAgent never handed it over, so the handler was
not called. Chrome as the default browser fails the same way on that host
(no sign-in page), which points at the system (FB21939656 reports the same
on macOS 26.2). With the key declared, a sign-in would hang instead of
using Safari, so the key stays out; the handler stays installed and is
inert without it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* cmux-next: install the sign-in session handler only when the capability is declared

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* cmux-next: sign-in review fixes (cx-q3y7)

- A stopped https URL the system's matcher rejects loads once with the
  shim callback cleared (no stop-reload loop); a rejected custom-scheme
  link from a sign-in page does not open another app; a late event after
  the session ended does nothing.
- The callback opened in a new tab (target=_blank, window.open) still
  ends the session instead of leaking to a normal tab.
- A system cancel that arrives before its begin opens nothing; a repeated
  begin opens one panel.
- A log line when the callback could not be read.
- WebAuthSessionHandler.install installs only with the capability key
  (test: theHandlerInstallsOnlyWithTheCapabilityKey).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* cmux-next: sign-in callbacks off CEFTab and AppServices; split the broker file

CEFSignInCallbacks holds the sign-in tabs (set, re-applied on attach,
AUTH_CALLBACK routed by CEFRuntime), so CEFTab and AppServices stay under
the god-type limit; AppDelegate's WebAuthSessionHandler owns the broker.
WebAuthCallback and the session protocols get their own files.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* cmux-next: crash-allow the SDK's implicitly unwrapped sign-in request and its main-actor hop

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* ci: pin GhosttyKit for ghostty 17357e12 (#18598)

Generated from the published GhosttyKit archive using the standard release packaging and SHA-256 verification path.

* fix(cmux-next): render account registry marks in both themes (#18081)

* fix(cmux-next): render account registry marks in brand color

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(cmux-next): use theme tone and ChatGPT account mark

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix: keep the pane catalog in base's layout

The base merge rewrote the agent pane catalog's layout (792 lines
removed). Rebuild it as the merge base's text plus this branch's keys;
the strings are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Lawrence Chen <54008264+lawrencecchen@users.noreply.github.com>

* test(pages): a rebound pooled page view forgets the old page's activation; submenu choice counts (red, cx-qoxe)

Red on cmux-lawrence-2 (nx-remote 1008-154834-be660b): retarget and
resetPooledPage keep the old document's gesture timestamp. The submenu test
is new coverage of the menu walk (already green).

* fix(pages): a rebound or parked pooled page view forgets the old page's activation (cx-qoxe)

retarget and resetPooledPage now clear PageWKWebView's gesture timestamp and
opened context menu, so a new document cannot use a click or key the person
made in the previous one for clipboard.write or person-only actions.

Gate: cmux-lawrence-2 nx-remote 1008-155539-e0ff66, PageUserActivationTests,
PageHostRetargetTests, PageHostPoolTests, PageDesktopDefaultsTests,
PageRouterTests, PageProvidersTests green.

* Test inspector action focus intent for automation

* Require explicit focus intent for automated inspector toggles

* Regenerate inspector action exports and complete localization audit

* ci(cmux-next): repin app FFI to published source (#18575)

* ci(cmux-next): repin app FFI to published source

The f1a32f1 build passed the app FFI release checks. Pin its immutable release and checksum so the target push verifies the current sources.

* ci(cmux-next): pin app FFI for current base

* cmux-tui-core: red tests: legacy ops, TUI workspace ops and older ledgers record the daemon (cx-44j.5 landing 3b)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* cmux-tui-core: legacy ops, TUI workspace ops and older ledgers record their actor (cx-44j.5 landing 3b)

P8 landing 3b (plans/cmux-next/identity.md section 3). The paths that still
recorded `daemon` for a caller now record the caller's actor:

- Legacy commands pass the connection actor: select-tab, close-pane /
  close-screen / close-tab-group with end_terminals (and the
  close-screen-group end_terminals branch), move-tab-to-split/column,
  move-tab-to-workspace, set-column-dock, set-row-heights, undo-layout,
  apply-layout, every tab group and screen group command
  (StripRequest::local takes an actor), set-tab-pinned, notify, the keyed
  bookmark ops, bind-conversation-tab-session, update-frontend-browser-tab
  owner, and the provider-managed close/rename.
- The in-process TUI (Session::Local) closes, renames and moves workspaces
  and undoes layouts as the local user.
- terminal.move projections, the v2 workspace.close effect and the
  apply-layout rollback commit as their caller. Agent hooks, terminal OSC
  notifications, reaps, runtime commits, interrupted-creation recovery and
  host-loss respawn stay the daemon's own work.
- The older ledgers (mutations, terminal_mutations, projection_mutations,
  bookmark_mutations) get a nullable actor column (design D: NULL reads
  `legacy`, an older daemon that omits it keeps working) and one shared
  write, insert_keyed_mutation. A fresh journal record takes the actor of
  the row its own commit wrote, matched by (origin, key), so another
  origin's row under the same key never lends it its actor.
- Key-less op names exist only under cfg(test)
  (mux/legacy_actor_test_wrappers.rs, TuiMuxOps, DaemonMuxOps).
- mux/tab_groups/reopen_saved.rs and server/group_outcome_json.rs move code
  out of two god files (no baseline raised).

Test fix vs the red commit: the undo check reads the effect receipt too
(a layout undo is effectful).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* red: the top of the first remote row in one list is a slot of that computer (cx-hzpd)

Restores SidebarOntoGroupTests.theTopOfARowReorders to the flat list
(sidebar.groupByComputer off, the default); cx-plf5 had switched it to
grouping-on.

* fix(sidebar): the open gap holds when the card's leading edge is over rows it cannot join (cx-hzpd)

In the one-list sidebar (sidebar.groupByComputer off) a remote computer's
rows follow the local rows with no header. Dragging a remote workspace to
the top of its computer's first row opened the gap there, the card's
centre then sat in that gap, and the leading edge (the card's top, over
the last local row) decided: a slot among the local rows, which a remote
workspace cannot take, so the drop was refused.

Rule: with the centre in the open gap, that gap is the drop the list
shows; the leading edge moves it only to a slot the dragged rows can
take, else the gap holds. Away from the gap an unreachable slot still
refuses the drop.

---------

Co-authored-by: Lawrence Chen <54008264+lawrencecchen@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Resolve concurrent catalog additions and regenerate pane strings

* Keep inspector strings outside concurrently changed catalog rows

* agent-pane: ACP inspector panel (#16604)

* cmux-next agent pane: log every acpmux message and socket change

The agent pane now keeps a log of what it sent to and received from
acpmux: each JSON-RPC request, its reply or error with latency, each
notification, and the socket's lifecycle (connecting, open, close with
code, errors, reconnect delays, a lost daemon and the handshake that
follows). The log survives reconnects, never holds the daemon token, and is
bounded to 2000 entries and about 4 MB of message text.

window.cmuxAcpmuxDebug.acpLog and acpLogExport (JSON Lines) read it, so the
DEBUG debug.agent_pane socket method can fetch it. The inspector panel and
the export action build on this.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* agent-pane: add an ACP inspector panel

A header icon opens a panel over the transcript with the pane's wire log
(every ACP request, reply, notification and socket event, with latency),
the selected session's ACP journal, connection and session state, request
and error counts, latency p50 and max, a filter, expandable JSON rows and
an export as JSON Lines.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Test opening the inspector from the current chat menu

* Test inspector journal selection and list isolation

* Open the localized ACP inspector from the chat menu

* Include inspector styles in the shipped agent pane bundle

* Run inspector checks against feat-cmux-next

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* cmux-next: tab hover cards without empty thumbnails or unavailable text (#17636)

* test(cmux-next): tab cards drop empty thumbnails and unavailable resources

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(cmux-next): tab cards drop empty thumbnails and unavailable resources

A tab with no resource numbers (an agent chat, the New Tab page) showed
"Resource usage unavailable" over an empty thumbnail frame. The card now
leaves out the resource line when the sample says unavailable and drops
the thumbnail once its fetch returns none, remembered per tab so the next
hover opens at the right size.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* test: reject inspector toggles on hidden surfaces

* fix: reject inspector toggles on hidden surfaces

* Keep inspector save panel and bridge handlers in focused owners

* Follow the existing reply type in the namespace lint ratchet

* Keep inspector strings separate from concurrently removed dialog strings

* Declare the stable inspector callback in the bridge effect

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Lawrence Chen <54008264+lawrencecchen@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants