Commit Graph

999 Commits

Author SHA1 Message Date
Peter Steinberger 122fc1c786 fix(apps): render legacy plan events when the Gateway lacks the progress-card store (#125588)
* fix(apps): render legacy plan events when the Gateway lacks the progress-card store

progressCard.get ships in no released Gateway tag, so iOS/macOS on any current
release silently showed no status card after the durable-card migration. Restore
legacy stream:"plan" rendering, synthesized into the unified progress card and
gated on a tri-state capability probe so a dual-emitting Gateway never fights the
durable store. Mirrors the Android fix in #125444.

* fix(apps): invalidate progress-card capability on gateway route replacement

A replacement route may be a different Gateway, so a cached known-absent store
must not authorize the legacy plan fallback against a new Gateway that dual-emits
both sources. Clear and re-probe on .routeChanged.
2026-08-17 22:40:55 -07:00
Peter Steinberger 60920998c0 feat(apps): migrate iOS/macOS plan surface to the durable progress card (#125442)
* feat(apps): migrate iOS/macOS plan surface to the durable progress card

Replace the legacy stream:"plan" agent-event pipeline (runId-scoped state,
run-gated pill) with the sessionKey-scoped progress-card store: the shared
chat surface now renders progressCard.get snapshots, refetches on
progressCard.changed pokes with revision dedupe, clears on null-revision
pokes, and persists the card after the run completes. The card renders
markdown through the shared markdown view plus typed steps. Legacy Apple-side
plan handling (agent-event case, run-snapshot plan reconciliation,
OpenClawChatPlanStep parsing) is deleted; gateway emission stays for Android.
Removes the ios progressCard.changed coverage allowlist entry so the check
enforces the handler.

* chore(i18n): refresh native inventory for the progress-card rename

* fix(apps): keep the last progress card when a refresh fails

A transient progressCard.get failure no longer clears an already-rendered
durable card; only a successful null fetch or a null-revision poke clears it.
2026-08-17 18:07:17 -07:00
openclaw-mantis[bot] 5fe5d26007 chore(i18n): refresh native locales (#125353)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-17 11:00:25 -07:00
Vyctor H. Brzezowski f61ec66249 Preserve ClawHub external source identity and expose only supported actions (#124250)
* fix(skills): keep ClawHub search results on the source the operator picked

ClawHub search returns each result's origin under `install.reference`, but the
response model expected a flat `installRef`. That field is never present, so
every row fell through to a synthesized `@owner/slug` reference. External
skills.sh results were rewritten onto a ClawHub-native identity, dropping both
the commit-pinned source and the "not scanned by ClawHub" trust record.

Map the search wire shape explicitly and make the search contract
action-specific: `installRef` always names the result's own source, `detailRef`
appears only while ClawHub can serve a detail card for that identity, and
`trustState` travels with unscanned sources. Clients render install directly
when detail is absent instead of offering a review the Gateway must refuse.

Covers the Control UI, macOS, iOS Settings, iOS AgentPro, and Android, which
previously routed every row through review and could not install an external
skill at all.

* fix(skills): make install-only sources explicit and keep legacy review intact

Address review findings on the search identity contract:

- Replace the detail-reference capability with an explicit `installOnly` flag.
  A Gateway released before this field omits it, and reading omission as
  install-only made ordinary registry results skip the reviewed-version flow on
  every client. Absence now means the existing review-then-install path.
- Parse closed source variants in the producer. A row whose source is unknown,
  whose external reference is missing, or whose registry publisher is absent is
  dropped instead of falling through to `@owner/slug`, which was the original
  source swap in a different disguise.
- Carry the exact install reference alongside the canonical slug. The Gateway
  already records `requestedReference`; the clients dropped it and matched
  installs by slug, so a completed external install read back as unknown.
- Gate the direct-install action on admin rights. The row previously stayed
  enabled for read-only operators and reached a guard that silently returned.
- Route the unscanned-source warning through the native and Control UI string
  catalogs instead of a hardcoded literal.

* chore(i18n): leave generated native locale artifacts to the refresh workflow

Preflight isolates generated locale output from source changes: only the native
sources and apps/.i18n/native-source.json belong in a feature commit.

* fix(skills): satisfy Android ktlint wrapping and Swift test link construction

Extract the ClawHub result action guard into a named value so the multiline
condition follows ktlint wrapping, and pass the new requestedReference field in
the OpenClawKit installed-link fixtures.

* fix(skills): preserve external install identity across clients

* test(skills): add exact refs to recommendation fixtures

---------

Co-authored-by: Patrick Erichsen <patrick.a.erichsen@gmail.com>
2026-08-15 21:38:46 -07:00
Peter Steinberger 644d93c412 test(ios): remove low-value render and source guards (#124291) 2026-08-15 14:56:17 -07:00
Peter Steinberger 2d9a3f5849 test(ios): remove construction-only probes (#124205) 2026-08-15 09:47:47 -07:00
Peter Steinberger f916e690c0 test: remove UI and native test residue (#124152) 2026-08-15 04:08:22 -07:00
openclaw-mantis[bot] 2d322d1ae7 chore(i18n): refresh native locales (#124089)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-15 01:54:57 -07:00
ClawSweeper c12745429a fix(ui): fork active sessions from stable history (#123718)
* fix(ui): fork active sessions from stable history

* fix(protocol): align active fork types

* test(ui): match main-session fork routing

* fix(sessions): unify stable fork admission

* fix(native): fork active sessions from stable history

* fix(android): fork active sessions from stable history

* style(android): simplify active fork result handling

* fix(native): preserve legacy fork transport API

* test(native): complete legacy fork transport stub

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-08-14 14:13:25 -07:00
Peter Steinberger 703c681aac test: remove latest duplicate coverage (#123551) 2026-08-14 01:39:19 -07:00
Peter Steinberger 73e2489a5e test: delete final plugin and UI duplicates (#123214)
* test: delete final plugin and UI duplicates

* test(ios): remove duplicate watch reply case

* test(nostr): isolate ambient private key

Co-authored-by: Josh Avant <830519+joshavant@users.noreply.github.com>

---------

Co-authored-by: Josh Avant <830519+joshavant@users.noreply.github.com>
2026-08-14 00:20:09 -07:00
Peter Steinberger e5fca42952 fix(apps): per-session desktop button opens that session's machine (#123412)
* fix(apps): open session desktop on its machine

* fix(ui): scope the desktop session lookup to the key's own agent

`sessions.list` has no exact-key filter, so the viewer resolves a `session=`
parameter by searching for the key and matching it exactly in the response. A
key that prefixes longer ones — `agent:main:main` alongside user-named sessions
that start the same way — could push the exact row outside a five-row page and
silently fall back to the picker.

Session keys encode their agent and the list API accepts `agentId`, so scope the
search to that agent and widen the page.

* refactor(ui): stop parking a session key in the desktop environment id

Document-mode inventory failures stashed the requested session key in
`environmentId` purely so the Retry button's non-null guard would pass, even
though document-mode retry refreshes the inventory and never reads the value.
A session key only names a machine once the inventory loads, so it now stays
out of `environmentId`, and the retry branch that ignores it runs before the
guard. Adds E2E coverage for recovering a session-preselected desktop.

* fix(ui): resolve the desktop session with an exact-key lookup

The session-preselect path searched `sessions.list` and scoped the search to
the key's own agent, but a bounded search cannot rule a key out: 25 newer
same-agent sessions sharing the requested key's prefix would push the exact row
off the page, and the viewer would report the source as unavailable for a
session that exists. `sessions.describe` is the exact-key operation and already
projects placement, so the panel calls it directly and the app-root resolver
plumbing goes away with it.

* refactor(ui): move the desktop document keyboard bridge into its own controller

`desktop-panel.ts` crossed the 700-line cap. The mobile keyboard bridge — the
padded sentinel, the value diffing that turns composed input into backspaces
and text, and the field focus/reset helpers — is a self-contained concern, so
it moves into a `DesktopMobileKeyboard` controller alongside the existing
fullscreen controller instead of taking a `max-lines` suppression.

* test(ios): drain text fields instead of assuming a delete burst lands

`testReleaseChatScreenshot` typed a 5-character probe, sent 5 deletes in one
`typeText`, then asserted the field was empty. CI dropped one synthetic
keystroke under simulator load and the assertion failed with a leftover "f".
XCUITest makes no lossless-burst guarantee, so clearing now re-sends against
whatever the field actually still holds, bounded. The two gateway-setup fields
that overtyped through the same burst use the helper for the same reason.

* fix(ui): keep the chat placement owner out of the startup chunk

`desktop-document-mode.ts` is imported by bootstrap, so importing the chat
placement owner from it pulled the chat page's dependency tree into the startup
bundle and pushed startup JS past its gzip budget (331075 B against a 330507 B
allowance). The route module now only parses the URL; resolving a session to its
machine moves next to the lazily loaded desktop panel, which is the only caller.
Startup JS is back to 329710 B.
2026-08-13 23:33:19 -07:00
Peter Steinberger 2b61dc5429 fix(mobile): embedded Control UI follows the app's dark or light appearance (#123408)
* fix(mobile): sync Control UI webview appearance

* docs(android): explain why an appearance flip rebuilds the Control UI webview
2026-08-13 22:05:55 -07:00
Peter Steinberger edf1777ddb refactor(i18n): re-key native i18n artifacts to content-hash identity (v2) (#123347)
* refactor(i18n): re-key native i18n artifacts to content-hash identity (v2)

The native inventory stored a write-only 'line' field per entry, so any
unrelated edit above a string rewrote apps/.i18n/native-source.json
(~half of all commits touching it were pure line-number churn). Identity
was (surface, path, source), duplicating the same string per file
(5385 entries for 4187 unique pairs) and churning IDs on file moves.
Locale artifacts were positional arrays repeating full English source
text, so one inserted string rewrote diff spans in all 21 files.

v2 artifacts: inventory entries keyed by (surface, source) with merged
per-site {path, kind} lists and pure sha256 content-hash IDs; locale
files become id-keyed sorted translation maps. Existing translations
carry over by source match with a deterministic duplicate pick; the
sticky-ID reuse machinery and positional validation are deleted.
Everything under apps/.i18n plus generated platform locale artifacts is
marked linguist-generated. ci-changed-scope gains a one-time
owner-complete migration escape mirroring the control-ui precedent.

CLI surface (baseline/check/sync/verify) and the locale-refresh
workflow are unchanged.

* ci: register run-attempt-state test in its Vitest lane

Commit e04dfd26e2 added extensions/codex/src/app-server/run-attempt-state.test.ts
without a lane owner, so the full-suite ownership audit
(test/vitest-projects-config.test.ts) fails on main. Register it in the
attempt-light shard alongside its run-attempt siblings.
2026-08-13 19:39:32 -07:00
openclaw-mantis[bot] 9550d6f962 chore(i18n): refresh native locales (#123101)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-14 01:00:58 +08:00
Peter Steinberger 2a8b322ebf feat: view your machine's screen from the iOS and Android apps (#123097)
* feat(ui): add mobile desktop document mode

Add a shell-free mobile desktop route that reuses the dock panel controller and lazy noVNC client, with source preselection, touch controls, keyboard input, and retryable inventory failures.

* feat(ios): add desktop viewer entry points

* feat(android): add desktop viewer

* fix(android): keep System Back inside the desktop viewer

The per-session viewer replaces SessionDashboardScreen in place instead of
pushing a shell tab, so System Back fell through to the shell-level handler
and popped the whole Dashboard tab, stranding the operator on Chat. Claim
Back while the viewer is showing.

Also carry over TerminalSettingsScreen's imePadding: the viewer's own touch
toolbar hosts the keyboard affordance, so the soft keyboard would cover it.

Proof (emulator, Medium_Phone_API_36.0, stub control UI on 18789):
pre-fix Back from the viewer lands on Chat; post-fix it returns to Dashboard.
No Robolectric regression test — no existing screen test constructs
MainViewModel, and BackHandler under Robolectric would need new scaffolding
for weaker evidence than the live repro.

* test(ui): stop the pairing views leaking dialogs into the shared document

`ui/vitest.config.ts` runs the unit project with `isolate: false`, so test files
share one jsdom document inside a worker. `view.pairing.test.ts` appends a
container to `document.body` for every case and never tears down, unlike its
sibling `channels-page.test.ts`, so whichever suite the worker scheduled next
inherited a mounted pairing dialog.

That surfaced on this PR's first CI run as ten failures in the untouched
`input-dialog.test.ts`, which found "Approve DM access" where it expected
"Rename session". A rerun went green, so the ordering is scheduler-dependent
rather than deterministic; this removes the contamination source rather than
leaving the next suite to lose the race.

Not a proven fix for that specific run — the leak reproduces only under CI's
file scheduling, and the full suite passes locally either way — but the missing
teardown is a real violation of the shared-environment contract.

* test(ui): stop the background-tasks rail asserting on a ticking clock

The rail e2e captured the main transcript's text before opening a task detail
and required it to be byte-identical afterwards. A running task renders a live
elapsed label, so the assertion failed whenever a second ticked over between
the two reads — twice while landing this PR, both times "12s" against "13s"
with no other difference.

Normalize elapsed labels on both sides instead of weakening the assertion. The
invariant it protects, that opening a detail leaves the main transcript alone,
still holds: a real content change is still caught, and only complete duration
tokens collapse, so diffstat figures like +14/-3 and phrases like "5 messages"
are untouched.
2026-08-13 04:10:48 -07:00
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
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
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 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
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 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
Peter Steinberger 3156b67708 ci(labeler): fix dead rules, cover all plugin dirs, drop vendored artifacts (#121348)
* ci(labeler): fix dead rules and cover unlabeled plugin dirs

* chore: drop vendored swabble workflow and empty ActivityWidget asset catalog
2026-08-09 22:28:02 -07:00
Peter Steinberger d4fd9cc96a fix(ui): restore settings search, media previews, clipboard, and native chat (#116654)
* fix(ui): restore search media and native text

* fix(native): unify visible chat text projection

* fix(ui): search composed array schemas

* fix(ui): keep config search off startup constraints

* fix(ui): honor schema and media path boundaries
2026-08-09 22:07:28 -07:00
Peter Steinberger af708e6628 test(ios): trim duplicate root shell mirrors (#121272) 2026-08-09 16:53:04 -07:00
joshavant 59e4e31602 docs(ios): cut 2026.8.10 release notes 2026-08-09 17:45:22 -05:00
Peter Steinberger c70aee247e refactor(scripts): migrate JavaScript tools to TypeScript (#121005)
* refactor(scripts): migrate JavaScript tools to TypeScript

* fix(ci): keep changed-scope preflight zero-install

* fix(ci): preserve zero-install script owners

* fix(ci): complete script migration follow-through

* fix(release): keep stable closeout zero-install

* fix(scripts): preserve standalone execution boundaries

* fix(scripts): repair standalone loader boundaries

* fix(scripts): normalize gateway observation ids

* fix(scripts): keep Docker packager standalone

* test(scripts): preserve rebase cleanup helpers

* test(sessions): use tracked temp directory
2026-08-09 07:21:35 -07:00
Peter Steinberger 0dbce297fd test(ios): isolate TLS pin clearing (#113067) 2026-08-09 06:34:10 -07:00
Colin Johnson 5cd184c91b fix(ios): keyboard unavailable after tapping chat composer (#120723)
* fix(ios): restore composer keyboard focus

* test(ios): cover composer focus in screenshot CI

Co-authored-by: Colin <colin@solvely.net>

* test(ios): make composer focus proof device-aware

Co-authored-by: Colin <colin@solvely.net>

* fix(ios): stabilize sidebar layout under keyboard

Co-authored-by: Colin <colin@solvely.net>

* chore(ios): refresh native i18n inventory

Co-authored-by: Colin <colin@solvely.net>

* test(ios): keep focus proof in screenshot helper

Co-authored-by: Colin <colin@solvely.net>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-08-08 21:56:46 -07:00
joshavant 480e0c0060 docs(ios): cut 2026.7.23 release notes 2026-08-07 19:22:57 -05:00
openclaw-mantis[bot] a8f314d587 chore(i18n): refresh native locales (#120352)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-08 07:42:35 +08:00
joshavant ac2994a0e2 fix(ios): keep permission actions readable 2026-08-07 15:27:58 -05:00
joshavant 0bcbaf2eda fix(ios): remove permission pre-prompts 2026-08-07 15:27:58 -05:00
Peter Steinberger f96fc529c3 test(ios): consolidate talk config fixtures (#118533) 2026-08-02 23:42:06 -07:00
Vincent Koc a842f482d5 fix(ios): keep attachments in composer when route is unavailable (#116787)
* fix(ios): retain attachments when delivery route is unavailable

Refs #116724

* chore(i18n): refresh native source inventory
2026-08-03 12:53:48 +08:00
Peter Steinberger 43d9ba493d refactor(ios): remove redundant node test seams (#118387)
* refactor(ios): remove redundant node test seams

* fix(ios): keep approval route context private

* fix(ios): preserve routing task assertion

* fix(ios): retain private talk permission test seam

* fix(ios): retain operator options boundary
2026-08-02 21:44:45 -07:00
clawsweeper[bot] fa0e298d84 fix(ios): route forced realtime consults through Gateway relay (#117485)
* fix(ios): route forced realtime consults through Gateway relay

* fix(ios): route forced realtime consults through Gateway relay

* fix(ios): route forced realtime consults through Gateway relay

* fix(ios): route forced realtime consults through Gateway relay

* style(ios): drop redundant Self in requiresForcedAgentConsultRelay

* style(ios): use explicit self for firstString per swiftformat

---------

Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-08-02 18:06:19 -07:00
PollyBot13 d9669ce72c fix(ios): finish Calendar and Reminders grants without relaunch (#116504) 2026-08-02 18:01:41 -07:00
Peter Steinberger 079d26c92c test(ios): consolidate gateway connection fixtures (#118072) 2026-08-02 11:10:17 -07:00
Peter Steinberger a3bdc53a71 test(ios): deduplicate node invoke fixtures (#117670) 2026-08-01 16:07:19 -07:00
Peter Steinberger 9e43844264 build: generate native Canvas resources on demand (#117424) 2026-08-01 08:16:56 -07:00
Vincent Koc 7cc2e6d830 fix(ci): repair full release validation regressions (#117447)
* fix(worktrees): reject repositories without commits

* test(memory-wiki): allow agent isolation runtime

* test(ios): await queued approval retry
2026-08-01 14:55:13 +00:00
metaforismo 102a5915ef fix(ios): restore Magic Keyboard return in chat composer (#116042)
* fix(ios): restore hardware return in chat composer

* test(ios): cover hardware return composer flow

* fix(ios): route history keys through native editor

* fix(ios): satisfy composer lint gates

* test(ios): fix snapshot app lookup

* test(ios): keep snapshot helper nonthrowing

---------

Co-authored-by: Patrick Erichsen <patrick.a.erichsen@gmail.com>
2026-07-31 16:21:41 -07:00
Vincent Koc 20e68e01df fix(gateway): sign device proofs with challenge time (#116679) 2026-07-31 16:45:53 +08:00
Vincent Koc e460fcfb60 test(ios): remove duplicate deep-link coverage (#116657) 2026-07-31 12:16:40 +08:00
Vincent Koc 8a12343efe fix(ios): stabilize Apple UI validation across runtimes (#116487)
* test(ios): align source guards with current contracts

* test(ios): stabilize cross-version UI automation

* test(ios): harden typography boundary audit

* test(ios): synchronize deterministic UI launches
2026-07-31 01:30:46 +08:00
Peter Steinberger d962a3d9c1 fix(ios): avoid duplicate URLs in shared drafts (#116430)
* fix(ios): deduplicate shared URLs

* test(ios): prove share provider extraction
2026-07-30 09:09:35 -07:00