Skip to content

cmux-next: keep the omnibar edit through a light/dark switch - #17633

Merged
teamleaderleo merged 22 commits into
feat-cmux-nextfrom
fix-next-omnibar-theme-edit
Oct 10, 2026
Merged

teamleaderleo merged 22 commits into
feat-cmux-nextfrom
fix-next-omnibar-theme-edit

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 6, 2026 •

Copy link
Copy Markdown
Collaborator

Switching light/dark (or auto dark mode at sunset) while a browser address bar is focused crashed cmux-next with a stack overflow. The address bar now keeps its edit through an appearance change: typed text, selection and focus stay put.

ChromeTextField recolors its placeholder on every appearance change through NSTextField.placeholderAttributedString. While the field is editing, that setter ends and restarts the edit. Ending it posts end-editing, which ran the omnibar's focus-lost path and the window's focus coordinator inside AppKit's endEditingFor:; the coordinator refocused the address bar, whose chrome refresh did more theme work, and the stack ran out (crash report frames: ChromeTextField.applyPlaceholder → -[NSCell _restartEditingWithTextView:] → ShellWindow.makeFirstResponder → FocusCoordinator → AddressBarView.focus → OmnibarPillView.refresh).

Text fields now set the placeholder on their cell while an edit is active, which only redraws. ChromeSecureTextField (the HTTP auth password field) had the same setter and uses the same helper.

Found in the 2026-10-06 complaint sweep: https://github.com/manaflow-ai/cmuxterm-hq/issues/1421

Testing

  • Live repro on the fleet build of 96f7421 (the sweep build): open an agent chat, add a Terminal split and then a Browser split, click into the empty address bar of the narrow browser pane, switch light/dark. It crashes every time with the stack above (two crash reports, 11:57 and 13:41). The same steps on a fleet build of this branch are recorded below.
  • OmnibarViewTests.appearanceChangeWhileEditingKeepsTheEdit types into the omnibar (and empties it) in a key window, flips to dark, and expects the edit, its text, and no omnibar events. It guards the behavior but passed without the fix too: I couldn't make the offscreen test harness take AppKit's restart-editing path, so it doesn't reproduce the crash. That's why the branch has three test commits.

Changelog

  • Fixed: switching light/dark mode while typing in a browser address bar no longer crashes cmux.

🤖 Generated with Claude Code


Note

Medium Risk
Broad CI and branch-autofix behavior changes (tree fallback, bot placement, optional pushes to feat-cmux-next) sit alongside a localized AppKit text-field fix.

Overview
Fixes a stack overflow when switching light/dark while the browser address bar is focused by updating placeholders through the text field cell during an active edit (setPlaceholderKeepingEdit) instead of placeholderAttributedString, which restarted editing and looped through focus chrome. The same helper is used on the secure password field.

The diff also lands a large cmux-next / CI batch: Swift canary as the PR gate for small package-only CmuxNext edits (Release compile advisory on those PRs); cmux-tui rustfmt on touched packages in cmux-tui-spec; base autofix on feat-cmux-next after cmux-next (generated files + cargo fmt, dry-run until CMUX_NEXT_BASE_AUTOFIX=1); tree probe fallback so PRs that do not touch cmux-tui can run daemon/scheme jobs on the newest published tree instead of failing; gallery-pr 4-way sharding plus narrow/normal pane widths; pre-commit vp fmt / staged rustfmt; manifest binary verify retries on transient digest mismatches; MessagesLab Chief subagent links moved to URL.isChiefSubagentLink; and assorted placement/nightly timeout tweaks.

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

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: ec55b2ca-39fa-435d-b0eb-e1646e0575af

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
  • Autofix · 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

Not verified: macOS jobs did not run: compile and app tests were skipped on 6382f68594; ci-status is green without them.

CI passes on 6382f68594 (run 38017450854 attempt 1).
macOS jobs did not run: compile and app tests were skipped: Fast static checks skipped (the macos job needs both to succeed). Re-run CI once they pass, before merging.

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.

The placeholder only restarts editing while it shows.

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

The offscreen harness window cannot become key, and AppKit restarts an
edit only in the key window.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
teamleaderleo and others added 2 commits October 6, 2026 13:34
Setting NSTextField.placeholderAttributedString mid-edit ends and restarts
the edit, which ran the focus coordinator inside AppKit's endEditing and
overflowed the stack. Write the cell's placeholder while editing.

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

Copy link
Copy Markdown
Collaborator Author

Batch queue: green. Batch stack b2ae9b9ef0f0 on feat-cmux-next 044508d44ee8 with #17609 #17611 #17620 #17623 #17630 #17633 #17635 #17636 #17648. Fleet production build: job d26b5daf716cd175c2f38aa0 (cmux-ci artifact d26b5daf716cd175c2f38aa0 (job d26b5daf716cd175c2f38aa0, tag nb-local-20261006-225524-1)). heavy tier did not run on this branch (run); your PR's own checks are the tests. Validated this PR at d77fda542a7f.

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

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Updated to ff40763d848cab06391feed2f3e75f57173ee48e with one base merge. Focused fleet OmnibarViewTests: 4 passed (job 61596515c218ce84e46339dc). Independent review found no production-code defect. The added regression still lacks failing-before proof, so this remains held. Hosted CI is red; this is scoped test evidence only.

lawrencecchen and others added 2 commits October 9, 2026 19:22
…a static-only type [cx-94dl]

35a61bd added enum HomeAppLinks (all-static public surface), which
lint-ios-package-conventions.sh refuses; cdd28b4 got past the lint by
making it a struct with an empty public init. URL.isChiefSubagentLink is
the same check on the receiver type; behavior is unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
teamleaderleo and others added 13 commits October 9, 2026 19:26
…18896)

* test(ci): the base autofix regenerates without touching frozen paths (red)

base-autofix.sh copies the Mac job's regenerated files into a checkout,
skipping frozen paths, and adds a missing cmux-tui tree input to both
lists. Red: the script does not exist yet.

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

* ci: a base autofix bot commits generated files, tree inputs and fmt

After each cmux-next run on a feat-cmux-next push, cmux-next-base-autofix
repairs the mechanical reds in one commit on top of it: the generated
files the Mac generated-files job rebuilt (its cmux-next-generated-patch
artifact, so no fleet Mac), missing cmux-tui tree inputs and cargo fmt in
cmux-tui. Frozen paths (base-autofix-frozen.txt) are reported and never
written; the app FFI pin stays with the app-ffi-repin pull request.

The push uses a GitHub App token minted only for the push step and a
plain push that never overwrites a moved base. Dry run until the repo
variable CMUX_NEXT_BASE_AUTOFIX is 1.

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

* test(ci): the base autofix never writes a workflow file (red)

The bot pushes with GITHUB_TOKEN, which cannot push .github/workflows
changes. A regenerated workflow file is skipped and reported, and a
missing cmux-tui tree input (its second list is cmux-tui-artifacts.yml's
paths) is reported without writing either list. Red: both are written.

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

* ci: the base autofix pushes as github-actions[bot] with GITHUB_TOKEN

No GitHub App: the job's GITHUB_TOKEN (contents: write) pushes the
repair; no ruleset or branch protection applies to feat-cmux-next.
GITHUB_TOKEN cannot push workflow files, so every .github/workflows path
is frozen for the bot, and missing cmux-tui tree inputs (whose second
list is cmux-tui-artifacts.yml's paths) are reported, not written. Its
pushes start no workflow: the next push's cmux-next run verifies the
repair commit. The trigger also checks the run's workflow path.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…x-tui crate (#18913)

36c60c8 moved the image paste spool into cmux-tui-image-paste, and
cmux-tui-core's lib.rs re-exports it (use cmux_tui_image_paste::
image_paste;). The image staleness guard (8e23f8a, cx-4l51) only
looked for crate::image_paste under cmux-tui-core, found 9 constants
named CAPABILITY and failed, so release rails is red on every PR and on
nightly-next. A crate:: path whose first segment lib.rs re-exports from
a workspace crate now also names that crate's module file.

No bead (repairs the cx-4l51 guard).

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* ci: format staged files in the trusted pre-commit hook

* ci: guard formatter scope for staged files

* ci: scope Rust formatter guard to its package

* ci: use direct rustfmt and skip merge formatting

* ci: pass the cmux-tui Rust edition to rustfmt
* test(ci): red test, PRs check rustfmt on the cmux-tui packages they touch

PR CI never runs cmux-tui.yml (dispatch only), so #18706 landed
unformatted Rust and broke base cargo fmt --check. These tests pin a
helper that runs cargo fmt --check once per touched package, checks
every package when a rustfmt config changes or there is no base, and
names each unformatted package.

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

* ci: check rustfmt on the cmux-tui packages a PR touches

PR CI never runs cmux-tui.yml (dispatch only), so #18706 landed
unformatted Rust and broke base cargo fmt --check. cmux-tui-spec.yml
already runs on every PR and push touching cmux-tui/** on hosted Linux;
its new rustfmt job runs cmux-tui-fmt-changed.py, which maps each changed
.rs file or Cargo.toml to its nearest tracked package and runs cargo fmt
--check on it with the pinned toolchain. No build and no dependency
download. A rustfmt config or toolchain change, or no base, checks every
package; vendored crates and deleted packages are skipped. A PR compares
with its merge commit's first parent, a push with the commit before it.

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

* style(cmux-tui): rustfmt acpmux's draft tests and the relay circuit

The new rustfmt job's full run found two base packages that fail
cargo fmt --check: acpmux, from #18706's draft tests and their module
order, and the Cloudflare relay's circuit.rs. Formatting only, exactly
the hosted rustfmt diff.

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

* style(cmux-tui): leave the relay circuit to its own repair

Touching the Cloudflare relay runs its lane, whose npm audit is red on
base (sharp and undici advisories through wrangler, fixed only by a
wrangler bump outside the stated range). That is the relay's own repair,
so this PR keeps acpmux's formatting only.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* ci: add mini-first Swift canary for cmux-next

* ci: remove unit tests from Swift canary change
…e cmux-tui (#18698)

* test(cmux-next): red: a PR that changes no cmux-tui fails same-tree on an unpublished merge tree

#16614, #17551 and #18605 change no cmux-tui or ghostty-next path, yet
same-tree cmux-tui failed them because the base tip's tree was never published
(its artifacts run was cancelled). Such a PR should reuse the newest published
tree in its history (tree_fetch_key, fetched through CMUX_TUI_TREE_KEY), or skip
the tree jobs when none is published, never fail.

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

* ci(cmux-next): same-tree cmux-tui is a hard check only for PRs that change cmux-tui

Path routing records whether the pull request's own diff touches cmux-tui/ or
ghostty-next. For one that does not, a merge tree that is not ready no longer
fails: the probe (CMUX_TUI_TREE_BASE_FALLBACK=1) resolves the newest published
tree in the merge's history and reports ready with tree_fetch_key, which the
daemon tests and the Debug scheme compile fetch through CMUX_TUI_TREE_KEY; with
none published it reports skipped. Pushes, dispatches and PRs that change
cmux-tui keep the hard check.

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

* fix(cmux-next): the newest-published search deepens only this commit's history

A bare `git fetch --deepen=50 origin` deepens every branch of origin: on this
PR's first run it took path routing past its 5-minute limit (job 113609407061)
before the probe's base fallback, which then resolved in under a second.
Deepening only HEAD takes about 30 s on a depth-2 clone of feat-cmux-next.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* docs(cmux-next): map UI parity reference sources

* docs(cmux-next): add media preview reference source

* docs(cmux-next): define reference freshness checks
* test(nightly): the notes step cannot spend the publish budget before the upload (red)

Run 37611677848 spent 29 of publish-nightly's 30 minutes on release notes and
was cancelled mid-upload, leaving partial release assets.

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

* fix(nightly): bound the publish notes step at 10 minutes

The notes take seconds since 0115b26. A regression now fails the step
before any asset upload, instead of spending publish-nightly's 30 minutes and
being cancelled mid-upload with partial assets left on the release.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…self (#17622)

* test(cmux-next): the cmux-tui gate pins and dispatches an unpublished tree itself

Publisher run 37505519359 failed transiently and its retry was replaced by a
newer feat-cmux-next push, so the tree was never published and lanes pushed
cmux-tui-pin-* branches by hand to unblock their gates.

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

* test(cmux-next): the tree gate watches the base and may pin the tree

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

* ci(cmux-next): the cmux-tui gate pins and dispatches an unpublished tree

When two run checks find no artifacts run that will publish the tree, the
gate creates cmux-tui-pin-<key12> at the publisher commit and dispatches the
artifacts workflow there, once, then keeps waiting. A pull request now
watches its base commit (the merge's first parent) instead of no publisher,
so it neither waits 45 minutes for a tree nobody builds nor needs a lane to
push a pin branch by hand. A superseded push still skips; forks keep a
read-only token and no autopin.

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

* test(cmux-tui): a transient wrong binary read must not fail publication

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

* fix(cmux-tui): read a mismatched published binary again before failing

R2 objects are write-once, so a digest mismatch on a binary the run just
uploaded is a bad read. Fetch it again from a cache-busting URL up to
three times, and name the response headers when it still differs.

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

* test(cmux-next): a pull request gate pins a tree its base never builds

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

* ci(cmux-next): a pull request gate pins a tree its base never builds

A pull request that changes cmux-tui has a merge tree no push builds,
and the artifacts workflow's pull_request_target trigger has never
started a run, so its gate waited 45 minutes with the run check off.
With CMUX_TUI_TREE_AUTOPIN the gate now pins its own checkout at once
and watches that run.

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

* ci(cmux-next): retain base tree dispatch tests

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* ci(gallery): capture narrow responsive states

* test(gallery): cover workflow matrix changes

* fix(gallery): dedupe equal responsive widths

* ci: shard gallery matrix renders

* ci: retrigger sharded gallery validation
Base deleted OmnibarViewTests.swift (no unit tests in cmux-next); kept the
deletion, dropping this PR's added test case. Source fix unchanged.

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

blacksmith-sh Bot commented Oct 10, 2026 •

Copy link
Copy Markdown

Found 2 test failures on Blacksmith runners:

Failures

Test View Logs
test_every_reused_workspace_checkout_retries_once_from_a_fresh_repository (main.Cmu
xNextCheckoutRetryTests.test_every_reused_workspace_checkout_retries_once_from_a_fresh_
repository) (job='swift-canary')/
test_every_reused_workspace_checkout_retries_once_from_a_fresh_repository (main.Cmu
xNextCheckoutRetryTests.test_every_reused_workspace_checkout_retries_once_from_a_fresh_
repository) (job='swift-canary')
View Logs
test_every_submodule_free_checkout_on_an_owned_runner_resets_submodules (main.Reuse
dWorkspaceSubmodules.test_every_submodule_free_checkout_on_an_owned_runner_resets_submo
dules)/
test_every_submodule_free_checkout_on_an_owned_runner_resets_submodules (main.Reuse
dWorkspaceSubmodules.test_every_submodule_free_checkout_on_an_owned_runner_resets_submo
dules)
View Logs

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

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 6382f68. Configure here.

contents: read
timeout-minutes: 20
env:
CMUX_NEXT_RUNNER: ${{ needs.macos-placement.outputs.runner || github.repository_owner != 'manaflow-ai' && 'macos-26' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && 'blacksmith-6vcpu-macos-26' || vars.CI_PR_POOL_OWNED == '1' && contains(fromJSON('["pull_request","push","workflow_dispatch"]'), github.event_name) && (github.run_attempt <= 2 || github.triggering_actor != 'github-actions[bot]') && vars.CI_SIDE_LANE_RUNNER || vars.MACOS_RUNNER_26 || 'blacksmith-6vcpu-macos-26') }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Canary skips Blacksmith overflow retry

High Severity

swift-canary still prefers macos-placement.outputs.runner on every attempt, unlike the other Mac jobs that drop that label on bot attempt 4. A rescue rerun of a refused mini therefore keeps the canary on the same placement label, so the merge gate for package-only Swift PRs can sit queued instead of overflowing to Blacksmith.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 6382f68. Configure here.

triggering_actor="github-actions[bot]")), FALLBACK)
self.assertEqual(evaluate(runs_on, self.context(fork=True)), FALLBACK)

def test_a_bot_attempt_4_leaves_the_placement_label_for_blacksmith(self):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Placement JOBS omit canary sync

Medium Severity

macos-placement now lists swift-canary first in JOBS, but the side-lane wiring tests still expect the old five-job set. test_every_mac_job_reads_the_placement fails on that mismatch, and the overflow cases never evaluate the new job, so the incomplete canary runs-on is not caught.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 6382f68. Configure here.

@teamleaderleo
teamleaderleo merged commit aecca9e into feat-cmux-next Oct 10, 2026
81 of 101 checks passed
@teamleaderleo
teamleaderleo deleted the fix-next-omnibar-theme-edit branch October 10, 2026 03:55
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