Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
149 commits
Select commit Hold shift + click to select a range
ad8fb0c
test: cover main window frame repair regressions
austinywang Sep 6, 2026
ec4d363
fix: reconcile main window frames across display changes
austinywang Sep 6, 2026
261d249
fix: preserve exact fullscreen display frames
austinywang Sep 6, 2026
df1d0ae
chore: normalize Xcode project
austinywang Sep 6, 2026
5be7c33
Merge branch 'main' into issue-2824-window-offscreen-monitor
austinywang Sep 6, 2026
4749674
Merge remote-tracking branch 'origin/main' into issue-2824-window-off…
austinywang Sep 6, 2026
bc74118
Merge remote-tracking branch 'origin/main' into issue-2824-window-off…
austinywang Sep 6, 2026
00e37b8
Merge remote-tracking branch 'origin/main' into issue-2824-window-off…
austinywang Sep 6, 2026
dd2f07d
Merge remote-tracking branch 'origin/main' into issue-2824-window-off…
austinywang Sep 6, 2026
df59ac6
fix: restore build after currentness merge
austinywang Sep 6, 2026
29e0d66
Merge branch 'main' into issue-2824-window-offscreen-monitor
austinywang Sep 6, 2026
0962db4
Merge branch 'main' into issue-2824-window-offscreen-monitor
austinywang Sep 6, 2026
a8309ba
Merge branch 'main' into issue-2824-window-offscreen-monitor
austinywang Sep 8, 2026
46c7d81
fix: clear stale zoom intent after user placement
austinywang Sep 8, 2026
c9e0485
fix: avoid clearing zoom intent on AppKit moves
austinywang Sep 8, 2026
382ab12
fix: narrow main windows before managed placement
austinywang Sep 8, 2026
15e9d4f
Merge branch 'main' into issue-2824-window-offscreen-monitor
austinywang Sep 8, 2026
5f14039
Merge branch 'main' into issue-2824-window-offscreen-monitor
austinywang Sep 8, 2026
03a1507
test: preserve system-owned Split View geometry during repairs
austinywang Sep 8, 2026
16b2d54
fix: leave fullscreen tile geometry to AppKit
austinywang Sep 8, 2026
9a5454d
Merge branch 'main' of https://github.com/manaflow-ai/cmux into issue…
austinywang Sep 10, 2026
477d14f
test: repair Bun mock typings and fixture path
austinywang Sep 10, 2026
bc56f91
Merge origin/main into window frame repair
austinywang Sep 10, 2026
6a92d83
test: initialize application for window cache passthrough
austinywang Sep 10, 2026
88d97db
test: cover zoom intent across clicks and native tiling
austinywang Sep 10, 2026
c5f692d
fix: clear zoom intent on AppKit placement callbacks
austinywang Sep 10, 2026
3725bb4
Merge remote-tracking branch 'origin/main' into issue-2824-window-off…
austinywang Sep 10, 2026
bbb9b03
test: align Cloud network coverage with baked image contracts
austinywang Sep 10, 2026
664374f
Merge main with completed Cloud readiness implementation
austinywang Sep 10, 2026
e2ae501
refactor: clarify the display topology repair trigger
austinywang Sep 10, 2026
a5b6b6e
ci: make window placement regressions a strict gate
austinywang Sep 10, 2026
6d4b641
Merge remote-tracking branch 'origin/main' into issue-2824-window-off…
austinywang Sep 10, 2026
5191deb
test: reject masked app-host assertion failures
austinywang Sep 10, 2026
acedf3f
test: enforce clean app-host runs and isolate shared test state
austinywang Sep 10, 2026
b7eca70
test: preserve zoom placement through untrusted display snapshots
austinywang Sep 10, 2026
fcf90a7
test: cover explicit SSH control options during config discovery
austinywang Sep 10, 2026
c8bfb58
fix: repair failures exposed by strict app-host CI
austinywang Sep 10, 2026
0f447a7
Merge remote-tracking branch 'origin/main' into issue-2824-window-off…
austinywang Sep 10, 2026
9816928
test: preserve pending cloud work across stale updates and revoke
austinywang Sep 10, 2026
cd9f34f
fix: resolve runtime races and finish app-host test repairs
austinywang Sep 11, 2026
33dcbd6
test: wait for initial PTY resize before delivering input
austinywang Sep 11, 2026
451ed25
test: use the concrete browser view in focus fixtures
austinywang Sep 11, 2026
4e88328
Merge branch 'ci12053-regression-compile' into issue-2824-window-offs…
austinywang Sep 11, 2026
236666e
test: keep titlebar sizing checks independent of system font metrics
austinywang Sep 11, 2026
5ec10ca
Merge remote-tracking branch 'origin/main' into issue-2824-window-off…
austinywang Sep 11, 2026
d3bf99b
test: keep settings recorder alive through external overwrite
austinywang Sep 11, 2026
b22e177
test: reproduce tunnel disconnect during status adoption
austinywang Sep 11, 2026
67d6b2a
fix: repair app-host runtime failures and stale test fixtures
austinywang Sep 11, 2026
0403525
Merge remote-tracking branch 'origin/main' into issue-2824-window-off…
austinywang Sep 11, 2026
b9a8ed3
test: route reconnect fixtures through persistent PTY attach
austinywang Sep 11, 2026
529b63f
Merge branch 'main' of https://github.com/manaflow-ai/cmux into issue…
austinywang Sep 11, 2026
d75b375
Merge remote-tracking branch 'origin/main' into issue-2824-window-off…
austinywang Sep 11, 2026
4120e35
Fix regressions after syncing main
austinywang Sep 11, 2026
f08041b
Fix async reconnect test declaration
austinywang Sep 11, 2026
362f450
Refresh stale assertions after main sync
austinywang Sep 11, 2026
051fe79
Merge remote-tracking branch 'origin/main' into issue-2824-window-off…
austinywang Sep 11, 2026
f3712c1
Fix Bun test timeout syntax
austinywang Sep 11, 2026
6a71b96
Merge remote-tracking branch 'origin/main' into issue-2824-window-off…
austinywang Sep 11, 2026
23a3a5a
test: cover Ubuntu APT HTTPS normalization
austinywang Sep 11, 2026
908896a
Repair remote restore test fixtures
austinywang Sep 11, 2026
846b0c7
ci: use HTTPS Ubuntu package sources
austinywang Sep 11, 2026
e65a24e
Stabilize app host regression fixtures
austinywang Sep 11, 2026
aa66c10
Merge origin/main into issue-2824-window-offscreen-monitor
austinywang Sep 12, 2026
10a8d87
fix: repair main sync compile and telemetry
austinywang Sep 12, 2026
98652a6
fix: preserve window dock focus fallback
austinywang Sep 12, 2026
bcc15b8
ci: classify expected app host failures
austinywang Sep 12, 2026
2f97084
docs: cover cloud diagnostics socket method
austinywang Sep 12, 2026
db1799d
fix: bound pending cloud workspace receipts
austinywang Sep 12, 2026
2ec894f
fix: preserve artifact transfer authorization context
austinywang Sep 12, 2026
2f177a2
test: avoid timer in publication pool race
austinywang Sep 12, 2026
2527b58
Merge branch 'main' of https://github.com/manaflow-ai/cmux into issue…
austinywang Sep 13, 2026
902d17c
Merge remote-tracking branch 'origin/issue-2824-window-offscreen-moni…
austinywang Sep 13, 2026
0df9649
fix: repair merged workspace action and CI fixtures
austinywang Sep 13, 2026
ebf9e20
Merge remote-tracking branch 'origin/main' into issue-2824-window-off…
austinywang Sep 13, 2026
18b7db9
fix: initialize cloud dismissal store on the main actor
austinywang Sep 13, 2026
5377911
fix: repair cloud machines action wiring
austinywang Sep 13, 2026
861fd3f
ci: retry macOS validation
austinywang Sep 13, 2026
914acee
fix: keep Swift warning budget clean
austinywang Sep 13, 2026
16eefce
Merge branch 'main' of https://github.com/manaflow-ai/cmux into issue…
austinywang Sep 13, 2026
4014d5c
style: normalize merged source file endings
austinywang Sep 13, 2026
1263282
test: include API key auth in coderouter mocks
austinywang Sep 13, 2026
61ba0fd
fix: convert guest prompt asset URLs for Node
austinywang Sep 13, 2026
c9908b9
fix: use portable guest prompt asset paths
austinywang Sep 13, 2026
186c809
fix: resolve guest prompt assets from project root
austinywang Sep 13, 2026
235d12c
test: allow bounded QUIC reconnect timing probe
austinywang Sep 13, 2026
546c26b
fix: remove duplicate TUI provider implementations
austinywang Sep 14, 2026
e77c924
fix: restore cloud workspace title normalization
austinywang Sep 14, 2026
088ccb1
fix: remove obsolete cloud row warning argument
austinywang Sep 14, 2026
6fc77d8
test: remove duplicate TUI cancellation regression
austinywang Sep 14, 2026
f0bdfc5
Merge origin/main into issue-2824-window-offscreen-monitor
austinywang Sep 16, 2026
8e61a6d
Merge branch 'main' of https://github.com/manaflow-ai/cmux into issue…
austinywang Sep 16, 2026
9e0be67
fix: disambiguate merged Xcode test source identifiers
austinywang Sep 16, 2026
198826d
test: deduplicate merged API key mocks
austinywang Sep 16, 2026
6ab5d46
test: align CLI fixtures with queued hooks and VM resize
austinywang Sep 16, 2026
82eecb4
fix: apply admission timeout to ambient Grok hooks
austinywang Sep 16, 2026
36290f0
fix: complete iOS pairing disabled translations
austinywang Sep 16, 2026
2d44605
fix: restore settings dependencies of legacy pairing runtime
austinywang Sep 16, 2026
17ca330
fix: complete pairing runtime dependencies and deduplicate cloud rename
austinywang Sep 16, 2026
76f36af
fix: preserve V2 pairing runtime across opt-in integration
austinywang Sep 16, 2026
0215739
test: derive beta artifact version from configured lane
austinywang Sep 16, 2026
903edc6
test: await transport and dashboard completion signals
austinywang Sep 16, 2026
c881cc3
fix: make resize Dock routing explicit
austinywang Sep 16, 2026
cc26aef
fix: keep pro upgrade flag on its registry evaluation path
austinywang Sep 16, 2026
59a13bd
Merge remote-tracking branch 'origin/main' into issue-2824-window-off…
austinywang Sep 16, 2026
c30ee22
test: await client config request progress
austinywang Sep 16, 2026
d0e5bea
fix: clear new Swift warning budget regressions
austinywang Sep 16, 2026
6fe70f6
fix: repair merged CI regressions and runtime test fixtures
austinywang Sep 16, 2026
1a9e0d4
fix: honor hook identity for Claude forked child
austinywang Sep 16, 2026
559a2e0
Merge remote-tracking branch 'origin/main' into issue-2824-window-off…
austinywang Sep 16, 2026
b93291a
fix: route TUI delivery guard through configured runner
austinywang Sep 16, 2026
5e5dcf0
fix: mark trusted relay hook route snapshots
austinywang Sep 16, 2026
5677dbf
test: retrigger semantic hook delivery validation
austinywang Sep 16, 2026
a7fb52b
merge latest main mobile runtime changes
austinywang Sep 16, 2026
1c980c1
fix: use exported TUI default child terminal
austinywang Sep 16, 2026
02c1ba4
test: preserve authenticated artifact fetch boundary
austinywang Sep 16, 2026
af7723a
fix: distinguish Claude fork parent from child identity
austinywang Sep 16, 2026
c402b9c
test: repair app-host regressions after main merge
austinywang Sep 16, 2026
e7e4eef
test: bind the owned tmux workspace fixture
austinywang Sep 16, 2026
0929dc2
fix: size Cloud headers and complete app-host fixtures
austinywang Sep 16, 2026
79cb0de
test: keep cloud replacement fixture independent of state ingestion
austinywang Sep 16, 2026
dd50e96
fix: limit deferred loopback injection to about pages
austinywang Sep 16, 2026
df030e1
test: use nonoptional alert window in layout spy
austinywang Sep 16, 2026
915446a
test: stabilize remaining app-host lifecycle fixtures
austinywang Sep 16, 2026
900b250
test: stabilize package and focus lifecycle races
austinywang Sep 16, 2026
0ba309f
fix: resolve standalone alert layout before showing
austinywang Sep 16, 2026
0317cc8
fix: compile detached portal resize fallback
austinywang Sep 16, 2026
297508b
test: isolate shortcut and Codex foreground fixtures
austinywang Sep 16, 2026
331ebc1
test: align sidebar shortcut defaults with visible modes
austinywang Sep 16, 2026
e3e2ba5
test: pin app delegate and Codex ownership context
austinywang Sep 16, 2026
e1142e4
test: isolate Codex ledger environment
austinywang Sep 16, 2026
caa5700
merge origin/main into issue-2824
austinywang Sep 16, 2026
2127d97
fix: reconcile remaining hosted lifecycle checks
austinywang Sep 16, 2026
10534fa
test: settle remaining app-host fixture contracts
austinywang Sep 16, 2026
6d7b23f
fix: preserve active window and skip duplicate sidebar seeds
austinywang Sep 16, 2026
0332047
test: align hosted regressions with current Cloud and SSH contracts
austinywang Sep 16, 2026
75891ac
fix: require the owning window before focusing a Dock browser
austinywang Sep 16, 2026
3244229
test: control fallback timing and isolate SSH authentication attempts
austinywang Sep 16, 2026
29af8ce
merge origin/main and unify duplicate test build references
austinywang Sep 16, 2026
21c4536
test: exercise Dock surface handles through a real window owner
austinywang Sep 16, 2026
abc4fef
test: await the port refresh event in the zsh prompt fixture
austinywang Sep 16, 2026
3f0d26d
test: await pane-local split failures and fail fast on missing connec…
austinywang Sep 16, 2026
df400dd
test: bind key-window observation to the fixture delegate
austinywang Sep 16, 2026
8d33410
Merge origin/main into issue-2824-window-offscreen-monitor
austinywang Sep 21, 2026
5c28505
fix: reject transient display and tunnel snapshots
austinywang Sep 21, 2026
38b32bb
Merge current main test and CLI implementations
austinywang Sep 21, 2026
646d36b
fix: bound retired tunnel and confirm status snapshots
austinywang Sep 21, 2026
dd9c8b4
fix: silence redundant tunnel snapshot warning
austinywang Sep 21, 2026
553767e
fix: keep mobile artifact fetch on socket worker
austinywang Sep 21, 2026
73e22a7
Merge latest origin/main into issue-2824-window-offscreen-monitor
austinywang Sep 21, 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
1 change: 1 addition & 0 deletions .github/test-determinism-allowlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ tests/test_ci_sparkle_build_monotonic.sh live-network-host release pretag guard
Packages/Shared/CMUXMobileCore/Tests/CMUXMobileCoreTests/CmxRetryAfterPolicyTests.swift sleep-then-assert virtual-clock injection makes these large delays non-blocking and deterministic
Packages/iOS/CmuxMobileShell/Tests/CmuxMobileShellTests/MobileTerminalLaneCoordinatorTests.swift sleep-then-assert upstream coordinator readiness timing assertion
web/tests/vm-publication-pool-db.test.ts sleep-then-assert deadline-bounded database pool wait has no fixed sleep
Packages/Shared/CmuxIrxTransport/Tests/CmuxIrxTransportTests/IrxLiveQUICTests.swift sleep-then-assert bounded QUIC reconnect and retirement readiness probe from main
29 changes: 26 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1176,6 +1176,27 @@ jobs:
echo "::warning::Passwordless sudo unavailable; XCTest will use its default automation-mode setup"
fi

- name: Run main window zoom placement regressions
if: ${{ matrix.shard == fromJSON(env.CMUX_APP_HOST_FOCUSED_REGRESSION_SHARD) }}
run: |
# The bulk app-host classifier tolerates ordinary assertion failures.
# Window placement regressions must fail the shard directly while
# reusing the compile-admission product.
set -euo pipefail
test_log="$RUNNER_TEMP/cmux-main-window-zoom-placement.txt"
scripts/ci/run-in-console-session.sh \
scripts/ci/run-app-host-xcodebuild.sh \
-xctestrun "$CMUX_APP_HOST_XCTESTRUN" \
-destination "platform=macOS" \
-only-testing:cmuxTests/MainWindowZoomPlacementTests \
CMUX_SKIP_ZIG_BUILD=1 \
-test-timeouts-enabled YES \
-default-test-execution-time-allowance 60 \
-maximum-test-execution-time-allowance 60 \
test-without-building 2>&1 | tee "$test_log"
scripts/ci/require_selected_test_execution.sh \
"$test_log" cmuxTests/MainWindowZoomPlacementTests

- name: Run bundled command PATH regression
if: ${{ matrix.shard == fromJSON(env.CMUX_APP_HOST_FOCUSED_REGRESSION_SHARD) }}
run: |
Expand Down Expand Up @@ -1902,13 +1923,15 @@ jobs:
}

run_unit_tests() {
local logical_shard
local logical_shard combined_status=0
for logical_shard in "${LOGICAL_SHARDS[@]}"; do
run_unit_test_batch "$logical_shard" || {
local batch_status=$?
return "$batch_status"
# Keep the other batch visible after a failure, without allowing
# a later successful batch to turn this worker green.
combined_status=$?
}
done
return "$combined_status"
}

# Stream output via tee so CI logs are visible in real time, while still
Expand Down
6 changes: 4 additions & 2 deletions CLI/AgentHookNotificationPolicy.swift
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,6 @@ enum AgentHookNotificationPolicy {
(#"[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}"#, "<email>"),
(#"(?:~|/)[^\s\"']+"#, "<path>"),
(#"\b(?:gh[pousr]_[A-Za-z0-9_]{20,}|AKIA[0-9A-Z]{16})\b"#, "<token>"),
(#"\b(?:sk|rk|sess|token|key|secret|api[_-]?key)[A-Za-z0-9._:-]{8,}\b"#, "<token>"),
(#"(?i)\bBearer\s+[A-Za-z0-9._~+/=-]{12,}"#, "Bearer <token>"),
(#"\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b"#, "<token>"),
(#"(?i)\b(?:authorization|proxy-authorization)\s*:\s*[^\s'\";&|]+(?:\s+[^\s'\";&|]+)*"#, "<credential>:<token>"),
Expand All @@ -435,9 +434,12 @@ enum AgentHookNotificationPolicy {
(#"(?i)--?(?:api[-_]?key|password|secret|token|authorization|cookie)(?:=|\s+)(?:'[^']*'|\"[^\"]*\"|[^\s'\";&|]+)"#, "<credential>=<token>"),
(#"(?i)(?:^|\s)(?:-u|--user)(?:=|\s+)(?:'[^']*'|\"[^\"]*\"|[^\s'\";&|]+)"#, " <credential>"),
(#"(?i)(?:^|\s)(?:--passphrase|--password|--pass|--auth|--credential)(?:=|\s+)(?:'[^']*'|\"[^\"]*\"|[^\s'\";&|]+)"#, " <credential>"),
(#"(?i)(?:^|\s)(?:-a|-p|-pass)(?:=|\s+|(?=[^\s]))(?:'[^']*'|\"[^\"]*\"|[^\s'\";&|]+)"#, " <credential>"),
(#"(?i)(?:^|\s)(?:-pass|-a|-p)(?:=|\s+|(?=[^\s]))(?:'[^']*'|\"[^\"]*\"|[^\s'\";&|]+)"#, " <credential>"),
(#"(?i)\b[A-Za-z_]*(?:api[_-]?key|password|secret|token|authorization|cookie)[A-Za-z0-9_]*\s*=\s*(?:'[^']*'|\"[^\"]*\"|[^\s;&|]+)"#, "<credential>=<token>"),
(#"(?i)\b(?:api[_-]?key|password|secret|token|authorization|cookie)\s*=\s*[^\s;&|]+"#, "<credential>=<token>"),
// Consume credential options and their values before generic token
// matching can replace a token-like option name on its own.
(#"\b(?:sk|rk|sess|token|key|secret|api[_-]?key)[A-Za-z0-9._:-]{8,}\b"#, "<token>"),
(#"\b[A-Za-z0-9_-]{24,}\b"#, "<token>"),
]
return patterns.reduce(boundedValue) { partial, entry in
Expand Down
16 changes: 14 additions & 2 deletions CLI/CMUXCLI+AgentHookDefinitions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -428,8 +428,20 @@ extension CMUXCLI {
// environments, and for a stale socket node left by an exited app: the
// ambient invocation must succeed, otherwise the pinned chain runs.
// https://github.com/manaflow-ai/cmux/issues/5473
let ambientGuard = pinnedHookAmbientDispatchGuard
let ambientInvocation = pinnedHookAmbientInvocation(routedArguments: routedArguments)
let ambientGuard: String
let ambientInvocation: String
if def.name == "grok" {
// Grok validates interpolated CMUX variables as required hook
// environment. Optional lookups preserve ambient-first routing
// when present and allow the pinned fallback when Grok strips them.
let socket = "\"$(printenv CMUX_SOCKET_PATH || true)\""
let executable = "\"$(printenv CMUX_BUNDLED_CLI_PATH || true)\""
ambientGuard = "[ -n \(socket) ] && [ -S \(socket) ] && [ -f \(executable) ] && [ -x \(executable) ]"
ambientInvocation = "\(pinnedHookEnvironmentPrefix(routedArguments: routedArguments))\(executable) --socket \(socket) \(routedArguments)"
} else {
ambientGuard = pinnedHookAmbientDispatchGuard
ambientInvocation = pinnedHookAmbientInvocation(routedArguments: routedArguments)
}
let dispatch: String
if let cliPath = pinnedAgentHookCLIPath() {
let quotedCLIPath = shellSingleQuote(cliPath)
Expand Down
5 changes: 4 additions & 1 deletion CLI/CMUXCLI+SSHConnectionSharing.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ extension CMUXCLI {
func resolvedUserSSHControlOptions(for options: SSHCommandOptions) -> [String]? {
guard let output = resolvedSSHConfigurationOutput(for: options) else { return nil }
return SSHConnectionSharingOptions()
.userConfiguredControlOptions(fromSSHConfigOutput: output)
.userConfiguredControlOptions(
fromSSHConfigOutput: output,
explicitOptions: options.sshOptions
)
}

func resolvedCmuxControlPathOptions(for options: SSHCommandOptions) -> [String] {
Expand Down
8 changes: 6 additions & 2 deletions CLI/CMUXCLI+SemanticNotifications.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,12 @@ extension CMUXCLI {

static func semanticAttentionContext(_ object: [String: Any]?) -> AgentAttentionContext {
func identifier(_ keys: [String]) -> String? {
for key in keys {
if let value = object?[key] as? String, !value.isEmpty { return value }
// Hermes shell hooks keep native causal IDs in `extra`. Prefer
// top-level evidence when both envelopes provide an identity.
for fields in [object, object?["extra"] as? [String: Any]] {
for key in keys {
if let value = fields?[key] as? String, !value.isEmpty { return value }
}
}
return nil
}
Expand Down
20 changes: 15 additions & 5 deletions CLI/CMUXCLI+TmuxCompatStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -225,11 +225,21 @@ extension CMUXCLI {
_ body: (TmuxCompatStoreDirectory) throws -> T
) throws -> T {
let directory = try TmuxCompatStoreDirectory(storeURL: storeURL, createIfMissing: true)
let lockDescriptor = try directory.open(
directory.lockName,
flags: O_CREAT | O_RDWR | O_CLOEXEC | O_NOFOLLOW,
mode: mode_t(S_IRUSR | S_IWUSR)
)
let lockDescriptor: Int32
do {
// Concurrent first-use O_CREAT opens can fail with ENOENT on APFS.
// Elect one creator, then open the stable lock without creation.
lockDescriptor = try directory.open(
directory.lockName,
flags: O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC | O_NOFOLLOW,
mode: mode_t(S_IRUSR | S_IWUSR)
)
} catch let error as POSIXError where error.code == .EEXIST {
lockDescriptor = try directory.open(
directory.lockName,
flags: O_RDWR | O_CLOEXEC | O_NOFOLLOW
)
}
defer { Darwin.close(lockDescriptor) }
guard Darwin.fchmod(lockDescriptor, mode_t(S_IRUSR | S_IWUSR)) == 0 else {
throw POSIXError(POSIXErrorCode(rawValue: errno) ?? .EIO)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,12 @@ extension CmxIrohHostRuntimeTests {
#expect(initialDirectPorts == expectedDirectPorts)
#expect(refreshedDirectPorts == expectedDirectPorts)

let published = await publications.values()
let published = await publications.waitForCount(2)
#expect(published.count == 2)
guard published.count == 2 else {
await runtime.stop()
return
}
#expect(published[0].registration.pathHints.isEmpty)
#expect(published[0].discovered.pathHints.isEmpty)
#expect(published[1].registration.pathHints == [relayHint])
Expand Down Expand Up @@ -215,6 +219,7 @@ private struct HostRuntimeBindingPublication: Equatable, Sendable {

private actor HostRuntimeBindingPublicationRecorder {
private var recorded: [HostRuntimeBindingPublication] = []
private var waiters: [UUID: (minimum: Int, continuation: CheckedContinuation<[HostRuntimeBindingPublication], Never>)] = [:]

func record(
registration: CmxIrohBrokerBinding,
Expand All @@ -229,9 +234,21 @@ private actor HostRuntimeBindingPublicationRecorder {
discovered: discovered
)
)
let ready = waiters.filter { recorded.count >= $0.value.minimum }
for (id, waiter) in ready {
waiters.removeValue(forKey: id)
waiter.continuation.resume(returning: recorded)
}
}

func values() -> [HostRuntimeBindingPublication] { recorded }

func waitForCount(_ minimum: Int) async -> [HostRuntimeBindingPublication] {
if recorded.count >= minimum { return recorded }
return await withCheckedContinuation { continuation in
waiters[UUID()] = (minimum, continuation)
}
}
}

private func registrationPathHints(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,14 @@ public struct SSHConnectionSharingOptions: Sendable {
/// Adds sharing defaults while honoring effective control settings from
/// the user's SSH configuration.
///
/// Explicit caller options retain highest precedence. When the caller did
/// not provide any control option and `ssh -G` reported non-default
/// control settings, those effective values are carried forward instead
/// of installing cmux's socket.
/// Explicit caller options retain highest precedence per key. Independently
/// configured host control settings fill the remaining keys instead of
/// installing cmux's socket.
///
/// - Parameters:
/// - options: Explicit OpenSSH `-o` values.
/// - userConfiguredControlOptions: Effective custom values parsed by
/// ``userConfiguredControlOptions(fromSSHConfigOutput:)``.
/// ``userConfiguredControlOptions(fromSSHConfigOutput:explicitOptions:)``.
/// - Returns: Effective explicit options for native SSH commands.
public func mergingDefaults(
into options: [String],
Expand Down Expand Up @@ -136,6 +135,25 @@ public struct SSHConnectionSharingOptions: Sendable {
/// cmux control options are added.
/// - Returns: Effective custom `-o` values, or `nil` for OpenSSH defaults.
public func userConfiguredControlOptions(fromSSHConfigOutput output: String) -> [String]? {
userConfiguredControlOptions(fromSSHConfigOutput: output, explicitOptions: [])
}

/// Parses resolved host control settings with the explicit caller options
/// that were included in the `ssh -G` invocation.
///
/// Explicit values do not prove host customization: OpenSSH includes them in
/// its output and normalizes `ControlPersist=0` to `yes`. A custom value on
/// another control key still preserves the host's full effective settings,
/// with explicit options retaining precedence when merged.
///
/// - Parameters:
/// - output: Effective configuration reported by OpenSSH.
/// - explicitOptions: Caller-provided `-o` values included in that output.
/// - Returns: Effective custom host control settings, or `nil` for defaults.
public func userConfiguredControlOptions(
fromSSHConfigOutput output: String,
explicitOptions: [String]
) -> [String]? {
var values: [String: String] = [:]
for line in output.split(whereSeparator: \.isNewline) {
let parts = line.split(maxSplits: 1, whereSeparator: \.isWhitespace)
Expand All @@ -151,9 +169,12 @@ public struct SSHConnectionSharingOptions: Sendable {
let controlMaster = values["controlmaster"] ?? "false"
let controlPath = values["controlpath"] ?? "none"
let controlPersist = values["controlpersist"] ?? "no"
let hasCustomValue = !isDisabled(controlMaster)
|| controlPath.lowercased() != "none"
|| !["no", "false", "off", "0"].contains(controlPersist.lowercased())
let resolver = SSHAgentSocketResolver()
let hasCustomValue =
(!resolver.hasOptionKey(explicitOptions, key: "ControlMaster") && !isDisabled(controlMaster))
|| (!resolver.hasOptionKey(explicitOptions, key: "ControlPath") && controlPath.lowercased() != "none")
|| (!resolver.hasOptionKey(explicitOptions, key: "ControlPersist")
&& !["no", "false", "off", "0"].contains(controlPersist.lowercased()))
guard hasCustomValue else { return nil }
return [
"ControlMaster=\(controlMaster)",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2624,12 +2624,12 @@ public struct SSHForegroundAuthenticationRetryPolicy: Sendable {
"cmux_ssh_auth_completion_event_fd=",
"cmux_ssh_auth_completion_ack_fd=",
"cmux_ssh_auth_completion_fds_open=0",
"cmux_ssh_auth_prepare_signal_completion() { cmux_ssh_auth_completion_fds_open=0; if [ -n \"$cmux_ssh_auth_event_token\" ] && [ -p \"$cmux_ssh_auth_term_event_fifo\" ] && [ -p \"$cmux_ssh_auth_term_event_ack_fifo\" ] && exec {cmux_ssh_auth_completion_event_fd}<> \"$cmux_ssh_auth_term_event_fifo\" 2>/dev/null && exec {cmux_ssh_auth_completion_ack_fd}<> \"$cmux_ssh_auth_term_event_ack_fifo\" 2>/dev/null; then cmux_ssh_auth_completion_fds_open=1; else exec {cmux_ssh_auth_completion_event_fd}>&- 2>/dev/null || true; exec {cmux_ssh_auth_completion_ack_fd}>&- 2>/dev/null || true; cmux_ssh_auth_completion_event_fd=; cmux_ssh_auth_completion_ack_fd=; fi; }",
"cmux_ssh_auth_prepare_signal_completion() { cmux_ssh_auth_completion_fds_open=0; if [ -n \"$cmux_ssh_auth_event_token\" ] && [ -p \"$cmux_ssh_auth_term_event_fifo\" ] && [ -p \"$cmux_ssh_auth_term_event_ack_fifo\" ] && exec {cmux_ssh_auth_completion_event_fd}<> \"$cmux_ssh_auth_term_event_fifo\" 2>/dev/null && exec {cmux_ssh_auth_completion_ack_fd}<> \"$cmux_ssh_auth_term_event_ack_fifo\" 2>/dev/null; then cmux_ssh_auth_completion_fds_open=1; else case \"${cmux_ssh_auth_completion_event_fd:-}\" in ''|*[!0-9]*) ;; *) exec {cmux_ssh_auth_completion_event_fd}>&- 2>/dev/null || true ;; esac; case \"${cmux_ssh_auth_completion_ack_fd:-}\" in ''|*[!0-9]*) ;; *) exec {cmux_ssh_auth_completion_ack_fd}>&- 2>/dev/null || true ;; esac; cmux_ssh_auth_completion_event_fd=; cmux_ssh_auth_completion_ack_fd=; fi; }",
// The cleanup helper creates the event FIFOs when cancellation
// begins, after this wrapper has started. Retry the open at signal
// completion so the normal startup race cannot disable the
// completion handshake.
"cmux_ssh_auth_signal_completion() { if [ \"$cmux_ssh_auth_completion_fds_open\" != 1 ]; then cmux_ssh_auth_prepare_signal_completion; fi; if [ \"$cmux_ssh_auth_completion_fds_open\" = 1 ]; then cmux_ssh_auth_marker_cleanup_deferred=1; printf '%s\\n' \"$cmux_ssh_auth_event_token\" >&$cmux_ssh_auth_completion_event_fd 2>/dev/null || true; cmux_ssh_auth_completion_ack=; IFS= read -r -t 2 cmux_ssh_auth_completion_ack <&$cmux_ssh_auth_completion_ack_fd || true; fi; if [ -n \"${cmux_ssh_auth_completion_event_fd:-}\" ]; then exec {cmux_ssh_auth_completion_event_fd}>&- 2>/dev/null || true; fi; if [ -n \"${cmux_ssh_auth_completion_ack_fd:-}\" ]; then exec {cmux_ssh_auth_completion_ack_fd}>&- 2>/dev/null || true; fi; cmux_ssh_auth_completion_event_fd=; cmux_ssh_auth_completion_ack_fd=; cmux_ssh_auth_completion_fds_open=0; }",
"cmux_ssh_auth_signal_completion() { if [ \"$cmux_ssh_auth_completion_fds_open\" != 1 ]; then cmux_ssh_auth_prepare_signal_completion; fi; if [ \"$cmux_ssh_auth_completion_fds_open\" = 1 ]; then cmux_ssh_auth_marker_cleanup_deferred=1; printf '%s\\n' \"$cmux_ssh_auth_event_token\" >&$cmux_ssh_auth_completion_event_fd 2>/dev/null || true; cmux_ssh_auth_completion_ack=; IFS= read -r -t 2 cmux_ssh_auth_completion_ack <&$cmux_ssh_auth_completion_ack_fd || true; fi; case \"${cmux_ssh_auth_completion_event_fd:-}\" in ''|*[!0-9]*) ;; *) exec {cmux_ssh_auth_completion_event_fd}>&- 2>/dev/null || true ;; esac; case \"${cmux_ssh_auth_completion_ack_fd:-}\" in ''|*[!0-9]*) ;; *) exec {cmux_ssh_auth_completion_ack_fd}>&- 2>/dev/null || true ;; esac; cmux_ssh_auth_completion_event_fd=; cmux_ssh_auth_completion_ack_fd=; cmux_ssh_auth_completion_fds_open=0; }",
"cmux_ssh_auth_capture_cleanup() {",
" if [ -n \"${cmux_ssh_auth_classifier_guard_fd:-}\" ]; then",
" exec {cmux_ssh_auth_classifier_guard_fd}>&-",
Expand Down
Loading
Loading