Repository navigation
fix(nightly-next): wait up to 40m for notarization in the job - #18736
Conversation
Three nightly-next builds in a row outlasted the 20m in-job wait. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Runs 37871970302 and 37872060374 (and 6d443005's) outlasted the 20m wait, so nothing published in-job. Wait 40m on every track, as main already does; the step's 50m and job's 80m timeouts already cover it. 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 |
|
The feat-cmux-next push run https://github.com/manaflow-ai/cmux/actions/runs/37876991913 at 3cc0805 failed: cmux-next generated files. |
|
The feat-cmux-next push run https://github.com/manaflow-ai/cmux/actions/runs/37877263866 at 9ca25d8 failed: cmux-next generated files. |
|
The feat-cmux-next push run https://github.com/manaflow-ai/cmux/actions/runs/37878426726 at 818b7f9 failed: cmux-next generated files. |
|
The feat-cmux-next push run https://github.com/manaflow-ai/cmux/actions/runs/37879215803 at 2dca7c1 failed: cmux-next checks (god files, concurrency, crash safety, l10n), cmux-next generated files. |
|
The feat-cmux-next push run https://github.com/manaflow-ai/cmux/actions/runs/37880226198 at 82f52c7 failed: cmux-next checks (god files, concurrency, crash safety, l10n), cmux-next generated files. |
…der… (#18715) * fix(backend): retire again every retired team VM paused before the fence (cx-009a) Review finding: a row that reached paused before retireVm existed never had its run budget spent. Retired rows now carry fenced, set by team_vm.retired_paused; the alarm retires every row that is pausing or paused without it (PATCH budget, then pause or already paused). The events use new idempotency keys (retired-fenced, retired-fence-failed) because a pre-fence row already spent retired-paused:<vm>, and a replayed key would not reduce again. The backfill test now models the pre-fence row exactly (old reducer state, no provider budget, no spent new key). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * crash (assume_isolated): the off-main post in VideoMainDeliveryTests goes through a GCD queue (Swift 6: no Thread.isMainThread in async code) * cmux-next sidebar: red test, a pin dropped on Home goes after the built-in rows (cx-odqn) * cmux-next sidebar: a pin dropped in the top rows goes after the built-in rows (cx-odqn) * test(acpmux): a fork holds its turns' ends (red, cx-f4sk) Dogfood of Fork from Here on dog77fk-v1: the forked chat showed its last reply streaming with a caret and the Stop button, because hub fork copied user_message and agent chunks but not turn_started/turn_result. * test(optchat, acpmux): turns and compactor load no user settings, MCP servers or skills (red) The reference runs its Claude Code turns with no user setting source and no slash commands. Failing tests: - acpmux accepts the preset args --setting-sources project and --disable-slash-commands; it refuses user/local sources, an empty list (it would drop the project denies) and = forms. - An isolated Claude turn preset and every Claude compactor slot preset pass --setting-sources project --disable-slash-commands; a subagent preset passes none (subagents keep the user's environment). - '[claude-code:unrecognized_model]' (Claude Code 2.1.287 on claude-haiku-5-5) counts as an unavailable model. host::subagent_preset is the subagent preset closure moved out, unchanged. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test(cmux-next): status icon sets and OSC 7501 blocked kind (red) Behavior tests for cx-kxa2: the default icon set keeps today's plans, eight or more candidate sets draw every state and mark permission, question and auth apart, the OSC 7501 kind reaches the row, tab and plan, the Debug menu writes the tunable, and a contact sheet of every set x state x size x theme. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: the folder picker's separator is an hr Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(cmux-next): status icon candidate sets with a live Debug switcher cx-kxa2. StatusIconSet (Debug Settings status.iconSet, Debug menu > Status Icons) restyles working, blocked, done and error marks in every indicator live through the shared StatusIndicatorConfig: sidebar rows, group headers, tab icon slots, tab badges and the OSC 7501 notification badge. Ten sets; the default current set keeps today's plans exactly. Marks are vector alpha masks (StatusMarkArt) tinted with theme roles; SF Symbol sets draw as templates. The OSC 7501 blocked kind (permission, question, auth) rides StatusIndicatorState.waiting(kind:) from ProgramStatusRecord through StatusMapping to the plan and the tab item. StatusIconSet.image draws a still mark from the same geometry; the notification badge uses it with the reason's kind. The candidate contact sheet (StatusIconSetSheetTests) renders every set x state x size x theme with CARenderer; both review sheets now host their sidebar strip in an offscreen window so the rows draw. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(optchat, acpmux): turns and compactor run with no user settings, MCP servers or skills As the reference's Claude Code path, Chief turns and compactor nodes now load none of the user's settings, MCP servers, plugins, skills or slash commands, and still sign in with the user's login (credentials are not a setting source). Subagents keep the user's environment. - acpmux: the preset args allowlist takes --setting-sources project and --disable-slash-commands (both take capabilities away). An empty source list stays refused: it would drop the project's denied tools. - optchat-chief: an isolated Claude turn preset passes both (the session directory's settings and .mcp.json still load: the Chief's MCP server, denied tools, hooks off); every Claude compactor slot preset adds them to its args. Checked on Claude Code 2.1.287 with a scratch HOME: a user-scope MCP server and a user skill leave the session's init, the project server and denied tools stay. - An older acpmux that refuses the new words gets the preset with the args it knows (--tools "" and the rest), logged, not with no args. - '[claude-code:unrecognized_model]' counts as an unavailable compactor model (Claude Code 2.1.287 does not list claude-haiku-5-5), so the compactor falls back to the turn model. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat(cmux-next): workspace groups look and work like Chrome tab groups (cx-rcby) Lawrence 2026-10-08: "new group is very ugly, the creation animation is very bad too. make groups like this", then "pixel match" the Chrome tab group sidebar "with our smaller height". - Header: one full-width rounded bar filled with the group's color (the active theme's ANSI palette, lightened; light gray for none), the name in dark regular type, a more (⋮) button on hover and the collapse chevron at the right edge. Radius, padding, type, glyphs, the member indent and the member bar scale with the sidebar row height (the density setting). No member counts. Members carry a thin bar in the group's color. - One editor bubble (name field focused and selected, color dots for none and the palette, New Workspace in Group, Move Group to New Window, Close Group, Ungroup, Delete Group, More Group Actions) opens from the name, the more button, a right-click, Return on a focused header, Rename, and every group a person makes. Rows run through the action registry. - Creation moves once: the new group is a pending edit until the store holds it (cx-odqn rows), the header view carries on under the daemon's id, the bar fades and scales in once (Reduce Motion: fade only). Name and color edits made while the daemon creates the group wait for its id. - A click on the open group's name or more button toggles the editor closed; a click in the list closes it; it follows only a group that just appeared and closes when its group goes or scrolls away. - Strings in en and ja (and the other catalog languages, needs review). * fix(acpmux): a fork copies its turns' starts and ends (cx-f4sk) hub fork copied prompts, replies and tools but not turn_started/turn_result, so a pane attached to the fork saw its last reply still streaming and the chat working (caret + Stop) until a new turn ended. Both kinds are now copied, so the fork's turns end and its latest turn can be forked again. * fix(cmux-next): restore baseline checks and app FFI pin (#18563) * fix(cmux-next): restore baseline routing checks * style(webviews): format Chief inspector fixture * ci(cmux-next): repin app FFI to published source The f1a32f1499bc0d6fcaf8175732f2123d4e14f225 build passed the app FFI release checks. Pin its immutable release and checksum so the target push verifies the current sources. * fix(gallery): wait for page readiness instead of network idle (cherry picked from commit 88096251c91499b5b2ef72e08b2dcc686947e169) * fix(gallery): recover from renderer target crashes (cherry picked from commit cf9444f021a720a4aa29626c15091252fcd9d75e) * cmux-agent-pane-policy: answers on _acpmux/permission_respond, only for a pending question and bounded Fixes the base-red AgentPanePolicyParityTests on feat-cmux-next (fleet step c670e2482c527e22bc5ee65a on 51731962c82c): Test thePolicyFileListsAreThisHostsLists() recorded an issue at AgentPanePolicyParityTests.swift:79:13: Expectation failed: (Set(known[method]?["params"] ?? []) → ["permissionId", "optionId", "sessionId"]) == (entry.params → ["optionId", "sessionId", "answers", "permissionId"]) ↳ _acpmux/permission_respond params Cause: d2d1fe161dfa ("fix(cmux-next): the agent pane bridge passes question answers", ask-gallery lane) added "answers" to the Swift known params of _acpmux/permission_respond; policy.json did not have it. The coordinator's security decision (2026-10-07): mirror "answers", plus two crate limits the Swift host does not have yet (its half goes to the ask-gallery lane): - answers only when the pending permission is a question (request.toolCall._meta.acpmux.question an object, the acpmux hub's mark, plans/cmux-next/agent-questions.md section 3); a tool permission, or one the host never saw, is refused (transport.intent_invalid). PermissionOptions records it from the frames it already observes (is_question); a permission seen once without the mark is not a question. - answers an object of 1 to 64 item ids, each id and each value at most 4096 UTF-8 bytes, each value a string or a list of strings (a list counted together). policy.json question_answers holds the numbers. The frame limit, the gesture rule (an allow still needs a fresh gesture) and the refusal of other extra keys (updatedInput) do not change. Cases: check.json 13 new (41 now; the Swift and Rust count asserts follow), the refused ones with swift_gap / swift_expect, so the Swift suite stays green and fails, naming the gap, once Swift adds the rule; params.json (answers known, updatedInput still breaks); gestures.json (an answer with an allow needs a gesture); parity.rs question_permissions. Red check: with the rule off, full_check_order fails. * fix(cmux-next): keep new column before new row * test(cmux-next): close parity fixture gaps * style(gallery): format chief inspector fixture * style(gallery): match vp formatter output * fix(cmux-next): enforce aggregate answer bounds * test(cmux-next): match redacted compatibility detail * fix(cmux-next): admit macOS helper inputs and annotate reap * test(cmux-next): align answer parity bounds * docs(policy): refresh answer parity description * test(ci): track current cmux-tui trigger inputs * test(cmux-next): seed parity question items * ci(cmux-next): route resource binaries through workflow * test(cmux-next): model combined question permission state --------- Co-authored-by: lawrencecchen <54008264+lawrencecchen@users.noreply.github.com> * test: Choose folder… survives WebKit's press blurring the folder field Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: Choose folder… keeps the folder field's focus on press Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * crash: fonts on render threads are held per size and nil-checked; ratchet render_font (red, cx-qpqs class) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * crash: fonts on render threads are held per size and nil-checked; ratchet class render_font (cx-qpqs class) cx-qpqs: NSFont factories annotated nonnull return nil when threads make and drop the last instance at once. The audit found the same make-per-draw pattern on the render threads beyond the code font: - RowDrawing (RowBitmaps, 3 concurrent renders): 17 fonts made per draw (captions, receipts, link cards, names, reaction glyph, tapbacks) now come from HomeFonts.system / monospacedDigit. - MarkdownLayout (measure, tail, tile queues): heading and table header fonts from HomeFonts.system; code fonts from HomeFonts.monospaced. - Layout.attributed and MarkdownLayout.attributed: bold/italic faces from HomeFonts.font(_:adding:), held per base, size and traits; no font attribute when the face does not exist (before: NSFont(descriptor:size:) returned nil, stored as NSNull). - SidebarDrawing (concurrentPerform): monogram fonts held per half point; the six CTFontCreateUIFontForLanguage(...)! force unwraps fall back to Helvetica. HomeFonts holds every font under one lock for the process and reads the factory's result as an optional (the annotation is not trusted), falling back through NSFont(descriptor:size:). Patches regenerated; sync --check ok. Ratchet: new class render_font (fonts made in place outside a static let in MessagesLabHome, MessagesLabSidebar, CmuxHomeRender): 31, mostly main-thread UI and the caches; it goes to BAN once the UI sites use HomeFonts. force_unwrap 210 -> 203. crash-elimination.md: rule for class b. Not changed: CmuxHomeRender (hq-6d's lane; TextDraw already falls back). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * next: compact model picker, starred models on top, one harness on the chip (#18719) * test: model picker stars on top, one-line rows, one harness on the chip Leo's dogfood (2026-10-08, A1): the favourites star filtered every harness to "No matching models", rows were two lines, and the chip drew the Codex mark beside "Claude Code". Red: 4 fail, 6 pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: compact model picker with starred models on top and one harness on the chip - The favourites-only star toggle is gone: starred models sit in a Starred section above the others, and nothing hides a harness's models. - Rows are one line (no harness subtitle) and the menu is 400px wide, the harness column 136px and top-aligned. - The chip draws one harness: the one a switch to another harness is starting, else the running one; browsing a harness in the open menu no longer renames the chip. - New string picker.starred in all 21 locales (non-English needs_review). - Gallery: composer model-menu-starred and model-switching. The red test expected data-agent "codex" for the Codex mark; the mark reports its brand, "openai", so the fix commit corrects that line. Green: modelPicker 10/10, composerPickers 33/33. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * crash ratchet: an enum case or member named unowned is not an unowned reference (H1 false positives) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * crash: ban MainActor.assumeIsolated without a main-proof (123 -> 0; H2, hq-6d for CmuxHomeRender) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test(optchat): sessions without the user setting source keep the user's settings env (red) Review finding on 4aa642cd045d: --setting-sources project also drops the env block of ~/.claude/settings.json, where a Mac may keep its Claude API route (ANTHROPIC_BASE_URL and the rest for the subrouter). Adds session_dir::user_settings_env and the SessionSetup/CompactorSpec user_env fields (read, not yet applied) and failing tests: the turn's project settings and a compactor slot's settings carry that env, with the session's own env winning. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(optchat): sessions without the user setting source keep the user's settings env A turn or compactor slot that loads no user setting source lost the env block of ~/.claude/settings.json, where a Mac may keep its Claude API route. The host reads that block at start; the session directory's and each compactor slot's project settings carry it, under their own env (PATH and the cmux variables of the session, FORCE_PROMPT_CACHING_5M of a 5-minute slot). Only env comes over: no hooks, permissions, MCP servers or plugins. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * style(optchat): rustfmt Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(cmux-next): group editor landing-review fixes (pending edits while the daemon creates a group, action rows target the daemon id, no focus steal on close, narrow-width clamp) (cx-rcby) * test(optchat, acpmux): a turn offers an allowlist of built-in tools (red) Turns deny a list of Claude Code built-ins, so a built-in a later Claude Code adds is offered until someone denies it. Failing tests: acpmux accepts --tools with a comma list of built-in names (and still refuses rules, MCP tool names, spaces, empty names and wildcards); an isolated Claude turn preset passes --tools Bash,Read,Edit,Write,WebFetch,WebSearch,ToolSearch. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * plans(cmux-next): team-vm lane note for the retired VM fence (cx-009a) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Home text layout: property tests, random Markdown, runs that do not fit, stale lines (red, crash program phase 3) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Home text layout: a run or line that does not fit its text is skipped, never raised (crash program phase 3) TextLayout.attributed checked only NSMaxRange(range) <= length: a negative start passed and addAttribute raised NSRangeException, and Int.max made NSMaxRange overflow (a Swift trap). link(at:) read lines measured for another text past its end. One overflow-free check, TextLayout.range(_:_:in:), now guards both. Found by TextLayoutFuzzTests. Patches regenerated. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * optchat-chief: red test, the last turn's cache mark is lost across a host restart * fix(optchat, acpmux): a turn offers only an allowlist of built-in tools - acpmux: a preset may pass --tools with a comma list of built-in names (letters and digits; no rules, MCP tool names or wildcards), which only narrows what the session offers. - optchat-chief: an isolated Claude turn preset passes --tools Bash,Read,Edit,Write,WebFetch,WebSearch,ToolSearch (host::TURN_TOOLS). Checked on Claude Code 2.1.287: the session's init lists exactly those and the Chief's MCP tools, so a built-in a later Claude Code adds is not offered. - TURN_DENIED_TOOLS stays as the second guard: on an acpmux older than these preset args the preset is installed without them (now also without the --tools list; --tools "" of the compactor stays). Kept --setting-sources project, not an empty list plus an explicit --mcp-config: project keeps the session directory's .mcp.json and settings, while a preset --mcp-config would let a preset add MCP servers (commands), which acpmux's allowlist does not allow. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test(CmuxNextCloud): the Mac app registers a mac install at sign-in and revokes it at sign-out (red, cx-wb5.64) CmuxNextCloud depends on the shared CmuxInstallAuthCore package. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(cmux-next): the Mac app's Cloud install principal: registered at sign-in, revoked at sign-out (cx-wb5.64) MacInstallIdentity (CmuxNextCloud) wraps the shared InstallAuthClient with the .mac profile: a signed build keeps its install key in the Secure Enclave (blob in the Keychain); a development build keeps a software key and the records in 0600 files (no Keychain prompt per rebuild). CloudService registers (or reuses) the install and mints one token when the user signs in, and revokes it (install.revoke, key rotated, record forgotten) at sign-out while the Stack session still exists. InstallHTTPTransport refuses redirects. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(CmuxNextCloud): Mac install review findings: API Worker origin, sign-out during register, per-user keys, store choice (red, cx-wb5.64) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(cmux-next): Mac install review findings (cx-wb5.64) - Install calls go to the API Worker (CloudConfiguration.ownerAPIBaseURL, now shared with FeedService), never the web origin; the debug override stays debug-only. - One key per Stack user; a sign-out always rotates the key and forgets the record, and a registration still in flight never writes its record (generation per bind); a session that ends elsewhere unbinds. - Only a debug build without a Team ID uses files; anything else (also a failed Team ID read) uses the Secure Enclave. - Key rotation reports Keychain and file errors; owner-only files are written through an exclusive, no-follow temporary file, synced, then renamed; cookies are off on the install transport. - Registration runs after the machine refresh, not before it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(CmuxNextCloud): sign-out revokes a stored install with nothing bound, and blocks registration until the session ends (red, cx-wb5.64) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * optchat-chief: the last turn's cache mark is saved with the turn's messages The marked view prefix (size and hash) goes into the host state in the same transaction as the turn's messages and pending turn, so the first turn after a restart still keeps its mark within the API's lookback of the last one. The turn's engine, preset and mark are now decided before the messages are logged; the engine note still follows them. * fix(cmux-next): Mac install re-review findings (cx-wb5.64) Sign-out takes the Stack user and session and revokes the stored install even when this launch never bound it, then refuses registration until the session ends; unbind resets the client so a mint in flight yields nothing; no registration while Cloud is turned off, the managed team is missing or the backend is local-only, and one after the organization lifts the block. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(cmux-next): the API Worker URL literal is a reviewed crash-allow; crash baseline lowered (cx-wb5.64) * fix(cmux-next): make trust refusals one clear flow (#18731) * test(cmux-next): keep trust refusals out of switch failures Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(cmux-next): route trust refusals through the trust prompt Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * CMUXMobileCore: protocol fuzz tests, input frames, sync frames, render grid, attach tickets (crash program phase 3) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test(optchat, acpmux): --tools default is refused; an older acpmux drops only the tools list (red) Review findings on 92a3cfe729e3: the built-in list check accepts 'default', which Claude Code reads as every built-in (a preset could widen a profile's narrower --tools). And an acpmux that knows the setting source but not a --tools list loses all three isolation words. Failing tests: 'default' is refused in any case; without_tools_list (seam, no behavior yet) drops only the list. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Toast host: move toasts after an avoidance change on a main-actor task, not MainActor.assumeIsolated (crash ratchet) * fix(nightly-next): wait up to 40m for notarization in the job (#18736) * test(nightly-next): require the 40m notarization wait Three nightly-next builds in a row outlasted the 20m in-job wait. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(nightly-next): wait up to 40m for notarization in the job Runs 37871970302 and 37872060374 (and 6d443005's) outlasted the 20m wait, so nothing published in-job. Wait 40m on every track, as main already does; the step's 50m and job's 80m timeouts already cover it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * test(cmux-tasks): a log write failure and a repeated positional flag must not end the process (red) serve() must return the log write error instead of process::exit(70) in the writer thread, and the CLI parser must refuse a repeated flag after its positional value instead of panicking on expect("array"). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(cmux-tui): zero production panics in cmux-unix-socket, cmux-tasks, cmux-pane-protocol, cmux-remote-protocol Each crate root now denies clippy unwrap_used, expect_used, panic, unreachable, todo, unimplemented and exit outside cfg(test), so the count stays at zero. - cmux-tasks: the writer thread returned process::exit(70) on a failed log write. serve() now returns ServeError::LogWrite, the accept loop runs on its own thread and serve() waits for the first of the two to stop, so the process still exits at once with code 70 (from the CLI's ExitCode) and the supervisor restarts it from disk. The CLI parser refused nothing when a repeated param took the positional word and then its flag: it panicked on expect("array"); it now returns "--<flag> given twice". - cmux-pane-protocol: SigningKey::from_seed returns anyhow::Result (ring rejects only a seed of the wrong length); the vector generator and emit-ir propagate it. The non-unix example provider returns ExitCode 2 instead of process::exit(2). Risk::default_for keeps its panic under crash-allow: pane_op! evaluates it only for the associated const Op::RISK, so it is a compile error, never a runtime panic. - cmux-remote-protocol: frame decode reads the header through first_chunk (no try_into().unwrap()); SessionId::from_hex parses with str::get instead of from_utf8().expect(). - cmux-unix-socket: short_test_dir keeps its expect under crash-allow: the test-support feature is enabled only from dev-dependencies. Ratchet baseline lowered (8 counts). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test(crash-ratchet): Rust cfg(all(test, ...)) modules are test code (red) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(crash-ratchet): cut Rust inline modules under cfg(all(..., test, ...)) INLINE_TESTS matched only #[cfg(test)], so test modules under #[cfg(all(test, unix))] counted as production (all cmux-link, cmux-wg and cmux-pty hits, most cmux-remote unwraps). The regex now also takes cfg(all(...)) with test as one top-level predicate; any(test, ...) and all(not(test), ...) still count. Counts only go down. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(optchat, acpmux): refuse --tools default; an older acpmux drops only the tools list - acpmux: the built-in list refuses 'default' (any case), Claude Code's word for every built-in, so a preset list can only narrow. The hub integration test now refuses --tools default and a rule, not a list. - optchat-chief: on an 'args' refusal the preset is first installed without its --tools list (without_tools_list; --tools "" stays), and only then without the setting source and slash-command words. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(cmux-tui): zero production panics in ghostty-vt, cmux-relay, cmux-pty Each crate root now denies clippy unwrap_used, expect_used, panic, unreachable, todo, unimplemented and exit outside cfg(test). - ghostty-vt: key encoding falls back to the plain encoding when the key field has no separator (guaranteed above, was unwrap); the PNG header check returns false instead of try_into().unwrap(); a failed cursor visual read reports none instead of expect; the kitty replay base64 buffer size is a compile-time assert and an encode error falls back to an allocating encode; an OSC 10-12 code outside 10..=12 is ignored (was unreachable!); the Kitty palette value is filtered once instead of expect after is_some_and. - cmux-relay: the default bind is a const SocketAddr (test: it equals 127.0.0.1:8787); TicketAuthority::open builds its value directly (test: the default issuer is valid); the CLI subcommand uses next_if; a Join ticket from the CLI is an error, not unreachable!; a missing SIGTERM handler stops on Ctrl-C only; a closed admission semaphore (private, never closed) stops admitting instead of panicking. - cmux-pty: its only hits were in cfg(all(test, unix)) test code. Ratchet baseline lowered (includes the regex fix in the previous commit). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * CMUXMobileCore: a render grid frame past a 16-bit terminal size or 1M scrollback rows is malformed; span width checked without overflow (crash program phase 3) MobileProtocolFuzzTests hung for 180 s on a mutated frame: rows or scrollback_rows near Int.max passed validation, and the phone's replay (fullSnapshotBytes -> appendFlowLines) looped to build an unbounded byte stream; cell_width Int.max made span.column + width overflow (a Swift trap). Now columns and rows must be 1...65535 (Ghostty's 16-bit size) and scrollback_rows at most 1_000_000 (the phone keeps 20000), else invalidDimensions; the width check is width <= columns - column. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * cmux-next: red tests for the cmux Updated! card and Share cmux (cx-7py7) Behavior tests: the card shows once after a version change, never on a first install; its x is per version and shares What's New's seen state; it wins the bottom slot over the tip (a staged update wins over it); its rows run updates.whatsNew and app.shareCmux; Copy Link copies the shown message (with the plain download link) and turns into Copied. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * optchat-chief: test a marked subagent session passes acpmux's env allowlist and takes its TTL from its directory (red) The live proof on cmux-lawrence-2 (tag subp2) showed every Claude subagent refused: session/new: env key CLAUDE_CODE_PROMPT_CACHE_TTL is not one a session may set. The fake now refuses what acpmux refuses. * optchat-chief: test the subagent TTL comes from its directory's settings, and a user directory gets no mark (red) * crash P1b red: MessagesLab pane controller read before install (traps today) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * crash P1b red: an unusable auth callback scheme traps at sign-in (CmuxNextCloud) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test(optchat): compactor asks Claude Code for the haiku alias; user env files private and gated (red) Claude Code 2.1.287 reports claude-haiku-5-5 as unrecognized, so the compactor fell back to the turn model (and lost its cost parity); it takes the 'haiku' alias. The copied user settings env can hold secrets. Adds compactor_model_for and session_dir::copy_user_env_allowed (seams, today's behavior) and failing tests: a Claude Code compactor resolves to 'haiku', the API route keeps claude-haiku-5-5; the session and compactor slot settings files are 0600; the copy happens only on macOS and OPTCHAT_COPY_USER_ENV=0 turns it off. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * plans: crash program status after phase 2 and the first phase 3 fuzz landings Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * CMUXMobileCore: render grid limits match what Macs send; scrolled rows and the replay cell budget bounded (review fixes, crash program phase 3) Review subagent findings on d2ae62f2ea87: - scrolled_rows had no upper bound: String(repeating:count:) in the replay trapped or exhausted memory. Now scrolled_rows <= rows + scrollback_rows (what every producer sends). - 65535 x (1M + 65535) cells still meant ~70 GB of replay. Limits now match the producers: columns and rows <= 4096 (DaemonRenderGridState.maxDimension), scrollback_rows <= MobileTerminalScrollbackPreference.maximumRows (20000), and columns * (rows + scrollback_rows) <= 32 Mi cells. - New error case invalidSize(columns:rows:scrollbackRows:scrolledRows:). - Fuzz test: the base frames must decode, at least 100 mutated frames must decode (no vacuous pass), a second base (screen-anchored delta with scrolled_rows, scrollback, cursor, cleared rows) reaches the scroll fields, and deterministic limit tests check the maximum and one past each limit. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * crash P1b: no force unwraps or IUOs in CmuxMessagesLab and the CmuxNext modules outside CmuxNextApp (cx-6so) force_unwrap (new ratchet counting) and iuo to 0 outside the deferred and excluded sites. MessagesLab: MessagesLabHome 62 -> 6 left (RowDrawing WideBitmap/RowBitmaps path: deferred until the TextLayout P0 fix cx-qpqs lands, chief's decision), MessagesLabSidebar 18 -> 2 left (SidebarDraw.bitmap, same CGImage? design, done with the WideBitmap cascade), iuo 4 -> 0. CmuxNext modules (Actions, AgentActivity, AgentPane, Apps, Bookmarks, Browser, BrowserAutomation, BrowserImport, Cloud, CodeRouter, Design, Feed, History, Layout, Onboarding, Pages, Remote, RemoteView, Resources, Tabs, Terminal; CmuxNextSettings is frozen and lands separately): force_unwrap -> 0, iuo (Browser 8, Onboarding 17) -> 0. CmuxNextApp and CmuxNextSidebar untouched. Per site (behavior unchanged except "no trap"): - MessagesLab ChatController.store/demo: plain optionals (most readers already read them optional-style); install() works on locals and returns the store. Red: 6204a39af730. - HeaderBar pill constraint, AddressBarView controller and trailing constraints, BrowserChromeView.toolbarHeight, Onboarding buttons, gallery bar: lazy vars built at the same line of init as before (`_ = x` where the next line did not read it). - LoadErrorView buttons: `let` with targets set in init. SidebarPalette.resolve: local builder; the synchronous appearance block sets it. - Literal URLs, color spaces, UI fonts, function-key scalars: non-trapping construction with a stated fallback (/dev/null URL, device RGB, system font, NUL) and a test per type that every literal resolves (CrashLiteralTests in 10 CmuxNext test targets, CrashSafeGraphicsTests, SidebarCrashSafeTests). BrowserProfileID.default from bytes. - CloudConfiguration: an environment callback scheme that cannot form a URL is ignored (it trapped at sign-in; red 091671413c3b); signInURL builds with optional components. - ImportedExtension.webStoreURL returns URL? (an imported id may not form a URL). - Dictionary re-reads -> key/value iteration; optional chains on spring dictionaries; baseAddress guards (PTY write, LZ4 decode, CSV read, CEF switches, LongText); try? for NSDataDetector/NSRegularExpression; optional CGGradient draws nothing; WKNavigation! -> WKNavigation? in delegate signatures (same type). Vendor patches regenerated in this commit (sync-messageslab.sh --check passes). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * cmux-next: cmux Updated! card and Share cmux modal (cx-7py7) After the app updates to a new version, the sidebar's bottom card slot shows "cmux Updated!" with an x and two rows on the tip card's glass: "See What's New" runs updates.whatsNew (the in-app What's New page) and "Share cmux" runs the new app.shareCmux. The card reads What's New's one seen state (WhatsNewCenter): it shows when this launch's version is newer than the last seen one, never on a first install; opening What's New from any entrypoint or the card's x marks the version seen, so the card and the sidebar item's dot clear together. updates.showWhatsNew off hides it. A staged update card keeps the slot first; the tip waits for the card. app.shareCmux (palette, Help menu, the card row) opens a centered modal in the cmux dialog style: title, one line, an editable message with the plain https://cmux.com/download link, Copy Link (copies the shown text, then reads Copied until the text changes), an x, and Escape. No referral or tracking. CmuxDialogButtonView gains a public init and retitle(_:) so the modal reuses the dialog button. debug.updater gains updated {previous}, share and share-copy for DEV and NIGHTLY proofs. Strings: en + ja reviewed, other languages needs_review. Keyboard: Copy Link takes the keyboard when the modal opens and Return copies; Tab leaves the message box; the x draws no system focus ring. Card rows announce as buttons, show a pressed fill and follow the writing direction. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * optchat-chief: a marked subagent takes its TTL from its directory's settings, never from session env Fixes the L4 regression the live proof found: acpmux allows only CMUX_WORKSPACE_ID in a session's env, so every Claude subagent with a cache mark was refused at session/new. The TTL now goes to the subagent directory's .claude settings (session_dir::set_prompt_cache_ttl, as the turns' session directory), and a spawn in a user's directory gets no mark. * fixup: fuzz mutates one or two fields per frame so most frames reach the replay * fix(optchat): Claude Code compactor uses the haiku alias; user env files private and gated - A Claude Code compactor now asks for 'haiku' (compactor_model_for), which Claude Code maps to its current Haiku. Claude Code 2.1.287 does not know 'claude-haiku-5-5', so the compactor fell back to the turn model and lost its cost parity. The Messages API route keeps claude-haiku-5-5; another harness keeps its own default. The host log's compactor line names the resolved model once at start. - The session's settings.json and settings.local.json and each compactor slot's settings are written 0600 from the first byte (write_private): they may hold the user's settings env. Its values are never logged. - The user's settings env is copied only on a macOS host (the user's own Mac, never a Linux VM or dev backend image), only from a settings file this user owns, and OPTCHAT_COPY_USER_ENV=0 turns it off. The subagent directory gets no copy: subagents load the user's settings themselves. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fixup: decode floor 100 (about 210 of 6000 mutated inputs decode per base) * test(acpmux): red: ACP Registry agents as harnesses, cmux harness registry and add --registry (cx-1785) * feat(acpmux): ACP Registry agents: installed ones are harnesses, cmux harness registry, add --registry (cx-1785) t3code supports every agent of the ACP Registry (41 today: GitHub Copilot, Qwen Code, goose, Kimi, Amp, Cline, Auggie, Factory Droid, Junie, Kilo, Mistral Vibe, ...); acpmux knew none of them. registry.rs reads the registry (daemon fetch at start, HTTPS only, no redirects, 1 MiB cap, cached in ~/.acpmux/acp-registry) and checks every field: exact npx/uvx versions, https archives, relative archive commands without .., no loader or runner env keys, no ${} expansions; a bad agent is dropped alone. Nothing runs at discovery: an agent whose program is on PATH (its binary command, or the known bin of its npm package) becomes a harness with the registry's arguments, after built-in harnesses and after the default choice. cmux harness registry lists every agent and how it starts here; cmux harness add ID --registry writes a profile at the pinned version (installed program, else npx, else uvx). Archives are never downloaded. The design follows t3code's ACP Registry driver (MIT, credited). * test(agent-brands): red: ACP Registry agent ids resolve to their brand marks (cx-1785) * fix(agent-brands): github-copilot-cli (the ACP Registry id) shows the Copilot mark (cx-1785) * test(acpmux): red: cmux harness login signs in through ACP authMethods (cx-1785) * feat(acpmux): cmux harness login: sign in to any ACP harness with its own methods (cx-1785) acpmux never called ACP authenticate and showed only a login text, so a harness that needs a sign-in (Cursor, Gemini, Copilot, Antigravity, most registry agents) could not be signed in from cmux. cmux harness login ID starts the harness in a private temp folder, reads its authMethods and runs one: agent methods through authenticate (the agent opens the browser), terminal methods by running the harness's command line plus the method's arguments in this terminal, env_var methods by printing the Keychain step. --status checks with session/new (-32000 = sign-in required); --list shows the methods. Claude Code runs claude auth login. Method types follow t3code's ACP Registry auth (MIT, credited). * test(acpmux): red: an installed Antigravity ACP server (agy_acp_server.par) is the antigravity harness (cx-1785) * feat(acpmux): Antigravity harness: an installed agy_acp_server.par (cx-1785) t3code supports Google Antigravity through its ACP server (agy_acp_server.par). The ACP Registry lists it, but its program name is not its id, so registry discovery skipped it. The pinned name makes an installed server the antigravity harness; cmux harness login antigravity runs its Google sign-in (oauth-personal and the other ACP methods it offers). acpmux still downloads nothing: the registry entry has no sha256, so the server must be installed from its page. * release-notes: remote tab datalist suggestions and extension popups (CEF cmux.21) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * cmux-next: red test, the Updated card skips nightly updates (cx-7py7) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * release notes: plain cmux is this app's CLI in every terminal (cx-c59m.1) * cmux-next: the Updated card shows only for stable and RC updates (cx-7py7) Nightly builds update several times a day, so a nightly version no longer shows the cmux Updated! card (chief decision 2026-10-08). The What's New item keeps its own rule. debug.updater updated still forces the card. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test(backend): Mac grants from before the mac grant cap lose execute once, on bind and in the per-request grant check (red, cx-wb5.64) * fix(backend): drop execute once from Mac install grants made before the mac grant cap (install.mac_execute_narrow on UserDO bind, cx-wb5.64) * indicators: red tests, Symbols is the default status icon set (Lawrence 2026-10-09) (cx-kxa2) * indicators: Symbols is the default status icon set; Dots stays as the original drawing in the switcher (cx-kxa2) * agent-screen-detection: red tests for herdr 0.9.3 parity and the herdr pin check Behavior tests only. They fail on this tree: - manifests: agy dialogs, thought-summary spinner and esc footer; agy and grok background work at the prompt is idle; codex Folder access trust dialog; pi spinner Working line (herdr 2563803d manifests). - process identity: Hermes through its Python installer (herdr e35f3937, reporter capture copied under Apache-2.0), non-interactive Letta processes (fc1cb77f), Cline .cline launcher and argument mentions (f3cbe03f), Kimi and omp package launchers (63ea2314, cd8306d7). - scripts/cmux-next/tests/test_herdr_sync.py: sync/check/drift for the herdr pin, including check failing on a mismatched pin (herdr-sync.py does not exist yet). * agent-screen-detection: sync herdr 0.9.3 (2563803d) and keep it current Pin and tooling: - HERDR_UPSTREAM.toml pins herdr 2563803d (0.9.3, engine 3) with the upstream sha256 of each vendored manifest and of the tracked engine sources (src/detect/{manifest,mod,manifest_update}.rs, src/pane/{agent_detection,osc}.rs). HERDR_PATCHES.toml documents local manifest edits; there are none now. - scripts/cmux-next/herdr-sync.py (stdlib, python3 -I): sync (git show, never checkout; reapplies documented patches or fails), check (offline), drift (nonzero on drift, markdown issue body). - cmux-next checks: herdr-sync.py check and its unit tests in the Script tests step on every push and PR. - .github/workflows/herdr-upstream-drift.yml: daily + dispatch, checks out feat-cmux-next, shallow-clones the herdr tip, opens or updates one "herdr upstream drift" issue. No PRs. Port: - manifests antigravity 2026.10.05.1, codex 2026.10.01.1, grok 2026.10.05.1, pi 2026.10.01.1, byte-identical to upstream. The cmux Grok precedence patch is dropped: upstream 2026.10.05.1 covers it. - process identity: Hermes Python installer (e35f3937), Letta interactivity (fc1cb77f), Cline .cline launcher and no identity from another program's arguments (f3cbe03f), Kimi and omp package launchers (63ea2314, cd8306d7), in the new src/process/launchers.rs (package launchers moved there). - background_agent.rs + scanner: a suspended or backgrounded agent keeps its identity while that exact process lives in the terminal session, and its screen is not read (950d012c). - ATTRIBUTIONS (plugin and cmux-tui), manifests/README, README and the hand-written notice (THIRD_PARTY_LICENSES.md section) name the new pin and the reviewed commits; the Apache text is unchanged. * cmux-tui-core: red test, an OSC 7501 record that finishes posts one done notification (cx-kxa2) * cmux-tui-core: an OSC 7501 record that finishes posts one done notification (info), shown by clients only for a terminal the user cannot see (cx-kxa2) * herdr-sync: red tests, whole-token patch edits, changed-file notice, removed tracked files and odd upstream text (cx-kxa2 review) * herdr-sync: patch edits match whole tokens and stamp a Manaflow change notice; drift tracks the ported process files, reports removed files, exits 2 on tool failures, keeps upstream text inert; the drift job clones history for the commit list (cx-kxa2 review) * cmux-next: menus and composer pickers pick by press-drag-release (#18727) * test: composer popovers pick by press-drag-release Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: rows are option buttons, as the pickers build them Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: menus and composer popovers pick by press-drag-release One shared press session (ui/pressRelease.ts) for Menu and every composer popover trigger: a press opens, a release over a row picks it, a release on the trigger within 150 ms or without moving is a click. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: a release over a row's icon picks the row Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: a release over a row's icon picks the row Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * test(spaces): scripted space.new gives the new space its own workspace without moving the view (cx-f8aw, red) * package-test-lane: an unknown CMUX_SWIFT_SANITIZE is refused before any build (red, crash program phase 3) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * package-test-lane: CMUX_SWIFT_SANITIZE=address|thread|undefined runs a lane under that sanitizer (crash program phase 3) Adds --sanitize and a separate --scratch-path (.build-sanitize-<name>) to every swift build/test of the lane, so a sanitizer pass is one ci-step: cmux-ci run --class light --script scripts/ci/package-test-lane.sh ... --env CMUX_SWIFT_SANITIZE=thread Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test(cmux-server-core): an identifier that does not quote must not panic the SQL builder (red) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(cmux-tui): zero production panics in cmux-server-core, cmux-layout-reducer, cmux-app-manifest, cmux-tasks-core Each crate root now denies clippy unwrap_used, expect_used, panic, unreachable, todo, unimplemented and exit outside cfg(test). - cmux-server-core: SQL identifiers and literals that do not quote (empty or NUL; impossible for constants and app_<AppId>) become "", a zero-length identifier Postgres refuses, instead of a panic; nothing unquoted reaches the SQL. SCRAM hmac/hi return Option into the existing Option of scram_verifier. Literal absolute Unix paths use HostPath::unix_absolute (debug_assert that HostPath::new accepts them unchanged). PairingCode::as_str/display and the fingerprint read do not unwrap; the word list fills a fixed array (the existing test checks 2,048 distinct words). An unparsable min_cmux_version after validation is ManifestError::Invalid. - cmux-layout-reducer: take_tab/place_tab/move_tab return Reject (UnknownPane/UnknownTab/UnknownWorkspace/RowSetMismatch) instead of expect; apply works on a copy, so a reject still changes nothing. No new Reject variant (no FFI change). The cfg(kani) proof harness keeps its expects under crash-allow (a panic is the proof failure). - cmux-app-manifest: every embedded schema and table loads once into a Result; a load failure refuses (an Issue, a reserved CLI word, an unknown scope), fail closed. Unit tests load every embedded asset and drive the broken-table paths. - cmux-tasks-core: handler lookups of validated entities reject with not_found before the first write (task_delegate now looks the task up before it inserts the session); cascade loops and void helpers skip a missing entity; place() plans the rebalance and checks the gap before any write and refuses with conflict when it has no room (state unchanged); sort_key::sequence stops instead of panicking. Ratchet baseline lowered. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test(backend): team_vm.retired.export downloads /srv/team of a fenced retired VM (cx-lyvg, red) Behavior tests for the missing export path: an owner or admin exports the retired, fenced team VM's /srv/team as a single-use tar download; the VM stays paused and fenced; members, agents and installs are refused; a VM not fenced yet, more than 2 GiB or 5000 entries, and a VM without /srv/team answer declared errors; a broken provider stream resumes with Range. Dashboard: a Download button on paused retired rows for owners and admins, and the Rebuild and Delete confirms say to download first. * feat(backend): team_vm.retired.export streams /srv/team of a fenced retired VM (cx-lyvg) A rebuild retires the old team VM with its team files on /srv/team, and the fence (cx-009a) means it never runs again, so the copy-off step had no path. team_vm.retired.export {vm} (owner/admin, person session only; TeamDO role check and team_vm.taint_audit retired_exported, like retired.delete) walks /srv/team through Freestyle's file API (fs/dir, fs/stat; the disk of a paused, budget-spent VM stays readable), refuses a VM that is not paused and fenced (team_vm.retired_not_fenced), over 2 GiB of files or 5000 entries (team_vm.export_too_large), without /srv/team (team_vm.export_no_files) or a walk over 60 s (team_vm.export_timeout), and stores the manifest under a single-use 5-minute ticket (SHA-256 only) in TeamVmDO. GET /v1/team-vm/export/<team>/<ticket> streams a pax/ustar tar from that manifest: one fs/read per file, chunk by chunk, so the Worker never holds the archive; the exact Content-Length (FixedLengthStream) turns a cut stream into a failed download; a broken read resumes with Range; 30 minute stream limit. Symlinks and special files are skipped and listed. Nothing starts or unfences the VM. No R2: the only bucket belongs to Home attachments, and a frozen VM is already the source of truth. Dashboard: Download files on each paused retired row (owners and admins); the Delete confirm says to download first and has the button; the Rebuild confirm says the same. The files-copied checkbox stays manual. en + ja. Generated: catalog, TS client, cmux-app-host files (the op is in `never`: gen-cmux-global NEVER names it; full regen also picks up the conversation.* ops that 7e10e236714b left ungenerated). * test(backend): a retired team VM's disk holds its newest writes; paused-disk stat metadata (cx-lyvg, red 2) Live check 2026-10-09 (dev account): Freestyle's file API reads a paused VM's disk image, not the guest page cache. A file written seconds before the pause read back as 0 bytes (stat size 0); after a guest sync it read back whole (300000 bytes, Range 206). retireVm must sync a running VM before the budget and pause, never wake a paused VM for it, and never let a failed sync hold the fence. stat answers modified as epoch seconds (running) or empty (paused) and numeric owners when paused. * fix(backend): retireVm syncs a running team VM before the fence; read paused-disk stat metadata (cx-lyvg) The provider's file API reads a paused VM's disk image, so writes still in the guest page cache at the pause were invisible to team_vm.retired.export (measured: 0 bytes). retireVm now reads the state and, only on a running VM, runs `sync` as root through exec-await (15 s), then spends the budget and pauses as before; a failed or slow sync is logged and never holds the fence, and a paused VM is never woken for it. fs/stat `modified` is epoch seconds (running) or empty (paused). Plan and coordination notes. * fix(backend): export download sends referrer-policy no-referrer; rebuild copy names the retired VM row (cx-lyvg review) Review by the coordinator: the ticket is in the URL path, so the download answer sets referrer-policy: no-referrer. The Rebuild confirm says to download the team files from the retired VM row after the rebuild. The full app-host regen keeps the conversation.* output that 7e10e236714b left ungenerated. Coordination note names the pre-change fence limit. * test(app): every static URL literal and function-key character parses (red: helpers missing) (cx-6so P1b, helper H4) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(app): no force unwrap on static literals in CmuxNextApp (force_unwrap CmuxNextApp 67 -> 48) (cx-6so P1b, helper H4) Per site (no behavior change except "no trap"): - Static URLs (feedback, docs, about:blank): StaticURL enum; `url` never traps (a literal that did not parse would be a file URL of the same text); StaticURLTests checks every case parses. - NS*FunctionKey characters (BrowserChordTable, DebugKey): arrows use the existing Shortcut.*ArrowKey constants; page up/down, home, end, forward delete use FunctionKeyCharacter.string, which gives "" for a non-scalar code; FunctionKeyCharacterTests checks every code the app uses. - CGColorSpace(name: sRGB)! (DebugPaletteCapture, ScreenEmojiIcon): `?? CGColorSpaceCreateDeviceRGB()`, a real color space. - AppResourceSource: the daemon index is bound once instead of re-read with `!`. - HistoryService: an empty or missing visit title falls back to the URL with flatMap instead of `title!`. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs(cmux-next): OSC 7501 matrix records landed SHAs and live evidence Bead: cx-6so.36.5 * cmux-next composer: the folder popover's field reads as a menu row The folder popover (LocationPicker allowPath) gave its search field no styles, so WebKit drew a native text box with the system blue focus ring, and the placeholder repeated the button label (Choose folder). The field is now a borderless menu row on the menu fill with a hairline over the results, and the placeholder says what it does (Search folders or type a path, all 21 locales). The gallery's agent-home variant was not a fresh chat (snapshot without sessionId, summary with ""), so it showed this fallback field instead of the new chat's folder menu (Choose folder...). Its snapshot now names the prewarmed session, as the app's does; a new agent-home-path variant keeps the field in the gallery. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(home): my own send shows as typed at the press, after the echo and after a reopen (red: the reducer's local message was never marked plain and took the Markdown engine) * optchat-chief: red tests, no request exceeds the API's 4 cache marks (turns, compactor nodes, subagents) Measured on Claude Code 2.1.287 on the subscription login and the subrouter: it marks its two system blocks and the last message of a session's first request, and the last two messages of every later request (tool step, follow-up prompt, steered message), so our view mark in the first message makes 5 on a session's second request. * fix(home): a message is plain unless HomeMapping marks it Markdown (an agent's text), so my own send shows as typed at the press, after the echo and after a reopen (green). The reducer's local message was measured before HomeMapping saw it and kept its Markdown layout under the same id * fix(spaces): space.new shares one path that gives the new space its own workspace and shows it only when the run may change the view (cx-f8aw) * fix(cmux-next): group color dots are named by their theme slot, never a fixed color word (cx-rcby) * crash: escaping tasks no longer outlive the owner of an unowned back-reference (cx-6so P1b, helper H1) Step B of the unowned plan (chief-approved A/B table): an unowned back-reference traps only when the child outlives its owner, and the escapes that could make it do so are tasks that keep the child and reach the owner after a suspension. Each site now either does not keep the child, or pins the owner until the task ends: - weak child: AgentHistory/CommandHistory refresh (the owner's daemons are read before the first suspension), ThemeCoordinator's launch prune loop. - owner values read before the task: AppOnboardingServices openProjects / resumeChats (folderFailed takes the logger) and importClassicSessions (machines + logger), so nothing after a suspension goes through the onboarding service. - owner pinned for the task's duration (`[services]` capture, released when the one-shot task ends; no stored task, so no cycle): TabDragSession commit (4), QuitCoordinator quit/complete, PaneController new tab / close / pin, SidebarBridge reorder + command re-sync (bridge weak), WindowManager newWorkspace / newWindow / incognito window / profile switch, WorkspaceContentController focus intents ([services, state]), CEFTab exitContentFullscreen ([runtime]). No reachable path changes while the owner lives (the app's services live for the process); the change matters only where the owner can be freed (tests, window teardown). Not driven by a test: freeing AppServices mid-task needs the whole service graph torn down, which the lifetime tests of step A cover. The unowned count is unchanged here (the references stay; step A allowlists them with lifetime tests). * notifications: red test, an OSC 7501 alert is recognized before its record arrives (cx-kxa2 live race) * notifications: an OSC 7501 alert waits up to 1.5 s for its record (observed, no poll) so its banner gets the status badge (cx-kxa2 live race) * notifications: red test, debug.notifications reports a banner's status badge attachment (cx-kxa2) * notifications: debug.notifications reports each banner's status badge attachment (cx-kxa2) * scripts: status-indicators-live.py, OSC 7501 and ACP status indicators on a fleet build per icon set and theme (cx-kxa2) * plans: mobile Rust core proposal (uniffi, cmux-mobile-core/net/ffi, slice order) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * optchat-chief: no request exceeds the API's 4 cache marks Claude Code 2.1.287 marks its two system blocks plus the last message of a session's first request, and the last two messages of every later request (tool step, size-loop follow-up, steered message), on the subscription login and through sr alike. Our view mark stays in the first message's history, so a session's second request had 5 and the API refused it (compactor nodes 0+8 and 8+4 in subp2). A turn or compactor node that carries our mark now runs Claude Code with DISABLE_PROMPT_CACHING=1 in its directory's settings env (Claude Code places none; every request reads up to our mark, a turn's tool steps send their tail uncached). One too small for a mark keeps Claude Code's marks. The pool hint writes the next turn's choice, a turn drops its mark when its pooled session started with Claude Code's marks on, and warm compactor sessions are keyed by it. Subagents carry no mark of ours (long sessions: Claude Code's own marks cache them step by step), so the spawn warm-up is idle. * test(cmux-tui-cdp): a poisoned lock must not panic the CDP client (red) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(cmux-tui-cdp): zero production panics; poisoned locks recover, rebuild or close The crate root now denies clippy unwrap_used, expect_used, panic, unreachable, todo, unimplemented and exit outside cfg(test). Per lock: - FrameEpoch.wait_lock guards (): recover (PoisonError::into_inner), also for the condvar wait. - Inner.pending is one map; every critical section is one insert, remove or drain: recover. - EventQueue.state keeps retained_bytes equal to the sum of the queued sizes: on poison, rebuild the sum from the events and clear the poison. - Inner.frame_epochs holds multi-field per-session navigation and screencast state: a poisoned lock is never read. The connection closes (pending calls fail, the event stream ends with Closed) and the caller gets an error, false or None. The three Page.* handlers take the session id with let-else instead of expect("guarded above"). The lock helpers, close_inner and the new tests live in client/locks.rs and client/lock_tests.rs (client.rs stays under its godfile baseline). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * cmux-tui: bundled-CLI daemon test is its own test target tests/cli.rs is at its god-file limit, so the real-daemon bundled-CLI test moves to tests/bundled_cli.rs with a small harness of its own. * test(home): the send-as-typed test reads the controller's optional store and window view (base removed the IUOs) * cmux-next: improve composer control hierarchy (#18485) * refine agent composer context surface * show composer controls in the toolbar * update composer layout assertion * cover visible access mode label * test: cover model picker Escape away from search * fix: close model picker on Escape from any control * fix: keep unified composer radius tokenized * chore(gallery): format chief inspector fixture * chore(gallery): match web formatter output * fix(composer): preserve full access warning color * fix(composer): keep warning color while access menu is active * test: locate model filter by accessible state * cmux-next: red tests for the cmux Updated! card and Share cmux (cx-7py7) Behavior tests: the card shows once after a version change, never on a first install; its x is per version and shares What's New's seen state; it wins the bottom slot over the tip (a staged update wins over it); its rows run updates.whatsNew and app.shareCmux; Copy Link copies the shown message (with the plain download link) and turns into Copied. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * optchat-chief: test a marked subagent session passes acpmux's env allowlist and takes its TTL from its directory (red) The live proof on cmux-lawrence-2 (tag subp2) showed every Claude subagent refused: session/new: env key CLAUDE_CODE_PROMPT_CACHE_TTL is not one a session may set. The fake now refuses what acpmux refuses. * optchat-chief: test the subagent TTL comes from its directory's settings, and a user directory gets no mark (red) * test(optchat): compactor asks Claude Code for the haiku alias; user env files private and gated (red) Claude Code 2.1.287 reports claude-haiku-5-5 as unrecognized, so the compactor fell back to the turn model (and lost its cost parity); it takes the 'haiku' alias. The copied user settings env can hold secrets. Adds compactor_model_for and session_dir::copy_user_env_allowed (seams, today's behavior) and failing tests: a Claude Code compactor resolves to 'haiku', the API route keeps claude-haiku-5-5; the session and compactor slot settings files are 0600; the copy happens only on macOS and OPTCHAT_COPY_USER_ENV=0 turns it off. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * cmux-next: cmux Updated! card and Share cmux modal (cx-7py7) After the app updates to a new version, the sidebar's bottom card slot shows "cmux Updated!" with an x and two rows on the tip card's glass: "See What's New" runs updates.whatsNew (the in-app What's New page) and "Share cmux" runs the new app.shareCmux. The card reads What's New's one seen state (WhatsNewCenter): it shows when this launch's version is newer than the last seen one, never on a first install; opening What's New from any entrypoint or the card's x marks the version seen, so the card and the sidebar item's dot clear together. updates.showWhatsNew off hides it. A staged update card keeps the slot first; the tip waits for the card. app.shareCmux (palette, Help menu, the card row) opens a centered modal in the cmux dialog style: title, one line, an editable message with the plain https://cmux.com/download link, Copy Link (copies the shown text, then reads Copied until the text changes), an x, and Escape. No referral or tracking. CmuxDialogButtonView gains a public init and retitle(_:) so the modal reuses the dialog button. debug.updater gains updated {previous}, share and share-copy for DEV and NIGHTLY proofs. Strings: en + ja reviewed, other languages needs_review. Keyboard: Copy Link takes the keyboard when the modal opens and Return copies; Tab leaves the message box; the x draws no system focus ring. Card rows announce as buttons, show a pressed fill and follow the writing direction. Co-Authored-By: Claude Opus 5.5 (1M …
Summary
Three nightly-next builds in a row outlasted the 20m in-job notarization wait from #18713: 6d443005's, plus runs 37871970302 and 37872060374, so none published in-job. Published nightly-next now waits up to 40m, the same as main and RC.
CMUX_NOTARY_WAIT_TIMEOUTbecomes a plain40mon every track.The step's 50m and the job's 80m timeouts already cover a 40m wait (
tests/test_notarize_nightly_dmg.shchecks the bounds). A wait that still runs out hands off through the recovery artifact as before, and #18722 continues it on a later run.Testing
tests/test_nightly_universal_build.shfails with "nightly-next bounded notarization contract is missing: CMUX_NOTARY_WAIT_TIMEOUT: 40m".test_notarize_nightly_dmg.shtimeout bounds pass and actionlint is clean. cmux-next-guards runs the release-notary group on this PR.Changelog
none
🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.Summary by cubic
Waits up to 40m for Apple notarization in the
nightly-nextjob, matching main and RC, after three consecutive nightly-next builds outlasted the previous 20m wait and failed to publish in-job.CMUX_NOTARY_WAIT_TIMEOUTto a flat40mon every track instead of track-specific values.Written for commit 5ba51c8. Summary will update on new commits.
Note
Low Risk
CI-only change to notarization wait duration in the nightly workflow; no app runtime or security logic is modified.
Overview
nightly-next no longer uses a shorter 20m in-job Apple notarization wait;
CMUX_NOTARY_WAIT_TIMEOUTis now40mon every track (main, RC, and nightly-next), matching the longer bound main/RC already used.Workflow comments note that three consecutive nightly-next runs exceeded 20m, so builds were not stapled or published in-job. The existing 50m step timeout and recovery-artifact handoff on timeout are unchanged—only the wait cap increases so more builds can finish notarization in the same run.
tests/test_nightly_universal_build.shwas updated to assert the fixed40mvalue instead of the old track-conditional expression.Reviewed by Cursor Bugbot for commit 5ba51c8. Bugbot is set up for automated code reviews on this repo. Configure here.