Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
582a498
feat: add terminal timestamp gutter
austinywang May 12, 2026
846ea15
Merge remote-tracking branch 'origin/main' into issue-3690-terminal-t…
austinywang May 12, 2026
b154a7a
fix: clamp terminal timestamp scrollbar values
austinywang May 12, 2026
678d830
fix: address terminal timestamp review feedback
austinywang May 12, 2026
9f9946f
fix: align timestamp gutter with live scroll position
austinywang May 12, 2026
e9a6a22
Merge remote-tracking branch 'origin/main' into issue-3690-terminal-t…
austinywang May 12, 2026
685fb40
fix: extract terminal timestamp store
austinywang May 12, 2026
88eb7d4
Merge remote-tracking branch 'origin/main' into issue-3690-terminal-t…
austinywang May 12, 2026
9b16076
fix: avoid timestamp prune hot-path copies
austinywang May 12, 2026
f22d321
fix: isolate terminal timestamp store on main actor
austinywang May 12, 2026
6a00a7b
ci: retrigger terminal timestamp checks
austinywang May 12, 2026
32e4969
fix: bound timestamp prune after scrollback shrink
austinywang May 12, 2026
ec41fc6
test: cover timestamp visible retention
austinywang May 12, 2026
5d8e7f9
fix: preserve marked timestamp rows
austinywang May 12, 2026
56054d3
fix: bound timestamp growth stamping
austinywang May 12, 2026
77b0536
test: cover timestamp viewport retention
austinywang May 12, 2026
6923862
fix: preserve visible timestamp rows while scrolling
austinywang May 12, 2026
cd37d5e
fix: cache terminal timestamp gutter draw style
austinywang May 13, 2026
2255067
fix: reset timestamp rows after scrollback rebase
austinywang May 13, 2026
5ecdcc9
fix: qualify timestamp store bounds assignment
austinywang May 13, 2026
9c3c589
Merge remote-tracking branch 'origin/main' into issue-3690-terminal-t…
austinywang May 13, 2026
781bd8d
fix: bound timestamp prune cursor
austinywang May 13, 2026
ff3745f
fix: preserve keyboard scroll timestamp policy
austinywang May 13, 2026
fe51489
fix: carry keyboard scroll intent across callback
austinywang May 13, 2026
b9e8e28
fix: preserve coalesced keyboard scroll intent
austinywang May 13, 2026
aa2d8fd
fix: limit keyboard scroll intent to viewport motions
austinywang May 13, 2026
d114d2a
Merge remote-tracking branch 'origin/main' into issue-3690-terminal-t…
austinywang May 14, 2026
464b20b
Merge remote-tracking branch 'origin/main' into issue-3690-terminal-t…
austinywang May 17, 2026
9785587
fix: preserve timestamp prune bounds
austinywang May 17, 2026
9b5cd7d
fix: share timestamp scroll intent enqueue path
austinywang May 18, 2026
5fec0ca
Merge branch 'main' of https://github.com/manaflow-ai/cmux into issue…
austinywang May 19, 2026
72d4d93
Merge remote-tracking branch 'origin/main' into issue-3690-terminal-t…
austinywang May 19, 2026
9b980a1
Merge origin/main into issue-3690-terminal-timestamps
austinywang May 19, 2026
c1d98b9
Fix search scrollbar sync after keyboard backscroll
austinywang May 19, 2026
dac1051
Remove obsolete keyboard scroll intent helper
austinywang May 19, 2026
50c6c59
Add terminal timestamp localizations
austinywang May 19, 2026
95c28ce
Merge remote-tracking branch 'origin/main' into issue-3690-terminal-t…
austinywang May 22, 2026
38b5add
merge: sync terminal timestamps with main
austinywang May 22, 2026
9c1a74e
fix: align cli helpers with main
austinywang May 22, 2026
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
343 changes: 343 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,343 @@
version: 2.1

executors:
linux-python-node:
docker:
- image: cimg/python:3.12-node
resource_class: medium

linux-go:
docker:
- image: cimg/go:1.22
resource_class: medium

macos-xcode:
macos:
xcode: "16.4.0"
resource_class: m4pro.medium
shell: /bin/bash --login -eo pipefail

commands:
checkout-source:
parameters:
submodules:
type: boolean
default: false
steps:
- checkout
- when:
condition: << parameters.submodules >>
steps:
- run:
name: Initialize submodules
no_output_timeout: 35m
command: |
git submodule sync --recursive
git submodule update --init --recursive

install-bun:
steps:
- run:
name: Install Bun
command: |
BUN_VERSION="1.3.3"
NPM_GLOBAL="$HOME/.npm-global"
mkdir -p "$NPM_GLOBAL"
npm install --global --prefix "$NPM_GLOBAL" "bun@$BUN_VERSION"
BASH_ENV="${BASH_ENV:-$HOME/.bash_env}"
echo "export PATH=\"$NPM_GLOBAL/bin:\$PATH\"" >> "$BASH_ENV"
export PATH="$NPM_GLOBAL/bin:$PATH"
test "$(bun --version)" = "$BUN_VERSION"

install-zig:
steps:
- run:
name: Install zig
no_output_timeout: 35m
command: |
export HOMEBREW_NO_AUTO_UPDATE=1
export HOMEBREW_NO_INSTALL_CLEANUP=1
export HOMEBREW_NO_ENV_HINTS=1
./scripts/install-zig-ci.sh

install-rust:
steps:
- run:
name: Install Rust
no_output_timeout: 15m
command: ./scripts/install-rust-ci.sh

print-xcode:
steps:
- run:
name: Print Xcode environment
command: |
xcodebuild -version
xcrun --sdk macosx --show-sdk-path
sw_vers

restore-swift-package-cache:
parameters:
prefix:
type: string
steps:
- restore_cache:
keys:
- v1-spm-<< parameters.prefix >>-{{ checksum "cmux.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved" }}
- v1-spm-<< parameters.prefix >>-

save-swift-package-cache:
parameters:
prefix:
type: string
path:
type: string
default: .ci-source-packages
steps:
- save_cache:
key: v1-spm-<< parameters.prefix >>-{{ checksum "cmux.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved" }}
paths:
- << parameters.path >>

restore-zig-cache:
steps:
- restore_cache:
keys:
- v1-zig-{{ checksum "ghostty/build.zig.zon" }}-{{ checksum "ghostty/build.zig.zon.json" }}
- v1-zig-

save-zig-cache:
steps:
- save_cache:
key: v1-zig-{{ checksum "ghostty/build.zig.zon" }}-{{ checksum "ghostty/build.zig.zon.json" }}
paths:
- ~/.cache/zig

resolve-swift-packages:
parameters:
scheme:
type: string
source-packages-dir:
type: string
default: .ci-source-packages
steps:
- run:
name: Resolve Swift packages
no_output_timeout: 35m
command: |
SOURCE_PACKAGES_DIR="$PWD/<< parameters.source-packages-dir >>"
mkdir -p "$SOURCE_PACKAGES_DIR"

for attempt in 1 2 3; do
if xcodebuild -project cmux.xcodeproj -scheme << parameters.scheme >> -configuration Debug \
-clonedSourcePackagesDirPath "$SOURCE_PACKAGES_DIR" \
-resolvePackageDependencies; then
exit 0
fi
if [ "$attempt" -eq 3 ]; then
echo "Failed to resolve Swift packages after 3 attempts" >&2
exit 1
fi
echo "Package resolution failed on attempt $attempt, retrying..."
sleep $((attempt * 5))
done

jobs:
macos-unit-tests:
executor: macos-xcode
steps:
- checkout-source:
submodules: true
- print-xcode
- install-rust
- restore-swift-package-cache:
prefix: unit
- restore-zig-cache
- run:
name: Download pre-built GhosttyKit.xcframework
no_output_timeout: 35m
command: ./scripts/download-prebuilt-ghosttykit.sh
- resolve-swift-packages:
scheme: cmux-unit
- run:
name: Run unit tests
no_output_timeout: 35m
command: |
export CMUX_SKIP_ZIG_BUILD=1
SOURCE_PACKAGES_DIR="$PWD/.ci-source-packages"
run_unit_tests() {
xcodebuild -project cmux.xcodeproj -scheme cmux-unit -configuration Debug \
-clonedSourcePackagesDirPath "$SOURCE_PACKAGES_DIR" \
-disableAutomaticPackageResolution \
-destination "platform=macOS" \
CMUX_SKIP_ZIG_BUILD=1 \
-skip-testing:cmuxTests/AppDelegateShortcutRoutingTests/testCmdWClosesWindowWhenClosingLastSurfaceInLastWorkspace \
test 2>&1
}

set +e
run_unit_tests | tee /tmp/test-output.txt
EXIT_CODE=${PIPESTATUS[0]}
OUTPUT=$(cat /tmp/test-output.txt)
set -e

if [ "$EXIT_CODE" -ne 0 ] && echo "$OUTPUT" | grep -q "Could not resolve package dependencies"; then
echo "SwiftPM package resolution failed, clearing caches and retrying once"
rm -rf ~/Library/Caches/org.swift.swiftpm
mkdir -p ~/Library/Caches/org.swift.swiftpm
rm -rf ~/Library/Developer/Xcode/DerivedData/cmux-*
rm -rf "$SOURCE_PACKAGES_DIR"
mkdir -p "$SOURCE_PACKAGES_DIR"
xcodebuild -project cmux.xcodeproj -scheme cmux-unit -configuration Debug \
-clonedSourcePackagesDirPath "$SOURCE_PACKAGES_DIR" \
-resolvePackageDependencies \
CMUX_SKIP_ZIG_BUILD=1
set +e
run_unit_tests | tee /tmp/test-output.txt
EXIT_CODE=${PIPESTATUS[0]}
OUTPUT=$(cat /tmp/test-output.txt)
set -e
fi

if [ "$EXIT_CODE" -ne 0 ]; then
SUMMARY=$(echo "$OUTPUT" | grep "Executed.*tests.*with.*failures" | tail -1)
if echo "$SUMMARY" | grep -q "(0 unexpected)"; then
echo "All failures are expected, treating as pass"
else
echo "Unexpected test failures detected"
exit 1
fi
fi
- run:
name: Run bundled Ghostty theme picker helper regression
no_output_timeout: 35m
command: |
CMUX_SKIP_ZIG_BUILD=1 \
CMUX_SOURCE_PACKAGES_DIR="$PWD/.ci-source-packages" \
./tests/test_bundled_ghostty_theme_picker_helper.sh
- run:
name: Run CLI no-socket regressions
no_output_timeout: 35m
command: |
CLI_BIN="$(
find "$HOME/Library/Developer/Xcode/DerivedData" -path "*/Build/Products/Debug/cmux" -exec stat -f '%m %N' {} \; \
| sort -nr \
| head -1 \
| cut -d' ' -f2-
)"
if [ -z "${CLI_BIN:-}" ] || [ ! -x "$CLI_BIN" ]; then
echo "cmux CLI binary not found in DerivedData" >&2
exit 1
fi

CMUX_CLI_BIN="$CLI_BIN" python3 tests/test_cli_version_memory_guard.py
CMUX_CLI_BIN="$CLI_BIN" python3 tests/test_cli_contract_help.py
CMUX_CLI_BIN="$CLI_BIN" python3 tests/test_cli_layout_focus_contract.py
CMUX_CLI_BIN="$CLI_BIN" python3 tests/test_cli_socket_operation_deadline.py
CMUX_CLI_BIN="$CLI_BIN" python3 tests/test_cli_omo_openagent_plugin_migration.py
CMUX_CLI_BIN="$CLI_BIN" python3 tests/test_cli_socket_autodiscovery.py
CMUX_CLI_BIN="$CLI_BIN" python3 tests/test_claude_hook_clear_running_status.py
- save-swift-package-cache:
prefix: unit
- save-zig-cache

macos-debug-build:
executor: macos-xcode
steps:
- checkout-source:
submodules: true
- print-xcode
- install-rust
- restore-swift-package-cache:
prefix: debug-build
- restore-zig-cache
- run:
name: Download pre-built GhosttyKit.xcframework
no_output_timeout: 35m
command: ./scripts/download-prebuilt-ghosttykit.sh
- resolve-swift-packages:
scheme: cmux
- run:
name: Build app and capture warnings
no_output_timeout: 35m
command: |
export CMUX_SKIP_ZIG_BUILD=1
SOURCE_PACKAGES_DIR="$PWD/.ci-source-packages"
xcodebuild -project cmux.xcodeproj -scheme cmux -configuration Debug \
-clonedSourcePackagesDirPath "$SOURCE_PACKAGES_DIR" \
-disableAutomaticPackageResolution \
-destination "platform=macOS" \
CMUX_SKIP_ZIG_BUILD=1 \
build 2>&1 | tee /tmp/cmux-build-output.txt
- run:
name: Validate Swift warning budget
command: python3 scripts/swift_warning_budget.py --log /tmp/cmux-build-output.txt
- save-swift-package-cache:
prefix: debug-build
- save-zig-cache

macos-release-build:
executor: macos-xcode
steps:
- checkout-source:
submodules: true
- print-xcode
- install-rust
- restore-swift-package-cache:
prefix: release
- restore-zig-cache
- run:
name: Download pre-built GhosttyKit.xcframework
no_output_timeout: 35m
command: ./scripts/download-prebuilt-ghosttykit.sh
- resolve-swift-packages:
scheme: cmux
source-packages-dir: .spm-cache
- run:
name: Build universal app (Release)
no_output_timeout: 35m
command: |
export CMUX_SKIP_ZIG_BUILD=1
xcodebuild -project cmux.xcodeproj -scheme cmux -configuration Release -derivedDataPath build-universal \
-destination "generic/platform=macOS" \
-clonedSourcePackagesDirPath .spm-cache \
-disableAutomaticPackageResolution \
ARCHS="arm64 x86_64" \
ONLY_ACTIVE_ARCH=NO \
CMUX_SKIP_ZIG_BUILD=1 \
CODE_SIGNING_ALLOWED=NO ASSETCATALOG_COMPILER_APPICON_NAME=AppIcon-Nightly build
- save-swift-package-cache:
prefix: release
path: .spm-cache
- save-zig-cache

workflows:
ci-trusted:
when:
and:
- << pipeline.git.branch >>
- not:
matches:
pattern: "^pull/.*"
value: << pipeline.git.branch >>
jobs:
- macos-unit-tests
- macos-debug-build
- macos-release-build

ci-gated:
when:
or:
- matches:
pattern: "^pull/.*"
value: << pipeline.git.branch >>
- << pipeline.git.tag >>
jobs:
- hold-for-approval:
type: approval
- macos-unit-tests:
requires: [hold-for-approval]
- macos-debug-build:
requires: [hold-for-approval]
- macos-release-build:
requires: [hold-for-approval]
5 changes: 1 addition & 4 deletions .github/review-bot-rules/runtime-no-hacky-sleeps.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# Runtime No Hacky Sleeps

Scope: TypeScript, JavaScript, shell, and non-Swift build/runtime scripts. Swift timing and blocking primitives are covered by `swift-blocking-runtime.md`.

GitHub Actions workflow and action YAML is intentionally out of scope. Fixed waits there are CI orchestration unless the PR also changes a covered runtime script that uses the wait as product synchronization.
Scope: TypeScript, JavaScript, shell, and non-Swift runtime scripts. Swift timing and blocking primitives are covered by `swift-blocking-runtime.md`.

Flag fixed delays used as synchronization in production application or runtime code.

Expand All @@ -15,7 +13,6 @@ Report a failure when the diff introduces or materially expands any of these in
Allowed cases:

- Deterministic sleeps in tests or explicit test-only scaffolding.
- GitHub Actions workflow or action YAML sleeps used only for CI orchestration.
- User-visible animation or progress timing where the timer is purely presentation and not coordination.
- Production retry or timeout logic implemented through a dedicated cancellation-aware abstraction with bounded deadlines and tests, where the delay is part of the product behavior rather than a race repair.
- Existing delay code that the PR does not introduce or worsen.
Expand Down
Loading
Loading