Skip to content

fix: preserve quoted NODE_OPTIONS while stripping cmux preload - #16031

Merged
teamleaderleo merged 6 commits into
mainfrom
fix/quoted-node-options-cleanup
Oct 1, 2026
Merged

teamleaderleo merged 6 commits into
mainfrom
fix/quoted-node-options-cleanup

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Sep 30, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Parse quoted NODE_OPTIONS arguments before removing cmux's restore preload, preserving spaces and escaped quotes in the remaining Node options and session resume commands.

Changelog

none

Origin: /Users/leoli/Projects/cmux-worktrees/pr14814-quoting (source checkout cmux-worktrees/pr14814-quoting).

Verification

Not run during idle-checkout triage; this draft needs the focused agent-launch and session-persistence tests.


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 Claude Node children dying with MODULE_NOT_FOUND after macOS purges $TMPDIR during long-lived sessions by keeping the restore preload in ~/.cmuxterm, and makes preload stripping preserve quoted arguments when $HOME contains spaces.

  • The preload now writes to ~/.cmuxterm/cmux-claude-node-options (0700) instead of $TMPDIR, and the --require path is quoted when it contains whitespace.
  • NODE_OPTIONS is tokenized like Node itself does, so quoted paths and escaped quotes survive stripping; an unusable $TMPDIR no longer disables the injection.

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

Review in cubic

teamleaderleo and others added 4 commits September 26, 2026 04:20
The wrapper's NODE_OPTIONS restore preload lives in $TMPDIR, so once
macOS purges it every later Node child exits with MODULE_NOT_FOUND.
Ported from #12067.

Co-authored-by: Austin Wang <austinwang115@gmail.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Both the claude wrapper and the claude-teams/omc launchers wrote the
restore preload to $TMPDIR, which macOS purges under long-lived
sessions, after which every Node child fails with MODULE_NOT_FOUND.
Write it to ~/.cmuxterm/cmux-claude-node-options (0700, atomic
temp-and-rename) alongside the other CLI shims, and quote the
--require path when $HOME contains whitespace.

Co-authored-by: Austin Wang <austinwang115@gmail.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The TMPDIR test rewrite dropped this function while main() still calls it,
so the Claude wrapper lane stopped with a NameError.

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

coderabbitai Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 2 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 10 included reviews currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

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

Review profile: ASSERTIVE

Plan: Advanced

Run ID: c50e74e7-fdee-47d1-8012-089d3a03d719

📥 Commits

Reviewing files that changed from the base of the PR and between 8840999 and be89b71.

📒 Files selected for processing (3)
  • Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/AgentLaunchEnvironmentPolicy.swift
  • Packages/macOS/CMUXAgentLaunch/Tests/CMUXAgentLaunchTests/AgentLaunchEnvironmentPolicyTests.swift
  • cmuxTests/SessionPersistenceTests.swift
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


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.

@github-actions

Copy link
Copy Markdown
Contributor

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

teamleaderleo and others added 2 commits October 1, 2026 10:07
Co-Authored-By: Codex <noreply@openai.com>
Co-Authored-By: Codex <noreply@openai.com>
@github-actions

github-actions Bot commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

CI failure attribution

CI failed on be89b71264 (run 36880674119 attempt 1): 1 unknown.

Job Verdict Why
changes unknown no known signature; failed step: Choose the macOS suite for this run

Not re-run automatically: changes is not a machine failure.

Written by scripts/ci/classify_failures.py (ci-failure-attribution.yml); signatures are its SIGNATURES table. A machine verdict is the runner's fault, not this PR's.

@github-actions

github-actions Bot commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

CI fast guards failed on be89b71264 (https://github.com/manaflow-ai/cmux/actions/runs/36880672511). It does not block the merge; a red guard merged into main breaks it for every open PR.

Run canonical CMUX CI guard profile

Duplicate cmuxTests selector identifiers:
  cmuxTests/SocketListenerAcceptPolicyTests/testClaudeResumeCommandStripsQuotedCmuxNodeOptionsRestoreModuleInHomeWithSpace(): cmuxTests/SessionPersistenceTests.swift:4050, cmuxTests/SessionPersistenceTests.swift:4098
{"artifact_identities":[],"benchmark":{"comparison_context_key":"sha256:ea0b92873db2498f8027d12abd21e258ef8f26f247d0661fc19580a6601e9663","semantic_comparison_key":"sha256:9653019352dfc55cf682ea1fc6f98d5831841d893a1d972251ed8dd50bd72d9a","state_class":"cold"},"cleanup":{"process_group_settled":true,"state":"complete"},"document_type":"cmux-workload-result","ended_at_unix_millis":1790866777510,"environment_class":"isolated-portable","exit_code":1,"expected_result_class":"cmux.ci-guard-result/v1","network_class":"none","parameters":{},"profile":{"generation":1,"id":"cmux.ci.guard"},"resource_summary":{"architecture":"x86_64","cpu_count":4,"memory_bytes":16766414848,"resource_class":"cmux-linux-ci-small"},"result":"failed","runtime_input_identities":[],"schema_version":1,"semantic_validator":"cmux.ci-guard/v1","source":{"commit":"80ab33e4604271d9749a6d29f750789f3fbe0864","repository":"manaflow-ai/cmux","tree":"4f47952844f06887cc1b548bdbb0df65b8a80bef"},"stage_timings":[{"seconds":7.506,"stage":"execute"}],"started_at_unix_millis":1790866769442,"timeout_class":"portable-short","toolchain":{"identity":"sha256:2df0267b8039ab43bd86e02b83e23fbecf587f109a12e189ca541fd4b691bcca","observations":{"bash":"GNU bash, version 5.2.21(1)-r ...

Fix: the assertion above names what the guard expects; change the tree to match it.
Reproduce in seconds, no build: scripts/ci/guards-local.sh --step 'Run canonical CMUX CI guard profile'

Agents: python3 scripts/ci/guard_attribution.py fix applies the mechanical fixes locally. This comment is updated in place on each push.

@teamleaderleo
teamleaderleo marked this pull request as ready for review October 1, 2026 19:09
@teamleaderleo
teamleaderleo enabled auto-merge (squash) October 1, 2026 19:10
@teamleaderleo
teamleaderleo merged commit a768c63 into main Oct 1, 2026
43 of 50 checks passed
@teamleaderleo
teamleaderleo deleted the fix/quoted-node-options-cleanup branch October 1, 2026 19:12
@github-actions

github-actions Bot commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

Merge receipt for be89b71264, merged 2026-10-01 19:12:00 UTC

  • Not verified at merge: ci-status (failure), CI fast guards (failure), ios-tests (failure), linux-preflight (failure), package-conventions-lint (failure), tests (failure)
  • Verified: CI timing, detect-ios-changes, Fast static checks, runner, Web complexity, web-validation
  • Skipped by policy: browser, Claude wrapper regressions, Dogfood build #​${{ github.event.pull_request.number }}, full-suite-coverage, GhosttyKit release check, guards, ios-simulator, ios-simulator-build, macos, macOS admission gate, mobile-core-package, remote-daemon, and 6 more
  • Full suite: runs on main after merge.

Labeled merged-unverified: if main breaks near this merge, look here first.

@github-actions github-actions Bot added the merged-unverified A judging check was not green at merge; see the merge receipt comment label Oct 1, 2026
@github-actions

github-actions Bot commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

This PR broke CI fast guards on main. Every open PR's guard check is red on Run canonical CMUX CI guard profile until it is fixed forward.
How this was found: the step was run on each of 2 commits since it last passed on main; this is the first to fail it. Merge commit a768c638bc; main run: https://github.com/manaflow-ai/cmux/actions/runs/36912546200.

Run canonical CMUX CI guard profile

Duplicate cmuxTests selector identifiers:
  cmuxTests/SocketListenerAcceptPolicyTests/testClaudeResumeCommandStripsQuotedCmuxNodeOptionsRestoreModuleInHomeWithSpace(): cmuxTests/SessionPersistenceTests.swift:4050, cmuxTests/SessionPersistenceTests.swift:4098
{"artifact_identities":[],"benchmark":{"comparison_context_key":"sha256:90221b2378e655202f39cbf5308f2249329e9a3ca45174762aaea1620047ba9e","semantic_comparison_key":"sha256:92c0c6b970263f46cfc2c7d96f2810ddc2badf2515cd8616d3a67fa5cd8988d4","state_class":"cold"},"cleanup":{"process_group_settled":true,"state":"complete"},"document_type":"cmux-workload-result","ended_at_unix_millis":1790881976332,"environment_class":"isolated-portable","exit_code":1,"expected_result_class":"cmux.ci-guard-result/v1","network_class":"none","parameters":{},"profile":{"generation":1,"id":"cmux.ci.guard"},"resource_summary":{"architecture":"x86_64","cpu_count":4,"memory_bytes":16766414848,"resource_class":"cmux-linux-ci-small"},"result":"failed","runtime_input_identities":[],"schema_version":1,"semantic_validator":"cmux.ci-guard/v1","source":{"commit":"b22abfa337883b18c700a0854c4f0d19292aa528","repository":"manaflow-ai/cmux","tree":"ad9d6039f60aad96d88830de29d72225a7f90d1a"},"stage_timings":[{"seconds":7.652,"stage":"execute"}],"started_at_unix_millis":1790881968163,"timeout_class":"portable-short","toolchain":{"identity":"sha256:2df0267b8039ab43bd86e02b83e23fbecf587f109a12e189ca541fd4b691bcca","observations":{"bash":"GNU bash, version 5.2.21(1)-r ...

Fix: the assertion above names what the guard expects; change the tree to match it.
Reproduce in seconds, no build: scripts/ci/guards-local.sh --step 'Run canonical CMUX CI guard profile'

Tracking: #16466. @teamleaderleo

teamleaderleo added a commit that referenced this pull request Oct 1, 2026
* test: repair four package test targets that main stopped compiling or passing

- CmuxAgentJournal: #15279 called draft(to:senderSurfaceId:body:) after
  #15863 put body before senderSurfaceId.
- CmuxFoundation: #16378's Codex TOML tests expected an appended
  [features] table, but the editor rewrites an existing hooks = false in
  place inside its marker block. Assert that block instead.
- CmuxSwiftRenderUI: #16408's allSatisfy(\.isValid) inside #expect does
  not compile (the macro makes the key path a throwing argument).
- CmuxUpdaterUI: #16357 reverted UpdateBadge.hostedIconRequest and the
  CmuxAppKitSupportUI dependency but left #15756's UpdateBadgeTests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FrR7YbsQtGw2eFtDeyiTcK

* ci: let consumer app-host tests find the source tree again

#16116 dropped the /private/tmp/cmux-ci/src alias in favor of
CMUX_CI_RUNTIME_SOURCE_ROOT, but xcodebuild only forwards TEST_RUNNER_
variables to the test host, so SwiftTestingAssertions.sourceURL() fell
back to the producer's #filePath. On a consumer runner that never
compiled, dozens of source-backed tests (shell integration, wrappers,
source scans) then fail with file-not-found.

Forward the root as TEST_RUNNER_CMUX_CI_RUNTIME_SOURCE_ROOT, and alias
the producer's canonical src to this checkout when nothing is there, for
raw #filePath users (cmuxCLITests, CLI dev-resource fallbacks).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FrR7YbsQtGw2eFtDeyiTcK

* test: repair two agent notification tests main never ran green

- AgentSemanticNotificationDeliveryTests (#15974): enqueue a session-
  scoped prompt only after binding that session to the surface, which
  notificationRequestIsCurrent has required since #11976. The PR merged
  with its app-host shards cancelled.
- testCodexStopWithMissedPromptSubmitClearsTerminalStaleTurn: since
  2f574d6 (#15345) turn_aborted is terminal for the transcript
  monitor, so its Stop replay may retire the aborted turn before the next
  Stop does. Accept either retirement and wait for it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FrR7YbsQtGw2eFtDeyiTcK

* ci: drop the producer-root alias; resolve CLI test sources through the runtime root

Review of 69a68d6: the restore-time alias at the producer's canonical src
breaks #16116's rule that restore never touches the producer root (two
wiring tests encode it) and can race a producer's rm/clone on shared
Macs. Instead, the two raw #filePath sites in cmuxCLITests read
CMUX_CI_RUNTIME_SOURCE_ROOT like SwiftTestingAssertions.sourceURL(), and
the CLI product step forwards it as TEST_RUNNER_.

The Codex aborted-turn test now captures from before the old prompt (a
fast monitor replay was missed) and asserts silence only on the
transcript-terminal path: the monitor replay settles the aborted turn as
a completed Stop, which notifies (#15345's behavior).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FrR7YbsQtGw2eFtDeyiTcK

* ci: forward the runtime source root into the console-session test runner

The app-host shards run run-app-host-xcodebuild.sh through
run-in-console-session.sh, which forwards only an allowlist of
variables. CMUX_CI_RUNTIME_SOURCE_ROOT was not on it, so the
TEST_RUNNER_ forwarding never fired and sourceURL() kept falling back to
the producer's #filePath (run 36903763717 still showed /tmp/cmux-ci/src).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FrR7YbsQtGw2eFtDeyiTcK

* ci: give the standalone CLI under test its bundled opencode plugin

The CLI product job tests Build/Products/Debug/cmux, where none of the
CLI's resource candidates exist, so 'hooks opencode install' only found
the plugin through its #filePath fallback into the source tree. Place it
beside the executable, one of the paths the CLI already searches.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FrR7YbsQtGw2eFtDeyiTcK

* test: rename the older of two same-named Claude NODE_OPTIONS resume tests

#16031 added testClaudeResumeCommandStripsQuotedCmuxNodeOptionsRestoreModuleInHomeWithSpace
next to an existing test of the same name, so cmuxTests no longer
compiles and the shard planner rejects the duplicate selector. The older
one keeps a user --require, so name it for that.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FrR7YbsQtGw2eFtDeyiTcK

* Revert "test: rename the older of two same-named Claude NODE_OPTIONS resume tests"

This reverts commit 852333a.

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merged-unverified A judging check was not green at merge; see the merge receipt comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant