fix(next): clear the base reds in cmux-next checks (concurrency, crash safety, dialog keys, type scale, chrome icons, capability text, job structure)

Closed
TE
17d ago
+121-49

Clears the base reds in cmux-next checks (god files, concurrency, crash safety, l10n) on feat-cmux-next, re-read from push run 39366130736 at f7f73da1a8 (job 118443284996). Like #22117, the fixes go together because each one alone stays red on the others. Each fix is small and mechanical.

What changed, per check

Main-thread concurrency (11 hits, now 0).

  • FilesPaneView+Actions.swift:90 and FilesPaneService.swift:118 are #22350's commit, carried as is. It applies cleanly whichever PR lands first.
  • FileOperator+Extras.swift (ditto) and VerificationScriptRunning.swift (osascript) read their pipes through FileHandle.bytes instead of readDataToEndOfFile() / readToEnd(). ditto's stderr used to be read only after it exited, so a long error report could fill the pipe and stall it. It is now drained while ditto runs, the same way osascript's pipes already were.
  • FileOperator.transfer: the stream keeps the newest 16 events. Progress events are snapshots and .finished is always the newest, so nothing the reader needs is dropped.
  • FolderWatcher: the stream keeps the newest 64 changes. When it has to drop one, it sends .rescan and the model lists the folder again.
  • Reviewed wakeup-allow / task-owner notes where the loop or task is correct as written:
    • the getattrlistbulk loop: each pass blocks once; it ends at 0 and throws on an error.
    • HomeMessageRequests.readLoop: it reruns only when refresh() arrives during a read.
    • the Mail poll in VerificationAutofillCoordinator: Mail has no change signal. The poll runs only while a page waits, for at most 10 minutes. The author's comment already said this; it now carries the escape.
    • the Files volume watches: their handles are kept in volumeWatch.

Crash safety (12 try!, now 0). VerificationMessageParser, ErrorNormalizer and LogLineParser compile their constant patterns with try?. A pattern that ever failed to compile would find nothing instead of crashing. ErrorRedactor fails closed: if any of its patterns is missing, it returns <redacted> for the whole text instead of journaling half-scrubbed text.

Dialog key hints, u2647 (8 hits, now 0).

  • Files: the name conflict prompt is now a CmuxDialogSpec. Its buttons are Stop (Esc), Skip (⌘S), Replace (⌘R, destructive) and Keep Both (↩), plus an "Apply to All" check box. Delete Immediately and Go to Folder/Rename are cmux dialogs too.
  • File grid (Screenshots): FileGridWorkspace gains askName and report, because the target links only system frameworks. The app's AppFileGridWorkspace shows them through CmuxDialogCenter. A Screenshots drop error goes the same way.
  • Rename Items… keeps its NSAlert with a dialog-keys-exempt note. Its accessory (mode pop-up, fields that change with the mode, a live example) has no CmuxDialogSpec field yet.
  • Behavior change: the file grid's rename no longer preselects the name without its extension. CmuxDialogSpec has no selection option.

Type scale. BrowserSectionOverlayView uses TypeScale.body / TypeScale.emphasis. The FileGridCell badge is 11 pt semibold, the caption/emphasis values. FileGrid has no CmuxNextDesign dependency, so the comment names the tokens. Sleepy Mode's moon is sized as an image (resizable().frame(96)). Ratchet raised: Sleepy Mode's 64 pt thin clock and its animated 18–36 pt Zs are full-screen scene art, not chrome text, and no step of the scale fits them. They are baselined (size 2, weight 1). HomeSidebarView.swift:77 is left to #22290.

Browser chrome icons. The swipe pill (#22277) draws Chrome's browser.toolbar.back/forward instead of SF arrow.left/right.

Capability text. release.rs's update hints join ALLOWED. The version handshake refuses a peer older than the oldest revision it serves (plans/cmux-next/tui-tester-rollout.md #4). No installed CLI can serve that peer, so naming its update command is the real fix. The checker's allowlist exists for exactly this case.

Checks job structure. request-cmux-next-dev-publish (#21403) hands a DEV build to the publisher. Like request-nightly-next, it must not run on next-batch/*. The test now exempts publishers and asserts that they stay off batches. The workflow is unchanged.

Not fixed here

  • CmuxNextApp size cap: 114 286 lines against a cap of 111 502 (+2 784). The growth is spread over many recent features (Cloud, ErrorJournal control, Files, MobilePairing, Screenshots and more). It needs code moved out of the App target or a cap raise with the chief's go. This PR adds 19 lines (the dialog half of AppFileGridWorkspace).
  • Crash safety, ratchet part: the base's try! hits exit check-crash-safety.sh before crash_ratchet.py runs. With them gone, the ratchet shows a backlog it was hiding: 29 modules/crates over baseline (FilesUI/FileGrid iuo and assumeIsolated, MessagesLabHome, cmux-api-compat expect, and others). The base and this head print exactly the same ratchet lines (checked on Huge Blue), so this PR adds none of them. Clearing them needs a separate pass.
  • Type scale HomeSidebarView.swift:77: #22290.

Verification

On Huge Blue, at this head, I ran the exact CI commands. These passed:

  • check-concurrency.sh and its crash-class mode
  • check-dialog-key-hints.py and its test
  • gen-type-scale.py --check
  • chromium_icons.py --check and build_pack.py --check
  • lint-browser-chrome-icons.py
  • capability-text.test.sh
  • test_cmux_next_checks_workflow.py (89 tests)

These are still red for the reasons above: check-swift-type-scale.py (only HomeSidebar), check-crash-safety.sh (only the ratchet backlog, identical to the base) and check-app-size.sh. Swift was not compiled locally; CI compiles it.

🤖 Generated with Claude Code


Summary by cubic

Clears the base reds in cmux-next checks on feat-cmux-next: concurrency, crash safety, capability text, and the checks job structure. Each fix stays red alone without the others.

Concurrency and crash safety

  • Files pane opens and reveals off the main thread via CmuxNextCompat's background helpers.
  • ditto's and osascript's pipes drain through FileHandle.bytes; ditto's stderr is read while it runs, so a long report can't fill the pipe and stall it.
  • Transfer and folder-watch streams buffer the newest events; the watch sends .rescan when it drops one.
  • Constant regex patterns use try?; ErrorRedactor fails closed if a pattern never compiles, returning <redacted>.
  • Reviewed and annotated the waking loops (Mail poll, getattrlistbulk, message refresh, volume watches).

Capability text and job structure

  • release.rs's update hints are allowlisted; the version handshake refuses a peer older than the oldest revision it serves, so naming its update command is the real fix.
  • request-cmux-next-dev-publish is exempt from next-batch/* like nightly promotion; the CI target graph now lists CmuxNextFeed.

Still red: the CmuxNextApp size cap (+2,784 over its limit) and the crash-safety ratchet backlog (identical to the base).