* fix(ui): confirm disruptive Control UI updates before dispatch
Every Control UI update affordance dispatched `update.run` (or the macOS
bridge `start-update` message) on the first click, so a misclick could
install new code, restart the Gateway, and interrupt active work.
Add one canonical confirmation gate in the Control UI owner boundary and
route the sidebar/settings-sidebar/floating update card and the
Settings -> Updates row through it. The gate owns the copy, the versions,
the restart consequence, the action-specific confirm label, and the
choice between the macOS bridge and `update.run`, so the bridge fork no
longer lives in the card and no surface can drift.
CLI, API, automation, agent-driven paths, automatic update campaigns, and
the `update.run` contract are unchanged.
Addresses the Control UI portion of #117178.
* style(ui): apply oxfmt to update confirmation sources
* perf(ui): load the update confirmation lazily and share its impact copy
Keeps the Control UI startup bundle under its 317 KiB gzip ceiling: the
confirmation dialog only loads when an operator opens it.
* test(ui): drive the update confirmation in sidebar and shell wiring tests
* fix(macos): let onboarding replace an auto-connected AI
The AI page auto-tests the best detected candidate and connects without
asking, then hides every alternative route. Add 'Choose a different AI'
to the connected banner: a re-detect pass with auto-activation
suppressed that ends at the picker (candidates, provider sign-in, API
keys). Also disable the manual key Connect button while another test
runs (submitManualKey silently dropped the tap), and isolate a test
that read the machine's real resume store.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(macos): surface real daemon errors past the Node banner
Gateway daemon failures summarized as 'Node.js v26.5.1' because the
summary takes the last non-empty line and Node fatal errors end with a
version banner. Drop trailing banner lines and prefer the last
error-shaped line above them; all other output keeps its last line.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(macos): hand onboarding off to the dashboard custodian
Native onboarding now ends once inference verifies: welcome, connection,
install (when needed), AI setup. Finish opens the dashboard at
/custodian?onboarding=1, where the custodian onboarding owns memory
import, channels, app recommendations, and the hatch (browser-first per
the onboarding redesign). The native memory-import and permissions
pages leave the first-run flow; 'Set up later' keeps the native ready
page. The native navigation bridge gains a validated optional search
field so the handoff can request onboarding chrome; the URL fallback
carries the query alongside the token fragment.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* refactor(macos): delete the unreachable native memory-import module
The dashboard handoff removed the memory-import page from every flow,
leaving the module reachable only from tests. CI's dead-code scan
rightly flagged the first orphans; remove the whole path (model, page,
mascot wiring, tests) instead of trimming symbol by symbol. The
dashboard's own memory-import surface owns the feature.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Peter Steinberger <steipete@mac-studio-sf2.local>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* feat(mac): show native notification permission in dashboard Notifications settings
The Mac app's embedded Control UI showed the web-push section as
Unsupported/Not subscribed even though the app delivers notifications
natively. The dashboard now installs an openclawNotifications WebKit
bridge (status / request-permission / send-test) and the Notifications
settings page renders native permission state with Enable, Open System
Settings, and Send test actions when hosted in the Mac app. Browsers
keep the existing web-push UI. The notifications section renderer moved
out of the oversized config view module.
* fix(ui): break config view import cycle and satisfy lint/deadcode/i18n gates
Move the notifications section props to a leaf contract (no view.ts
type import), unexport the status-event constant, use bracket access
for the injected dunder global, default-case the status switch, and
refresh the native i18n inventory line offset.
* feat(mac): add Quick Chat floating composer with global shortcut
- Spotlight-style non-activating key panel on Option+Space (KeyboardShortcuts
3.0.1 exact-pinned, recorder row in Settings -> General) plus a menu bar item
- shows the main-session agent identity via agent.identity.get with a
'main session' chip; Return sends via chat.send reusing the idempotency key
on ambiguous retries; Cmd+Return also opens full chat; Shift+Return newline
- targeted permission strip (notifications/accessibility/screen recording)
with a scoped 1s status poll while visible; grant flow keeps the bar alive
and avoids PermissionMonitor's AppleScript probe
- extract shared ChatSendStatus acceptance mapping; TalkModeRuntime adopts it
- rename anchored-panel 'quick chat' wording to 'compact chat panel'; docs
* chore(mac): regenerate docs map and native i18n inventory for Quick Chat
* ci: retrigger checks after stalled push event
* chore(mac): refresh native locale artifacts for Quick Chat strings
* chore(android): regenerate locale strings for refreshed shared translations
User-facing name is now OpenClaw (the system speaks); internal code name is
system-agent. Gateway methods crestodian.* -> openclaw.chat/openclaw.setup.*,
agent tool -> openclaw, reserved agent ids openclaw + retired crestodian.
openclaw setup routes: onboarding flags -> onboard, -m/--yes -> system agent,
bare configured interactive -> OpenClaw chat, unconfigured -> onboarding.
Hidden crestodian CLI and /crestodian TUI aliases kept; docs moved to
docs/cli/openclaw.md with redirect stub. macOS/Android strings in lockstep.
Refs #107237
* feat(mac): swap dashboard titlebar buttons with sidebar state
The Control UI reports sidebar collapsed/width over a new openclawNav
WKScriptMessage; the titlebar accessory shows toggle+back/forward
right-aligned to the sidebar edge while expanded, and
toggle+search+new-session while collapsed. Search opens the command
palette and + opens the new-session surface via openclaw:native-*
events. Older gateway bundles that never report keep the shipped
toggle/back/forward layout.
Refs #105129
* docs: describe state-dependent mac titlebar buttons
* feat(nodes): route alerts by active computer
* fix(ci): allowlist node presence mobile coverage
* test(prompts): refresh node presence snapshots
* fix(macos): await presence reporter actor hop
* fix(macos): type presence test delivery state
* docs(nodes): add active presence guide
* docs(nodes): format presence troubleshooting
* 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
Each inline link opens in its own tab (exact-URL dedupe); sidebar
target=_blank links open new tabs. Tab strip on top with click to
activate, close buttons, middle-click close, pointer-drag reorder, and
a per-tab context menu (Open in Default Browser, Copy Link, Reload,
Close Tab, Close Other Tabs). Navigation controls sit below the tabs
and follow the active tab. Closing the last tab collapses the sidebar
with no lingering webviews or history.
Replaced 60 typography characters (curly quotes, apostrophes, em/en
dashes, non-breaking hyphens) with ASCII equivalents per
docs/CLAUDE.md heading and content hygiene rules.
- docs/start/openclaw.md: 10 chars; removed the duplicate '# Building
a personal assistant with OpenClaw' H1 (Mintlify renders title from
frontmatter).
- docs/platforms/mac/remote.md: 10 chars; removed the duplicate
'# Remote OpenClaw (macOS ⇄ remote host)' H1 (the U+21C4 codepoint
and parens both produced brittle anchors).
- docs/tools/thinking.md: 10 chars
- docs/reference/templates/BOOTSTRAP.md: 10 chars (kept the in-body
'# BOOTSTRAP.md - Hello, World' heading because the page is a
template whose content is meant to be copied verbatim into a
workspace BOOTSTRAP.md).
- docs/plugins/sdk-provider-plugins.md: 10 chars
- docs/platforms/macos.md: 10 chars
Per docs/CLAUDE.md, Mintlify anchor generation is brittle for headings
that contain em dashes, apostrophes, and ampersands. Normalize 9 H2
headings across docs/date-time.md, docs/pi.md, docs/platforms/{index,
macos, mac/webchat, mac/peekaboo}.md, docs/nodes/{images,audio}.md, and
docs/reference/AGENTS.default.md from `X & Y` to `X and Y` so anchors
do not collapse on entity decoding. Verified no inbound anchor references
to the renamed sections in the docs tree.
- platforms/android: blockquote Note for Android app status, Note for canvas host port
- platforms/macos: Tip component for app vs CLI discovery comparison
- plugins/zalouser, channels/zalouser: blockquote Warning components for unofficial automation risk
- channels/pairing: convert two Important paragraphs to Note components for DM-vs-group scope and silent-upgrade behavior
* Doctor: detect macOS cloud-synced state directories
* Doctor tests: cover cloud-synced macOS state detection
* Docs: note cloud-synced state warning in doctor guide
* Docs: recommend local macOS state dir placement
* Changelog: add macOS cloud-synced state dir warning
* Changelog: credit macOS cloud state warning PR
* Doctor state: anchor cloud-sync roots to macOS home
* Doctor tests: cover OPENCLAW_HOME cloud-sync override
* Doctor state: prefer resolved target for cloud detection
* Doctor tests: cover local-target cloud symlink case