Repository navigation
test(ci): nightly jobs that run the license check must init ghostty-next - #20893
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… check Apple accepted, stapled and launch-tested each recovered nightly-next build, then verify-app-bundle-licenses.sh failed on the missing ghostty-next/build.zig.zon and the build was skipped as not accepted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
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. Comment |
|
Bead |
…tly-recovery-notices-submodule # Conflicts: # .github/workflows/nightly.yml
Bugbot needs on-demand usage enabledBugbot uses usage-based billing for this team and requires on-demand usage to be enabled. A team admin can enable on-demand usage in the Cursor dashboard. |
#20880) * cx-tgf4h red: cmux chief -p under ACPMUX_AGENT_LAUNCH=deny fails at once with a typed refusal * cx-tgf4h: the Chief says at once that agents are disabled in this build session With ACPMUX_AGENT_LAUNCH=deny (the nx-remote gui/input default since HQ #2130) or CMUX_AGENTS_DISABLED=1, no Chief turn can start an agent. `cmux chief -p` started a daemon and a brain and waited 240 s for a reply that could not come. - cmux-tui-core agent_launch: one test of the kill switch (acpmux launch_policy.rs), the reason agent_launch_disabled. - `cmux chief` (pipe and chat) refuses before it starts or sends anything: operation.failed, details.reason agent_launch_disabled, exit 1. - The daemon's supervisor starts no Chief brain; chief.engine.* and chief.stop answer the typed refusal at once. - optchat-chief host does not start (logs why, exit 0). - Home: the local Chief conversation's notice says agents are disabled; the engine panel maps the typed refusal (localized, all Home languages). - Every Chief proof script refuses at once under deny and names `nx-remote --allow-agents`. * test: code pages follow the terminal font; font variables resolve Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cx-tgf4h review: forward chief control to a running brain first; daemon-side deny test; engine/stop CLI text; guard before side effects; fmt * acpmux tests: every acpmux process a test starts gets a hermetic environment (cx-s8wux) One helper, tests/support/daemon_env.rs, starts the acpmux binary for every integration test: env_clear, a bare PATH (python3 plus named host tools, then the system directories), a scratch HOME, and ACPMUX_AGENT_LAUNCH=deny unless the test drives a stand-in agent (Agents::StandIn keeps the bare PATH). The 26 test files that started the binary with the host environment use it; tests/hermetic_daemon_guard.rs refuses a test file that names CARGO_BIN_EXE_acpmux anywhere else. Root cause of cx-w014j: a fleet host's PATH holds real codex/claude, which a test daemon discovered and ran (probes, sign-in checks, auto-updates). * cx-tgf4h: fmt and clippy * acpmux tests: the hermetic HOME is <scratch>/home, never a chat's folder * acpmux tests: review fixes for the hermetic environment (cx-s8wux) python3 links the interpreter itself (sys.executable), not a version manager's shim; stale tool links from an earlier run are replaced; the guard also flags daemon_env::bin() outside a listed use; the live codex test probes only codex; codex_bridge_config's discovery test runs with launches denied. * acpmux tests: router_install_secret starts the router through daemon_env (cx-s8wux) * fix: code pages draw in the terminal's font; agent pane defines --font-mono The diff, markdown and code editor pages were written to follow the terminal font (appearance.ts, editorFont), but no cmux NEXT host ever sent it, so code always drew in Menlo. Every page theme now carries the terminal's family (cmux.json terminal.fontFamily, else the Ghostty config's font-family), resent when it changes. The agent pane's mono text read --font-mono, which only Tailwind's theme layer emitted because a source file happened to name it; conversation.css defines it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next: fix two Chief profile relay base reds (concurrency check, Release compile crash) (no bead) (#20876) * cmux-next: mark the Chief profile relay retry loop as bounded (no bead) check-concurrency flags its while true as a loop that can spin. It retries once, only after a lost connection, and every other error throws. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next: nonisolated deinit for PageCallDeadline.Once (no bead) The Release compile crashes swift-frontend 6.3.3 in EarlyPerfInliner on the isolated deinit of this main-actor generic class (exit 65, no error line), the same crash #20408 fixed elsewhere. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * fix(cmux-next): the Chief profile relay's retry is a two-attempt for loop, not while true with a wakeup-allow (cx-ebm.59.5) * cmux-next sidebar perf round 3: Release-build hitch bench with real wheel input; O(1) hover-card hit - scripts/cmux-next/sidebar-rows-perf-release.py: runs in a Release tagged app (no debug.* methods) inside nx-remote --needs input: CLI workspaces (50 with a terminal, 950 empty), HID-tap wheel events, Animation Hitches per gesture, A/B of two apps in one job (side by side, interleaved), traces and the recorder's ktrace files removed after each export, PTY count logged. - SidebarListView+HoverCard: the hover-card hit reads the list's row dictionary instead of SidebarModel.isPlaceholder, an O(workspaces) section walk on every scroll frame (7-12% of main-thread samples while scrolling 1,000 rows in Release). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Channels: a primary or danger button keeps its fill under the pointer (a soft ring shows the hover); gallery play primary-hover Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Channels gallery: primary-hover asserts the hover ring and the unchanged fill; a budget with a reason for the Create frame Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * cmux-motion: Chrome tab strip tween (200 ms easeOutQuad, restart from value), tabStrip geometry tokens, damping <= 0 takes the fallback (hq-1d, no bead) Additive: MotionTween {TabOpen, TabClose, TabMove}, TweenCurve::EaseOutQuad, ease_out_quad, TweenParameters, TweenValue (f64 core: retarget restarts the duration from the current value with no velocity; the same target does not restart), Tween (f32, token-driven), MotionPolicy::tween (0 under speed off, Reduce Motion, or tabOpen/tabClose with ui.animations.newTab off), TabStripGeometry (design-tokens.json motion.tabStrip: max 200, open/close 18, min 56 active / 32 inactive / 64 pinned, reorder 16 x width / 200, closing mode +40 below / +60 trailing / 0.3 s). cmux-app-ffi ABI 2 exports cmux_motion_tween_{base,seconds,retarget,step}, cmux_motion_ease and cmux_motion_tab_strip_geometry. SpringParameters::finite_or now treats a damping fraction <= 0 like NaN (hq-4e nit). The parity corpus example prints tween paths (60 Hz: 12 frames for 200 ms). * fix: read the font from the files the Ghostty config loaded, includes too Review: a font-family in a config-file include won in the terminal but not on pages. Read the runtime's loaded files (with includes, in load order) instead of guessing paths, repaint after the last override is set, and fix a stale doc comment. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * acpmux: record a session's git branch and HEAD at start (hq#1920) (#20840) * test(acpmux): record a session's git branch and head at start A session should keep its folder's branch and HEAD commit as they were at session/new, and a fork its own folder's state at fork time (hq#1920), so agent spend can be joined to the pull request a session produced. These fail today: neither the saved meta nor _acpmux/info carries gitBranch or gitHead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(acpmux): record a session's git branch and head at start session/new and session/fork now store the cwd's checked-out branch and full HEAD commit in the session meta (gitBranch, gitHead), so a session can later be joined to the pull request it produced (hq#1920). The values are read once, as the session starts, from the repository's own files (HEAD, loose refs, packed-refs, a linked worktree's gitdir and commondir), never a git process, and off the async runtime. A detached HEAD records only the head; a folder outside a repository records neither; a lookup that fails never fails the session. A fork reads its own folder at fork time instead of copying the parent's. _acpmux/info carries both fields. Old session.json files load unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(acpmux): git state skips non-files, bad branch names and missing folders; follows symlinks Review of #20840: a FIFO HEAD hung session/new, a symlinked folder was walked lexically, a missing fork folder took its parent repository's state, and an invalid ref name was stored as the branch. The test git also runs without the machine's global or system config. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(acpmux): git state reads only small regular files, the physical folder and valid ref names Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * cx-tgf4h: keep CmuxNextApp line count (App size cap) * acpmux: a pooled agent host no longer spins on Linux reading its own record (cx-7z8yx) The record watch used notify's inotify backend, whose watch mask always includes open, close-write and modify, and ran its callback on every event. The callback reads the host record; on Linux that read queued an open and a close in the watched directory, which ran the callback again. Every pooled host spun at 100% CPU (about 200,000 read calls a second). Linux now has its own inotify watch, like the macOS kqueue watch: a mask of entry changes only (create, delete, moved from/to) and the directory's own delete or move, one thread in poll with no timeout, an eventfd to stop it. A read of the record never queues an event. The notify fallback (other platforms) ignores access events. macOS is unchanged. Behavior test (tests/host_lifetime.rs, Linux): a real daemon pools a host; idle for 3 s it makes fewer than 100 read calls and 30 CPU ticks (before: 599,042 reads, 298 ticks), a rename rewrite of its record keeps it, and the record removed ends it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * cmux-tui smoke: sidebar drag checks the drawn sidebar document order Since sidebar-v2 S6 the TUI draws the daemon's sidebar document, where a new workspace goes to the top (workspaces.newPlacement default), and a workspace drop is one sidebar.move that changes the document only. The smoke still assumed the list-workspaces order: it dragged the drawn top row (the new workspace) below the original, which the product did, and then read list-workspaces, which a sidebar.move never changes. The smoke now reads the order from sidebar.get, checks that the rail draws it, drags the top row below the second (a real reorder), and drags again when needed so the original workspace ends below the new one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * PR dock chips; tooltips only where nothing else names the control (#20375) * test: no tooltip on an element whose text shows Red on base: 105 elements with visible text carry title/data-tooltip. Command: bun test test/tooltip-rules.test.ts Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: PR dock chips; tooltips only where nothing else names the control The pull request dock's bars become content-sized chips (icon, #N, repo, title cut off at 360 px) with the dismiss button inside and no tooltip. Across the pages, a row, chip, link, path or thought whose text shows carries no title tooltip any more; tooltips stay on icon-only controls, shortcuts and text shown nowhere else (why a control is disabled or failed, who reacted, policy detail), each marked tooltip-allow. Tooltips wait the native hover delay (about a second) and show at once when moving straight on to the next one. Green: bun test test/tooltip-rules.test.ts Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: review of tooltip audit Keep the PR dock's state colours, drop four more tooltips the lint now finds inside components (a setting's summary, the branch and folder pickers, a video), let a click or scroll end the quick next-tooltip window, and move two tests to the no-tooltip rule. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: Backdrop Art's line has no tooltip Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at 047c247 - vp fmt webviews/src/pages/history/HistoryPage.tsx Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38502564051 * test(mock): the worked chat opens its pull request, so mock mode shows the PR dock Captures of the agent pane in a real window (--showcase runs the in-page mock) now show the pull request dock. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: the PR dock takes its own space; the transcript ends above it Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at 39f3ca9 - vp fmt webviews/test/ime-composition-keys.test.ts - vp fmt webviews/test/new-tab-omnibar-pointer.test.ts Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38567629461 * chore(next): PR autofix at c7cb261 - regenerated Packages/macOS/CmuxNext/ci-target-graph.json Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38592980576 * fix: a channel image keeps its name tooltip (the name shows only when it fails) Base added title={part.name} on channel image attachments (AttachmentViews.tsx). A loaded image shows no name, so the tooltip is its only label; mark it with tooltip-allow. tooltip-rules.test.ts: red before, green after. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at f221864 - regenerated Packages/macOS/CmuxNext/ci-target-graph.json Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38633116142 * fix: keep the tool card scope hint and Steer shortcut tooltips Both explain something shown nowhere else, so they stay under tooltip-allow. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at 022cc8e - vp fmt webviews/src/pages/home-channels/cloudHome.ts Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38647981824 --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: cmux-autofix[bot] <cmux-autofix[bot]@users.noreply.github.com> * ci: nightly-next recovery initializes the notices submodule before continuing accepted submissions The recovery job's checkout had no ghostty-next submodule, so the bundle notice check that notarize-nightly-dmg.sh runs after Apple accepts failed, and run 38669958906 skipped five accepted builds as 'Apple did not accept'. Initialize the submodule like the signing job does, and make the skip notice say that a post-acceptance check can also be the cause. * ci: the cmux NIGHTLY-identity job also initializes the notices submodule Run 38669958906's publish-nightly-identity-legacy job saw Apple accept, then failed the bundle notice check for lack of ghostty-next and retired the accepted submission of run 38609024986. * agent pane: progress and stop for a running Claude subagent or workflow (cx-liswe) (#20718) * test: a running subagent or workflow shows what it does and what it has spent Red on base: both rows read only "Running" (bun test test/subagent-progress.test.tsx). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * webviews: a running subagent or workflow shows what it does and what it has spent The subagent fold keeps acpmux's subagent_progress fields (action, tokens, tool uses, a workflow's agents done of started), and the transcript's subagent row adds them to its status line through one shared helper (subagentProgress.ts) the summary list and the Background tasks pane can use. Three plural strings, translated for every pane locale. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: a running subagent row has a stop button Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: stop a running Claude subagent or workflow from its row Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: restore the catalog's base order after the merge Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: stopping a subagent leaves its row closed, and a refused stop says so Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: a subagent's stop button waits for Claude and says when the stop failed The button is off while Claude has the request and until the subagent ends; a refused or unanswered stop (10 s) turns it into "Couldn't stop <name>" and it can be tried again. The pane no longer drops the error. Also moves the stop wiring above showSubagent's doc comment and corrects two comments. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * style: format the subagent progress test Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: stop rejects without English the pane would never show Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: restore the catalog's base order after the merge Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at 2fe6cc4 - vp fmt webviews/src/pages/home-channels/HomeChannelsPage.tsx Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38637059713 * test: the agent pane relays a subagent stop for its chat (cx-liswe) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: the agent pane may stop a subagent of its chat (cx-liswe) Adds _acpmux/subagent_stop to the pane's method allowlist: session-scoped, params sessionId and subagentSessionId, no gesture (it stops work, like _acpmux/kill). Without it the host refused every stop click. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: mirror the subagent stop into the shared pane policy (cx-liswe) The Swift allowlist took _acpmux/subagent_stop; policy.json, its parity source for Rust hosts, gets the same request, session scope and params, with cases for an in-scope stop, another chat and an unknown param. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * gallery: a light window with no theme named renders light (#20794) * test(gallery): a light window with no theme named should show the light default Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(gallery): a light window with no theme named shows Apple System Colors Light The gallery defaulted the theme to the dark side of the app's default pair whatever the window appearance, so colorScheme=light (or Appearance: Light) rendered every stage in dark colors under a light media query. The default now follows the appearance, as the app's does with no theme set. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: cmux-autofix[bot] <cmux-autofix[bot]@users.noreply.github.com> * Channels view: gallery plays for a message link with no link read (red) A Cloud conversation has no link resolver (G4), so the Messages view's switch hand-off #/conversation/<id>/message/<id> showed an error. Two plays: a thread reply and a timeline message, opened through the store's openLink with an owner that has no resolver. cx-hnmbt Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Channels view: open a known conversation's message link without the owner's link read When conversation-link-resolve fails (a Cloud conversation, an older daemon) and the page knows the conversation, it opens it, pages the timeline until the message shows, opens its thread when it is a reply, and marks it. The Messages view's switch hands off Cloud selections this way. cx-hnmbt Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Channels view: format parseConversationLink (vp fmt) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Channels view: link fallback review follow-ups Ids in a known conversation's link may hold '-' (the gallery's sample ids); the scheme check follows the daemon (cmux[-<tag>], any case); the fallback runs only for a Cloud conversation or an owner without a link read, so a refused local link (a deleted message) still shows its error. cx-hnmbt Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * acpmux: host_lifetime idle test cleans up from the start and never signals a reused pid (cx-7z8yx review) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * cmux-tui: move the build identity into a leaf crate so an edit no longer recompiles cmux-remote cmux-remote's build script hashed the dirty source tree into CMUX_TUI_BUILD_IDENTITY, so every edit in the workspace reran it and recompiled cmux-remote and every crate above it (about 8 s of a 12.6 s one-line edit loop on rbx). The same build script now lives in cmux-build-identity, which only cmux-tui reads; cmux-remote takes the identity as an argument (SshBootstrapConfig::defaults, pinned_linux_payload). The identity value, its inputs and format, and every skew and SSH re-bootstrap comparison are unchanged. * test: warm the dev server in the Claude reasoning default browser test (#20884) #20592 landed after #20873 without warmViteServer, so check:browser-lanes is red on base again. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next: frame-strip report as an NSWindow method, not a namespace enum (no bead) (#20887) The package conventions lint fails every PR on the new all-static public enum WindowFrameStrip (cx-me3xd). The report reads its window, so it is an extension on NSWindow; same body, same report. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * Home channels: the run card is an inline disclosure (no frame, steps on an indented rail) The live and done run cards under a Chief's reply lose their box: "Working for" / "Worked for", the step count, cost and Open sit inline under the message, and the opened steps hang on a thin rail under the status mark. The narrow rules stay: the first line never wraps, and below 480 px of card width the step count and cost move under it with no leading separator. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Home channels: the run rail and columns follow the author's picture Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Home channels: the run sheet keeps its error line; run card columns in logical properties Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Revert "cmux-motion: Chrome tab strip tween ..." (8a3ee62) until the app-ffi release App 403 is fixed (run 38682698310) (hq-1d, chief go 2026-10-15, no bead) The release App could not publish cmux-app-ffi-854febb26527 (HTTP 403 on POST /releases), so the app FFI pin check stays red on the tip. The tween re-lands with the publish and repin after the App is fixed. * test(ci): nightly jobs that run the license check must init ghostty-next (#20893) * test(ci): nightly jobs that run the license check must init ghostty-next Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(ci): nightly recovery initializes ghostty-next before the license check Apple accepted, stapled and launch-tested each recovered nightly-next build, then verify-app-bundle-licenses.sh failed on the missing ghostty-next/build.zig.zon and the build was skipped as not accepted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next: terminal-face repaint lives in DesignSettings, not the App target Keeps CmuxNextApp under its size cap: setting either terminal family repaints pages when the face the terminal draws in changed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Lawrence Chen <54008264+lawrencecchen@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: cmux-autofix[bot] <cmux-autofix[bot]@users.noreply.github.com> Co-authored-by: safe-push <safe-push@cmux.local>
#20759) * test: the strip scrollbar's thumb stays above a browser page A Chromium page at the bottom of the column strip is a child window above the scrollbar band, so it hid the thumb and took its clicks (cx-6so.44, dock-column.md Known gaps). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: the strip scrollbar's thumb stays above a browser page While shown, the thumb's band is an occluder of the window's overlay host, so a Chromium page under it leaves the thumb showing and its clicks to the bar. Updates dock-column.md's known gaps: reveal under an overlay and the strip clip were already fixed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: a hidden screen's strip scrollbar leaves no hole in a browser page Review of #20759: a screen switch hides the screen's view, not the bar, so the old screen's thumb stayed an occluder and the new one's never came back. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: a hidden or sliding screen's strip scrollbar keeps its occluder current The thumb's occluder now follows an ancestor's hide and unhide (viewDidHide/viewDidUnhide), and each screen's origin as the screen switch moves it (applyScreenFrames). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cx-tgf4h red: cmux chief -p under ACPMUX_AGENT_LAUNCH=deny fails at once with a typed refusal * cx-tgf4h: the Chief says at once that agents are disabled in this build session With ACPMUX_AGENT_LAUNCH=deny (the nx-remote gui/input default since HQ #2130) or CMUX_AGENTS_DISABLED=1, no Chief turn can start an agent. `cmux chief -p` started a daemon and a brain and waited 240 s for a reply that could not come. - cmux-tui-core agent_launch: one test of the kill switch (acpmux launch_policy.rs), the reason agent_launch_disabled. - `cmux chief` (pipe and chat) refuses before it starts or sends anything: operation.failed, details.reason agent_launch_disabled, exit 1. - The daemon's supervisor starts no Chief brain; chief.engine.* and chief.stop answer the typed refusal at once. - optchat-chief host does not start (logs why, exit 0). - Home: the local Chief conversation's notice says agents are disabled; the engine panel maps the typed refusal (localized, all Home languages). - Every Chief proof script refuses at once under deny and names `nx-remote --allow-agents`. * cx-tgf4h review: forward chief control to a running brain first; daemon-side deny test; engine/stop CLI text; guard before side effects; fmt * cx-tgf4h: fmt and clippy * cx-tgf4h: keep CmuxNextApp line count (App size cap) * acpmux: a pooled agent host no longer spins on Linux reading its own record (cx-7z8yx) The record watch used notify's inotify backend, whose watch mask always includes open, close-write and modify, and ran its callback on every event. The callback reads the host record; on Linux that read queued an open and a close in the watched directory, which ran the callback again. Every pooled host spun at 100% CPU (about 200,000 read calls a second). Linux now has its own inotify watch, like the macOS kqueue watch: a mask of entry changes only (create, delete, moved from/to) and the directory's own delete or move, one thread in poll with no timeout, an eventfd to stop it. A read of the record never queues an event. The notify fallback (other platforms) ignores access events. macOS is unchanged. Behavior test (tests/host_lifetime.rs, Linux): a real daemon pools a host; idle for 3 s it makes fewer than 100 read calls and 30 CPU ticks (before: 599,042 reads, 298 ticks), a rename rewrite of its record keeps it, and the record removed ends it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * cmux-tui smoke: sidebar drag checks the drawn sidebar document order Since sidebar-v2 S6 the TUI draws the daemon's sidebar document, where a new workspace goes to the top (workspaces.newPlacement default), and a workspace drop is one sidebar.move that changes the document only. The smoke still assumed the list-workspaces order: it dragged the drawn top row (the new workspace) below the original, which the product did, and then read list-workspaces, which a sidebar.move never changes. The smoke now reads the order from sidebar.get, checks that the rail draws it, drags the top row below the second (a real reorder), and drags again when needed so the original workspace ends below the new one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * ci: nightly-next recovery initializes the notices submodule before continuing accepted submissions The recovery job's checkout had no ghostty-next submodule, so the bundle notice check that notarize-nightly-dmg.sh runs after Apple accepts failed, and run 38669958906 skipped five accepted builds as 'Apple did not accept'. Initialize the submodule like the signing job does, and make the skip notice say that a post-acceptance check can also be the cause. * ci: the cmux NIGHTLY-identity job also initializes the notices submodule Run 38669958906's publish-nightly-identity-legacy job saw Apple accept, then failed the bundle notice check for lack of ghostty-next and retired the accepted submission of run 38609024986. * agent pane: progress and stop for a running Claude subagent or workflow (cx-liswe) (#20718) * test: a running subagent or workflow shows what it does and what it has spent Red on base: both rows read only "Running" (bun test test/subagent-progress.test.tsx). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * webviews: a running subagent or workflow shows what it does and what it has spent The subagent fold keeps acpmux's subagent_progress fields (action, tokens, tool uses, a workflow's agents done of started), and the transcript's subagent row adds them to its status line through one shared helper (subagentProgress.ts) the summary list and the Background tasks pane can use. Three plural strings, translated for every pane locale. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: a running subagent row has a stop button Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: stop a running Claude subagent or workflow from its row Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: restore the catalog's base order after the merge Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: stopping a subagent leaves its row closed, and a refused stop says so Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: a subagent's stop button waits for Claude and says when the stop failed The button is off while Claude has the request and until the subagent ends; a refused or unanswered stop (10 s) turns it into "Couldn't stop <name>" and it can be tried again. The pane no longer drops the error. Also moves the stop wiring above showSubagent's doc comment and corrects two comments. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * style: format the subagent progress test Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: stop rejects without English the pane would never show Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: restore the catalog's base order after the merge Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at 2fe6cc4 - vp fmt webviews/src/pages/home-channels/HomeChannelsPage.tsx Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38637059713 * test: the agent pane relays a subagent stop for its chat (cx-liswe) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: the agent pane may stop a subagent of its chat (cx-liswe) Adds _acpmux/subagent_stop to the pane's method allowlist: session-scoped, params sessionId and subagentSessionId, no gesture (it stops work, like _acpmux/kill). Without it the host refused every stop click. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: mirror the subagent stop into the shared pane policy (cx-liswe) The Swift allowlist took _acpmux/subagent_stop; policy.json, its parity source for Rust hosts, gets the same request, session scope and params, with cases for an in-scope stop, another chat and an unknown param. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * gallery: a light window with no theme named renders light (#20794) * test(gallery): a light window with no theme named should show the light default Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(gallery): a light window with no theme named shows Apple System Colors Light The gallery defaulted the theme to the dark side of the app's default pair whatever the window appearance, so colorScheme=light (or Appearance: Light) rendered every stage in dark colors under a light media query. The default now follows the appearance, as the app's does with no theme set. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: cmux-autofix[bot] <cmux-autofix[bot]@users.noreply.github.com> * Channels view: gallery plays for a message link with no link read (red) A Cloud conversation has no link resolver (G4), so the Messages view's switch hand-off #/conversation/<id>/message/<id> showed an error. Two plays: a thread reply and a timeline message, opened through the store's openLink with an owner that has no resolver. cx-hnmbt Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Channels view: open a known conversation's message link without the owner's link read When conversation-link-resolve fails (a Cloud conversation, an older daemon) and the page knows the conversation, it opens it, pages the timeline until the message shows, opens its thread when it is a reply, and marks it. The Messages view's switch hands off Cloud selections this way. cx-hnmbt Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Channels view: format parseConversationLink (vp fmt) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Channels view: link fallback review follow-ups Ids in a known conversation's link may hold '-' (the gallery's sample ids); the scheme check follows the daemon (cmux[-<tag>], any case); the fallback runs only for a Cloud conversation or an owner without a link read, so a refused local link (a deleted message) still shows its error. cx-hnmbt Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * acpmux: host_lifetime idle test cleans up from the start and never signals a reused pid (cx-7z8yx review) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * cmux-tui: move the build identity into a leaf crate so an edit no longer recompiles cmux-remote cmux-remote's build script hashed the dirty source tree into CMUX_TUI_BUILD_IDENTITY, so every edit in the workspace reran it and recompiled cmux-remote and every crate above it (about 8 s of a 12.6 s one-line edit loop on rbx). The same build script now lives in cmux-build-identity, which only cmux-tui reads; cmux-remote takes the identity as an argument (SshBootstrapConfig::defaults, pinned_linux_payload). The identity value, its inputs and format, and every skew and SSH re-bootstrap comparison are unchanged. * test: warm the dev server in the Claude reasoning default browser test (#20884) #20592 landed after #20873 without warmViteServer, so check:browser-lanes is red on base again. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next: frame-strip report as an NSWindow method, not a namespace enum (no bead) (#20887) The package conventions lint fails every PR on the new all-static public enum WindowFrameStrip (cx-me3xd). The report reads its window, so it is an extension on NSWindow; same body, same report. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * Home channels: the run card is an inline disclosure (no frame, steps on an indented rail) The live and done run cards under a Chief's reply lose their box: "Working for" / "Worked for", the step count, cost and Open sit inline under the message, and the opened steps hang on a thin rail under the status mark. The narrow rules stay: the first line never wraps, and below 480 px of card width the step count and cost move under it with no leading separator. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Home channels: the run rail and columns follow the author's picture Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Home channels: the run sheet keeps its error line; run card columns in logical properties Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Revert "cmux-motion: Chrome tab strip tween ..." (8a3ee62) until the app-ffi release App 403 is fixed (run 38682698310) (hq-1d, chief go 2026-10-15, no bead) The release App could not publish cmux-app-ffi-854febb26527 (HTTP 403 on POST /releases), so the app FFI pin check stays red on the tip. The tween re-lands with the publish and repin after the App is fixed. * test(ci): nightly jobs that run the license check must init ghostty-next (#20893) * test(ci): nightly jobs that run the license check must init ghostty-next Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(ci): nightly recovery initializes ghostty-next before the license check Apple accepted, stapled and launch-tested each recovered nightly-next build, then verify-app-bundle-licenses.sh failed on the missing ghostty-next/build.zig.zon and the build was skipped as not accepted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- 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> Co-authored-by: cmux-autofix[bot] <cmux-autofix[bot]@users.noreply.github.com> Co-authored-by: safe-push <safe-push@cmux.local>
* feat(cx-gakp): unify slash commands, skills and prompts Keep the existing Milkdown editor and its URL, mention and attachment behavior. Label ACP command sources so skills and prompts share the same searchable picker. * chore(next): PR autofix at cade19a - vp fmt webviews/src/agent-session/acpmux/composer.gallery.ts Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38535762014 * fix(cx-gakp): localize slash picker labels and cmux command descriptions The Skill/Prompt labels and the four cmux command descriptions were hard-coded English, which pane-english rejects. They now come from the pane's table in all 21 languages; cmux commands carry a descriptionKey. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(cx-gakp): keep Codex skills' $ prefix in the slash picker codex-acp names each skill `$name` and passes `/$name` through to Codex as a skill mention. Stripping the $ inserted `/name`, which ran a same-named builtin or nothing, and deduped the skill behind cmux's own commands. Keep the name and use the $ as the skill signal. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at f4ed982 - regenerated schemas/defaults/cmux-next.json Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38541336447 * fix(cx-gakp): read the skill tag from ACP _meta in the slash picker acpmux will tag Claude skills as _meta.kind (ACP keeps extensions in _meta); read it alongside codex-acp's $ prefix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(cx-gakp): slash picker play finds its rows by name; harness stays harness - The gallery play waited for exactly 3 rows, but cmux's /import shares the menu; it now finds the fixture rows by name, asserts Skill and Prompt on their own rows and no label on a harness command, and clears the "/" before typing the draft. - The comment no longer claims acpmux tags Claude skills. - /continue's description keeps "harness" as the catalog does elsewhere (17 locales said "tool"). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: regenerate pane strings after the base merge Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * webviews: regenerate pane strings after the base merge Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Chief registry: chief.profile.adopt makes an existing agent participant a Chief record under its own id The owner (a trusted local Unix caller acting as the person) adopts an agent that is already in a conversation: the record keeps the participant's id and display name, so its DMs, history and credential stay its own, and gets chief.profile.create's defaults and only the fields given. A page (WebSocket or the host's page relay, even with a gesture), a paired or remote device and a bound agent get origin.forbidden; there is no page route. agent_mux is default_chief, a live record already_chief, a deleted Chief deleted_chief (an adopt never revives its tombstone or kept memory), and a person or an unknown id not_an_agent_participant. The write goes through the daemon's registry ledger (idempotent per key) and the same chief_written hook as a create. Capability chief-profile-adopt-v1; CLI cmux chief adopt AGENT [PROFILE], refused for an agent caller. Real-daemon tests for each refusal and for an adopt that keeps the DM and its history. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * chief.profile.adopt review fixes: owner gate first, any page origin refused, brain directory collisions refused, tests for the event and the limit Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * chief.profile.adopt: refuse a bound participant, revoke its earlier credentials in the same write, and only the brain (or, with no supervisor, the person's terminal) mints the Chief's credential The adopt claims the participant inside the registry write: under the bindings lock it refuses a participant with a bound connection (participant_bound, "stop its current agent session first") and otherwise revokes every credential issued for it. conversation-bind now checks the credential and binds under the same lock, so a revoked credential never binds after the adopt. For a Chief record other than agent_mux, conversation-agent-token is refused while a brain supervisor runs (the supervisor mints the brain's credential in process); with no supervisor only the person's own terminal mints it, never a page, a paired or remote device or an agent. Tests: a bound participant is refused; after it unbinds the adopt succeeds and the brain starts; the old credential is refused; the brain's credential binds; the person mints the post-adopt credential on a daemon with no supervisor; a page, a device and an agent cannot mint it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * chief.profile.adopt: the Chief-credential check and the mint run under the registry lock Review finding: a mint that passed the Chief check before an adopt could overwrite the brain's credential after it. conversation-agent-token now checks and mints inside one registry-locked step (registry, then the conversation store, the adopt's order). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Regenerate bindings after merge Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * chief.profile.adopt: clippy (one write struct for mutate, no redundant clone) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * resource_attach: chief.profile.adopt is the 54th connection operation Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * cmux-next: CmuxNextApp cap back to 113692 (frame-strip proof analysis and animation palette toggles leave the App target) (cx-me3xd) The debug.new_tab frame_strip analysis (frame comparisons, PNGs, report fields) moves to WindowFrameStrip in CmuxNextDesign beside WindowFrame and MotionFrameProgress; the drag_new gesture moves to TabStripDebug.dragFirstTab in CmuxNextTabs. DebugFrameStrip keeps only the wiring (record, send key or gesture, spans), so plus, drag_new and every report field stay. The ui.animations.<kind> toggles and bounce bind through AnimationKindsSetting.bindActions (CmuxNextSettings) on the shared SettingChoiceActions save, as ChromeStyleSetting does (ported from nx-grow-land-fallback b1e0c989). CmuxNextApp 113810 -> 113692; the cap follows. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * cx-tgf4h red: cmux chief -p under ACPMUX_AGENT_LAUNCH=deny fails at once with a typed refusal * cx-tgf4h: the Chief says at once that agents are disabled in this build session With ACPMUX_AGENT_LAUNCH=deny (the nx-remote gui/input default since HQ #2130) or CMUX_AGENTS_DISABLED=1, no Chief turn can start an agent. `cmux chief -p` started a daemon and a brain and waited 240 s for a reply that could not come. - cmux-tui-core agent_launch: one test of the kill switch (acpmux launch_policy.rs), the reason agent_launch_disabled. - `cmux chief` (pipe and chat) refuses before it starts or sends anything: operation.failed, details.reason agent_launch_disabled, exit 1. - The daemon's supervisor starts no Chief brain; chief.engine.* and chief.stop answer the typed refusal at once. - optchat-chief host does not start (logs why, exit 0). - Home: the local Chief conversation's notice says agents are disabled; the engine panel maps the typed refusal (localized, all Home languages). - Every Chief proof script refuses at once under deny and names `nx-remote --allow-agents`. * Channels view: gallery plays for the host's home.currentSelection (red: the page does not serve it yet) The host-callable command type (hostActions.ts) and two plays: a conversation, the keyboard's current message and the open thread; the docked list pane answers null. cx-hnmbt Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Channels view: home.currentSelection for the Home dock's view switch The page serves window.cmuxHomeActions["home.currentSelection"] (the agent page's cmuxAcpmuxActions pattern; the host calls it with callAsyncJavaScript): {conversation, message?, thread?} = the open conversation, the keyboard's current message or the message a link marked, and the open thread's root; null on the narrow list pane or with nothing open. The host never reads the page hash for the hand-off. cx-hnmbt Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Channels view: serve home.currentSelection on the page bridge, not a window global The host calls it with PageRouter.callPage (the typed host-to-page call the page bridge already has; PageClient.handle on the page): {} -> {conversation, message?} | null. message = the keyboard's current message, else the message a link marked, else the open thread's root. The gallery plays drive a real BridgePageClient through __cmuxPageReceive, as the app does. cx-hnmbt Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Channels view: home.currentSelection review follow-ups Layout effect for the answered selection; null before the page's first measure (a docked list pane never reports a hidden conversation); the gallery host uses a private bridge target; the thread case is its own play (the gallery opens the thread). cx-hnmbt Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * acpmux: Codex picks run the in-process bridge, not the npx codex-acp adapter (#20800) * test(acpmux): the npx codex-acp adapter is offered beside the Codex bridge Red: with codex and npx on PATH and no codex-acp, discovery keeps the pinned npx adapter (@agentclientprotocol/codex-acp) as `codex-acp` next to the in-process bridge. That adapter reads the account through codex's account/read, which fails for a ChatGPT login behind a routing proxy (subrouter): its sessions never start ("Authentication required"). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * acpmux: Codex picks run the in-process bridge, not the npx codex-acp adapter With codex installed and no codex-acp on PATH, discovery kept the pinned npx adapter (@agentclientprotocol/codex-acp@1.10.0) as `codex-acp` beside the in-process bridge. The adapter reads the account through codex's account/read; with codex 0.162 a ChatGPT login behind a routing proxy (subrouter) fails that ("selected workspace missing from routing discovery"), so its chats never started ("Authentication required"), while the bridge works on the same login. Discovery no longer offers the npx adapter: an installed codex is the bridge, and `codex-acp` names the bridge too (like `codex-app-server`), so sessions, presets and model picks that recorded it run the bridge. A codex-acp on PATH, an ~/.acpx entry and a config-written launch are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * acpmux: one description for the bridge's aliases (rustfmt) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * cx-tgf4h review: forward chief control to a running brain first; daemon-side deny test; engine/stop CLI text; guard before side effects; fmt * test: warm the dev server in three agent pane browser tests (#20873) check:browser-lanes (#20733) requires warmViteServer after listen; #20752, #20780 and #20785 landed tests without it, so react-apps-check is red on base. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * acpmux tests: every acpmux process a test starts gets a hermetic environment (cx-s8wux) One helper, tests/support/daemon_env.rs, starts the acpmux binary for every integration test: env_clear, a bare PATH (python3 plus named host tools, then the system directories), a scratch HOME, and ACPMUX_AGENT_LAUNCH=deny unless the test drives a stand-in agent (Agents::StandIn keeps the bare PATH). The 26 test files that started the binary with the host environment use it; tests/hermetic_daemon_guard.rs refuses a test file that names CARGO_BIN_EXE_acpmux anywhere else. Root cause of cx-w014j: a fleet host's PATH holds real codex/claude, which a test daemon discovered and ran (probes, sign-in checks, auto-updates). * cx-tgf4h: fmt and clippy * acpmux tests: the hermetic HOME is <scratch>/home, never a chat's folder * acpmux tests: review fixes for the hermetic environment (cx-s8wux) python3 links the interpreter itself (sys.executable), not a version manager's shim; stale tool links from an earlier run are replaced; the guard also flags daemon_env::bin() outside a listed use; the live codex test probes only codex; codex_bridge_config's discovery test runs with launches denied. * cmux-tui: agent-session-attach takes the agent pane's whole kind list (up to 32; the pane asks 9 since prompt bookmarks), so a remote chat shows after Trust instead of falling back to New Tab with bad request (cx-kpd0v) * agent pane: the attach asks at most 8 kinds again (session offers come with transcript), so an older remote cmux-tui shows the chat (cx-kpd0v) * cmux-tui: test fake needs no mut (cx-kpd0v) * acpmux tests: router_install_secret starts the router through daemon_env (cx-s8wux) * cmux-next composer: keep base's catalog order; regenerate strings on the merged base Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * acpmux: one typed protocol registry; generated web types and drift checks (hq#2025, no bead) (#20576) * acpmux: typed protocol registry and IR (hq#2025, no bead) One registry names every acpmux method and notification; sessions and permissions carry serde/schemars types, and the daemon builds SessionSummary and PermissionGroup from them. ir() emits spec/acpmux-protocol.json for the web codegen. Tests fail when the committed IR is stale or the dispatcher serves a name the registry lacks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * webviews: acpmux protocol codegen, typed request helper and drift check (hq#2025, no bead) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * acpmux protocol: committed IR, generated web types; permissions and session_changed use them (hq#2025, no bead) The permission group client and permission_respond go through the typed request; session_changed and permission_pending are narrowed by the registry's notification map. The IR declares a peer summary's optional fields and peer key, permission_pending's always-sent keys, and closed param objects. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * webviews: format direct.ts Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * webviews: acpmux codegen lives beside the pane protocol codegen, outside the pane sources Its developer-facing IR errors tripped pane-english, which scans src/agent-session/acpmux for user-visible English. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at 1bb7576 - cargo fmt in Native/OptChat/optchat-chief Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38569912312 * chore(next): PR autofix at c601de5 - regenerated Packages/macOS/CmuxNext/ci-target-graph.json Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38593588859 * chore(next): PR autofix at 7a7fb66 - regenerated Packages/macOS/CmuxNext/ci-target-graph.json Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38606761975 * acpmux protocol: register offer_session and offer_respond Base (#20305) serves two new methods; the registry's completeness test caught them. Both are untyped requests for now. Spec and generated TS are regenerated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * acpmux protocol: register prompt_withdraw Base serves _acpmux/prompt_withdraw; the completeness test caught it. Spec and generated TS are regenerated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at 4e1d3c9 - vp fmt webviews/src/pages/home-channels/HomeChannelsPage.tsx Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38637598208 * acpmux protocol: register the process methods Base serves _acpmux/process/list and process/kill and sends _acpmux/process_update; the completeness test caught them. Spec and generated TS are regenerated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at 64ca080 - vp fmt webviews/src/pages/home-channels/cloudHome.ts - cargo fmt in Native/OptChat/optchat-chief Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38649959912 --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: cmux-autofix[bot] <cmux-autofix[bot]@users.noreply.github.com> * cmux-next: fix two Chief profile relay base reds (concurrency check, Release compile crash) (no bead) (#20876) * cmux-next: mark the Chief profile relay retry loop as bounded (no bead) check-concurrency flags its while true as a loop that can spin. It retries once, only after a lost connection, and every other error throws. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next: nonisolated deinit for PageCallDeadline.Once (no bead) The Release compile crashes swift-frontend 6.3.3 in EarlyPerfInliner on the isolated deinit of this main-actor generic class (exit 65, no error line), the same crash #20408 fixed elsewhere. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * fix(cmux-next): the Chief profile relay's retry is a two-attempt for loop, not while true with a wakeup-allow (cx-ebm.59.5) * cmux-next sidebar perf round 3: Release-build hitch bench with real wheel input; O(1) hover-card hit - scripts/cmux-next/sidebar-rows-perf-release.py: runs in a Release tagged app (no debug.* methods) inside nx-remote --needs input: CLI workspaces (50 with a terminal, 950 empty), HID-tap wheel events, Animation Hitches per gesture, A/B of two apps in one job (side by side, interleaved), traces and the recorder's ktrace files removed after each export, PTY count logged. - SidebarListView+HoverCard: the hover-card hit reads the list's row dictionary instead of SidebarModel.isPlaceholder, an O(workspaces) section walk on every scroll frame (7-12% of main-thread samples while scrolling 1,000 rows in Release). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Channels: a primary or danger button keeps its fill under the pointer (a soft ring shows the hover); gallery play primary-hover Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Channels gallery: primary-hover asserts the hover ring and the unchanged fill; a budget with a reason for the Create frame Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * cmux-motion: Chrome tab strip tween (200 ms easeOutQuad, restart from value), tabStrip geometry tokens, damping <= 0 takes the fallback (hq-1d, no bead) Additive: MotionTween {TabOpen, TabClose, TabMove}, TweenCurve::EaseOutQuad, ease_out_quad, TweenParameters, TweenValue (f64 core: retarget restarts the duration from the current value with no velocity; the same target does not restart), Tween (f32, token-driven), MotionPolicy::tween (0 under speed off, Reduce Motion, or tabOpen/tabClose with ui.animations.newTab off), TabStripGeometry (design-tokens.json motion.tabStrip: max 200, open/close 18, min 56 active / 32 inactive / 64 pinned, reorder 16 x width / 200, closing mode +40 below / +60 trailing / 0.3 s). cmux-app-ffi ABI 2 exports cmux_motion_tween_{base,seconds,retarget,step}, cmux_motion_ease and cmux_motion_tab_strip_geometry. SpringParameters::finite_or now treats a damping fraction <= 0 like NaN (hq-4e nit). The parity corpus example prints tween paths (60 Hz: 12 frames for 200 ms). * acpmux: record a session's git branch and HEAD at start (hq#1920) (#20840) * test(acpmux): record a session's git branch and head at start A session should keep its folder's branch and HEAD commit as they were at session/new, and a fork its own folder's state at fork time (hq#1920), so agent spend can be joined to the pull request a session produced. These fail today: neither the saved meta nor _acpmux/info carries gitBranch or gitHead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(acpmux): record a session's git branch and head at start session/new and session/fork now store the cwd's checked-out branch and full HEAD commit in the session meta (gitBranch, gitHead), so a session can later be joined to the pull request it produced (hq#1920). The values are read once, as the session starts, from the repository's own files (HEAD, loose refs, packed-refs, a linked worktree's gitdir and commondir), never a git process, and off the async runtime. A detached HEAD records only the head; a folder outside a repository records neither; a lookup that fails never fails the session. A fork reads its own folder at fork time instead of copying the parent's. _acpmux/info carries both fields. Old session.json files load unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(acpmux): git state skips non-files, bad branch names and missing folders; follows symlinks Review of #20840: a FIFO HEAD hung session/new, a symlinked folder was walked lexically, a missing fork folder took its parent repository's state, and an invalid ref name was stored as the branch. The test git also runs without the machine's global or system config. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(acpmux): git state reads only small regular files, the physical folder and valid ref names Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * cx-tgf4h: keep CmuxNextApp line count (App size cap) * acpmux: a pooled agent host no longer spins on Linux reading its own record (cx-7z8yx) The record watch used notify's inotify backend, whose watch mask always includes open, close-write and modify, and ran its callback on every event. The callback reads the host record; on Linux that read queued an open and a close in the watched directory, which ran the callback again. Every pooled host spun at 100% CPU (about 200,000 read calls a second). Linux now has its own inotify watch, like the macOS kqueue watch: a mask of entry changes only (create, delete, moved from/to) and the directory's own delete or move, one thread in poll with no timeout, an eventfd to stop it. A read of the record never queues an event. The notify fallback (other platforms) ignores access events. macOS is unchanged. Behavior test (tests/host_lifetime.rs, Linux): a real daemon pools a host; idle for 3 s it makes fewer than 100 read calls and 30 CPU ticks (before: 599,042 reads, 298 ticks), a rename rewrite of its record keeps it, and the record removed ends it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * cmux-tui smoke: sidebar drag checks the drawn sidebar document order Since sidebar-v2 S6 the TUI draws the daemon's sidebar document, where a new workspace goes to the top (workspaces.newPlacement default), and a workspace drop is one sidebar.move that changes the document only. The smoke still assumed the list-workspaces order: it dragged the drawn top row (the new workspace) below the original, which the product did, and then read list-workspaces, which a sidebar.move never changes. The smoke now reads the order from sidebar.get, checks that the rail draws it, drags the top row below the second (a real reorder), and drags again when needed so the original workspace ends below the new one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * PR dock chips; tooltips only where nothing else names the control (#20375) * test: no tooltip on an element whose text shows Red on base: 105 elements with visible text carry title/data-tooltip. Command: bun test test/tooltip-rules.test.ts Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: PR dock chips; tooltips only where nothing else names the control The pull request dock's bars become content-sized chips (icon, #N, repo, title cut off at 360 px) with the dismiss button inside and no tooltip. Across the pages, a row, chip, link, path or thought whose text shows carries no title tooltip any more; tooltips stay on icon-only controls, shortcuts and text shown nowhere else (why a control is disabled or failed, who reacted, policy detail), each marked tooltip-allow. Tooltips wait the native hover delay (about a second) and show at once when moving straight on to the next one. Green: bun test test/tooltip-rules.test.ts Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: review of tooltip audit Keep the PR dock's state colours, drop four more tooltips the lint now finds inside components (a setting's summary, the branch and folder pickers, a video), let a click or scroll end the quick next-tooltip window, and move two tests to the no-tooltip rule. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: Backdrop Art's line has no tooltip Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at 047c247 - vp fmt webviews/src/pages/history/HistoryPage.tsx Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38502564051 * test(mock): the worked chat opens its pull request, so mock mode shows the PR dock Captures of the agent pane in a real window (--showcase runs the in-page mock) now show the pull request dock. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: the PR dock takes its own space; the transcript ends above it Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at 39f3ca9 - vp fmt webviews/test/ime-composition-keys.test.ts - vp fmt webviews/test/new-tab-omnibar-pointer.test.ts Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38567629461 * chore(next): PR autofix at c7cb261 - regenerated Packages/macOS/CmuxNext/ci-target-graph.json Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38592980576 * fix: a channel image keeps its name tooltip (the name shows only when it fails) Base added title={part.name} on channel image attachments (AttachmentViews.tsx). A loaded image shows no name, so the tooltip is its only label; mark it with tooltip-allow. tooltip-rules.test.ts: red before, green after. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at f221864 - regenerated Packages/macOS/CmuxNext/ci-target-graph.json Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38633116142 * fix: keep the tool card scope hint and Steer shortcut tooltips Both explain something shown nowhere else, so they stay under tooltip-allow. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at 022cc8e - vp fmt webviews/src/pages/home-channels/cloudHome.ts Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38647981824 --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: cmux-autofix[bot] <cmux-autofix[bot]@users.noreply.github.com> * ci: nightly-next recovery initializes the notices submodule before continuing accepted submissions The recovery job's checkout had no ghostty-next submodule, so the bundle notice check that notarize-nightly-dmg.sh runs after Apple accepts failed, and run 38669958906 skipped five accepted builds as 'Apple did not accept'. Initialize the submodule like the signing job does, and make the skip notice say that a post-acceptance check can also be the cause. * ci: the cmux NIGHTLY-identity job also initializes the notices submodule Run 38669958906's publish-nightly-identity-legacy job saw Apple accept, then failed the bundle notice check for lack of ghostty-next and retired the accepted submission of run 38609024986. * agent pane: progress and stop for a running Claude subagent or workflow (cx-liswe) (#20718) * test: a running subagent or workflow shows what it does and what it has spent Red on base: both rows read only "Running" (bun test test/subagent-progress.test.tsx). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * webviews: a running subagent or workflow shows what it does and what it has spent The subagent fold keeps acpmux's subagent_progress fields (action, tokens, tool uses, a workflow's agents done of started), and the transcript's subagent row adds them to its status line through one shared helper (subagentProgress.ts) the summary list and the Background tasks pane can use. Three plural strings, translated for every pane locale. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: a running subagent row has a stop button Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: stop a running Claude subagent or workflow from its row Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: restore the catalog's base order after the merge Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: stopping a subagent leaves its row closed, and a refused stop says so Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: a subagent's stop button waits for Claude and says when the stop failed The button is off while Claude has the request and until the subagent ends; a refused or unanswered stop (10 s) turns it into "Couldn't stop <name>" and it can be tried again. The pane no longer drops the error. Also moves the stop wiring above showSubagent's doc comment and corrects two comments. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * style: format the subagent progress test Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: stop rejects without English the pane would never show Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: restore the catalog's base order after the merge Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at 2fe6cc4 - vp fmt webviews/src/pages/home-channels/HomeChannelsPage.tsx Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38637059713 * test: the agent pane relays a subagent stop for its chat (cx-liswe) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: the agent pane may stop a subagent of its chat (cx-liswe) Adds _acpmux/subagent_stop to the pane's method allowlist: session-scoped, params sessionId and subagentSessionId, no gesture (it stops work, like _acpmux/kill). Without it the host refused every stop click. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: mirror the subagent stop into the shared pane policy (cx-liswe) The Swift allowlist took _acpmux/subagent_stop; policy.json, its parity source for Rust hosts, gets the same request, session scope and params, with cases for an in-scope stop, another chat and an unknown param. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * gallery: a light window with no theme named renders light (#20794) * test(gallery): a light window with no theme named should show the light default Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(gallery): a light window with no theme named shows Apple System Colors Light The gallery defaulted the theme to the dark side of the app's default pair whatever the window appearance, so colorScheme=light (or Appearance: Light) rendered every stage in dark colors under a light media query. The default now follows the appearance, as the app's does with no theme set. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: cmux-autofix[bot] <cmux-autofix[bot]@users.noreply.github.com> * Channels view: gallery plays for a message link with no link read (red) A Cloud conversation has no link resolver (G4), so the Messages view's switch hand-off #/conversation/<id>/message/<id> showed an error. Two plays: a thread reply and a timeline message, opened through the store's openLink with an owner that has no resolver. cx-hnmbt Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Channels view: open a known conversation's message link without the owner's link read When conversation-link-resolve fails (a Cloud conversation, an older daemon) and the page knows the conversation, it opens it, pages the timeline until the message shows, opens its thread when it is a reply, and marks it. The Messages view's switch hands off Cloud selections this way. cx-hnmbt Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Channels view: format parseConversationLink (vp fmt) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Channels view: link fallback review follow-ups Ids in a known conversation's link may hold '-' (the gallery's sample ids); the scheme check follows the daemon (cmux[-<tag>], any case); the fallback runs only for a Cloud conversation or an owner without a link read, so a refused local link (a deleted message) still shows its error. cx-hnmbt Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * acpmux: host_lifetime idle test cleans up from the start and never signals a reused pid (cx-7z8yx review) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * cmux-tui: move the build identity into a leaf crate so an edit no longer recompiles cmux-remote cmux-remote's build script hashed the dirty source tree into CMUX_TUI_BUILD_IDENTITY, so every edit in the workspace reran it and recompiled cmux-remote and every crate above it (about 8 s of a 12.6 s one-line edit loop on rbx). The same build script now lives in cmux-build-identity, which only cmux-tui reads; cmux-remote takes the identity as an argument (SshBootstrapConfig::defaults, pinned_linux_payload). The identity value, its inputs and format, and every skew and SSH re-bootstrap comparison are unchanged. * test: warm the dev server in the Claude reasoning default browser test (#20884) #20592 landed after #20873 without warmViteServer, so check:browser-lanes is red on base again. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next: frame-strip report as an NSWindow method, not a namespace enum (no bead) (#20887) The package conventions lint fails every PR on the new all-static public enum WindowFrameStrip (cx-me3xd). The report reads its window, so it is an extension on NSWindow; same body, same report. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * Home channels: the run card is an inline disclosure (no frame, steps on an indented rail) The live and done run cards under a Chief's reply lose their box: "Working for" / "Worked for", the step count, cost and Open sit inline under the message, and the opened steps hang on a thin rail under the status mark. The narrow rules stay: the first line never wraps, and below 480 px of card width the step count and cost move under it with no leading separator. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Home channels: the run rail and columns follow the author's picture Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Home channels: the run sheet keeps its error line; run card columns in logical properties Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Revert "cmux-motion: Chrome tab strip tween ..." (8a3ee62) until the app-ffi release App 403 is fixed (run 38682698310) (hq-1d, chief go 2026-10-15, no bead) The release App could not publish cmux-app-ffi-854febb26527 (HTTP 403 on POST /releases), so the app FFI pin check stays red on the tip. The tween re-lands with the publish and repin after the App is fixed. * test(ci): nightly jobs that run the license check must init ghostty-next (#20893) * test(ci): nightly jobs that run the license check must init ghostty-next Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(ci): nightly recovery initializes ghostty-next before the license check Apple accepted, stapled and launch-tested each recovered nightly-next build, then verify-app-bundle-licenses.sh failed on the missing ghostty-next/build.zig.zon and the build was skipped as not accepted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * fix: keep catalog in base order after feat merge Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: cmux-autofix[bot] <cmux-autofix[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Lawrence Chen <54008264+lawrencecchen@users.noreply.github.com> Co-authored-by: safe-push <safe-push@cmux.local>
…ceiling, lower CPU weight; no process scanning) (#20755) * test(acpmux): a chat's harness runs in its own cgroup scope on Linux (red) cx-v9s8g, Linux half: systemd-run --user --scope with MemoryMax and CPUWeight from the profile or daemon env; unscoped when systemd cannot make a scope; no scope when both limits are 0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(acpmux): each chat's harness in its own cgroup scope on Linux cx-v9s8g, Linux half: session_scope.rs starts a session's harness under systemd-run --user --scope (which execs it: same pid and process group) with MemoryMax (ACPMUX_SESSION_MEMORY_MB, default half the machine's memory) and CPUWeight (ACPMUX_SESSION_CPU_WEIGHT, default 50), from the profile's env, then the daemon's; 0 turns one off. The kernel enforces both, so nothing measures or scans processes. Without systemd-run, or when it cannot make a scope (asked once per runner and limits), the harness starts as before. macOS's process-group half stays with ptyh-noscan after cx-t2sqm.3. A runaway hitting MemoryMax ends that process, not the scope (OOMPolicy=continue, dropped on a systemd that refuses it); a probe's answer holds for 5 minutes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at 348a805 - cargo fmt in Native/OptChat/optchat-chief Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38650955451 * cx-tgf4h red: cmux chief -p under ACPMUX_AGENT_LAUNCH=deny fails at once with a typed refusal * cx-tgf4h: the Chief says at once that agents are disabled in this build session With ACPMUX_AGENT_LAUNCH=deny (the nx-remote gui/input default since HQ #2130) or CMUX_AGENTS_DISABLED=1, no Chief turn can start an agent. `cmux chief -p` started a daemon and a brain and waited 240 s for a reply that could not come. - cmux-tui-core agent_launch: one test of the kill switch (acpmux launch_policy.rs), the reason agent_launch_disabled. - `cmux chief` (pipe and chat) refuses before it starts or sends anything: operation.failed, details.reason agent_launch_disabled, exit 1. - The daemon's supervisor starts no Chief brain; chief.engine.* and chief.stop answer the typed refusal at once. - optchat-chief host does not start (logs why, exit 0). - Home: the local Chief conversation's notice says agents are disabled; the engine panel maps the typed refusal (localized, all Home languages). - Every Chief proof script refuses at once under deny and names `nx-remote --allow-agents`. * cx-tgf4h review: forward chief control to a running brain first; daemon-side deny test; engine/stop CLI text; guard before side effects; fmt * acpmux tests: every acpmux process a test starts gets a hermetic environment (cx-s8wux) One helper, tests/support/daemon_env.rs, starts the acpmux binary for every integration test: env_clear, a bare PATH (python3 plus named host tools, then the system directories), a scratch HOME, and ACPMUX_AGENT_LAUNCH=deny unless the test drives a stand-in agent (Agents::StandIn keeps the bare PATH). The 26 test files that started the binary with the host environment use it; tests/hermetic_daemon_guard.rs refuses a test file that names CARGO_BIN_EXE_acpmux anywhere else. Root cause of cx-w014j: a fleet host's PATH holds real codex/claude, which a test daemon discovered and ran (probes, sign-in checks, auto-updates). * cx-tgf4h: fmt and clippy * acpmux tests: the hermetic HOME is <scratch>/home, never a chat's folder * acpmux tests: review fixes for the hermetic environment (cx-s8wux) python3 links the interpreter itself (sys.executable), not a version manager's shim; stale tool links from an earlier run are replaced; the guard also flags daemon_env::bin() outside a listed use; the live codex test probes only codex; codex_bridge_config's discovery test runs with launches denied. * acpmux tests: router_install_secret starts the router through daemon_env (cx-s8wux) * fix(cmux-next): the Chief profile relay's retry is a two-attempt for loop, not while true with a wakeup-allow (cx-ebm.59.5) * cmux-next sidebar perf round 3: Release-build hitch bench with real wheel input; O(1) hover-card hit - scripts/cmux-next/sidebar-rows-perf-release.py: runs in a Release tagged app (no debug.* methods) inside nx-remote --needs input: CLI workspaces (50 with a terminal, 950 empty), HID-tap wheel events, Animation Hitches per gesture, A/B of two apps in one job (side by side, interleaved), traces and the recorder's ktrace files removed after each export, PTY count logged. - SidebarListView+HoverCard: the hover-card hit reads the list's row dictionary instead of SidebarModel.isPlaceholder, an O(workspaces) section walk on every scroll frame (7-12% of main-thread samples while scrolling 1,000 rows in Release). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Channels: a primary or danger button keeps its fill under the pointer (a soft ring shows the hover); gallery play primary-hover Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Channels gallery: primary-hover asserts the hover ring and the unchanged fill; a budget with a reason for the Create frame Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * cmux-motion: Chrome tab strip tween (200 ms easeOutQuad, restart from value), tabStrip geometry tokens, damping <= 0 takes the fallback (hq-1d, no bead) Additive: MotionTween {TabOpen, TabClose, TabMove}, TweenCurve::EaseOutQuad, ease_out_quad, TweenParameters, TweenValue (f64 core: retarget restarts the duration from the current value with no velocity; the same target does not restart), Tween (f32, token-driven), MotionPolicy::tween (0 under speed off, Reduce Motion, or tabOpen/tabClose with ui.animations.newTab off), TabStripGeometry (design-tokens.json motion.tabStrip: max 200, open/close 18, min 56 active / 32 inactive / 64 pinned, reorder 16 x width / 200, closing mode +40 below / +60 trailing / 0.3 s). cmux-app-ffi ABI 2 exports cmux_motion_tween_{base,seconds,retarget,step}, cmux_motion_ease and cmux_motion_tab_strip_geometry. SpringParameters::finite_or now treats a damping fraction <= 0 like NaN (hq-4e nit). The parity corpus example prints tween paths (60 Hz: 12 frames for 200 ms). * acpmux: record a session's git branch and HEAD at start (hq#1920) (#20840) * test(acpmux): record a session's git branch and head at start A session should keep its folder's branch and HEAD commit as they were at session/new, and a fork its own folder's state at fork time (hq#1920), so agent spend can be joined to the pull request a session produced. These fail today: neither the saved meta nor _acpmux/info carries gitBranch or gitHead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(acpmux): record a session's git branch and head at start session/new and session/fork now store the cwd's checked-out branch and full HEAD commit in the session meta (gitBranch, gitHead), so a session can later be joined to the pull request it produced (hq#1920). The values are read once, as the session starts, from the repository's own files (HEAD, loose refs, packed-refs, a linked worktree's gitdir and commondir), never a git process, and off the async runtime. A detached HEAD records only the head; a folder outside a repository records neither; a lookup that fails never fails the session. A fork reads its own folder at fork time instead of copying the parent's. _acpmux/info carries both fields. Old session.json files load unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(acpmux): git state skips non-files, bad branch names and missing folders; follows symlinks Review of #20840: a FIFO HEAD hung session/new, a symlinked folder was walked lexically, a missing fork folder took its parent repository's state, and an invalid ref name was stored as the branch. The test git also runs without the machine's global or system config. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(acpmux): git state reads only small regular files, the physical folder and valid ref names Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * cx-tgf4h: keep CmuxNextApp line count (App size cap) * acpmux: a pooled agent host no longer spins on Linux reading its own record (cx-7z8yx) The record watch used notify's inotify backend, whose watch mask always includes open, close-write and modify, and ran its callback on every event. The callback reads the host record; on Linux that read queued an open and a close in the watched directory, which ran the callback again. Every pooled host spun at 100% CPU (about 200,000 read calls a second). Linux now has its own inotify watch, like the macOS kqueue watch: a mask of entry changes only (create, delete, moved from/to) and the directory's own delete or move, one thread in poll with no timeout, an eventfd to stop it. A read of the record never queues an event. The notify fallback (other platforms) ignores access events. macOS is unchanged. Behavior test (tests/host_lifetime.rs, Linux): a real daemon pools a host; idle for 3 s it makes fewer than 100 read calls and 30 CPU ticks (before: 599,042 reads, 298 ticks), a rename rewrite of its record keeps it, and the record removed ends it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * cmux-tui smoke: sidebar drag checks the drawn sidebar document order Since sidebar-v2 S6 the TUI draws the daemon's sidebar document, where a new workspace goes to the top (workspaces.newPlacement default), and a workspace drop is one sidebar.move that changes the document only. The smoke still assumed the list-workspaces order: it dragged the drawn top row (the new workspace) below the original, which the product did, and then read list-workspaces, which a sidebar.move never changes. The smoke now reads the order from sidebar.get, checks that the rail draws it, drags the top row below the second (a real reorder), and drags again when needed so the original workspace ends below the new one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * PR dock chips; tooltips only where nothing else names the control (#20375) * test: no tooltip on an element whose text shows Red on base: 105 elements with visible text carry title/data-tooltip. Command: bun test test/tooltip-rules.test.ts Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: PR dock chips; tooltips only where nothing else names the control The pull request dock's bars become content-sized chips (icon, #N, repo, title cut off at 360 px) with the dismiss button inside and no tooltip. Across the pages, a row, chip, link, path or thought whose text shows carries no title tooltip any more; tooltips stay on icon-only controls, shortcuts and text shown nowhere else (why a control is disabled or failed, who reacted, policy detail), each marked tooltip-allow. Tooltips wait the native hover delay (about a second) and show at once when moving straight on to the next one. Green: bun test test/tooltip-rules.test.ts Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: review of tooltip audit Keep the PR dock's state colours, drop four more tooltips the lint now finds inside components (a setting's summary, the branch and folder pickers, a video), let a click or scroll end the quick next-tooltip window, and move two tests to the no-tooltip rule. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: Backdrop Art's line has no tooltip Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at 047c247 - vp fmt webviews/src/pages/history/HistoryPage.tsx Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38502564051 * test(mock): the worked chat opens its pull request, so mock mode shows the PR dock Captures of the agent pane in a real window (--showcase runs the in-page mock) now show the pull request dock. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: the PR dock takes its own space; the transcript ends above it Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at 39f3ca9 - vp fmt webviews/test/ime-composition-keys.test.ts - vp fmt webviews/test/new-tab-omnibar-pointer.test.ts Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38567629461 * chore(next): PR autofix at c7cb261 - regenerated Packages/macOS/CmuxNext/ci-target-graph.json Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38592980576 * fix: a channel image keeps its name tooltip (the name shows only when it fails) Base added title={part.name} on channel image attachments (AttachmentViews.tsx). A loaded image shows no name, so the tooltip is its only label; mark it with tooltip-allow. tooltip-rules.test.ts: red before, green after. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at f221864 - regenerated Packages/macOS/CmuxNext/ci-target-graph.json Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38633116142 * fix: keep the tool card scope hint and Steer shortcut tooltips Both explain something shown nowhere else, so they stay under tooltip-allow. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at 022cc8e - vp fmt webviews/src/pages/home-channels/cloudHome.ts Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38647981824 --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: cmux-autofix[bot] <cmux-autofix[bot]@users.noreply.github.com> * ci: nightly-next recovery initializes the notices submodule before continuing accepted submissions The recovery job's checkout had no ghostty-next submodule, so the bundle notice check that notarize-nightly-dmg.sh runs after Apple accepts failed, and run 38669958906 skipped five accepted builds as 'Apple did not accept'. Initialize the submodule like the signing job does, and make the skip notice say that a post-acceptance check can also be the cause. * ci: the cmux NIGHTLY-identity job also initializes the notices submodule Run 38669958906's publish-nightly-identity-legacy job saw Apple accept, then failed the bundle notice check for lack of ghostty-next and retired the accepted submission of run 38609024986. * agent pane: progress and stop for a running Claude subagent or workflow (cx-liswe) (#20718) * test: a running subagent or workflow shows what it does and what it has spent Red on base: both rows read only "Running" (bun test test/subagent-progress.test.tsx). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * webviews: a running subagent or workflow shows what it does and what it has spent The subagent fold keeps acpmux's subagent_progress fields (action, tokens, tool uses, a workflow's agents done of started), and the transcript's subagent row adds them to its status line through one shared helper (subagentProgress.ts) the summary list and the Background tasks pane can use. Three plural strings, translated for every pane locale. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: a running subagent row has a stop button Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: stop a running Claude subagent or workflow from its row Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: restore the catalog's base order after the merge Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: stopping a subagent leaves its row closed, and a refused stop says so Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: a subagent's stop button waits for Claude and says when the stop failed The button is off while Claude has the request and until the subagent ends; a refused or unanswered stop (10 s) turns it into "Couldn't stop <name>" and it can be tried again. The pane no longer drops the error. Also moves the stop wiring above showSubagent's doc comment and corrects two comments. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * style: format the subagent progress test Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: stop rejects without English the pane would never show Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: restore the catalog's base order after the merge Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at 2fe6cc4 - vp fmt webviews/src/pages/home-channels/HomeChannelsPage.tsx Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38637059713 * test: the agent pane relays a subagent stop for its chat (cx-liswe) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: the agent pane may stop a subagent of its chat (cx-liswe) Adds _acpmux/subagent_stop to the pane's method allowlist: session-scoped, params sessionId and subagentSessionId, no gesture (it stops work, like _acpmux/kill). Without it the host refused every stop click. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: mirror the subagent stop into the shared pane policy (cx-liswe) The Swift allowlist took _acpmux/subagent_stop; policy.json, its parity source for Rust hosts, gets the same request, session scope and params, with cases for an in-scope stop, another chat and an unknown param. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * gallery: a light window with no theme named renders light (#20794) * test(gallery): a light window with no theme named should show the light default Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(gallery): a light window with no theme named shows Apple System Colors Light The gallery defaulted the theme to the dark side of the app's default pair whatever the window appearance, so colorScheme=light (or Appearance: Light) rendered every stage in dark colors under a light media query. The default now follows the appearance, as the app's does with no theme set. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: cmux-autofix[bot] <cmux-autofix[bot]@users.noreply.github.com> * Channels view: gallery plays for a message link with no link read (red) A Cloud conversation has no link resolver (G4), so the Messages view's switch hand-off #/conversation/<id>/message/<id> showed an error. Two plays: a thread reply and a timeline message, opened through the store's openLink with an owner that has no resolver. cx-hnmbt Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Channels view: open a known conversation's message link without the owner's link read When conversation-link-resolve fails (a Cloud conversation, an older daemon) and the page knows the conversation, it opens it, pages the timeline until the message shows, opens its thread when it is a reply, and marks it. The Messages view's switch hands off Cloud selections this way. cx-hnmbt Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Channels view: format parseConversationLink (vp fmt) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Channels view: link fallback review follow-ups Ids in a known conversation's link may hold '-' (the gallery's sample ids); the scheme check follows the daemon (cmux[-<tag>], any case); the fallback runs only for a Cloud conversation or an owner without a link read, so a refused local link (a deleted message) still shows its error. cx-hnmbt Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * acpmux: host_lifetime idle test cleans up from the start and never signals a reused pid (cx-7z8yx review) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * cmux-tui: move the build identity into a leaf crate so an edit no longer recompiles cmux-remote cmux-remote's build script hashed the dirty source tree into CMUX_TUI_BUILD_IDENTITY, so every edit in the workspace reran it and recompiled cmux-remote and every crate above it (about 8 s of a 12.6 s one-line edit loop on rbx). The same build script now lives in cmux-build-identity, which only cmux-tui reads; cmux-remote takes the identity as an argument (SshBootstrapConfig::defaults, pinned_linux_payload). The identity value, its inputs and format, and every skew and SSH re-bootstrap comparison are unchanged. * test: warm the dev server in the Claude reasoning default browser test (#20884) #20592 landed after #20873 without warmViteServer, so check:browser-lanes is red on base again. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next: frame-strip report as an NSWindow method, not a namespace enum (no bead) (#20887) The package conventions lint fails every PR on the new all-static public enum WindowFrameStrip (cx-me3xd). The report reads its window, so it is an extension on NSWindow; same body, same report. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * Home channels: the run card is an inline disclosure (no frame, steps on an indented rail) The live and done run cards under a Chief's reply lose their box: "Working for" / "Worked for", the step count, cost and Open sit inline under the message, and the opened steps hang on a thin rail under the status mark. The narrow rules stay: the first line never wraps, and below 480 px of card width the step count and cost move under it with no leading separator. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Home channels: the run rail and columns follow the author's picture Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Home channels: the run sheet keeps its error line; run card columns in logical properties Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Revert "cmux-motion: Chrome tab strip tween ..." (8a3ee62) until the app-ffi release App 403 is fixed (run 38682698310) (hq-1d, chief go 2026-10-15, no bead) The release App could not publish cmux-app-ffi-854febb26527 (HTTP 403 on POST /releases), so the app FFI pin check stays red on the tip. The tween re-lands with the publish and repin after the App is fixed. * test(ci): nightly jobs that run the license check must init ghostty-next (#20893) * test(ci): nightly jobs that run the license check must init ghostty-next Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(ci): nightly recovery initializes ghostty-next before the license check Apple accepted, stapled and launch-tested each recovered nightly-next build, then verify-app-bundle-licenses.sh failed on the missing ghostty-next/build.zig.zon and the build was skipped as not accepted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: cmux-autofix[bot] <cmux-autofix[bot]@users.noreply.github.com> Co-authored-by: Lawrence Chen <54008264+lawrencecchen@users.noreply.github.com> Co-authored-by: safe-push <safe-push@cmux.local>
… one left edge (cx-w4q7j) (#20892) * test: Chrome group look fixes from the sidebar groups verdict (red) A collapsed header shows its member count, the members' line starts under the header bar rounded, the header ink is white or near-black on the group color, and the header name starts on the ungrouped rows' column (cg-design-judge 2026-10-14, cx-w4q7j). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: Chrome group look: collapsed count, line under the bar, on-color ink, ungrouped column - A collapsed group header shows its member count after the name. - The members' line starts just under the header bar with a rounded end, so it no longer cuts the bar's rounded corner. - The header ink is white or near-black, whichever reads better on the group color, not the theme's text color (grey on the dark green header in Apple System Colors dark). - The header name starts on the ungrouped rows' leading column (icon there, name on their text column), one left edge for headers and ungrouped rows. cg-design-judge sidebar groups verdict 2026-10-14, cx-w4q7j. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cx-tgf4h red: cmux chief -p under ACPMUX_AGENT_LAUNCH=deny fails at once with a typed refusal * cx-tgf4h: the Chief says at once that agents are disabled in this build session With ACPMUX_AGENT_LAUNCH=deny (the nx-remote gui/input default since HQ #2130) or CMUX_AGENTS_DISABLED=1, no Chief turn can start an agent. `cmux chief -p` started a daemon and a brain and waited 240 s for a reply that could not come. - cmux-tui-core agent_launch: one test of the kill switch (acpmux launch_policy.rs), the reason agent_launch_disabled. - `cmux chief` (pipe and chat) refuses before it starts or sends anything: operation.failed, details.reason agent_launch_disabled, exit 1. - The daemon's supervisor starts no Chief brain; chief.engine.* and chief.stop answer the typed refusal at once. - optchat-chief host does not start (logs why, exit 0). - Home: the local Chief conversation's notice says agents are disabled; the engine panel maps the typed refusal (localized, all Home languages). - Every Chief proof script refuses at once under deny and names `nx-remote --allow-agents`. * cx-tgf4h review: forward chief control to a running brain first; daemon-side deny test; engine/stop CLI text; guard before side effects; fmt * cx-tgf4h: fmt and clippy * cx-tgf4h: keep CmuxNextApp line count (App size cap) * acpmux: a pooled agent host no longer spins on Linux reading its own record (cx-7z8yx) The record watch used notify's inotify backend, whose watch mask always includes open, close-write and modify, and ran its callback on every event. The callback reads the host record; on Linux that read queued an open and a close in the watched directory, which ran the callback again. Every pooled host spun at 100% CPU (about 200,000 read calls a second). Linux now has its own inotify watch, like the macOS kqueue watch: a mask of entry changes only (create, delete, moved from/to) and the directory's own delete or move, one thread in poll with no timeout, an eventfd to stop it. A read of the record never queues an event. The notify fallback (other platforms) ignores access events. macOS is unchanged. Behavior test (tests/host_lifetime.rs, Linux): a real daemon pools a host; idle for 3 s it makes fewer than 100 read calls and 30 CPU ticks (before: 599,042 reads, 298 ticks), a rename rewrite of its record keeps it, and the record removed ends it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * ci: nightly-next recovery initializes the notices submodule before continuing accepted submissions The recovery job's checkout had no ghostty-next submodule, so the bundle notice check that notarize-nightly-dmg.sh runs after Apple accepts failed, and run 38669958906 skipped five accepted builds as 'Apple did not accept'. Initialize the submodule like the signing job does, and make the skip notice say that a post-acceptance check can also be the cause. * ci: the cmux NIGHTLY-identity job also initializes the notices submodule Run 38669958906's publish-nightly-identity-legacy job saw Apple accept, then failed the bundle notice check for lack of ghostty-next and retired the accepted submission of run 38609024986. * Channels view: gallery plays for a message link with no link read (red) A Cloud conversation has no link resolver (G4), so the Messages view's switch hand-off #/conversation/<id>/message/<id> showed an error. Two plays: a thread reply and a timeline message, opened through the store's openLink with an owner that has no resolver. cx-hnmbt Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Channels view: open a known conversation's message link without the owner's link read When conversation-link-resolve fails (a Cloud conversation, an older daemon) and the page knows the conversation, it opens it, pages the timeline until the message shows, opens its thread when it is a reply, and marks it. The Messages view's switch hands off Cloud selections this way. cx-hnmbt Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Channels view: format parseConversationLink (vp fmt) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Channels view: link fallback review follow-ups Ids in a known conversation's link may hold '-' (the gallery's sample ids); the scheme check follows the daemon (cmux[-<tag>], any case); the fallback runs only for a Cloud conversation or an owner without a link read, so a refused local link (a deleted message) still shows its error. cx-hnmbt Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * acpmux: host_lifetime idle test cleans up from the start and never signals a reused pid (cx-7z8yx review) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * cmux-tui: move the build identity into a leaf crate so an edit no longer recompiles cmux-remote cmux-remote's build script hashed the dirty source tree into CMUX_TUI_BUILD_IDENTITY, so every edit in the workspace reran it and recompiled cmux-remote and every crate above it (about 8 s of a 12.6 s one-line edit loop on rbx). The same build script now lives in cmux-build-identity, which only cmux-tui reads; cmux-remote takes the identity as an argument (SshBootstrapConfig::defaults, pinned_linux_payload). The identity value, its inputs and format, and every skew and SSH re-bootstrap comparison are unchanged. * test: warm the dev server in the Claude reasoning default browser test (#20884) #20592 landed after #20873 without warmViteServer, so check:browser-lanes is red on base again. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next: frame-strip report as an NSWindow method, not a namespace enum (no bead) (#20887) The package conventions lint fails every PR on the new all-static public enum WindowFrameStrip (cx-me3xd). The report reads its window, so it is an extension on NSWindow; same body, same report. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * Home channels: the run card is an inline disclosure (no frame, steps on an indented rail) The live and done run cards under a Chief's reply lose their box: "Working for" / "Worked for", the step count, cost and Open sit inline under the message, and the opened steps hang on a thin rail under the status mark. The narrow rules stay: the first line never wraps, and below 480 px of card width the step count and cost move under it with no leading separator. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Home channels: the run rail and columns follow the author's picture Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Home channels: the run sheet keeps its error line; run card columns in logical properties Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Revert "cmux-motion: Chrome tab strip tween ..." (8a3ee62) until the app-ffi release App 403 is fixed (run 38682698310) (hq-1d, chief go 2026-10-15, no bead) The release App could not publish cmux-app-ffi-854febb26527 (HTTP 403 on POST /releases), so the app FFI pin check stays red on the tip. The tween re-lands with the publish and repin after the App is fixed. * test(ci): nightly jobs that run the license check must init ghostty-next (#20893) * test(ci): nightly jobs that run the license check must init ghostty-next Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(ci): nightly recovery initializes ghostty-next before the license check Apple accepted, stapled and launch-tested each recovered nightly-next build, then verify-app-bundle-licenses.sh failed on the missing ghostty-next/build.zig.zon and the build was skipped as not accepted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next: group header count yields to trailing controls; review test fixes Drop the collapsed count when a narrow sidebar has no room for it, measure the ungrouped column the way the header's is, expect on-color inks in the palette test, and mark ChipInks nonisolated like its neighbours. 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> Co-authored-by: safe-push <safe-push@cmux.local>
…t folder, icon-only computer when narrow (#20791) * test: location strip lines up with the prompt and survives a narrow pane Boundary tests for the composer's location strip: its folder icon and branch chevron line up with the prompt's edges, no gap shows where it stands inside the card's corner, no "·" floats between folder and computer, and at 290-300 px the folder cuts in the middle, the computer shows its icon alone and the branch keeps its name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * CmuxNext: align the composer location strip with the prompt; middle-cut folder, icon-only computer when narrow - The strip's folder icon sits over the prompt's first letter and the branch chevron over its last column (strip inset 9 px, a foot covers the card's corner drop so it still stands on the card). - The floating "·" between folder and computer is gone; the two are ghost buttons 2 px apart, told apart by their icons. - A folder name cuts in the middle ("atl…web"); below a 320 px strip the computer shows its icon alone with its name in the tooltip and label; the branch keeps its name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * CmuxNext: location strip cuts a folder only when it runs out of room; tail keeps the last word The strip's folder and branch still carried the controls' fixed cap (190 px, 145 px under a 480 px pane), so a long folder name cut beside empty strip, and a long branch cut before half the strip. They now cut only to fit. The computer never shrinks (a sub-pixel shrink put an ellipsis on "This Mac"). The middle cut keeps the name's last word when it is 3 to 10 characters ("atlas-we…service", not "…ervice"). Adds a long-folder gallery variant and boundary tests at 300, 400 and 760 px. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next browser: Fit as 16:9 Desktop per browser tab (browser.tab.emulate {fit}, palette, device menu, CEF + WebKit) (cx-va1wd) A browser tab can fit a desktop layout instead of a device: the daemon keeps {fit: {aspect: [16, 9]}} on the tab and shows extra.emulation {mode: fit, fit {aspect, min_width 1024, max_width 1920}}. The engine lays the page out at clamp(view height x 16/9, 1024, 1920) CSS px, scales it to the view width, and makes the layout as tall as the view over that scale, so the page fills the pane with no bars. It recomputes on resize without a reload. CEF sends the Emulation calls with the computed size and scale; WebKit sizes the web view and scales its container. Surfaces: the browserFitDesktop toggle (palette with a check, context menu, cmux browser fit-desktop, MCP), a row in Emulate Device..., and cmux tab <tab> emulate --fit 16:9 (MCP browser.tab.emulate fit). Palette rows of toggles that are on show a check. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * cmux-next: an agent page in an unfocused pane cannot take the keyboard by itself; responder source counts the current event only during its dispatch (cx-3hw0i.2) A subagent pane's page focuses its composer as it loads; WebKit then asks the window to make its web view first responder (WebPageProxy::makeFirstResponder, seen in debug stacks of nx job 1014-202829-5378d2), and the focus model took that as the user's choice: the new pane got the keyboard and the daemon focus although its move ran with keep_focus. ShellWindow now refuses that request when no input event is in dispatch, the focus model is not applying its own target or waiting on an expectation, and the page is not in the focused pane. FocusEvent.Source.current read NSApp.currentEvent, which stays the last key after its dispatch, so such a change was logged as keyboard input; it now counts the event only inside sendEvent. * cmux-next: Source.current returns its switch (cx-3hw0i.2) * cmux-next: only a focus expectation for the page's own pane lets it take the keyboard (review P2) (cx-3hw0i.2) * cmux-next browser: Fit as 16:9 Desktop review fixes (cx-va1wd) browser-fit-v1 gates the action and the menu row, so an older daemon never sees an unknown fit field. A fit that shows the page as is keeps the WebKit view at the container's size (it stayed 0x0 or stale). The palette check comes from a new opt-in, non-refusing Action.paletteState, so other toggles keep their icons and no refusal shows while the palette builds. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * cmux-tui: the fit case joins the extra transport path cases (one case per operation in cases.rs) (cx-va1wd) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * cmux-next: debug agent-pane click on the view path gives the clicked web view the keyboard inside an input event, as AppKit's click does (cx-3hw0i.2) * cmux-next browser: the device menu's Fit row comes from a helper (the inline optional closure crashed the type checker) (cx-va1wd) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * AcpmuxChiefHandoff: the log says every built-in Chief preset of a mismatched daemon fails closed, not only codex (review note of 1ae9e97593fd) * cx-8mla8 red: cmux chief list shows the daemon's words for an internal registry failure * chief CLI brain HOME red: a brain cmux chief starts gets the account's home, not the caller's (follow-up of c47dd2fd0112) * cx-8mla8: the CLI shows the daemon's own words for an operation.failed (details.extra.message), never a bare 'internal: internal' * chief CLI: a brain cmux chief starts gets the account's home (getpwuid_r), like the daemon's brains (c47dd2fd0112) * CI optchat-chief job: run the dm_daemon behavior test against a real daemon (shared_acpmux already runs in the suite step) * cx-8mla8 review: accurate handoff log text (codex turn/compactor fail closed, others start without MUX_HOME); sanitize the daemon's words; control refusal keeps the reason; bounded wait for the state dir; skip the HOME test without a user record * scripts: agent-pane-live.py typed-keys run brings the app front with open before it clicks the composer (cx-3hw0i.2) * scripts: ext-mv2-live.py judges uBlock Origin by what DevTools sees on an uncached load uBlock Origin enforced its filters in the earlier runs: it answers adsbygoogle.js and pagead2 XHR with neutered local resources (||pagead2.googlesyndication.com^$xhr,redirect=noop.js), so the page saw loads. The network check now classifies each watched request from the Network domain (blocked, redirected to the extension, loaded) with the cache off; dynamic filtering is judged the same way; a tabs.insertCSS probe checks the cosmetic path. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * cmux-next browser: full uBlock Origin built in (bundled, on by default, browser.builtInAdBlocker toggle) Lawrence 2026-10-14: ship full uBlock Origin (Manifest V2) pre-installed and enabled, with a Settings toggle; the Web Store lists only uBlock Origin Lite. - scripts/cmux-next/fetch-ublock.sh stages the pinned gorhill release ZIP (1.75.0, SHA-256 checked) with the Web Store key in its manifest (stable id cjpalhdlnbpafiamejdnhcphjbkeiagm), LICENSE.txt, SOURCE.txt (corresponding source link) and a source receipt; bundle-ublock.sh copies it to Contents/Resources/Extensions/ublock-origin from the Embed CEF phase. - CEFBuiltInExtensions loads it at Chromium start through --load-extension without turning on the extensions developer mode. - Setting browser.builtInAdBlocker (Browser > Extensions, default on; agents may not change it: privacy) is followed by the CEF engine. - The Extensions menu says "uBlock Origin (full) is built in". - ext-mv2-live.py builtin checks the bundled copy. Bead cx-d0d.100. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * scripts: ext-mv2-live.py counts data: no-op redirects as enforcement, turns on uBlock Origin's advanced mode for dynamic rules, reads its content-script state Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * settings: the Browser page shows the Extensions group (built-in uBlock Origin toggle) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * cmux-next exports: settings schema, MDM, defaults snapshot and Settings page strings for browser.builtInAdBlocker Generated by the export-settings cmux-ci step (abe9d52acb54), defaults_guard.py snapshot and gen-strings.mjs. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * scripts: ext-mv2-live.py --label and --config (A/B runs of the built-in uBlock Origin) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * scripts: ext-mv2-live.py checks generic cosmetic filtering on example.com and reads dynamic blocks from the page uBlock Origin turns generic cosmetic filtering off on the 127.0.0.1 test page (its content script reports noGenericCosmeticFiltering); dynamic filtering did block the script (the page saw onerror; DevTools reported 'failed other'). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * cmux-next browser: built-in uBlock Origin stays enabled without developer mode; review fixes Live proof on a fresh profile: Chromium recorded the --load-extension copy as unpacked and disabled it (DISABLE_UNSUPPORTED_DEVELOPER_EXTENSION, 1<<24) because the built-in load does not turn on developer mode. When the built-in copy loads, disable-features=ExtensionDisableUnsupportedDeveloper keeps it on (the shim merges it into CEF's list). Review fixes: the setting's loaded value is set before any Chromium tab can start Chromium; the Extensions menu line shows only when this Chromium loaded the built-in copy; a folder path with a comma is not passed; a failed stage removes a stale copy from the app; the shared cache moves a staged copy in with one rename (concurrent builds); SOURCE.txt pins the source tarball digest and names the bundled components' licenses; embed-cef.test.sh copies bundle-ublock.sh and sets CMUX_NEXT_SKIP_UBLOCK=1; cmux-next.yml path filters list fetch-ublock.sh. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * scripts: embed-cef strip test skips the built-in uBlock Origin stage Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * cmux-next browser: Fit as 16:9 Desktop state and requests live in CmuxNextDaemon (TabModel.fitsDesktop, setTabFit, setTabEmulation); the App binding does not grow the App (cx-va1wd) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * cmux-next: the self-focus refusal lives in CmuxNextAgentPane (AgentPaneView.refusesSelfFocus); drop the expectation exemption (review: the focus model lands those first); no CmuxNextApp growth (cx-3hw0i.2) * cmux-next exports: regenerate settings schema, MDM and Settings page strings after rebasing on feat-cmux-next (browser.builtInAdBlocker) export-settings cmux-ci step a05ed0dab553. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * cmux-tui: move the build identity into a leaf crate so an edit no longer recompiles cmux-remote cmux-remote's build script hashed the dirty source tree into CMUX_TUI_BUILD_IDENTITY, so every edit in the workspace reran it and recompiled cmux-remote and every crate above it (about 8 s of a 12.6 s one-line edit loop on rbx). The same build script now lives in cmux-build-identity, which only cmux-tui reads; cmux-remote takes the identity as an argument (SshBootstrapConfig::defaults, pinned_linux_payload). The identity value, its inputs and format, and every skew and SSH re-bootstrap comparison are unchanged. * cx-8mla8 red: an internal failure gives the CLI a Request ID that the daemon log names with the cause * cx-8mla8: an internal operation.failed carries a Request ID (details.extra.request_id); the daemon logs it with the operation and the cause; the CLI prints it * Home channels: the run card is an inline disclosure (no frame, steps on an indented rail) The live and done run cards under a Chief's reply lose their box: "Working for" / "Worked for", the step count, cost and Open sit inline under the message, and the opened steps hang on a thin rail under the status mark. The narrow rules stay: the first line never wraps, and below 480 px of card width the step count and cost move under it with no leading separator. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Home channels: the run rail and columns follow the author's picture Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Home channels: the run sheet keeps its error line; run card columns in logical properties Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * cx-8mla8: fmt * Revert "cmux-motion: Chrome tab strip tween ..." (8a3ee620b09a) until the app-ffi release App 403 is fixed (run 38682698310) (hq-1d, chief go 2026-10-15, no bead) The release App could not publish cmux-app-ffi-854febb26527 (HTTP 403 on POST /releases), so the app FFI pin check stays red on the tip. The tween re-lands with the publish and repin after the App is fixed. * test(ci): nightly jobs that run the license check must init ghostty-next (#20893) * test(ci): nightly jobs that run the license check must init ghostty-next Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(ci): nightly recovery initializes ghostty-next before the license check Apple accepted, stapled and launch-tested each recovered nightly-next build, then verify-app-bundle-licenses.sh failed on the missing ghostty-next/build.zig.zon and the build was skipped as not accepted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * ci: publish acpmux for Windows (cmux-tui-acpmux-x86_64-pc-windows-gnu.exe) for GPUI (cx-ephhf) cmux-tui-build-package.yml: input windows_acpmux; job build-windows-acpmux, in parallel with build-windows on the same runner, Rust pin, MinGW toolchain check and lld: cargo build -p acpmux --release --locked --target x86_64-pc-windows-gnu, acpmux.exe --version, artifact cmux-tui-acpmux-x86_64-pc-windows-gnu. Optional (continue-on-error): a failure never drops the Windows daemon. cmux-tui-artifacts.yml sets windows_acpmux; the publish job moves the exe into cmux-tui-windows/<sha>/ (manifest sha256), never cmux-tui/<sha>/ (forbidden in the pre-upload check). publish-cmux-tui-tree.py: an optional Windows companion, so a new tree carries cmux-tui/tree/<key>/cmux-tui-acpmux-x86_64-pc-windows-gnu.exe and .sha256, attested in completion-windows.json; the tree check verifies each optional Windows companion that completion attests. No acpmux code change. * acpmux: suggested tasks, Do it here and child results back to the parent (cx-lo9yf) (#20864) * acpmux: test suggested tasks, Do it here and results back to the parent (cx-lo9yf) Behavior tests at the hub boundary for the suggested-tasks contract: a groupId on session_offer, the "here" decision, the child's first reply delivered once to its parent with offer_result provenance, and the cmux-sessions MCP server's suggest_tasks tool. They fail before the fix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * acpmux: suggested tasks, Do it here and child results back to the parent (cx-lo9yf) - cmux-sessions MCP server gains suggest_tasks: 1 to 5 follow-ups, one _acpmux/offer_session per task under one fresh groupId. - _acpmux/offer_session takes an optional one-line groupId (<= 64 bytes), recorded on session_offer. - _acpmux/offer_respond takes outcome "here": the offer closes with no chat. - When an accepted offer's chat ends its first turn, the hub sends its last reply to the parent once (steer, else queue), recorded with provenance {kind: offer_result, offerId, childSessionId, title}. Set hub-internally; no new client param. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * ci: an Apple-accepted cmux NIGHTLY-identity submission is never retired; bundle checks run from the build's own source (cx-x7hwx) Run 38669958906: Apple accepted 00b3d8f2, staple and smokes passed, then the bundle notice check failed (no ghostty-next in the job's checkout) and the job retired the accepted submission. hq-a3 decision 2026-10-15: - An Accepted submission is never retired by a later failure (staple, spctl, smoke, license check or publication). The job stores metadata marking its bundle accepted (bundle_run points at the original bundle); later runs continue it with no time limit, re-staple, re-check and publish, and never submit that build again while the bundle is kept. The failure counts ("Build N failed:"); two counted failures stop the build, a newer build still goes. Apple refused -> retire and count. (A new submission Apple accepts within the 20 min wait keeps no bundle: notarize-nightly-dmg.sh writes no state for it.) - The legacy-identity-target script counts failures per build itself (--failure-log, --max-failures 2) for continue and new. - Class fix: the bundle notice check (LICENSE, toolchain pins, ghostty and ghostty-next gitlinks and license trees) runs from a checkout of the copied build's own commit (CMUXCommit) with ghostty-next initialized there (CMUX_VERIFY_LICENSES_TOOL), because the copied cmux NEXT build can be older than the run's commit. - CI guard in tests/test_nightly_universal_build.sh: every job that calls notarize-nightly-dmg.sh initializes ghostty-next first; the legacy job runs the checks from the build's source. * cmux-next: launch marks for the connecting screen and a launch journey script (cx-r650e) connecting_view_shown / connecting_status_shown / connecting_view_left / workspace_content_shown say how long a launch showed the Connecting to cmux-tui screen. scripts/cmux-next/launch-connect-journey.py drives a fleet-built tagged app through first, warm and restart launches with a large registry and checks the screen never shows on a relaunch. * cmux-next: restore phase launch marks; launch journey checks the first launch's status line (cx-r650e) * cmux-next browser: Chromium asks browser.builtInAdBlocker when it starts (no CmuxNextApp growth) The App hands the CEF engine a closure over the settings snapshot instead of following the value in a task: the value Chromium reads is the one current at its start, and CmuxNextApp stays at the base's line count (size cap). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * cmux-next: workspace create launch marks (cx-r650e) * launch-connect-journey: never-left flag, clear server status error (review) * cmux-next: keep only the connecting-screen launch marks (CmuxNextApp size cap); restore/spawn marks were diagnosis only (cx-r650e) * cmux-next: no Connecting to cmux-tui line once connected; the first-workspace wait shows no status (cx-r650e, cx-b4sjc) * cmux-next: CmuxNextApp cap 113735 = base 113729 + 6 launch-mark/status lines (chief go 2026-10-15, cx-r650e) * web: fix the feat-cmux-next web test base reds (no bead) (#20865) * web: fix two feat-cmux-next web test base reds (no bead) The main sync brought #20524's devbox-agents-1014b ladder, so the awaiting-rebake excuse for feat's own devbox sources now names that bake and feat's current digest. The publishable-key test still expected the x-stack-project-id header that #20236 replaced with x-hexclave-project-id. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * web: drop cmux-tui files staged in this worktree by mistake Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * web: give the 0.65.2 changelog cards their try-it lines The changelog cards test requires every feature of the latest documented release to say how to try it; v0.65.2 shipped without them (red on main and feat-cmux-next). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * test: cmux NIGHTLY-identity failure count moved into the target script (cx-x7hwx) * cmux-next: All chats Filter menu: Working, Needs input, Done (cx-htpk0) (#20747) * test: All chats filters by status (cx-htpk0) Red: the All chats header has no Filter menu yet. Adds the filter's strings (All, Working, Needs input, Done, Filter) in all 21 locales, copied from the existing translations of the same words. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: All chats Filter menu: Working, Needs input, Done (cx-htpk0) The New Tab and History pages' All chats header gets a Filter menu next to Chats and Projects. All stays the default and shows the list as it was. Working and Needs input show the live chats in that state (a failed turn counts as needing input); Done shows live chats at rest, then the indexed chats. A filter with nothing to show says No matching chats. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at b02e6111f073 - vp fmt webviews/src/pages/home-channels/cloudHome.ts Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38646041870 * test: a Filter pick closes its menu (cx-htpk0) Red: the shared Select keeps its menu open after a pick, and in the agent pane (which does not load ui.css) that open menu draws as bare text over the rows. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: All chats Filter uses the pane's styled menu (cx-htpk0) The real-app capture showed the Select popup unstyled: the agent pane does not load ui.css. The Filter is now a Menu styled as the changes view's scope menu, with a chevron, and a pick closes it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * gallery: All chats Filter open (cx-htpk0) Covers ChatFilterMenu, which gallery coverage requires of every component. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: cmux-autofix[bot] <cmux-autofix[bot]@users.noreply.github.com> * Fix: hibernated Chromium tabs leave their renderers running (#20866) * test: hidden pages hibernate despite scripted forms and keep bounded snapshots Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: hibernate pages whose scripts fill their forms and bound hibernated snapshots The hibernation probe called every form field whose value differed from its default the person's input, so pages that fill fields from script (a <select> with no default option, a version menu, appearance radios) never hibernated: 7 of the audit's 20 sites, one live renderer each. The page recorder now notes fields the person changed (trusted input and change events) and the probe asks it, falling back to the old comparison when the recorder did not answer. A hibernated tab's placeholder kept its own full-size snapshot outside the 32 MB preview cache; it now reads the picture from that cache and holds it only while a pane shows it. An exempt page is no longer captured before the probe decides it stays. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: hibernation keeps used pages and rich edits, and wakes with a fresh bounded snapshot #20866 review: a page the person used whose script then set a field, a contenteditable draft, a pane larger than the preview cache, and a page that hibernates a second time. Adds a capture seam to BrowserHibernation (no behavior change). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: hibernation keeps used and rich-edited pages, and wakes with a fresh bounded snapshot #20866 review findings: - A recorder 'no edits' no longer overrides the field comparison once the person used the document (trusted key, pointer or paste, or a user activation the page had when Chromium's late-attached recorder arrived): values a widget or script set for the person keep the page. Untouched documents whose script fills fields still hibernate. - Trusted typing in a contenteditable editor counts as an edit. - The hibernation snapshot is scaled to at most a quarter of the 32 MB preview cache, which refused a large pane's picture outright. - A page takes a fresh picture each time it hibernates and drops its old one when it wakes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: drive the used-page case with a key press The synthesized click never reached the WebKit page on the fleet (the test stopped before its expectation, red and green alike); a key press to the first-responder web view is the path the typing tests already use. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: browsing a page or sending a composer leaves it free to hibernate; snapshots keep color and shape #20866 second review: a key press on a page whose script filled its fields, a rich editor cleared after typing, and a large P3 pane's snapshot color space and aspect. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: browsing a page or sending a composer no longer keeps a tab awake #20866 second review: - At the person's first use the recorder notes every field's value; after that a field counts only when it differs from its default and from that value, so fields a script filled at load no longer pin the tab, while a value a widget sets later still does. - Rich editors are tracked weakly with the text they held when the person started typing; a cleared or removed composer no longer counts. - Trusted click and drop count as use. - The hibernation snapshot scales through TabPreviewFitting (off the main actor, keeps the color space and aspect) instead of a new helper. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * refactor: the hibernation probe script lives with the page recorder Keeps the app target from growing (its size cap). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: the moved field probe gets its own name Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * ci: cmux NIGHTLY-identity skips pending metadata whose bundle is confirmed gone; guard ignores comments (cx-x7hwx) * cmux NEXT: Cloud machines show Reconnecting while the link redials (cx-z5oif) (#20896) * test(cx-z5oif): a Cloud link that redials stops reading as connected The test runs a CloudMachineLink against a stand-in /api/vm, hub and cmux-tui remote connect that reports reconnecting, then connected. The seams (CloudLinkRedial, SidebarMachine.redialing) are inert here, so the machine keeps reading as connected: red. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(cx-z5oif): show Reconnecting while a Cloud link redials After sleep, a network drop or a Wi-Fi change the cmux-tui remote connect client redials on its own and keeps its local socket up, so a Cloud machine kept reading as connected while its terminals froze. The link now follows the client's later connection-snapshot lines into CloudLinkRedial, and the sidebar header reads Reconnecting until the client reports connected again, as SSH machines do (cx-ojk7n). The App target gains no lines. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * New Tab composer: a long draft wraps and grows instead of showing as one cut line (#20870) * test: a typed draft wraps whole and the composer caps then scrolls The New Tab field (where every chat starts) holds a draft on one clipped line. This boundary test types a long one-line draft at 300 and 760 px, focused and blurred, and grows a draft word by word past the field's cap, in Chromium and WebKit, for the New Tab field and the chat composer (idle, running, queued). The New Tab cases fail. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: the New Tab composer wraps a long draft instead of cutting it The New Tab page, where every chat starts, held the draft in a one-line <input> in a fixed 52px row, so a long prompt showed as one clipped line (scrolled to the caret while typing, cut at the field's edge once blurred). The field is now a textarea that wraps and grows with the draft up to eight lines (the chat composer's cap) or 40% of the pane, then scrolls inside, keeping a caret at the draft's end in view. Return still sends; the prompt glyph sits on the first line; the placeholder stays one line. Tests that set the field's value use its own prototype. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * acpmux: Claude chats get a short generated title (cx-ncc.91) (#20538) * test(acpmux): a chat its harness never titles gets a generated title (cx-ncc.91) Red: acpmux keeps the first prompt as a Claude chat's title, and has no title command. The tests use a fake title command; none reaches a model. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(acpmux): format the generated-title test (cx-ncc.91) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * acpmux: generated titles for chats their harness never titles (cx-ncc.91) Claude Code's -p stream-json has no title event, so a Claude chat kept its first prompt's line as its title, and so did the workspace named after it. After a chat's first completed turn, acpmux asks a title command once for 3-6 words: titles.command (or ACPMUX_TITLE_COMMAND), else the chat's own Claude Code profile with --model haiku, no tools, MCP or session file. A harness title always wins. The result is a titled record that watchers hear of as session_changed. titles.generate: false turns it off. The session-changed kind table moves to server/change_kind.rs and the test to its own binary: server/mod.rs and hub_integration.rs are over budget. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at c7394b95436c - regenerated schemas/defaults/cmux-next.json Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38542576704 * acpmux: title only a chat's own first prompt, without the person's hooks (cx-ncc.91) Review: a chat titled before generated titles, or adopted, was retitled on its next turn from its latest prompt; a queued second turn could swap the prompt and empty the reply first; the title call ran the person's Claude hooks; a wrapper's children outlived the timeout. Now only a title set from this chat's first prompt (title_source prompt) is replaced, from that prompt as dispatched, with the reply only while no later turn has started. The default command passes disableAllHooks, and a timeout ends the command's whole process group. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(acpmux): the title test watches session changes, as the app does (cx-ncc.91) _acpmux/session_changed reaches only connections that called _acpmux/watch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * acpmux: an adopted chat keeps its title; end a timed-out title group first (cx-ncc.91) Re-review: an adopted chat whose replay set no title (history from the harness, no replayable turns) took its first prompt here as a prompt title, so a later prompt was sent to the title model. check_resumed, which every adoption passes, now marks it adopted. On a timeout the title command's group is killed while its unreaped leader still holds the group id. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * acpmux tests: every acpmux process a test starts gets a hermetic environment (cx-s8wux) One helper, tests/support/daemon_env.rs, starts the acpmux binary for every integration test: env_clear, a bare PATH (python3 plus named host tools, then the system directories), a scratch HOME, and ACPMUX_AGENT_LAUNCH=deny unless the test drives a stand-in agent (Agents::StandIn keeps the bare PATH). The 26 test files that started the binary with the host environment use it; tests/hermetic_daemon_guard.rs refuses a test file that names CARGO_BIN_EXE_acpmux anywhere else. Root cause of cx-w014j: a fleet host's PATH holds real codex/claude, which a test daemon discovered and ran (probes, sign-in checks, auto-updates). * acpmux tests: the hermetic HOME is <scratch>/home, never a chat's folder * acpmux tests: review fixes for the hermetic environment (cx-s8wux) python3 links the interpreter itself (sys.executable), not a version manager's shim; stale tool links from an earlier run are replaced; the guard also flags daemon_env::bin() outside a listed use; the live codex test probes only codex; codex_bridge_config's discovery test runs with launches denied. * acpmux tests: router_install_secret starts the router through daemon_env (cx-s8wux) * cmux-next: fix two Chief profile relay base reds (concurrency check, Release compile crash) (no bead) (#20876) * cmux-next: mark the Chief profile relay retry loop as bounded (no bead) check-concurrency flags its while true as a loop that can spin. It retries once, only after a lost connection, and every other error throws. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next: nonisolated deinit for PageCallDeadline.Once (no bead) The Release compile crashes swift-frontend 6.3.3 in EarlyPerfInliner on the isolated deinit of this main-actor generic class (exit 65, no error line), the same crash #20408 fixed elsewhere. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * fix(cmux-next): the Chief profile relay's retry is a two-attempt for loop, not while true with a wakeup-allow (cx-ebm.59.5) * cmux-next sidebar perf round 3: Release-build hitch bench with real wheel input; O(1) hover-card hit - scripts/cmux-next/sidebar-rows-perf-release.py: runs in a Release tagged app (no debug.* methods) inside nx-remote --needs input: CLI workspaces (50 with a terminal, 950 empty), HID-tap wheel events, Animation Hitches per gesture, A/B of two apps in one job (side by side, interleaved), traces and the recorder's ktrace files removed after each export, PTY count logged. - SidebarListView+HoverCard: the hover-card hit reads the list's row dictionary instead of SidebarModel.isPlaceholder, an O(workspaces) section walk on every scroll frame (7-12% of main-thread samples while scrolling 1,000 rows in Release). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Channels: a primary or danger button keeps its fill under the pointer (a soft ring shows the hover); gallery play primary-hover Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Channels gallery: primary-hover asserts the hover ring and the unchanged fill; a budget with a reason for the Create frame Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * cmux-motion: Chrome tab strip tween (200 ms easeOutQuad, restart from value), tabStrip geometry tokens, damping <= 0 takes the fallback (hq-1d, no bead) Additive: MotionTween {TabOpen, TabClose, TabMove}, TweenCurve::EaseOutQuad, ease_out_quad, TweenParameters, TweenValue (f64 core: retarget restarts the duration from the current value with no velocity; the same target does not restart), Tween (f32, token-driven), MotionPolicy::tween (0 under speed off, Reduce Motion, or tabOpen/tabClose with ui.animations.newTab off), TabStripGeometry (design-tokens.json motion.tabStrip: max 200, open/close 18, min 56 active / 32 inactive / 64 pinned, reorder 16 x width / 200, closing mode +40 below / +60 trailing / 0.3 s). cmux-app-ffi ABI 2 exports cmux_motion_tween_{base,seconds,retarget,step}, cmux_motion_ease and cmux_motion_tab_strip_geometry. SpringParameters::finite_or now treats a damping fraction <= 0 like NaN (hq-4e nit). The parity corpus example prints tween paths (60 Hz: 12 frames for 200 ms). * acpmux: record a session's git branch and HEAD at start (hq#1920) (#20840) * test(acpmux): record a session's git branch and head at start A session should keep its folder's branch and HEAD commit as they were at session/new, and a fork its own folder's state at fork time (hq#1920), so agent spend can be joined to the pull request a session produced. These fail today: neither the saved meta nor _acpmux/info carries gitBranch or gitHead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(acpmux): record a session's git branch and head at start session/new and session/fork now store the cwd's checked-out branch and full HEAD commit in the session meta (gitBranch, gitHead), so a session can later be joined to the pull request it produced (hq#1920). The values are read once, as the session starts, from the repository's own files (HEAD, loose refs, packed-refs, a linked worktree's gitdir and commondir), never a git process, and off the async runtime. A detached HEAD records only the head; a folder outside a repository records neither; a lookup that fails never fails the session. A fork reads its own folder at fork time instead of copying the parent's. _acpmux/info carries both fields. Old session.json files load unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(acpmux): git state skips non-files, bad branch names and missing folders; follows symlinks Review of #20840: a FIFO HEAD hung session/new, a symlinked folder was walked lexically, a missing fork folder took its parent repository's state, and an invalid ref name was stored as the branch. The test git also runs without the machine's global or system config. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(acpmux): git state reads only small regular files, the physical folder and valid ref names Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * PR dock chips; tooltips only where nothing else names the control (#20375) * test: no tooltip on an element whose text shows Red on base: 105 elements with visible text carry title/data-tooltip. Command: bun test test/tooltip-rules.test.ts Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: PR dock chips; tooltips only where nothing else names the control The pull request dock's bars become content-sized chips (icon, #N, repo, title cut off at 360 px) with the dismiss button inside and no tooltip. Across the pages, a row, chip, link, path or thought whose text shows carries no title tooltip any more; tooltips stay on icon-only controls, shortcuts and text shown nowhere else (why a control is disabled or failed, who reacted, policy detail), each marked tooltip-allow. Tooltips wait the native hover delay (about a second) and show at once when moving straight on to the next one. Green: bun test test/tooltip-rules.test.ts Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: review of tooltip audit Keep the PR dock's state colours, drop four more tooltips the lint now finds inside components (a setting's summary, the branch and folder pickers, a video), let a click or scroll end the quick next-tooltip window, and move two tests to the no-tooltip rule. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: Backdrop Art's line has no tooltip Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at 047c2470d420 - vp fmt webviews/src/pages/history/HistoryPage.tsx Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38502564051 * test(mock): the worked chat opens its pull request, so mock mode shows the PR dock Captures of the agent pane in a real window (--showcase runs the in-page mock) now show the pull request dock. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: the PR dock takes its own space; the transcript ends above it Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at 39f3ca973ed3 - vp fmt webviews/test/ime-composition-keys.test.ts - vp fmt webviews/test/new-tab-omnibar-pointer.test.ts Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38567629461 * chore(next): PR autofix at c7cb26191eb1 - regenerated Packages/macOS/CmuxNext/ci-target-graph.json Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38592980576 * fix: a channel image keeps its name tooltip (the name shows only when it fails) Base added title={part.name} on channel image attachments (AttachmentViews.tsx). A loaded image shows no name, so the tooltip is its only label; mark it with tooltip-allow. tooltip-rules.test.ts: red before, green after. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at f221864ee886 - regenerated Packages/macOS/CmuxNext/ci-target-graph.json Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38633116142 * fix: keep the tool card scope hint and Steer shortcut tooltips Both explain something shown nowhere else, so they stay under tooltip-allow. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at 022cc8e1ae35 - vp fmt webviews/src/pages/home-channels/cloudHome.ts Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38647981824 --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: cmux-autofix[bot] <cmux-autofix[bot]@users.noreply.github.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: cmux-autofix[bot] <cmux-autofix[bot]@users.noreply.github.com> Co-authored-by: Lawrence Chen <54008264+lawrencecchen@users.noreply.github.com> * chore(next): base autofix at 15c5ffe4ec30 - regenerated plans/cmux-next/action-surfaces.json - regenerated plans/cmux-next/actions.md scripts/cmux-next/base-autofix.sh: https://github.com/manaflow-ai/cmux/actions/runs/38688832594 * Composer: show the location strip only before a chat's first send (#20869) * test: composer location strip shows only before a chat's first send Boundary tests for the composer's folder · computer · branch strip: a new chat shows it, the first send hides it, a reopened chat with history never draws it (not even while loading), a failed first send offers it again, and a prompt queued before the first turn hides it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: hide the composer location strip after a chat's first send Not every harness can change folder or machine mid-chat, and cmux does not, so the composer's folder · computer · branch strip now shows only on a new chat before its first send (locationRow.ts). The first send is read from the session: a turn acpmux recorded, a user prompt that did not fail (the in-flight optimistic row included), a running turn, or a queued prompt. A selected session whose summary has not arrived shows none, so a reopened chat never flashes it; a failed first send offers it again. The strip's CSS keys on :has(> .acpmux-composer-strip), so without it the queue and the card close up with no gap. Galleries and browser tests that measured the strip on started chats now measure a new chat, or assert the strip is gone and the queue meets the card. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * refactor: move SidebarSameTurn into CmuxNextSidebar (#20883) #20709 put SidebarSameTurn in CmuxNextApp and left the app 37 lines over its size cap (113729 vs 113692 on 9d70c8abb75a). It only uses SidebarView and ObservationStream, so it belongs with the sidebar; the app keeps the bridge that owns it. CmuxNextApp is now 113687 lines. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * CmuxNext: mark the computer picker's tooltip as allowed (it names the icon-only computer) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * ci: the tour comment says when capture died before writing a receipt (#20899) * test: a UI tour whose capture wrote no receipt says so in the comment (#20763) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * ci: the tour comment says when capture died before writing a receipt (#20763) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * test(cmux-next): a closed sidebar row may park hidden in the list (base red) (#20793) * test: a closed sidebar row may park hidden in the list Lawrence's 5763d7372701 parks a recycled row view hidden in place instead of removing it, so SidebarInsertWhileDisplayAsleepTests' two superview == nil checks failed on base on display hosts. A completed close is now: out of the list or hidden. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: count only a closing row still shown as leaving A row recycled at once now stays parked hidden in the list, so without this the setup would pass for a close that skipped its motion. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * cx-o9yox: every rounded hairline draws one device pixel (follow-up to #20481) (#20713) * test: scanner for raw sub-pixel rims on rounded elements (wip, cx-o9yox) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: rounded rims draw one device pixel, not a raw 0.5px (cx-o9yox) A ratchet over webviews/src: a border, outline or ring shadow thinner than one CSS pixel on a rounded element (or in a shadow token) must use var(--cmux-hairline). Red on base: 29 rims outside the pending list (the popup shadow token, cards, pills, bubbles, popovers, the find bar and the prototype), plus styles.css over its pending count. The pending list holds the composer and New Tab files that another branch owns. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: rounded rims draw one device pixel (cx-o9yox) 29 rounded rims drew a raw 0.5px inset shadow or border. macOS WebKit snaps the hole of a sub-pixel rim to device pixels but not its rounded clip, so on a 1x display or at a fractional pane zoom they lost edges and corner arcs (#20481). Each now uses var(--cmux-hairline, .5px), with its color and alpha unchanged: the popup shadow token (every menu and popover), dictation notice, New Tab box and kind chip, file search, diff scope and tools pills, edited-files and turn-preview cards, question card, secret field, chat gallery tiles, user bubble, render card, find bar, Jump to latest, minimap popover, branch pill, changes banner, harness action, replay controls, update cards, the effort hint and the prototype. The Jump to latest and minimap popover rims, the two with a fixed color, now clear with appearance.borders none as the popups' does. popup-one-hairline.test.ts accepts the token as the popup's one hairline. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: hairline scanner checks each shadow layer; review fixes A shadow with one hairline-token layer and a raw 0.5px ring layer is now flagged. popup-one-hairline matches --cmux-hairline exactly, not --cmux-hairline-ring. The update card comment names the token. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: composer, attachment and New Tab card rims draw one device pixel #20678 landed, so the composer files are free: the composer box base rim, the permission card, the attachment chip, thumbnail outline (and its offset), PDF sheet, viewer and open button, the remove button ring and the New Tab card move onto var(--cmux-hairline), colors unchanged. The hairline pending list is empty. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at fc69dee66225 - vp fmt webviews/src/pages/home-channels/HomeChannelsPage.tsx Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38635963929 --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: cmux-autofix[bot] <cmux-autofix[bot]@users.noreply.github.com> * Code pages draw in the terminal's font; agent pane defines --font-mono (#20880) * cx-tgf4h red: cmux chief -p under ACPMUX_AGENT_LAUNCH=deny fails at once with a typed refusal * cx-tgf4h: the Chief says at once that agents are disabled in this build session With ACPMUX_AGENT_LAUNCH=deny (the nx-remote gui/input default since HQ #2130) or CMUX_AGENTS_DISABLED=1, no Chief turn can start an agent. `cmux chief -p` started a daemon and a brain and waited 240 s for a reply that could not come. - cmux-tui-core agent_launch: one test of the kill switch (acpmux launch_policy.rs), the reason agent_launch_disabled. - `cmux chief` (pipe and chat) refuses before it starts or sends anything: operation.failed, details.reason agent_launch_disabled, exit 1. - The daemon's supervisor starts no Chief brain; chief.engine.* and chief.stop answer the typed refusal at once. - optchat-chief host does not start (logs why, exit 0). - Home: the local Chief conversation's notice says agents are disabled; the engine panel maps the typed refusal (localized, all Home languages). - Every Chief proof script refuses at once under deny and names `nx-remote --allow-agents`. * test: code pages follow the terminal font; font variables resolve Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cx-tgf4h review: forward chief control to a running brain first; daemon-side deny test; engine/stop CLI text; guard before side effects; fmt * acpmux tests: every acpmux process a test starts gets a hermetic environment (cx-s8wux) One helper, tests/support/daemon_env.rs, starts the acpmux binary for every integration test: env_clear, a bare PATH (python3 plus named host tools, then the system directories), a scratch HOME, and ACPMUX_AGENT_LAUNCH=deny unless the test drives a stand-in agent (Agents::StandIn keeps the bare PATH). The 26 test files that started the binary with the host environment use it; tests/hermetic_daemon_guard.rs refuses a test file that names CARGO_BIN_EXE_acpmux anywhere else. Root cause of cx-w014j: a fleet host's PATH holds real codex/claude, which a test daemon discovered and ran (probes, sign-in checks, auto-updates). * cx-tgf4h: fmt and clippy * acpmux tests: the hermetic HOME is <scratch>/home, never a chat's folder * acpmux tests: review fixes for the hermetic environment (cx-s8wux) python3 links the interpreter itself (sys.executable), not a version manager's shim; stale tool links from an earlier run are replaced; the guard also flags daemon_env::bin() outside a listed use; the live codex test probes only codex; codex_bridge_config's discovery test runs with launches denied. * acpmux tests: router_install_secret starts the router through daemon_env (cx-s8wux) * fix: code pages draw in the terminal's font; agent pane defines --font-mono The diff, markdown and code editor pages were written to follow the terminal font (appearance.ts, editorFont), but no cmux NEXT host ever sent it, so code always drew in Menlo. Every page theme now carries the terminal's family (cmux.json terminal.fontFamily, else the Ghostty config's font-family), resent when it changes. The agent pane's mono text read --font-mono, which only Tailwind's theme layer emitted because a source file happened to name it; conversation.css defines it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next: fix two Chief profile relay base reds (concurrency check, Release compile crash) (no bead) (#20876) * cmux-next: mark the Chief profile relay retry loop as bounded (no bead) check-concurrency flags its while true as a loop that can spin. It retries once, only after a lost connection, and every other error throws. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next: nonisolated deinit for PageCallDeadline.Once (no bead) The Release compile crashes swift-frontend 6.3.3 in EarlyPerfInliner on the isolated deinit of this main-actor generic class (exit 65, no error line), the same crash #20408 fixed elsewhere. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * fix(cmux-next): the Chief profile relay's retry is a two-attempt for loop, not while true with a wakeup-allow (cx-ebm.59.5) * cmux-next sidebar perf round 3: Release-build hitch bench with real wheel input; O(1) hover-card hit - scripts/cmux-next/sidebar-rows-perf-release.py: runs in a Release tagged app (no debug.* methods) inside nx-remote --needs input: CLI workspaces (50 with a terminal, 950 empty), HID-tap wheel events, Animation Hitches per gesture, A/B of two apps in one job (side by side, interleaved), traces and the recorder's ktrace files removed after each export, PTY count logged. - SidebarListView+HoverCard: the hover-card hit reads the list's row dictionary instead of SidebarModel.isPlaceholder, an O(workspaces) section walk on every scroll frame (7-12% of main-thread samples while scrolling 1,000 rows in Release). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Channels: a primary or danger button keeps its fill under the pointer (a soft ring shows the hover); gallery play primary-hover Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Channels gallery: primary-hover asserts the hover ring and the unchanged fill; a budget with a reason for the Create frame Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * cmux-motion: Chrome tab strip tween (200 ms easeOutQuad, restart from value), tabStrip geometry tokens, damping <= 0 takes the fallback (hq-1d, no bead) Additive: MotionTween {TabOpen, TabClose, TabMove}, TweenCurve::EaseOutQuad, ease_out_quad, TweenParameters, TweenValue (f64 core: retarget restarts the duration from the current value with no velocity; the same target does not restart), Tween (f32, token-driven), MotionPolicy::tween (0 under speed off, Reduce Motion, or tabOpen/tabClose with ui.animations.newTab off), TabStripGeometry (design-tokens.json motion.tabStrip: max 200, open/close 18, min 56 active / 32 inactive / 64 pinned, reorder 16 x width / 200, closing mode +40 below / +60 trailing / 0.3 s). cmux-app-ffi ABI 2 exports cmux_motion_tween_{base,seconds,retarget,step}, cmux_motion_ease and cmux_motion_tab_strip_geometry. SpringParameters::finite_or now treats a damping fraction <= 0 like NaN (hq-4e nit). The parity corpus example prints tween paths (60 Hz: 12 frames for 200 ms). * fix: read the font from the files the Ghostty config loaded, includes too Review: a font-family in a config-file include won in the terminal but not on pages. Read the runtime's loaded files (with includes, in load order) instead of guessing paths, repaint after the last override is set, and fix a stale doc comment. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * acpmux: record a session's git branch and HEAD at start (hq#1920) (#20840) * test(acpmux): record a session's git branch and head at start A session should keep its folder's branch and HEAD commit as they were at session/new, and a fork its own folder's state at fork time (hq#1920), so agent spend can be joined to the pull request a session produced. These fail today: neither the saved meta nor _acpmux/info carries gitBranch or gitHead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(acpmux): record a session's git branch and head at start session/new and session/fork now store the cwd's checked-out branch and full HEAD commit in the session meta (gitBranch, gitHead), so a session can later be joined to the pull request it produced (hq#1920). The values are read once, as the session starts, from the repository's own files (HEAD, loose refs, packed-refs, a linked worktree's gitdir and commondir), never a git process, and off the async runtime. A detached HEAD records only the head; a folder outside a repository records neither; a lookup that fails never fails the session. A fork reads its own folder at fork time instead of copying the parent's. _acpmux/info carries both fields. Old session.json files load unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(acpmux): git state skips non-files, bad branch names and missing folders; follows symlinks Review of #20840: a FIFO HEAD hung session/new, a symlinked folder was walked lexically, a missing fork folder took its parent repository's state, and an invalid ref name was stored as the branch. The test git also runs without the machine's global or system config. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(acpmux): git state reads only small regular files, the physical folder and valid ref names Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * cx-tgf4h: keep CmuxNextApp line count (App size cap) * acpmux: a pooled agent host no longer spins on Linux reading its own record (cx-7z8yx) The record watch used notify's inotify backend, whose watch mask always includes open, close-write and modify, and ran its callback on every event. The callback reads the host record; on Linux that read queued an open and a close in the watched directory, which ran the callback again. Every pooled host spun at 100% CPU (about 200,000 read calls a second). Linux now has its own inotify watch, like the macOS kqueue watch: a mask of entry changes only (create, delete, moved from/to) and the directory's own delete or move, one thread in poll with no timeout, an eventfd to stop it. A read of the record never queues an event. The notify fallback (other platforms) ignores access events. macOS is unchanged. Behavior test (tests/host_lifetime.rs, Linux): a real daemon pools a host; idle for 3 s it makes fewer than 100 read calls and 30 CPU ticks (before: 599,042 reads, 298 ticks), a rename rewrite of its record keeps it, and the record removed ends it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * cmux-tui smoke: sidebar drag checks the drawn sidebar document order Since sidebar-v2 S6 the TUI draws the daemon's sidebar document, where a new workspace goes to the top (workspaces.newPlacement default), and a workspace drop is one sidebar.move that changes the document only. The smoke still assumed the list-workspaces order: it dragged the drawn top row (the new workspace) below the original, which the product did, and then read list-workspaces, which a sidebar.move never changes. The smoke now reads the order from sidebar.get, checks that the rail draws it, drags the top row below the second (a real reorder), and drags again when needed so the original workspace ends below the new one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * PR dock chips; tooltips only where nothing else names the control (#20375) * test: no tooltip on an element whose text shows Red on base: 105 elements with visible text carry title/data-tooltip. Command: bun test test/tooltip-rules.test.ts Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: PR dock chips; tooltips only where nothing else names the control The pull request dock's bars become content-sized chips (icon, #N, repo, title cut off at 360 px) with the dismiss button inside and no tooltip. Across the pages, a row, chip, link, path or thought whose text shows carries no title tooltip any more; tooltips stay on icon-only controls, shortcuts and text shown nowhere else (why a control is disabled or failed, who reacted, policy detail), each marked tooltip-allow. Tooltips wait the native hover delay (about a second) and show at once when moving straight on to the next one. Green: bun test test/tooltip-rules.test.ts Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: review of tooltip audit Keep the PR dock's state colours, drop four more tooltips the lint now finds inside components (a setting's summary, the branch and folder pickers, a video), let a click or scroll end the quick next-tooltip window, and move two tests to the no-tooltip rule. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: Backdrop Art's line has no tooltip Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at 047c2470d420 - vp fmt webviews/src/pages/history/HistoryPage.tsx Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38502564051 * test(mock): the worked chat opens its pull request, so mock mode shows the PR dock Captures of the agent pane in a real window (--showcase runs the in-page mock) now show the pull request dock. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: the PR dock takes its own space; the transcript ends above it Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at 39f3ca973ed3 - vp fmt webviews/test/ime-composition-keys.test.ts - vp fmt webviews/test/new-tab-omnibar-pointer.test.ts Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38567629461 * chore(next): PR autofix at c7cb26191eb1 - regenerated Packages/macOS/CmuxNext/ci-target-graph.json Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38592980576 * fix: a channel image keeps its name tooltip (the name shows only when it fails) Base added title={part.name} on channel image attachments (AttachmentViews.tsx). A loaded image shows no name, so the tooltip is its only label; mark it with tooltip-allow. tooltip-rules.test.ts: red before, green after. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at f221864ee886 - regenerated Packages/macOS/CmuxNext/ci-target-graph.json Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38633116142 * fix: keep the tool card scope hint and Steer shortcut tooltips Both explain something shown nowhere else, so they stay under tooltip-allow. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at 022cc8e1ae35 - vp fmt webviews/src/pages/home-channels/cloudHome.ts Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38647981824 --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: cmux-autofix[bot] <cmux-autofix[bot]@users.noreply.github.com> * ci: nightly-next recovery initializes the notices submodule before continuing accepted submissions The recovery job's checkout had no ghostty-next submodule, so the bundle notice check that notarize-nightly-dmg.sh runs after Apple accepts failed, and run 38669958906 skipped five accepted builds as 'Apple did not accept'. Initialize the submodule like the signing job does, and make the skip notice say that a post-acceptance check can also be the cause. * ci: the cmux NIGHTLY-identity job also initializes the notices submodule Run 38669958906's publish-nightly-identity-legacy job saw Apple accept, then failed the bundle notice check for lack of ghostty-next and retired the accepted submission of run 38609024986. * agent pane: progress and stop for a running Claude subagent or workflow (cx-liswe) (#20718) * test: a running subagent or workflow shows what it does and what it has spent Red on base: both rows read only "Running" (bun test test/subagent-progress.test.tsx). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * webviews: a running subagent or workflow shows what it does and what it has spent The subagent fold keeps acpmux's subagent_progress fields (action, tokens, tool uses, a workflow's agents done of started), and the transcript's subagent row adds them to its status line through one shared helper (subagentProgress.ts) the summary list and the Background tasks pane can use. Three plural strings, translated for every pane locale. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: a running subagent row has a stop button Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: stop a running Claude subagent or workflow from its row Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: restore the catalog's base order after the merge Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: stopping a subagent leaves its row closed, and a refused stop says so Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: a subagent's stop button waits for Claude and says when the stop failed The button is off while Claude has the request and until the subagent ends; a refused or unanswered stop (10 s) turns it into "Couldn't stop <name>" and it can be tried again. The pane no longer drops the error. Also moves the stop wiring above showSubagent's doc comment and corrects two comments. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * style: format the subagent progress test Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: stop rejects without English the pane would never show Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: restore the catalog's base order after the merge Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at 2fe6cc48ea66 - vp fmt webviews/src/pages/home-channels/HomeChannelsPage.tsx Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38637059713 * test: the agent pane relays a subagent stop for its chat (cx-liswe) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: the agent pane may stop a subagent of its chat (cx-liswe) Adds _acpmux/subagent_stop to the pane's method allowlist: session-scoped, params sessionId and subagentSessionId, no gesture (it stops work, like _acpmux/kill). Without it the host refused every stop click. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: mirror the subagent stop into the shared pane polic…
Summary
Regression test for the nightly-next recovery gap that Lawrence fixed in e3defdc.
Between runs 38625732642 and 38659284357, Apple accepted, stapled and launch-tested each recovered build. Then
verify-app-bundle-licenses.shfailed becauseghostty-next/build.zig.zonwas missing:recover-nightly-next-notarizationnever raninit-submodule.sh ghostty-next. Each build was skipped as "Apple did not accept".This PR originally carried the same one-step fix. Base landed it first, so after the base merge only the test remains.
tests/test_nightly_notices_submodule.pychecks that every nightly.yml job running the license check (directly, via notarize-nightly-dmg.sh, or via resume-nightly-notarization.sh) initializes ghostty-next first. It is wired into ci-guards in the release-notary group.publish-nightly-identity-legacy, which has the same gap and was reported to them.Testing
python3 tests/test_nightly_notices_submodule.py:Changelog
none
🤖 Generated with Claude Code