Skip to content

Fail closed on app-host test outcomes and remove impossible route waits - #12173

Closed
austinywang wants to merge 60 commits into
mainfrom
ship/proven-green
Closed

austinywang wants to merge 60 commits into
mainfrom
ship/proven-green

Conversation

@austinywang

@austinywang austinywang commented Sep 8, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Preserve authoritative mixed-framework failures and total-timeout outcomes instead of allowing an earlier tolerant XCTest summary to pass the job.
  • Reject unknown app-host exit statuses; the regression harness now models XCTest assertion failures with status 65 and includes the real classifier.
  • Bound app-host retries and complete mixed-framework runs, preserve heartbeat behavior, and isolate app-host fixture cleanup.
  • Remove impossible unauthenticated mobile-host route waits from TerminalOffscreenStartupTests by seeding the public route cache directly; tear down headless surfaces deterministically.
  • Keep the debug mobile RPC inventory sorted at its shared declaration; the existing app-host regression caught the out-of-order simulator recovery method.

Verification

  • python3 tests/test_ci_change_areas.py
  • bash tests/test_ci_app_host_xcodebuild_retry.sh
  • python3 tests/test_ci_xcodebuild_noninteractive_helper.py
  • bash tests/test_ci_app_host_identity.sh
  • bash tests/test_ci_app_host_processes.sh
  • bash tests/test_ci_app_host_home_cleanup.sh
  • python3 scripts/check-test-determinism.py --self-test and --strict
  • python3 scripts/check-package-resolved-policy.py
  • python3 scripts/check-workspace-package-groups.py
  • bash scripts/check-pbxproj.sh
  • bash scripts/lint-pbxproj-test-wiring.sh
  • python3 scripts/swift_file_length_budget.py

September 10 resume, pushed HEAD 4ee30db3f4973982076c6dc609c3a15bdb217e3b: local CI-tooling regressions pass, including the complete change-area test runner, noninteractive helper, app-host retry/identity/process/home fixtures, sharding tests (2457 selectors), shared Swift lexer tests (14), determinism fixtures (150 positive + 90 negative), strict determinism scan (0 findings), and the policy/wiring checks above. New regression fixtures were committed separately and observed failing locally before their fixes. No local Xcode build or test was run.

Final-head full CI run 34460787505 is pending, not claimed green. E2E 34458121381 tested SHA fa74034a08 and passed all 29 TerminalOffscreenStartupTests, including the three attach-ticket cases and the inventory-order regression. The app/runtime/test-source trees are unchanged between that SHA and HEAD. Hosted web-typecheck passed at da947bab7f; the web test files are unchanged in HEAD. The prior E2E attribution was corrected in comment 5589141222: run 34248807414 tested branch SHA 7eb9b54add, not main.

Trade-offs

  • The branch is current with main via merge commits, preserving the existing commit provenance instead of rewriting the long PR stack.
  • The origin branch was force-updated with --force-with-lease from its stale pre-rebase SHA; the explicit lease prevented overwriting any intervening origin update.
  • Main's newer XCTest-summary parser is reused by both batch and final classification; this branch retains authoritative Swift Testing failures, deadlines, and unknown-status rejection. Main's idle-progress diagnostics are also retained.
  • Three large Swift Testing suites are kept whole instead of using XCTest-style method selectors. This preserves framework coverage but changes shard composition; broad failures cannot be assumed unrelated without remote verification.
  • No visual evidence is attached because there is no visual change. The only new runtime delta is DEBUG-only RPC inventory ordering, verified through its existing app-host RPC regression. Sorting preserves the complete inventory and does not silently deduplicate it.
  • This includes mobile/iOS release-gate behavior. It will not be self-merged; Austin owns merge approval after the actual done bar.
  • Scope-safe shard detection reuses the existing structural Swift tokenizer, adding a lexical pass to handle attribute order, suite braces, nested comments, raw strings, and interpolation without another lexer implementation.
  • This continuation used three grouped pushes, including post-push CI/review follow-ups. Main-derived web failures were fixed only in test declarations and fixture paths; billing behavior and runtime assertions were not weakened. Final-head CI remains required even though the affected runtime suite already passed.

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.


Note

Medium Risk
Changes affect CI gating for the full app-host unit suite and agent automatic-resume ownership rules; misclassification could hide real failures or leave stale bindings, though the direction is fail-closed with expanded regression coverage.

Overview
App-host CI now treats Swift Testing and wrapper exit codes as authoritative: sharding emits per-batch Swift Testing metadata, the noninteractive helper enforces total deadlines and reserved statuses (123–127), batches run with -parallel-testing-enabled NO, and classify-app-host-test-result.sh only tolerates ordinary XCTest failures when the log still shows (0 unexpected)—so a stale summary cannot green a missing or failed Swift Testing phase. Ghostty config validation is tightened with canonical path checks (aliases OK, traversal rejected).

Product fixes include not marking agent resume bindings stale when the live index has no entry after a completed scan (only a observed non-live entry counts), rewriting loopback browser URLs with correct IPv6 bracket handling, and sorting the DEBUG mobile RPC inventory for release-gate parity.

Tests and tooling move private-URL and simulator-gesture coverage into dedicated suites, fix attach-ticket tests by seeding MobileHostPublicStatusCache instead of waiting on the unauthenticated status probe, split UserDefaults superseded-source coverage, and extend the determinism scanner for Process.run/curl-style invocations. Several snapshot/cloud/tree expectations were updated for tab-scoped port nodes and parser tab-ID behavior.

Reviewed by Cursor Bugbot for commit 3d8c1be. Bugbot is set up for automated code reviews on this repo. Configure here.


Summary by cubic

Fails closed on app-host test outcomes so a tolerant XCTest summary can no longer pass a job with real Swift Testing failures, timeouts, or unknown exit statuses. Also removes impossible unauthenticated mobile-host route waits in TerminalOffscreenStartupTests and fixes related restore and release-gate bugs.

CI hardening

  • classify-app-host-test-result.sh only tolerates ordinary XCTest statuses when the summary shows "(0 unexpected)" and no Swift Testing failure line is present.
  • Reserved exit codes 123–127 cover Swift Testing failures, idle/post-test timeouts, missing Swift Testing phases, and total deadline; app-host xcodebuild forces serial Swift Testing.
  • Ghostty config paths are canonicalized so a symlink alias is accepted but traversal through it is rejected.
  • check-test-determinism.py flags curl/wget inside Process.run, exec, and multiline shell strings, while allowing a wrapped deadline-timeout race.

Bug fixes and test updates

  • Rewrites loopback URLs with correct IPv6 brackets, and classifies deferred browser URLs so a restored-but-not-yet-loaded tab is no longer an empty new tab.
  • A completed index scan with no matching entry no longer marks a fresh agent binding stale; only observed non-live process evidence does.
  • Attach-ticket tests seed MobileHostPublicStatusCache directly, headless startup tests tear down surfaces deterministically, and the mobile debug RPC inventory is sorted.
  • Superseded-source and simulator-gesture suites are wired into the app target with Bun fixture updates, and the cloud VM reference now documents the vm.diagnostics RPC.

Written for commit 09118b6. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • Bug Fixes

    • Improved automated test-result classification across XCTest and Swift Testing, including mixed suites, timeouts, incomplete runs, and expected failures.
    • Strengthened configuration-path validation to reject unsafe or invalid paths while accepting valid aliases.
    • Improved test cleanup and reduced reliance on service polling in mobile attachment tests.
    • Improved detection of network-dependent test commands.
  • Tests

    • Expanded coverage for timeout handling, retries, path validation, network detection, and result classification.
  • Chores

    • Added configurable total timeouts and Swift Testing expectations for noninteractive test runs.

ejc3 and others added 25 commits September 1, 2026 16:56
…ectations

Three changes that a red-to-green run on a macOS builder proves together, covering two
suites.

The product bug: a BrowserPanel built with an initial URL and rendering deferred keeps the
.newTab lifecycle state it is born with, so a restored-but-not-yet-loaded tab is classified
as an empty new tab. That state feeds the omnibar's new-tab handling and is exported in top
telemetry. The recompute is driven by shouldRenderWebView's didSet, and on this path the
assignment writes false over a declared default of false, so the didSet guard on
oldValue != newValue never fires and the initializer returns without recomputing. Both
deferred branches had the same gap. Two tests written when .deferredURL was introduced
already assert the right thing and were failing on it, so no test is added here.

TerminalOffscreenStartupTests read the runtime-creation counter synchronously right after
the initializer returns, but a startup surface now installs its per-surface claude wrapper
shim on a detached task and only calls createSurface once that finishes. The tests wait for
the attempt and keep the claim they were written for by asserting uiWindow is nil, which is
non-nil only once the surface is in a real window rather than the hidden bootstrap one. The
same suite's three attach-ticket tests waited on mobile.host.status reporting routes; that
method is the unauthenticated probe and discloses none, so the wait was unsatisfiable rather
than slow. They seed the public status cache instead, which is what the ticket path reads.

The browser under-page fill tests asserted the raw translucent colour they posted, but the
panel composites it over the window background and fills opaquely. The expectation is now
derived from the panel's own theme helper, with a guard assertion so the derivation cannot
go vacuous.

Measured on a macOS builder, base eeb4866 against this tree:
TerminalOffscreenStartupTests red with 10 failures -> passing.
BrowserDeveloperToolsConfigurationTests red with 18 failures -> passing. That suite needs
both the colour update and the product fix, since its three failures split across them.
@vercel

vercel Bot commented Sep 8, 2026 •

Copy link
Copy Markdown

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

Project Deployment Actions Updated
cmux166 Ready Ready Preview Sep 12, 2026 2:48am UTC
cmux41 Ready Ready Preview Sep 12, 2026 2:48am UTC

@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@coderabbitai

coderabbitai Bot commented Sep 8, 2026 •

Copy link
Copy Markdown

Review Change StackReview Change Stack

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

The pull request updates app-host test classification, Swift Testing sharding, timeout handling, configuration-path validation, network determinism detection, terminal test isolation, and mobile capability ordering.

Changes

App-host CI execution

Layer / File(s) Summary
Mixed test classification and timeout handling
scripts/ci/xcodebuild_noninteractive.py, scripts/ci/classify-app-host-test-result.sh, tests/test_ci_xcodebuild_noninteractive_helper.py, tests/test_ci_app_host_xcodebuild_retry.sh
The runner tracks XCTest and Swift Testing results, enforces total and idle deadlines, and classifies mixed-framework outcomes.
Canonical app-host configuration validation
scripts/ci/run-app-host-xcodebuild.sh, tests/test_ci_app_host_xcodebuild_retry.sh
Configuration paths are canonicalized before validation. Traversal, invalid entries, and missing evidence are rejected.
Swift Testing shard metadata and workflow integration
scripts/ci/cmux_unit_test_shard.py, .github/workflows/ci.yml, scripts/ci/run-in-console-session.sh, tests/test_ci_change_areas.py, tests/test_ci_cmux_unit_test_shard.py
The shard generator detects Swift Testing declarations and emits metadata. The workflow validates and forwards that metadata, then uses the shared result classifier.

Test determinism detection

Layer / File(s) Summary
Network execution detection rules
scripts/check-test-determinism.py
The checker recognizes Swift Process.run calls for curl and wget, restricts matches by language, and adds regression fixtures.

Terminal test isolation

Layer / File(s) Summary
Terminal and mobile route test fixtures
cmuxTests/TerminalAndGhosttyTests.swift
Offscreen tests tear down panel surfaces. Mobile attach-ticket tests seed loopback routes in MobileHostPublicStatusCache instead of starting and polling MobileHostService.
Sorted mobile capability inventory
Sources/Mobile/MobileHostService+Capabilities.swift
The DEBUG Iroh release-gate method inventory is sorted before return, and its documentation reflects the ordering.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CIWorkflow
  participant ConsoleSession
  participant XcodebuildRunner
  participant ResultClassifier
  CIWorkflow->>ConsoleSession: forward timeout and Swift Testing settings
  ConsoleSession->>XcodebuildRunner: run noninteractive xcodebuild
  XcodebuildRunner->>ResultClassifier: provide exit status and output file
  ResultClassifier-->>CIWorkflow: return classified result
Loading

Merge Risk: 🟡 Moderate · up to da947

A total CI deadline can hide the specific test failure classification needed by app-host reporting, and the determinism gate concern remains unresolved. Resolve these before merge to keep CI results trustworthy.

🚥 Pre-merge checks | ✅ 24 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 17.65% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 34 functions across 15 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (24 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Cmux Swift Actor Isolation ✅ Passed PASS. The only changed production Swift file changes MobileHostService.irohReleaseGateRPCMethods from an array literal to the sorted value ].sorted() and updates its comment. The declaration remai…
Cmux Swift Blocking Runtime ✅ Passed PASS: The only non-test Swift change sorts the DEBUG-only irohReleaseGateRPCMethods array and adds no blocking or timing synchronization. The cmuxTests/TerminalAndGhosttyTests.swift changes are te…
Cmux Browser Automation Off-Main ✅ Passed PASS. The pull request does not change the policy-scoped browser automation files: Sources/TerminalController.swift, ControlCommandExecutionPolicy.swift, and its policy tests are unchanged. The co…
Cmux Expensive Synchronous Load ✅ Passed PASS. The authoritative diff changes only two Swift files: one production file and one test file. The production change only appends .sorted() to the fixed irohReleaseGateRPCMethods constant and u…
Cmux Cache Substitution Correctness ✅ Passed PASS. The only changed production Swift file, Sources/Mobile/MobileHostService+Capabilities.swift, sorts the static irohReleaseGateRPCMethods inventory and updates its comment. It does not replace…
Cmux No Hacky Sleeps ✅ Passed PASS. The diff adds no fixed sleep, timer, or polling delay to covered non-test code. The new xcodebuild_noninteractive.py total deadline uses time.monotonic() with PTY select() and process-grou…
Cmux Algorithmic Complexity ✅ Passed No changed production path violates the complexity rule. The Swift change sorts a fixed 92-entry DEBUG RPC inventory once. The shard change scans each Swift file once and uses only constant-size token…
Cmux Swift Concurrency ✅ Passed The Swift diff does not introduce or materially expand any prohibited legacy async pattern. Sources/Mobile/MobileHostService+Capabilities.swift only sorts a static method list. `cmuxTests/TerminalAn…
Cmux Swift @Concurrent ✅ Passed The pull request changes only two Swift files. The Swift changes add synchronous defer cleanup, replace an async polling helper with the synchronous publishLoopbackMobileHostRouteForTesting, and s…
Cmux Swift Package Boundaries ✅ Passed PASS. The only production Swift change sorts the existing DEBUG-only MobileHostService.irohReleaseGateRPCMethods inventory and updates its comment. It does not introduce or materially expand indepen…
Cmux Swiftpm Lockfiles ✅ Passed PASS. The review-range diff contains no Package.swift, Package.resolved, .gitignore, Xcode project, or SwiftPM package-reference changes. The workflow change only updates SwiftPM retry-output handling…
Cmux Swift Logging ✅ Passed PASS. The only production Swift change is in Sources/Mobile/MobileHostService+Capabilities.swift: it updates a comment and applies .sorted() to a #if DEBUG RPC inventory. It adds no logging. The…
Cmux User-Facing Error Privacy ✅ Passed PASS. The authoritative diff changes one production source file only by sorting a DEBUG-only authenticated RPC inventory and updating its developer comment. All other changes are CI scripts, workflows…
Cmux Full Internationalization ✅ Passed PASS. The authoritative diff contains no new or materially changed user-facing text, localization key, catalog entry, or web message. The only production Swift change sorts a DEBUG-only RPC method inv…
Cmux Swiftui State Layout ✅ Passed PASS. The reviewed range changes only two Swift files: an AppKit/XCTest cleanup and a DEBUG RPC inventory sort. The added Swift code contains no SwiftUI views, ObservableObject/@Published/@State patte…
Cmux Architecture Rethink ✅ Passed PASS. The only production Swift change sorts an existing DEBUG RPC inventory. The remaining Swift changes are test-only: they add deterministic surface cleanup and replace an impossible polling/sleep …
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed PASS. The only non-test Swift change sorts MobileHostService.irohReleaseGateRPCMethods; it does not add or change a window. The other Swift file changes are in `cmuxTests/TerminalAndGhosttyTests.swi…
Cmux Source Artifacts ✅ Passed The authoritative diff changes 17 existing source/config/test files and adds only scripts/ci/classify-app-host-test-result.sh. The paths use Swift, Python, Bash, YAML, TypeScript, and declaration-file…
Cmux No Test Or Debug Seam In Production Source ✅ Passed PASS. The only changed production Swift file is Sources/Mobile/MobileHostService+Capabilities.swift, and the diff only changes the existing DEBUG inventory by appending .sorted() and updating its …
Cmux No Ambient Global State ✅ Passed PASS. The only production Swift change is in Sources/Mobile/MobileHostService+Capabilities.swift: an existing nonisolated static let irohReleaseGateRPCMethods array now uses .sorted(), and its c…
Title check ✅ Passed The title clearly summarizes the primary changes: fail-closed app-host test outcomes and removal of impossible route waits.
Description check ✅ Passed The description is detailed and on-topic. It explains the changes, rationale, testing performed, pending verification, trade-offs, and the absence of visual evidence for non-visual changes. Some templ…
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ship/proven-green

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.

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

Stale Bugbot comment from a previous run.

Comment thread .github/workflows/ci.yml Outdated
Comment thread scripts/ci/run-app-host-xcodebuild.sh

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

Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 73689e1. Configure here.

Comment thread Sources/Surfaces/CmuxTuiSurfaceProviders.swift Outdated
Comment thread scripts/ci/xcodebuild_noninteractive.py
@blacksmith-sh

This comment has been minimized.

@lawrencecchen

Copy link
Copy Markdown
Contributor

Mac fleet instructions for head 09118b6f3f4f5634df366ce34026fb77c9f50968. Planned tag: pr-12173-09118b6f; this is not yet a published build.

JOB_JSON=$(~/.local/bin/cmux-ci submit --kind cmux --command 'CMUX_FLEET_BUILD_TAG=pr-12173-09118b6f /Users/Shared/cmux-build-fleet/recipes/cmux.sh https://github.com/manaflow-ai/cmux.git 09118b6f3f4f5634df366ce34026fb77c9f50968' --artifact artifacts/cmux.app.zip --workspace https://github.com/manaflow-ai/cmux/pull/12173 --source-digest 09118b6f3f4f5634df366ce34026fb77c9f50968 --cache-key cmux:pr-12173 --min-free-bytes 268435456000 --label cmux --label ram48)
JOB_ID=$(python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])' <<<"$JOB_JSON")
~/.local/bin/cmux-ci wait "$JOB_ID" --receipt artifacts/fleet/$JOB_ID.json
~/.local/bin/cmux-ci publish-hq "$JOB_ID"

Use an existing campaign job ID if one is already posted; do not submit a duplicate. A wait timeout leaves the remote job running. Published results will include an exact-head artifact link and timing/disk receipt. This recipe validates the macOS app only, not iOS or tests. Never use maclease or put credentials in a PR comment.

@austinywang austinywang mentioned this pull request Sep 20, 2026
5 of 6 tasks
@teamleaderleo teamleaderleo added area: build-and-ci Build system, CI workflows, test infrastructure difficulty:4 Architecture: security, protocol, migration, release, or broad design ready-to-land Reviewed and ready to land when CI is green closing-soon Conflicting or red with no activity for 7+ days; closes 2026-10-06 unless the label is removed labels Sep 30, 2026
@teamleaderleo

Copy link
Copy Markdown
Collaborator

Closing; reopen if you still want it.

This branch was successfully deployed

2 active deployments
Preview – cmux166 — 09118b6f Deployed Sep 12, 2026 by vercel[bot]
Preview – cmux41 — 09118b6f Deployed Sep 12, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: build-and-ci Build system, CI workflows, test infrastructure closing-soon Conflicting or red with no activity for 7+ days; closes 2026-10-06 unless the label is removed difficulty:4 Architecture: security, protocol, migration, release, or broad design ready-to-land Reviewed and ready to land when CI is green

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants