Preserve existing gateway.auth and unrelated config keys during macOS app fallback writes, while requiring explicit opt-in for auth mutation paths.\n\nValidation:\n- swift test --package-path apps/macos --filter OpenClawIPCTests.OpenClawConfigFileTests\n- swift test --package-path apps/macos --filter OpenClawIPCTests.ConfigStoreTests\n- node scripts/check-changed.mjs CHANGELOG.md apps/macos/Sources/OpenClaw/ConfigStore.swift apps/macos/Sources/OpenClaw/OpenClawConfigFile.swift apps/macos/Sources/OpenClaw/TailscaleIntegrationSection.swift apps/macos/Tests/OpenClawIPCTests/OpenClawConfigFileTests.swift\n\nCloses #75631.
Replaces JavaScriptCore catalog evaluation with a bounded fail-closed object-literal parser for the generated macOS model catalog.\n\nValidation: macos-node, macos-swift, security-fast, security-scm-fast, security-dependency-audit, workflow sanity checks passed on PR #73112.
Fixes#68160.
Drops stale optionality from the hello-ok auth schema and keeps generated Swift models, macOS fixtures, browser client types, protocol docs, and merged-base test boundaries aligned.
Keep WhatsApp QR login state synced across gateway, macOS, and UI wait flows.
- Preserve the latest QR data URL/version while login polling rotates codes.
- Keep the wait-result protocol bounded to current QR metadata.
- Stabilize QR rendering and media fixture coverage after rebasing on main.
Validation:
- pnpm test extensions/whatsapp/src/login-qr.test.ts extensions/whatsapp/src/media.test.ts extensions/whatsapp/src/agent-tools-login.test.ts src/gateway/protocol/channels.schema.test.ts src/gateway/server-methods/web.start.test.ts ui/src/ui/controllers/channels.test.ts
- pnpm test:extension whatsapp
- cd apps/macos && swift test --filter ChannelsSettingsSmokeTests
- GitHub PR checks: 62 success, 5 skipped
* fix(exec-approvals): escape control characters in display sanitizers
* docs(changelog): add exec approval control-char display sanitizer entry
* fix(exec-approvals): redact before escape, cover U+2028/U+2029 in display sanitizers
* fix(exec-approvals): strip invisibles before redaction and align forwarder test
* fix(exec-approvals): cover Zs bypass and preserve multi-line context on obfuscated secrets
* fix(exec-approvals): compare redaction outputs by content, not length
* fix(exec-approvals): suppress raw command on bypass; cover non-ASCII Zs in macOS sanitizer
* fix(exec-approvals): use position-bitmap bypass detection and bound input size
* style(exec-approvals): satisfy oxlint no-new-array-single-argument and SwiftFormat
* fix(exec-approvals): iterate by code point and redact before truncating
`openclaw --version` outputs "OpenClaw 2026.x.y-z" but
readGatewayVersion() passed the full string to Semver.parse(),
which failed on the "OpenClaw " prefix. This caused the app to
fall back to reading package.json from a local source checkout
(~/Projects/openclaw), reporting a false version mismatch.
Strip the product name prefix before parsing so the installed
CLI version is correctly recognized.
* fix(macos): show sessions after controls in tray menu
When many sessions are active, the injected session rows push the
toggles, action buttons, and settings items off-screen, requiring
a scroll to reach them.
Change findInsertIndex and findNodesInsertIndex to anchor just before
the separator above 'Settings…' instead of before 'Send Heartbeats'.
This ensures the controls section is always immediately visible on
menu open, with sessions appearing below.
* refactor: extract findAnchoredInsertIndex to eliminate duplication
findInsertIndex and findNodesInsertIndex shared identical logic.
Extract into a single private helper so any future anchor change
(e.g. Settings item title) only needs one edit.
* macOS: use structural tray menu anchor
---------
Co-authored-by: Brian Ernesto <bernesto@users.noreply.github.com>
Co-authored-by: ImLukeF <92253590+ImLukeF@users.noreply.github.com>