* fix(macos): attach the onboarding CLI install prompt to the window
On an unreleased build, the onboarding CLI page resolved its install target
through NSAlert.runModal() — a detached app-modal panel that is absent from
the app's AX window list and freely covered by system permission dialogs.
Live repro: with two TCC prompts stacked over it, the main thread sat parked
in runModal for 30+ minutes while the page showed an active "Install
OpenClaw" spinner, the close button was disabled, and busyReason claimed an
install was in flight — before the user had chosen anything. A spinner that
means "answer a dialog you cannot see" is a silent-failure trap.
The prompt (both the confirm-stable alert and the channel chooser) is now a
sheet attached to the onboarding window via beginSheetModal, so it stays
z-ordered with the window and AX-visible. The busy state is honest: a new
.choosingTarget phase renders the install row as pending instead of running,
and installingCLI/close-disabled/busyReason only engage after a target is
actually chosen. Non-onboarding callers (checkAndPromptIfNeeded) keep
runModal by passing no window. All alert text and button order unchanged.
* style(macos): wrap sheetPresentationWindow property body
* fix(macos): surface concrete Gateway start failure reason in onboarding
GatewayProcessManager already retains the specific registration/readiness
failure (e.g. "launchd disabled", a launchd enable error, a readiness
timeout) in lastFailureReason, and Settings/menu bar UI already read it.
Onboarding discarded it: LocalGatewayActivation.failed collapses every
cause to the same generic "Retry setup" message, so a missing LaunchAgent
registration is indistinguishable from any other startup failure.
Surface the retained reason in the onboarding status text so the failure
is diagnosable without going through Settings.
* fix(macos): record command-resolution failures in lastFailureReason
GatewayProcessManager set status but not lastFailureReason when
GatewayEnvironment.resolveGatewayCommand() returns no command (missing
runtime/CLI), unlike the launchd-disabled and launchd-enable-error
branches a few lines below. Onboarding's new failure message therefore
rendered the generic text or a stale reason from an earlier attempt
for this failure class. Mirror the sibling branches and record
resolution.status.message.
Also fixes the macos-swift SwiftFormat lint failure: the comment block
directly above gatewayStartFailureMessage needed to be a doc comment
(///), matching the repo's existing convention for declaration-adjacent
comments.
* fix(macos): bind Gateway start failure reason to its activation attempt
LocalGatewayActivation.failed carried no data, so both onboarding call
sites reread the mutable GatewayProcessManager.shared.lastFailureReason
singleton after activateLocalGateway() returned. A later gateway-start
attempt can overwrite that singleton before the caller gets around to
reading it, so a stale wait could surface a newer attempt's reason (or
vice versa) attributed to the wrong onboarding attempt.
Widen LocalGatewayActivation.failed to carry reason: String?, captured
inside activateLocalGateway() the instant waitUntilReady() resolves to
false, and have both onboarding call sites map that bound value instead
of rereading the singleton. CLIInstallPrompter's two `!= .failed`
comparisons become `if case .failed = activation` pattern matches since
`.failed` is no longer a payload-free value; its existing `case .failed:`
message switch is unaffected, since bare-case patterns still match
regardless of associated data.
* fix(macos): satisfy SwiftFormat lint on CLIInstaller.swift
Converts the LocalGatewayActivation.failed declaration comment to a
doc comment and wraps activateLocalGateway's closing signature per
config/swiftformat, matching the same docComments convention already
applied elsewhere in this PR. No behavior change.
Fresh Dev installs now preflight disk space and stream honest stages, while Codex activation probes the refreshed request-scoped registry.
Closes#120779Closes#120780
* fix(mac): prerelease-exact launch resolution and policy-aware update ownership
* fix(ui): keep update affordance when nav is hidden and fall back on native decline
* chore(i18n): sync native inventory
* feat: sidebar update card (web + macOS) with app-first mac update flow and Sparkle beta track
Squashed from claude/update-notification-display-c6cfb9 after semantic merge
with #104178 (channel-aware CLI installs). See PR #104171 body for details.
* chore(i18n): resync generated inventories after rebase
* chore(i18n): resync locale metadata after rebase