Skip to content

Migrate CI/CD to WarpBuild, consolidate test jobs - #1501

Merged
lawrencecchen merged 25 commits into
mainfrom
task-migrate-warpcloud-consolidated
Mar 17, 2026
Merged

lawrencecchen merged 25 commits into
mainfrom
task-migrate-warpcloud-consolidated

Conversation

@lawrencecchen

@lawrencecchen lawrencecchen commented Mar 16, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Swaps all macOS runner labels to WarpBuild and consolidates CI test jobs.

  • depot-macos-latest → warp-macos-15-arm64-6x
  • macos-15 → warp-macos-15-arm64-6x
  • macos-14 → warp-macos-14-arm64-6x
  • ubuntu-latest unchanged for lightweight jobs
  • Merges tests + tests-depot into a single tests job that runs unit tests, regressions, UI tests, and lag tests sequentially on one WarpBuild runner (net -66 lines in ci.yml)
  • Updated CI guard test and comments

Affected workflows: ci.yml, build-ghosttykit.yml, ci-macos-compat.yml, nightly.yml, release.yml, test-depot.yml, test-e2e.yml

Compare with https://github.com/manaflow-ai/cmux/pull/new/task-migrate-warpcloud (keeps separate jobs for speed).

Tradeoff: consolidated runs all tests sequentially on one runner (~slower wall time), but eliminates duplicated checkout/build setup and uses one runner instead of two per CI run.

Testing

  • Guard test passes locally: bash tests/test_ci_self_hosted_guard.sh → PASS
  • No old runner labels remain: grep -rn 'depot-macos-latest\|runs-on: macos-1[45]' .github/workflows/ → empty

🤖 Generated with Claude Code


Summary by cubic

Migrates macOS CI/CD to WarpBuild, consolidates tests, adds caching, and pins zig 0.15.2 for reproducible builds. UI tests on WarpBuild are replaced with build + typing‑lag; full interactive E2E UI tests run on Depot; macOS compat now runs a smoke test on macOS 15 only (dropped 26 due to zig linker issues).

  • Refactors

    • Switch macOS jobs to warp-macos-15-arm64-6x; drop macOS 26 from compat; keep ubuntu-latest; set 20‑min timeouts
    • Consolidate unit/regression into a guarded tests job; add guarded tests-build-and-lag (builds cmux, runs typing‑lag); guard script enforces both
    • Add caches: GhosttyKit.xcframework keyed by ghostty SHA; Xcode DerivedData keyed by OS/Xcode/Package.resolved/project; use scripts/download-prebuilt-ghosttykit.sh
    • E2E: test-e2e.yml defaults to depot-macos-latest (also depot-macos-14) for GUI activation
  • Bug Fixes

    • Pin zig 0.15.2 via tarball across workflows (fix tarball URL; create /usr/local/bin and /usr/local/lib; verify version even if preinstalled)
    • Strengthen paid‑runner fork guards in CI and update the guard test to validate both guarded test jobs

Written for commit 5519992. Summary will update on new commits.

Summary by CodeRabbit

  • Chores
    • Migrated CI/CD workflows to WarpBuild-hosted macOS runners and expanded architecture coverage.
    • Added explicit tool-version verification with tarball-based installation fallback to stabilize builds.
    • Removed an obsolete test job and refined Xcode selection for more reliable macOS build environments.
    • Strengthened CI guards to better detect fork PRs and validate runners.

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>
@vercel

vercel Bot commented Mar 16, 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 7:54am

@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.

@lawrencecchen

Copy link
Copy Markdown
Contributor Author

Compare with separate-jobs version: #1500

@coderabbitai

coderabbitai Bot commented Mar 16, 2026 •

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

CI workflows switch runner labels to WarpBuild images, enforce Zig version 0.15.2 with a tarball-based install, add a fork-PR guard and dynamic Xcode discovery in ci.yml, and remove the old tests-depot job and Depot-specific steps.

Changes

Cohort / File(s) Summary
Runner image updates
.github/workflows/build-ghosttykit.yml, .github/workflows/nightly.yml, .github/workflows/release.yml, .github/workflows/test-depot.yml, .github/workflows/ci.yml
Replaced depot-macos-latest / macos-15 runs-on values with warp-macos-*-arm64-6x runner labels.
Matrix & cache adjustments
.github/workflows/ci-macos-compat.yml, .github/workflows/test-e2e.yml
Updated matrix OS values, default runs-on, inputs, and Swift package cache/restore keys to use WarpBuild runner labels.
Zig versioned install
.github/workflows/* (build-ghosttykit, ci-macos-compat, ci, nightly, release, test-depot, test-e2e)
Introduce ZIG_REQUIRED="0.15.2" and replace brew fallback with exact-version check and tarball download/extract/copy to /usr/local, PATH update, and zig version verification.
Core CI refactor
.github/workflows/ci.yml
Renamed guard step, added fork-PR guard to skip WarpBuild jobs on forks, removed tests-depot job, switched tests job to WarpBuild runner, and implemented dynamic Xcode discovery under /Applications.
CI guard test
tests/test_ci_self_hosted_guard.sh
Updated header and awk matching to check tests:, changed runner check to runs-on: warp-macos-15-arm64-6x, adjusted guard variables/messages from Depot to WarpBuild, and updated fork-guard logic.

Sequence Diagram(s)

sequenceDiagram
  participant GH as GitHub Actions
  participant Runner as WarpBuild Runner
  participant FS as Filesystem (/Applications)
  participant ZigHost as ziglang.org
  participant Build as Build Steps

  GH->>Runner: start job (runs-on: warp-macos-*-arm64-6x)
  Runner->>FS: check /Applications/Xcode.app/Contents/Developer
  alt Developer dir exists
    FS-->>Runner: set DEVELOPER_DIR (fixed path)
  else
    FS->>FS: find latest Xcode*.app
    alt found
      FS-->>Runner: set DEVELOPER_DIR (found path)
    else
      FS-->>Runner: fail (no Xcode)
    end
  end
  Runner->>Runner: check `zig` binary version
  alt zig matches ZIG_REQUIRED
    Runner-->>Build: proceed (use existing zig)
  else
    Runner->>ZigHost: download Zig tarball for macOS aarch64
    ZigHost-->>Runner: tarball
    Runner->>Runner: extract, copy `zig` and libs to /usr/local, update PATH
    Runner-->>Build: verify zig version then proceed
  end
  Runner->>Build: run checkout, caches, build, tests (tests-depot job removed)
  Build-->>GH: report job result
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

codex

Poem

🐰 I hopped from Depot to Warp with glee,
Zig snug in a tarball — versioned for me.
I sniffed for Xcode beneath Applications' trees,
A fork-guard now watches, tests run with new keys.
CI pranced ahead — builds ready, swift, and free.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main changes: migration to WarpBuild and consolidation of test jobs, which aligns with the substantial refactoring across multiple workflow files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description check ✅ Passed PR description exceeds template structure with detailed summaries by multiple tools (cubic, Claude Code) and comprehensive technical details about the migration.

✏️ 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 task-migrate-warpcloud-consolidated
📝 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 8 files

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 64d83a7dea

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/workflows/ci.yml
tests:
runs-on: macos-15
# Never run WarpBuild jobs for fork pull requests (avoid billing on external PRs).
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Keep macOS test coverage for fork pull requests

This new job-level guard skips tests for every fork PR, and this commit also removed the separate tests-depot job, so fork contributions now run no macOS unit/UI/lag tests at all. In practice that means external PRs can go green with only Ubuntu checks, allowing macOS regressions to land undetected until after merge; a non-self-hosted fallback test path is still needed for fork PRs.

Useful? React with 👍 / 👎.

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/workflows/test-depot.yml (1)

1-1: ⚠️ Potential issue | 🟡 Minor

Workflow name is now inconsistent with runner.

The workflow is named "Run tests on Depot" but now runs on WarpBuild. Consider updating the name for clarity:

-name: Run tests on Depot
+name: Run tests on WarpBuild
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/test-depot.yml at line 1, The workflow name "Run tests on
Depot" is inconsistent with the runner (WarpBuild); update the workflow's name
string to reflect the actual runner or purpose (e.g., "Run tests on WarpBuild"
or "Run tests on Depot (WarpBuild)") by editing the top-level name value in the
workflow YAML so it matches the runner configuration and intent.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In @.github/workflows/test-depot.yml:
- Line 1: The workflow name "Run tests on Depot" is inconsistent with the runner
(WarpBuild); update the workflow's name string to reflect the actual runner or
purpose (e.g., "Run tests on WarpBuild" or "Run tests on Depot (WarpBuild)") by
editing the top-level name value in the workflow YAML so it matches the runner
configuration and intent.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: dd5e182e-a9ae-42de-80a7-a4f2933542d6

📥 Commits

Reviewing files that changed from the base of the PR and between 2e4c482 and 64d83a7.

📒 Files selected for processing (8)
  • .github/workflows/build-ghosttykit.yml
  • .github/workflows/ci-macos-compat.yml
  • .github/workflows/ci.yml
  • .github/workflows/nightly.yml
  • .github/workflows/release.yml
  • .github/workflows/test-depot.yml
  • .github/workflows/test-e2e.yml
  • tests/test_ci_self_hosted_guard.sh

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>

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 70e6da4ed5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/workflows/build-ghosttykit.yml Outdated
Comment on lines 67 to 69
else
brew upgrade zig 2>/dev/null || true
else

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Fix malformed zig install conditional

The Build GhosttyKit.xcframework script now has a mis-nested if block: the new else before brew upgrade zig appears before the inner if command -v brew is closed, which makes the shell script syntactically invalid. When this step executes (for commits where the xcframework release does not already exist), bash fails with syntax error near unexpected token 'else', and the workflow cannot build or publish GhosttyKit.xcframework.

Useful? React with 👍 / 👎.

@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.

1 issue found across 7 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name=".github/workflows/build-ghosttykit.yml">

<violation number="1" location=".github/workflows/build-ghosttykit.yml:67">
P1: The inserted `else` creates an invalid shell `if` structure, so this CI step will fail to parse at runtime.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread .github/workflows/build-ghosttykit.yml

@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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/build-ghosttykit.yml:
- Around line 64-69: The shell conditional for installing Zig is malformed due
to duplicated else branches; fix the if/else/fi nesting around the checks for
`command -v zig` and `command -v brew` so there is a single inner else and
proper closing `fi`s. Concretely, ensure the block reads: if Zig is missing
(`command -v zig`), then check for Homebrew (`command -v brew`); if brew is
present run `brew install zig` (or `brew upgrade zig` as fallback), otherwise
handle the no-brew case (echo error/exit); close the inner and outer
conditionals with `fi` to remove the extra `else`.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7520e48b-c379-477f-a755-8e8425000713

📥 Commits

Reviewing files that changed from the base of the PR and between 64d83a7 and 70e6da4.

📒 Files selected for processing (7)
  • .github/workflows/build-ghosttykit.yml
  • .github/workflows/ci-macos-compat.yml
  • .github/workflows/ci.yml
  • .github/workflows/nightly.yml
  • .github/workflows/release.yml
  • .github/workflows/test-depot.yml
  • .github/workflows/test-e2e.yml

Comment thread .github/workflows/build-ghosttykit.yml Outdated
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>

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: faad21d3fb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/workflows/ci.yml
tests:
runs-on: macos-15
# Never run WarpBuild jobs for fork pull requests (avoid billing on external PRs).
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Restore macOS coverage for fork pull requests

This guard makes the only tests job skip all fork PRs, and this commit also removes the separate tests-depot job, so external contributions now run no macOS unit/UI/lag tests in CI. In practice, fork PRs can pass with only Ubuntu checks, allowing macOS regressions to merge undetected unless a maintainer manually reruns coverage on an internal branch.

Useful? React with 👍 / 👎.

@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.

9 issues found across 7 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name=".github/workflows/test-e2e.yml">

<violation number="1" location=".github/workflows/test-e2e.yml:103">
P2: Replace the Zig lib directory instead of recursively nesting it; the current copy command can leave stale stdlib files and break upgrades.</violation>
</file>

<file name=".github/workflows/release.yml">

<violation number="1" location=".github/workflows/release.yml:107">
P1: Verify the Zig tarball checksum before extracting it; the current flow executes an unverified downloaded binary.</violation>

<violation number="2" location=".github/workflows/release.yml:110">
P2: Replace the existing Zig lib directory before copying; otherwise `cp` can create `/usr/local/lib/zig/lib` and leave stale libs active.</violation>
</file>

<file name=".github/workflows/nightly.yml">

<violation number="1" location=".github/workflows/nightly.yml:159">
P2: Verify the downloaded Zig tarball before installing; it is currently executed/installed without integrity validation.</violation>

<violation number="2" location=".github/workflows/nightly.yml:162">
P1: Copying Zig's `lib` directory this way can leave an old stdlib in place during upgrades.</violation>
</file>

<file name=".github/workflows/build-ghosttykit.yml">

<violation number="1" location=".github/workflows/build-ghosttykit.yml:69">
P1: Verify the downloaded Zig tarball (pinned checksum or signature) before extracting/installing it.</violation>
</file>

<file name=".github/workflows/ci.yml">

<violation number="1" location=".github/workflows/ci.yml:87">
P2: Use an exact version match for `zig version`; the current grep pattern is prefix-based and can accept unintended versions.</violation>

<violation number="2" location=".github/workflows/ci.yml:91">
P1: Verify the Zig tarball checksum/signature before extraction and install to avoid untrusted toolchain injection in CI.</violation>
</file>

<file name=".github/workflows/test-depot.yml">

<violation number="1" location=".github/workflows/test-depot.yml:92">
P1: Verify the Zig tarball integrity before extracting/copying it; the current flow trusts an unverified downloaded compiler binary.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread .github/workflows/release.yml Outdated
echo "zig ${ZIG_REQUIRED} already installed"
else
echo "Installing zig ${ZIG_REQUIRED} from tarball"
curl -fSL "https://ziglang.org/download/${ZIG_REQUIRED}/zig-macos-aarch64-${ZIG_REQUIRED}.tar.xz" -o /tmp/zig.tar.xz

@cubic-dev-ai cubic-dev-ai Bot Mar 16, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1: Verify the Zig tarball checksum before extracting it; the current flow executes an unverified downloaded binary.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/release.yml, line 107:

<comment>Verify the Zig tarball checksum before extracting it; the current flow executes an unverified downloaded binary.</comment>

<file context>
@@ -99,10 +99,17 @@ jobs:
           else
-            brew upgrade zig 2>/dev/null || true
+            echo "Installing zig ${ZIG_REQUIRED} from tarball"
+            curl -fSL "https://ziglang.org/download/${ZIG_REQUIRED}/zig-macos-aarch64-${ZIG_REQUIRED}.tar.xz" -o /tmp/zig.tar.xz
+            tar xf /tmp/zig.tar.xz -C /tmp
+            sudo cp -f /tmp/zig-macos-aarch64-${ZIG_REQUIRED}/zig /usr/local/bin/zig
</file context>
Suggested change
curl -fSL "https://ziglang.org/download/${ZIG_REQUIRED}/zig-macos-aarch64-${ZIG_REQUIRED}.tar.xz" -o /tmp/zig.tar.xz
curl -fSL "https://ziglang.org/download/${ZIG_REQUIRED}/zig-macos-aarch64-${ZIG_REQUIRED}.tar.xz" -o /tmp/zig.tar.xz
ZIG_SHA256="$(curl -fsSL https://ziglang.org/download/index.json | ZIG_REQUIRED="$ZIG_REQUIRED" python3 -c 'import json,os,sys; d=json.load(sys.stdin); print(d[os.environ["ZIG_REQUIRED"]]["aarch64-macos"]["shasum"])')"
echo "${ZIG_SHA256} /tmp/zig.tar.xz" | shasum -a 256 -c -
Fix with Cubic

Comment thread .github/workflows/nightly.yml Outdated
curl -fSL "https://ziglang.org/download/${ZIG_REQUIRED}/zig-macos-aarch64-${ZIG_REQUIRED}.tar.xz" -o /tmp/zig.tar.xz
tar xf /tmp/zig.tar.xz -C /tmp
sudo cp -f /tmp/zig-macos-aarch64-${ZIG_REQUIRED}/zig /usr/local/bin/zig
sudo cp -rf /tmp/zig-macos-aarch64-${ZIG_REQUIRED}/lib /usr/local/lib/zig

@cubic-dev-ai cubic-dev-ai Bot Mar 16, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1: Copying Zig's lib directory this way can leave an old stdlib in place during upgrades.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/nightly.yml, line 162:

<comment>Copying Zig's `lib` directory this way can leave an old stdlib in place during upgrades.</comment>

<file context>
@@ -151,10 +151,17 @@ jobs:
+            curl -fSL "https://ziglang.org/download/${ZIG_REQUIRED}/zig-macos-aarch64-${ZIG_REQUIRED}.tar.xz" -o /tmp/zig.tar.xz
+            tar xf /tmp/zig.tar.xz -C /tmp
+            sudo cp -f /tmp/zig-macos-aarch64-${ZIG_REQUIRED}/zig /usr/local/bin/zig
+            sudo cp -rf /tmp/zig-macos-aarch64-${ZIG_REQUIRED}/lib /usr/local/lib/zig
+            export PATH="/usr/local/bin:$PATH"
+            zig version
</file context>
Suggested change
sudo cp -rf /tmp/zig-macos-aarch64-${ZIG_REQUIRED}/lib /usr/local/lib/zig
sudo rm -rf /usr/local/lib/zig
sudo mkdir -p /usr/local/lib/zig
sudo cp -rf /tmp/zig-macos-aarch64-${ZIG_REQUIRED}/lib/. /usr/local/lib/zig/
Fix with Cubic

Comment thread .github/workflows/build-ghosttykit.yml Outdated
echo "zig ${ZIG_REQUIRED} already installed"
else
echo "Installing zig ${ZIG_REQUIRED} from tarball"
curl -fSL "https://ziglang.org/download/${ZIG_REQUIRED}/zig-macos-aarch64-${ZIG_REQUIRED}.tar.xz" -o /tmp/zig.tar.xz

@cubic-dev-ai cubic-dev-ai Bot Mar 16, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1: Verify the downloaded Zig tarball (pinned checksum or signature) before extracting/installing it.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/build-ghosttykit.yml, line 69:

<comment>Verify the downloaded Zig tarball (pinned checksum or signature) before extracting/installing it.</comment>

<file context>
@@ -61,15 +61,17 @@ jobs:
-              exit 1
-            fi
+            echo "Installing zig ${ZIG_REQUIRED} from tarball"
+            curl -fSL "https://ziglang.org/download/${ZIG_REQUIRED}/zig-macos-aarch64-${ZIG_REQUIRED}.tar.xz" -o /tmp/zig.tar.xz
+            tar xf /tmp/zig.tar.xz -C /tmp
+            sudo cp -f /tmp/zig-macos-aarch64-${ZIG_REQUIRED}/zig /usr/local/bin/zig
</file context>
Fix with Cubic

Comment thread .github/workflows/ci.yml Outdated
echo "zig ${ZIG_REQUIRED} already installed"
else
echo "Installing zig ${ZIG_REQUIRED} from tarball"
curl -fSL "https://ziglang.org/download/${ZIG_REQUIRED}/zig-macos-aarch64-${ZIG_REQUIRED}.tar.xz" -o /tmp/zig.tar.xz

@cubic-dev-ai cubic-dev-ai Bot Mar 16, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1: Verify the Zig tarball checksum/signature before extraction and install to avoid untrusted toolchain injection in CI.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/ci.yml, line 91:

<comment>Verify the Zig tarball checksum/signature before extraction and install to avoid untrusted toolchain injection in CI.</comment>

<file context>
@@ -83,10 +83,17 @@ jobs:
           else
-            brew upgrade zig 2>/dev/null || true
+            echo "Installing zig ${ZIG_REQUIRED} from tarball"
+            curl -fSL "https://ziglang.org/download/${ZIG_REQUIRED}/zig-macos-aarch64-${ZIG_REQUIRED}.tar.xz" -o /tmp/zig.tar.xz
+            tar xf /tmp/zig.tar.xz -C /tmp
+            sudo cp -f /tmp/zig-macos-aarch64-${ZIG_REQUIRED}/zig /usr/local/bin/zig
</file context>
Fix with Cubic

Comment thread .github/workflows/test-depot.yml Outdated
echo "zig ${ZIG_REQUIRED} already installed"
else
echo "Installing zig ${ZIG_REQUIRED} from tarball"
curl -fSL "https://ziglang.org/download/${ZIG_REQUIRED}/zig-macos-aarch64-${ZIG_REQUIRED}.tar.xz" -o /tmp/zig.tar.xz

@cubic-dev-ai cubic-dev-ai Bot Mar 16, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1: Verify the Zig tarball integrity before extracting/copying it; the current flow trusts an unverified downloaded compiler binary.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/test-depot.yml, line 92:

<comment>Verify the Zig tarball integrity before extracting/copying it; the current flow trusts an unverified downloaded compiler binary.</comment>

<file context>
@@ -84,10 +84,17 @@ jobs:
           else
-            brew upgrade zig 2>/dev/null || true
+            echo "Installing zig ${ZIG_REQUIRED} from tarball"
+            curl -fSL "https://ziglang.org/download/${ZIG_REQUIRED}/zig-macos-aarch64-${ZIG_REQUIRED}.tar.xz" -o /tmp/zig.tar.xz
+            tar xf /tmp/zig.tar.xz -C /tmp
+            sudo cp -f /tmp/zig-macos-aarch64-${ZIG_REQUIRED}/zig /usr/local/bin/zig
</file context>
Fix with Cubic

Comment thread .github/workflows/test-e2e.yml Outdated
curl -fSL "https://ziglang.org/download/${ZIG_REQUIRED}/zig-macos-aarch64-${ZIG_REQUIRED}.tar.xz" -o /tmp/zig.tar.xz
tar xf /tmp/zig.tar.xz -C /tmp
sudo cp -f /tmp/zig-macos-aarch64-${ZIG_REQUIRED}/zig /usr/local/bin/zig
sudo cp -rf /tmp/zig-macos-aarch64-${ZIG_REQUIRED}/lib /usr/local/lib/zig

@cubic-dev-ai cubic-dev-ai Bot Mar 16, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: Replace the Zig lib directory instead of recursively nesting it; the current copy command can leave stale stdlib files and break upgrades.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/test-e2e.yml, line 103:

<comment>Replace the Zig lib directory instead of recursively nesting it; the current copy command can leave stale stdlib files and break upgrades.</comment>

<file context>
@@ -92,10 +92,17 @@ jobs:
+            curl -fSL "https://ziglang.org/download/${ZIG_REQUIRED}/zig-macos-aarch64-${ZIG_REQUIRED}.tar.xz" -o /tmp/zig.tar.xz
+            tar xf /tmp/zig.tar.xz -C /tmp
+            sudo cp -f /tmp/zig-macos-aarch64-${ZIG_REQUIRED}/zig /usr/local/bin/zig
+            sudo cp -rf /tmp/zig-macos-aarch64-${ZIG_REQUIRED}/lib /usr/local/lib/zig
+            export PATH="/usr/local/bin:$PATH"
+            zig version
</file context>
Suggested change
sudo cp -rf /tmp/zig-macos-aarch64-${ZIG_REQUIRED}/lib /usr/local/lib/zig
sudo rm -rf /usr/local/lib/zig
sudo mkdir -p /usr/local/lib/zig
sudo cp -Rf /tmp/zig-macos-aarch64-${ZIG_REQUIRED}/lib/. /usr/local/lib/zig/
Fix with Cubic

Comment thread .github/workflows/release.yml Outdated
curl -fSL "https://ziglang.org/download/${ZIG_REQUIRED}/zig-macos-aarch64-${ZIG_REQUIRED}.tar.xz" -o /tmp/zig.tar.xz
tar xf /tmp/zig.tar.xz -C /tmp
sudo cp -f /tmp/zig-macos-aarch64-${ZIG_REQUIRED}/zig /usr/local/bin/zig
sudo cp -rf /tmp/zig-macos-aarch64-${ZIG_REQUIRED}/lib /usr/local/lib/zig

@cubic-dev-ai cubic-dev-ai Bot Mar 16, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: Replace the existing Zig lib directory before copying; otherwise cp can create /usr/local/lib/zig/lib and leave stale libs active.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/release.yml, line 110:

<comment>Replace the existing Zig lib directory before copying; otherwise `cp` can create `/usr/local/lib/zig/lib` and leave stale libs active.</comment>

<file context>
@@ -99,10 +99,17 @@ jobs:
+            curl -fSL "https://ziglang.org/download/${ZIG_REQUIRED}/zig-macos-aarch64-${ZIG_REQUIRED}.tar.xz" -o /tmp/zig.tar.xz
+            tar xf /tmp/zig.tar.xz -C /tmp
+            sudo cp -f /tmp/zig-macos-aarch64-${ZIG_REQUIRED}/zig /usr/local/bin/zig
+            sudo cp -rf /tmp/zig-macos-aarch64-${ZIG_REQUIRED}/lib /usr/local/lib/zig
+            export PATH="/usr/local/bin:$PATH"
+            zig version
</file context>
Suggested change
sudo cp -rf /tmp/zig-macos-aarch64-${ZIG_REQUIRED}/lib /usr/local/lib/zig
sudo rm -rf /usr/local/lib/zig
sudo cp -R /tmp/zig-macos-aarch64-${ZIG_REQUIRED}/lib /usr/local/lib/zig
Fix with Cubic

Comment thread .github/workflows/nightly.yml Outdated
echo "zig ${ZIG_REQUIRED} already installed"
else
echo "Installing zig ${ZIG_REQUIRED} from tarball"
curl -fSL "https://ziglang.org/download/${ZIG_REQUIRED}/zig-macos-aarch64-${ZIG_REQUIRED}.tar.xz" -o /tmp/zig.tar.xz

@cubic-dev-ai cubic-dev-ai Bot Mar 16, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: Verify the downloaded Zig tarball before installing; it is currently executed/installed without integrity validation.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/nightly.yml, line 159:

<comment>Verify the downloaded Zig tarball before installing; it is currently executed/installed without integrity validation.</comment>

<file context>
@@ -151,10 +151,17 @@ jobs:
           else
-            brew upgrade zig 2>/dev/null || true
+            echo "Installing zig ${ZIG_REQUIRED} from tarball"
+            curl -fSL "https://ziglang.org/download/${ZIG_REQUIRED}/zig-macos-aarch64-${ZIG_REQUIRED}.tar.xz" -o /tmp/zig.tar.xz
+            tar xf /tmp/zig.tar.xz -C /tmp
+            sudo cp -f /tmp/zig-macos-aarch64-${ZIG_REQUIRED}/zig /usr/local/bin/zig
</file context>
Fix with Cubic

Comment thread .github/workflows/ci.yml
if ! command -v zig >/dev/null 2>&1; then
brew install zig
ZIG_REQUIRED="0.15.2"
if command -v zig >/dev/null 2>&1 && zig version 2>/dev/null | grep -q "^${ZIG_REQUIRED}"; then

@cubic-dev-ai cubic-dev-ai Bot Mar 16, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: Use an exact version match for zig version; the current grep pattern is prefix-based and can accept unintended versions.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/ci.yml, line 87:

<comment>Use an exact version match for `zig version`; the current grep pattern is prefix-based and can accept unintended versions.</comment>

<file context>
@@ -83,10 +83,17 @@ jobs:
-          if ! command -v zig >/dev/null 2>&1; then
-            brew install zig
+          ZIG_REQUIRED="0.15.2"
+          if command -v zig >/dev/null 2>&1 && zig version 2>/dev/null | grep -q "^${ZIG_REQUIRED}"; then
+            echo "zig ${ZIG_REQUIRED} already installed"
           else
</file context>
Suggested change
if command -v zig >/dev/null 2>&1 && zig version 2>/dev/null | grep -q "^${ZIG_REQUIRED}"; then
if command -v zig >/dev/null 2>&1 && zig version 2>/dev/null | grep -Fxq "${ZIG_REQUIRED}"; then
Fix with Cubic

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

@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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/test-depot.yml:
- Line 31: Add an actionlint configuration that declares the custom runner
labels so actionlint won't flag them: create/update the actionlint YAML config
and set allowed_runner_labels (or allowed-runners depending on your actionlint
version) to include "warp-macos-14-arm64-6x" and "warp-macos-15-arm64-6x";
ensure the config is valid YAML and committed to the repository so workflows
using runs-on: warp-macos-14-arm64-6x and runs-on: warp-macos-15-arm64-6x are
recognized.
- Around line 87-98: The Zig tarball is downloaded and extracted without
checksum verification; modify the install block that references ZIG_REQUIRED to
fetch Zig's published SHA-256 from https://ziglang.org/download/index.json (or
the specific shasum entry for the macOS aarch64 tarball), compare the downloaded
/tmp/zig.tar.xz SHA-256 against that published value (use shasum -a 256 or
sha256sum and fail the script on mismatch) and only proceed to tar/ cp/ install
if the checksum matches; apply the same checksum verification pattern to the
other workflows that download Zig (test-e2e.yml, build-ghosttykit.yml,
release.yml, nightly.yml, ci.yml, ci-macos-compat.yml) so all Zig downloads
validate integrity before extraction.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 793fac7a-f4bf-4920-989b-be7865e5de1b

📥 Commits

Reviewing files that changed from the base of the PR and between 70e6da4 and faad21d.

📒 Files selected for processing (7)
  • .github/workflows/build-ghosttykit.yml
  • .github/workflows/ci-macos-compat.yml
  • .github/workflows/ci.yml
  • .github/workflows/nightly.yml
  • .github/workflows/release.yml
  • .github/workflows/test-depot.yml
  • .github/workflows/test-e2e.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/test-e2e.yml

jobs:
tests:
runs-on: depot-macos-latest
runs-on: warp-macos-15-arm64-6x

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Warp labels referenced in workflows =="
rg -n 'warp-macos-(14|15)-arm64-6x' .github/workflows

echo "== actionlint config files present =="
fd -HI 'actionlint.(yml|yaml)|\.actionlint.(yml|yaml)'

for f in $(fd -HI 'actionlint.(yml|yaml)|\.actionlint.(yml|yaml)'); do
  echo "---- $f ----"
  sed -n '1,200p' "$f"
done

Repository: manaflow-ai/cmux

Length of output: 1269


Configure actionlint for custom WarpBuild runner labels.

The custom runner labels warp-macos-14-arm64-6x and warp-macos-15-arm64-6x are used across multiple workflows but no actionlint config exists to declare them. Without this configuration, actionlint will flag these labels as invalid during lint checks.

Proposed config addition
+# .github/actionlint.yaml
+self-hosted-runner:
+  labels:
+    - warp-macos-14-arm64-6x
+    - warp-macos-15-arm64-6x
🧰 Tools
🪛 actionlint (1.7.11)

[error] 31-31: label "warp-macos-15-arm64-6x" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2025", "windows-2025-vs2026", "windows-2022", "windows-11-arm", "ubuntu-slim", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-24.04-arm", "ubuntu-22.04", "ubuntu-22.04-arm", "macos-latest", "macos-latest-xlarge", "macos-latest-large", "macos-26-xlarge", "macos-26-large", "macos-26", "macos-15-intel", "macos-15-xlarge", "macos-15-large", "macos-15", "macos-14-xlarge", "macos-14-large", "macos-14", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file

(runner-label)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/test-depot.yml at line 31, Add an actionlint configuration
that declares the custom runner labels so actionlint won't flag them:
create/update the actionlint YAML config and set allowed_runner_labels (or
allowed-runners depending on your actionlint version) to include
"warp-macos-14-arm64-6x" and "warp-macos-15-arm64-6x"; ensure the config is
valid YAML and committed to the repository so workflows using runs-on:
warp-macos-14-arm64-6x and runs-on: warp-macos-15-arm64-6x are recognized.

Comment on lines +87 to 98
ZIG_REQUIRED="0.15.2"
if command -v zig >/dev/null 2>&1 && zig version 2>/dev/null | grep -q "^${ZIG_REQUIRED}"; then
echo "zig ${ZIG_REQUIRED} already installed"
else
echo "Installing zig ${ZIG_REQUIRED} from tarball"
curl -fSL "https://ziglang.org/download/${ZIG_REQUIRED}/zig-macos-aarch64-${ZIG_REQUIRED}.tar.xz" -o /tmp/zig.tar.xz
tar xf /tmp/zig.tar.xz -C /tmp
sudo cp -f /tmp/zig-macos-aarch64-${ZIG_REQUIRED}/zig /usr/local/bin/zig
sudo cp -rf /tmp/zig-macos-aarch64-${ZIG_REQUIRED}/lib /usr/local/lib/zig
export PATH="/usr/local/bin:$PATH"
zig version
fi

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Zig download/install sites =="
rg -n 'ziglang.org/download/.*/zig-macos-aarch64-.*\.tar\.xz|/tmp/zig\.tar\.xz' .github/workflows

echo "== Integrity checks currently present =="
rg -n 'shasum -a 256|sha256sum|minisig|cosign|gpg --verify' .github/workflows || true

Repository: manaflow-ai/cmux

Length of output: 2042


🌐 Web query:

Zig official download checksums SHA256 verification

💡 Result:

Where Zig publishes “official” SHA-256 checksums

Zig’s download metadata is published at https://ziglang.org/download/index.json (linked as the “JSON version” of the download page) and includes a shasum field (hex SHA-256) for each downloadable artifact. [1], [4], [3]

Recommended official verification (authenticity): minisign

Zig release archives are signed with minisign; the public key is shown on the official download page. [1]
If you download from community mirrors, you must verify the minisign signature. [2]

Example (download the archive and its .minisig, then verify):

minisign -Vm zig-x86_64-linux-<version>.tar.xz -P "<PUBKEY_FROM_ZIG_DOWNLOAD_PAGE>"

(Usage: minisign -Vm <file> -P <pubkey>.) [5]

SHA-256 integrity check (matches shasum from index.json)

After downloading the file, compute SHA-256 locally and compare to the shasum value from index.json:

Linux

sha256sum zig-x86_64-linux-<version>.tar.xz

macOS

shasum -a 256 zig-x86_64-linux-<version>.tar.xz

Windows (PowerShell / CMD)

certutil -hashfile zig-x86_64-windows-<version>.zip SHA256

If the computed hash equals the shasum from index.json, the download is intact; minisign verification is what proves it’s authentic. [1], [4], [5]


🏁 Script executed:

# Check if there's any Zig verification in the repository or documentation
git ls-files | grep -i zig || true

Repository: manaflow-ai/cmux

Length of output: 42


🏁 Script executed:

# Look at the test-depot.yml file more broadly to understand context
cat -n .github/workflows/test-depot.yml | head -110 | tail -30

Repository: manaflow-ai/cmux

Length of output: 1623


Add SHA-256 integrity verification for Zig tarball downloads.

Lines 92–93 download Zig without checksum verification. Zig publishes official SHA-256 checksums at https://ziglang.org/download/index.json; verify the tarball against the published shasum before extraction. This same gap exists in 6 other workflows (test-e2e.yml, build-ghosttykit.yml, release.yml, nightly.yml, ci.yml, ci-macos-compat.yml).

Hardening example
           ZIG_REQUIRED="0.15.2"
+          ZIG_SHA256="<sha256-from-official-index.json>"
           if command -v zig >/dev/null 2>&1 && zig version 2>/dev/null | grep -q "^${ZIG_REQUIRED}"; then
             echo "zig ${ZIG_REQUIRED} already installed"
           else
             echo "Installing zig ${ZIG_REQUIRED} from tarball"
             curl -fSL "https://ziglang.org/download/${ZIG_REQUIRED}/zig-macos-aarch64-${ZIG_REQUIRED}.tar.xz" -o /tmp/zig.tar.xz
+            echo "${ZIG_SHA256}  /tmp/zig.tar.xz" | shasum -a 256 -c -
             tar xf /tmp/zig.tar.xz -C /tmp
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/test-depot.yml around lines 87 - 98, The Zig tarball is
downloaded and extracted without checksum verification; modify the install block
that references ZIG_REQUIRED to fetch Zig's published SHA-256 from
https://ziglang.org/download/index.json (or the specific shasum entry for the
macOS aarch64 tarball), compare the downloaded /tmp/zig.tar.xz SHA-256 against
that published value (use shasum -a 256 or sha256sum and fail the script on
mismatch) and only proceed to tar/ cp/ install if the checksum matches; apply
the same checksum verification pattern to the other workflows that download Zig
(test-e2e.yml, build-ghosttykit.yml, release.yml, nightly.yml, ci.yml,
ci-macos-compat.yml) so all Zig downloads validate integrity before extraction.

@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.

1 issue found across 7 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name=".github/workflows/build-ghosttykit.yml">

<violation number="1" location=".github/workflows/build-ghosttykit.yml:69">
P1: Validate the Zig tarball (signature or checksum) before extracting/installing it. Installing an unverified network download with `sudo` creates a supply-chain risk in the release build.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

echo "zig ${ZIG_REQUIRED} already installed"
else
echo "Installing zig ${ZIG_REQUIRED} from tarball"
curl -fSL "https://ziglang.org/download/${ZIG_REQUIRED}/zig-aarch64-macos-${ZIG_REQUIRED}.tar.xz" -o /tmp/zig.tar.xz

@cubic-dev-ai cubic-dev-ai Bot Mar 16, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1: Validate the Zig tarball (signature or checksum) before extracting/installing it. Installing an unverified network download with sudo creates a supply-chain risk in the release build.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/build-ghosttykit.yml, line 69:

<comment>Validate the Zig tarball (signature or checksum) before extracting/installing it. Installing an unverified network download with `sudo` creates a supply-chain risk in the release build.</comment>

<file context>
@@ -66,10 +66,10 @@ jobs:
           else
             echo "Installing zig ${ZIG_REQUIRED} from tarball"
-            curl -fSL "https://ziglang.org/download/${ZIG_REQUIRED}/zig-macos-aarch64-${ZIG_REQUIRED}.tar.xz" -o /tmp/zig.tar.xz
+            curl -fSL "https://ziglang.org/download/${ZIG_REQUIRED}/zig-aarch64-macos-${ZIG_REQUIRED}.tar.xz" -o /tmp/zig.tar.xz
             tar xf /tmp/zig.tar.xz -C /tmp
-            sudo cp -f /tmp/zig-macos-aarch64-${ZIG_REQUIRED}/zig /usr/local/bin/zig
</file context>
Fix with Cubic

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

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

@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 (2)
.github/workflows/test-e2e.yml (1)

173-174: Cache key pattern differs from other workflows.

This workflow uses spm-${{ inputs.runner || 'warp-macos-15-arm64-6x' }}-... while:

  • ci.yml uses spm-${{ hashFiles(...) }} (no runner suffix)
  • ci-macos-compat.yml uses spm-${{ matrix.os }}-...

Consider aligning cache key patterns across workflows to improve cache hit rates when the same runner is used.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/test-e2e.yml around lines 173 - 174, The cache key pattern
currently using "spm-${{ inputs.runner || 'warp-macos-15-arm64-6x' }}-..."
should be aligned with other workflows to improve cache hits; update the "key"
and "restore-keys" entries to use the same pattern used elsewhere (either
"spm-${{ hashFiles('...') }}" as in ci.yml or "spm-${{ matrix.os }}-..." as in
ci-macos-compat.yml) so it matches on the same cache namespace—modify the lines
referencing spm-${{ inputs.runner ... }} to the chosen consistent pattern.
.github/workflows/nightly.yml (1)

102-102: Configure actionlint for custom WarpBuild runner labels.

The warp-macos-15-arm64-6x label triggers actionlint errors across all modified workflows. Create .github/actionlint.yaml to declare these custom runner labels.

Proposed actionlint config
# .github/actionlint.yaml
self-hosted-runner:
  labels:
    - warp-macos-14-arm64-6x
    - 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/nightly.yml at line 102, Add an actionlint configuration
that declares the custom self-hosted runner labels used by the workflows so
actionlint stops flagging the runs-on label `warp-macos-15-arm64-6x`; create a
YAML config that defines `self-hosted-runner.labels` and list
`warp-macos-14-arm64-6x`, `warp-macos-15-arm64-6x`, and `warp-macos-26-arm64-6x`
so the workflow runner label `runs-on: warp-macos-15-arm64-6x` is recognized by
actionlint.
🤖 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/nightly.yml:
- Line 102: Add an actionlint configuration that declares the custom self-hosted
runner labels used by the workflows so actionlint stops flagging the runs-on
label `warp-macos-15-arm64-6x`; create a YAML config that defines
`self-hosted-runner.labels` and list `warp-macos-14-arm64-6x`,
`warp-macos-15-arm64-6x`, and `warp-macos-26-arm64-6x` so the workflow runner
label `runs-on: warp-macos-15-arm64-6x` is recognized by actionlint.

In @.github/workflows/test-e2e.yml:
- Around line 173-174: The cache key pattern currently using "spm-${{
inputs.runner || 'warp-macos-15-arm64-6x' }}-..." should be aligned with other
workflows to improve cache hits; update the "key" and "restore-keys" entries to
use the same pattern used elsewhere (either "spm-${{ hashFiles('...') }}" as in
ci.yml or "spm-${{ matrix.os }}-..." as in ci-macos-compat.yml) so it matches on
the same cache namespace—modify the lines referencing spm-${{ inputs.runner ...
}} to the chosen consistent pattern.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 65c881ca-9da3-4b85-b6bf-7ffdbd1a1610

📥 Commits

Reviewing files that changed from the base of the PR and between faad21d and 34c1441.

📒 Files selected for processing (7)
  • .github/workflows/build-ghosttykit.yml
  • .github/workflows/ci-macos-compat.yml
  • .github/workflows/ci.yml
  • .github/workflows/nightly.yml
  • .github/workflows/release.yml
  • .github/workflows/test-depot.yml
  • .github/workflows/test-e2e.yml

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 93e5d45bef

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +107 to +108
curl -fSL "https://ziglang.org/download/${ZIG_REQUIRED}/zig-aarch64-macos-${ZIG_REQUIRED}.tar.xz" -o /tmp/zig.tar.xz
tar xf /tmp/zig.tar.xz -C /tmp

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Verify Zig tarball integrity before running release build

This step downloads and executes a Zig toolchain directly from the network (curl + tar + zig) without any checksum or signature verification, which introduces a supply-chain risk in the release pipeline. In this job, the same runner later uses signing/notarization secrets, so a compromised artifact source (or network interception) could execute attacker-controlled code with access to release credentials; pinning the version alone does not authenticate the binary.

Useful? React with 👍 / 👎.

tar xf /tmp/zig.tar.xz -C /tmp
sudo mkdir -p /usr/local/bin /usr/local/lib
sudo cp -f /tmp/zig-aarch64-macos-${ZIG_REQUIRED}/zig /usr/local/bin/zig
sudo cp -rf /tmp/zig-aarch64-macos-${ZIG_REQUIRED}/lib /usr/local/lib/zig

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Replace Zig stdlib directory instead of nesting it

Copying .../lib into /usr/local/lib/zig with cp -rf will create /usr/local/lib/zig/lib when /usr/local/lib/zig already exists, leaving old stdlib files in place. That means on runners that already have Zig installed (the exact upgrade case this change targets), the new binary can still resolve stale libraries, causing version skew and flaky build behavior; the destination should be cleaned or copied as directory contents rather than as a nested lib folder.

Useful? React with 👍 / 👎.

@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.yml (1)

65-78: Xcode selection prioritizes latest version.

The logic uses sort | tail -n 1 to select the latest Xcode when /Applications/Xcode.app doesn't exist. This is appropriate for WarpBuild runners that may have multiple Xcode versions installed.

Note: This differs slightly from the fallback in build-ghosttykit.yml (line 48) which uses head -n 1 instead. Consider aligning the selection strategy across workflows.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/ci.yml around lines 65 - 78, The Xcode selection logic
inconsistently picks the Xcode version: update the fallback that computes
XCODE_APP (currently using ls -d /Applications/Xcode*.app | sort | tail -n 1)
and the assignment to XCODE_DIR/DEVELOPER_DIR to use a consistent selection
strategy across workflows (either always use the latest with sort | tail -n 1 or
always use the first with head -n 1); find the XCODE_APP/XCODE_DIR/DEVELOPER_DIR
handling and replace the differing variant so both this workflow and the
build-ghosttykit workflow use the same deterministic choice for selecting the
Xcode bundle, and ensure the echoed DEVELOPER_DIR and xcodebuild -version
behavior remain unchanged.
🤖 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.yml:
- Around line 65-78: The Xcode selection logic inconsistently picks the Xcode
version: update the fallback that computes XCODE_APP (currently using ls -d
/Applications/Xcode*.app | sort | tail -n 1) and the assignment to
XCODE_DIR/DEVELOPER_DIR to use a consistent selection strategy across workflows
(either always use the latest with sort | tail -n 1 or always use the first with
head -n 1); find the XCODE_APP/XCODE_DIR/DEVELOPER_DIR handling and replace the
differing variant so both this workflow and the build-ghosttykit workflow use
the same deterministic choice for selecting the Xcode bundle, and ensure the
echoed DEVELOPER_DIR and xcodebuild -version behavior remain unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a7cdda24-02a4-402d-b20f-a771a40cf573

📥 Commits

Reviewing files that changed from the base of the PR and between 34c1441 and 93e5d45.

📒 Files selected for processing (7)
  • .github/workflows/build-ghosttykit.yml
  • .github/workflows/ci-macos-compat.yml
  • .github/workflows/ci.yml
  • .github/workflows/nightly.yml
  • .github/workflows/release.yml
  • .github/workflows/test-depot.yml
  • .github/workflows/test-e2e.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/test-e2e.yml

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…5/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>
@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.

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>
@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.

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>
@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.

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>
@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.

@lawrencecchen
lawrencecchen merged commit a561a27 into main Mar 17, 2026
11 checks passed
@lawrencecchen
lawrencecchen deleted the task-migrate-warpcloud-consolidated branch March 17, 2026 08:00
@coderabbitai coderabbitai Bot mentioned this pull request Mar 17, 2026
3 tasks
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
* 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>

This branch was successfully deployed

1 active deployment
Preview — 5519992f 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