Repository navigation
ci: warm Vite before browser tests, per-file limits, 40 min cap (cx-v6fbz) - #20733
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…imits (cx-v6fbz) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…(cx-v6fbz) Vite prints its port before it has transformed a module, so a test's first goto paid for the whole module graph inside its 30 s navigation timeout. On a busy CI runner that failed chat-find and text-field-focus (#20697), and the gallery-frame and agent-pane browser warm-ups hit the same wait (#20681). warmDevServer requests the page and every module it imports first. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…er the pointer (cx-v6fbz) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # webviews/test/agent-pane-session-pages.test.ts
…o (cx-v6fbz) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The browser-lane check now fails a test file that starts a dev server (vite.listen() or a vp dev spawn) without warmViteServer/warmDevServer. On base it flags 80 of 240 test files; on this head none. 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 |
…6fbz) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s (cx-v6fbz) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…l; the diff row check climbs out of shadow roots (cx-v6fbz) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Review follow-ups pushed:
Reds not from this PR (this PR edits ci-web.yml, so the whole web workflow runs; most PRs skip these jobs):
|
This comment has been minimized.
This comment has been minimized.
|
all web/size checks green |
|
Passes: CI passes on CI passes on Written by |
|
|
…v6fbz) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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. |
… 22 loads took about 115 s (cx-v6fbz) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The ci-web.yml edit widens this PR's web scope to the web/ unit shards, which are red on base. The cap raise lands separately. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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. |
Review follow-up: the spawned-server files and menu-focus warm the whole gallery graph before their browser warm-up, which can pass the default 120 s file limit on a loaded runner. A failed warm-up visit no longer leaves the other in-flight visits as unhandled rejections. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
The feat-cmux-next push run https://github.com/manaflow-ai/cmux/actions/runs/38677180348 at 70edcd5 failed: cmux-next Release compile (Xcode 26). |
The browser-lane check (#20733) requires a test that starts a dev server to warm it; warmViteServer replaces the play this test used as its warm-up. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
check:browser-lanes (#20733) requires warmViteServer once the server listens. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* 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>
* test: a pending command asks in one quiet row Red on base: the pane draws a waiting command three times (the transcript's "Ran" row, the card's bold title and its summary), under "1 request from this turn", "ACP requests only · Isolation unverified" and an "Expand details" button with a tooltip; its answers read "Allow once", "Allow for this chat" and "Deny". Locally (jsdom, with a pass-through askRows): "Expected: 1, Received: 3". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: a pending command asks in one quiet row The tool permission card becomes the transcript's tool row: its glyph, a verb and the command once (regular weight, one line, cut with an ellipsis), on a thin rim with no shadow. While it waits, small Allow, Always and Deny answers sit at the row's right end. A click on the row opens the full command, its folder and the scope in plain words. - The transcript leaves out a call while an ask waits on it, so the command is never drawn twice; answered, the call is back in place. - No "1 request from this turn", no "ACP requests only · Isolation unverified", no Expand details button and no tooltips. - An edit's proposed change still shows under its row (cx-d73v2). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at 1718b8e - regenerated schemas/defaults/cmux-next.json Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38545059793 * fix: hide only the calls the panel's rows name, after the turns The transcript drops a pending call only while the grouped permission panel shows it (not the legacy card, not behind folder trust), and filters after turnViewFrom so a live turn's status still reads it. A deny-only group says so inline. Logical CSS for RTL. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: the ask row shows whole in the pane's bottom stack, in WebKit too The DEV app (WebKit) drew the pending command's row as a 15px strip under the composer: its flex fieldset collapsed inside the asks stack. The harness now mounts the panel in that stack, and the look test runs in WebKit as well as Chromium and checks the row is not cut. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: the ask row keeps its height in the bottom stack; Always says what it grants The row's fieldset was a flex box that shrank to 16px in the pane's bottom stack (red at d12d889: cardHeight 16.19 in Chromium and WebKit). It is a block now and never shrinks; its rows are the flex lines. From cg-design-judge's blind bouts: the scope sentence for Always shows under the row while it can be chosen (hidden lost 0-16), and Always gets a hairline rim beside the filled Allow so it does not read as disabled in light. The coverage words stay in the expanded details. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: regenerate agent pane strings on the merged base; keep the base's catalog order Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at 6796380 - 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/38567683198 * chore(next): PR autofix at aa1f1ee - cargo fmt in Native/OptChat/optchat-chief Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38570608054 * test: whole permission ask shows when the stack height is definite The app's WebKit resolved the panel's 45% cap against the bottom stack, which is the panel's own height, and cut a lone ask through its answers. Playwright's engines leave that height indefinite, so the test pins it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: the ask card is its row plus the Always note 9dcfe06 added the note that says what Always grants under the row; the look test still capped the whole card at one row's 40px. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: the permission panel's cap is the pane's, not its own height max-height:45% resolved against the bottom stack, whose height is the panel's own once WebKit treats it as definite: a lone ask showed under half of itself (row cut through its answers, the Always note hidden). 45vh is 45% of the pane's web view, as meant. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at 2484ccd - vp fmt webviews/src/pages/home-channels/cloudHome.ts Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38647152752 * fix: the permission ask keeps the permission card's surface hooks composer-edges.test.ts (#20454) reads .acpmux-permission-surface for the card's hairline and its appearance.borders = none clearing; the ask card now carries that class, draws the shared --cmux-hairline and clears its rim when borders are off. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at 9686b27 - vp fmt webviews/src/agent-session/acpmux/permissions/Panel.tsx Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38675379032 * fix: keep base's agent pane strings after the base merge Rebuilt the catalog as base's text plus this PR's key changes and regenerated strings.json; the clean merge had dropped base keys. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: warm the dev server in the permission ask row test check:browser-lanes (#20733) requires warmViteServer once the server listens. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: keep base's agent pane strings after the base merge Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: the permission ask's secondary rim uses the device hairline Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: keep base's agent pane strings after the base merge 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>
…every frame, jumps land, 250 ms card) (#22228) * test: prompt bookmarks persist in the acpmux session (red) Behavior tests for _acpmux/bookmark_get and _acpmux/bookmark_set before they exist: restart, prompt-only seqs, fork, transfer, peer forwarding, the pane relay's scope and params, and the minimap popover's store. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * acpmux: prompt bookmarks persist in the session _acpmux/bookmark_get and _acpmux/bookmark_set keep the thread minimap's marks in SessionMeta.bookmarks: seqs of the chat's user_message records, checked against its log and capped at 1000. A change logs a mux bookmarks record, as tags do, so attached panes hear it; the chat keeps its place in the session list. A fork carries the marks of the prompts it copies under its own seqs; a move carries them (the log keeps its seqs) and the source keeps none. Peers' chats forward to their owner. The pane relay allows both methods for a chat in the pane's scope with only sessionId, seq and bookmarked. The minimap's store reads them from acpmux, toggles optimistically with rollback, and imports this pane's old localStorage marks for the chat once. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: thread minimap matches the Codex rail; bookmarks show and jump (red) Behavior tests for the rail's thresholds, hover magnification, card timing, keyboard focus, scrub, the bookmark dot and row button, and the bookmark steps, plus a WebKit motion test and the Swift action/page-event test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next: thread minimap matches the Codex rail; bookmarks show and jump The rail now follows the Codex desktop app's measured behavior: it shows from 4 prompts with 48 px left of the column, 16 px in and centered, with 10 px x 36 px rows and 6 px ticks that scroll past 64 rows or 70% of the window. Hover magnifies the rows (26/20/14/10 px) in 160 ms on Codex's spring, the preview card opens after 250 ms (at once within 300 ms of a close, or on keyboard focus) and closes 100 ms after leaving. A click scrolls on cubic-bezier(0.35, 0.05, 0, 1) (~400 ms for ~650 px), landing the bubble 35 px below the top, and highlights it for 1400 ms; an unmounted target jumps. Dragging scrubs. Every row is a tab stop. Bookmarks show as a 2 px dot past the tick (a click on its spot toggles it), in the card, and in a new button on the prompt's own row. Previous and Next Bookmarked Prompt are palette actions with no default key; the turn steps keep Ctrl-Opt-Up/Down, now on Codex's 200 ms scroll curve. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next: regenerate action exports for the bookmarked-prompt steps Generated by scripts/measure/export-action-surfaces.sh on the fleet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: concurrent bookmark sets log the kept marks; legacy marks wait for acpmux (red) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * acpmux: log bookmark changes in order; keep legacy marks until acpmux holds them set_bookmark changes, logs and saves the marks under the chat's move lock, so concurrent sets log in the order they change the marks and a move begins before or after a change. The prompt check scans the log on a blocking thread. The pane forgets an old localStorage mark only once bookmark_set succeeds for it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: a clicked minimap row takes focus so Tab goes on from the rail WebKit does not focus a clicked button, so in the app Tab after a click left the rail for the transcript. Codex's rail (Chromium) focuses it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: focus a clicked minimap row so Tab goes on from the rail Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: read the minimap hover transition by seeking it, not by frame samples CI's headless WebKit paced frames unevenly, so a sample 40 ms into the transition could come long after it ended. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: regenerate action exports on the merged head Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at 568dba62ae7a - vp fmt webviews/test/ime-composition-keys.test.ts - cargo fmt in Native/OptChat/optchat-chief Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38566033765 * chore: regenerate action exports after merging #20556's head Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: the minimap's card follows the app hover intent (red) Base's hover-intent and elevation tests now drive the rewritten rail (.acpmux-minimap__card, the rows' pointerenter/pointerleave), and the rail test pins the app hover intent (450 ms delay, warm 500 ms, gone as the pointer leaves unless it enters the card) instead of CardTiming's 250/300/100 ms. heavy --mem 3G bun test test/hover-intent-cards.test.tsx test/subtle-elevation.test.ts test/thread-minimap-rail.test.tsx (fail) the card follows the app's hover intent: it waits the hover delay, follows the pointer at once while warm, and goes as the pointer leaves thread-minimap-rail.test.tsx:210 expect(card()).toBeNull() after 400 ms: the card opened at 250 ms (fail) the minimap's turn preview waits the hover delay, then follows the pointer at once until the rail cools hover-intent-cards.test.tsx:117 expect(visible()).toBe(false) right after leaving: CardTiming keeps it 100 ms (fail) one subtle elevation scale > .lg-sheet casts --elevation-2 (base red, ledger.css untouched) The .acpmux-minimap__card casts --elevation-2 case passes (the merge already moved the card to it). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: the minimap's card follows the app hover intent The preview card now runs on ui/hoverIntent's useHoverIntent, as base's minimap did: the first waits the hover delay, the card then follows the pointer from row to row at once while the rail is warm, and it goes as the pointer leaves the rail (moving into the card, or back, keeps it). Keyboard focus still shows it at once; Escape dismisses it and focus-out closes it on that frame. cardTiming.ts and the CARD_* constants are gone. thread-bookmarks.test.tsx goes back to the PR's version: the merge took base's half, which drives the old rail's pointermove on two prompts. heavy --mem 3G bun test test/hover-intent-cards.test.tsx test/subtle-elevation.test.ts test/thread-minimap-rail.test.tsx 46 pass, 1 fail (.lg-sheet casts --elevation-2: base red, ledger.css untouched) heavy --mem 3G bun test test/thread-minimap-current.test.tsx test/thread-bookmarks.test.tsx test/thread-turn-keys.test.tsx test/hover-intent-parity.test.ts test/hover-row-sweep.test.ts test/thread-minimap-motion.test.ts 7 pass, 0 fail (browser lanes skipped locally) heavy --mem 4G bun run check: pass Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: regenerate action exports on the merged head export-action-surfaces.sh on 6cf54078 (fleet step a2d9f3a7): 961 actions (base's chat-identifier actions plus this PR's transcript actions). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: regenerate action exports on the merged head export-action-surfaces.sh on eec94827 (fleet step fa811efc): 963 actions (base's Music actions added). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * debug: a short seed of one-line turns for the thread minimap's density captures debug.agent_pane seed_rows fixture "short": one-line prompts answered "ok N", the same content as the Codex reference chat, so tick and highlight density compare like for like. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next: regenerate action exports after merging feat-cmux-next Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: warm Vite before the minimap motion and Claude reasoning browser tests check-browser-test-lanes (#20733) requires warmViteServer after listen; claude-reasoning-default (#20592) landed without it and fails the base check. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at 0f6b92945b0c - regenerated plans/cmux-next/action-surfaces.json - regenerated plans/cmux-next/actions.md Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38683433717 * fix: a prompt's bookmark shows with the hover actions experiment at one The hover-actions experiment hides a prompt's action row unless it has Copy, versions or Edit; a prompt that can carry a mark keeps the row for its bookmark. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at a97cff790a52 - regenerated plans/cmux-next/action-surfaces.json - regenerated plans/cmux-next/actions.md Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38694299706 * fix: a drag's click on the minimap stays swallowed until the next press The flag cleared on a 0 ms timer, which a slow frame could run between the pointerup and its click, so the drag's click jumped (CI web shard 2). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next: regenerate action exports after merging feat-cmux-next Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: the thread minimap's feel in a long chat, in Chromium (red) Jump landing for undrawn rows, the hover card's 250 ms, the band following the scroll on its own frame, and older turns loading without moving the band. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: the thread minimap lands, previews, tracks and holds like the Codex rail - A jump corrects its landing from the bubble while the rows it crossed measure. - The card opens 250 ms after the pointer reaches the rail (Codex's delayOpen). - The band of lit rows follows the scroll on the scroll's own frame, and counts the turns on screen as Codex's observer does (no turn below the view). - Older turns loading above the reader leave the band where it was on screen. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: settle skips a scroller with no layout; the rail's card tests at 250 ms; gallery rest, scrub and long-chat states Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * style: format Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: a jump settles only on a bubble with a box to measure Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: review findings on the minimap feel - Older turns: the band reads the offset as the transcript will restore it, the keep-in-view scroll skips that commit, the hovered, focused, card and scrub rows follow their prompts, and a second page continues a running glide. - The band's first turn is Codex's: a prompt within 35 + 16 px of the top ends the turn above it, so a prompt just jumped to is the first lit. - A jump's landing correction ends on any input in the page; a pending turn step is tracked by its turn, not its offset. - The scroll listener runs in capture; the gallery's synthetic scrub cannot throw. - Tests: a scrolling rail taking 30 older turns, waits on frames instead of timers, a looser card window and one stray frame allowed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: the band reads the restored offset until the transcript's restoring scroll arrives Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at b030bd39f09d - regenerated plans/cmux-next/actions.md - regenerated cmux-tui/crates/cmux-app-host/generated/scopes.json Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/39347840624 * fix: the band reads the transcript's placement; jumps end with their chat; the card closes on focus out and Escape; the rail fits a short pane - VirtualTranscript calls the rail once its placement pass has set the offset, so the band reads the restored place directly instead of guessing from a frame with no scroll event. - A running jump stops when the chat changes or the rail unmounts. - The card closes when focus leaves rail and card, and on Escape inside it. - The rail's height is capped by the transcript's own height. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: a press released off the minimap ends there; a chat switch stops a jump in its own commit Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: the minimap card's Escape goes through ui/escapeDismiss, not a raw key handler (ui rules) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at a73c00f9cf02 - plans/cmux-next/action-surfaces.json - plans/cmux-next/actions.md Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/39360464009 * chore(next): PR autofix at 3c3d0e0b6bcf - Packages/macOS/CmuxNext/ci-target-graph.json Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/39364182964 * chore(next): PR autofix at 9d214de119ff - plans/cmux-next/action-surfaces.json - plans/cmux-next/actions.md Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/39380161552 * chore(next): PR autofix at 6e9a03929633 - plans/cmux-next/action-surfaces.json - plans/cmux-next/actions.md - schemas/defaults/cmux-next.json - web/data/cmux-shortcuts.generated.json Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/39386397629 * agents: fence native updates to the captured machine (#21389) * agents: expose machine platform capabilities * agents: document machine capability metadata * agents: model machine platform capabilities * agents: format machine platform metadata * agents: show machine platform metadata * cloud: preserve machine capability contract * test: cover cloud machine capabilities * cloud: expose capability operation checks * test: cover capability operation helpers * cloud: gate actions on provider capabilities * cloud: clarify capability refusal * cloud: keep capability gates within app size budget * agents: show machine capability summaries * agents: show machine capability summaries * test: cover agent capability summaries * cloud-server: type capability checks * cloud-server: centralize access gates * cloud-server: centralize access gates * cloud-server: carry machine capability metadata * docs: specify machine capability metadata * agents: exercise machine capability metadata * testdata: add machine capability fixtures * testdata: add machine capability fixtures * testdata: add machine capability fixtures * testdata: add machine capability fixtures * testdata: add machine capability fixtures * testdata: add machine capability fixtures * testdata: add machine capability fixtures * testdata: add machine capability fixtures * agents: sanitize machine metadata at ingress * agents: sanitize machine metadata at ingress * test: cover agent metadata sanitization * protocol: carry machine platform capabilities * protocol: carry machine platform capabilities * fix: restore provider runtime after upload truncation * style: format machine capability protocol * style: format provider runtime capability fields * style: fix provider snapshot indentation * protocol: retain provider metadata in machine catalog * protocol: map provider metadata into machine catalog * tests: update machine descriptors for provider metadata * tests: update machine descriptors for provider metadata * tests: update machine descriptors for provider metadata * tests: update machine descriptors for provider metadata * tests: update machine descriptors for provider metadata * tests: update machine descriptors for provider metadata * tests: update machine descriptors for provider metadata * tests: update machine descriptors for provider metadata * apps: reserve agent CLI provider family * test: enforce agent CLI provider ownership * agents: add verified read-only agent_cli owner * agents: cover read-only agent_cli owner projection * agents: register the read-only agent_cli owner * agents: defer App provider adapter until feature ownership extraction * agents: defer App provider adapter until feature ownership extraction * agents: keep App provider wiring within its module size boundary * agents: reproduce malformed machine capability crashes * agents: validate capability wire types before rendering * agents: specify cached harness inventory privacy and no-execution behavior * agents: expose cached harness inventory without health side effects Select only non-secret health fields and reject controls or machine selectors. Advertise the view in initialize so older daemons cannot silently execute a normal health request when a client expects a cache-only read. Cmux-Daemon-Tests: run * agents: retain prerelease and build metadata in cached inventory Cmux-Daemon-Tests: run * agents: negotiate cached inventory before sending health requests Keep initialize and the inventory request on one transport. Unsupported owners receive no health operation, and typed inventory decoding rejects legacy or noncached responses. Preserve pipelining for existing calls and enforce the documented frame limit before parsing complete replies. * machines: import platform type in provider runtime The hosted same-tree daemon build caught the missing import used by the machine catalog projection. Cmux-Daemon-Tests: run * test: specify trusted machine inventory routing Exercise same-owner feature negotiation, cache-only responses, missing owners and refusal of machine selectors, controls and untrusted clients before adding the daemon command. Cmux-Daemon-Tests: run * machines: read cached agent inventory through the native owner Add the agent-inventory-v1 daemon verb on trusted Unix connections. Negotiate harnessInventory on the exact owner socket before the cache-only health request, reject controls and machine selectors, bound per-daemon concurrency and serialize only non-secret DTO fields. Keep the conversations-only relay denied. Cmux-Daemon-Tests: run * test: unwrap successful provider snapshots before checking defaults The hosted workspace test build caught direct accesses to a nonexistent ResponseEnvelope.result field in the legacy-metadata regression. Match its ProviderResponse::Success payload instead. Also use the already-imported AtomicUsize in the inventory worker bound. Cmux-Daemon-Tests: run * agents: share the inventory wire model with native machine requests Move the cached observation DTO to the lower daemon protocol module, add the capability-gated AgentInventoryRequest and reuse that DTO in the direct acpmux reader. AgentPane now depends on Daemon, whose dependencies remain Compat and Wakeups; no cycle or app-target growth. Cmux-Daemon-Tests: run * chore(next): PR autofix at 48a59aac18e3 - regenerated Packages/macOS/CmuxNext/ci-target-graph.json Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/39024598894 * test: repair machine metadata fixture construction The hosted workspace test build caught duplicate platform/capabilities assignments in MachineDescriptor fixtures and assignments intended for MachineDescriptor on ManagedMachineDescriptor. Remove the duplicate and wrongly typed pairs while preserving each descriptor's actual capabilities. Cmux-Daemon-Tests: run * test: reproduce false absence claims from partial agent inventory Cover partial caches, launcher uncertainty, presence-only auth evidence, watch removals and all three rendered layouts using FakeHost. Before the fix the focused suite executes 16 tests: 15 fail and the complete-inventory control passes. Command: bun test first-party-apps/agents/test/inventory.test.ts * agents: preserve unknown evidence in cached machine inventories Only an explicit complete:true inventory can establish missing CLIs. Preserve nullable installation and presence-only auth evidence, keep partial removals unknown, and show uncertain rows/cells without install or update actions in every layout. Empty account observations no longer imply signed out. Add translated uncertainty copy and regenerate synthetic preview fixtures and the app bundle. Focused regression: 15 failures and 1 control pass at 9863b7dc; all 16 pass after the fix. Full Agents suite: 27 passed, 297 assertions. Current Swift inventory suites also passed all 10 tests at 48a59aac. The repository-wide localization audit still reports errors in unchanged macOS catalogs; the Agents English/Japanese source-key and placeholder checks pass. * test: preserve inventory assertions during owner fixture cleanup Do not set a read timeout on the immediately closed cleanup wake socket (macOS returns EINVAL), and preserve the original assertion if the worker fails during panic cleanup. Real owner calls are already bounded and close their link; the fixture reads their EOF. Cmux-Daemon-Tests: run * apps: move injected capability handlers into their feature owner Move the request, error, handler protocol and family router from the executable App target to CmuxNextApps, preserving dispatch and refusal behavior. The App keeps its concrete handlers and channel wiring. Add a focused Apps test target, regenerate the target graph and import the feature at the remaining PageFactory use. The extraction removes 61 App-target lines and gives the agent inventory owner an injectable feature-level handler seam. Local Swift syntax, namespace, concurrency, graph freshness, App size and diff checks pass; hosted compilation and the new behavioral suite are pending. * docs: scope duplicate handler ownership to the in-process router Clarify the existing local dictionary replacement behavior without implying that a live provider registration may be taken over. * test: reproduce missing canonical machine identity in identify * machines: expose canonical owner identity in trusted daemon handshakes * sdk: preserve optional machine owner IDs in raw identify results * test: reproduce inventory refusal without a selected-owner fence * agents: fence native inventory reads to the selected machine owner * test: require inventory family evidence from cached executable and package * agents: project CLI family from the cached executable and package evidence * test: require an admitted read grant for agent CLI inventory * agents: serve scoped CLI inventory through admitted machine owner routes * test: use synthetic host labels in machine inventory fixtures * apps: give provider registration its own connection adapter Preserve captured-transport capability admission and legacy-family fallback without growing the already oversized DaemonConnection type. Update the wire-level registration test and the request documentation. * test(agents): reproduce wrong-platform install hints Exercise structured Linux metadata and unknown remote owners through the packed app. Keep legacy OS and recognized-platform controls. * fix(agents): choose install hints from the selected owner platform Prefer structured machine metadata, retain legacy OS compatibility, and keep unknown or unsupported systems unknown instead of offering Mac install commands. Record the current inventory owner/provider integration in the shared coordination lane. Regression: platform.test.ts goes from 3 behavioral failures and 2 controls to 5 passes. Full Agents suite: 32 passed, 340 assertions. * test(machines): define verified remote-catalog publication behavior Exercise the existing machine.list/get API, exact owner fencing, bounded metadata, ordered replacement, exclusive publication and connection expiry. Keep the local-only default as a control. * test(machines): use the resource module's error type Repair the fixture import before evaluating the behavioral catalog regression. * machines: project verified remote routes through the native catalog Accept bounded, sequenced publications on the verified local app's existing connection, fenced to this daemon's public ID. Keep the publication in that connection record so disconnect removes it atomically. Expose metadata through machine.list/get while retaining the native local identity and session owner. Reject competing publishers, local impersonation, stale replacement, unknown fields, commands, paths and nonlocal/agent-bound carriers. The app publisher is not wired yet. No new route, remote execution authority, owner reconnect, disk schema or credential delegation is introduced. * test(machines): cover SDK catalog decoding and retain outer disconnect denial Correct the expired native client's expected outer remote_denied refusal. Add a behavioral SDK regression for native platform/capability metadata and remote origins, preserving legacy records and strict malformed-field checks. * sdk: carry machine origins and owner capability metadata across resource clients Extend the authoritative MachineSnapshot contract and all seven ergonomic SDKs to preserve optional platform/capability metadata and Cloud, SSH and server origins. Keep legacy omission defaults and strict typed metadata. Extract the Rust and Zig machine models instead of growing oversized files; Zig retains a bounded capability table without allocation. Regenerate the app declaration and canonical SDK descriptors. Update the boundary guard to validate the exact remote metadata shape and add rejection coverage for command fields, arbitrary origins and an open platform schema. Document the native publication bridge; its app publisher remains unwired. Behavioral Python SDK regression: four assertion failures at 1552187f, then all three tests pass. Existing Python resource suite: 69 passed. Focused TS: three passed. Resource boundary guard suite: 34 passed. Native catalog tests: eight passed at 1552187f (f5d2957368a6c4fbd973f19d). Compiled SDK lanes pending. * test(java): preserve the SDK test runner executable bit * test(machines): require native owner metadata in the handshake The app must publish the owner's observed platform and machine capabilities, not infer them from a UI route, provider label or its own local system. * machines: publish admitted owner metadata from the app registry Observe existing native registry routes on the captured local connection. Fence snapshots to the owner and handshake epoch, preserve live lease sequences across temporary source loss, withdraw removed routes and discard stale acknowledgements. Bound catalog records and frames, and negotiate publication without a legacy fallback. Expose native platform and machine capabilities in trusted identify using the same snapshot helpers; regenerate all seven raw SDKs. Add deterministic publisher lifecycle and wire-contract coverage. * machines: verify the publication transport and avoid catalog panics Exercise actual connection negotiation, legacy refusal before write and owner mismatch propagation. Repair test-fixture compilation and remove three fallible expect sites from catalog projection and selection. Document event-driven publication and native owner metadata. * test(machines): expose policy readmission observation regression Extract the current registry projection unchanged from app composition and exercise it against a paired-server fixture. A blocked route must keep observing the policy that can readmit it. No host or connection is started by the fixture. * machines: keep blocked catalog routes observing readmission Read observable registry admission and carrier state before excluding blocked routes. This preserves the subscriptions needed when policy or a reconnect readmits the existing route, without opening a connection. Cover both policy and carrier invalidation. * test(machines): cover curated CLI and MCP catalog discovery Exercise read-only machine discovery, explicit metadata lookup and continued exclusion of session effects and arbitrary machine routing. Extract existing catalog tests instead of growing the large MCP test file. * test(machines): preserve CLI paths after catalog test extraction * machines: expose read-only catalog discovery to CLI and MCP Offer curated machine list/show and generate machine_list/machine_get from the existing operation catalog. Keep session effects and other-tool machine routing excluded. Share operation-aware route defaults between CLI and MCP so the catalog socket's session is not serialized as metadata, and resolve machine prefixes on the same connection with no ancestor fields. Extract the machine grammar instead of growing command.rs. Document the metadata-only contract and translate root discovery help in both native CLI locales. Add actual transport and route regression coverage. * machines: clarify catalog tool authority and repair fixture lints * test(machines): use an explicit name selector for reserved words * test: reproduce Swift catalog ancestor selector mismatch * fix: encode Swift catalog selectors for their operation * test: exercise catalog trust with real native owner connections * machines: exercise app discovery and scoped inventory through real server owners * test: use the catalog's read risk in the app journey fixture * test: retain owned app diagnostics for native journey failures * test: preserve new app runs across replacement host exit * fix: fence queued app runs from the outgoing host generation * style: terminate app dispatch match arm consistently * docs: distinguish machine catalog metadata from session authority * test: require negotiated metadata for strict provider v1 clients * machines: negotiate optional provider metadata per control generation * machines: reproduce strict native reader catalog incompatibility * machines: require reader opt-in for extended native catalogs * chore(next): PR autofix at 1938babb0ef6 - regenerated cmux-tui/crates/cmux-app-host/generated/cmux-app.d.ts Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/39046739528 * tests: preserve native field validation in MCP catalog plans * sdk: expose machine reader options and reproduce missing wire opt-in * tests: format the SDK catalog wire regression for hosted Zig * sdk: serialize explicit machine catalog reads without changing defaults * tests: cover the extracted machine facade and typed invalid inputs * tests: reproduce strict identify reader compatibility and opt-in boundaries * tests: exercise identify through its native command handler * machines: negotiate owner identity metadata without changing legacy identify * tests: preserve identify callers and validate explicit metadata options * cloud: localize unavailable operation refusals * tests: capture bounded catalog withdrawal receipts on journey failures * tests: await the acknowledged withdrawn catalog instead of a fixed sequence * test(agents): reproduce stale and cross-owner inventory refreshes * test(agents): require explicit catalog discovery and local fallback controls * fix(agents): discover admitted owners and fence inventory refreshes * test(agents): reproduce missing cache-only inventory change feed * feat(agents): publish bounded cache-only inventory changes * test(agents): require owner-fenced native inventory watch leases * feat(agents): fence native cache watches to owner connection leases * test: reproduce inventory watch replacement cleanup race Correct the native watch fixture's writer construction and qualification warnings so the barrier-controlled socket replacement case can execute before changing cleanup behavior. * fix: fence inventory watches across socket replacement Detach old leases while changing the configured socket and close only that detached set outside the lock. Capture a monotonic internal socket epoch in every watch so a reused path cannot admit stale work. Preserve the native wire contract and the pre-fix barrier regression. * fix: document native inventory streams and guard handshake replies Declare the targeted watch events as control streams and document their payload/lifecycle. Keep moved agent-session emitters in their existing internal wire family. Replace the computed metadata reply subscript with a bounded lookup that fails malformed responses closed. Spec inventory and all32 checker tests pass after the previously observed missing-stream failure. Swift syntax, scoped conventions/size and crash ratchet pass; no crash baseline changed. Native watch Rust inputs are unchanged from the 25-case fleet pass at01418d27; final job cleanup remains pending. * test: preserve inventory lease events through tree resyncs Exercise native event decoding, DaemonStore side-event delivery behind a snapshot barrier, and EventInbox overflow. Inventory changed/ended events belong to the separate subscription; keep an unrelated unknown-event control. Regression only, before event-retention repair; fleet execution pending. * fix: retain native inventory lease events behind tree snapshots Classify the two targeted inventory lease notices as independent of workspace snapshots. Keep unrelated unknown events behind the existing tree barrier. EventInbox already retains unknown events; the new overflow cases preserve that control behavior. Regression be913d2e precedes this fix. Syntax, scoped conventions and size checks pass; exact fleet red/green execution remains pending the matching native artifact. No app-facing watch advertisement or new authority. * test: preserve exact native inventory watch revisions Exercise actual DaemonEvent wire decoding across UInt64 boundary values and malformed owner/lease/revision inputs. Require bounded lease-only side-event payloads and retain an unrelated numeric-event control. Regression only; no runtime RED claim before fleet execution. * feat: type native inventory watch requests and exact revisions Add separately capability-gated owner-fenced enable/disable requests and a directly decoded UInt64 receipt. Normalize targeted side events through validated owner/lease fields, preserving revisions as decimal text before generic JSON can round them and discarding diagnostics or malformed notices. Keep unrelated events unchanged. Revision regression8ddb7918 precedes this change. Add request framing and bounded real-connection bridge coverage for legacy refusal and exact UInt64 replies. Syntax, scoped conventions/size and crash ratchet pass; packet0 localization entries. Fleet runtime red/green remains pending matching artifact publication. App-facing subscriptions are not yet wired or advertised. * test: fence delayed inventory disable to its original lease Enable a new lease on the same native control connection after socket replacement, then deliver cleanup naming the retired lease. Assert idempotent no-op for stale cleanup, continued invalidations on the new lease, and successful conditional retirement of its exact ID. Regression only, before owner-side conditional disable. * fix: condition inventory cleanup on its captured lease Advertise agent-inventory-watch-fence-v1 and accept a canonical expected_watch_id only on disable. Atomically compare/remove only that client's matching lease; a stale ID or absent lease is an idempotent no-op, never a selector for another client. Keep the original explicit connection-wide disable. Managed Swift enable/disable requests require fencing support before starting and include the exact receipt ID on cleanup, with no unfenced fallback. Add cross-client, malformed-input and capability coverage. Regressionedd780 executes the missing conditional-disable assertion in the selected run and alone (jobdb37d30741c3eecdeda6d36e, failed100, no leaks). Spec inventory/32checker tests, scoped syntax/conventions/size and diff checks pass; runtime GREEN pending. * test: use the daemon JSON object case in the watch fixture Correct the connection fixture's assumed AppJSON accessor to pattern-match CmuxNextDaemon.JSONValue.object. Current lease-fenced wire assertions remain intact. The earlier904577 candidate stopped at this fixture compile error; it provided no runtime GREEN. Production sources and native inputs are unchanged. * test: consume admitted agent inventory invalidations Exercise the real Agents store in FakeHost: agent_cli.changed must re-discover/re-read admitted owners, ignore claimed event payload rows/selectors, and coalesce bursts while retaining a follow-up. The same focused Bun command executes13controls passed and3expected failures before the fix. Keep this regression before the implementation; advance the public branch with both after local GREEN. * fix: re-read admitted agent inventory on cache invalidations Subscribe to agent_cli.changed and ignore event payload rows, selectors, commands and job results. Re-discover/re-read current owners without live checks; coalesce an active batch and preserve a follow-up. Remove the unsupported watch payload listener and its proposed stream operation. Preserve stale-read, withdrawal and local-fallback fences across all three views. Regression154e9306 precedes this fix. The same focused Bun command first executes13pass/3expected failures, then passes all16original cases plus2refusal/removal cases. Full Agents suite50tests/416assertions, canonical bundle/check and manifest pass; existing execute-scope warning remains. Localization packet0entries/attention; global static baseline failures unchanged. Publish both commits together after local GREEN. App-facing native/provider invalidation production remains open; Agents is unbundled. * machines: bind inventory watch lifecycle to the ready control session Capture one manager per admitted native control transport, retain pending receipts for cancellation cleanup, and serialize conditional retirement before readmission. Failed cleanup cannot silently admit another lease. Add bounded bridge coverage for cancellation, owner refusal and reconnect. Extract handshake admission to keep DaemonConnection within its size ratchet. Runtime validation follows on the immutable hosted source; no end-to-end provider watch or Cloud journey is claimed. * test: reject cached inventory watch admission after control reconnect An old manager must not return its cached receipt after the original transport closes, even when the same canonical owner reconnects. Keep the new transport's live lease as the cleanup isolation control. * fix: refuse retired inventory watch transports before returning receipts Check the captured transport before cached admission and after pending admission. Recheck retirement when another caller starts a cleanup while an earlier cleanup await resumes. The preceding reconnect regression executes one expected cached-receipt failure with four passing controls on fleet job7c5042eb1d069c387c351d77. No reconnect or alternate-owner cleanup fallback is introduced. * machines: exercise watch manager admission refusal before native contact The new manager refuses an owner with only the older watch capability and an owner without canonical identity. Real bridge inspection confirms no watch operation is sent in either case. Production watch lifecycle at parent7c58329a passes all seven selected Swift suites, fleet job1d9ad29f7b992e9612c26052, including the preceding closed-transport regression. * test: revalidate app stream authority before each queued delivery Use the scripted host and an explicit queue barrier to hold the current process alive across grant, enabled, host-state and manifest changes. A saved subscription must not keep receiving events after those changes. The readable running host remains the positive delivery control. * apps: fence inventory invalidations to current readable demand Recheck install, manifest, grant and host state under the supervisor lock before queuing stream events. Keep fixed inventory invalidation out of the generic daemon event feed. Add opt-in inventory demand snapshots, targeted monotonic demand events, and a strict verified non-agent Unix provider ingress taking only the current demand sequence. Revoke, unsubscribe, host exit and provider replacement fence stale callbacks without supplying rows or selectors. The preceding real-host queue-barrier regression executes five expected authority failures with a passing running-host control, selected and alone, job b8b8381c06c4dd0c40a75d3a; no leaks. Current runtime validation follows. * fix: validate inventory invalidations at the apps request entry Move the strict frame check from cancel-request to try_handle, where the command discriminator and optional response shape are available. The prior candidate stopped during native compilation; no runtime result is attributed to it. Inventory and cancel-request behavioral gates will run on this corrected immutable source. * test: preserve the page relay role while proving its inventory refusal The generic verify helper sets role main. Set only the verified-app test fact in this fixture so the request actually originates from page_relay. Production inventory permission and demand behavior is unchanged. * apps: satisfy demand test lint and document inventory provider opt-in Add the two required test closure semicolons without suppressing warnings. Document the additive demand snapshot and fixed provider carrier in the owning module; legacy registration remains unchanged. Prior f85cfc62 runtime executes42 passing inventory cases with one invalid page-relay fixture failure, corrected in parent8859e57c. The queued8859 verification was cancelled before placement after these lint issues were known; the final exact source is the verification target. * machines: preserve source identity through side-event delivery Tag native event envelopes with the connection instance and retain their original control serial through the store, snapshots and inbox collapse. A new envelope subscription rejects unsequenced or unstamped delivery; existing event-only subscriptions remain compatible. Delegate typed wire execution and ready transport sequence projection to their resource owners without growing the connection type. Exact Swift files pass eight suites/28methods on immutable validation source2a74fd62 using its official matching published native tree eb966; job a4c6a87c47577e66e78cd436 is done/0/reset. This is component proof only. Current carrier Rust at parenta11bfff6 passes43inventory and140shared app cases. Current native/provider composition awaits its matching artifact and the production demand-to-watch bridge. * test: retain exact provider inventory demand sequences * apps: connect permissioned inventory demand to admitted machine watches * apps: validate inventory subscriptions through the native app journey * apps: fence provider callbacks and verify reconnect and lease retirement * test: reject stale registry admission after actor reconnect * apps: require the registry observed control transport for inventory admission * daemon: expose observable side event control admission * test: name disconnected control reason in stamp lifecycle fixture * test: recover explicit no-lease inventory admission refusals * machines: prove absent inventory leases before explicit admission retry * sdk: model native owner inventory events across generated wire layers * test(agents): reproduce duplicate and stale selected-owner job admission * fix(agents): bind job actions to one admitted pending request * test(core): pin agent update admission to the captured machine * feat(core): fence agent update calls to their captured machine --------- Co-authored-by: cmux-autofix[bot] <cmux-autofix[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * Use paired server identities for links (#21644) * test(server): expose missing pairing commands * test(server): reject missing idempotency values before mutation * Implement human-approved server enrollment in Rust * test(server): keep pairing links in the selected API environment * Keep pairing verification links on the selected API and fix isolated fixtures * Keep server enrollment coordination in its lane ledger * test(link): bind paired servers to their enrolled WireGuard identity * Use the enrolled server identity for an explicitly selected link * Dereference the protected key when checking a running link identity * Share link help and exercise enrolled traffic through real cmux processes * Report the exact encrypted-journey deadline and owned process logs * test(link): exit a refused encrypted dial while stdin remains open * Finish link dial after peer EOF with stdin still open --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * docs(web): point Huge Blue inspection comment at the vms README (#21952) docs/design/huge-blue-app-server-inspection.md only existed in the unmerged #21335; the design lives in web/services/vms/README.md. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * test(agent cursor): red: the name tag is a gray Liquid Glass capsule (pill gallery P1) User (Oct 20): 'more designs for tinted pill ... gray and liquid glassy, think about how Apple would design this'. Replaces the light-glass tag expectations: neutral gray translucent tint, continuous corners, light specular rim and top highlight, subtle shadow, dark text, gray dot. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next agent cursor: the name tag is a gray Liquid Glass capsule (pill gallery P1) Neutral gray translucent tint (#D6D6D8 at 78%), continuous-corner capsule 22 pt tall, light specular rim, top highlight gradient, soft 1.5 pt shadow, dark label text and a gray dot; the typing caption uses the same material. No agent color anywhere in the tag. The overlay panel sits above Chromium's child windows, so it cannot blur the page; the tint stands in for the blur. No new animation: the tag still shows and hides through the existing Motion fades, so Reduce Motion and animation speed apply unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(cmux-next tabs): a tab switch at rest walks no row of tabs (red: every switch runs the occlusion and full separator passes) TabSwitchWorkBudgetTests counts the strip's passes over every cell (TabStripRowPasses: occlusion, separators, frames) across 2N switches at 2, 10 and 30 tabs and expects none: the switch's cost must not grow with the tab count. Deterministic, where a timing gate on shared CI hosts is not (the same bench measured 0.4 ms on one fleet host and 29 ms on another). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next tabs: a tab switch updates the two tabs it changes, not the row (tab-switch-rewrite) syncSelection walked every cell twice per switch: the full separator pass and the occlusion pass (TabOcclusion samples each cell's motion path). At rest no tab overlaps another and no mask is on, so occlusion runs only while a strip move is in flight (movesInFlight, cleared by the move's completion), and the separator rule is applied to the lines next to the old and new selected tab through a slot index built once per layout (TabSlotIndex), which reveal also reads. A multi-selection change keeps the full pass. TabStripSwitchSeparatorTests proves the lines equal a full pass after any switch order. Benches (fleet, aws-m4pro-5, same host A/B against a9439ce7ac3): TabSwitchPathBench apply p50 60 tabs 0.42 -> 0.31 ms, 30 tabs 0.21 -> 0.15 ms; strip separators 38 us -> 2.5 us at 60 tabs, constant. TabSwitchPathBench now prints the per-stage split (BenchSpans switch.*), and TabStripSelectionBench each strip step. scripts/cmux-next/tab-switch-matrix.py also reports each Chromium and WebKit page's own first frame after a switch (content_frame_ms). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Server: Add Server card: the Name/Team grid takes the card's width The fleet render at 39b0b0b23b5 still drew the Name field at its ideal width: the Grid sized to its cells, so maxWidth on a cell had nothing to fill. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Server: Add Server card: Name and Team as captioned full-width rows The Grid kept the Name field at its ideal width (the maxWidth frame sat outside the drawn card) and wrapped the Chief checkbox. Captions over the controls need no label column, so long labels in any language fit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: actions.md lists the transcript actions where the generator puts them (AgentTranscriptActionCatalog order) * test(next): pinned groups read as pinned; a group header's right-click is one flat menu (red) Lawrence 2026-10-20: Move to Top left a workspace under groups that were pinned (the Pinned band lists above the machine sections), but nothing showed they were pinned and Pin/Unpin could only pin. And the header's right-click opened the editor, whose More Group Actions row held the menu. Red: SidebarDocPinnedGroupTests (a Pinned-band group maps pinned), WorkspaceGroupFlatMenuTests (common rows top-level, no catch-all folder, every row in the palette), GroupPaletteDefaultTests (right-click shows the menu, editor rows without More). Design: plans/cmux-next/sidebar-ordering-DESIGN.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(next): pinned groups read as pinned and unpin; a group header's right-click is one flat menu Root cause (plans/cmux-next/sidebar-ordering-DESIGN.md): the groups Move to Top left a workspace under were pinned. Pin Group moves a group into the Pinned band, above every machine section, but SidebarDocSections mapped every document group with pinned: false, so no pin glyph showed and Pin/Unpin always pinned. A Pinned-band group now maps pinned (the header's pin, Unpin Group in the menu and editor), and Pin/Unpin toggles from what the sidebar shows. The header's right-click opens the group's menu at once (no editor, no More Group Actions row): Color, Set/Remove Icon, Pin/Unpin, Collapse All/Expand All/Collapse Others, Move to Top, Ungroup, Close Group, Delete Group and Close Other Groups are top-level; Move and Sort keep their lists. The editor offers Pin and Move to Top itself. New Workspace in Group, Pin/Unpin Group, Mark Read/Unread, Clear Notifications and Edit Group Config join the palette. Pin and Collapse rows read as the change they make. Strings in all 21 locales (19 need review). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(next): the flat group menu keeps 12 top-level rows ActionSurfaceParityTests.everyMenuKeepsAShortTopLevel (Lawrence 2026-10-01: at most 12 top-level rows) failed at 21. The rows Lawrence named stay top-level (New Workspace in Group, Rename, Color, Pin/Unpin, Collapse/Expand, Move to Top, Ungroup, Close Group) with Delete Group and Close Other Groups; Options ▸ takes icon, read state, collapse-all, config and Duplicate, and Move ▸ takes the group sorts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(next): Copy Group ID joins Options, so the group menu keeps 12 top-level rows Its one-row Copy folder showed inline as a 13th row. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): regenerate action exports for the flat group menu Regenerated on the fleet (key a219-exports-820ba663b9c, scripts/measure/export-action-surfaces.sh). check-group-menus.py passes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(next): TitleCoalescerTests takes mutating results before #expect (the pattern that broke CEFPumpScheduleTests) 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: lawrencecchen <54008264+lawrencecchen@users.noreply.github.com>
Summary
web / react-apps-checkflaked on PRs (e.g. #20697 at 3764122, and the gallery-frame tests #20681 hit). Three causes, all from load on the 8 vCPU runner, none in the code under test:*.gallery.tsxload on first paint (src/gallery/entryStore.ts), about 2,300 modules, so the gallery-frame and agent-pane browser warm-ups hit the same wait.--with-depsengine install took 2.5 min on one attempt and 11.5 on the next, which left the tests 17 min, so the rerun was cancelled at 30.Fixes, no assertion changed or loosened:
test/support/warmDevServer.ts:warmDevServer(base, page)/warmViteServer(vite, page)request the page and every module it imports, as the browser will, so the server caches each transform before a test's own timeouts start. 80 test files call it once their server listens (70 in-process servers, 10 spawnedvp dev).scripts/check-browser-test-lanes.ts(run bybun run check) now fails a test that starts a dev server without warming it. On base it flags 80 of 240 test files; on this head none.scripts/ci/run-webviews-tests.sh: a file may declare a longer limit with a// cmux-web-test-timeout: SECONDSheader line; editor-page declares 240.nullfor a header the click never opened).Measured on the private Linux builder (idle 96 cores), cold then warm:
/Verification
python3 -m unittest tests.test_webviews_tests_per_file(7 tests). The new per-file limit test was committed first and failed (TIMEOUT test/slow-declared.test.tsat the 2 s default), then passed.bun run checkpasses on this head with the rule (format, lint, types on 1,379 files, plus layers, type scale, focus rings). Both ran on the Linux builder.warmDevServer: checked against real Vite (table above) and a local fixture with an import cycle, a relative entry and a lazy import.Not verified locally: the browser test files themselves. Big-red may not run browser suites; this PR's react-apps-check run is their first run with the change.
Follow-up
The gallery frame loads every entry to find one; loading only the requested entry would cut a cold gallery load from about 2,300 modules. That is a gallery change, not part of this fix.
Changelog
none
Bead: cx-v6fbz
🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need.Summary by cubic
Fixes flaky browser and webviews CI tests that timed out or failed because the cold Vite dev server compiled the whole module graph during a test's first page load. Tests now warm the server before launching browsers, can declare a longer per-file limit, and the diff-virtualization test no longer clicks a tree row that has moved.
warmDevServer/warmViteServerto request a page and its imports before the first navigation; called in 81 test files (settings-scroll warms only after its readiness poll).check-browser-test-lanesnow fails any test that starts a dev server without warming it.// cmux-web-test-timeout: SECONDSheader for a longer per-file limit; editor-page, text-field-focus, chat-find, diff-virtualization, files-panel-coverage, ime-composition-keys, menu-focus, settings-scroll, and ui-a11y declare longer limits.Written for commit 893282f. Summary will update on new commits.