Skip to content

Add macOS 26 (Tahoe) compat tests - #1590

Merged
lawrencecchen merged 2 commits into
mainfrom
fix-zig-macos26-linker
Mar 17, 2026
Merged

lawrencecchen merged 2 commits into
mainfrom
fix-zig-macos26-linker

Conversation

@lawrencecchen

@lawrencecchen lawrencecchen commented Mar 17, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Adds macOS 26 (Tahoe) to the compat test matrix on WarpBuild
  • Skips the zig CLI helper build on macOS 26 (zig 0.15.2's MachO linker can't resolve libSystem against the macOS 26 SDK)
  • CMUX_SKIP_ZIG_BUILD=1 creates a stub binary so the Xcode Run Script phase passes, unit tests run normally
  • Smoke test skipped on macOS 26 (needs real CLI helper + screen lock blocks app activation)

Test plan

  • macOS 15 compat passes with smoke test (no change)
  • macOS 26 compat passes unit tests with zig build skipped
  • Main CI unaffected

🤖 Generated with Claude Code


Summary by cubic

Add macOS 26 (Tahoe) to the CI compat matrix and skip the zig CLI helper build via CMUX_SKIP_ZIG_BUILD=1 to work around a zig 0.15.2 MachO linker issue. When skipped, an executable stub is created; the macOS 26 smoke test is disabled; macOS 15 is unchanged.

  • New Features
    • CI: add warp-macos-26-arm64-6x with smoke: false, skip_zig: true; only install zig when not skipping; pass CMUX_SKIP_ZIG_BUILD to tests.
    • Script: build-ghostty-cli-helper.sh supports CMUX_SKIP_ZIG_BUILD=1 and writes an executable stub to satisfy the Xcode run script check.

Written for commit 4f356a1. Summary will update on new commits.

Summary by CodeRabbit

  • Bug Fixes

    • Enhanced macOS 26 compatibility by implementing conditional Zig build skipping on platforms where Zig cannot link system libraries, preventing build failures.
  • Chores

    • Updated continuous integration workflow to intelligently manage Zig installation and build processes based on OS requirements, with fallback implementations for testing.

Zig 0.15.2's MachO linker can't resolve libSystem on macOS 26 (the
version number jump from 15 to 26 breaks zig's SDK handling). The unit
tests don't need the CLI helper binary at runtime, so we skip the zig
build on macOS 26 by setting CMUX_SKIP_ZIG_BUILD=1, which creates a
stub binary to satisfy the Xcode Run Script file check.

Smoke test (full app build + launch) is skipped on macOS 26 since it
needs the real CLI helper.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@vercel

vercel Bot commented Mar 17, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cmux Ready Ready Preview, Comment Mar 17, 2026 8:37am

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@coderabbitai

coderabbitai Bot commented Mar 17, 2026 •

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR modifies CI configuration and build scripts to conditionally skip Zig compilation on macOS 26, where Zig cannot link libSystem. It introduces a matrix flag in the GitHub Actions workflow and propagates an environment variable that gates Zig installation and build steps.

Changes

Cohort / File(s) Summary
CI Workflow Configuration
.github/workflows/ci-macos-compat.yml
Adds a per-OS matrix flag skip_zig (false for macOS 15, true for macOS 26) to conditionally skip Zig installation, and propagates CMUX_SKIP_ZIG_BUILD environment variable to unit test steps.
Build Script Bypass
scripts/build-ghostty-cli-helper.sh
Introduces CI-only logic to check CMUX_SKIP_ZIG_BUILD environment variable; when set, creates a stub shell binary and exits early instead of running the full Zig build.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • #1501: Modifies the same CI workflow and Zig build logic paths, including conditional Zig installation and build handling.
  • #769: Directly added the .github/workflows/ci-macos-compat.yml workflow that this PR extends with the skip_zig flag mechanism.
  • #1459: Previously modified scripts/build-ghostty-cli-helper.sh to add the full Zig installation and helper build, which this PR now gates with a conditional bypass.

Poem

🐰 On macOS twenty-six, where Zig links cannot flow,
A stub becomes the answer, a wise CI's "no."
The matrix flag now whispers: skip or build with care,
One system gets the shortcut, one full journey through the air. ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The pull request description provides a summary and test plan, but is missing key required sections including Testing details, Demo Video, Review Trigger block, and a complete Checklist. Complete the PR description by adding a Testing section with verification details, include the Review Trigger block for bot reviews, and complete all checklist items with checkmarks to indicate completion status.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Add macOS 26 (Tahoe) compat tests' directly summarizes the main change: adding macOS 26 to the compatibility test matrix.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-zig-macos26-linker
📝 Coding Plan
  • Generate coding plan for human review comments

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 2 files

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
.github/workflows/ci-macos-compat.yml (1)

21-21: Actionlint flags the WarpBuild runner label as unknown.

The static analysis tool reports warp-macos-26-arm64-6x as an unknown label since it only knows GitHub-hosted runner labels by default. This is a false positive for WarpBuild's custom runners.

Consider adding an actionlint.yaml config at the repo root to silence this:

📝 Suggested actionlint.yaml configuration
# actionlint.yaml
self-hosted-runner:
  labels:
    - warp-macos-15-arm64-6x
    - warp-macos-26-arm64-6x
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/ci-macos-compat.yml at line 21, Add an actionlint
configuration to silence the false-positive unknown runner label: create an
actionlint.yaml at the repo root and register the custom self-hosted labels
(e.g., warp-macos-26-arm64-6x and warp-macos-15-arm64-6x) under a
self-hosted-runner.labels key so actionlint recognizes those labels used in the
workflow (reference the label string warp-macos-26-arm64-6x from the CI
workflow).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In @.github/workflows/ci-macos-compat.yml:
- Line 21: Add an actionlint configuration to silence the false-positive unknown
runner label: create an actionlint.yaml at the repo root and register the custom
self-hosted labels (e.g., warp-macos-26-arm64-6x and warp-macos-15-arm64-6x)
under a self-hosted-runner.labels key so actionlint recognizes those labels used
in the workflow (reference the label string warp-macos-26-arm64-6x from the CI
workflow).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e5c95565-7a67-4246-8ef5-4a36bc9a29f3

📥 Commits

Reviewing files that changed from the base of the PR and between 8531e4f and 55e9f58.

📒 Files selected for processing (2)
  • .github/workflows/ci-macos-compat.yml
  • scripts/build-ghostty-cli-helper.sh

@lawrencecchen
lawrencecchen merged commit 1fc4bcb into main Mar 17, 2026
14 checks passed
@lawrencecchen
lawrencecchen deleted the fix-zig-macos26-linker branch March 17, 2026 08:44
EtanHey added a commit to EtanHey/cmux that referenced this pull request Mar 17, 2026
* Add browser import flow with installed-browser detection

* Tone down empty browser import overlay

* Make browser import a 2-step choice flow

* Use single-window browser import wizard with close button

* Mention extensions not yet supported in import note

* Reapply "Merge pull request manaflow-ai#239 from manaflow-ai/issue-151-ssh-remote-port-proxying"

This reverts commit f7cbbad.

* Fix ssh stack review regressions

* Address ssh stack review follow-ups

* Optimize remote daemon builds and TCP latency

* Add remote favicon proxy regression

* Proxy remote browser favicon fetches

* Add ssh profile-noise regression

* Avoid sourcing profile in ssh bootstrap

* Add ssh stack regression tests

* Fix ssh stack review regressions

* Fix ghostty deferred-init regression harness

* Fix SSH workspace priming and restore state

* Fix SSH transport dedupe and loopback review issues

* Fix browser move and zsh bootstrap regressions

* Add regressions for v1 panel focus preservation

* Fix socket focus and startup env regressions

* Add regression test for deferred terminal portal sync

* Defer terminal portal sync past layout churn

* Keep portal sync responsive during live resize

* fix: show sidebar update banner from background checks (manaflow-ai#1543)

* Update bonsplit for split transparency

* Update bonsplit for split transparency

* Support folder drops on dock icon (manaflow-ai#1571)

* Fix sidebar PR badges for restored workspaces (manaflow-ai#1570)

* test: cover sidebar PR explicit branch fallback

* fix: restore sidebar PR badges for workspace branches

* test: preserve sidebar PR badge on first prompt

* fix: keep sidebar PR badges through first prompt

* feat: add browser profile mapping import flow

* Avoid blocking browser PR metadata updates (manaflow-ai#1564)

* Fix manaflow-ai#1574: remove top update banner in sidebar (manaflow-ai#1575)

* test: cover sidebar update indicator regression

* fix: remove duplicate sidebar update banner

* fix: address browser import review feedback

* Stabilize SSH remote flow after merging main

* Make remote proxy close idempotent

* Fix UI test helper closure captures

* Add remote CLI relay regressions

* Fix nightly remote daemon and SSH relay wiring

* Migrate CI/CD to WarpBuild, consolidate test jobs (manaflow-ai#1501)

* Migrate CI/CD to WarpBuild, consolidate test jobs

Replace all macOS runner labels across workflows:
- depot-macos-latest → warp-macos-15-arm64-6x
- macos-15 → warp-macos-15-arm64-6x
- macos-14 → warp-macos-14-arm64-6x

Consolidates tests + tests-depot into a single tests job that runs
unit tests, regressions, UI tests, and lag tests sequentially on one
WarpBuild runner. Ubuntu jobs remain on ubuntu-latest.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Upgrade stale zig on runners that have an outdated version pre-installed

WarpBuild macos-14 ships zig 0.15.1 but the project requires 0.15.2.
The install step skipped because zig was found, just outdated.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Pin zig 0.15.2 via direct tarball instead of Homebrew

Homebrew's zig bottle for macOS 14 (Sonoma) is stuck at 0.15.1 but the
ghostty submodule requires 0.15.2. Download zig directly from
ziglang.org to guarantee the correct version on all runner images.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Fix zig tarball URL: arch-os order is aarch64-macos, not macos-aarch64

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Create /usr/local/bin and /usr/local/lib before copying zig

WarpBuild runners don't have /usr/local/lib by default.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Add 20-min timeout to WarpBuild jobs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Fix UI test hang: stream output instead of variable capture, use GitHub runner for macOS 14

The OUTPUT=$(...) pattern buffers all xcodebuild output into a bash
variable. For the full cmux scheme (build + UI tests), this can be
hundreds of MB, causing the shell to hang. Replace with tee streaming.

macOS 14 on WarpBuild consistently hangs (unit tests timeout at 20min
vs 4min on macOS 15, same M4 Pro hardware). Use GitHub-hosted macos-14
runner for compat tests instead, which works on main today.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Split UI tests to GitHub-hosted runner (WarpBuild can't activate GUI apps)

WarpBuild macOS VMs leave XCUIApplication stuck in "Running Background"
state, causing every UI test to burn ~62s waiting for activation and
timing out the job. Root cause: WarpBuild ephemeral VMs don't provide
a full GUI session for app activation.

Split CI into parallel jobs:
- tests: WarpBuild (unit tests + regressions, ~6 min)
- tests-ui: GitHub-hosted macos-15 (UI tests + lag regression)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Move tests-ui to WarpBuild with TCC permission grants

Grant accessibility, post-event, and screen capture TCC permissions
to Xcode and XCTest processes on WarpBuild ephemeral VMs. This should
fix "Failed to activate application (Running Background)" errors that
prevent XCUITests from bringing the app to foreground.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Add GUI session diagnostics and DevToolsSecurity for WarpBuild UI tests

Add session diagnostics (who, console user, GUI domain, WindowServer,
loginwindow) to understand WarpBuild VM session state. Also enable
DevToolsSecurity and security authorizationdb for XCTest process
control. Try bootstrapping GUI session if missing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Fix TCC permissions: use Xcode-Helper + user DB (CircleCI approach)

Previous TCC grants used wrong client IDs (com.apple.dt.Xcode) and
only wrote to the system database. CircleCI's proven approach grants:
- kTCCServiceAccessibility to com.apple.dt.Xcode-Helper (not Xcode)
- kTCCServiceDeveloperTool to com.apple.Terminal
- Both system AND user-level TCC databases

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Reduce UI test timeout to 15s for WarpBuild expected failures

WarpBuild Virtualization.framework VMs cannot activate macOS GUI apps
(XCUIApplication stuck "Running Background"). Tests still execute and
report expected failures. But the 62s per-test activation timeout
makes 30+ tests take 30+ minutes total.

Set per-test timeout to 15s so expected failures resolve quickly.
Full interactive UI test coverage runs via test-e2e.yml on
GitHub-hosted runners with proper display support.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Replace XCUITest run with build + lag regression on WarpBuild

WarpBuild Virtualization.framework VMs cannot activate macOS GUI apps
(XCUIApplication stuck "Running Background" with 62s activation
timeout per test). Tried TCC permissions, DevToolsSecurity, virtual
display, reduced timeouts, nothing fixes the framework-level issue.

Replace tests-ui job with tests-build-and-lag:
- Build the full cmux scheme (verifies compilation)
- Run workspace churn typing-lag regression (socket-based, no GUI)
- XCUITests run via test-e2e.yml on GitHub-hosted runners

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Move macOS 14 compat to WarpBuild (no GitHub-hosted runners)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Add diagnostic workflow to probe WarpBuild GUI activation

Tests multiple app activation approaches on WarpBuild VMs:
- open -a, NSWorkspace, NSRunningApplication.activate, osascript
- Virtual display state before/after CGVirtualDisplay
- TCC/accessibility permissions, Quartz session info
- VM type detection

This is a workflow_dispatch-only diagnostic to determine if
XCUITest can work on WarpBuild with the right configuration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Trigger GUI probe on branch push (workflow_dispatch needs main)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Rewrite GUI probe with Swift (Python lacks AppKit on WarpBuild)

v1 failed because WarpBuild's Python isn't a framework build and
can't import AppKit/Quartz. v2 uses a compiled Swift binary to test
NSRunningApplication.activate(), osascript, Quartz session state,
display info, and AX trust.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* GUI probe v3: try 5 approaches to unlock WarpBuild screen

1. defaults write (screensaver, loginwindow, pmset)
2. automationmodetool enable-automationmode-without-authentication
3. CGSSessionSetScreenLocked private API + System Events keystroke
4. sysadminctl -screenLock off + keychain unlock
5. CGEvent simulation (mouse move + Return key to dismiss lock)

Each approach is followed by an activation check to see if it worked.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Test GUI activation on macOS 14, 15, and 26 (Tahoe)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Add DerivedData and GhosttyKit caching to CI workflows

Major caching improvements across ci.yml and ci-macos-compat.yml:

- Cache GhosttyKit.xcframework keyed on ghostty submodule SHA
  (skip download on cache hit)
- Cache DerivedData keyed on OS + Xcode version + Package.resolved +
  project.pbxproj (enables incremental builds across runs)
- Remove explicit DerivedData wipe (rely on cache key invalidation)
- Use download-prebuilt-ghosttykit.sh in compat workflow too

This should significantly speed up macOS 14 compat tests which were
taking 20+ min due to full recompilation every run.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Bump macOS 14 compat timeout to 45 min for cold cache seeding

The DerivedData cache wasn't saved because the job timed out at 30 min,
causing the post-job cache save step to be skipped. 45 min gives enough
headroom for the first uncached run to complete and seed the cache.
Subsequent runs should be much faster with incremental builds.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Use Depot runners for E2E tests (WarpBuild has screen lock on macOS 15/26)

WarpBuild VMs on macOS 15 and 26 have CGSSessionScreenIsLocked=1, which
prevents XCUIApplication activation. Depot runners have working GUI
activation. Can switch back to WarpBuild once they fix the VM images.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Skip smoke test on macOS 14 compat, remove GUI diagnostic workflow

macOS 14 was slow because it built the full app (cmux scheme) on top of
unit tests (cmux-unit scheme). Unit tests are the real compat check;
smoke test runs on macOS 15 only. Also removes the temporary
test-warpbuild-gui.yml diagnostic workflow.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Replace Sonoma with Tahoe in compat matrix, drop macOS 14

Swap macOS 14 (Sonoma) for macOS 26 (Tahoe). Smoke test runs on
macOS 15 only (WarpBuild screen lock blocks app activation on 26).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Drop macOS 26 from compat matrix (zig 0.15.2 linker failure)

Zig 0.15.2 can't link against the macOS 26 (Tahoe) SDK: undefined
symbols for basic libc functions (_abort, _free, _fork, etc.). The zig
toolchain needs an update to support Tahoe. Keep macOS 15 only for now.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* Fix release browser portal compile

* Add macOS 26 (Tahoe) compat tests, skip zig build via stub (manaflow-ai#1590)

Zig 0.15.2's MachO linker can't resolve libSystem on macOS 26 (the
version number jump from 15 to 26 breaks zig's SDK handling). The unit
tests don't need the CLI helper binary at runtime, so we skip the zig
build on macOS 26 by setting CMUX_SKIP_ZIG_BUILD=1, which creates a
stub binary to satisfy the Xcode Run Script file check.

Smoke test (full app build + launch) is skipped on macOS 26 since it
needs the real CLI helper.

Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Add regression tests for SSH remote CLI follow-ups

* Fix SSH remote CLI and loopback proxy follow-ups

* Fix remote daemon build script using relative output path after cd (manaflow-ai#1595)

The Go build runs in a subshell that cd's to daemon/remote/, but
OUTPUT_DIR was relative to the repo root. Resolve to absolute path
after mkdir so go build -o writes to the correct location.

Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Address SSH follow-up PR review comments

* fix: restore Sparkle automatic update checks (manaflow-ai#1597)

* feat: add native MCP protocol support to socket server

Add MCP (Model Context Protocol) Content-Length framing support directly
to the cmux socket server, enabling AI tools to connect via socat without
needing a separate Node.js MCP wrapper process.

Protocol detection on first read: "Content-Length:" → MCP mode,
"{" → V2 JSON-RPC, else V1 plain text. All three protocols coexist
on the same Unix socket.

New files:
- MCPServer.swift: Content-Length framing parser, MCPHandler with 3
  JSON-RPC methods (initialize, tools/list, tools/call), and 20 MCP
  tool schemas that route to existing V2 socket methods
- MCPServerTests.swift: 28 unit tests covering framing, handler logic,
  and tool routing

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: address MCP server review findings

- Fix test initialization: tests calling tools/list and tools/call
  now send initialize first (XCTest creates fresh instances per test)
- Add testToolsListBeforeInitializeReturnsError to cover the guard
- Fix MCP message loop: continue parsing after each message instead
  of breaking after one, avoiding latency when multiple messages
  arrive in a single socket read
- Forward press_enter param in send_input tool routing
- Quote V1 command arguments to prevent injection via tokenizer
- Add writeSocketData helper with EINTR/partial-write handling
- Add encodeResponse fallback for non-serializable dicts
- Require initialized handshake before tools/list and tools/call
- Reject MCP connections when password auth is required
- Close connection on corrupted data after MCP detection

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.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: Austin Wang <austinwang115@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
EtanHey added a commit to EtanHey/cmux that referenced this pull request Mar 17, 2026
* Add browser import flow with installed-browser detection

* Tone down empty browser import overlay

* Make browser import a 2-step choice flow

* Use single-window browser import wizard with close button

* Mention extensions not yet supported in import note

* Reapply "Merge pull request manaflow-ai#239 from manaflow-ai/issue-151-ssh-remote-port-proxying"

This reverts commit f7cbbad.

* Fix ssh stack review regressions

* Address ssh stack review follow-ups

* Optimize remote daemon builds and TCP latency

* Add remote favicon proxy regression

* Proxy remote browser favicon fetches

* Add ssh profile-noise regression

* Avoid sourcing profile in ssh bootstrap

* Add ssh stack regression tests

* Fix ssh stack review regressions

* Fix ghostty deferred-init regression harness

* Fix SSH workspace priming and restore state

* Fix SSH transport dedupe and loopback review issues

* Fix browser move and zsh bootstrap regressions

* Add regressions for v1 panel focus preservation

* Fix socket focus and startup env regressions

* Add regression test for deferred terminal portal sync

* Defer terminal portal sync past layout churn

* Keep portal sync responsive during live resize

* fix: show sidebar update banner from background checks (manaflow-ai#1543)

* Update bonsplit for split transparency

* Update bonsplit for split transparency

* Support folder drops on dock icon (manaflow-ai#1571)

* Fix sidebar PR badges for restored workspaces (manaflow-ai#1570)

* test: cover sidebar PR explicit branch fallback

* fix: restore sidebar PR badges for workspace branches

* test: preserve sidebar PR badge on first prompt

* fix: keep sidebar PR badges through first prompt

* feat: add browser profile mapping import flow

* Avoid blocking browser PR metadata updates (manaflow-ai#1564)

* Fix manaflow-ai#1574: remove top update banner in sidebar (manaflow-ai#1575)

* test: cover sidebar update indicator regression

* fix: remove duplicate sidebar update banner

* fix: address browser import review feedback

* Stabilize SSH remote flow after merging main

* Make remote proxy close idempotent

* Fix UI test helper closure captures

* Add remote CLI relay regressions

* Fix nightly remote daemon and SSH relay wiring

* Migrate CI/CD to WarpBuild, consolidate test jobs (manaflow-ai#1501)

* Migrate CI/CD to WarpBuild, consolidate test jobs

Replace all macOS runner labels across workflows:
- depot-macos-latest → warp-macos-15-arm64-6x
- macos-15 → warp-macos-15-arm64-6x
- macos-14 → warp-macos-14-arm64-6x

Consolidates tests + tests-depot into a single tests job that runs
unit tests, regressions, UI tests, and lag tests sequentially on one
WarpBuild runner. Ubuntu jobs remain on ubuntu-latest.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Upgrade stale zig on runners that have an outdated version pre-installed

WarpBuild macos-14 ships zig 0.15.1 but the project requires 0.15.2.
The install step skipped because zig was found, just outdated.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Pin zig 0.15.2 via direct tarball instead of Homebrew

Homebrew's zig bottle for macOS 14 (Sonoma) is stuck at 0.15.1 but the
ghostty submodule requires 0.15.2. Download zig directly from
ziglang.org to guarantee the correct version on all runner images.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Fix zig tarball URL: arch-os order is aarch64-macos, not macos-aarch64

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Create /usr/local/bin and /usr/local/lib before copying zig

WarpBuild runners don't have /usr/local/lib by default.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Add 20-min timeout to WarpBuild jobs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Fix UI test hang: stream output instead of variable capture, use GitHub runner for macOS 14

The OUTPUT=$(...) pattern buffers all xcodebuild output into a bash
variable. For the full cmux scheme (build + UI tests), this can be
hundreds of MB, causing the shell to hang. Replace with tee streaming.

macOS 14 on WarpBuild consistently hangs (unit tests timeout at 20min
vs 4min on macOS 15, same M4 Pro hardware). Use GitHub-hosted macos-14
runner for compat tests instead, which works on main today.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Split UI tests to GitHub-hosted runner (WarpBuild can't activate GUI apps)

WarpBuild macOS VMs leave XCUIApplication stuck in "Running Background"
state, causing every UI test to burn ~62s waiting for activation and
timing out the job. Root cause: WarpBuild ephemeral VMs don't provide
a full GUI session for app activation.

Split CI into parallel jobs:
- tests: WarpBuild (unit tests + regressions, ~6 min)
- tests-ui: GitHub-hosted macos-15 (UI tests + lag regression)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Move tests-ui to WarpBuild with TCC permission grants

Grant accessibility, post-event, and screen capture TCC permissions
to Xcode and XCTest processes on WarpBuild ephemeral VMs. This should
fix "Failed to activate application (Running Background)" errors that
prevent XCUITests from bringing the app to foreground.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Add GUI session diagnostics and DevToolsSecurity for WarpBuild UI tests

Add session diagnostics (who, console user, GUI domain, WindowServer,
loginwindow) to understand WarpBuild VM session state. Also enable
DevToolsSecurity and security authorizationdb for XCTest process
control. Try bootstrapping GUI session if missing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Fix TCC permissions: use Xcode-Helper + user DB (CircleCI approach)

Previous TCC grants used wrong client IDs (com.apple.dt.Xcode) and
only wrote to the system database. CircleCI's proven approach grants:
- kTCCServiceAccessibility to com.apple.dt.Xcode-Helper (not Xcode)
- kTCCServiceDeveloperTool to com.apple.Terminal
- Both system AND user-level TCC databases

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Reduce UI test timeout to 15s for WarpBuild expected failures

WarpBuild Virtualization.framework VMs cannot activate macOS GUI apps
(XCUIApplication stuck "Running Background"). Tests still execute and
report expected failures. But the 62s per-test activation timeout
makes 30+ tests take 30+ minutes total.

Set per-test timeout to 15s so expected failures resolve quickly.
Full interactive UI test coverage runs via test-e2e.yml on
GitHub-hosted runners with proper display support.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Replace XCUITest run with build + lag regression on WarpBuild

WarpBuild Virtualization.framework VMs cannot activate macOS GUI apps
(XCUIApplication stuck "Running Background" with 62s activation
timeout per test). Tried TCC permissions, DevToolsSecurity, virtual
display, reduced timeouts, nothing fixes the framework-level issue.

Replace tests-ui job with tests-build-and-lag:
- Build the full cmux scheme (verifies compilation)
- Run workspace churn typing-lag regression (socket-based, no GUI)
- XCUITests run via test-e2e.yml on GitHub-hosted runners

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Move macOS 14 compat to WarpBuild (no GitHub-hosted runners)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Add diagnostic workflow to probe WarpBuild GUI activation

Tests multiple app activation approaches on WarpBuild VMs:
- open -a, NSWorkspace, NSRunningApplication.activate, osascript
- Virtual display state before/after CGVirtualDisplay
- TCC/accessibility permissions, Quartz session info
- VM type detection

This is a workflow_dispatch-only diagnostic to determine if
XCUITest can work on WarpBuild with the right configuration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Trigger GUI probe on branch push (workflow_dispatch needs main)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Rewrite GUI probe with Swift (Python lacks AppKit on WarpBuild)

v1 failed because WarpBuild's Python isn't a framework build and
can't import AppKit/Quartz. v2 uses a compiled Swift binary to test
NSRunningApplication.activate(), osascript, Quartz session state,
display info, and AX trust.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* GUI probe v3: try 5 approaches to unlock WarpBuild screen

1. defaults write (screensaver, loginwindow, pmset)
2. automationmodetool enable-automationmode-without-authentication
3. CGSSessionSetScreenLocked private API + System Events keystroke
4. sysadminctl -screenLock off + keychain unlock
5. CGEvent simulation (mouse move + Return key to dismiss lock)

Each approach is followed by an activation check to see if it worked.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Test GUI activation on macOS 14, 15, and 26 (Tahoe)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Add DerivedData and GhosttyKit caching to CI workflows

Major caching improvements across ci.yml and ci-macos-compat.yml:

- Cache GhosttyKit.xcframework keyed on ghostty submodule SHA
  (skip download on cache hit)
- Cache DerivedData keyed on OS + Xcode version + Package.resolved +
  project.pbxproj (enables incremental builds across runs)
- Remove explicit DerivedData wipe (rely on cache key invalidation)
- Use download-prebuilt-ghosttykit.sh in compat workflow too

This should significantly speed up macOS 14 compat tests which were
taking 20+ min due to full recompilation every run.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Bump macOS 14 compat timeout to 45 min for cold cache seeding

The DerivedData cache wasn't saved because the job timed out at 30 min,
causing the post-job cache save step to be skipped. 45 min gives enough
headroom for the first uncached run to complete and seed the cache.
Subsequent runs should be much faster with incremental builds.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Use Depot runners for E2E tests (WarpBuild has screen lock on macOS 15/26)

WarpBuild VMs on macOS 15 and 26 have CGSSessionScreenIsLocked=1, which
prevents XCUIApplication activation. Depot runners have working GUI
activation. Can switch back to WarpBuild once they fix the VM images.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Skip smoke test on macOS 14 compat, remove GUI diagnostic workflow

macOS 14 was slow because it built the full app (cmux scheme) on top of
unit tests (cmux-unit scheme). Unit tests are the real compat check;
smoke test runs on macOS 15 only. Also removes the temporary
test-warpbuild-gui.yml diagnostic workflow.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Replace Sonoma with Tahoe in compat matrix, drop macOS 14

Swap macOS 14 (Sonoma) for macOS 26 (Tahoe). Smoke test runs on
macOS 15 only (WarpBuild screen lock blocks app activation on 26).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Drop macOS 26 from compat matrix (zig 0.15.2 linker failure)

Zig 0.15.2 can't link against the macOS 26 (Tahoe) SDK: undefined
symbols for basic libc functions (_abort, _free, _fork, etc.). The zig
toolchain needs an update to support Tahoe. Keep macOS 15 only for now.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* Fix release browser portal compile

* Add macOS 26 (Tahoe) compat tests, skip zig build via stub (manaflow-ai#1590)

Zig 0.15.2's MachO linker can't resolve libSystem on macOS 26 (the
version number jump from 15 to 26 breaks zig's SDK handling). The unit
tests don't need the CLI helper binary at runtime, so we skip the zig
build on macOS 26 by setting CMUX_SKIP_ZIG_BUILD=1, which creates a
stub binary to satisfy the Xcode Run Script file check.

Smoke test (full app build + launch) is skipped on macOS 26 since it
needs the real CLI helper.

Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Add regression tests for SSH remote CLI follow-ups

* Fix SSH remote CLI and loopback proxy follow-ups

* Fix remote daemon build script using relative output path after cd (manaflow-ai#1595)

The Go build runs in a subshell that cd's to daemon/remote/, but
OUTPUT_DIR was relative to the repo root. Resolve to absolute path
after mkdir so go build -o writes to the correct location.

Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Address SSH follow-up PR review comments

* fix: restore Sparkle automatic update checks (manaflow-ai#1597)

* feat: add native MCP protocol support to socket server

Add MCP (Model Context Protocol) Content-Length framing support directly
to the cmux socket server, enabling AI tools to connect via socat without
needing a separate Node.js MCP wrapper process.

Protocol detection on first read: "Content-Length:" → MCP mode,
"{" → V2 JSON-RPC, else V1 plain text. All three protocols coexist
on the same Unix socket.

New files:
- MCPServer.swift: Content-Length framing parser, MCPHandler with 3
  JSON-RPC methods (initialize, tools/list, tools/call), and 20 MCP
  tool schemas that route to existing V2 socket methods
- MCPServerTests.swift: 28 unit tests covering framing, handler logic,
  and tool routing

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: address MCP server review findings

- Fix test initialization: tests calling tools/list and tools/call
  now send initialize first (XCTest creates fresh instances per test)
- Add testToolsListBeforeInitializeReturnsError to cover the guard
- Fix MCP message loop: continue parsing after each message instead
  of breaking after one, avoiding latency when multiple messages
  arrive in a single socket read
- Forward press_enter param in send_input tool routing
- Quote V1 command arguments to prevent injection via tokenizer
- Add writeSocketData helper with EINTR/partial-write handling
- Add encodeResponse fallback for non-serializable dicts
- Require initialized handshake before tools/list and tools/call
- Reject MCP connections when password auth is required
- Close connection on corrupted data after MCP detection

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.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: Austin Wang <austinwang115@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
EtanHey added a commit to EtanHey/cmux that referenced this pull request Mar 17, 2026
* Add browser import flow with installed-browser detection

* Tone down empty browser import overlay

* Make browser import a 2-step choice flow

* Use single-window browser import wizard with close button

* Mention extensions not yet supported in import note

* Reapply "Merge pull request manaflow-ai#239 from manaflow-ai/issue-151-ssh-remote-port-proxying"

This reverts commit f7cbbad.

* Fix ssh stack review regressions

* Address ssh stack review follow-ups

* Optimize remote daemon builds and TCP latency

* Add remote favicon proxy regression

* Proxy remote browser favicon fetches

* Add ssh profile-noise regression

* Avoid sourcing profile in ssh bootstrap

* Add ssh stack regression tests

* Fix ssh stack review regressions

* Fix ghostty deferred-init regression harness

* Fix SSH workspace priming and restore state

* Fix SSH transport dedupe and loopback review issues

* Fix browser move and zsh bootstrap regressions

* Add regressions for v1 panel focus preservation

* Fix socket focus and startup env regressions

* Add regression test for deferred terminal portal sync

* Defer terminal portal sync past layout churn

* Keep portal sync responsive during live resize

* fix: show sidebar update banner from background checks (manaflow-ai#1543)

* Update bonsplit for split transparency

* Update bonsplit for split transparency

* Support folder drops on dock icon (manaflow-ai#1571)

* Fix sidebar PR badges for restored workspaces (manaflow-ai#1570)

* test: cover sidebar PR explicit branch fallback

* fix: restore sidebar PR badges for workspace branches

* test: preserve sidebar PR badge on first prompt

* fix: keep sidebar PR badges through first prompt

* feat: add browser profile mapping import flow

* Avoid blocking browser PR metadata updates (manaflow-ai#1564)

* Fix manaflow-ai#1574: remove top update banner in sidebar (manaflow-ai#1575)

* test: cover sidebar update indicator regression

* fix: remove duplicate sidebar update banner

* fix: address browser import review feedback

* Stabilize SSH remote flow after merging main

* Make remote proxy close idempotent

* Fix UI test helper closure captures

* Add remote CLI relay regressions

* Fix nightly remote daemon and SSH relay wiring

* Migrate CI/CD to WarpBuild, consolidate test jobs (manaflow-ai#1501)

* Migrate CI/CD to WarpBuild, consolidate test jobs

Replace all macOS runner labels across workflows:
- depot-macos-latest → warp-macos-15-arm64-6x
- macos-15 → warp-macos-15-arm64-6x
- macos-14 → warp-macos-14-arm64-6x

Consolidates tests + tests-depot into a single tests job that runs
unit tests, regressions, UI tests, and lag tests sequentially on one
WarpBuild runner. Ubuntu jobs remain on ubuntu-latest.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Upgrade stale zig on runners that have an outdated version pre-installed

WarpBuild macos-14 ships zig 0.15.1 but the project requires 0.15.2.
The install step skipped because zig was found, just outdated.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Pin zig 0.15.2 via direct tarball instead of Homebrew

Homebrew's zig bottle for macOS 14 (Sonoma) is stuck at 0.15.1 but the
ghostty submodule requires 0.15.2. Download zig directly from
ziglang.org to guarantee the correct version on all runner images.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Fix zig tarball URL: arch-os order is aarch64-macos, not macos-aarch64

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Create /usr/local/bin and /usr/local/lib before copying zig

WarpBuild runners don't have /usr/local/lib by default.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Add 20-min timeout to WarpBuild jobs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Fix UI test hang: stream output instead of variable capture, use GitHub runner for macOS 14

The OUTPUT=$(...) pattern buffers all xcodebuild output into a bash
variable. For the full cmux scheme (build + UI tests), this can be
hundreds of MB, causing the shell to hang. Replace with tee streaming.

macOS 14 on WarpBuild consistently hangs (unit tests timeout at 20min
vs 4min on macOS 15, same M4 Pro hardware). Use GitHub-hosted macos-14
runner for compat tests instead, which works on main today.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Split UI tests to GitHub-hosted runner (WarpBuild can't activate GUI apps)

WarpBuild macOS VMs leave XCUIApplication stuck in "Running Background"
state, causing every UI test to burn ~62s waiting for activation and
timing out the job. Root cause: WarpBuild ephemeral VMs don't provide
a full GUI session for app activation.

Split CI into parallel jobs:
- tests: WarpBuild (unit tests + regressions, ~6 min)
- tests-ui: GitHub-hosted macos-15 (UI tests + lag regression)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Move tests-ui to WarpBuild with TCC permission grants

Grant accessibility, post-event, and screen capture TCC permissions
to Xcode and XCTest processes on WarpBuild ephemeral VMs. This should
fix "Failed to activate application (Running Background)" errors that
prevent XCUITests from bringing the app to foreground.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Add GUI session diagnostics and DevToolsSecurity for WarpBuild UI tests

Add session diagnostics (who, console user, GUI domain, WindowServer,
loginwindow) to understand WarpBuild VM session state. Also enable
DevToolsSecurity and security authorizationdb for XCTest process
control. Try bootstrapping GUI session if missing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Fix TCC permissions: use Xcode-Helper + user DB (CircleCI approach)

Previous TCC grants used wrong client IDs (com.apple.dt.Xcode) and
only wrote to the system database. CircleCI's proven approach grants:
- kTCCServiceAccessibility to com.apple.dt.Xcode-Helper (not Xcode)
- kTCCServiceDeveloperTool to com.apple.Terminal
- Both system AND user-level TCC databases

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Reduce UI test timeout to 15s for WarpBuild expected failures

WarpBuild Virtualization.framework VMs cannot activate macOS GUI apps
(XCUIApplication stuck "Running Background"). Tests still execute and
report expected failures. But the 62s per-test activation timeout
makes 30+ tests take 30+ minutes total.

Set per-test timeout to 15s so expected failures resolve quickly.
Full interactive UI test coverage runs via test-e2e.yml on
GitHub-hosted runners with proper display support.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Replace XCUITest run with build + lag regression on WarpBuild

WarpBuild Virtualization.framework VMs cannot activate macOS GUI apps
(XCUIApplication stuck "Running Background" with 62s activation
timeout per test). Tried TCC permissions, DevToolsSecurity, virtual
display, reduced timeouts, nothing fixes the framework-level issue.

Replace tests-ui job with tests-build-and-lag:
- Build the full cmux scheme (verifies compilation)
- Run workspace churn typing-lag regression (socket-based, no GUI)
- XCUITests run via test-e2e.yml on GitHub-hosted runners

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Move macOS 14 compat to WarpBuild (no GitHub-hosted runners)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Add diagnostic workflow to probe WarpBuild GUI activation

Tests multiple app activation approaches on WarpBuild VMs:
- open -a, NSWorkspace, NSRunningApplication.activate, osascript
- Virtual display state before/after CGVirtualDisplay
- TCC/accessibility permissions, Quartz session info
- VM type detection

This is a workflow_dispatch-only diagnostic to determine if
XCUITest can work on WarpBuild with the right configuration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Trigger GUI probe on branch push (workflow_dispatch needs main)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Rewrite GUI probe with Swift (Python lacks AppKit on WarpBuild)

v1 failed because WarpBuild's Python isn't a framework build and
can't import AppKit/Quartz. v2 uses a compiled Swift binary to test
NSRunningApplication.activate(), osascript, Quartz session state,
display info, and AX trust.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* GUI probe v3: try 5 approaches to unlock WarpBuild screen

1. defaults write (screensaver, loginwindow, pmset)
2. automationmodetool enable-automationmode-without-authentication
3. CGSSessionSetScreenLocked private API + System Events keystroke
4. sysadminctl -screenLock off + keychain unlock
5. CGEvent simulation (mouse move + Return key to dismiss lock)

Each approach is followed by an activation check to see if it worked.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Test GUI activation on macOS 14, 15, and 26 (Tahoe)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Add DerivedData and GhosttyKit caching to CI workflows

Major caching improvements across ci.yml and ci-macos-compat.yml:

- Cache GhosttyKit.xcframework keyed on ghostty submodule SHA
  (skip download on cache hit)
- Cache DerivedData keyed on OS + Xcode version + Package.resolved +
  project.pbxproj (enables incremental builds across runs)
- Remove explicit DerivedData wipe (rely on cache key invalidation)
- Use download-prebuilt-ghosttykit.sh in compat workflow too

This should significantly speed up macOS 14 compat tests which were
taking 20+ min due to full recompilation every run.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Bump macOS 14 compat timeout to 45 min for cold cache seeding

The DerivedData cache wasn't saved because the job timed out at 30 min,
causing the post-job cache save step to be skipped. 45 min gives enough
headroom for the first uncached run to complete and seed the cache.
Subsequent runs should be much faster with incremental builds.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Use Depot runners for E2E tests (WarpBuild has screen lock on macOS 15/26)

WarpBuild VMs on macOS 15 and 26 have CGSSessionScreenIsLocked=1, which
prevents XCUIApplication activation. Depot runners have working GUI
activation. Can switch back to WarpBuild once they fix the VM images.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Skip smoke test on macOS 14 compat, remove GUI diagnostic workflow

macOS 14 was slow because it built the full app (cmux scheme) on top of
unit tests (cmux-unit scheme). Unit tests are the real compat check;
smoke test runs on macOS 15 only. Also removes the temporary
test-warpbuild-gui.yml diagnostic workflow.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Replace Sonoma with Tahoe in compat matrix, drop macOS 14

Swap macOS 14 (Sonoma) for macOS 26 (Tahoe). Smoke test runs on
macOS 15 only (WarpBuild screen lock blocks app activation on 26).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Drop macOS 26 from compat matrix (zig 0.15.2 linker failure)

Zig 0.15.2 can't link against the macOS 26 (Tahoe) SDK: undefined
symbols for basic libc functions (_abort, _free, _fork, etc.). The zig
toolchain needs an update to support Tahoe. Keep macOS 15 only for now.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* Fix release browser portal compile

* Add macOS 26 (Tahoe) compat tests, skip zig build via stub (manaflow-ai#1590)

Zig 0.15.2's MachO linker can't resolve libSystem on macOS 26 (the
version number jump from 15 to 26 breaks zig's SDK handling). The unit
tests don't need the CLI helper binary at runtime, so we skip the zig
build on macOS 26 by setting CMUX_SKIP_ZIG_BUILD=1, which creates a
stub binary to satisfy the Xcode Run Script file check.

Smoke test (full app build + launch) is skipped on macOS 26 since it
needs the real CLI helper.

Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Add regression tests for SSH remote CLI follow-ups

* Fix SSH remote CLI and loopback proxy follow-ups

* Fix remote daemon build script using relative output path after cd (manaflow-ai#1595)

The Go build runs in a subshell that cd's to daemon/remote/, but
OUTPUT_DIR was relative to the repo root. Resolve to absolute path
after mkdir so go build -o writes to the correct location.

Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Address SSH follow-up PR review comments

* fix: restore Sparkle automatic update checks (manaflow-ai#1597)

* feat: add native MCP protocol support to socket server

Add MCP (Model Context Protocol) Content-Length framing support directly
to the cmux socket server, enabling AI tools to connect via socat without
needing a separate Node.js MCP wrapper process.

Protocol detection on first read: "Content-Length:" → MCP mode,
"{" → V2 JSON-RPC, else V1 plain text. All three protocols coexist
on the same Unix socket.

New files:
- MCPServer.swift: Content-Length framing parser, MCPHandler with 3
  JSON-RPC methods (initialize, tools/list, tools/call), and 20 MCP
  tool schemas that route to existing V2 socket methods
- MCPServerTests.swift: 28 unit tests covering framing, handler logic,
  and tool routing

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: address MCP server review findings

- Fix test initialization: tests calling tools/list and tools/call
  now send initialize first (XCTest creates fresh instances per test)
- Add testToolsListBeforeInitializeReturnsError to cover the guard
- Fix MCP message loop: continue parsing after each message instead
  of breaking after one, avoiding latency when multiple messages
  arrive in a single socket read
- Forward press_enter param in send_input tool routing
- Quote V1 command arguments to prevent injection via tokenizer
- Add writeSocketData helper with EINTR/partial-write handling
- Add encodeResponse fallback for non-serializable dicts
- Require initialized handshake before tools/list and tools/call
- Reject MCP connections when password auth is required
- Close connection on corrupted data after MCP detection

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.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: Austin Wang <austinwang115@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
EtanHey added a commit to EtanHey/cmux that referenced this pull request Mar 17, 2026
* Add browser import flow with installed-browser detection

* Tone down empty browser import overlay

* Make browser import a 2-step choice flow

* Use single-window browser import wizard with close button

* Mention extensions not yet supported in import note

* Reapply "Merge pull request manaflow-ai#239 from manaflow-ai/issue-151-ssh-remote-port-proxying"

This reverts commit f7cbbad.

* Fix ssh stack review regressions

* Address ssh stack review follow-ups

* Optimize remote daemon builds and TCP latency

* Add remote favicon proxy regression

* Proxy remote browser favicon fetches

* Add ssh profile-noise regression

* Avoid sourcing profile in ssh bootstrap

* Add ssh stack regression tests

* Fix ssh stack review regressions

* Fix ghostty deferred-init regression harness

* Fix SSH workspace priming and restore state

* Fix SSH transport dedupe and loopback review issues

* Fix browser move and zsh bootstrap regressions

* Add regressions for v1 panel focus preservation

* Fix socket focus and startup env regressions

* Add regression test for deferred terminal portal sync

* Defer terminal portal sync past layout churn

* Keep portal sync responsive during live resize

* fix: show sidebar update banner from background checks (manaflow-ai#1543)

* Update bonsplit for split transparency

* Update bonsplit for split transparency

* Support folder drops on dock icon (manaflow-ai#1571)

* Fix sidebar PR badges for restored workspaces (manaflow-ai#1570)

* test: cover sidebar PR explicit branch fallback

* fix: restore sidebar PR badges for workspace branches

* test: preserve sidebar PR badge on first prompt

* fix: keep sidebar PR badges through first prompt

* feat: add browser profile mapping import flow

* Avoid blocking browser PR metadata updates (manaflow-ai#1564)

* Fix manaflow-ai#1574: remove top update banner in sidebar (manaflow-ai#1575)

* test: cover sidebar update indicator regression

* fix: remove duplicate sidebar update banner

* fix: address browser import review feedback

* Stabilize SSH remote flow after merging main

* Make remote proxy close idempotent

* Fix UI test helper closure captures

* Add remote CLI relay regressions

* Fix nightly remote daemon and SSH relay wiring

* Migrate CI/CD to WarpBuild, consolidate test jobs (manaflow-ai#1501)

* Migrate CI/CD to WarpBuild, consolidate test jobs

Replace all macOS runner labels across workflows:
- depot-macos-latest → warp-macos-15-arm64-6x
- macos-15 → warp-macos-15-arm64-6x
- macos-14 → warp-macos-14-arm64-6x

Consolidates tests + tests-depot into a single tests job that runs
unit tests, regressions, UI tests, and lag tests sequentially on one
WarpBuild runner. Ubuntu jobs remain on ubuntu-latest.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Upgrade stale zig on runners that have an outdated version pre-installed

WarpBuild macos-14 ships zig 0.15.1 but the project requires 0.15.2.
The install step skipped because zig was found, just outdated.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Pin zig 0.15.2 via direct tarball instead of Homebrew

Homebrew's zig bottle for macOS 14 (Sonoma) is stuck at 0.15.1 but the
ghostty submodule requires 0.15.2. Download zig directly from
ziglang.org to guarantee the correct version on all runner images.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Fix zig tarball URL: arch-os order is aarch64-macos, not macos-aarch64

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Create /usr/local/bin and /usr/local/lib before copying zig

WarpBuild runners don't have /usr/local/lib by default.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Add 20-min timeout to WarpBuild jobs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Fix UI test hang: stream output instead of variable capture, use GitHub runner for macOS 14

The OUTPUT=$(...) pattern buffers all xcodebuild output into a bash
variable. For the full cmux scheme (build + UI tests), this can be
hundreds of MB, causing the shell to hang. Replace with tee streaming.

macOS 14 on WarpBuild consistently hangs (unit tests timeout at 20min
vs 4min on macOS 15, same M4 Pro hardware). Use GitHub-hosted macos-14
runner for compat tests instead, which works on main today.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Split UI tests to GitHub-hosted runner (WarpBuild can't activate GUI apps)

WarpBuild macOS VMs leave XCUIApplication stuck in "Running Background"
state, causing every UI test to burn ~62s waiting for activation and
timing out the job. Root cause: WarpBuild ephemeral VMs don't provide
a full GUI session for app activation.

Split CI into parallel jobs:
- tests: WarpBuild (unit tests + regressions, ~6 min)
- tests-ui: GitHub-hosted macos-15 (UI tests + lag regression)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Move tests-ui to WarpBuild with TCC permission grants

Grant accessibility, post-event, and screen capture TCC permissions
to Xcode and XCTest processes on WarpBuild ephemeral VMs. This should
fix "Failed to activate application (Running Background)" errors that
prevent XCUITests from bringing the app to foreground.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Add GUI session diagnostics and DevToolsSecurity for WarpBuild UI tests

Add session diagnostics (who, console user, GUI domain, WindowServer,
loginwindow) to understand WarpBuild VM session state. Also enable
DevToolsSecurity and security authorizationdb for XCTest process
control. Try bootstrapping GUI session if missing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Fix TCC permissions: use Xcode-Helper + user DB (CircleCI approach)

Previous TCC grants used wrong client IDs (com.apple.dt.Xcode) and
only wrote to the system database. CircleCI's proven approach grants:
- kTCCServiceAccessibility to com.apple.dt.Xcode-Helper (not Xcode)
- kTCCServiceDeveloperTool to com.apple.Terminal
- Both system AND user-level TCC databases

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Reduce UI test timeout to 15s for WarpBuild expected failures

WarpBuild Virtualization.framework VMs cannot activate macOS GUI apps
(XCUIApplication stuck "Running Background"). Tests still execute and
report expected failures. But the 62s per-test activation timeout
makes 30+ tests take 30+ minutes total.

Set per-test timeout to 15s so expected failures resolve quickly.
Full interactive UI test coverage runs via test-e2e.yml on
GitHub-hosted runners with proper display support.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Replace XCUITest run with build + lag regression on WarpBuild

WarpBuild Virtualization.framework VMs cannot activate macOS GUI apps
(XCUIApplication stuck "Running Background" with 62s activation
timeout per test). Tried TCC permissions, DevToolsSecurity, virtual
display, reduced timeouts, nothing fixes the framework-level issue.

Replace tests-ui job with tests-build-and-lag:
- Build the full cmux scheme (verifies compilation)
- Run workspace churn typing-lag regression (socket-based, no GUI)
- XCUITests run via test-e2e.yml on GitHub-hosted runners

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Move macOS 14 compat to WarpBuild (no GitHub-hosted runners)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Add diagnostic workflow to probe WarpBuild GUI activation

Tests multiple app activation approaches on WarpBuild VMs:
- open -a, NSWorkspace, NSRunningApplication.activate, osascript
- Virtual display state before/after CGVirtualDisplay
- TCC/accessibility permissions, Quartz session info
- VM type detection

This is a workflow_dispatch-only diagnostic to determine if
XCUITest can work on WarpBuild with the right configuration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Trigger GUI probe on branch push (workflow_dispatch needs main)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Rewrite GUI probe with Swift (Python lacks AppKit on WarpBuild)

v1 failed because WarpBuild's Python isn't a framework build and
can't import AppKit/Quartz. v2 uses a compiled Swift binary to test
NSRunningApplication.activate(), osascript, Quartz session state,
display info, and AX trust.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* GUI probe v3: try 5 approaches to unlock WarpBuild screen

1. defaults write (screensaver, loginwindow, pmset)
2. automationmodetool enable-automationmode-without-authentication
3. CGSSessionSetScreenLocked private API + System Events keystroke
4. sysadminctl -screenLock off + keychain unlock
5. CGEvent simulation (mouse move + Return key to dismiss lock)

Each approach is followed by an activation check to see if it worked.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Test GUI activation on macOS 14, 15, and 26 (Tahoe)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Add DerivedData and GhosttyKit caching to CI workflows

Major caching improvements across ci.yml and ci-macos-compat.yml:

- Cache GhosttyKit.xcframework keyed on ghostty submodule SHA
  (skip download on cache hit)
- Cache DerivedData keyed on OS + Xcode version + Package.resolved +
  project.pbxproj (enables incremental builds across runs)
- Remove explicit DerivedData wipe (rely on cache key invalidation)
- Use download-prebuilt-ghosttykit.sh in compat workflow too

This should significantly speed up macOS 14 compat tests which were
taking 20+ min due to full recompilation every run.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Bump macOS 14 compat timeout to 45 min for cold cache seeding

The DerivedData cache wasn't saved because the job timed out at 30 min,
causing the post-job cache save step to be skipped. 45 min gives enough
headroom for the first uncached run to complete and seed the cache.
Subsequent runs should be much faster with incremental builds.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Use Depot runners for E2E tests (WarpBuild has screen lock on macOS 15/26)

WarpBuild VMs on macOS 15 and 26 have CGSSessionScreenIsLocked=1, which
prevents XCUIApplication activation. Depot runners have working GUI
activation. Can switch back to WarpBuild once they fix the VM images.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Skip smoke test on macOS 14 compat, remove GUI diagnostic workflow

macOS 14 was slow because it built the full app (cmux scheme) on top of
unit tests (cmux-unit scheme). Unit tests are the real compat check;
smoke test runs on macOS 15 only. Also removes the temporary
test-warpbuild-gui.yml diagnostic workflow.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Replace Sonoma with Tahoe in compat matrix, drop macOS 14

Swap macOS 14 (Sonoma) for macOS 26 (Tahoe). Smoke test runs on
macOS 15 only (WarpBuild screen lock blocks app activation on 26).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Drop macOS 26 from compat matrix (zig 0.15.2 linker failure)

Zig 0.15.2 can't link against the macOS 26 (Tahoe) SDK: undefined
symbols for basic libc functions (_abort, _free, _fork, etc.). The zig
toolchain needs an update to support Tahoe. Keep macOS 15 only for now.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* Fix release browser portal compile

* Add macOS 26 (Tahoe) compat tests, skip zig build via stub (manaflow-ai#1590)

Zig 0.15.2's MachO linker can't resolve libSystem on macOS 26 (the
version number jump from 15 to 26 breaks zig's SDK handling). The unit
tests don't need the CLI helper binary at runtime, so we skip the zig
build on macOS 26 by setting CMUX_SKIP_ZIG_BUILD=1, which creates a
stub binary to satisfy the Xcode Run Script file check.

Smoke test (full app build + launch) is skipped on macOS 26 since it
needs the real CLI helper.

Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Add regression tests for SSH remote CLI follow-ups

* Fix SSH remote CLI and loopback proxy follow-ups

* Fix remote daemon build script using relative output path after cd (manaflow-ai#1595)

The Go build runs in a subshell that cd's to daemon/remote/, but
OUTPUT_DIR was relative to the repo root. Resolve to absolute path
after mkdir so go build -o writes to the correct location.

Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Address SSH follow-up PR review comments

* fix: restore Sparkle automatic update checks (manaflow-ai#1597)

* feat: add native MCP protocol support to socket server

Add MCP (Model Context Protocol) Content-Length framing support directly
to the cmux socket server, enabling AI tools to connect via socat without
needing a separate Node.js MCP wrapper process.

Protocol detection on first read: "Content-Length:" → MCP mode,
"{" → V2 JSON-RPC, else V1 plain text. All three protocols coexist
on the same Unix socket.

New files:
- MCPServer.swift: Content-Length framing parser, MCPHandler with 3
  JSON-RPC methods (initialize, tools/list, tools/call), and 20 MCP
  tool schemas that route to existing V2 socket methods
- MCPServerTests.swift: 28 unit tests covering framing, handler logic,
  and tool routing

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: address MCP server review findings

- Fix test initialization: tests calling tools/list and tools/call
  now send initialize first (XCTest creates fresh instances per test)
- Add testToolsListBeforeInitializeReturnsError to cover the guard
- Fix MCP message loop: continue parsing after each message instead
  of breaking after one, avoiding latency when multiple messages
  arrive in a single socket read
- Forward press_enter param in send_input tool routing
- Quote V1 command arguments to prevent injection via tokenizer
- Add writeSocketData helper with EINTR/partial-write handling
- Add encodeResponse fallback for non-serializable dicts
- Require initialized handshake before tools/list and tools/call
- Reject MCP connections when password auth is required
- Close connection on corrupted data after MCP detection

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.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: Austin Wang <austinwang115@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
bn-l pushed a commit to bn-l/cmux that referenced this pull request Apr 3, 2026
…ai#1590)

Zig 0.15.2's MachO linker can't resolve libSystem on macOS 26 (the
version number jump from 15 to 26 breaks zig's SDK handling). The unit
tests don't need the CLI helper binary at runtime, so we skip the zig
build on macOS 26 by setting CMUX_SKIP_ZIG_BUILD=1, which creates a
stub binary to satisfy the Xcode Run Script file check.

Smoke test (full app build + launch) is skipped on macOS 26 since it
needs the real CLI helper.

Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

This branch was successfully deployed

1 active deployment
Preview — 4f356a10 Deployed Mar 17, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant