Skip to content

Keep CLI socket-discovery tests off the host's real cmux - #14919

Merged
teamleaderleo merged 3 commits into
mainfrom
fix/cli-tests-isolate-home
Sep 27, 2026
Merged

teamleaderleo merged 3 commits into
mainfrom
fix/cli-tests-isolate-home

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Sep 27, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Two tests in CMUXCLIErrorOutputRegressionTests expect the CLI to find no live socket: testAmbientTaggedCLIListsEveryDeadSocketCandidateOnFailure and testLaunchCapableCommandsReachTheirDispatchPathWithoutLiveImplicitSocket. On runner cmuxs-mac-mini-3 they failed because the CLI reached the runner's own cmux, which runs as the same user:

cmux: default socket /tmp/cmux-debug-cli-ambient-all-dead-….sock is unavailable; using /Users/cmux/.local/state/cmux/cmux-501.sock.

Failing runs:

Root cause

The tests moved the home directory only through CFFIXED_USER_HOME. That does move the resolver's state directory, because homeDirectoryForCurrentUser honors it. But implicit discovery also reads the machine-wide /tmp/*-last-socket-path marker mirrors and tries the legacy /tmp/cmux.sock and /tmp/cmux-<uid>.sock aliases. Every cmux running as that user shares those paths.

writeStableSocketMarker worked around the stable /tmp marker back when discovery stopped at the first readable marker. Discovery now walks every marker, so the real app's /tmp/cmux-last-socket-path was followed to its live socket. The same leak lets these tests send ping, restore and fork to a developer's running cmux.

Fix

  • Tests: BundledCLITestSupport.hermeticCLIEnvironment(home:) sets HOME, CFFIXED_USER_HOME, XDG_* and TMPDIR inside the temp home. It drops every inherited CMUX* and XDG_* variable and sets CMUX_TEST_ISOLATED_SOCKET_DISCOVERY=1. All 20 CFFIXED_USER_HOME call sites in the suite now use it.
  • CLI: in Debug builds only, CLISocketPathResolver honors that key. It skips marker files outside the state directory and drops the legacy /tmp aliases. The variant's own default socket and state-directory markers still count. Release builds compile the check out, and neither production discovery order nor socket locations change.
  • New tests:
    • a guard that the helper never exposes the real home or socket pins
    • a spawned-CLI regression: a per-tag /tmp marker names a live socket, and the CLI must not use it
    • a resolver test comparing the isolated and ambient candidate lists

Commits

  • ed883fc9ba0: failing regression. The new CLI test fails, because the CLI follows the /tmp marker, and the resolver test does not compile yet.
  • d52024cbadc: fix
  • a test tidy-up commit

Verification

  • verify-local --affected mf/main --swift-changed mf/main: swift-syntax, test-wiring and feature-flags passed.
  • No local xcodebuild; the machine is under heavy load. App-host execution of the suite is left to CI.
  • Suites in other files that also set CFFIXED_USER_HOME are not migrated here. Most of them pin CMUX_SOCKET_PATH.

🤖 Generated with Claude Code


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


Summary by cubic

Fixes socket-discovery tests reaching the host's real cmux by isolating implicit discovery to the test's state directory in Debug builds.

Bug Fixes

  • CLISocketPathResolver honors CMUX_TEST_ISOLATED_SOCKET_DISCOVERY=1 in Debug only, skipping /tmp marker files and legacy aliases outside the state directory.
  • Release builds compile the check out; production discovery order and socket locations are unchanged.

Refactors

  • Added BundledCLITestSupport.hermeticCLIEnvironment(home:) and migrated all 20 CFFIXED_USER_HOME call sites in the suite to it.
  • Added tests covering the helper's isolation guarantees, a spawned-CLI regression for /tmp markers naming a live socket, and a resolver test comparing ambient vs isolated candidate lists.

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

Review in cubic

Summary by CodeRabbit

  • Tests
    • CLI test runs now use isolated temporary environments, reducing interference from machine-wide settings and socket markers.
    • Added regression coverage to verify socket discovery stays within the test environment while retaining local candidates.

teamleaderleo and others added 3 commits September 27, 2026 03:12
CLI subprocess tests in CMUXCLIErrorOutputRegressionTests redirected only
CFFIXED_USER_HOME. Implicit socket discovery still reads the machine-wide
/tmp last-socket-path markers, so on a runner (or developer Mac) where a
real cmux runs as the same user, tests that expect no live socket were
rerouted to that app's socket (cmuxs-mac-mini-3:
/Users/cmux/.local/state/cmux/cmux-501.sock).

Add BundledCLITestSupport.hermeticCLIEnvironment, which points HOME,
CFFIXED_USER_HOME, the XDG base directories and TMPDIR into the temp home,
drops inherited CMUX_*/CMUXTERM_*/XDG_* variables, and asks the Debug CLI to
confine discovery to its state directory. Route every CFFIXED_USER_HOME
call site in the suite through it, and add:

- a guard that the helper never exposes the real home or socket pins,
- a CLI regression where a per-tag /tmp marker names a live socket,
- a resolver test for the isolated candidate list.

The regression and resolver tests fail until the CLI honors the
isolation key (next commit).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Implicit discovery walks the state-directory markers, then the
machine-wide /tmp last-socket-path mirrors and the legacy /tmp socket
aliases. Those /tmp entries are shared by every cmux running as the same
user, so a test that moves the state directory with CFFIXED_USER_HOME
still reached the host's real app (CI runner cmuxs-mac-mini-3 rerouted
to /Users/cmux/.local/state/cmux/cmux-501.sock).

Debug builds now honor CMUX_TEST_ISOLATED_SOCKET_DISCOVERY=1: marker
files outside the state directory are skipped, and the legacy /tmp
aliases and non-state-dir requested paths are dropped from the candidate
list. The variant's own default socket and state-directory markers still
count. Release builds compile the check out, and production discovery
order is unchanged.

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

Copy link
Copy Markdown
Contributor

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

@coderabbitai

coderabbitai Bot commented Sep 27, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: manaflow-ai/cmux/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 34c35351-c24d-4d96-9376-62fa2ab7b67a

📥 Commits

Reviewing files that changed from the base of the PR and between b1daa44 and f859835.

📒 Files selected for processing (3)
  • CLI/CLISocketPathResolver.swift
  • cmuxTests/BundledCLILinkageTests.swift
  • cmuxTests/CMUXCLIErrorOutputRegressionTests.swift

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 2 remain after this review.


📝 Walkthrough

Walkthrough

The CLI socket resolver adds debug-only confinement for implicit discovery candidates. CLI subprocess tests now use a hermetic environment and include coverage for environment paths and socket discovery.

Changes

CLI socket discovery

Layer / File(s) Summary
Resolver discovery confinement
CLI/CLISocketPathResolver.swift
A debug-only setting enables filtering of requested, fallback, and marker-file candidates outside stateDirectory. Release builds disable the setting.
Hermetic CLI environment and regression coverage
cmuxTests/BundledCLILinkageTests.swift, cmuxTests/CMUXCLIErrorOutputRegressionTests.swift
Test support creates a private environment for CLI subprocesses. Tests use the helper and check environment confinement, machine-wide marker exclusion, and retention of test-local candidates.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Bug fix

Merge Risk: ⚪ Minimal · up to f8598

The CLI tests exclude machine-wide socket markers and legacy aliases while retaining their intended test-local candidates. No issue identified here needs to block merging.

Security Architecture Review

Security architecture risk: 🔵 Low · up to f8598

The change appears to reduce the chance that tests contact a running cmux on the host, without changing release behavior. Isolation is deliberately limited rather than a guarantee that every reachable socket is test-owned, and the tests were not observed running in this review.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The affected boundary is local CLI-to-same-user Unix-socket discovery, principally for Debug CLI subprocesses using temporary homes. The new setting does not increase release-build discovery reachability.

Security Findings and Attack Paths

  • inferred — Previously, an implicit CLI command using a temporary home could still follow a shared /tmp marker to a live same-user cmux. The added regression models that path and asserts that isolated discovery does not send its ping to the simulated outside listener; this is test evidence, not an observed execution result.

Trust Boundaries and Controls

  • observed — The resolver requires an owned socket that accepts connections and applies ownership, file-type, link-count, and size checks before reading marker contents. Those checks do not constrain an accepted marker's destination to the temporary state directory.
🚥 Pre-merge checks | ✅ 24 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.43% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 35 functions across 3 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (24 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main change: preventing CLI socket-discovery tests from connecting to the host's real cmux instance.
Description check ✅ Passed The description explains the failure, root cause, implementation, added tests, verification results, and remaining CI coverage. It does not include the template checklist or a demo attachment, but the…
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 Cloud Persistent Session And Early Input ✅ Passed PASS. The reviewed diff changes CLI socket discovery and test environment setup in three Swift files. It does not change Cloud terminal creation, persistent cmux-tui transport, manual renderers, PTY r…
Cmux Swift Actor Isolation ✅ Passed The only production change is in CLI/CLISocketPathResolver.swift. It adds a stored Bool, a static environment-key constant, and synchronous path-filtering helpers to an existing value-type resolve…
Cmux Swift Blocking Runtime ✅ Passed PASS. The production change in CLI/CLISocketPathResolver.swift only adds a Debug-gated flag and path filtering. It adds no semaphore, blocking wait, sleep, delayed dispatch, polling loop, main-queue…
Cmux Browser Automation Off-Main ✅ Passed PASS: The pull request changes only CLI socket discovery and CLI test environment files. The authoritative diff contains no browser.* commands, WebKit/AppKit automation routing, socket-worker policy c…
Cmux Expensive Synchronous Load ✅ Passed PASS. The only production Swift change is in CLI/CLISocketPathResolver.swift; it adds a Debug-only environment flag and filters socket-discovery paths by state directory. The diff adds no `Restorabl…
Cmux Cache Substitution Correctness ✅ Passed PASS: The production diff only adds Debug-only filtering for CLI socket discovery in CLI/CLISocketPathResolver.swift. It does not replace a fresh authoritative read with a cache or opportunistic val…
Cmux No Hacky Sleeps ✅ Passed The pull request changes only three Swift files. It introduces no TypeScript, JavaScript, shell, or build/runtime-script changes. The existing Swift socket poll remains unchanged, so this check has no…
Cmux Algorithmic Complexity ✅ Passed PASS. The only production change is in CLI/CLISocketPathResolver.swift. It filters the fixed socket-discovery inputs and standardizes each path once. SocketPathMarkerFiles.paths returns at most tw…
Cmux Swift Concurrency ✅ Passed The pull request introduces no legacy async pattern covered by the check. The added Swift lines contain no Dispatch, Combine, Task, async/await, completion-handler, or fire-and-forget usage. The only …
Cmux Swift @Concurrent ✅ Passed The PR adds no changed async, await, nonisolated, @concurrent, or actor-isolation declarations. The new hermeticCLIEnvironment helper is synchronous. The existing async theme test and its ex…
Cmux Swift Package Boundaries ✅ Passed PASS. The production diff adds a small Debug-only test-isolation branch to the existing CLI/CLISocketPathResolver, plus path filtering. It does not introduce or materially expand a reusable domain f…
Cmux Swiftpm Lockfiles ✅ Passed PASS. The PR changes only CLI/CLISocketPathResolver.swift and two test files. It does not change Package.swift, Package.resolved, .gitignore, workflows, or Xcode package references. The SwiftP…
Cmux Swift Logging ✅ Passed PASS. The only production Swift change is CLI/CLISocketPathResolver.swift, which adds environment-gated path filtering and no logging calls or logger declarations. The changed test code writes socke…
Cmux User-Facing Error Privacy ✅ Passed PASS. The only production-file change adds Debug-only socket-discovery filtering and the internal CMUX_TEST_ISOLATED_SOCKET_DISCOVERY key. It adds no user-facing error, alert, command-output, or rec…
Cmux Full Internationalization ✅ Passed PASS: The production diff only adds Debug-only socket-discovery isolation and a configuration key. It adds no user-facing text. Existing CLI diagnostics remain localized and their catalog entries are …
Cmux Swiftui State Layout ✅ Passed PASS. The pull request changes only CLI socket resolution and CLI test support. The authoritative diff contains no SwiftUI imports, ObservableObject, @Published, @Observable, GeometryReader, lazy/list…
Cmux Architecture Rethink ✅ Passed PASS. The diff adds a local CLISocketPathResolver invariant: when the Debug-only test key is set, implicit candidates must remain under stateDirectory; explicit paths remain unchanged. The test he…
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed PASS. The PR changes only CLI socket discovery and CLI test environment support in three Swift files. The scoped diff adds no NSWindow, NSPanel, NSWindowController, SwiftUI Window, WindowGroup, or clo…
Cmux Source Artifacts ✅ Passed All three changed paths are tracked Swift source or test files. The diff adds resolver logic, test-environment support, and regression tests. No changed path or added source line introduces a local/ge…
Cmux No Test Or Debug Seam In Production Source ✅ Passed PASS: The only changed Swift file outside test targets is CLI/CLISocketPathResolver.swift, which is not under a **/Sources/** path. The custom check therefore does not apply. The other changed Swi…
  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

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.

@teamleaderleo
teamleaderleo merged commit dc90332 into main Sep 27, 2026
100 of 105 checks passed
@teamleaderleo
teamleaderleo deleted the fix/cli-tests-isolate-home branch September 27, 2026 12:57
@github-actions

Copy link
Copy Markdown
Contributor

Merge receipt for f859835461: every check was green at merge (16 verified; 14 skipped by policy). Full suite runs on main after merge.

rustybret pushed a commit to rustybret/bmux that referenced this pull request Sep 27, 2026
f5c179f iOS: fix the test failures that keep iOS CI red on main (manaflow-ai#14803)
8685bf5 Hold update relaunch while agents are mid-turn (manaflow-ai#14969)
dc90332 Keep CLI socket-discovery tests off the host's real cmux (manaflow-ai#14919)
dd3c91b docs: shorten root agent instructions and link existing procedures (manaflow-ai#14998)
8c744df Rename edits inline or in the palette, never in an alert (manaflow-ai#14986)
9ae4383 Calmer chrome motion: appear instantly, fade out only, no overshoot (manaflow-ai#14984)
6510f56 Write opencode config JSON without escaping slashes (cmux 7140) (manaflow-ai#14805)
ab5e7da ci: stop catch-up merges from failing the CLA check (manaflow-ai#14913)
52c8f41 Add cmux session move for Claude sessions (manaflow-ai#14959)
36785b1 Hide decorative Settings sidebar icons from VoiceOver (manaflow-ai#14989)
4c7158c Label the sound preview button and fix mistranslated action verbs (manaflow-ai#14983)
e704a77 Bound untracked paths stored in last-turn diff baselines (manaflow-ai#14980)
f073df1 Fix remote Files sidebar for names that change under NFD (manaflow-ai#14978)
5c68499 Bump bonsplit: mouse wheel scrolls the overflowed tab strip (manaflow-ai#14985)
9466dcb Keep agent resume bindings through the update-relaunch save (manaflow-ai#14971)
ef8b037 docs: take release notes from a Changelog section in each PR instead of CHANGELOG.md edits (manaflow-ai#14934)
6eddfd7 ci: skip the delta diff when main moved further than the pull request (manaflow-ai#14987)
fefcec7 ci: attribute red PR runs to the machine or the code, re-run machine failures once (manaflow-ai#14977)
c185deb Accept file drops on remote tmux mirror panes (manaflow-ai#14981)
90773c7 test: make CmuxSidebarGit probe waits event-driven (manaflow-ai#14973)
1f2dbfe ci: skip the scheduled Blacksmith cache warmers while owned pools serve PRs (manaflow-ai#14827)
2850651 docs: add a guide to customizing cmux's look (manaflow-ai#14850)
b66e365 Resolve a separate sidebar's content against its own backdrop (manaflow-ai#14841)
88a9360 UI tests: one labelled frame per action, built in CI; scripts/ui-test (manaflow-ai#14966)
20cfa78 fix(omo): resolve relative file refs in the shadow config without double-loading OpenCode config (manaflow-ai#14935)
f0e964c ci: make the aggregate app-host product the default, layers opt-in (manaflow-ai#14975)
52dce98 ci: run and register the machine-failure test (manaflow-ai#14972)
7bf48bc ci: route compile admission by kept-build distance across minis (manaflow-ai#14949)
44fa3f5 Offer cmux in Open With for Markdown, source, and text files (manaflow-ai#14968)
45c2d66 Replay the Claude session id of agents in cmux ssh (cmux-tui) panes (manaflow-ai#14906)
b4c1b31 Label icon-only chrome buttons and localize project panel text (manaflow-ai#14926)
14a6909 seed prefetch: keep the seed adopt would pick, of any seeded width (manaflow-ai#14944)
19e73d2 ci: self-calibrating warm-distance compile estimates (manaflow-ai#14932)
fa98d86 ci: redispatch focused runs the Mac failed before any test started (manaflow-ai#14963)
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