reload: let a build-only run keep the tagged app running - #60
Closed
teamleaderleo wants to merge 4258 commits into
Closed
teamleaderleo wants to merge 4258 commits into
teamleaderleo wants to merge 4258 commits into
Conversation
…ory-reclaim-retention Preserve aggregate memory accounting and safe hibernation scopes
This reverts commit 38dcda7.
This reverts commit 42631af.
…-12684-image-drop-attachment
This reverts commit cadea32.
…low-ai#12712) * feat(web): add computer use landing page * Remove product label from computer use heading * Localize Computer Use landing and documentation in all site languages * Serve the local search index on standalone docs previews * Add copyable Computer Use prompt and bottom CTAs * Share Computer Use action row spacing between top and bottom
…12709) * Cache client config evaluations in Vercel Runtime Cache * Test cache identity isolation and Firewall cancellation * Preserve cache identity and bound shared evaluations * Cover request limits for cached and shared flag evaluations * Enforce request admission before cached flag evaluations
…ud-auth-browser cmux24: manaflow-ai#12346 cloud auth browser
…2902) * test: cover iOS initial connection telemetry * feat: measure iOS initial connection readiness * fix: preserve initial connection attempts across duplicate foreground events * fix: require terminal output before connection completion
…manaflow-ai#12886) * test(cloud): reproduce duplicate VPN starts * fix(cloud): coalesce duplicate VPN starts * fix(cloud): actorize VPN start callback gate * fix(cloud): tighten provider start concurrency * fix(cloud): avoid tunnel start overload collision * refactor(cloud): isolate VPN start gate package * fix(cloud): expose tunnel gate initializer * fix(cloud): order VPN starts and stops through one lifecycle * test(cloud): build real VPN extension for lifecycle verification * test(cloud): reliably reject stub tunnel engines * fix(cloud): drain lifecycle callbacks during provider cleanup * refactor(cloud): extract WireGuard tunnel device discovery * test(cloud): reproduce stale tunnel device selection * fix(cloud): bind WireGuard to the configured tunnel device
…aflow-ai#12908) * test: require the shared daemon readiness and probe cache contract * fix: wait for daemon identity and socket before image reachability
…anaflow-ai#12909) * test: cover IndexNow notification without duplicated private credentials * fix: notify IndexNow directly from the deployed public sitemap * fix: give IndexNow retries their full workflow budget * fix: batch IndexNow updates from the deployed revision
…anaflow-ai#11572) * feat(ios): Sentry session replay with always-masked content surfaces Enables replay on the cmux-ios project: sessionSampleRate 0.1, onErrorSampleRate 1.0, quality .low, view renderer V2, no touch capture (swizzling stays off). Masking is applied on-device before upload; the text/image/webview defaults stay on and every content surface the class defaults cannot classify is masked unconditionally through a central list (MobileSessionReplayMasking): the Metal ghostty terminal, the browser stream's CALayer mirror, the sim-stream video view, and a new dedicated camera preview host view. Replay consent rides the existing sendAnonymousTelemetry gate on all three layers (start-gated SDK, per-event beforeSend, revocation purge of Caches/io.sentry, which holds buffered segments). DEBUG builds honor CMUX_REPLAY_FORCE_SESSION=1 to force a full-session replay for mask audits. Privacy policy gains a masked-session-replay disclosure (collection, masking, opt-out, 90-day retention) in English and all 19 other locales. The ASC privacy label already covers replay (Product Interaction + Diagnostics declared; verified against the pulled label and sentry-cocoa's privacy manifest), so no label change ships with this. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(ios): start replay with Sentry session lifecycle * fix(ios): fail closed before replay masking is configured * fix(ios): require every replay mask surface * fix(ios): keep camera controls above replay host * fix(ios): validate replay masks by exact class names * fix(ios): preserve Sentry replay mask defaults --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* test: terminal grid must not follow scroller visibility under legacy scrollers Adds a hosted-view behavior test that hosts a real GhosttySurfaceScrollView in an offscreen window, pins the legacy scroller style on its scroll view, and publishes Ghostty scrollbar packets the way the runtime does: history present, then emptied (the Cloud mirror's replay reset), then refilled (the replay). It asserts the terminal surface keeps the same content width throughout. On main the scroller hides and shows with scrollback, so the legacy gutter comes and goes and the grid width moves by the gutter each time; for a Cloud mirror that turns every remote `resized` replay into a new size report and an endless remote resize loop (manaflow-ai#12885). Also adds TerminalScrollBarPresencePolicy (not yet used by the view) with its own unit test. Refs manaflow-ai#12885 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * fix: keep terminal grid width stable across cloud replays * Handle optional capability probe in browser proxy --------- Co-authored-by: Austin Wang <austinwang115@gmail.com> Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
* Trace terminal replay latency across mobile and host * Close abandoned terminal replay traces * Harden terminal trace ID validation
…2384) * Encrypt push notifications and reply relays end to end * Register the iOS notification encryption key * Fix public peer key store API * Export crypto framework types from push package * Fix encrypted payload encoding * Fix reply inbox decryption compile errors * Complete end-to-end device notification encryption * Preserve legacy push clients during encryption rollout * Keep push identity and legacy clients compatible * Fix reply key routing and legacy token lookup * Harden notification extension and recipient delivery * Allow encrypted push payloads without plaintext fields * Harden encrypted push delivery compatibility * Map encrypted dismissals to legacy notification IDs * Preserve push key exchange compatibility * Bound encrypted reply failures and peer keys * Enforce authenticated push recipient keys * Complete push target and lifecycle compatibility * Preserve push registration compatibility * Restore push account identity with auth session * Preserve encrypted notification collapse identity * Drain legacy parked replies during encryption rollout * Harden push compatibility lifecycle * Restore legacy reply decoder keys * Prune stale reply decrypt state * Use configured keychain group for push decrypt * Keep encrypted push and reply data fresh * Separate legacy and E2E notification transports * Keep phone push package compatible with iOS 17 * Repair E2E notification merge blockers * Harden notification migration recovery paths * Fix decrypt outcome switch exhaustiveness * Fail closed when push encryption is unavailable * Complete strict push key setup * Fix phone push retry task visibility * Fix push route type errors * Reencrypt queued pushes after key rotation * Preserve legacy push registration path * Reject cross-account push registration takeover * Fix push requeue control flow * Wire phone push package and bound key retries * Bound push recipient discovery * Retain pushes during recipient discovery * Fix pending push queue admission * Reject malformed encrypted push tuples * Retry transient push key discovery * Fix secure push recovery and authenticated payload merging
Require cmux 0.64.25 stable or the first published 0.64.25 nightly for every App Store iOS compatibility tier, keeping the native fallback and remote policy synchronized.
* test: cover SSH split remote cwd inheritance
* fix: preserve remote cwd when splitting SSH panes
* fix: make remote cwd resolution explicit
* fix: tighten remote cwd provenance
* fix: honor remote cwd inheritance flag
* test: make remote cwd paths deterministic
* test: cover stale remote cwd environment
* fix: clear stale remote cwd overrides
* test: cover SSH startup cwd edge cases
* fix: preserve SSH startup cwd across splits
* refactor: isolate SSH cwd regression coverage
* test: remove stale actor annotation after SSH test extraction
* test: retain local image files through terminal delivery
Exercise the shared local image transfer path for both image drops and Cmd+V paste. The materialized file must remain available after the path is sent so Claude Code and Codex can read it asynchronously.
* fix: keep local image transfer files alive
Do not delete cmux-owned image files when the local terminal path is delivered. Claude Code and Codex read that path asynchronously after sendText returns; retain the file for the existing process-lifetime cleanup instead.
* test: reject releases missing SSH daemon assets (#12648)
* fix: restore and verify the SSH daemon release contract
* test: synchronize restored daemon log capture under race detection
* test: use synchronized sinks for asynchronous daemon fixtures
* test: reproduce relay rejection of a System-keychain root
* test: cover restored daemon permissions and non-launch behavior
* test: bound and report relay TLS harness setup
* fix: harden restored daemon boundaries and address review findings
* test: verify native discovery failures and bound keychain cleanup
* fix: authenticate local CLI bridge peers before forwarding
* test: reject credential lookup errors even with a matching UID
* fix: honor macOS relay system trust and preserve issuer diagnostics
* fix: verify locked relay artifact and declare logger isolation
* Read relay timeout diagnostics from the native endpoint
* Use pinned Xcode for Swift relay diagnostic tests
* Show safe relay TLS failures while the Mac retries
* Select certificate fixture extensions explicitly
* Fix duplicate test build phase identifier
* Pass current device list to legacy relay admission
* fix: restore the legacy pairing auth observer dependency
* test: exercise restored daemon on native macOS
* test: cover macOS daemon filesystem behavior without instrumentation
* fix: create the tmux compatibility lock atomically on macOS
* test: reproduce Cloud surface ownership violations
* fix: disambiguate app and test build file identities
* Separate restored auth observation state from its owner
* Fix duplicate Xcode build file IDs after main merge
* build: restore omitted mobile auth observer dependency
Restore the dependency required by current main, using the original author repair from d2f04134f3390307d796225362f9aab373066644. The tagged build otherwise fails to resolve MobileHostIrohAuthObserver.
* Repair restored host API call sites and verify CA cleanup strictly
* build: repair inherited Xcode ID and localization blockers
* Restore auth observer required by merged mobile runtime
* Scope restored auth streams and preserve supplied device identity
* build: restore missing and colliding legacy runtime dependencies
* fix: enforce Cloud surface ownership across drag and move paths
* Revert "Restore auth observer required by merged mobile runtime"
This reverts commit 38dcda7fe6a30f9c4c581cd9b13551c42a15189b.
* Revert "Fix duplicate Xcode build file IDs after main merge"
This reverts commit 42631afaaa01928ce7148223b13f7d8400fd2cbe.
* Align restored pairing view with its ready state
* fix: restore the IRX sign-out lifecycle contract
* Keep TLS fix scoped while upstream transport restoration is repaired
* Revert "build: restore omitted mobile auth observer dependency"
This reverts commit cadea3232baa81f4eced2117611fe0f42acd8424.
* build: restore complete legacy runtime settings companions
* build: align the Mac mobile facade with the v2 transport owner
* Add localized cmux Computer Use landing page and documentation (#12712)
* feat(web): add computer use landing page
* Remove product label from computer use heading
* Localize Computer Use landing and documentation in all site languages
* Serve the local search index on standalone docs previews
* Add copyable Computer Use prompt and bottom CTAs
* Share Computer Use action row spacing between top and bottom
* fix: distinguish Dock origins from workspace rollback
* Cache client config evaluations in Vercel Runtime Cache (#12709)
* Cache client config evaluations in Vercel Runtime Cache
* Test cache identity isolation and Firewall cancellation
* Preserve cache identity and bound shared evaluations
* Cover request limits for cached and shared flag evaluations
* Enforce request admission before cached flag evaluations
* test: reproduce legacy ownership loss and pairing recovery gaps
* fix: retain Cloud ownership and bound pairing preparation
* fix: show ownership feedback over Cloud tree destinations
* test: cover Cloud tree rejection and document auth scope generations
* fix(web): align bottom Computer Use CTA vertical spacing (#12761)
* Restore TUI publishing and detect undelivered releases (#12763)
* test: catch undelivered TUI releases and unchecked wheel identity
* fix: verify TUI registry delivery and installed wheel identity
* test: isolate native TUI publishing from separately deployed worker
* fix: scope TUI release verification to shipped native packages
* test: keep unpublished experimental Windows package out of default releases
* fix: make experimental Windows publishing opt-in
* Fix iOS archive after the pairing opt-in merge (#12765)
The squash of https://github.com/manaflow-ai/cmux/pull/12316 clobbered three
later main changes in CmuxMobileShellUI and broke the TestFlight archive:
- DisconnectedWorkspaceShellView used the retired device-id contract for the
Devices toolbar label and the pre-v2 empty-state copy. Restore the pairing-id
contract every other caller uses and the localized v2 copy.
- CMUXMobileRootView still pushed the Mac compatibility policy into
MobileWhatsNewCenter, which the merge removed with the What's New footnote.
- MobileWhatsNewSheet called presentationSizing(.fitted) unguarded; the package
targets iOS 17. Route it through a compatibility helper next to the others.
Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
* Preserve existing Mac identity across the v2 upgrade (#12754)
* fix: preserve the v2 connection owner with explicit pairing opt-in
* test: reproduce v2 legacy computer identity split
* fix: preserve existing Mac identity for older iOS discovery
* test: recover computer identity repair after a lost reply
* test: restore v2 lifecycle coverage and preserve prior pairing opt-in
* fix: retain historical explicit pairing choice under the v2 owner
* test: preserve another same-named Mac during identity repair
* test: verify unauthorized subscriptions without an unowned TCP peer
* fix: preserve canonical saved identity and sorted RPC inventory
* test: preserve equivalent defaults when repairing the shared identity file
* fix: avoid rewriting an equivalent saved host identity
* perf: throttle CodeRouter API key metadata writes
Merges the API key metadata write throttling, account transaction fencing, safe auth telemetry, and preview configuration fixes after rebasing onto current main.
* Pin detached TUI sessions to the client terminal identity (#12767)
* fix(tui): pass host colors to detached owner
* fix: satisfy TUI color handoff lint
* fix(tui): pin detached owner terminal identity
* fix: expose shared child terminal identity resolver
* Fix cmux-tui build: use the crate-root child term re-export (#12774)
https://github.com/manaflow-ai/cmux/pull/12767 re-exported default_child_term
from cmux-tui-core's crate root but called it through the platform module in
main.rs, so every cmux-tui workflow on main fails with E0425.
Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
* web: simplify the settings gear in the account dropdown (#12708)
* web: make dashboard settings a gear button
* web: draw a toothed gear for dashboard settings
* web: keep settings gear in account popover
* web: simplify settings gear icon
* web: preserve settings icon weight and Lucide attribution
* Add monthly Max pricing and gate the Go starter plan (#12415)
* Add the cmux Max plan and gate 32 GB and 64 GB machines behind it (#12309)
* Add the Max plan constants and the per-plan machine memory ceiling
Max is a personal plan above Pro at $200/mo, monthly only. Free, Pro,
Team, and Founder's Edition machines now stop at 24 GB; the 32 GB and
64 GB ladder rows are locked behind Max. The machine list publishes the
locked sizes and the upgrade plan, and a create that asks for a locked
size is refused with vm_memory_requires_plan instead of being coerced.
Claude-Session: https://claude.ai/code/session_01Dk6H9RfvcYnGTm5yuVgPYX
* Sell Max through Stripe and label personal subscriptions by their Price
A user-scoped subscription row now takes its plan (pro or max) from
its Price's lookup key, so a Billing Portal switch relabels the row on
the next webhook and the cmuxPlan mirror follows. Checkout accepts
plan=max (monthly only), an active Pro subscriber asking for Max is
sent to a dedicated portal configuration that lists Pro and Max, and
the catalog script provisions the Max product, its $200 price, and
that portal configuration. /api/billing/plan keeps planId at free|pro
for installed clients and adds subscriptionPlanId.
Claude-Session: https://claude.ai/code/session_01Dk6H9RfvcYnGTm5yuVgPYX
* Add the Max card and column to every pricing page
Public, in-app, and dashboard pricing show Max at $200/mo between Pro
and Team, the compare table grows a fifth column with a Largest Cloud
VM row, and the copy tests allow 32 GB and 64 GB only in Max copy.
Claude-Session: https://claude.ai/code/session_01Dk6H9RfvcYnGTm5yuVgPYX
* Show locked 32 GB and 64 GB sizes with a Max upgrade in the Mac app
The New Machine sheet keeps the ladder visible: sizes above the plan
ceiling are disabled rows that name Max, with an upgrade button that
opens checkout for plan=max. The native pricing screen gains the Max
card and column, VMClient decodes the locked sizes and the
vm_memory_requires_plan error, and the CLI size copy names Max.
Claude-Session: https://claude.ai/code/session_01Dk6H9RfvcYnGTm5yuVgPYX
* Test the Max checkout, portal switch, plan route, and memory gate; keep account.me compatible
account.me keeps planId at free|pro for the generated Swift enum and
adds subscriptionPlanId, with both checked-in OpenAPI specs
regenerated. The billing skill and the VM README describe the Max
catalog, the portal switch configuration, and the 24 GB ceiling.
Claude-Session: https://claude.ai/code/session_01Dk6H9RfvcYnGTm5yuVgPYX
* Add Max plan unit tests and record the live Stripe ids
Claude-Session: https://claude.ai/code/session_01Dk6H9RfvcYnGTm5yuVgPYX
* test: cover Max upgrades for Founder and Team accounts
* test: reject oversized copied machines before provisioning
* feat: enforce Max VM sizing and add authenticated CLI checkout
* fix: tighten Max size telemetry and workflow typing
* chore: complete Max localization and CLI help
* fix: show Max billing price in dashboard
* docs: describe VM resources per machine
* fix: keep Team entitlements scoped while honoring personal Max
* docs: clarify per-VM resource limits
* fix: remove duplicate dashboard plan binding
* fix: keep VM upgrade telemetry values type safe
* fix: correct Max resource copy in all pricing views
* fix: require an explicit CLI billing plan
* fix: update cloud client bootstrap after main merge
* fix: keep account plan decoding compatible with older servers
* feat: separate individual and business pricing sections
* feat: add Go plan and separate pricing categories
* test: cover Go billing-period runtime accounting
* feat: enforce Go runtime and saved-machine limits
* Add individual and team pricing audience switch
* test: cover Go provider caps and size upgrade targets
* fix: enforce provider runtime caps and preserve Cloud diagnostics
* fix: expose cloud panel failures to lifecycle extension
* test: cover pricing controls and billing review regressions
* test: use complete billing fixtures and native fork capabilities
* fix: simplify pricing controls and address billing review findings
* test: provide request headers in pricing renders
* fix: keep pricing controls aligned on mobile
* test: model request-time pricing render boundary
* fix: defer billing reads until a pricing request arrives
* test: preserve upgraded VMs during Go pause recovery
* test: model database queries with real promises
* fix: honor upgraded plans during pause recovery
* fix: refine Max copy and review test seams
* fix: keep shared package out of cmux test target
* Gate Go plan behind rollout flag
* test: require monthly-only purchase offers
* Make new Cloud subscriptions monthly only
* Fix ungrouped Cloud workspace destination defaults
* Align Bun test declaration with main
* Combine monthly billing with current VM resize limits
* Restore current VM resize limits after main merge
* Fix TabID lookup in pane focus index
* Fix pinned Ghostty open URL enum
* Fix indexed Cloud workspace reconciliation lookup
* Restore headless Cloud terminal provider methods
* Fix Cloud environment cleanup call
* Fix billing review contract and localized Go errors
* Center pricing audience switcher
* Gate pricing checkout behind sign-in
* Gate embedded pricing checkout behind sign-in
* Remove duplicate Cloud provider declarations
* Keep legacy subscription plan field optional
* Preserve current native localization catalog
* Restore pricing localization entries
* Fix plan-specific VM upgrade guidance
* Avoid unavailable Go downgrades
* Disable creation when every VM size is locked
* Align Cloud provider extensions with main
* Keep Go billing states and VM upgrade maps aligned
* Respect App Store billing gate after sign-in
* Coalesce new machine plan refreshes
* Fix Cloud provider access level for CI
* Apply Go rollout flag at every billing boundary
* Require secure native checkout URLs
* Fail closed on stale VM entitlements
* Preserve legacy VM size compatibility
* Fix billing portal complexity and VM paywall import
* test: cover checkout authentication and locked machine submissions
* fix: finish authenticated billing flow and repair native plan refresh
* test: separate snapshot ownership from legacy memory gating
* Fix native drag test window mock
* Align optional account plan schema
* Keep dynamic pricing account lookup explicit
* Show every plan in mixed VM size guidance
* Fix native drag hover point conversion
* Route Max upgrades through the billing portal
* Fix Max upgrade targets and dashboard scope
* Use highest plan in machine size upgrade CTA
* Preserve legacy VM shapes during plan checks
* Handle disabled Cloud machines in list errors
* Test unknown VM shapes and complete plan selection
* Complete main merge for pricing entitlements
* Align drag test with latest machine actions API
* Rename Tailscale Pairing to Mobile Pairing
* Update pairing label and search expectations for Mobile Pairing
* Rename Tailscale Pairing to Mobile Pairing throughout the UI
* test: cover targeted tmux compat read budget
* test: cover committed terminal pane geometry
* fix: commit portal-owned terminal geometry before rendering
* Fix iOS crash on duplicate WebSocket ping completion (#12787)
* test: reproduce duplicate URLSession ping completion crash
* fix: resume each WebSocket ping continuation only once
* test: tighten ping regression workflow setup
* test: restore portal refresh test extension
* Fix delayed build labels in iOS computer picker (#12786)
* test: cover picker labels before paired Mac load
* fix: show Mac build labels during picker startup
* refactor: make Mac label helper a free function
* refactor: isolate Mac label derivation
* refactor: inject Mac label resolver
* refactor: separate Mac label resolver
* fix: cache targeted tmux pane reads per connection
* fix: explain local workspace workaround for cloud drops
* fix: close committed geometry review gaps
* test: preserve image paste payloads with auxiliary URLs
* fix: prefer copied image payloads over auxiliary URLs
* ci: route the release delivery guard through the configured runner
* test: isolate App Store lane versions from release bumps
* test: exercise tmux commands against production polling limiter
* test: reproduce stale pane appearance reverting terminal themes
* fix: honor polling backpressure within the CLI request deadline
* fix: resolve terminal appearance from the live application
* test: recognize mapped pane resize actions in Dock routing audit
* test: make polling admission and protocol failure checks deterministic
* test: use a generic flag in cache round-trip fixtures
* test: await causal transport and dashboard events
* test: synchronize client config concurrency through request admission
* chore: keep transport extraction and test fixture focused
* test: cover drag payload priority and bracketed image delivery
* fix: preserve complete image payloads through terminal drop routing
* test: type mock implementations in Bun test declarations
* fix: keep portal geometry pending through viewport transitions
* test: reproduce light terminal appearance with font-only config
* test: use supported terminal accessibility query
* test: allow main-actor terminal startup during image delivery capture
* fix: preserve adaptive terminal colors with non-color settings
* test: verify terminal screen and PTY converge after portal changes
* test: await portal commits without starving the main actor
* test: cover geometry settlement after retry exhaustion
* fix: retain pending geometry until layout settles
* refactor: keep pasteboard context limited to file insertion
* test: preserve Finder originals when the pasteboard includes a TIFF preview
* fix: preserve backing files before decoding Finder paste previews
* fix: keep PTY resize independent from input writes
* test: await settled viewport geometry in portal regressions
* fix: apply TUI rustfmt before release (#12823)
* test: reject incomplete bundled SSH daemon assets
* Use PlanetScale for Cloud VM migrations and operator guidance (#12821)
* test: reproduce PlanetScale operator migration failure
* fix: use PlanetScale for Cloud VM operator migrations
* fix: bundle verified SSH daemons for unpublished builds
* chore: remove fixture trailing blank lines
* Add the cmux RC release channel (com.cmuxterm.app.rc) (#12777)
* Add the cmux RC release channel
Publish a third signed channel, cmux RC (com.cmuxterm.app.rc), from every
push to an rc/** branch through nightly.yml. The decide job resolves the
channel identity once (bundle id, app name, URL scheme, DMG prefix, release
tag, feed base, entitlements, icon) and every later job reads it, so nightly
and RC share one build, sign, notarize, delta, and publish path. RC ships to
the GitHub release `rc` with per-architecture DMGs and Sparkle feeds under
https://files.cmux.com/rc/, installs next to stable and nightly, and only
ever updates within its own feed, so a release candidate can be dogfooded
for days while cherry-picks respin it automatically.
Runtime: SocketPathVariant.rc with its own sockets and marker files, the
cmux-rc auth URL scheme, BuildFlavor.rc, RC-aware updater feed resolution and
manual-download recovery, Ghostty config release fallback, GUI launch
sentinel, WireGuard interface naming, iOS official-lane pairing, and the
hand-maintained mirrors in reload.sh, tests/cmux.py, and
start-cmux-profiling. Signing uses cmux.rc.entitlements plus a
com.cmuxterm.app.rc.tunnel system extension identity and the
APPLE_RC_*_PROVISIONING_PROFILE_BASE64 secrets. The release helper scripts
take the channel and asset prefix as parameters instead of assuming nightly.
* Ship RC without the WebAuthn browser entitlement until Apple approves it
The WebAuthn browser capability is an Apple-approved request. The
com.cmuxterm.app.rc App ID has had one pending since 2026-07-10, so the RC
profile cannot carry it yet. cmux.rc.entitlements no longer asks for it and
the profile check in nightly.yml follows the channel entitlements file, so a
channel that requests the entitlement still fails fast when its profile lacks
it. RC loses passkey sign-in in the embedded browser until the request is
approved; then the key returns to the entitlements and the check re-arms.
* Address review: RC tunnel path test, tag-push test, icon generator preflight
The RC tunnel test now derives its expected credential file names from the
nightly manager, so it asserts the isolation contract (own interface name,
never the stable private.key) instead of a spelled-out suffix. The tag-push
auth test follows the renamed channel release tag step and its
CHANNEL_RELEASE_TAG push ref. generate_rc_icon.py exits nonzero before
writing anything when a source icon is missing.
* iOS: make the keyboard button Liquid Glass by default
Use the native iOS 26 Liquid Glass button configuration for the terminal keyboard toggle. Existing actions, geometry, accessibility, and pre-iOS-26 styling remain unchanged.
* docs: localize adaptive terminal appearance in every web locale
* test: reproduce restored daemon closeout regressions
* fix: import workspace model for iOS release build (#12829)
* fix: close out restored daemon review findings
* chore: restore unrelated daemon test formatting
* test: cover signal state inherited by CLI exec children
Refs #12681. A restored agent launched through cmux restore starts with
SIGWINCH blocked, so it never sees a resize again. This test forks from a
cooperative-pool thread, hands the child to the CLI exec path, and reads
the signal mask and SIGWINCH disposition the child actually starts with.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* fix: exec restored agents with the default signal state
Fixes #12681. CLI commands run on Swift concurrency threads, which carry a
nearly full signal mask on macOS. execve hands the calling thread's mask to
the new image, so every agent that cmux restore launched (Codex, Claude
Code) started with SIGWINCH blocked: the kernel never delivered a resize,
the TUI kept its startup grid, and the first pane resize garbled it for
good. Fresh launches from a shell were unaffected, which is why a plain
codex in the same pane resized cleanly.
cliExecFailureErrno now restores an empty signal mask and default
dispositions for the signals the CLI itself may leave ignored (SIGPIPE,
SIGWINCH, SIGTTOU) before running the exec, and the restore and legacy
fork exec sites use it. The provider preflight child spawns with the same
default signal state through posix_spawn attributes.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* ci: verify PlanetScale access before migration (#12828)
* test: guard every CLI exec and spawn site for default signal state
The exec wrapper from bb2f6741d1 only protects the sites that call it.
This source-level check walks CLI/ and fails for any execve/execv/execvp
outside cliExecFailureErrno and any posix_spawn without
POSIX_SPAWN_SETSIGMASK. On the current tree it reports the two
`cmux restore` exec sites in CMUXCLI+RestoreExecution.swift and the Codex
Teams app-server spawn, which still hand children the Swift concurrency
thread's blocked signal mask (#12681).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* fix: exec restored agents through the signal-state reset wrapper
bb2f6741d1 routed the two `cmux fork` exec sites and the provider preflight
spawn through cliExecFailureErrno, but `cmux restore` execs the resumed agent
from CMUXCLI+RestoreExecution.swift, and both of its execve calls
(structured argv and the legacy `$SHELL -lc` form) still ran on the raw
Swift concurrency thread. Restored Codex and Claude Code sessions therefore
kept starting with SIGWINCH blocked and garbled on the first pane resize
(#12681), while forked sessions were already fixed.
Both restore sites now go through the wrapper, and the Codex Teams
app-server spawn sets POSIX_SPAWN_SETSIGMASK with an empty mask so it no
longer inherits the watcher thread's mask either. The source-level guard
test from the previous commit passes with every CLI exec and spawn site
covered.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* test: verify resize signals through actual CLI restore and fork
* Render pricing before subscription checks finish (#12836)
* Test pricing streaming and single current-plan actions
* Render pricing before account checks finish
* Read complete pricing shell in streaming tests
* test: verify portal settlement and presentation at resize end
* ci: pin and serialize Cloud VM migration source (#12839)
* fix: recover iOS Iroh runtime after sign-in (#12837)
* test: cover iOS Iroh endpoint readiness notification
* fix: keep iOS Iroh runtime alive through sign-in
* fix: require healthy iOS Iroh endpoint before dialing
* test: cover blocked iOS runtime shutdown during auth changes
* fix: let the endpoint supervisor retry binding during dial
* test: construct lifecycle fixture storage outside its actor
* test: bound workspace listing requests in tmux batch output
* fix: reuse tmux workspace snapshots and sanitize shell diagnostics
* Scope Cloud VM coderouter access to its team and account pool (#12771)
* test: reject mismatched VM coderouter teams and credentials
* fix: bind Cloud VM account access to immutable teams and model pools
* fix: defer coderouter authorization until a dashboard request arrives
* test: cover request rendering and a member without account permissions
* fix: keep dashboard params beneath suspense and update VM scope fixtures
* fix: preserve legacy writes during rollout and require VM resource ownership
* fix: bound migration work and harden isolated VM verification
* test: give upstream VM fixtures their resource team
* test: tighten VM scope review coverage
* test: complete scope identity and localized sharing checks
* test: SSH attach must not hang when the remote session can never become ready
Regression tests for https://github.com/manaflow-ai/cmux/issues/12813. They
model the issue's precondition (direct SSH and the ControlMaster probe
succeed) and fail on main at runtime:
- RemoteSessionReadinessParkingTests: a bootstrap that gives up must release
the `ssh-pty-attach --wait` already parked on it, an attach that arrives
afterwards must be refused at once, and a reverse relay or proxy that never
becomes ready must park the session in bounded time.
- SSHPTYAttachParkedSessionExitCodeTests: the structured parked code is
terminal however its detail is worded.
- SSHPTYAttachParkedSessionCLITests: the real CLI stops with the app's
actionable detail and keeps the remote session for Reconnect.
- RemoteSessionParkedReconnectTests: Reconnect after a session that never
provisioned the remote must start a replacement controller, a launching
attach must not repaint a parked session as connecting, and a waiting
attach must fail at once when the workspace cannot create a controller.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* fix: end SSH attach loudly when the remote session can never become ready
Fixes https://github.com/manaflow-ai/cmux/issues/12813.
`ssh-pty-attach --wait` parked on the workspace's remote session until the
daemon, reverse relay, and proxy were all ready, but nothing told it when the
session owner had already given up. Each attach timed out after 90s with a
generic "not ready", the wrapper labelled that "remote service is starting"
and re-attached, up to 20 times: ~40 minutes of a terminal sitting at the
login banner. Every wrapper attempt also repainted the workspace as
`connecting`, erasing the one actionable message in the sidebar, and a
Reconnect after such a session was refused forever.
The session state machine now owns readiness end to end:
- Parking is the single terminal transition (`parkSessionLocked`). It stops
the retry owners, publishes the suspended state, and releases every bridge
start parked on readiness with the same detail the sidebar shows. A start
that arrives while parked is refused at once instead of being parked.
- Every supervisor loop now reaches that transition. Bootstrap and
reachability already had budgets; the relay restart loop and the
escalate-and-rebootstrap cycle had none, so the hello-to-proxy-endpoint
seek gets a 60s deadline (injected clock, armed once per seek, cancelled on
readiness, stop, sleep, and re-arm).
- `workspace.remote.pty_bridge` answers a parked session with the structured
`remote_session_parked` code and the unsanitized, app-localized detail,
including the case where the workspace has no controller and cannot create
one. The CLI treats the code as terminal whatever the wording, prints the
detail, and keeps the remote session for Reconnect.
- A launching attach no longer repaints a parked session as connecting.
- A coordinator that never installed relay metadata has nothing to clean up,
so the ownership check's exit 64 is a completed transport cleanup rather
than a failure that blocks every later Reconnect. A cleanup that genuinely
fails now says why instead of leaving a bare error state.
- A persistent pane whose wrapper exits while the workspace tracks it as a
disconnected placeholder is now kept, with its session binding, like an
active one. Otherwise parking after a reconnect closed the panes and
orphaned their still-running remote shells (main does the same once the
wrapper's retry budget runs out).
- "No daemon for this platform / no manifest in this build" gets its own
message instead of "Could not prepare the remote daemon".
Two pure moves keep files inside their length budgets:
`userFacingRemoteDaemonBootstrapErrorMessage` and the relay port-binding
matchers moved to sibling extension files unchanged.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* Fix dropped socket-send bytes and GHOSTTY_BIN_DIR use-after-free (ghostty bump) (#12842)
* test: multi-KB surface.send_text must reach a slow PTY reader intact
A 5000-byte send into a raw-mode reader that drains 64 bytes every 30 ms
loses about 1.7 KB from the middle of the payload on the first burst per
terminal. Three rounds in fresh workspaces; each exercises the termio
write pool's first growth.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* ghostty: adopt upstream MemoryPool write path; fix GHOSTTY_BIN_DIR use-after-free
Bumps the fork to manaflow-ai/ghostty#223.
termio's SegmentedPool could hand a write request slot out again while it
was still linked in libxev's write queue, cutting the queue and silently
dropping every request behind it: multi-KB socket sends lost 1.6 to 1.8 KB
mid-payload, first burst per terminal, no error, no stall. The fork now
carries upstream e0ef934f7, which replaces the pool with a per-write
std.heap.MemoryPool record returned by the completion itself.
resolveGhosttyBin returned the env map's own GHOSTTY_BIN value and the
next env.put freed it, so GHOSTTY_BIN_DIR and the PATH suffix copied
freed memory. codex crashed at startup on the non-UTF-8 value.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* ghosttykit: pin checksum for ghostty 4a0e9e185
Built by https://github.com/manaflow-ai/cmux/actions/runs/35189431056.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
* Cloud: keep terminal creation targets and errors visible (#12478)
* fix cloud terminal observability and first replay redraw
* fix cloud terminal split placeholders and replay rendering
* split cloud mirror protocol handling from lifecycle
* fix pending Cloud pane cancellation fence
* fix use pinned Ghostty OSC8 action enum
* trim Ghostty compatibility change
* fix cloud mirror protocol access across files
* fix quote protocol source path in project
* remove duplicate cloud pane routing extension
* fix replay redraw log interpolation
* fix escaping cloud tree operation runner
* fix cross-file protocol state and test polling
* test: catch renderer claiming presentation before a frame
* fix: recover and diagnose blank terminal surfaces
* feat: show terminal render health in tree output
* fix: gate renderer probe draw-end recovery
* fix: log terminal render health transitions
* refactor: own terminal health overlay separately
* fix: keep render health overlay on main actor
* fix: expose render health within terminal module
* test: acknowledge deferred first presentation
* fix: harden renderer health lifecycle and callback tests
* fix: keep shell exit health through failed probes
* fix: keep health diagnostics inside terminal content
* test: remove app-target overlay test from package
* fix: reset renderer recovery on window visibility
* fix: preserve rendered health across window occlusion
* test: cover portal recovery episodes
* test: match tokened probe admission semantics
* remove obsolete redraw and trim changed files
* Restore headless Cloud terminal provider methods
* fix use public Bonsplit tab UUID in cloud layout
* Fix Cloud environment cleanup call
* fix Cloud file cleanup call
* fix Cloud workspace target helper call
* remove unneeded Cloud protocol extraction
* fix renderer callback test fixtures
* fix renderer health test callback lifecycle
* test: reproduce stale Cloud presentation acknowledgements
* fix: bind Cloud frame proof to pane and replay ownership
* style: keep merged source within file budgets
* fix: remove duplicate Cloud terminal IO methods
* test: cover repeated Cloud terminal projection opens
* fix: wire render health overlay into app target
* fix: keep Cloud error guidance consistent with redaction
* test: avoid nested Swift Testing require
* style: keep provider test within file budget
* test: split throwing Cloud fixture assertions
* test: evaluate mutable readiness gates before assertions
* test: exercise Cloud socket errors and correct hidden-pane assertions
* fix: reject stale explicit Cloud destinations
* fix: preserve Cloud catalog error details
* test: anchor Cloud projections to fixture workspace
* fix: validate explicit Cloud workspace ownership
* fix: make Cloud readiness layer independent
* fix: allow presentation callback sequence updates
* fix: keep Cloud mirror focus on its own panel
* fix: return Cloud focus target decision
* fix: hand explicit Cloud opens keyboard focus
* fix: validate Cloud panes within explicit workspace
* fix: remove duplicate provider declarations after main merge
* fix: align cloud row rendering with main
* fix: restore cloud workspace rename helper
* fix: recover cloud placement for terminal splits
* fix: restore cloud close terminal source after main merge
* fix: reconcile latest main build sources
* fix: link render health overlay with app target
* fix: preserve provider helpers and test wiring after merge
* test: reject false Cloud snapshot conflicts after tab close
* fix: normalize omitted Cloud lifecycle fields
* fix: localize Cloud placement failure
* fix: place Cloud creation errors above portal terminals
* fix: host Cloud failure card above portal layer
* fix: drop superseded renderer proof source
* fix: remove duplicate pending creation helpers after main merge
* fix: use shared Cloud graph validation after main migration
* test: keep Cloud failure cards within their visible workspace
* fix: scope native Cloud errors to visible workspace geometry
* chore: deduplicate renderer overlay group reference
* chore: remove duplicate renderer overlay group entry
* test: cover Cloud surface targets in another window
* fix: resolve Cloud surface targets through their live owner
* test: compare Cloud graph rows independently of wire order
* fix: compare Cloud resource graphs by stable identity
* fix: ignore Cloud session envelope in revision comparison
* fix: fail closed when Cloud terminal routing is unavailable
* fix cloud retry actions and preserve layout intent keys
* test: keep Cloud reconnect cards within narrow panes
* fix: fit Cloud reconnect cards to their pane width
* fix cloud action closure type
* fix cloud action task closure capture
* fix: restore pairing deadline dropped by main merge
* test: locate Cloud card buttons by accessibility identity
* Fix Cloud test imports and nested Swift Testing macro
* test: import the owning module for remote workspace configuration
* test: cover retained Cloud ownership and current recovery behavior
* fix: retain Cloud routing while the provider graph is unavailable
---------
Co-authored-by: austinpower1258 <austinwang115@gmail.com>
* Fix SSH PTY terminal ownership and reject mismatched daemons (#12726)
* test(ssh): cover PTY attach terminal mode boundaries
* fix(ssh): own and restore PTY mode through validated attaches
* test(ssh): include daemon identity in bridge endpoint fixtures
* test(ssh): exercise current attach lifecycle and async cleanup contracts
* test(ssh): respect retry wrapper timeout presentation
* fix(ssh): preserve lifecycle on output failure
* test: repair cloud surface suite compilation after main merge
* test(ssh): cover cancelled output and pre-admission reconnect cleanup
* fix(ssh): make PTY cancellation and input restoration authoritative
* test(ssh): preserve established lifecycle on admission rejection
* fix(ssh): retain established lifecycle until reconciliation
* docs(ssh): keep lifecycle invariants within CLI file budget
* test(ssh): cover quit-signal terminal cleanup
* fix(ssh): restore terminal state when reattach receives SIGQUIT
* test(ssh): tolerate bridge peer closure during cancellation
* test(ssh): wait for output backpressure before cancellation
* test(ssh): observe stalled output through readable pipe state
* test: align pairing coverage with current model API
* Let the nightly universal build fan out again (#12848)
xcodebuild -jobs 1 (#12704) serialized the two whole-module compiles of
the cmux target (about 10 and 16 minutes), which miss the compilation
cache on every push because every push changes the module. The warm
build step went from 21 minutes to 31-40 and a cold build no longer fit
the 45 minute budget: main runs 35179030871 and 35182663752 restored no
cache and were cancelled mid-compile. The diagnostics wrapper does not
need a serial build; PR 12704 recorded 95% free memory on the host.
Drop the cap, and give build-nightly-app and refresh-compilation-cache
a 90 minute budget so a cold build (per-branch Blacksmith cache scope,
or main's own entry evicted) still completes and re-saves the cache.
* Investigate macOS 27 native browser hover (#12683)
* test: cover browser hover popover layout on macOS 27
* fix(browser): detect real inspector companions before pinning
* test(browser): exercise native hover with XCUITest
* test(browser): fix native hover test compile
* test(browser): activate app before native hover setup
* test(browser): prime native hover main thread
* test(browser): use legacy activation readiness probe
* test(browser): seed native hover fixture at launch
* test(browser): find native webview through accessibility tree
* test(browser): require native hover entry exit and painted feedback
* test(browser): reproduce native macOS 27 hover with window coordinates
* test(browser): require overlays inside the window content hierarchy
* fix(browser): keep native browser hosting inside window content
* test(browser): tighten native hover e2e coverage
* test(browser): reject stale file drag hover capture
* fix(browser): ignore stale file drags during hover
* test(browser): reproduce hover with stale Finder drag data
* fix(browser): traverse pane drag routing ancestors
* test(browser): use live drop destinations and deferred repaint assertions
* fix(browser): restore physical slot ownership on repeated context updates
* First RC build fixes: cold-cache build budget, WebAuthn check follows the channel (#12840)
* Give the nightly app build a cold-cache budget
The Blacksmith cache is scoped per branch, so the first build of a new
rc/** branch restores neither the Xcode compilation cache nor the SwiftPM
cache and exceeds the 45 minute job budget that fits a warm main build
(rc/v0.65.0 run 35172632556 was cancelled mid-compile). Raise the
build-nightly-app job to 90 minutes.
* Assert the WebAuthn entitlement only for channels that request it
sign-cmux-bundle.sh required every signed app to carry the web-browser
public-key-credential entitlement. cmux.rc.entitlements omits it while the
RC App ID's capability request is pending at Apple, which failed the first
RC sign jobs (run 35180389918). The check now follows the channel's
entitlements file, so stable and nightly keep the hard requirement.
* Give the scheduled cache refresh the cold budget too
The refresh-compilation-cache job runs cold by design and shares the 45
minute budget that only fits a warm build; scheduled run 35134963192
was cancelled mid-compile. main also loses its own entry from the
Blacksmith store (run 35179030871 restored nothing 4.5 hours after run
35159407931 saved it), so both cold paths get 90 minutes.
* test: wait for the parking block before reading released waiters
Parking publishes `.suspended` and then releases its waiters inside one
block on the coordinator queue. The relay test parks from the deadline's
`queue.async`, so observing the publication did not guarantee that block
had finished; a fast CI runner read the waiter slot between the two
statements (run 35189697709). A `queue.sync {}` barrier, the package's
idiom for this, makes the read deterministic. 15/15 consecutive passes.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* fix: scope the readiness deadline to sessions that bootstrap over SSH
A managed Cloud VM session (`skipDaemonBootstrap`) has no relay, and its
proxy broker legitimately keeps redialing while the machine wakes or its
endpoint is re-minted, which can outlast the 60s deadline. Parking those
would change Cloud VM behavior, which is outside #12813. The deadline now
arms only for the SSH bootstrap flow the issue is about.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* ghostty: targeted upstream picks (input encoding, erase/scroll state, termio lifetime) (#12849)
* ghostty: targeted upstream picks (input encoding, erase/scroll state, termio lifetime)
Bumps the fork to manaflow-ai/ghostty#224: seventeen upstream commits
selected for the reported stray-escape, Ctrl-J, and garbled-line symptoms.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* ghosttykit: pin checksum for ghostty 8718162b0
Built by https://github.com/manaflow-ai/cmux/actions/runs/35190180209.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
* fix: report a rejected ControlMaster adoption to a waiting attach
`configureRemoteConnection` fails a rejected ControlMaster adoption before it
records any configuration or controller state; only the presented state says
`.error`. The no-controller verdict required a configuration and a parked
*controller* state, so an attach in that situation still waited out its 90s
controller deadline and rejoined the wrapper's retry loop. The verdict now
also accepts a presented `.error` with no controller and no transition in
flight, and falls back to the presented detail.
The generic fallback sentence no longer takes a target, because this state
can exist without a configuration to name one (all nine locales updated).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* Revert "ghostty: targeted upstream picks (input encoding, erase/scroll state, termio lifetime) (#12849)" (#12852)
This reverts commit 3bdfaaa86d019ef9052ae9fbcd92c2f9cd79d4f1.
* docs: record parked remote sessions and the remote_session_parked contract
Adds the bounded-readiness behavior to the spec's error-surfacing list and
documents the new workspace.remote.pty_bridge error code, including the rule
that clients classify on the code and show the message verbatim.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* fix: let an explicit PTY cleanup outrank the parked verdict
Review feedback on #12851. The parked check in the bridge-start path runs
before the broker's lifecycle check, so an attach for a generation the user
had already closed got `remote_session_parked` instead of
`pty_lifecycle_closed`. The CLI then preserved a lifecycle it should have
reconciled into a clean exit, and Reconnect would have reattached a pane the
user meant to end. On main such an attach ends cleanly at its first failure.
The session owner now applies the precedence itself: a bridge start that
meets a parked session consults the broker's lifecycle registry (no daemon
needed) and reports an explicit cleanup through the existing
`pty_lifecycle_closed` path, both for new requests and for waiters released
by parking. Doing it in the CLI instead, as suggested, would have re-entered
the wrapper's retry loop: while parked, reconciliation's session listing
fails with a retryable error.
Also drops the two measured-duration assertions from the tests. The parked
detail and the `remote_session_parked` code already prove the timeout and
controller-deadline paths were not taken. Fixtures move to a sibling file to
keep the suite inside the file-length budget.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* test: a ControlMaster reap must not repaint a parked session
A parked session has torn its transport down, but the broker's reap
observer outlives that transport. When the idle shared master is reaped
later, handleSharedControlMasterReapLocked publishes .reconnecting while
scheduleReconnectLocked refuses to schedule anything for a parked
session, so the workspace is stranded in "reconnecting" without its
verdict. Red on this commit:
Expectation failed: (host.publishedStates.last → .reconnecting) == .suspended
The recording host gains an ordered publication history so the test can
assert on what was published after the park, not only await the park.
Refs https://github.com/manaflow-ai/cmux/issues/12813
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* fix: keep a parked session parked when its ControlMaster is reaped
The reap observer belongs to the connection broker and outlives the
transport a parked session tore down. Its handler reset the transport
and published .reconnecting, but scheduleReconnectLocked refuses to
schedule a retry for a parked session, so the workspace lost its
actionable verdict and sat in "reconnecting" with nothing driving it.
A readiness-timeout park makes this likely in practice: it releases the
relay forward, the idle shared master expires, and the reap follows.
The handler still records the event, then leaves a parked session
alone. Skipping the transport reset is safe because every exit from the
parked state resets the transport itself: resetReconnectPolicyAndReconnect
(wake, re-arm) calls resetTransportForReconnectLocked before scheduling,
and a user Reconnect replaces the coordinator.
Refs https://github.com/manaflow-ai/cmux/issues/12813
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* fix(l10n): name the Reconnect button as each locale labels it
The parked-session messages tell the user to use Reconnect, but four
locales named the action differently from sidebar.remote.reconnect.button:
German (Wieder verbinden), Arabic, Traditional Chinese, and Korean. The
messages now quote the button's actual label. German "wurde nicht bereit"
becomes the idiomatic "ist nicht bereit geworden".
Only the four remoteSession.parked.* entries added by this branch change.
Refs https://github.com/manaflow-ai/cmux/issues/12813
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* test: restore pairing preparation deadline coverage (#12850)
#12799 merged this test while its model change was lost in a merge, which
broke the cmuxTests target on main for eight hours. #12478 restored
MobilePairingModel(preparationClock:preparationTimeout:) and #12726 deleted
the test to make main compile again. The API is back, so the deadline,
its cancellation, and recovery are covered again.
* test: bound tmux-compat backpressure checks by causality, not wall-clock windows
The deadline case gave the CLI a 150 ms budget with a 20 ms hint and required
at least one retry to fit inside it, and the permanent-error cases ran under a
100 ms budget. Both can fail a correct CLI on a loaded runner, which
.github/review-bot-rules/test-determinism.md rules out: a deadline may bound
only the failure path.
Split the deadline case into three load-independent checks:
- rejected once, then success: exactly two identical requests on one connection
- hint longer than the whole deadline: fails at once with a single request
- permanently limited: at most three requests fit in one total 1 s deadline
Permanent-error cases now use a generous deadline; they still assert exactly
one request, so a CLI that wrongly retried is caught either way.
Verified green against this branch's CLI and red against the released
0.64.24 (f5da007dd) CLI, which fails with the reported
"rate_limited: Polling rate limited for this connection".
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* feat: add prefix shortcuts for smart panes and resizing
Adds tmux-style Ctrl-b fallbacks for smart pane creation and split resizing, with docs and behavior coverage.
* test: order renderer windows before presentation setup
(cherry picked from commit 0209dbc750ff8143b28aa03a096bd236f7c4b9ec)
* test: align renderer fixtures with native callback lifecycle
(cherry picked from commit e88fc7e289a5c648fd6b00a6ea33466dc0aaec68)
* test: keep renderer presentation suite within budget
(cherry picked from commit b3925dc3ef84b8430922cbb9d4aadb7e4f5ec613)
* test: sync the CLI help contract with the shipped vm sizes and Cloud guide
tests/test_cli_contract_help.py has been failing on main, which stops the
set -e "Run CLI no-socket regressions" step at its second command:
- docs/cli-contract.md still advertised `--size <20g>` for `cmux vm run` and
`cmux vm route`. #12415 replaced the 20g plan machine with the 4g/8g/16g/24g
presets and changed the help text to `<8g>` without updating the contract.
- The Cloud guide probe expected the contiguous text
`google-chrome-stable --remote-debugging-port=9222`, but the guide added in
the same change (#12468) launches Chrome with `--no-first-run
--remote-debugging-address=127.0.0.1` ahead of the port. Pin the guide's
real text, which also keeps the loopback-only DevTools binding under contract.
The CLI is the source of truth in both cases; no CLI behavior changes.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* test: keep exec-based transfer progress coverage to pull
`cmux vm push` moved to private SCP in 5f0ce77cab and now opens with
`vm.scp_info`, which this test's fake `vm.exec` socket rejects, so its four
push cases fail on main ("Unexpected method: vm.scp_info") and stop the set -e
"Run CLI no-socket regressions" step.
Push is covered where it can be exercised for real: tests/test_vm_scp.py runs
OpenSSH and SFTP against an isolated local SSH server and is driven from
cmuxTests/CLIVMTransferTests.swift. Pull still goes through `vm.exec`, so this
test keeps verifying it.
This is the tests/test_cli_vm_transfer_progress.py half of f9f5148f69 from
#12759; the other half extends test_vm_scp.py on top of that PR's feature work
and lands with it.
Co-authored-by: Lawrence Chen <54008264+lawrencecchen@users.noreply.github.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* fix: clear the Swift warnings that put main over its warning budget
tests-build-and-lag fails on main with 23 cmux-owned warnings in 9 buckets that
have no allowance in .github/swift-warning-budget.tsv. Fix them at the source
rather than raising the budget. No behavior changes.
- CloudTreeNodeActions: restore `@discardableResult` on the local `run`, which
#12478 dropped while reformatting it. All 15 call sites are fire-and-forget.
- SurfaceCatalog default arguments (5 sites): a default-argument expression is
not MainActor-isolated, so `catalog: SurfaceCatalog = .shared` is a Swift 6
error. Take `SurfaceCatalog? = nil` and resolve `.shared` inside the
MainActor body, the idiom WorkspaceSurfaceResourceDrop already uses.
Callers that pass a catalog and callers that omit it are unaffected.
- CloudWorkspaceLayoutTranslator: `??` was boxing an optional dictionary into a
non-optional `Any`. Type the fallback as `Any?`; `build` casts to
`[String: Any]`, which fails identically for both, so parsing is unchanged.
- CmuxTuiSurfaceProviders: parenthesize a trailing closure inside `for ... where`.
- cmux ssh-pty-attach: `var decoded` is never mutated.
Verified with a fleet build that recompiled all nine files: none of these
warnings remain and scripts/swift_warning_budget.py reports no bucket over
budget.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* test: let the custom-path re-entry fixture answer inject-settings
#8537 made the Claude wrapper build its hook settings from
`cmux hooks claude inject-settings`, falling back to a minimal
PreToolUse/PermissionRequest block when that output is missing or fails
validation. It taught two scenarios' fake `cmux` to answer inject-settings, but
not test_custom_path_reentry_converges_to_one_settings_block.
That scenario's fake printed nothing, so the wrapper correctly fell back and the
test failed with "issue #10230 emitted malformed hooks structure" on every run
since, locally and on CI, where it stops the set -e "Run CLI no-socket
regressions" step. Bisected: passes at c006e64ae3, fails at fbcdd8dc71.
Give the fixture the same inject-settings handler and generated settings as the
other two scenarios, so it again asserts what it is for: one re-entry converges
to a single hook block (1 SessionStart, 3 Stop). No wrapper change.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* test: expect the Campfire extension's queued hook delivery
#8537 moved extension lifecycle hooks to bounded queued delivery, so the
generated Campfire extension spawns `cmux hooks enqueue campfire <event>`
(CLI/CMUXCLI+CampfireExtension.swift), like the Amp, OMP and OpenCode
extensions. tests/test_omp_extension_install.py was updated for that;
this test still expected `hooks campfire <event>` and has failed since with
"lifecycle hooks did not run serially", although the logged order was serial.
Expect the enqueue form in all ten places. The serial-order, payload, host-role
and session-persistence assertions are unchanged.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* chore: match #12759's text for two CI fixes so the branches merge cleanly
#12759 already carries equivalent fixes for the layout-translator coercion
warning (7ba7f62d2e) and the Cloud guide help probe (1c36d58119). Mine changed
the same lines with different text, which would conflict when either lands.
Adopt that PR's exact text for both. Behavior is identical: the translator
still picks the bare node when `root` is absent, and the help probe now checks
`google-chrome-stable` and `--remote-debugging-port=9222` as separate needles
rather than one contiguous string.
With this, every file both branches fix is byte-identical between them.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* Update app-host fixtures for current remote and group behavior
(cherry picked from commit 25a4f621f2a535a6d03e8fd10fb4955e0fa0c100)
* Fix app-host fixture contracts
(cherry picked from commit 1645b85d268ee1bbaf5c8b1bcf3796de8b700fdd)
* Align Cloud fixtures with current projection contracts
(cherry picked from commit 732a920f4a75f469126e87ad60a95b3724917ff2)
* test: keep Cloud fixture updates within source budgets
(cherry picked from commit eb65cbf895b681f85365f8cdf71c3b97ad112895)
* Stabilize portal visibility test lifecycle fixtures
(cherry picked from commit 32f7528fad9bdd32e1c9708a8bfddc7da63c8aec)
* test: fit visibility lifecycle fixture budget
(cherry picked from commit 4282edc0d085a988d7b9e2b7077d60376b632fbc)
* fix: import terminal surface in visibility fixtures
(cherry picked from commit 8b9d2b98013de31db1831d0ac997fb50c7f5b9f8)
* test: preserve visibility fixture budget after import
(cherry picked from commit 8959f279a185071109f461062a2598074be2082e)
* Authorize portal test surfaces through isolated workspaces
(cherry picked from commit f2c779f792be9be76328290c7ddac07428c2e12a)
* Exercise workspace reveal through noninteractive layout settlement
(cherry picked from commit 0b9e38fe2a8bb2bfd278562beb5a00a332da732b)
* chore: keep CloudTreeNodeActions within its file length budget
Restoring `@discardableResult` on its own line took the file to 515 lines
against a tracked budget of 514. Put it beside `@MainActor` instead.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* Add v0.64.25 changelog, highlights, and iOS pairing translations
Changelog and changelog-media entries cover the stable fixes since v0.64.24.
The 11 mobile.whatsNew.pairing.* keys added by #12316 shipped English-only in
both iOS catalogs; translate them into de, fr, ar, es, zh-Hant, zh-Hans, ko,
and ja with scripts/localization_catalog.py merge.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* Bump version to 0.64.25
Build 106, not 105: the rc feed already serves com.cmuxterm.app 0.64.25 (105)
built from rc/v0.64.25, and bump-version.sh only checks the stable appcast
(104). Reusing 105 from a different source tree would give Sparkle two
binaries with one build number.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* Show pane-centered Cloud terminal failures with useful diagnostics
Show one compact Cloud terminal error inside its owning pane, with a square 1 px border, no shadow, Retry, and contextual Copy Error. Preserve safe failure categories and operation traces, and clean up every classified cancellation consistently.
Verified the default card in a tagged app, all 22 focused Cloud tests, and the cancellation regression before and after the fix.
https://github.com/manaflow-ai/cmux/pull/12609
* Fix idle Cloud SCP watches and report local transfer failures (#12759)
* test: close idle control connections during SCP watch
* test: require signed-in Cloud reporting for CLI transfer failures
* fix: scope SCP control sockets to each request and report local failures
* refactor: isolate SCP transport and diagnostic socket helpers
* docs: explain SCP connection ownership and error reporting
* test: reject colliding Xcode project object IDs
* fix: enforce unique Xcode project object identities
* fix: complete pairing message locale coverage
* test: recognize mapped pane resize actions in Dock routing audit
* test: isolate App Store lane versions from release bumps
* ci: route registry verification through the shared Linux runner setting
* docs: correct Cloud SCP contract and document failure reports
* test: use generic flag data in the client config cache fixture
* fix: use the exported child terminal identity resolver
* docs: describe the SCP transport in vm push help
* style: apply formatter output to terminal identity repair
* test: await causal transport and dashboard events
* test: synchronize concurrent config requests with fetch admission
* test: establish a real WireGuard peer before asserting hub readiness
* test: retain the supported notify compatibility alias
* fix: keep SurfaceCatalog defaults actor-safe
* fix: resolve remaining Cloud compiler warnings
* Update app-host fixtures for current remote and group behavior
* test: order renderer windows before presentation setup
* Fix app-host fixture contracts
* test: align renderer fixtures with native callback lifecycle
* test: keep renderer presentation suite within budget
* Stabilize portal visibility test lifecycle fixtures
* test: fit visibility lifecycle fixture budget
* Align Cloud fixtures with current projection contracts
* test: keep Cloud fixture updates within source budgets
* fix: import terminal surface in visibility fixtures
* test: preserve visibility fixture budget after import
* Authorize portal test surfaces through isolated workspaces
* fix: keep surface ownership catalog actor-safe
* test: align pairing transition coverage with current model API
* fix: restore pairing preparation recovery lost in upstream merge
* test: split nested Cloud assertion to unblock hosted suites
* test: import Cloud fixture remote configuration from its owning module
* fix: keep decoded SSH command immutable
* Revert "test: align pairing transition coverage with current model API"
This reverts commit ff4207ef98b6f5abf334d8b52b04d46ca35a30f5.
* test: distinguish cleanup grant failure from invalid responses
* fix: complete Cloud transfer diagnostics review fixes
* test: align Cloud help contract with current sizes and browser flags
* Exercise workspace reveal through noninteractive layout settlement
* test: verify push output through the current SSH transport
* fix: preserve cloud navigation task result
* fix: pass cloud navigation runner directly
* fix: register cloud failure card window
---------
Co-authored-by: austinpower1258 <austinwang115@gmail.com>
* Classify and back off Cloud usage failures (#12869)
* fix: classify and back off cloud usage failures
* fix: make usage backoff helper sendable
* Add iOS terminal latency observability (#12816)
* Add iOS terminal latency observability
* Avoid terminal latency telemetry contention
* Test terminal markers and presentation timing boundaries
* Measure accepted input markers through real terminal presentation
* Import shared terminal input framing in irx host
* Record presentation only after render gate completion
* Test input bursts retain earlier waiting latency
* Retain earlier input waits when output acknowledges a burst
* Test background exclusion and sustained render incident limits
* Exclude app suspension from terminal latency measurements
* Ignore cached redraws without an observed output receipt
* Test render incidents remain separate from transport outages
* Keep rendering incidents out of connection outage escalation
* Document terminal latency boundaries and operating controls
* Test active-only latency window durations across suspension
* Exclude inactive segments from terminal latency window duration
* Simplify terminal telemetry validation
* Preserve legacy terminal input compatibility
* Tie terminal latency to marked inputs and GPU presentation
* Import mobile input capability in explicit sender
* Exclude viewport policy from latency metrics
* Centralize mobile input observation
* Fix presentation callback type inference
* Bound marked input buffers and consume callbacks
* Return verified replay enqueue result
* Preserve coalesced IRX input buffering
* Keep input call compatible with Swift 6.0
* Exclude theme deliveries from latency metrics
* test: reject custom relay advice for a managed relay TLS failure
* fix: distinguish relay transport errors from configuration errors
* ci: cover relay connection advice with system trust checks
* fix: keep direct endpoint timeout diagnostics generic
* test: tolerate verified keychain cleanup timeout
* fix: preserve relay diagnosis during activation retry
---------
Co-authored-by: Abdulaziz Albahar <67667005+azooz2003-bit@users.noreply.github.com>
Co-authored-by: Lawrence Chen <54008264+lawrencecchen@users.noreply.github.com>
Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
…aflow-ai#12906) * test: cover resumable release publication and feed ordering * fix: reconcile release uploads before publishing update feeds * fix: keep stable releases draft until every upload is verified * test: run catalog structure checks on every catalog change * fix: remove shadowed duplicate pairing error localization * fix: preserve published assets during replacement uploads * fix: restore release aliases after ambiguous renames * fix: materialize replacement upload files * test: synchronize concurrent release upload coverage * test: drive analytics timeout from diagnostic timestamps * fix: restore main CI compile and deterministic timeout test * fix: use GitHub-safe release staging names * fix: remove unused connected binding from environment delivery * fix: key Cloud capability probes by client URL * fix: hash release assets when GitHub omits digests * fix: resolve nullable release digests before asset renames * test: keep a deterministic timeout margin
Adds resource and tmux-style shorthands through the canonical public parser, with literal argument protection, docs, localization, behavior coverage, and exact binary preflight.
Exact-head local autoreview was clean. Required hosted checks passed, including semantic macOS integration, CLI pipe regressions, web tests/build/validation, agent notification tests, Socket, CLA, and complexity checks.
Adds atomic tab moves into existing, empty, or new workspaces through drag and context menus, preserves terminal identity and saved ownership, negotiates support with older owners, and adds generated SDK coverage.
* Encrypt push notifications and reply relays end to end * Register the iOS notification encryption key * Fix public peer key store API * Export crypto framework types from push package * Fix encrypted payload encoding * Fix reply inbox decryption compile errors * Complete end-to-end device notification encryption * Preserve legacy push clients during encryption rollout * Keep push identity and legacy clients compatible * Fix reply key routing and legacy token lookup * Harden notification extension and recipient delivery * Allow encrypted push payloads without plaintext fields * Harden encrypted push delivery compatibility * Map encrypted dismissals to legacy notification IDs * Preserve push key exchange compatibility * Bound encrypted reply failures and peer keys * Enforce authenticated push recipient keys * Complete push target and lifecycle compatibility * Preserve push registration compatibility * Restore push account identity with auth session * Preserve encrypted notification collapse identity * Drain legacy parked replies during encryption rollout * Harden push compatibility lifecycle * Restore legacy reply decoder keys * Prune stale reply decrypt state * Use configured keychain group for push decrypt * Keep encrypted push and reply data fresh * Separate legacy and E2E notification transports * Keep phone push package compatible with iOS 17 * Repair E2E notification merge blockers * Harden notification migration recovery paths * Fix decrypt outcome switch exhaustiveness * Fail closed when push encryption is unavailable * Complete strict push key setup * Fix phone push retry task visibility * Fix push route type errors * Reencrypt queued pushes after key rotation * Preserve legacy push registration path * Reject cross-account push registration takeover * Fix push requeue control flow * Wire phone push package and bound key retries * Bound push recipient discovery * Retain pushes during recipient discovery * Fix pending push queue admission * Reject malformed encrypted push tuples * Retry transient push key discovery * Fix secure push recovery and authenticated payload merging * test: cover push token revocation during delivery * fix: revoke push tokens on auth loss * fix: serialize push revocation with APNs delivery * refactor: split push delivery preparation * fix: fence stale push registrations after sign-out * fix: coordinate push revocation without holding db locks * fix: retain bounded push revocation tombstones * fix: fail closed without stable push session * fix: preserve legacy push registration * fix: bind push revocation to installation * test: provide stable push session identity * fix: clean revoked push rows after delivery * fix: reap revoked rows after lease expiry
…#12826) Korean filenames that macOS returns decomposed (NFD jamo) rendered as unrelated symbols, e.g. 무제.md as ☘㎍.md, whenever the selected font has precomposed Hangul syllables but no jamo glyphs (D2Coding and most Hangul fonts). Regression from manaflow-ai/ghostty#185, shipped in v0.64.23 through v0.64.25: font selection used the composed syllable while shaping still received the jamo, so CoreText silently substituted another font and its glyph IDs were drawn with the selected face. The Ghostty fix (manaflow-ai/ghostty#221, merged to fork main as 3869e81a0; branch tip 370f08cf1) reached main through manaflow-ai#12669, whose pin 35ae29b7c2 contains that merge with an identical src/font tree. RunIterator.resolveFontInfo now carries the composed syllable together with the font index it resolved, so selection and shaping use one spelling. Terminal cells, copy bytes and cell widths are unchanged. This commit records it: docs/ghostty-fork.md describes the 35ae29b7c2 pin's lineage (the doc still named abd40f6e4) and the Hangul change with its upstream merge conflict note, and scripts/ghosttykit-checksums.txt keeps the checksum of the published 370f08cf1 archive (sha256 ec53b8992b466ecd9cc87b42754188fe504898ff0b139f54b3eef1dc6a441233, build-ghosttykit run 35197286294), the build used for the runtime proof. Also route .github/workflows/relay-tls.yml (manaflow-ai#12723) through the runner repo variables: diagnostic-presentation runs on vars.MACOS_RUNNER_15 with the Blacksmith fallback, and system-keychain keeps the GitHub-hosted macos-14 image with the runner guard's github-hosted-required marker (the probe mutates the system keychain and needs Xcode 16.2 on an isolated ephemeral image). The bare labels failed "Validate macOS runner guards" for every PR. Verified: Ghostty Hangul tests 78/78 (CoreText) and 77/77 (HarfBuzz) at 370f08cf1, red with the fix reverted under both shapers; before/after in the real tagged app for both configurations in the report, with stored text byte-identical. Not verified on macOS 27 itself. Fixes manaflow-ai#12753 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* Fix production notification extension bundle identity * Run emergency App Store upload outside production queue * Use valid xcconfig comments * Use automatic signing for notification extension release * Run automatic signing retry separately * Provision notification extension for App Store export * Pass ASC credentials to extension profile lookup * Restore App Store workflow main branch guard * Resolve App Store extension profile in cloud lane * Scope extension profile mapping to App Store lane * Handle existing App Store extension profiles * Validate App Store extension profile provenance * Validate cloud profiles through shared helper * Prepare extension profile before App Store archive
Merge authorized by the user after required checks passed.
* test: cover checklist hover seeding * fix: keep checklist remove button visible under pointer * test: require visible checklist remove glyph * fix: render checklist remove button as visible x * test: cover legacy checklist remove glyph * fix: render legacy checklist remove button as x * test: preserve filled symbol cutouts in checklist rendering * fix: preserve monochrome cutouts and restore circled checklist X
A tagged reload terminates the running app after a successful build so macOS launches the fresh binary on cmd-click or --launch. That is right for a reload, and wrong for a build that is not replacing the session in front of you: a warm rebuild to check that the tree still compiles, a build driven by an external cache/build wrapper, or an agent building while the developer is using the previous build. CMUX_RELOAD_KEEP_RUNNING=1 skips only that termination. Everything else is unchanged, and the default is unchanged, so --launch and ordinary reloads keep their current behaviour. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This was referenced Sep 18, 2026
With CMUX_RELOAD_KEEP_RUNNING=1 the running instance still holds the tag socket lock, so wait_for_tag_socket_lock_release blocked for its full 10 s and reported a teardown timeout that never was one. Detect the kept live instance, skip the wait, and report the real reason publication was skipped. --launch needs the new binary, so it ignores the variable and terminates as before. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Owner
Author
|
Opened upstream as manaflow-ai#12962. This one targeted fork |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A tagged reload terminates the running app after a successful build, so macOS launches the fresh binary on cmd-click or
--launch. That is right for a reload and wrong for a build that is not replacing the session in front of you:CMUX_RELOAD_KEEP_RUNNING=1skips only that termination. The default is unchanged, so--launchand ordinary reloads behave exactly as before.Three lines, one of them documentation. I have been running this locally on every build for the last week — the tagged dev app stays up while a rebuild runs behind it.
🤖 Generated with Claude Code