Skip to content

Improve macOS onboarding UX and gateway setup#47263

Closed
ImLukeF wants to merge 4 commits into
mainfrom
imlukef/onboarding-ux-improvements
Closed

Improve macOS onboarding UX and gateway setup#47263
ImLukeF wants to merge 4 commits into
mainfrom
imlukef/onboarding-ux-improvements

Conversation

@ImLukeF

@ImLukeF ImLukeF commented Mar 15, 2026

Copy link
Copy Markdown
Contributor

Summary

  • improve macOS onboarding flow so local installs reach the CLI step and don’t race the gateway/node connection paths
  • refresh the onboarding wizard layout and provider selection UI so the primary action stays visible and provider copy/defaults are clearer
  • harden local CLI install behavior and gateway readiness handling for debug/dev builds

Testing

  • pnpm check
  • pnpm protocol:check
  • pnpm canvas:a2ui:bundle && pnpm exec vitest run --config vitest.unit.config.ts
  • OPENCLAW_TEST_WORKERS=1 OPENCLAW_TEST_SHARDS=6 OPENCLAW_TEST_SHARD_INDEX=6 pnpm test
  • swift test --package-path apps/shared/OpenClawKit --filter ChatViewModelTests
  • swift test --package-path apps/macos --filter WebChatSwiftUISmokeTests

@openclaw-barnacle openclaw-barnacle Bot added app: macos App: macos commands Command implementations size: M maintainer Maintainer-authored PR labels Mar 15, 2026
@ImLukeF ImLukeF self-assigned this Mar 15, 2026
@greptile-apps

greptile-apps Bot commented Mar 15, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR improves the macOS onboarding UX for local installs by inserting a CLI installation step (with Xcode CLT preflight) before the wizard, adding an onboarding gate to the node-mode connection loop, and refreshing the wizard's provider-selection layout so the primary action always stays visible. The TypeScript side updates provider hint copy and bumps default model strings.

Key changes and findings:

  • Logic regression (OnboardingWizard.swift): shouldSkipWizard now only checks for a wizard config key. The previously checked gateway auth fields (mode/token/password) are no longer considered. Users who configured auth manually without going through the wizard (no wizard key) will be unexpectedly shown the wizard again after updating.
  • Resource concern (GatewayProcessManager.swift): probeLocalGatewayHealth creates a new GatewayChannelActor on every call and disposes it asynchronously. In the 300–400 ms polling loops it can accumulate many concurrent channels before cleanup completes.
  • The CLT preflight flow in CLIInstaller.swift, the canAdvance gate on the CLI page, and the node-mode onboarding check are all implemented correctly.
  • GatewayEnvironment.expectedGatewayVersionString is cleanly extracted into a testable overload with a correct debug bypass.

Confidence Score: 3/5

  • Merging is risky for users who have existing gateway auth config without a wizard key — they will be re-shown the wizard unexpectedly.
  • The onboarding UX improvements and CLT preflight logic are solid. However, the removal of the gateway-auth fallback checks in shouldSkipWizard introduces a behavioral regression for any existing users on the legacy auth-only config format, which warrants investigation before shipping.
  • apps/macos/Sources/OpenClaw/OnboardingWizard.swift (shouldSkipWizard regression) and apps/macos/Sources/OpenClaw/GatewayProcessManager.swift (per-probe channel allocation)

Comments Outside Diff (1)

  1. apps/macos/Sources/OpenClaw/GatewayProcessManager.swift, line 219-231 (link)

    New channel allocated per probe in tight polling loops

    probeLocalGatewayHealth allocates a fresh GatewayChannelActor on every call. This is invoked every ~300–400 ms in both the waitForGatewayReady loop and the launchd-start loop. The cleanup Task { await channel.shutdown() } runs asynchronously, so up to 15–20 channels could be alive simultaneously during a 6-second wait window.

    If GatewayChannelActor holds a URL session or a WebSocket connection, this could exhaust OS connection resources under slow-start conditions. Consider caching a short-lived probe channel for the duration of each wait loop, or re-using a single channel instance created once per probeLocalGatewayHealth call-site rather than creating one per invocation.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: apps/macos/Sources/OpenClaw/GatewayProcessManager.swift
    Line: 219-231
    
    Comment:
    **New channel allocated per probe in tight polling loops**
    
    `probeLocalGatewayHealth` allocates a fresh `GatewayChannelActor` on every call. This is invoked every ~300–400 ms in both the `waitForGatewayReady` loop and the launchd-start loop. The cleanup `Task { await channel.shutdown() }` runs asynchronously, so up to 15–20 channels could be alive simultaneously during a 6-second wait window.
    
    If `GatewayChannelActor` holds a URL session or a WebSocket connection, this could exhaust OS connection resources under slow-start conditions. Consider caching a short-lived probe channel for the duration of each wait loop, or re-using a single channel instance created once per `probeLocalGatewayHealth` call-site rather than creating one per invocation.
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: apps/macos/Sources/OpenClaw/OnboardingWizard.swift
Line: 199-204

Comment:
**Existing users may be re-shown the wizard after update**

The previous `shouldSkipWizard` also returned `true` when `gateway.auth.mode`, `gateway.auth.token`, or `gateway.auth.password` were set in the config. With those checks removed, any user who configured gateway auth manually (without the wizard producing a `wizard` key) will now encounter the wizard when they next open the app — even though they are already fully configured.

This is a meaningful regression if there is any population of users on the legacy auth-only config format. Consider either keeping the fallback gateway-auth checks in place, or adding a one-time migration that writes a sentinel `wizard` key for users whose config already contains auth credentials.

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: apps/macos/Sources/OpenClaw/GatewayProcessManager.swift
Line: 219-231

Comment:
**New channel allocated per probe in tight polling loops**

`probeLocalGatewayHealth` allocates a fresh `GatewayChannelActor` on every call. This is invoked every ~300–400 ms in both the `waitForGatewayReady` loop and the launchd-start loop. The cleanup `Task { await channel.shutdown() }` runs asynchronously, so up to 15–20 channels could be alive simultaneously during a 6-second wait window.

If `GatewayChannelActor` holds a URL session or a WebSocket connection, this could exhaust OS connection resources under slow-start conditions. Consider caching a short-lived probe channel for the duration of each wait loop, or re-using a single channel instance created once per `probeLocalGatewayHealth` call-site rather than creating one per invocation.

How can I resolve this? If you propose a fix, please make it concise.

Last reviewed commit: 01a6e0d

Comment on lines 199 to 204
static func shouldSkipWizard(root: [String: Any]) -> Bool {
if let wizard = root["wizard"] as? [String: Any], !wizard.isEmpty {
return true
}
if let gateway = root["gateway"] as? [String: Any],
let auth = gateway["auth"] as? [String: Any]
{
if let mode = auth["mode"] as? String,
!mode.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
{
return true
}
if let token = auth["token"] as? String,
!token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
{
return true
}
if let password = auth["password"] as? String,
!password.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
{
return true
}
}
return false
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Existing users may be re-shown the wizard after update

The previous shouldSkipWizard also returned true when gateway.auth.mode, gateway.auth.token, or gateway.auth.password were set in the config. With those checks removed, any user who configured gateway auth manually (without the wizard producing a wizard key) will now encounter the wizard when they next open the app — even though they are already fully configured.

This is a meaningful regression if there is any population of users on the legacy auth-only config format. Consider either keeping the fallback gateway-auth checks in place, or adding a one-time migration that writes a sentinel wizard key for users whose config already contains auth credentials.

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/macos/Sources/OpenClaw/OnboardingWizard.swift
Line: 199-204

Comment:
**Existing users may be re-shown the wizard after update**

The previous `shouldSkipWizard` also returned `true` when `gateway.auth.mode`, `gateway.auth.token`, or `gateway.auth.password` were set in the config. With those checks removed, any user who configured gateway auth manually (without the wizard producing a `wizard` key) will now encounter the wizard when they next open the app — even though they are already fully configured.

This is a meaningful regression if there is any population of users on the legacy auth-only config format. Consider either keeping the fallback gateway-auth checks in place, or adding a one-time migration that writes a sentinel `wizard` key for users whose config already contains auth credentials.

How can I resolve this? If you propose a fix, please make it concise.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 01a6e0da81

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


if (params.setDefaultModel) {
const model = "github-copilot/gpt-4o";
const model = "github-copilot/gpt-5.4";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep Copilot default on a resolvable model

This now writes github-copilot/gpt-5.4 as the default model, but the forward-compat path only synthesizes gpt-5.4 for openai-codex (see src/agents/model-forward-compat.ts where CODEX_GPT54_ELIGIBLE_PROVIDERS excludes github-copilot), so Copilot onboarding can end up with a default model the resolver cannot provide unless that exact model is already present in the live catalog. In environments where Copilot does not expose gpt-5.4, users will immediately hit unknown-model failures after auth setup.

Useful? React with 👍 / 👎.

if !self.desiredActive { return false }
do {
_ = try await self.connection.requestRaw(method: .health, timeoutMs: 1500)
_ = try await self.probeLocalGatewayHealth(timeoutMs: 1500)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve injected connection path for health probes

Switching readiness checks to probeLocalGatewayHealth bypasses self.connection, so the existing DEBUG injection hook (setTestingConnection) no longer affects waitForGatewayReady and related attach/start paths. That breaks deterministic testing/mocking of gateway readiness (for example apps/macos/Tests/OpenClawIPCTests/GatewayProcessManagerTests.swift now cannot drive this path with its fake GatewayConnection) and makes these flows depend on a real local socket even under tests.

Useful? React with 👍 / 👎.

@aisle-research-bot

aisle-research-bot Bot commented Mar 18, 2026

Copy link
Copy Markdown

🔒 Aisle Security Analysis

We found 3 potential security issue(s) in this PR:

# Severity Title
1 🟠 High GatewayProcessManager health probe can connect to non-loopback host and leak gateway credentials
2 🟡 Medium Unpinned/unchecked CLI install for .debug builds via expectedGatewayVersionString() returning nil
3 🔵 Low Onboarding security acknowledgement can be bypassed via page navigation dots

1. 🟠 GatewayProcessManager health probe can connect to non-loopback host and leak gateway credentials

Property Value
Severity High
CWE CWE-918
Location apps/macos/Sources/OpenClaw/GatewayProcessManager.swift:414-426

Description

GatewayProcessManager.probeLocalGatewayHealth() creates a new GatewayChannelActor using GatewayEndpointStore.localConfig() and passes token/password. Despite the method name, localConfig() is not guaranteed to be loopback-only:

  • GatewayEndpointStore.localConfig() derives the host from user-configurable config/env (gateway.bind, OPENCLAW_GATEWAY_BIND) and may return:
    • gateway.bind = custom -> gateway.customBindHost (arbitrary hostname/IP)
    • gateway.bind = tailnet -> a Tailscale IP
  • GatewayChannelActor sends auth in the initial websocket connect frame (token/password) during request(). If the resolved host is not loopback, those secrets are transmitted to a potentially remote endpoint.
  • localConfig() also permits ws:// (default) when TLS is disabled, so credentials may be sent unencrypted over the network when probing a non-loopback address.

This behavior is newly exercised in the local gateway process manager polling loops (attach/wait), so it can happen automatically and repeatedly during startup/health checks.

Vulnerable code:

let config = GatewayEndpointStore.localConfig()
let channel = GatewayChannelActor(
    url: config.url,
    token: config.token,
    password: config.password)
return try await channel.request(method: GatewayConnection.Method.health.rawValue, params: nil, timeoutMs: timeoutMs)

Recommendation

Constrain the "local" health probe to a local-only endpoint and avoid transmitting secrets to non-loopback addresses.

Recommended hardening options (pick one depending on intended feature set):

  1. Force loopback for process-manager probes (safest):
private func probeLocalGatewayHealth(timeoutMs: Double) async throws -> Data {
    let port = GatewayEnvironment.gatewayPort()
    let scheme = "ws" // or "wss" if you require TLS
    let url = URL(string: "\(scheme)://127.0.0.1:\(port)")!

    let channel = GatewayChannelActor(url: url, token: nil, password: nil)
    defer { Task.detached { await channel.shutdown() } }

    return try await channel.request(method: GatewayConnection.Method.health.rawValue,
                                    params: nil,
                                    timeoutMs: timeoutMs)
}

If the gateway requires auth even for health, consider adding a dedicated unauthenticated health path on the gateway, or restrict auth usage to loopback only.

  1. If you must support non-loopback binds, validate before sending secrets:
  • Reject/ignore gateway.customBindHost unless it matches loopback or a verified local interface address.
  • Require wss (TLS) when host is not loopback.

Also consider using Task.detached for shutdown to avoid cancellation preventing cleanup.


2. 🟡 Unpinned/unchecked CLI install for .debug builds via expectedGatewayVersionString() returning nil

Property Value
Severity Medium
CWE CWE-494
Location apps/macos/Sources/OpenClaw/GatewayEnvironment.swift:98-103

Description

GatewayEnvironment.expectedGatewayVersionString(bundleVersion:bundleIdentifier:) now returns nil when the app’s bundle identifier ends with .debug.

Downstream call sites treat nil as a signal to install "latest":

  • CLIInstaller.install():
    • Uses GatewayEnvironment.expectedGatewayVersionString() ?? "latest"
    • Executes a remote install script via curl | bash
  • OnboardingView.devLinkCommand shows npm install -g openclaw@​latest

This creates a supply-chain exposure for debug builds:

  • The installed CLI/gateway version becomes un-pinned (moves to whatever latest resolves to at install time).
  • The macOS app executes a network-fetched shell script without an integrity check.
  • If openclaw.bot (or its DNS/TLS termination), the install script, or the latest package distribution channel is compromised, an attacker can achieve arbitrary code execution under the current user.

Vulnerable flow (key parts):

​// GatewayEnvironment.swift
if let bundleIdentifier,
   bundleIdentifier.trimmingCharacters(in: .whitespacesAndNewlines).hasSuffix(".debug")
{
    return nil // triggers downstream fallback to "latest"
}

​// CLIInstaller.swift
let expected = GatewayEnvironment.expectedGatewayVersionString() ?? "latest"
curl -fsSL https://openclaw.bot/install-cli.sh | bash -s -- ... --version \(expected)

While this is gated on .debug bundle identifiers, debug builds are often used by developers and testers on real machines; this change increases the chance of executing an unpinned remote installer in those environments.

Recommendation

Avoid installing/executing unpinned code for debug builds, and add integrity verification for any network-delivered installer.

Recommended options (best → better):

  1. Avoid curl | bash entirely: ship a notarized/pinned installer with the app (or embed the CLI binary) and verify its signature.

  2. If you must download:

    • Download a versioned artifact (not latest) and verify a cryptographic signature (preferred) or a hard-coded SHA-256 that is shipped in the app.
    • Only then execute/install.

Example approach (hash verification sketch):

​// Pseudocode
let url = URL(string: "https://openclaw.bot/releases/openclaw-\(version).tar.gz")!
let data = try await URLSession.shared.data(from: url).0
let actual = sha256Hex(data)
guard actual == expectedSha256 else { throw InstallError.integrityFailed }
​// proceed to unpack/install
  1. If the .debug behavior is only for local development, require an explicit opt-in flag (e.g., an env var like OPENCLAW_ALLOW_LATEST=1) rather than implicitly selecting latest based on bundle identifier.

3. 🔵 Onboarding security acknowledgement can be bypassed via page navigation dots

Property Value
Severity Low
CWE CWE-284
Location apps/macos/Sources/OpenClaw/OnboardingView+Layout.swift:111-125

Description

The new onboarding “security notice acknowledged” gate only blocks the Next button (canAdvance), but it does not prevent users from navigating away from page 0 using the page indicator dots.

As a result, a user can:

  • Start on page 0 with securityNoticeAcknowledged == false
  • Click a page dot to jump to later pages (connection/CLI/etc.)
  • Complete onboarding and trigger finish(), which unconditionally sets onboardingSecurityAcknowledgedKey = true

This makes the acknowledgement requirement trivially bypassable in-app and undermines it as a security/consent control.

Vulnerable code (page dot navigation ignores securityNoticeAcknowledged):

Button {
    withAnimation { self.currentPage = index }
} label: {
    Circle()
        .fill(index == self.currentPage ? Color.accentColor : Color.gray.opacity(0.3))
        .frame(width: 8, height: 8)
}
.disabled(isLocked)

Recommendation

Treat the acknowledgement as a navigation invariant, not just a “Next button” state.

Option A (minimal UI fix): disable non-zero page dots until acknowledged when currently on page 0.

let blockedBySecurityNotice = !self.securityNoticeAcknowledged && self.currentPage == 0 && index > 0

Button {
    withAnimation { self.currentPage = index }
} label: {
    ​// ...
}
.disabled(isLocked || blockedBySecurityNotice)
.opacity((isLocked || blockedBySecurityNotice) ? 0.3 : 1)

Option B (stronger): centralize page transitions through a function that enforces the rule, and use it for all navigation paths (dots, next/back, programmatic changes).

Also consider not setting onboardingSecurityAcknowledgedKey automatically in finish() unless the user explicitly acknowledged it, if the acknowledgement is meant to be meaningful/compliance-relevant.


Analyzed PR: #47263 at commit 5f2f9a0

Last updated on: 2026-03-18T07:01:38Z

@openclaw openclaw deleted a comment Mar 18, 2026
@ImLukeF
ImLukeF force-pushed the imlukef/onboarding-ux-improvements branch from f135473 to fbbca10 Compare March 18, 2026 00:34

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fbbca10c83

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +721 to +725
Text("Prefer to install manually?")
.font(.footnote)
.foregroundStyle(.secondary)
Button(self.copied ? "Copied" : "Copy install command") {
self.copyToPasteboard(self.devLinkCommand)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Add a recheck path for manual CLI installs

If users follow the new “Prefer to install manually?” path here, onboarding has no way to notice success while they stay on this page: Next is disabled until cliInstalled becomes true (apps/macos/Sources/OpenClaw/Onboarding.swift:151-154), but the only refreshes now happen on page entry or after installCLI() runs (apps/macos/Sources/OpenClaw/OnboardingView+Monitoring.swift:42-49, 63-79). Running the copied command in Terminal leaves the page stuck with Next disabled until the user backs out and re-enters the page or restarts onboarding.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5f2f9a05a3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +62 to 63
UserDefaults.standard.set(true, forKey: onboardingSecurityAcknowledgedKey)
UserDefaults.standard.set(true, forKey: "openclaw.onboardingSeen")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Require security acknowledgement before persisting completion

This now records openclaw.onboardingSecurityAcknowledged unconditionally when finish() runs. The new warning only blocks the Next button on page 0, but the progress dots in OnboardingView.navigationBar are still clickable, so a first-run user can jump straight to a later page (for example the final “All set” page) and finish onboarding without ever ticking the acknowledgement checkbox. That makes the new security gate ineffective for anyone who navigates with the dots.

Useful? React with 👍 / 👎.

Comment on lines +145 to +147
// Preserve runtime connectivity for existing local installs when a newer
// app build refreshes onboarding copy or flow.
return OnboardingWizardModel.hasExistingLocalSetup(root: root)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve env-backed local auth when deciding node-mode startup

This fallback now depends entirely on OnboardingWizardModel.hasExistingLocalSetup(root:), which only inspects openclaw.json. However, the macOS app already treats OPENCLAW_GATEWAY_TOKEN / OPENCLAW_GATEWAY_PASSWORD and the saved launchd snapshot as valid local auth sources in GatewayEndpointStore.resolveGatewayToken/Password. On an upgraded local install that keeps its gateway auth in the environment or service plist, shouldConnectNodeMode() will now return false here and run() will disconnect node mode until the user reruns onboarding, even though the local gateway is still configured.

Useful? React with 👍 / 👎.

dustin-olenslager pushed a commit to dustin-olenslager/ironclaw-supreme that referenced this pull request Mar 24, 2026
dustin-olenslager pushed a commit to dustin-olenslager/ironclaw-supreme that referenced this pull request Mar 24, 2026
@clawsweeper clawsweeper Bot added the rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. label May 19, 2026
@clawsweeper

clawsweeper Bot commented May 19, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed July 5, 2026, 9:35 AM ET / 13:35 UTC.

Summary
This PR changes macOS onboarding by adding a CLI/preflight step, a security acknowledgement, gateway readiness probing changes, a node-mode onboarding gate, provider/layout copy updates, and focused Swift tests.

PR surface: Source 0, Other +421. Total +421 across 17 files.

Reproducibility: yes. for the review findings: source inspection of the PR head shows the credentialed localConfig() probe, the page-dot acknowledgement bypass, and the env/launchd auth upgrade gap. I did not run a live macOS UI reproduction in this read-only review.

Review metrics: 2 noteworthy metrics.

  • Persisted onboarding state: 1 UserDefaults key added. The new acknowledgement key changes first-run completion semantics and must not be persistable through a bypass.
  • Config/default-sensitive behavior: 1 debug version fallback changed, 1 health probe endpoint source changed. The PR changes installer version selection and the process-manager endpoint used for authenticated startup checks.

Stored data model
Persistent data-model change detected: serialized state: apps/macos/Tests/OpenClawIPCTests/OnboardingWizardModelTests.swift. Confirm migration or upgrade compatibility proof before merge.

Merge readiness
Overall: 🧂 unranked krab
Proof: 🧂 unranked krab
Patch quality: 🧂 unranked krab
Result: blocked until real behavior proof from a real setup is added.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

Proof guidance:

  • [P1] Needs real behavior proof before merge: The PR body lists test commands but no after-fix live macOS run, screenshot, recording, terminal output, linked artifact, or redacted logs; the real-behavior proof checks are failing, so contributor action is still required before merge. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Proof path suggestion
A native macOS onboarding recording would materially help review once the branch is rebased and the security gates are fixed. Mantis is currently scoped to Telegram, Discord, and web UI chat proof, so it is not the right proof path for this surface.
Use maintainer screenshot/manual proof, browser or Playwright proof, Crabbox where appropriate, or normal local artifact proof instead.

Risk before merge

  • [P1] Merging this stale branch could regress current main's newer macOS onboarding flow from feat(macos): install and run the local Gateway automatically #99767 and feat(crestodian): conversational agent-loop onboarding across CLI, web install, and macOS app #99935 unless it is rebased and narrowed first.
  • [P1] The health-probe change can send Gateway token/password credentials to a custom or tailnet endpoint resolved by localConfig(), including over ws:// when TLS is disabled.
  • [P1] The new acknowledgement gate is bypassable through page dots and is then persisted by finish(), so it does not reliably protect the intended first-run consent step.
  • [P1] The node-mode onboarding gate only checks openclaw.json, while current endpoint resolution accepts environment and launchd-snapshot auth, so some upgraded local installs can be disconnected until onboarding is rerun.
  • [P1] The PR body lists tests but no after-fix real macOS run, screenshot, recording, logs, or live validation transcript; the real-behavior proof checks are failing.

Maintainer options:

  1. Close after maintainer confirmation (recommended)
    Treat the merged macOS setup work as canonical and close this stale, proof-missing branch instead of repairing it in place.
  2. Require a rebased security pass
    Before any merge, rebase onto current main and remove the credentialed non-loopback probe, preserve env/launchd auth upgrades, and lock all acknowledgement navigation paths.
  3. Cherry-pick only narrow UI value
    If maintainers want any remaining copy/layout improvements, land them in a fresh narrow PR with real macOS onboarding proof rather than merging this branch wholesale.

Next step before merge

  • [P1] Protected label, current-main supersession, missing real proof, and security/auth compatibility findings make this a maintainer close/rebase decision rather than a safe automated repair lane.

Maintainer decision needed

  • Question: Should maintainers close this stale macOS onboarding PR as superseded by feat(macos): install and run the local Gateway automatically #99767 and feat(crestodian): conversational agent-loop onboarding across CLI, web install, and macOS app #99935, or sponsor a narrow rebase/cherry-pick of any remaining UI improvements?
  • Rationale: The protected maintainer label blocks automated cleanup, and the branch now intersects security, auth-provider, and current onboarding product direction decisions that should not be resolved by repair automation.
  • Likely owner: steipete — He owns the recent merged macOS onboarding setup direction that most directly supersedes this branch.
  • Options:
    • Close as superseded (recommended): Close this PR after maintainer confirmation and route any remaining short-screen, remote trust, or AI-access checks to the newer narrower open items.
    • Rebase and narrow: Ask for a fresh branch on current main that keeps only still-needed UI work and fixes the credentialed probe, acknowledgement bypass, and auth-upgrade behavior before review.
    • Keep for design discussion: Leave this PR open only as a historical reference while the remaining macOS remote Gateway direction is handled in [Feature]: Align on macOS remote Gateway UX before broader PRs #90665.

Security
Needs attention: Security review needs attention because the PR adds a credentialed non-loopback probe path, a bypassable acknowledgement control, and a debug-build path that can fall back to an unpinned installer target.

Review findings

  • [P1] Keep local health probes on loopback — apps/macos/Sources/OpenClaw/GatewayProcessManager.swift:415-419
  • [P1] Block page dots behind the acknowledgement — apps/macos/Sources/OpenClaw/OnboardingView+Layout.swift:115-123
  • [P1] Preserve env and launchd auth in the onboarding gate — apps/macos/Sources/OpenClaw/NodeMode/MacNodeModeCoordinator.swift:145-147
Review details

Best possible solution:

Close this PR as superseded by #99767.

Do we have a high-confidence way to reproduce the issue?

Yes for the review findings: source inspection of the PR head shows the credentialed localConfig() probe, the page-dot acknowledgement bypass, and the env/launchd auth upgrade gap. I did not run a live macOS UI reproduction in this read-only review.

Is this the best way to solve the issue?

No. The PR is a plausible old UX direction, but the best current solution is the newer main onboarding path plus narrow rebased fixes for any remaining gaps, not merging this stale branch wholesale.

Full review comments:

  • [P1] Keep local health probes on loopback — apps/macos/Sources/OpenClaw/GatewayProcessManager.swift:415-419
    localConfig() is not loopback-only: current source resolves gateway.bind=tailnet or gateway.bind=custom to tailnet/custom hosts and also returns token/password. This new process-manager probe passes those credentials into a fresh channel during startup polling, so local health checks can send Gateway auth to a non-loopback ws:// endpoint. Force this probe to loopback or validate/TLS-gate the endpoint before attaching credentials.
    Confidence: 0.9
  • [P1] Block page dots behind the acknowledgement — apps/macos/Sources/OpenClaw/OnboardingView+Layout.swift:115-123
    The new security acknowledgement only disables Next; the page dots still call currentPage = index with no security lock, and finish() then writes the acknowledgement key unconditionally. A first-run user can jump past page 0 and complete onboarding without checking the box, so all navigation paths need to enforce the same gate.
    Confidence: 0.87
  • [P1] Preserve env and launchd auth in the onboarding gate — apps/macos/Sources/OpenClaw/NodeMode/MacNodeModeCoordinator.swift:145-147
    This fallback decides whether node mode may connect by calling hasExistingLocalSetup(root:), which only inspects openclaw.json. Current endpoint resolution also accepts OPENCLAW_GATEWAY_TOKEN, OPENCLAW_GATEWAY_PASSWORD, and launchd-snapshot credentials, so upgraded local installs using those supported auth sources can be disconnected until they rerun onboarding.
    Confidence: 0.82

Overall correctness: patch is incorrect
Overall confidence: 0.9

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against f9e194e4a122.

Label changes

Label justifications:

  • P2: This is a normal-priority macOS onboarding improvement PR with important merge blockers but no evidence of an emergency current-main outage.
  • merge-risk: 🚨 compatibility: The branch changes macOS onboarding completion, CLI install flow, and node-mode startup gating in ways that can affect upgraded users.
  • merge-risk: 🚨 auth-provider: The node-mode gate can ignore env/launchd-backed local Gateway auth even though current endpoint resolution accepts those credentials.
  • merge-risk: 🚨 security-boundary: The branch adds a credentialed health probe path and a bypassable security acknowledgement control.
  • rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🧂 unranked krab and patch quality is 🧂 unranked krab.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The PR body lists test commands but no after-fix live macOS run, screenshot, recording, terminal output, linked artifact, or redacted logs; the real-behavior proof checks are failing, so contributor action is still required before merge. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Evidence reviewed

PR surface:

Source 0, Other +421. Total +421 across 17 files.

View PR surface stats
Area Files Added Removed Net
Source 1 1 1 0
Tests 0 0 0 0
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 16 498 77 +421
Total 17 499 78 +421

Security concerns:

  • [high] Credentialed health probe can target non-loopback hosts — apps/macos/Sources/OpenClaw/GatewayProcessManager.swift:415
    The PR's probeLocalGatewayHealth() builds a channel from GatewayEndpointStore.localConfig() and passes token/password; that resolver may produce tailnet or custom hosts and defaults to ws:// when TLS is disabled.
    Confidence: 0.9
  • [medium] Acknowledgement can be bypassed and persisted — apps/macos/Sources/OpenClaw/OnboardingView+Layout.swift:115
    Page-dot navigation can skip the page-0 checkbox while finish() persists the acknowledgement key, weakening the intended consent boundary.
    Confidence: 0.87
  • [medium] Debug builds can install an unpinned latest target — apps/macos/Sources/OpenClaw/GatewayEnvironment.swift:102
    The new .debug bundle handling returns nil, and the branch's installer path treats that as latest, increasing supply-chain exposure for real debug/test machines.
    Confidence: 0.76

What I checked:

  • linked superseding PR: feat(macos): install and run the local Gateway automatically #99767 (feat(macos): install and run the local Gateway automatically) is merged at 2026-07-04T05:09:57Z.
  • cluster evidence: the durable review links that PR in the work cluster or recommended risk path.
  • no human follow-up: live comments and timeline hydrated by apply contain no non-automation activity after the ClawSweeper review.

Likely related people:

  • steipete: Recent maintainer-led work owns the current macOS onboarding direction, including automatic local Gateway setup and the Crestodian onboarding re-sync that now overlap this PR. (role: recent area contributor; confidence: high; commits: 6a7b62889e8c, 07bf384a8b3f, 92fb0caf35ab; files: apps/macos/Sources/OpenClaw/Onboarding.swift, apps/macos/Sources/OpenClaw/OnboardingView+Layout.swift, apps/macos/Sources/OpenClaw/GatewayProcessManager.swift)
  • ngutman: Merged macOS onboarding remote-auth and gateway TLS repair work touches the same endpoint/auth surfaces implicated by this PR's auth-provider and security risks. (role: adjacent auth and remote-gateway contributor; confidence: medium; commits: 144c1b802bf6, 3d3e8fe78c91, eecd758e3992; files: apps/macos/Sources/OpenClaw/Onboarding.swift, apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift, apps/macos/Sources/OpenClaw/GatewayEndpointStore.swift)
  • BunsDev: Recent direct Gateway TLS pinning work is adjacent to the remote/local endpoint trust boundary that this PR's health-probe change affects. (role: adjacent security contributor; confidence: medium; commits: 6a41a5421265; files: apps/macos/Sources/OpenClaw/NodeMode/MacNodeModeCoordinator.swift, apps/macos/Tests/OpenClawIPCTests/GatewayEndpointStoreTests.swift)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (1 earlier review cycle)
  • reviewed 2026-07-05T12:22:23.671Z sha 5f2f9a0 :: needs real behavior proof before merge. :: [P1] Keep local health probes on loopback | [P1] Block page dots behind the acknowledgement | [P1] Preserve env and launchd auth in the onboarding gate

@clawsweeper

clawsweeper Bot commented May 20, 2026

Copy link
Copy Markdown
Contributor

ClawSweeper PR egg

🎁 Pass real behavior proof to wake the egg and unlock a hatchable treat.

Where did the egg go?
  • The egg game starts only after the PR passes the real-behavior proof check.
  • Before that, no creature or rarity is rolled. The treat waits for real proof.
  • This is still just collectible flavor: proof affects review readiness, not creature quality.

@clawsweeper clawsweeper Bot removed the rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. label May 22, 2026
@clawsweeper clawsweeper Bot added status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 auth-provider 🚨 May break OAuth, tokens, provider routing, model choice, or credentials. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. labels May 22, 2026
@clawsweeper clawsweeper Bot added rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. labels Jun 11, 2026
@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jun 25, 2026
@steipete

steipete commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Thanks @ImLukeF. Closing this stale implementation branch while preserving #90665 for the remaining macOS onboarding work. The useful current-main direction has since moved through #99767, #99935, and #102677; this head is conflicting, lacks current proof, and still has unresolved authentication/security findings. Any remaining gap should be a focused patch on current main rather than a conflict resolution of this branch.

@steipete steipete closed this Jul 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app: macos App: macos commands Command implementations maintainer Maintainer-authored PR merge-risk: 🚨 auth-provider 🚨 May break OAuth, tokens, provider routing, model choice, or credentials. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. P2 Normal backlog priority with limited blast radius. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. size: L status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants