Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/ci-macos-compat.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ jobs:
run: |
./scripts/install-rust-ci.sh

- name: Provision cmux-iroh FFI
run: |
./scripts/ensure-cmux-iroh.sh

- name: Cache DerivedData
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
Expand Down
12 changes: 12 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,10 @@ jobs:
run: |
./scripts/install-rust-ci.sh

- name: Provision cmux-iroh FFI
run: |
./scripts/ensure-cmux-iroh.sh

- name: Cache Swift packages
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
Expand Down Expand Up @@ -1226,6 +1230,10 @@ jobs:
run: |
./scripts/install-rust-ci.sh

- name: Provision cmux-iroh FFI
run: |
./scripts/ensure-cmux-iroh.sh

- name: Cache Zig packages
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
Expand Down Expand Up @@ -1537,6 +1545,10 @@ jobs:
run: |
./scripts/install-rust-ci.sh

- name: Provision cmux-iroh FFI
run: |
./scripts/ensure-cmux-iroh.sh

- name: Cache DerivedData
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/ios-app-store.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ jobs:
- name: Provision GhosttyKit
run: ./scripts/ensure-ghosttykit.sh

- name: Provision cmux-iroh FFI
run: |
./scripts/install-rust-ci.sh
export PATH="$HOME/.cargo/bin:$PATH"
./scripts/ensure-cmux-iroh.sh

- name: Install asc CLI
run: |
set -euo pipefail
Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/ios-testflight.yml
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,12 @@ jobs:
# a local-path binaryTarget, so it must exist before package resolve.
./scripts/ensure-ghosttykit.sh

- name: Provision cmux-iroh FFI
run: |
./scripts/install-rust-ci.sh
export PATH="$HOME/.cargo/bin:$PATH"
./scripts/ensure-cmux-iroh.sh

Comment on lines +369 to +374

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Include the cmux-iroh inputs in the scheduled-upload path gate.

The iosPathPattern at Line 244 does not match native/cmux-iroh/** or scripts/ensure-cmux-iroh.sh. A scheduled run containing only an FFI or packaging change can therefore set needsBuild=false and skip archiving the newly provisioned framework.

Proposed fix
- const iosPathPattern = /^(ios\/|Packages\/Shared\/|Packages\/iOS\/|Sources\/Mobile\/|vendor\/stack-auth-swift-sdk-prerelease\/|ghostty$|scripts\/ensure-ghosttykit\.sh$|scripts\/ghosttykit-checksums\.txt$|scripts\/install-zig-ci\.sh$|\.github\/workflows\/ios-testflight\.yml$)/;
+ const iosPathPattern = /^(ios\/|native\/cmux-iroh\/|Packages\/Shared\/|Packages\/iOS\/|Sources\/Mobile\/|vendor\/stack-auth-swift-sdk-prerelease\/|ghostty$|scripts\/ensure-cmux-iroh\.sh$|scripts\/ensure-ghosttykit\.sh$|scripts\/ghosttykit-checksums\.txt$|scripts\/install-zig-ci\.sh$|\.github\/workflows\/ios-testflight\.yml$)/;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Provision cmux-iroh FFI
run: |
./scripts/install-rust-ci.sh
export PATH="$HOME/.cargo/bin:$PATH"
./scripts/ensure-cmux-iroh.sh
const iosPathPattern = /^(ios\/|native\/cmux-iroh\/|Packages\/Shared\/|Packages\/iOS\/|Sources\/Mobile\/|vendor\/stack-auth-swift-sdk-prerelease\/|ghostty$|scripts\/ensure-cmux-iroh\.sh$|scripts\/ensure-ghosttykit\.sh$|scripts\/ghosttykit-checksums\.txt$|scripts\/install-zig-ci\.sh$|\.github\/workflows\/ios-testflight\.yml$)/;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ios-testflight.yml around lines 369 - 374, Update the
iosPathPattern path gate to include native/cmux-iroh/** and
scripts/ensure-cmux-iroh.sh, ensuring scheduled runs with only cmux-iroh FFI or
provisioning changes set needsBuild=true and archive the newly provisioned
framework.

- name: Materialize App Store Connect API key
env:
ASC_API_KEY_P8_BASE64: ${{ secrets.ASC_API_KEY_P8_BASE64 }}
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,11 @@ jobs:
run: |
./scripts/download-prebuilt-ghosttykit.sh

- name: Provision cmux-iroh FFI
if: needs.decide.outputs.should_publish != 'true' || steps.current_head_prebuild.outputs.still_current == 'true'
run: |
./scripts/ensure-cmux-iroh.sh

- name: Cache Swift packages
if: needs.decide.outputs.should_publish != 'true' || steps.current_head_prebuild.outputs.still_current == 'true'
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/perf-activation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,10 @@ jobs:
run: |
./scripts/install-rust-ci.sh

- name: Provision cmux-iroh FFI
run: |
./scripts/ensure-cmux-iroh.sh

- name: Cache Swift packages
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
Expand Down
19 changes: 6 additions & 13 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -190,19 +190,7 @@ jobs:
- name: Install build deps
if: steps.guard_release_assets.outputs.skip_all != 'true'
run: |
export PATH="$HOME/.cargo/bin:$PATH"
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
if ! command -v rustup >/dev/null 2>&1; then
export HOMEBREW_NO_AUTO_UPDATE=1
export HOMEBREW_NO_INSTALL_CLEANUP=1
export HOMEBREW_NO_ENV_HINTS=1
brew install rustup-init
rustup-init -y --profile minimal --default-toolchain stable
fi
if ! rustup show active-toolchain >/dev/null 2>&1; then
rustup default stable
fi
rustup target add aarch64-apple-darwin x86_64-apple-darwin
./scripts/install-rust-ci.sh
CMUX_NODE_BIN="$(command -v node)"
export npm_config_prefix="$RUNNER_TEMP/npm-global"
mkdir -p "$npm_config_prefix"
Expand All @@ -221,6 +209,11 @@ jobs:
run: |
./scripts/download-prebuilt-ghosttykit.sh

- name: Provision cmux-iroh FFI
if: steps.guard_release_assets.outputs.skip_all != 'true'
run: |
./scripts/ensure-cmux-iroh.sh

- name: Cache Swift packages
if: steps.guard_release_assets.outputs.skip_all != 'true'
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
Expand Down
15 changes: 9 additions & 6 deletions .github/workflows/reload-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ jobs:
- name: Install zig
run: ./scripts/install-zig-ci.sh

- name: Install Rust (macOS)
if: ${{ inputs.platform == 'macos' }}
run: ./scripts/install-rust-ci.sh

- name: Provision GhosttyKit (macOS)
if: ${{ inputs.platform == 'macos' }}
run: ./scripts/download-prebuilt-ghosttykit.sh || ./scripts/ensure-ghosttykit.sh
Expand All @@ -107,13 +111,12 @@ jobs:
mkdir -p artifact
( cd "$(dirname "$app_path")" && ditto -c -k --sequesterRsrc --keepParent "$(basename "$app_path")" "$GITHUB_WORKSPACE/artifact/app.zip" )

# iOS links the CmuxIrohFFI xcframework (gitignored, built from the Rust
# crate under Native/cmux-iroh). The macOS path builds it via
# iOS links the CmuxIrohFFI xcframework directly from the Xcode project
# (gitignored, built from the Rust crate under native/cmux-iroh). The macOS path builds it via
# reload.sh -> ensure-cmux-iroh.sh; the iOS archive below runs xcodebuild
# directly, so provision it here or SwiftPM fails with "local binary target
# 'CmuxIrohFFIBinary' ... does not contain a binary artifact". Guarded so
# source refs that predate the crate are a no-op (scripts come from
# inputs.ref, not this workflow's ref). install-rust-ci.sh is idempotent.
# directly, so provision it here before Xcode resolves framework references.
# Guarded so source refs that predate the crate are a no-op (scripts come
# from inputs.ref, not this workflow's ref). install-rust-ci.sh is idempotent.
- name: Provision cmux-iroh FFI (iOS)
if: ${{ inputs.platform == 'ios' }}
run: |
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/test-depot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ jobs:
run: |
./scripts/install-rust-ci.sh

- name: Provision cmux-iroh FFI
run: |
./scripts/ensure-cmux-iroh.sh

- name: Create virtual display
run: |
set -euo pipefail
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/test-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,10 @@ jobs:
run: |
./scripts/install-rust-ci.sh

- name: Provision cmux-iroh FFI
run: |
./scripts/ensure-cmux-iroh.sh

- name: Install Bun for Feed sidebar tests
if: ${{ steps.filter.outputs.target == 'cmuxUITests' && (steps.filter.outputs.filter == 'FeedSidebarUITests' || startsWith(steps.filter.outputs.filter, 'FeedSidebarUITests/')) }}
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
Expand Down
7 changes: 7 additions & 0 deletions .github/workflows/test-ios.yml
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,13 @@ jobs:
# a local-path binaryTarget, so it must exist before package resolve.
./scripts/ensure-ghosttykit.sh

- name: Provision cmux-iroh FFI
if: ${{ !(github.event_name == 'workflow_dispatch' && inputs.device_family != 'both' && inputs.device_family != matrix.family) }}
run: |
./scripts/install-rust-ci.sh
export PATH="$HOME/.cargo/bin:$PATH"
./scripts/ensure-cmux-iroh.sh

- name: Pick simulator
if: ${{ !(github.event_name == 'workflow_dispatch' && inputs.device_family != 'both' && inputs.device_family != matrix.family) }}
env:
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/tmux-corpus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ jobs:
- name: Install Rust
run: ./scripts/install-rust-ci.sh

- name: Provision cmux-iroh FFI
run: ./scripts/ensure-cmux-iroh.sh

- name: Cache Swift packages
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ ios/Config/AppStoreConnect.local.plist
GhosttyKit.xcframework
GhosttyKit.xcframework.bak-*/

# CmuxIrohFFI binary (built from native/cmux-iroh via scripts/ensure-cmux-iroh.sh)
CmuxIrohFFI.xcframework
CmuxIrohFFI.xcframework.bak-*/

# Release artifacts
cmux-*.zip
cmux-macos.dmg
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,23 @@ extension MobileShellComposite {
return true
}

/// Request an authoritative replacement without racing another replay that
/// already owns this surface. An active barrier remains the sole lifecycle
/// owner; marking output as dropped makes its acknowledgement launch the
/// existing bounded follow-up replay. A surface without an owner keeps the
/// established unbarriered repair semantics, allowing a later byte gap to
/// supersede that in-flight replay and paint live output immediately.
func requestTerminalResync(surfaceID: String) {
guard hasTerminalOutputSink(surfaceID: surfaceID) else { return }
if terminalReplayBarrierTokensBySurfaceID[surfaceID] != nil {
terminalReplayBarrierDroppedOutputSurfaceIDs.insert(surfaceID)
terminalReplayBarrierDroppedOutputCountsBySurfaceID[surfaceID, default: 0] &+= 1
MobileDebugLog.anchormux("terminal.output.resync_deferred surface=\(surfaceID)")
return
}
requestTerminalReplay(surfaceID: surfaceID)
}

func markTerminalReplayInFlight(
surfaceID: String,
requestID: UUID,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6681,7 +6681,7 @@ public final class MobileShellComposite: MobileTerminalOutputSinking {
"sync.resync reason=\(reason) restart=\(restartEventStream) surfaces=\(surfaceIDs.count)"
)
for surfaceID in surfaceIDs {
requestTerminalReplay(surfaceID: surfaceID)
requestTerminalResync(surfaceID: surfaceID)
}
}

Expand Down
16 changes: 16 additions & 0 deletions cmux.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,7 @@ C0DE71B10000000000000001 /* AppDelegate+AgentChatNotifications.swift in Sources
C0DE34020000000000000001 /* CmuxHelpCommands.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0DE34020000000000000003 /* CmuxHelpCommands.swift */; };
C0DE34020000000000000002 /* CmuxHelpResource.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0DE34020000000000000004 /* CmuxHelpResource.swift */; };
C0DE46010000000000000001 /* CMUXInstalledExtensionSidebarHostView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0DE46010000000000000002 /* CMUXInstalledExtensionSidebarHostView.swift */; };
C1F00100C1F00100C1F00100 /* CmuxIrohFFI.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = C1F00101C1F00101C1F00101 /* CmuxIrohFFI.xcframework */; };
E7E00000000000000000000B /* CmuxLifecycleEventPublishing.swift in Sources */ = {isa = PBXBuildFile; fileRef = E7E00000000000000000000C /* CmuxLifecycleEventPublishing.swift */; };
2F0C07000000000000000002 /* CmuxMainWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F0C07000000000000000001 /* CmuxMainWindow.swift */; };
D36090010000000000000005 /* CmuxMainWindowConstrainFrameTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D36090010000000000000006 /* CmuxMainWindowConstrainFrameTests.swift */; };
Expand Down Expand Up @@ -2138,6 +2139,7 @@ C0DE71B10000000000000002 /* AppDelegate+AgentChatNotifications.swift */ = {isa =
C0DE34020000000000000003 /* CmuxHelpCommands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App/CmuxHelpCommands.swift; sourceTree = "<group>"; };
C0DE34020000000000000004 /* CmuxHelpResource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App/CmuxHelpResource.swift; sourceTree = "<group>"; };
C0DE46010000000000000002 /* CMUXInstalledExtensionSidebarHostView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CMUXInstalledExtensionSidebarHostView.swift; sourceTree = "<group>"; };
C1F00101C1F00101C1F00101 /* CmuxIrohFFI.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = CmuxIrohFFI.xcframework; sourceTree = "<group>"; };
E7E00000000000000000000C /* CmuxLifecycleEventPublishing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CmuxLifecycleEventPublishing.swift; sourceTree = "<group>"; };
2F0C07000000000000000001 /* CmuxMainWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App/CmuxMainWindow.swift; sourceTree = "<group>"; };
D36090010000000000000006 /* CmuxMainWindowConstrainFrameTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CmuxMainWindowConstrainFrameTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -3285,6 +3287,7 @@ C0DE71B10000000000000002 /* AppDelegate+AgentChatNotifications.swift */ = {isa =
C9A2C00000000000000000C3 /* CmuxFeedback in Frameworks */,
CF00F00000000000000000A3 /* CmuxFoundation in Frameworks */,
C617000000000000000000A3 /* CmuxGit in Frameworks */,
C1F00100C1F00100C1F00100 /* CmuxIrohFFI.xcframework in Frameworks */,
799F1BEF876006EEB8CD1035 /* CMUXMobileCore in Frameworks */,
E3B7A30000000000000000D3 /* CmuxNotifications in Frameworks */,
E3B7A30000000000000000F3 /* CmuxPanes in Frameworks */,
Expand Down Expand Up @@ -3537,6 +3540,7 @@ C0DE71B10000000000000002 /* AppDelegate+AgentChatNotifications.swift */ = {isa =
A5001101 /* Assets.xcassets */,
IC000002 /* AppIcon.icon */,
A5001016 /* GhosttyKit.xcframework */,
C1F00101C1F00101C1F00101 /* CmuxIrohFFI.xcframework */,
A5001017 /* ghostty.h */,
A5001018 /* cmux-Bridging-Header.h */,
3196C9C2D01F054C1D3385DD /* cmuxUITests */,
Expand Down Expand Up @@ -7159,6 +7163,12 @@ C0DE71B10000000000000002 /* AppDelegate+AgentChatNotifications.swift */ = {isa =
UniformTypeIdentifiers,
"-framework",
Carbon,
"-framework",
SystemConfiguration,
"-framework",
CoreWLAN,
"-framework",
Security,
);
PRODUCT_BUNDLE_IDENTIFIER = com.cmuxterm.app.debug;
PRODUCT_NAME = "cmux DEV";
Expand Down Expand Up @@ -7206,6 +7216,12 @@ C0DE71B10000000000000002 /* AppDelegate+AgentChatNotifications.swift */ = {isa =
UniformTypeIdentifiers,
"-framework",
Carbon,
"-framework",
SystemConfiguration,
"-framework",
CoreWLAN,
"-framework",
Security,
);
PRODUCT_BUNDLE_IDENTIFIER = com.cmuxterm.app;
PRODUCT_NAME = cmux;
Expand Down
Loading
Loading