Commit Graph

1211 Commits

Author SHA1 Message Date
Vincent Koc
9fbe9abc86 fix(ci): restore Android CodeQL compatibility (#115095) 2026-07-28 11:24:22 +02:00
Vincent Koc
f8ed8ecf4f fix(security): harden CodeQL-reported boundaries (#115055)
* fix(security): harden CodeQL-reported boundaries

* style(android): fix WebMessage listener indentation
2026-07-28 16:47:12 +08:00
Peter Steinberger
4b05d83035 fix: generated images do not appear in native chat (#115042)
* fix(chat): render managed images in native clients

Co-authored-by: Francesco Giannicola <francescogiannicola1@gmail.com>

* chore: keep release changelog owned

* refactor(macos): split managed image loading

* test(apple): prove managed image header policy

* test(native): stabilize managed image proof

* test(apple): satisfy strict concurrency checks

---------

Co-authored-by: Francesco Giannicola <francescogiannicola1@gmail.com>
2026-07-28 04:39:53 -04:00
Vincent Koc
9000da0451 refactor(android): remove unused Wear voice button (#115061) 2026-07-28 16:19:34 +08:00
Vincent Koc
7838c6a6fd fix(apps): fence stale mobile delivery state 2026-07-28 08:15:52 +02:00
Peter Steinberger
a4d60af42b fix: sharpen working-claw silhouette into a toothed pincer (#114939) 2026-07-28 01:18:36 -04:00
Peter Steinberger
01f6ad67d5 chore(i18n): refresh native locale catalogs (#114915)
* chore(i18n): refresh native locale catalogs

* chore(i18n): sync native translation artifacts
2026-07-28 00:42:59 -04:00
Masato Hoshino
852120e724 fix(android): honor reduced motion reactively in mascot and talk waveform (#112687)
* fix(android): honor reduced motion reactively in mascot and talk waveform

OpenClawMascot and TalkWaveform read Settings.Global.ANIMATOR_DURATION_SCALE
with a one-shot remember(context){} that never reacts when the user toggles
"Remove animations" while the screen stays mounted. Extract the reactive
ContentObserver read that ChatWorkingIndicator already used into a shared
ui/SystemAnimations.kt helper and use it in all three surfaces. Follow-up to
#112245 (Wear avatar).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(android): resync the native i18n baseline after the animation refactor

The native-i18n check failed with "native app i18n inventory drift detected".

apps/.i18n/native-source.json pins a line number for each of its 5290 entries,
and 23 of them point into ChatWorkingIndicator.kt. Extracting the shared
rememberSystemAnimationsEnabled helper shortened that file by 26 lines, so every
recorded string below the edit moved and the inventory no longer matched.

Regenerated with `pnpm native:i18n:baseline`, as the failure message instructs.
The diff is 23 line-number updates (384 -> 358 and so on); no `source` value
changes, because this refactor adds and removes no user-facing strings.
`node --import tsx scripts/native-app-i18n.ts verify` now passes.

* fix(android): reuse Compose motion scale

Co-authored-by: Masato Hoshino <g515hoshino@gmail.com>

* fix(android): keep system motion scale authoritative

Co-authored-by: Masato Hoshino <g515hoshino@gmail.com>

* test(cli): raise root help deadlock guard

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-28 00:38:50 -04:00
NianJiu
aa26ecfac1 fix(android): Wear Talk works after exiting and reopening (#112383)
* fix(android): scope Wear Talk client to ViewModel

* test(android): exercise Wear ViewModel factory lifecycle

Co-authored-by: NianJiuZst <180004567+NianJiuZst@users.noreply.github.com>

---------

Co-authored-by: NianJiuZst <180004567+NianJiuZst@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-27 23:35:10 -04:00
dependabot[bot]
52bf653427 build(deps): bump the android-deps group across 1 directory with 5 updates (#113083)
Bumps the android-deps group with 5 updates in the /apps/android directory:

| Package | From | To |
| --- | --- | --- |
| [io.kotest:kotest-assertions-core-jvm](https://github.com/kotest/kotest) | `6.2.2` | `6.2.3` |
| [io.kotest:kotest-runner-junit5-jvm](https://github.com/kotest/kotest) | `6.2.2` | `6.2.3` |
| com.android.application | `9.3.0` | `9.3.1` |
| com.android.library | `9.3.0` | `9.3.1` |
| com.android.test | `9.3.0` | `9.3.1` |



Updates `io.kotest:kotest-assertions-core-jvm` from 6.2.2 to 6.2.3
- [Release notes](https://github.com/kotest/kotest/releases)
- [Commits](https://github.com/kotest/kotest/compare/6.2.2...6.2.3)

Updates `io.kotest:kotest-runner-junit5-jvm` from 6.2.2 to 6.2.3
- [Release notes](https://github.com/kotest/kotest/releases)
- [Commits](https://github.com/kotest/kotest/compare/6.2.2...6.2.3)

Updates `io.kotest:kotest-runner-junit5-jvm` from 6.2.2 to 6.2.3
- [Release notes](https://github.com/kotest/kotest/releases)
- [Commits](https://github.com/kotest/kotest/compare/6.2.2...6.2.3)

Updates `com.android.application` from 9.3.0 to 9.3.1

Updates `com.android.library` from 9.3.0 to 9.3.1

Updates `com.android.test` from 9.3.0 to 9.3.1

Updates `com.android.library` from 9.3.0 to 9.3.1

Updates `com.android.test` from 9.3.0 to 9.3.1

---
updated-dependencies:
- dependency-name: com.android.application
  dependency-version: 9.3.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: android-deps
- dependency-name: com.android.library
  dependency-version: 9.3.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: android-deps
- dependency-name: com.android.library
  dependency-version: 9.3.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: android-deps
- dependency-name: com.android.test
  dependency-version: 9.3.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: android-deps
- dependency-name: com.android.test
  dependency-version: 9.3.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: android-deps
- dependency-name: io.kotest:kotest-assertions-core-jvm
  dependency-version: 6.2.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: android-deps
- dependency-name: io.kotest:kotest-runner-junit5-jvm
  dependency-version: 6.2.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: android-deps
- dependency-name: io.kotest:kotest-runner-junit5-jvm
  dependency-version: 6.2.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: android-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-27 21:51:56 -04:00
Peter Steinberger
f85a458a45 refactor(mobile): consolidate native gateway and voice lifecycles (#114671)
* refactor(mobile): consolidate native lifecycle ownership

* fix(ci): cover Codex prewarm and chat lifecycle proof
2026-07-27 14:52:02 -04:00
Peter Steinberger
56d9802f6e fix(mobile): prevent stale reconnect, approval and voice cancellation (#114549)
* fix(mobile): fence reconnect, approval and voice cancellation

* fix(mobile): refresh native localization source inventory

* test(android): advance cancelled voice finalizer scheduler

* test(android): retain one approval during cancellation proof
2026-07-27 08:49:01 -04:00
Peter Steinberger
4aa96a118d fix(sessions): prevent stale and cross-agent observer status after reconnect (#114548)
* fix(sessions): prevent stale and cross-agent observer status

* fix(sessions): sync native observer source inventory

* fix(android): satisfy observer ownership formatting gate
2026-07-27 08:39:29 -04:00
Peter Steinberger
64bf485ba2 fix(sessions): scope observer state by agent 2026-07-27 05:43:19 -04:00
Peter Steinberger
6a3696000e fix(android): prefer selected observer owner 2026-07-27 05:43:19 -04:00
Peter Steinberger
51f228f6fe fix(ui): preserve agent-owned session navigation
Add agent ownership to observer digests, scope global observer delivery and reconciliation, and centralize application session selection across navigation and reconnects.

Co-authored-by: xbrxr03 <abrarhabib03@gmail.com>
2026-07-27 05:43:19 -04:00
Peter Lee
0406e66369 fix(ui): keep stable chat rows in insertion order and only sort live tool/stream items by timestamp (#113266)
* fix(ui): keep stable chat rows in insertion order and only sort live tool/stream items by timestamp

* fix(ui): keep live rows within current turn

* fix(ui): keep current work above queued turns

* fix(ui): keep streamed replies above queued turns

* fix(ui): preserve reconnecting run order

* fix(ui): preserve causal terminal ordering

* fix(ui): bound replay rows to owning turns

* fix(ui): keep question summaries in owning turns

* fix(ui): scope question run ownership to session

* fix(ui): restore reconnecting chat run identity

* fix(ui): remove unused chatItemTimestamp import in chat-thread-build.ts

* fix(ui): correlate question summaries with agent runs

Co-authored-by: Peter Lee <li.xialong@xydigit.com>

* chore(i18n): refresh native source baseline

Co-authored-by: Peter Lee <li.xialong@xydigit.com>

* fix(ui): remove unused chatItemTimestamp export and split tool-stream test file

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-27 02:08:22 -04:00
Peter Steinberger
852a686a1b feat(chat): restore prompt image attachments on rewind/fork (#113945)
* feat(chat): restore prompt image attachments on rewind/fork

* chore(i18n): refresh native source inventory anchors

* fix(gateway): restore media-store images on rewind/fork

* fix(gateway): bound and dedupe rewind media reads

* fix(sessions): bound inline editor attachments in message cut

* fix(ui): align restored attachment cap with gateway 5 MiB limit

* fix(gateway): dedupe rewind media refs by resolved id

* fix(sessions): lint-safe __openclaw access in message cut
2026-07-25 20:32:16 -07:00
Peter Steinberger
af44cb1a72 feat(native): show Swarm progress in chat (#113850)
* feat(native): show swarm progress

* fix(native): align swarm progress lifecycle

* chore(native): shorten swarm progress source name

* style(macos): pad swarm progress surfaces

* chore(native): use compact swarm source name

* fix(native): harden swarm route ownership

* fix(native): preserve swarm render ownership

* chore(i18n): refresh native swarm inventory

* fix(native): bound swarm refresh ownership

* fix(native): remove unused swarm capability initializer
2026-07-25 15:11:19 -07:00
Peter Steinberger
ce5ab8adb8 refactor(gateway): remove dead sessions.observer.ask rpc (#113791)
* refactor(gateway): remove dead sessions.observer.ask rpc

* docs: record btw and companion contract split

* fix(gateway): unexport observer model sanitizer after ask removal
2026-07-25 14:44:02 -07:00
Peter Steinberger
935ee7fedf fix(wear): keep active watch replies when older turns finish (#113804)
* fix(wear): preserve active replies when older turns end

* fix(wear): isolate terminal events at the watch

---------

Co-authored-by: Peter Steinberger <steipete@golden-gate.local>
2026-07-25 12:42:42 -07:00
Peter Steinberger
a95486cefc feat: session rail with read-only session companion in Control UI chat (#113698)
* feat(protocol): add session companion schemas

* feat(gateway): add session companion service

* feat(gateway): expose session companion rpc

* fix(gateway): harden companion runtime limits

* test(gateway): fix companion type assertions

* test(gateway): align companion test target

* feat(ui): replace observer HUD and side chat with session rail

* docs: session rail companion for control ui

* test(ui): align session rail client mock

* fix(ui): drop stale chat search import

* fix: satisfy session companion lint contracts

* refactor(gateway): isolate companion state contract

* fix(ui): keep session rail reachable while idle

* fix(agents): clamp derived openai prompt cache keys at boundary

* fix(ai): clamp chatgpt responses session_id affinity header

* fix(ci): align session companion branch gates

* fix(ui): require run id for sessionless terminal chat events

* fix(agents): scope internal run events to transcript

* chore: revert changelog edit (release generation owns changelog)
2026-07-25 08:14:32 -07:00
Peter Steinberger
53be78269e fix(android): connect to pasted manual gateway host and port (#113722)
* fix(android): preserve pasted manual gateway authorities

* fix(android): align gateway formatting and native i18n baseline

---------

Co-authored-by: Peter Steinberger <steipete@golden-gate.local>
2026-07-25 07:52:46 -07:00
Peter Steinberger
7e80f36723 fix(apps): restore live session updates after native reconnects (#113634)
* fix(apps): replay session visibility across native reconnects

* fix(apps): refresh shifted native i18n source lines

---------

Co-authored-by: Peter Steinberger <steipete@golden-gate.local>
2026-07-25 04:58:41 -07:00
Peter Steinberger
dd7f7ada7e feat(sessions): show preambles as live subtitles (#112958)
* feat(sessions): show preambles as live subtitles

* fix(sessions): harden preamble observer ordering

* fix(sessions): suppress duplicate preamble restore

* fix(sessions): preserve preamble observer lifecycle

* fix(ci): satisfy session subtitle checks

* fix(sessions): preserve terminal and preamble dedupe

* fix(sessions): finalize contextless terminal runs

* test(sessions): cover dormant contextless terminals

* fix(sessions): preserve queued preambles across dormancy
2026-07-25 01:26:50 -07:00
Vincent Koc
b3e3f06584 fix(i18n): correct Indonesian seconds labels 2026-07-24 17:17:56 +08:00
github-actions[bot]
2a465debe8 chore(i18n): refresh native locales 2026-07-24 17:17:56 +08:00
Vincent Koc
e3c2a8be58 fix(i18n): drop concatenated runtime prefixes 2026-07-24 16:29:32 +08:00
Vincent Koc
ac3eb02951 fix(android): avoid pluralized observation copy 2026-07-24 16:29:32 +08:00
Vincent Koc
6dbe278283 fix(android): allow post-merge flavor translations 2026-07-24 15:26:58 +08:00
Vincent Koc
2f85a77cc1 fix(android): localize accessibility executor UI 2026-07-24 15:26:58 +08:00
Vincent Koc
292cc5659d fix(android): localize recommended option labels 2026-07-24 15:26:58 +08:00
Peter Steinberger
90aee82793 feat(sessions): suggestion queue + typing indicator (#113173)
* feat(protocol): add session collaboration contracts

* feat(gateway): add session suggestion queue and typing

* feat(ui): add session suggestion controls

* fix(collaboration): restrict suggestion resolution

* fix(collaboration): dedupe suggestion dispatch modes

* fix(collaboration): preserve resolver identity

* fix(collaboration): reconcile suggestion state

* fix(collaboration): filter identityless suggestion events

* fix(ui): expose full suggestion text

* fix(collaboration): durably claim suggestion dispatch

* fix(collaboration): harden suggestion events and typing

* fix(collaboration): reconcile suggestion races

* fix(ui): reconcile suggestion capabilities

* fix(collaboration): close suggestion privacy races

* test(ui): satisfy suggestion lifecycle lint

* fix(collaboration): fence resolved suggestion events

* test(collaboration): type deferred audit result

* fix(collaboration): fence delayed typing events

* fix(ui): coalesce suggestion refreshes

* fix(ui): preserve resolved self suggestions

* fix(collaboration): enforce draft suggestion visibility

* fix(collaboration): fence post-dispatch finalization

* fix(ui): retain suggestions across visibility changes

* fix(collaboration): fence suggestion context and archives

* fix(collaboration): fence suggestion resolve lifecycle

* fix(collaboration): map suggestion replacement races

* refactor(gateway): extract session typing state

* fix(collaboration): integrate suggestion storage with session nodes

* refactor(gateway): extract session sharing snapshot cache

* fix(collaboration): satisfy protocol and deadcode gates

* fix(ci): register iOS release script entrypoints

* fix(collaboration): fence typing by session instance

* fix(collaboration): enforce incognito suggestion privacy

* docs(ui): clarify solo suggestion dormancy

* test(gateway): preserve incognito literal type

* test(gateway): split session typing coverage

* test(gateway): register collaboration method expectations
2026-07-23 18:59:58 -07:00
Peter Steinberger
3e2b3ea4d5 feat(cron): database-backed heartbeat monitor scratch replaces HEARTBEAT.md (#112967)
* feat(cron): move heartbeat context into database-backed per-job cron scratch

- new additive cron_job_scratch SQLite table (revision tombstones keep
  compare-and-swap monotonic across unset/recreate; 256KiB cap)
- heartbeat runner reads monitor scratch instead of workspace HEARTBEAT.md;
  heartbeat_respond gains a private scratch replacement parameter
- openclaw doctor --fix migrates HEARTBEAT.md into scratch (hash-verified,
  archived under state backups, idempotent, symlink-contained)
- gateway cron.scratch.get/set admin RPCs + openclaw cron scratch CLI
- workspace bootstrap no longer seeds HEARTBEAT.md; Codex heartbeat file
  guidance removed; docs and prompt snapshots updated

* fix(cron): review round 2 — shared-workspace heartbeat migration and non-default agent monitors

- doctor migration groups agents by heartbeat source file and imports into
  every monitor before archiving/removing the shared file once
- exempt heartbeat payloads from the main-session default-agent restriction:
  monitors only poke the wake bus, so non-default agents converge again
- document why disabled monitors retain their last cadence (config default
  already resolves before the fallback)

* fix(cron): honor configured cron store, legacy heartbeat fallback, and safer doctor claim

* fix(cron): claim HEARTBEAT.md before committing scratch and restore without clobbering

* fix(cron): pin migration CAS to precondition revision, re-verify claim on release, archive first, report scratch as pending

* docs(heartbeat): remove retired config options

* fix(cron): crash-recoverable migration claims, partial-import rollback, latest-response scratch pairing

* test(heartbeat): keep latest scratch proposal paired

* fix(cron): roll back committed scratch on changed-claim release and restore no-row state

* fix(cron): revision-guarded rollback delete and recreated-file detection on claim release

* fix(cron): treat every failed claim re-verification as a migration conflict

* test(heartbeat): rename ack test after ackMaxChars retirement

* fix(heartbeat): keep monitor scratch out of bypass-scope runs

* fix(cron): resolve claimed symlinks on release and gate legacy fallback on proven scratch state

* fix(cron): strict claim-name recovery and per-entry migration grouping

* fix(ci): heartbeat scratch gate repairs — lint causes, dead exports, since-train, inventory path, prompt snapshot, regenerated docs map, SDK baseline, protocol bindings

* fix(cron): live-owner claim guard and canonical entry-key migration grouping

* fix(cron): archive claimed inode on release and flag orphan claims beside recreated files

* docs(cron): document process-global state-db invariant for scratch service ops

* chore(i18n): refresh native inventory line numbers after protocol binding regen
2026-07-23 11:10:49 -07:00
Peter Steinberger
6251343384 feat(sessions): visibility states, membership, and server-enforced participation (#112787)
* feat(sessions): enforce visibility and membership

* feat(ui): add session sharing controls

* docs: add session sharing implementation report

* refactor(sessions): use canonical creator identity

* fix(sessions): adopt creator ownership contract

* docs: refresh session sharing rebase report

* docs: record final creator integration proof

* docs: record final main rebase

* chore: drop worktree report artifact

* fix(sessions): keep drafts owner-only

* fix(ui): preserve redacted session restrictions

* fix(sessions): preserve scoped sharing authorization

* fix(sessions): re-verify session instance inside sharing mutation queue

* test(sessions): cover stale sharing mutation

* fix(sessions): bind membership to session instance, gate absence blocking on sharing

* fix(sessions): preserve entry normalization on rebase

* fix(sessions): atomic visibility instance guard, reset visibility on recreate

* docs(ui): name the absence-heuristic tradeoff and link follow-up

* feat(protocol): expose session sharing row state

* docs: note generated creator identity type

* fix(sessions): bind member writes and visibility rollback to session instance

* fix(ui): discard stale-connection sharing loads; drop worktree scratch files

* fix(ui): block composer only on observed sharing state, never on list absence

* fix(gateway): authorize agent runs against the resolved session (close keyless bypass)

* chore(protocol): allowlist Control UI-only session.sharing event for mobile

* test(config): record session.sharing keys in common-tier snapshot

* refactor(sessions): unexport internal sharing helpers

* test(gateway): update sessions changed routing assertions

* fix(sessions): align sharing identity with created actor

* fix(sessions): align membership identities and storage keys

* fix(gateway): re-filter drafts against fresh sharing state in sessions.list

* fix(gateway): drafts stay owner+admin only in the sessions.list fresh filter

* fix(ui): re-export sharing protocol types for the Control UI

* fix(ui): keep SessionSharingRole internal to satisfy deadcode gate

* fix(gateway): read runtime config lazily in session-mutation authorization

authorizeSessionMutation ran on every gateway request but eagerly called
context.getRuntimeConfig() — a non-trivial config resolve — for methods that
are never session mutations. Read config only once a real session-mutation
target is resolved. Also register the four session sharing methods in the
2026.7 release-train inventory test.

* fix(gateway): share one config snapshot across session-mutation authorization

Group rename/delete discovery and the authorization loop were each resolving
runtime config separately after the lazy-read change. Memoize the resolve so
non-session requests still pay nothing, while any session mutation resolves
config at most once and both discovery and authorization use that single
snapshot (no double reload, no mid-request config-change split).

* fix(gateway): resolve session-sharing CI gates

- isGatewayAdmin: null-safe connect access so internal/plugin-runtime runs
  (which reach authorization with a connect-less client) do not crash.
- emitSessionsChanged: scope only to a concrete session key; a [undefined]
  sessionKeys scope filters nothing correctly and would strip draft gating.
- session stores: mark the sync TOCTOU re-read and the sqlite_master
  existence probe as narrowly-justified raw SQLite primitives.
- tests: provide getRuntimeConfig to the session-action contract context,
  drop a shadowed 'call' binding, use structuredClone, and assert the
  agent-scoped sessions.changed broadcast shape.

* docs(gateway): note best-effort participation gate + refresh native i18n baseline

Session ownership/visibility are usability features, not a security boundary
(docs/concepts/multi-user.md, SECURITY.md); document that the pre-dispatch
authorization is intentionally not commit-bound to the resolved instance.
Also refresh apps/.i18n/native-source.json after the session-sharing protocol
codegen shifted line numbers of existing native strings (position-only).

* test(gateway): reset session sharing snapshots

* style(gateway): format sharing reset import
2026-07-23 08:53:57 -04:00
openclaw-mantis[bot]
c5ea0787a2 chore(i18n): refresh native locales (#112803)
* chore(i18n): refresh native locales

* fix(i18n): correct native secret translations

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-23 00:56:26 -04:00
Peter Steinberger
c26b0e0843 feat(android): add OpenClaw settings chat (#112788) 2026-07-22 19:29:51 -04:00
WhatsSkiLL
b3752e375d feat(android): add Wear instant talk tile (#112721)
* feat(android): add Wear instant talk tile

* fix(android): preserve Wear screenshot warm launches

* fix(android): preserve Wear state on warm launch

---------

Co-authored-by: Colin <colin@solvely.net>
2026-07-22 19:28:41 -04:00
openclaw-mantis[bot]
a3a08a6db0 chore(i18n): refresh native locales (#112662)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-22 09:38:17 -07:00
WhatsSkiLL
80aaaeea3e fix(android): respect reduced motion in Wear avatar (#112245)
* fix(android): respect reduced motion in Wear avatar

* fix(android): observe effective Wear animation scale

* fix(android): refresh legacy Wear motion scale

* fix(android): initialize Wear motion scale before snapshot observation

---------

Co-authored-by: Colin <colin@solvely.net>
2026-07-22 09:22:29 -04:00
Peter Steinberger
0c99a4e362 feat(ui): manage DM pairing requests in Channels (#112401)
* feat(ui): manage DM pairing requests

* fix(ui): clear pairing data across auth changes

* test(ui): tighten pairing page fixture type

* fix(gateway): complete pairing protocol contracts

* fix(ui): guard pairing mutations across epochs

* fix(ui): restore chat teardown gates

* fix(ui): isolate channel auth lifecycles

* fix(ui): remove stale chat view export
2026-07-22 04:54:20 -07:00
Peter Steinberger
45f9da8535 test: stabilize Swift and Android coordination suites (#112628) 2026-07-22 03:36:17 -07:00
Peter Steinberger
92540b8735 feat(ui): redesign session observer HUD with labeled status and visibility-gated digests (#112594)
* feat(ui): redesign session observer HUD with labeled status and visibility-gated digests

* chore(protocol): regenerate app protocol bindings for sessions.observer.visibility
2026-07-22 02:56:10 -07:00
Peter Steinberger
0b080b9c2e feat(apps): native session-list observer digests on iOS, Android, and macOS (#112597)
* feat(apps): native session-list observer digests on iOS, Android, and macOS

* fix(apps): satisfy swift, periphery, and lint gates for native digests
2026-07-22 01:53:29 -07:00
Peter Steinberger
d899dd7682 feat(android,gateway): mobile.ui node commands (PR 2/3) (#112241)
* feat(android,gateway): expose mobile.ui.observe/act as node commands (PR 2/3)

Wire the PR1 AccessibilityService executor over the existing node.invoke
transport. Additive: no gateway protocol version bump.

- New commands mobile.ui.observe / mobile.ui.act (capability mobileUI),
  generated into the protocol constants.
- thirdParty MobileUiHandler owns one mutex-serialized AccessibilityActionExecutor
  and bridges JSON <-> the PR1 snapshot/action model; play flavor ships a
  permanently-unavailable no-op stub (Play APK stays accessibility-free).
- Commands advertised only when accessibilityControlEnabled and the service is
  connected; NodeRuntime refreshes the advertised surface on connect/disconnect.
- Classified dangerous in node-command-policy (declarable-but-armed, mirroring
  computer.act): the transport cannot invoke them until gateway.nodes.allowCommands
  explicitly arms them. Screen reads are treated as dangerous too, so observe is
  gated as well as act.

Both flavors assemble; thirdParty/play unit tests, ktlint, android lint, and the
gateway node-command-policy tests pass; protocol generator is idempotent; Play
APK verified to contain zero accessibility classes. Emulator: no regression to
PR1 dev-screen observe.

* fix(gateway): migrate mobile.ui arming test/comment to gateway.nodes.commands.allow

Main renamed the node-command arming config from gateway.nodes.allowCommands to
gateway.nodes.commands.allow; update the mobile.ui policy test config shape and
the comment to the current contract. Production resolution already reads the new
path.

* chore(android): update native i18n baseline for PR2 line-number shifts
2026-07-22 01:10:49 -07:00
Peter Steinberger
9c7b034005 feat(android): port the zen, drummer, and peekaboo claw stances (#112571)
* feat(android): add rare claw stances

* chore(i18n): refresh native source anchors
2026-07-22 01:09:08 -07:00
Peter Steinberger
12df806e90 feat(android): AccessibilityService UI executor (thirdParty, PR 1/3) (#112232)
* feat(android): AccessibilityService UI executor (thirdParty, PR 1/3)

Add a thirdParty-flavor-only AccessibilityService that observes the active
app's UI as a bounded semantic snapshot and performs typed actions, exercised
via a local developer screen. No gateway/agent wiring yet (PR 2 adds
node.invoke commands, PR 3 the agent tool + policy gates).

- Play APK stays accessibility-free: service, config, executor, and UI live
  entirely under src/thirdParty; SensitiveFeatureConfig.accessibilityControlEnabled
  gates it. Verified: 0 accessibility refs in every merged Play manifest and
  0 accessibility classes in the Play dex.
- Semantic-first executor: observe() returns a bounded snapshot (node/depth/text
  caps, deterministic order, password + sensitive-field redaction, stable action
  vocabulary, generation-scoped refs); act() performs one typed action with a
  closed ActionOutcomeCode result set.
- Safety model: coordinate gestures gated by package-match (fail-closed) + a UI
  epoch advanced on window/content/scroll/text mutation events; node actions
  gated by package-match + per-node refresh(); global actions ungated. Capture
  runs off the main thread. Dev UI honestly disables cross-app node controls
  (only reachable while the target is foreground; validated via the remote path).

Built and emulator-tested on API 36: live connection status, immediate observe,
a 103-node cross-app Settings capture, and global Home. Both flavors assemble;
thirdParty unit tests, ktlint, and android lint pass.

* feat(android): gate accessibility control behind an off-by-default opt-in

Make landing the accessibility feature a no-op for existing thirdParty users:
the service is invisible and inert until the user explicitly opts in.

- The AccessibilityService and its dev activity are declared
  android:enabled="false", so a fresh install exposes NO new accessibility
  service in system settings and nothing can bind it (verified on device:
  absent from the installed-services list and unbindable; shell cannot enable
  it either — only the app can).
- New thirdParty-only "Control other apps" toggle (persisted in the existing
  openclaw.node prefs, default OFF). Turning it on enables both components via
  PackageManager.setComponentEnabledSetting and deep-links to Accessibility
  settings so the user can grant it; turning it off disables them again
  (DONT_KILL_APP). A disclosure describes what enabling does.
- Play flavor is a no-op (FlavorPhoneCapabilitiesSettings = Unit); no
  accessibility component/controller/toggle references reach the Play APK.
- No new permissions or dependencies. The compile-time flavor gate and the
  gateway dangerous-command arming remain as additional layers.

* chore(android): update native i18n baseline for accessibility control strings
2026-07-22 00:36:13 -07:00
Peter Steinberger
1a8583ba45 feat(gateway,ui): ask-the-observer questions from the session HUD (#112448)
* feat(gateway,ui): ask-the-observer card input over sessions.observer.ask

* refactor(ui): single home for observer run-identity helper after restack

* test(ui): drop duplicated observer hud test after restack

* test(ui): give the observer ask flow its own colocated suite

* refactor(gateway): leaf observer contract and ask module split for ci gates

* refactor(gateway): drop observer contract re-export shims
2026-07-21 20:59:32 -07:00
github-actions[bot]
a8537805bd chore(i18n): refresh native locales 2026-07-22 10:22:42 +08:00
Vincent Koc
116a38c167 test(android): cover locale-neutral branch counts 2026-07-22 06:33:27 +08:00