4991 Commits

Author SHA1 Message Date
Vyctor H. Brzezowski aba94bbe0b fix: install or review the publisher you picked when ClawHub skills share a slug (#121697)
* fix(skills): keep ClawHub publisher identity from search through install

ClawHub search returns one entry per publisher, so several results can share a
slug. Every client collapsed the selection to that bare slug before calling
skills.detail and skills.install, and ClawHub answered 409 AMBIGUOUS_SKILL_SLUG
with no in-product way forward.

searchClawHubSkills now records the publisher-qualified reference once, on the
result that carries it, and the Gateway protocol documents it. skills.detail
parses the same reference grammar skills.install already accepted, so review and
install cannot resolve to different publishers. Control UI carries that one
reference through row actions, detail, busy state, and acknowledgement retries,
and shows it so otherwise identical rows are distinguishable.

Fixes #117633

* fix(apps): send the ClawHub publisher reference from native skill browsers

macOS, iOS, and Android read the qualified reference from search results and use
it for skills.detail, install, busy state, installed matching, and list identity,
so two publishers sharing a slug stay distinct instead of collapsing into one
ambiguous request.

* fix(skills): refuse external-source skill detail instead of reading a same-slug skill

ClawHub has no source-qualified read endpoint, so a skills-sh reference parsed
down to its bare slug would have returned a registry skill's card while install
resolved the external artifact. Review and install could name different skills.

skills.detail now fails closed on any reference that carries a source, and the
macOS and AgentPro rows show the publisher reference next to the summary instead
of only when a summary is missing, so same-slug rows stay distinguishable.

* chore(apps): refresh native i18n source baseline for the skill row references

* refactor(skills): drop the unread search-result ownerHandle field

installRef is the one reference clients send back, and no client reads the
publisher handle separately, so the protocol and Control UI carry one field
instead of two.

* fix(skills): name the next step when external skill detail is refused

Clients that gate install behind a successful review would otherwise see only a
refusal, so the error names the direct install path and the CLI equivalent.

* fix(macos): use a doc comment on the ClawHub row subtitle

swift-format's docComments rule requires doc comments on declarations; the
subtitle property carried a regular comment and failed macos-swift.

* fix(skills): carry ClawHub trust state to clients that can install

Forwarding installRef let clients install the exact publisher the operator
picked, including external skills-sh sources. It did not forward the trust
state that says ClawHub never scanned that source, so iOS AgentPro — the one
surface that installs in a single tap with no review step — could install an
unscanned artifact with nothing on screen saying so. The CLI already labels
these (docs/clawhub/cli.md, docs/cli/skills.md); native clients could not,
because trustState was never on the wire.

trustState becomes an optional field on SkillsSearchResultSchema. It is purely
additive: older clients ignore an unknown key and the field is absent for
registry results, so downgraded readers are unaffected and no protocol version
moves.

Every client that renders a search row now shows "Not scanned by ClawHub",
matching the CLI wording exactly: iOS AgentPro in the row above the install
button, macOS and Android beside the review action, and Control UI on the row
that explains why review is refused for these sources.

Covered by a wire assertion that the state reaches clients for an external
source and stays absent for registry rows, plus decode-and-label tests on the
shared Swift kit and the Android parser, and a Control UI render assertion.

* fix(ui): size the ClawHub detail dialog to a refusal message

Refusing detail for an external source made an error-only dialog reachable.
The shared preview panel reserves a tall reader height for skill documents, so
a two-line refusal rendered in a mostly empty dialog and read as broken rather
than deliberate. Found by inspecting the review captures.

* revert(ui,apps): drop the ClawHub trust label layer

Maintainer product decision: skills.sh runs its own scanners, so OpenClaw does
not add a second alert layer in the apps. Removes the label from Control UI,
iOS, macOS and Android, and drops the trustState wire field that nothing would
render. The CLI keeps its existing label; changing that is a separate call.

Publisher identity, the fail-closed detail refusal, and the message-only dialog
are unchanged. Splits the oversized skills view test file to satisfy max-lines
without a suppression.

* test(ui): fix ClawHub skill fixture checks

* chore(plugin-sdk): refresh API baseline

---------

Co-authored-by: Patrick Erichsen <patrick.a.erichsen@gmail.com>
2026-08-12 20:13:15 -07:00
Peter Steinberger cef071582e feat: let limited browsers request admin access (#121459)
* feat(gateway): add live device scope upgrades

* feat(ui): add limited-access upgrade flow

* fix(protocol): refresh Swift scope upgrade models

* perf(ui): lazy-load device scope upgrades

* fix(ci): complete scope upgrade generated surfaces

* perf(ui): lazy-load GitHub link hovercards

* fix(ui): keep admin repair guidance focusable

* fix(ui): gate and refresh scope upgrade banner

* refactor(ui): keep gateway client within line budget

* fix(ci): align rebased scope upgrade checks

* fix(ui): resolve scope upgrade in browser tests

* fix(gateway): honor refreshed scope upgrade deadline

* fix(gateway): honor refreshed scope upgrade deadline

* fix(gateway): coalesce scope upgrade waiters

* fix(ui): gate scope upgrade actions

* chore(plugin-sdk): refresh rebased API baseline

* fix(scope-upgrade): return canonical request ids

* fix(ui): preserve gateway event type binding

* fix(protocol): generate scope upgrade result models

* fix(ui): preserve scope upgrade recovery guidance

* chore(plugin-sdk): refresh rebased API baseline

* test(ui): avoid scope upgrade navigation race

* docs(control-ui): clarify scope upgrade approver

* test(gateway): align appended method counts

* chore(plugin-sdk): refresh rebased API baseline

* refactor(ui): keep place picker within line budget

* chore(plugin-sdk): refresh rebased API baseline

* chore(plugin-sdk): refresh rebased API baseline

* chore(plugin-sdk): refresh rebased API baseline

* chore(plugin-sdk): refresh rebased API baseline

* chore(plugin-sdk): refresh rebased API baseline

* chore(plugin-sdk): refresh rebased API baseline

* chore(plugin-sdk): refresh rebased API baseline

* chore(plugin-sdk): refresh rebased API baseline

* chore(plugin-sdk): refresh rebased API baseline

* chore(plugin-sdk): refresh rebased API baseline

* chore(plugin-sdk): refresh rebased API baseline

* fix(gateway): preserve scope-upgrade browser origin
2026-08-12 18:32:00 -07:00
Peter Steinberger 7c7c7524ad feat: add paired-device worker provider foundation (#122769)
* feat(worker-provider): add core device lease foundation

* feat(gateway): dispatch sessions to paired devices

* test(gateway): cover node-ready lifecycle edge

* fix(gateway): defer device worker installation prep

* chore(plugin-sdk): refresh API baseline

* test(gateway): isolate worker turn state database

* docs(runners): refresh milestone table format

* test(gateway): track device dispatch temp state
2026-08-12 16:50:09 -07:00
Josh Lehman bb5ef9872a fix: resume sessions interrupted by gateway restarts (#122644)
* fix: resume sessions interrupted by gateway restarts

* fix: make session recovery retry-safe

* refactor: isolate restart session recovery

* test: track recovery temp directories

* fix: inherit recovery state under lifecycle lock

* fix: surface rejected recovery continuation

* fix: fence recovery continuation authority

* chore: regenerate plugin sdk api baselines

* test(gateway): track sessions.recover release train
2026-08-12 16:18:58 -07:00
Peter Steinberger a8b05c66d7 test(macos): remove residual smoke probes (#122856) 2026-08-12 16:04:32 -07:00
Peter Steinberger 1ca60fbc3a refactor(agents): make multi-agent ownership explicit (H2-1 core) (#114388)
* refactor(agents): make roster ownership explicit

* feat(config): materialize legacy agent roles

* fix(cron): migrate legacy owners at startup

* feat(gateway): expose agent selection contracts

* fix(gateway): enforce agent-scoped authorization

* docs(config): document explicit agent ownership

* fix(config): pin retained owner workspace

* fix(gateway): target hook wakes at effective agent

* fix(sessions): preserve fixed-store ownership

* fix: preserve retained agent ownership

* fix: preserve legacy agent ownership across runtime surfaces

* fix: fail closed on ambiguous session ownership

* fix: preserve compatibility owners across dispatch and writes

* fix: preserve retained agent projections

* fix: preserve agent ownership compatibility

* fix: preserve per-agent heartbeat guidance

* fix: preserve compatibility owners in generic paths

* fix: enforce configured ownership in session paths

* fix: defer remote roster selection

* fix: preserve ownership across session and config writes

* fix: fail closed on ambiguous restored ownership

* fix: preserve explicit ACP and legacy ownership

* fix: honor durable fixed-store ownership

* fix: enforce fixed-store owner authority

* fix: preserve ownership evidence boundaries

* fix: honor resolved session ownership

* fix: align compatibility ownership paths

* fix: persist legacy main store ownership

* fix: close ownership fallback gaps

* fix(agents): close retained owner compatibility gaps

* fix(agents): enforce session owner resolution

* fix(agents): complete session owner resolution sweep

* fix(agents): preserve durable session ownership

* fix: complete persisted session owner routing

* fix: thread prepared session owners

* fix: preserve stable session ownership

* fix: enforce session ownership boundaries

* fix: close session ownership delta gaps

* fix: reconcile session ownership after rebase

* fix: reconcile ownership with current main

* fix: align session store path imports

* fix: align session store config path import

* fix: reconcile explicit ownership CI

* fix: reconcile ownership rebase checks

* fix: align ownership ci contracts

* fix: align ownership rebase checks

* fix: preserve compatibility owner during setup

* fix(doctor): migrate ownerless heartbeat monitors

* fix(gateway): preserve explicit session ownership

* test: align ownership fixtures after rebase

* test: complete plugin manifest fixture

* test: align runtime context mocks

* fix(gateway): preserve alias routing for existing sessions

* style: format agent routing update

* fix(gateway): preserve selected owner during alias routing

* style: normalize rebased ownership files

* fix(gateway): preserve owner through global alias routing

* fix(gateway): preserve explicit ownership at HTTP boundaries

* fix(gateway): validate compatibility model ownership

* fix(agents): reconcile strict session ownership

* fix(agents): contain media yield callback failures

* fix(agents): avoid eager bare-key owner resolution

* chore: refresh rebased ownership baselines

* chore: align hosted plugin SDK baseline

* chore: refresh ownership baselines after main sync

* chore: refresh ownership baselines after main sync

* test: align routed event owner fixtures

* chore: retrigger CI after runner startup failure

* chore: refresh ownership SDK budgets after main sync

* fix(tasks): require agent identity for bare owners

* chore: align Linux plugin SDK baseline

* chore: remove release-owned changelog entry
2026-08-12 15:55:16 -07:00
Peter Steinberger b6548e509a refactor(state): retire commitments schema (#122176)
* refactor(state): retire commitments schema

* fix(state): complete commitments retirement safeguards

* test(state): expect doctor retirement report

* test(state): prove doctor v7 markers atomically

* fix(state): align schema support metadata

* fix(state): report actual commitments retirement

* fix(state): validate retired commitments schema

* fix(state): preserve early commitments upgrades

* fix(state): require exact commitments index set

* fix(state): reject non-exact retired schemas

* fix(state): recognize supported retirement layouts

* fix(state): expose commitments retirement to doctor

* fix(voice-call): describe commitments retirement

* test(state): align v7 rebase proof

* fix(state): protect commitments retirement dependencies

* fix(state): accept partial commitments layouts

* chore(docs): refresh v7 api baselines
2026-08-12 14:21:34 -07:00
Peter Steinberger 0c824f09d5 feat(gateway): observe paired node desktops (#122724)
* feat(gateway): stream paired node desktops

* chore(protocol): refresh desktop observe model

* fix(gateway): preserve desktop stream boundaries

* fix(gateway): keep desktop streams lifetime-bound

* fix(gateway): harden node desktop stream lifecycle

* fix(gateway): stabilize node desktop lifecycle setup

* chore(plugin-sdk): refresh API baselines
2026-08-12 13:17:45 -07:00
Peter Steinberger a1615cdfcf feat(linux): suspend the local gateway across host sleep via logind (#122719)
* feat(linux): suspend the local gateway across host sleep via logind

Mirror the macOS sleep cycle in the Tauri companion: a logind
PrepareForSleep listener with a delay inhibitor best-effort prepares a
local gateway suspension before sleep and resumes it on wake with a
reconnect nudge and bounded retries; leases are route-bound, always
cleared on wake, and late prepare responses resume immediately.

* fix(linux): keep the sleep listener alive when inhibitor re-acquire fails

* fix(linux): activate the driver for sleep cycles and bound driver-side sleep RPCs

Sleep cycles temporarily unpark the gateway driver so prepare/resume work
without the Quick Chat window; suspend RPCs carry a 3s driver-side budget
that recycles a hung socket instead of starving wake retries; a mock-logind
integration test exercises the Linux listener end to end.

* fix(linux): count overlapping sleep cycles instead of a boolean flag

An older wake task ending late cleared the shared activation flag and
parked the driver mid-cycle; a saturating depth counter keeps the driver
active until the last cycle ends.

* fix(linux): gate sleep-cycle activation on loopback routes and never block wake on logind

Remote or unconfigured routes no longer activate the driver during
sleep, the paired end hook runs only for cycles that began, and wake
recovery is spawned before the inhibitor re-acquire so a slow logind
cannot delay reconnect/resume.
2026-08-12 11:53:51 -07:00
Peter Steinberger 8bbc0a9bc7 fix(config): keep named profiles off the default gateway port (#122751)
* fix(config): derive profile gateway ports like the Mac app instead of defaulting to 18789

* fix(config): use canonical profile normalization
2026-08-12 11:47:44 -07:00
openclaw-mantis[bot] d17264f5fd chore(i18n): refresh native locales (#122688)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-13 02:45:50 +08:00
Peter Steinberger fb13d62e70 test(macos): remove unused coverage artifacts (#122755) 2026-08-12 11:34:28 -07:00
Peter Steinberger 8624b9acb8 feat(gateway): recover channels and health promptly after host sleep (#122489)
* feat(gateway): recover channels and health promptly after host sleep

A dependency-free thaw detector rides the existing 30s maintenance tick:
when the process resumes after being frozen >=45s beyond cadence (laptop
sleep, VM pause, SIGSTOP), the gateway restarts running channel accounts
(dead sockets otherwise take up to ~35 minutes to notice), refreshes
health/presence, and resets the event-loop histogram so the freeze does
not read as degradation. Admission is rechecked before every recovery
side effect; a suspension beginning mid-recovery re-pends the thaw, and
timed-out channel stops complete their two-call restart in one pass.

The macOS app cooperates: NSWorkspace sleep/wake observers in
GatewayConnectivityCoordinator best-effort prepare a local gateway
suspension before sleep and resume it on wake, never blocking sleep.
The lease is bound to the route that prepared it and always cleared on
wake; route or mode changes across sleep drop it to self-expiry.

Live proof: SIGSTOP 85s on an isolated dev gateway -> 'host thaw
detected: process was frozen ~57683ms', channels restarted, health ok,
eventLoop degraded=false after thaw.

* fix(macos): resume a sleep lease whose prepare response arrives after wake

A prepare completing after didWake previously discarded the lease id,
fencing the gateway until the two-minute expiry after micro-sleeps; the
late response now resumes immediately. Document the conservative
route-token drift tradeoff.

* fix(macos): retry wake resume after refreshing the dead post-sleep transport

After real sleep the WebSocket is usually dead exactly when resume runs;
refresh the endpoint first, then attempt resume up to three times with
bounded delays, clearing the lease only on success or exhaustion. A new
sleep cycle aborts in-flight retries.

* fix(gateway): bound plugin stopAccount so channel stops cannot wedge recovery

stopChannel awaited plugin stopAccount unbounded; a never-settling stop
hung the thaw restart (and health-monitor sweeps) and held the
single-flight recovery guard forever. Race it against the existing
5s stop timeout; the timed-out path flows into the established
recoveryStopTimedOut two-call restart contract. Regression wedges
pre-fix.

* refactor(gateway): move thaw channel restart off ChannelManager and fence mid-pass

restartRunningChannelAccounts is a standalone helper over the public
manager surface with a shouldContinue probe checked before every stop
and start, so a suspension committing while an account stop is awaited
leaves later accounts untouched. Regression covers the mid-pass close.

* fix(gateway): sanitize late writes from an abandoned stopAccount

An abandoned (timed-out) stopAccount can settle after its replacement
started; route its late setStatus writes through the existing
stale-task sanitizer so they cannot repaint or tear down the
replacement. Regression fails pre-fix.
2026-08-12 08:15:24 -07:00
Peter Steinberger f9f602a0df test(macos): remove body-only smoke probes (#122645) 2026-08-12 07:59:35 -07:00
Peter Steinberger df707a9670 feat: view this machine in the Desktop panel (#122545)
* feat(gateway): add gateway-host desktop source behind desktop.host lab

Introduce the host as a first-class desktop source so operators can view
the machine OpenClaw runs on, not just cloud-worker environments:

- protocol: desktop.observe / desktop.launch with a discriminated
  DesktopSource union (host | environment) plus an additive auth hint;
  EnvironmentSummary gains a top-level desktop flag
- config: desktop.host { enabled, port?, passwordFile? }, Labs-gated
- rfb-probe: pure RFB version/security-type parser used to detect an
  already-running loopback VNC server and classify its auth
- host-source: attaches to 127.0.0.1:<port>, refuses unauthenticated
  (None) and unsupported (VeNCrypt) servers, and refuses ARD with the
  supported alternative until the macOS milestone
- host-guidance: per-OS enablement text so no path dead-ends
- doctor + status report host desktop availability and auth type only

worker.desktop.observe/launch stay as delegating aliases with identical
behavior. Also drops the now-unused WorkerDesktopTunnels type export.

Live-verified against macOS Screen Sharing: probe reads RFB 003.889,
returns security types [30,33,36,35], classifies ard-account.

* test(gateway): probe RFB handshakes through the socket boundary

The probe's banner and security-offer parsers were exported solely so
unit tests could call them, which the dead-export gate rejects and which
tests internals rather than behavior. Keep them module-local and drive
the probe through a scripted loopback server instead.

The boundary tests also cover what pure-function vectors could not:
handshakes split across packets, legacy RFB 3.3 single-word security,
server-rejected handshakes, early hangups, and connect timeouts.

* feat(ui): let the Desktop panel view this machine, not just cloud workers

The Desktop panel was gated on a cloud-worker session placement, so an
operator running OpenClaw locally had no way to see the machine hosting
their main session even with a VNC server running on it.

Availability now follows the advertised desktop.observe method plus
operator.admin instead of session placement, and the picker lists every
environment whose summary reports a desktop, with the gateway row shown
as "This machine". Sources are passed to the generic desktop.observe /
desktop.launch RPCs; the app launcher stays worker-only. When a host
attach needs a password the gateway did not supply, the panel prompts and
keeps the value in memory for that connection only.

Adds the hostDesktop Labs toggle for desktop.host.enabled.

* fix(scripts): keep the env-var ratchet usable in shallow checkouts

The env-var budget check resolved its base ref, then hard-failed when
`git merge-base` found no shared ancestor. Shallow clones and grafted
agent checkouts resolve origin/main but truncate the history behind it,
so an advisory growth ratchet took down the whole check:changed gate
with "Could not resolve env-var count merge base for: origin/main".

Only the growth comparison needs a baseline, and the script already has
a no-baseline path. Treat git's exit 1 with empty output (no shared
ancestor) as that case and say so on stderr; a genuine failure still
exits 128 and still throws, and the absolute count-vs-budget check runs
either way.

* test(ui): measure the inline-code chip against its line box

The inline-code spacing test compared the chip's height to a prose text
rect, so it silently measured the monospace font's default line spacing.
That is ~17px on macOS and several px shorter on Linux, so the assertion
passed on CI and failed locally at 4.5 against a 3.75 bound -- after the
bound had already been widened once to chase browser font metrics.

Compare the chip to the paragraph's CSS line box instead, which is what
"the chip must not disrupt the line" actually means and is platform
independent. The horizontal gap stays as-is: it is em-derived padding
plus border, and it is the assertion that catches detached punctuation.

Verified both directions on macOS: the file is fully green, and
restoring the pre-fix 0.15em/0.35em padding still fails the gap
assertion at 5.41.

* feat(gateway): view macOS Screen Sharing from the Desktop panel

Modern macOS only offers ARD account authentication for Screen Sharing,
so the host desktop source refused every Mac. The Gateway now performs
the ARD handshake itself against the loopback server and hands the
browser a plain RFB 003.008 no-auth handshake, so the operator's macOS
account password authenticates the desktop without ever reaching the
browser, the observe result, a URL, or a log.

- rfb-preauth: ARD (type 30) Diffie-Hellman with MD5-derived AES-128-ECB
  credentials, and VncAuth (type 2) bit-reversed DES, both under a single
  10s negotiation deadline; Apple's RFB 003.889 maps to 3.8
- observe-bridge: runs pre-auth before splicing and starts the view-only
  filter at clientInit, since the browser handshake is consumed here;
  worker tokens keep the original version start phase
- host-source: attaches ARD, requiring per-observation credentials that
  live only in the one-shot observer token and are dropped after use
- doctor: offers an explicitly confirmed sudo launchctl repair when
  Screen Sharing is off, and prints the System Settings path otherwise

Live-verified against this Mac's Screen Sharing: the DH exchange and
credential framing are accepted and the server returns SecurityResult.
The VncAuth DES vector is confirmed against OpenSSL independently.
2026-08-12 06:58:30 -07:00
Peter Steinberger ade3456dd4 feat: add one-paste node onboarding (#122499)
* feat(pairing): add short join onboarding

* fix(gateway): isolate device join routing tests
2026-08-12 06:17:39 -07:00
Peter Steinberger 40cb6f0e3b feat(ui): keep Where picker destinations live (#122531)
* feat(gateway): enrich environment summaries

* chore(sdk): refresh plugin API surface

surface drift approved: additive EnvironmentSummary enrichment (runners plan rev 2, milestone 4)

* feat(ui): keep where picker destinations live

* docs: link picker liveness milestone PR

* fix(ui): deduplicate picker locale keys

* test(ui): update picker section expectations

* fix(ssrf): narrow lookup resolver contract

* fix(gateway): publish authoritative environment facts
2026-08-12 05:11:46 -07:00
Pavan Kumar Gondhi 5eb18c1387 fix(ios): keep authenticated Control UI pages bound to the trusted Gateway [AI] (#119906)
* fix(ios): enforce gateway TLS pins in control pages

* test(ios): run control UI trust regressions in CI

* test(ios): avoid nested Testing macros

* fix(ios): preserve control page navigation

* fix(ios): keep authenticated control pages on origin

* fix(ios): canonicalize control page IPv6 hosts

* chore(ios): refresh native i18n inventory

* fix(ios): normalize default TLS challenge ports

* fix(apps): share gateway TLS authority matching

* test(apps): fix authority CI validation

* chore(ci): drop control UI test routing
2026-08-12 15:18:19 +05:30
Peter Steinberger d44f70eb4b feat(pairing): one-paste device pairing via oc-pair setup links (#120768)
* feat(pairing): one-paste device pairing via oc-pair setup links

Implements milestone 3 from docs/plan/runners.md.

* fix(pairing): sign bootstrap handshake, keep URL candidates, wire pairing countdown

* test(gateway): update client callsite guard

* fix(pairing): preserve setup URL context paths

* fix(ui): keep pairing help aligned with setup mode

* fix(pairing): isolate bootstrap credentials

* perf(ui): keep one-paste pairing within bundle budget

* refactor(pairing): isolate native pair URL prefix parsing

* fix(pairing): preserve candidate lifecycle state

* fix(pairing): retire shared credentials after bootstrap

* fix(pairing): apply rotated manifest through client owner

* test(pairing): prove bootstrap retirement across reconnect

* fix(pairing): preserve native gateway context paths

* fix(pairing): carry native context paths through reconnect

* fix(ios): preserve encoded gateway context path

* chore(plugin-sdk): refresh pairing API baselines
2026-08-12 02:01:33 -07:00
Peter Steinberger 85a176b98a feat(ui): commit-scoped session diff viewer with file, sync, and view menus (#122470)
* feat(ui): commit-scoped session diff viewer with file, sync, and view menus

The Control UI session diff panel becomes a dense Amp-style viewer: per-file
menus (copy path, open file, reveal in file tree, open in editor), a Sync
Locally popover with a copyable git fetch command, view options (collapse all,
wrapping, split/unified layout), and a sticky footer that reports how far the
branch is ahead of its merge base and switches between all changes,
uncommitted work, and individual commits.

sessions.diff gains an additive scope param (all | uncommitted | commit) plus
commits, aheadCount, and mergeBase metadata. Commit-scope diffs read only the
object database, skip untracked collection, and bypass session-start baseline
filtering; unknown commits surface a typed unavailableReason. Offscreen file
bodies use content-visibility so large diffs stay responsive.

* fix(ui): satisfy session diff CI gates

* fix(gateway): fence commit-scoped session diffs to the advertised branch history

ClawSweeper found that commit-scoped sessions.diff accepted any commit resolvable in the checkout. Fence operator.read commit reads to the advertised merge-base..HEAD history and cover sibling-branch and base-history commits.
2026-08-12 01:08:33 -07:00
Peter Steinberger 0de17482ae feat(gateway,ui): quiet Where picker, placement chip, and projects read model (#120804)
* feat(gateway): projects.list groups known checkouts by repo identity

Implements docs/plan/runners.md milestone 4 derived projects read model.

* feat(ui): regroup the Where picker by gateway, devices, and cloud

* feat(ui): placement chip shows where a session runs with reclaim

Implements docs/plan/runners.md milestone 4 placement display and reclaim.
2026-08-12 00:21:23 -07:00
Peter Steinberger 526ae6d944 fix(macos): honor While Using location permission (#122435) 2026-08-11 22:12:56 -07:00
Peter Steinberger 4401ff2a92 refactor(macos): remove final private test seams (#122202)
* test(macos): remove final private test seams

* chore(macos): refresh native i18n inventory
2026-08-11 20:42:45 -07:00
openclaw-mantis[bot] 4bd56a316b chore(i18n): refresh native locales (#122355)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-11 20:00:14 -07:00
Peter Steinberger 8876528f7c feat: clone GitHub projects from session picker (#121818)
* feat(projects): add managed GitHub clones

* feat(ui): clone GitHub projects from session picker

* fix(projects): integrate current gateway owners

* fix(protocol): derive Swift error detail accessors

* fix(ui): gate project cloning by scope

* test(gateway): isolate session prewarm probes

* revert: drop duplicate session prewarm repair
2026-08-11 18:49:16 -07:00
Peter Steinberger cd0a1235a3 feat: sync new-session preferences and recents by identity (#121816)
* feat(gateway): add identity preferences and project recents

* feat(ui): sync new-session identity state

* docs: explain identity-scoped session state

* test: track preference temp directories

* fix(gateway): preserve identity preference boundaries

* chore(protocol): refresh identity preference bindings

* test: refresh historical schema hashes

* style(gateway): format method order assertion

* fix(protocol): emit project recent Swift models

* test(gateway): track preference RPC release train

* fix(gateway): harden identity preference state

* fix(state): keep preference errors internal

* chore: refresh split plugin SDK baseline

* fix(gateway): use core session store loader

* refactor(state): fold additive migration checks

* chore: regenerate plugin SDK baseline

* chore: regenerate plugin SDK baseline

* chore: regenerate plugin SDK baseline

* chore: regenerate plugin SDK baseline

* chore: regenerate plugin SDK baseline

* chore: regenerate plugin SDK baseline

* chore: regenerate plugin SDK baseline

* test(ui): relocate identity recents e2e

* chore: regenerate plugin SDK baseline

* chore: regenerate plugin SDK baseline

* chore: regenerate plugin SDK baseline

* chore: regenerate plugin SDK baseline

* chore: regenerate plugin SDK baseline
2026-08-11 16:52:59 -07:00
Peter Steinberger db9bdb4a11 fix(gateway): preserve session identity through archive transitions (#121169)
* fix(sessions): fence lifecycle mutations by identity

* fix(sessions): finalize lifecycle identity fences
2026-08-11 16:43:10 -07:00
Peter Steinberger 896e3fb0ac fix(android): keep completed subagent activity visible for sixty seconds (#122089)
* fix(android): retain terminal subagent activity locally

* chore(android): preserve native i18n inventory
2026-08-11 15:19:57 -07:00
Peter Steinberger 01804a7531 feat(apps): Android chat adopts the system-notice family (#122268)
* feat(apps): Android chat adopts the system-notice family

Decode internal_system provenance and __openclaw markers in parseHistory,
classify into SystemNotice/SystemDivider timeline variants with web-parity
kinds, render minimal Compose rows, round-trip metadata through the
transcript cache textPartsJson envelope (no Room change), and extend the
deterministic screenshot fixture.

* fix(apps): keep generated locale artifacts out of the source PR

The native locale refresh workflow owns NativeStringResources.kt and
values-*/strings.xml; ship source strings plus the regenerated
apps/.i18n/native-source.json inventory only.
2026-08-11 15:03:15 -07:00
Peter Steinberger cb51cf7d3e feat(apps): Apple chat adopts the system-notice family (#122255)
* feat(apps): adopt the system-notice family in Apple chat (OpenClawChatUI)

Decode internal_system provenance and __openclaw history markers, classify
once into message/notice/divider rows (web-parity kinds), render minimal
hairline notice/divider SwiftUI rows, preserve metadata through history
reconciliation, live transport, and the transcript cache, and align the
transcript exporter with visible classification instead of leaking raw
[System] prompts.

* fix(apps): satisfy OpenClawKit periphery gate

Remove the dead visibleMessages projection (rows path replaced its
consumers) and annotate the provenance test-fixture initializer with the
repo-standard periphery:ignore rationale.

* fix(apps): refresh native i18n inventory after periphery cleanup
2026-08-11 14:47:19 -07:00
Peter Steinberger 627e83d4f7 fix(ui): effort slider matches selected level after model switches (#122125)
* fix(ui): align effort picker after model switches

Publish ordered per-model effort profiles from the Gateway and reconcile new-session effort overrides so labels, slider positions, and create payloads stay consistent.

* fix(ci): align model profile contracts
2026-08-11 13:14:11 -07:00
Peter Steinberger 73ae583263 refactor(tasks): simplify subagent activity tracking (#122198)
* refactor(tasks): simplify subagent activity tracking

* fix(android): single-source subagent activity expiry clock

* chore(i18n): refresh native source baseline
2026-08-11 12:30:49 -07:00
Peter Steinberger 5179e12352 fix(macos): deliver provisional notifications (#122179)
* fix(macos): accept provisional notifications

* fix(macos): return notification permission labels

* fix(macos): preserve notification inventory
2026-08-11 11:42:06 -07:00
Peter Steinberger 1dcac5b15f fix: open terminals no longer delay gateway updates (#121601)
* fix(gateway): allow updates with open terminals

* fix(updater): support terminal policy upgrades

* chore(plugin-sdk): refresh API baseline
2026-08-11 09:37:58 -07:00
Peter Steinberger 1383144b02 test(macos): remove private helper mirrors (#122081)
* test(macos): remove private helper mirrors

* test(macos): cover voice transcript finality directly
2026-08-11 09:14:38 -07:00
Patrick Erichsen ad704f35c4 fix(control-ui): hide unusable models from picker (#121852)
* fix(ui): hide unusable models from picker

* refactor(ui): remove stale model availability helper

* refactor(ui): simplify catalog state guards

* style: format provider catalog imports

* chore: refresh plugin SDK API baseline

* refactor(core): break provider catalog type cycle

* chore(protocol): refresh models list Swift output

* chore: refresh plugin SDK API baseline after rebase

* fix(gateway): preserve full catalog preload semantics

* fix(ui): keep model status within startup budget

* fix(ui): preserve provider status within startup budget

* fix(models): scope live catalog outcomes

* test(ui): expect agent-scoped model refresh

* test(ui): align model refresh e2e fixtures
2026-08-11 09:13:44 -07:00
openclaw-mantis[bot] 6e9e569243 chore(i18n): refresh native locales (#121939)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-11 09:10:15 -07:00
Pavan Kumar Gondhi 8862cc46b3 fix(ios): harden share relay persistence (#121900)
* fix(ios): harden share relay persistence

* fix(ios): make relay migration transactional

* fix(ios): make relay migration host-owned

* fix(ios): reject legacy auth in share extension

* fix(ios): reject failed relay credential migration

* style(ios): fix relay settings indentation
2026-08-11 18:46:34 +05:30
Peter Steinberger a96fba6ff6 test(ios): remove preview source mirrors (#121960) 2026-08-11 02:03:07 -07:00
Peter Steinberger df72781ed4 fix(macos): make the whole AI candidate row clickable and clear stale exhausted verdicts (#121928)
* fix(macos): make the whole AI candidate row clickable and clear stale exhausted verdicts

Live-testing pick-during-testing on 2026-08-11 showed clicks on a candidate
row's blank stretch (between the title/subtitle texts or over the spacer)
silently doing nothing: plain-style buttons only hit-test opaque label
pixels. A user trying to pick Claude Code while Codex auto-tests can click
the visually highlighted row and get no outcome. .contentShape(Rectangle())
makes the full row hit-test.

Also, after auto-candidates exhaust, a user-picked retest left the stale
"None of the found options worked" card up while the new test visibly ran;
userSelect now clears exhaustedAutoCandidates when a fresh attempt begins.

* test(tooling): drop stateless poll tests from stateful-helper fixtures

Main went red when #121923 rewrote the outbound poll tests to be
order-independent and removed their stateful helper import/file; this
lane-config test hardcoded both as stateful-helper classification
fixtures. Folded into this PR per red-main landing policy.
2026-08-11 01:10:12 -07:00
Peter Steinberger 7d647f6810 fix(macos): stop profile onboarding from promising refused attachment (#121614)
* fix(macos): align profile gateway onboarding ownership

Stop onboarding from advertising foreign profile listeners as attachable. Reuse the GatewayProcessManager PID ownership rule and preserve existing non-profile listener wording.

* chore(macos): refresh onboarding i18n inventory
2026-08-11 00:26:46 -07:00
Peter Steinberger ea06d72e85 feat(secrets): manage team secrets in Control UI (#121724)
* feat(secrets): add gateway store settings

* perf(control-ui): trim secrets startup copy

* perf(control-ui): reduce secrets startup payload

* fix(secrets): harden store mutation refresh

* perf(control-ui): meet secrets startup budget

* test(control-ui): update secrets navigation copy

* fix(ui): pluralize secret-detection count and drop duplicated dialog hint

* chore(protocol): regenerate gateway clients and SDK baseline after rebase

* fix(gateway): merge secrets store methods after project RPCs in advertised order

* chore: leave changelog to release generation

* test(gateway): retain desktop launch train coverage
2026-08-11 07:20:38 +00:00
Peter Steinberger 79dcf48434 test(macos): remove stale Canvas helper probes (#121866) 2026-08-10 22:12:49 -07:00
Peter Steinberger 4b46a14a54 feat(apple): show live subagent activity in chat (#121815)
* feat(apple): show live subagent activity in chat

* chore(apple): refresh native localization inventory
2026-08-10 21:50:13 -07:00
Josh Avant 73a9eed95b refactor(audit): add canonical admitted-run context (#120534)
* feat(audit): carry canonical admitted execution context

* fix(agents): preserve admitted context across retries

* fix(worker): fence legacy launch dialect

* test(gateway): track approval temp dirs

* fix(plugin-sdk): preserve harness attempt compatibility

* fix: close delegated run authority at owner boundaries

* fix: internalize delegated authority validators

* refactor: split delegated authority proof surfaces

* refactor: centralize command admission identity

* test: claim runtime tool authority

* fix(gateway): keep lifecycle cleanup within static budgets

* fix(agents): revalidate harness policy authority

* fix(agents): fence awaited approval capability results

* test(copilot): supply required harness capability fixtures

* fix(agent): preserve scoped embedded run admission

* fix(agent): preserve keyless and worker authority

* test(agent): bind incomplete-turn authority

* docs: preserve execution authority invariants

* chore(plugin-sdk): regenerate API baseline

* fix(gateway): notify pending claim closure

* fix(gateway): revalidate delegated tool authority

* fix(plugin-sdk): keep source guard internal

* fix: close delegated authority races

* fix: revalidate delegated side effects

* fix: close harness authority projection gaps

* fix: align authority integration types

* fix: isolate settled harness finalization

* fix: fence recovery identity finalization

* fix: preserve committed session worktrees

* fix: preserve worker placement agent identity

* fix: fence active harness tool work

* fix(plugins): restore embedded run admission owner

* chore(plugin-sdk): compose integrated surface budgets

* fix(copilot): keep finalization attempt type internal

* fix(plugins): complete admission owner type imports

* test(harness): use settled finalization attempt shape

* fix(security): retain exact side-run and approval authority

* fix(security): preserve protected authority through terminal sweep

* fix(agents): follow moved recovery store owner

* fix(ci): align integrated authority owners with gates

* fix(plugins): distinguish embedded agent adapter export

* chore(plugin-sdk): regenerate API baseline after rolling integration

* refactor(gateway): keep session authority within owner budgets

* fix(gateway): keep session helpers private

* docs(plugin-sdk): name the V2 parameter subpath

* chore(integration): reconcile worker and SDK surfaces

* docs(plugin-sdk): require the V2 host API floor

* chore(plugin-sdk): regenerate after proxy-auth integration
2026-08-10 23:15:20 -05:00
Peter Steinberger 8c3c8a2ab0 feat(android): show live subagent activity in chat (#121813)
* feat(android): show live subagent activity

* chore(android): mark task event handled

* fix(android): localize activity diff chips

* fix(android): reconcile dropped task activity
2026-08-10 21:08:44 -07:00
Peter Steinberger b5d5ec340f feat(cloud-workers): add desktop apps and browser autonomy (#121475)
* feat(cloud-workers): add desktop apps and browser autonomy

provider-attested Browser/Terminal launchers, shared visible loopback CDP Browser tool, no MCP/cookies/generic command.

* feat(ui): add cloud desktop app launcher

* docs(gateway): document cloud desktop apps and browser autonomy

* perf(ui): trim desktop launcher startup copy

* refactor(ui): simplify desktop launch feedback

* perf(ui): reuse desktop app labels

* fix(ui): keep desktop launch failures actionable

* fix(crabbox): allow browser bootstrap to finish

* fix(cloud-workers): honor provider provision budgets

* fix(cloud-workers): persist browser screenshot receipts

* fix(cloud-workers): bound browser screenshot lifecycle

* fix(cloud-workers): avoid replaying desktop launches

* test(cloud-workers): isolate browser runtime integration

* refactor(cloud-workers): tighten desktop runtime boundaries

* test(cloud-workers): keep browser runtime mock synchronous

* fix(cloud-workers): break gateway type import cycle

* fix(ci): settle admitted setup sessions in tests

* build(plugin-sdk): refresh desktop app contract

* ci: refresh merge-tree validation

* build(plugin-sdk): regenerate desktop app baseline

* style(gateway): format merged method order test
2026-08-10 20:31:07 -07:00
Peter Steinberger 69220fc0d4 test(macos): remove body-only view probes (#121820)
* test(macos): remove body-only view probes

* test(macos): drop retired i18n wrapper contract
2026-08-10 20:26:56 -07:00
Peter Steinberger b985d5a1ed feat: stream live subagent progress in task events (#121549)
* feat(tasks): stream live subagent activity

* fix(tasks): correlate edit activity from start events

* fix(gateway): sanitize live task activity

* test(reply): align custody harnesses with lifecycle

* fix(outbound): preserve post-send recovery evidence

* fix(types): align reply harnesses with current contracts

* fix(tasks): preserve activity liveness and SDK parity

* test(sdk): avoid unsafe task summary assertion

* chore(contracts): refresh Plugin SDK API baseline
2026-08-10 18:37:58 -07:00
Peter Steinberger 32894a3ba5 feat: start sessions from registered projects (#121465)
* feat(gateway): add project registry sessions

* fix(gateway): authorize project branch discovery

* test(gateway): reuse worktree test imports

* fix(protocol): register projects schema owner

* fix(gateway): gate project paths by write scope

* feat(control-ui): register projects from folder browser

* refactor(gateway): extract session diff baseline preparation

* fix(gateway): honor admin scope in project listings
2026-08-10 17:56:12 -07:00