4498 Commits
Author SHA1 Message Date
Peter SteinbergerandGitHub f06b6be182 feat(macos): manage Gateway profiles and multiple windows (#111986)
* feat(macos): manage gateway profiles and windows

* fix(macos): preserve gateway settings localization

* fix(deps): update axios past security advisory
2026-07-20 18:10:02 -07:00
Josh AvantandGitHub 33720886c8 fix(agents): keep sender-scoped tools in delegated runs (#110345)
* fix(agents): preserve requester policy across delegation

* fix(agents): keep policy types internal

* test(codex): cover delegated policy forwarding

* fix(agents): harden delegated policy contract

* fix(agents): preserve split-owner completion policy

* fix: version delegated requester snapshots

* fix: refresh delegated policy protocol artifacts
2026-07-20 19:42:06 -05:00
Peter SteinbergerandGitHub 49ff6a4497 fix(protocol): classify system agents in rosters (#111920)
* fix(protocol): classify system agents in rosters

* fix(ci): align agent kind client gates

* fix(ci): keep roster filtering in startup bundle

* chore(ui): remove superseded roster module

* style(android): satisfy agent kind test formatting

* style(linux): format merged agent capability assertion

* fix(config): reject reserved system agent ids

* chore(i18n): refresh native source inventory

* style(android): format agent kind surfaces

* fix(gateway): preserve configured agent ownership
2026-07-20 16:57:04 -07:00
Peter SteinbergerandGitHub d5a8233e76 feat(gateway,ui): agent-scoped model provider credentials (#111796)
* feat: scope model provider credentials by agent

* fix: reject unknown model auth agent ids

* fix: discard stale model provider preload

* fix(gateway): reject whitespace-only explicit agent ids

* fix: scope model provider probes by agent

* fix: complete model provider agent scoping

* fix(ui): always clear the providers refresh flag on completion

* fix(ui): keep probe epochs monotonic across agent switches

* fix: derive agent scope for provider aborts

* fix: satisfy model provider CI checks
2026-07-20 16:22:09 -07:00
Colin JohnsonandGitHub 0d3cbae6a1 fix(ios): sidebar drags jitter and toolbar control flickers (#111831)
* fix(ios): smooth sidebar gestures and toolbar controls

* fix(ios): keep sidebar edge gesture below toolbar

* chore(ios): refresh native localization inventory

* fix(ios): preserve edge content interactions

* fix(ios): restore smooth sidebar tracking

* test(ios): align drawer source guards
2026-07-20 17:26:17 -04:00
Peter SteinbergerandGitHub a52eb2134b feat(apps): connect multiple gateways simultaneously (#111932)
* feat(apps): support simultaneous gateways

* fix(apps): satisfy multi-gateway checks

* chore(apps): refresh multi-gateway baselines

* style(android): format gateway fleet code
2026-07-20 13:06:29 -07:00
Peter SteinbergerandGitHub ba3711bb82 feat(linux): render widgets in Quick Chat (#111933) 2026-07-20 11:56:03 -07:00
Peter SteinbergerandGitHub 38df399ed8 fix(macos): show local ClickClack session discussions (#111883)
* fix(macos): show local ClickClack session discussions

* fix(macos): support loopback aliases in discussion embeds

* fix(macos): allow trusted hosted ClickClack embeds

* fix(macos): trust only dashboard-initiated discussion frames
2026-07-20 09:33:27 -07:00
ec9bc46e80 Wear: animate Talk avatar from playback audio (#111516)
* Wear: animate Talk avatar from playback audio

* fix(wear): preserve PCM mouth frame continuity

---------

Co-authored-by: Colin <colin@solvely.net>
2026-07-20 12:33:09 -04:00
Peter SteinbergerandGitHub 154a49a78b feat(dashboard): widget capabilities — net CSP, host tools, hardened shared sandbox (#111687)
* feat(boards): enforce widget capability grants

* feat(ui): expose dashboard widget capabilities

* test(dashboard): align rebased gateway contracts

* refactor(dashboard): finish capability alignment

* chore: internalize unused board sandbox exports

* test(dashboard): bind grants to widget instances

* fix(dashboard): close widget authority lifetime gaps

* refactor(ui): preserve modular widget frame ownership

* test(ui): preserve explicit MCP App lease refresh

* test(ui): use shared dashboard sandbox server

* fix(ui): settle widget requests on reconnect

* fix(ui): retry transient widget document loads

* refactor(dashboard): document WebRTC egress residual

* fix(dashboard): clear landing checks
2026-07-20 06:54:44 -07:00
Colin JohnsonandGitHub 2f967bc8f3 test(ios): refresh chat voice and sidebar UI coverage (#111655) 2026-07-20 08:02:16 -04:00
Peter SteinbergerandGitHub 7defd4a7b4 refactor(android): split offline client databases (#111710)
* refactor(android): split offline client databases

* chore(android): refresh native i18n inventory

* test(gateway): close databases before transcript cleanup
2026-07-20 02:28:02 -07:00
Peter SteinbergerandGitHub 248726fafd feat(anthropic): import Claude Desktop custom groups (#111644)
* feat(anthropic): import Claude Desktop custom groups

* fix(anthropic): resolve Claude Desktop groups from LevelDB entries

Group discovery regexed whole decompressed blocks, so matches were not
attributable to a Local Storage value and byte order decided the winner.
On a real 5.4MB store that mislabelled 59 of 159 sessions, surfacing a
mojibake label spliced out of Snappy copy-record bytes.

Parse SSTable entries properly instead: prefix-delta keys bounded by the
restart array, newest internal sequence per user key (honoring deletions),
and record scanning confined to a single value. Values are normalized so
Chromium's UTF-16 form scans like Latin-1, and unflushed WAL writes keep
precedence over SSTables.

Prod LOC grows ~77; it buys structural correctness in place of ordering
luck, and folds the old index-only walk into one shared entry decoder.

Verified against the live store: 159 assignments, 0 mislabelled versus an
independent entry-level ground truth, 0 control-character labels.

* fix(ui): sort custom session groups ahead of project groups

Custom groups were pushed into the section list as encountered, so their
position depended on roster order rather than the documented behavior;
the existing test only passed because its fixture happened to be ordered
that way. Collect custom and project groups separately and concatenate,
and assert the guarantee with a reversed-input case.

* fix(anthropic): widen LevelDB fixture key type for test typecheck

The prefix-delta helper assigned a Buffer into a Buffer-typed accumulator
whose generic argument differed, which tsgo rejects in the test lane.

* chore(anthropic): drop release-owned changelog edit from the PR

CHANGELOG.md is generated at release time, so a normal PR must not carry
an entry. The release-note context lives in the feature commit message and
the PR body instead.
2026-07-20 00:30:37 -07:00
Jason (Json)andGitHub 6304a47762 feat(dashboard): harden MCP widget authority (#111679) 2026-07-20 00:32:02 -06:00
Peter SteinbergerandGitHub bdf71d7d98 refactor(apple): unify offline client databases (#111598)
* refactor(apple): unify offline client databases

* refactor(apple): remove dead cache APIs

* fix(apple): satisfy native storage gates

* fix(apple): sync generated localization catalog

* Revert "fix(apple): sync generated localization catalog"

This reverts commit d0f5e7b74932e98ccc5f1984840e8f9d545edc2d.

* fix(i18n): keep source validation pre-merge

* test(macos): isolate flaky suite state

* test(macos): isolate log locator on main actor
2026-07-19 22:14:12 -07:00
Peter SteinbergerandGitHub bc76bb8933 feat(agents): agent-controlled session status, attention, and TTL in the sessions tool (#111583)
* feat(agents): agent-controlled session status, attention, and TTL in the sessions tool

* feat(protocol): sessions.patch agent status fields and curated attention icon ids

* chore(protocol): regenerate bindings for agent-status patch fields, unexport internal cap

* chore(sessions): unexport internal agent-status TTL default
2026-07-19 21:01:09 -07:00
Peter SteinbergerandGitHub 64c82812a5 feat(dashboard): pinned MCP apps — board rendering, lease re-mint, durable tool grants (#111524)
* feat(boards): mint pinned MCP app views

* feat(ui): render pinned MCP apps on dashboards

* fix(dashboard): reconcile MCP app rebase

* fix(dashboard): align generated CI contracts

* test(gateway): record board.widget.appView release train

* fix(dashboard): revalidate pinned MCP app views
2026-07-19 19:51:26 -07:00
Peter SteinbergerandGitHub 0fff74c800 feat(ios): replace the tab bar with a black overlay sidebar (web parity + dashboard) (#111339)
* feat(ios): unify navigation on a black overlay sidebar and drop the phone tab bar

* test(ios): rework navigation tests and snapshot UITests for the sidebar shell

* chore(i18n): sync derived native catalogs for sidebar strings

* feat(ios): reveal the sidebar beneath a push-away rounded content card

* feat(ios): web-parity sidebar — agent switcher, pinned pages, sessions vocabulary, uniform content card

* chore(i18n): translate sidebar and session strings across native catalogs

* fix(ios): sidebar footer shows connection dot only when degraded, like the web

* feat(ios): sidebar toggle top-left with edge-swipe open; card surface owns the drawer chrome

* fix(ios): single sidebar refresh owner, alias-aware Home badges, RM tap-close, user pin order, drop vestigial idiom shims

* feat(ios): align sidebar with the mobile prototype — agent roster, theme-following palette, web session subtitles, row badges

* chore(i18n): translate agent roster and Recent strings across native catalogs

* feat(ios): frosted-glass agent picker with uniform drawer insets

* fix(ios): address sidebar review findings — settings toggle edge, per-agent scoping, alias-aware selection, cron paging, refresh cadence

* fix(ios): clear landing CI blockers
2026-07-19 14:50:39 -07:00
Peter SteinbergerandGitHub 06480d767c feat(dashboard): stitch session dashboards end-to-end — live provider, show_widget pin, board commands (#111218)
* feat(dashboard): pin canvas widgets through board domain

* feat(control-ui): wire session dashboards end to end

* fix(control-ui): preserve direct reset confirmation

* fix(control-ui): localize dashboard default tab

* test(dashboard): satisfy changed typecheck gate

* fix(dashboard): satisfy changed lint gate

* fix(dashboard): harden pinned widget lifecycle

* fix(dashboard): use extracted mock normalizer

* test(dashboard): reconcile hardened board admission tests

* fix(dashboard): align grant and canvas protocol requests

* fix(dashboard): preserve refresh and pin invariants

* fix(boards): treat missing board tables as empty on read-only paths

* fix(boards): accept read-only handles in board table probe

* fix(control-ui): preserve virtual board widget types

* fix(dashboard): align view types with protocol

* fix(dashboard): keep resolved board view typed

* chore(canvas): drop test-only html read wrapper

* chore(release): defer dashboard note generation

* fix(protocol): align board widget put params type

* fix(control-ui): preserve queued reset approval

* fix(control-ui): gate dashboard pinning capability

* chore(test): isolate dashboard capability fixture

* fix(control-ui): refresh dashboard pin affordance
2026-07-19 12:36:54 -07:00
Peter SteinbergerandGitHub 6d4082ef97 fix(ui): prevent unsafe custodian nudge answers (#111430)
* fix(ui): harden custodian nudge actions

* refactor(ui): split custodian page helpers

* fix(ui): classify custodian nudge delivery

* fix(ui): ignore stale custodian question replies

* fix(ui): restore rejected custodian questions

* fix(ui): preserve custodian wizard uncertainty

* refactor(ui): keep nudge text helper private

* test(ui): model uncertain custodian delivery

* fix(ui): scope delayed custodian dismissals

* fix(ui): retain in-flight custodian nudges

* fix(ui): block nudges during hosted wizard input

* chore(protocol): regenerate gateway models
2026-07-19 11:10:41 -07:00
50ce5dedea fix(android): improve Wear thread follow behavior (#111459)
* improve(android): move Wear agent, session, and model pickers to Home

* fix(android): improve Wear thread follow behavior

* fix(android): stabilize Wear thread follow lifecycle

* fix(android): keep streamed Wear tail visible

Co-authored-by: JARVIS-Glasses <whatsskilll@gmail.com>

---------

Co-authored-by: Colin <colin@solvely.net>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-19 10:54:10 -07:00
Peter SteinbergerandGitHub 197c4f5a04 feat: generic session discussion seam with Control UI panel (#111337)
* feat: add session discussion panel seam

* fix: keep discussion iframe cookie-capable and changelog release-owned

* test: cover cookie-capable discussion iframe sandbox

* fix: stretch discussion panel host so the embed fills the rail

* fix: keep provider failures retryable and probe discussion availability before showing the action

* fix: block same-origin discussion embeds, show action on catalog sessions, close stale panel on reconnect

* fix: scope discussion probes and panel callbacks to the issuing connection

* fix: dedupe in-flight discussion probes per session

* fix: retry superseded discussion probes and key-scope panel results

* fix: regenerate Swift protocol models and extend advertised-method expectations

* style: format chat-pane-header

* fix: regenerate Kotlin protocol models and date discussion methods in the 2026.7 train

* chore: restore release-owned changelog to main state

* chore: keep changelog untouched relative to merge-base
2026-07-19 09:47:47 -07:00
Peter SteinbergerandGitHub 1ef99e6dfb feat(agents): authoritative write diffs end to end (#111456)
* feat(agents): authoritative write diffs end to end

The write tool now reports what actually happened: no-op (changed:false),
created files (created:true with a bounded numbered diff), and overwrites
(created:false with a real old-to-new diff when the old content is
readable text within byte, line, and edit-distance budgets — unknown
removals are never fabricated). The gateway history projection forwards
the changed/created flags, the web and iOS write rows prefer the
authoritative diff and suppress the +N -0 stat when creation is not
proven, and the iOS transcript cache persists one bounded apply_patch
envelope so patch diffs survive cold opens.

* chore(i18n): sync native inventory
2026-07-19 08:48:26 -07:00
Peter SteinbergerandGitHub 8c7f09a3c4 feat(system-agent): durable rolling transcript with openclaw.chat.history (#111440)
* feat(system-agent): durable rolling transcript with openclaw.chat.history

* chore(ui): scanner-safe auth root in custodian session ownership key

* fix(system-agent): durable reset boundary for transcript seeding

* fix(ui): ownership-aware custodian session rotation with capability gating

* fix(ui): bounded history load and reconnect-safe transcript refresh

* fix(ui): keep unknown-outcome warning and event nudges across transport transitions

* fix(ui): flag-backed unknown-outcome warning independent of retry state

* fix(ui): armed ownership boundaries and abandon-before-rotate ordering

* chore(ui): localize the server-side sensitive mask in durable history

* fix(ui): repair rebase-dropped import and mock arity

* chore: gate fixes — void history handler, module-local transcript internals

* refactor(gateway): leaf history-turn contract to keep the module graph acyclic

* chore(gateway): stamp openclaw.chat.history with its introduction train

* test(gateway): record openclaw.chat.history in the 2026.7 train pin
2026-07-19 08:37:00 -07:00
metaforismoandGitHub a53461b2b1 fix(ios): render Markdown lists and thematic breaks (#111223) 2026-07-19 11:24:30 -04:00
Peter SteinbergerandGitHub da534dc506 fix(ios): harden Talk voice-session lifecycle from review (#111424)
- Close+clear the adopted logical voice session when a config/provider change
  invalidates a realtime prefetch (a live call is preserved); prevents the
  gateway rejecting a stale voiceSessionId resume under a new provider.
- Retry talk.client.close (0/500/2000ms) before forgetting the session, matching
  the web client, so a transient close does not orphan it until the 6h sweep.
- Surface exhausted transcript-persist failures through the session delegate so a
  dropped affirmation transcript no longer silently blocks spoken confirmation.
- Localize the "Confirmation needed" status through the presentation switches;
  add its native locale translations.
2026-07-19 07:01:28 -07:00
Peter SteinbergerandGitHub 4e008cd713 feat(ios): adopt Talk voice sessions (#111369)
* feat(ios): adopt Talk voice sessions

* docs(agents): fix unrelated red-main breakage in the landing PR

* chore(i18n): translate Talk voice-session strings across native locales
2026-07-19 06:28:18 -07:00
e24420bc1c fix(android): stabilize Wear realtime Talk audio and tool calls (#111033)
* fix(android): relay Wear realtime Talk tool calls

* fix(android): preserve Wear realtime audio streams

* refactor(android): share realtime agent coordination

Co-authored-by: JARVIS-Glasses <whatsskilll@gmail.com>

* fix(android): bound Wear realtime audio pipelines

Co-authored-by: JARVIS-Glasses <whatsskilll@gmail.com>

* fix(android): close realtime correlation races

Co-authored-by: JARVIS-Glasses <whatsskilll@gmail.com>

* fix(android): scope realtime correlation jobs

Co-authored-by: JARVIS-Glasses <whatsskilll@gmail.com>

* fix(android): bound Wear realtime audio work

Co-authored-by: JARVIS-Glasses <whatsskilll@gmail.com>

* fix(android): bound realtime run correlation

Co-authored-by: JARVIS-Glasses <whatsskilll@gmail.com>

* fix(android): stop stale Wear audio delivery

Co-authored-by: JARVIS-Glasses <whatsskilll@gmail.com>

* fix(android): track Wear playback per chunk

Co-authored-by: JARVIS-Glasses <whatsskilll@gmail.com>

* chore(android): refresh native i18n inventory

Co-authored-by: JARVIS-Glasses <whatsskilll@gmail.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-19 05:21:38 -07:00
Peter SteinbergerandGitHub 3b84a55d99 refactor(protocol): pre-publish cheat-window cleanup and vintage tracking (#111041)
* fix(codex): drain dynamic-tool handlers before side-thread cleanup

* refactor(protocol): rename question ids to questionId and flatten answer maps

* refactor(protocol): slim worker stack and unify session-catalog shapes

* refactor(protocol): delete dead public surface and polish packaging

* feat(protocol): track release-train vintage on gateway methods and schemas

* fix(apps): align question surfaces merged from main with reshaped protocol

* test(health): shape secret fixtures to scanner-safe token names

* test(health): use scanner-safe token fixtures

* fix(apps): align question surfaces merged from main with reshaped protocol

* fix(ci): prove reshaped protocol in shallow checks

* fix(ui): align sidebar question fixtures with protocol

* fix(apps): read flat Swift question answers

* fix(apps): align question surfaces merged from main with reshaped protocol

* fix(apps): refresh native question inventory

* fix(apps): align macOS snapshot fixtures with protocol

* fix(ui): align narration question fixture with protocol
2026-07-19 04:07:15 -07:00
Peter SteinbergerandGitHub 8178b3cc14 feat(clients): adopt model controls, session management, and keyboard history recall on iOS (#110831)
* feat(clients): adopt model controls, session management, and keyboard history recall on iOS

* chore(i18n): translate iOS adoption strings and realign locale artifacts

* refactor(clients): drop test-only group response inits flagged by the shared dead-code intersect

* chore: retrigger ci

* chore(i18n): resync inventory after voice-unification main rebase

* chore(i18n): resync inventory after main rebase

* chore(i18n): resync inventory after main rebase

* chore(i18n): realign locale artifacts after main rebase

* fix(clients): preserve native chat API and locale copy

* fix(ios): retain public session DTO initializers

* refactor(clients): delete test-only session DTO inits flagged dead instead of suppressing
2026-07-19 03:08:22 -07:00
Peter SteinbergerandGitHub 5c9916950e feat(gateway): watched sessions in presence with viewer facepiles (#111225)
* feat(gateway): expose watched sessions in presence

* fix(gateway): resolve concurrent watched-session rollbacks via in-flight state

* fix(ui): viewing CI conformance — lazy facepile, bindings, dead exports

* fix(ui): move viewer presence projection out of the startup chunk

* fix(ui): capture sessionKey before facepile filter closure
2026-07-19 02:53:19 -07:00
Peter SteinbergerandGitHub e0ecdc47be feat(chat-ui): tool-diff follow-ups — cached diffs, apply_patch, isError, long lines (#111326)
* feat(chat-ui): tool-diff follow-ups from PR review

Persist bounded applied-diff details in the transcript cache so cold
opens keep inline diffs; parse apply_patch envelopes into per-file diff
sections with stats; thread tool-result isError so failed calls suppress
proposal diffs and read as failures; replace per-line truncation with
horizontal scrolling for long diff lines.

* chore(i18n): sync native inventory for tool-diff follow-ups

* fix(chat-ui): render move-only patches and drop zero diffstats
2026-07-19 02:40:37 -07:00
Peter SteinbergerandGitHub b9fa1ffa27 feat(gateway): system change history RPC and Ask OpenClaw recent-changes panel (#111286)
* feat(gateway): system change history RPC and Ask OpenClaw recent-changes panel

* test(gateway): fix journal fixtures, split custodian page tests, refresh docs map

* chore: quiet lint on journal reader tests and custodian harness
2026-07-19 02:38:05 -07:00
Peter SteinbergerandGitHub b3bb40551b fix(mac): opening General Settings crashes in packaged app (#111300)
* fix(macos): package KeyboardShortcuts resources

* fix(macos): keep dependency patch whitespace-safe

* fix(macos): preserve locked Swift resolution

* fix(macos): guard Swift lock across builds

* fix(macos): simplify KeyboardShortcuts packaging
2026-07-19 02:30:49 -07:00
Peter SteinbergerandGitHub 8631832048 fix: workspace divergence no longer wedges cloud-worker sessions (#111244)
* fix(cloud-workers): resolve workspace divergence with keep-local conflicts

* fix: retain workspace conflicts during worker reclaim

* style: satisfy workspace reconciliation lint

* chore: defer cloud worker changelog to release

* refactor: split cloud workspace reconciliation modules

* fix: satisfy workspace module boundary checks
2026-07-19 01:49:35 -07:00
Peter SteinbergerandGitHub 59b2fbbb4b feat(ios): Talk camera flip control and mic input selection (#111044)
* feat(ios): add Talk camera flip and mic selection

* chore(ios): sync native i18n inventory and locale artifacts for talk camera/mic strings

* chore(ios): commit regenerated Localizable.xcstrings for new talk strings

* fix(ios): extract Talk composer controls

* chore(ios): resync native i18n inventory and locale artifacts atop landed Android entries

* fix(ios): repair Talk composer CI checks

* chore(i18n): commit regenerated Android locale outputs from catalog reconciliation

* chore(i18n): sync Android locale outputs after rebase
2026-07-19 01:24:53 -07:00
Peter SteinbergerandGitHub 3a0d6b327b feat(chat-ui): inline diffs for edit and write tool rows (#111039)
* feat(chat-ui): inline diffs for edit and write tool rows

Port the web Control UI's kind-aware diff rendering to the shared SwiftUI
tool rows: persisted details.diff parses into numbered add/del/ctx lines,
edit/write/text-editor args fall back to a local capped line diff, the
collapsed row shows a +N/-M diffstat, and the expanded surface renders the
diff with the result summary or error diagnostic beneath it.

* fix(chat-ui): preserve tool-result details through message reconciliation

Canonical-adoption rebuilds enumerated message fields and silently dropped
details, so inline diffs vanished after cache-warm history reconciliation
(every app relaunch). Carry details through adoptingCanonicalMessage and
messageWithTimestampIfNeeded and lock it in with regression tests.

* chore(i18n): sync native inventory for tool diff rows

* fix(chat-ui): render diffstat and line numbers as verbatim text

* fix(chat-ui): use theme tokens for diff colors

* refactor(chat-ui): drop test-only parseDetailsDiff wrapper

* fix(chat-ui): address diff-row review findings

Interpret details.diff only for edit/write/patch tool names so plugin
detail schemas stay opaque; number write previews from line 1 with an
80-line cap and a subtractive char budget while keeping the exact stat;
bound per-line rendering to 2000 unicode scalars; announce add/del rows
and collapsed skip markers to assistive tech.

* chore(i18n): sync native artifacts for diff-row labels

* fix(chat-ui): announce diff line numbers to assistive tech
2026-07-19 01:21:51 -07:00
0f95e66b7f feat(talk): add durable client voice sessions (#111216)
Live-append voice transcripts into the agent session and persist a per-agent SQLite call record across relay and client transcript paths.

Add run-scoped spoken confirmation for high-impact actions, mutation digests, bootstrap-context injection, talk.client.transcript and talk.client.close protocol methods, and Control UI adoption. This adds zero new configuration.

Co-authored-by: Clifton King <clifton@users.noreply.github.com>
2026-07-19 01:06:49 -07:00
Peter SteinbergerandGitHub 83fc53a22f feat(android): approve, reject, and remove device pairings from the phone (#111014)
The Nodes & Devices screen showed pending pairing counts but pointed users
at a CLI command on the gateway host. An already-trusted phone can now act:
approve/reject pending requests (gated on hello methods plus the
operator.pairing or admin scope, mirroring the gateway's second
authorization gate for requested roles/scopes) and remove paired devices
(admin-gated, matching the gateway's removal contract). The confirm dialog
is the consent surface: it renders the complete requested roles/scopes
unbounded and scrollable with control/bidi sanitization, keyed to the
gateway identity so a pending confirmation cannot survive a gateway switch.
Mutations capture the gateway scope at claim time, require the exact write
acknowledgement plus a canonical device.pair.list readback before claiming
success, surface definitive gateway denials verbatim, and take over the
refresh generation with the verified snapshot so stale refreshes cannot
republish pre-mutation state. Bootstrap-requested scopes stay on the
canonical limited profile; extending it with operator.pairing is a
deliberate gateway-side product decision left open.
2026-07-19 01:03:45 -07:00
Peter SteinbergerandGitHub a8b7290f34 feat(gateway): durable user profiles with email aliases and avatars (#111224)
* feat(gateway): durable user profiles with email aliases and avatars

* fix(gateway): compress merge tombstones, content-hash avatar ETags, users CLI json output

* fix(gateway): lean profile listing, scoped avatar routing, typed email validation

* fix(gateway): protocol-complete profile payloads and consistent store reads

* fix(gateway): mark profile schema ensured only after commit

* fix(gateway): avatar endpoint HEAD support and RFC If-None-Match

* fix(gateway): profiles CI conformance — bindings, lint, knip, sql boundary

* feat(gateway): self-service profile edits for authenticated users

* fix(gateway): users.self bootstrap, tombstone-aware ownership, escaped CLI output

* fix(gateway): raw-DDL allowlist entry and lean profile exports
2026-07-19 00:58:43 -07:00
Peter SteinbergerandGitHub 33b50089cd feat(android): platform trust for public gateway certs and manual fingerprint pinning (#110976)
Publicly-CA-valid gateway hosts (e.g. Tailscale Funnel with Let's Encrypt)
no longer force fingerprint pinning: a real platform-trust handshake with
HTTPS hostname verification and SNI connects without prompting, ending the
changed-pin re-prompt on every cert renewal. Candidate gating excludes
.local, IP literals, and single-label hosts so LAN endpoints keep pinning.
Existing pins stay authoritative: a valid public chain never silently clears
a stored pin - the changed-pin prompt gains an explicit one-time 'Use system
trust' switch instead. Discovered endpoints still require a stored pin for
reconnect eligibility (discovery data is attacker-controllable). When the
TLS probe cannot capture a certificate, the trust dialog now accepts an
out-of-band SHA-256 fingerprint paste (sha256:/colon tolerant, 64-hex
validated) which is then enforced on connect. Malformed stored pins now
fail closed instead of silently degrading. Both probe attempts share one
connect+handshake budget so stalled hosts cannot double the probe latency.
2026-07-19 00:48:06 -07:00
Peter SteinbergerandGitHub 53d600ab83 feat(android): accept audio and document attachments via share sheet and composer (#110941)
* feat(android): accept audio and document attachments via share sheet and composer

Extends Android share-sheet intake beyond text/images: audio plus a curated
document set (PDF, OOXML, CSV, Markdown) with code-side mime enforcement,
provider-type revalidation while the URI grant is live, bounded streaming
reads, per-kind size budgets aligned with the outbox command limit, and a
document/audio picker in the composer. Share parsing moves off the main
thread behind a bounded slot queue; draft-not-autosend and drop/failure
reporting behavior unchanged.

* test(android): cover audio and document share intake

* test(android): align composer draft test with attachment kinds

* chore(android): refresh native i18n inventory

* chore(android): rebuild native locale artifacts for inventory order
2026-07-19 00:32:24 -07:00
Peter SteinbergerandGitHub c84a59284b fix(android): stop push-to-talk from dropping speech after mid-hold pauses (#110995)
* fix(android): stop push-to-talk from dropping speech after mid-hold pauses

The SpeechRecognizer PTT path ran one session with a 2.5s silence window,
kept only the last final, and never restarted during a hold - speech after
a mid-hold pause was silently dropped. Capture now uses an ordered rung
ladder: API 33+ app-owned AudioRecord piped via EXTRA_AUDIO_SOURCE with
EXTRA_SEGMENTED_SESSION, then silence-keyed segmented sessions, then a
restart-during-hold single-session fallback for older devices; failed holds
only descend. Final segments accumulate and merge locale-aware (no ASCII
separators after CJK/Arabic punctuation), with a trailing live partial
deduped against the last final. Release waits one bounded grace for the
terminal recognizer callback so late finals are not truncated; rapid
re-press drains the prior release instead of cancelling it; cancellation
mid-release still tears capture down, resumes realtime talk, and resolves
the stop payload. Raw-rung release also stops the recognizer since
EXTRA_AUDIO_SOURCE is optional and a service may run its own microphone.
Input level meters from our PCM stream in the raw rung where onRmsChanged
never fires.

* fix(android): API-33 recognizer extras behind RequiresApi and inventory refresh

Min-SDK lint (InlinedApi) flagged the API 33 RecognizerIntent extras; they
now live in RequiresApi(TIRAMISU) helpers behind explicit SDK gates, and
the native i18n inventory is refreshed for the moved lines.

* chore(android): rebuild native locale artifacts for inventory order
2026-07-19 00:13:19 -07:00
Peter SteinbergerandGitHub ccb147518c feat(agents): Swarm core — collector spawn, agents_wait, structured output, caps (gated) (#110932)
* docs: add Swarm implementation spec

* feat(agents): Swarm core — collector spawn, agents_wait, structured output, fastMode, caps

Implements docs/plan/swarms.md §4-6: tools.swarm config gate (default off),
collector-mode sessions_spawn (collect/outputSchema/fastMode/groupId), fail-closed
child approvals, agents_wait race-semantics tool, per-group FIFO scheduler with
maxConcurrent/maxChildrenPerGroup/maxTotalPerGroup caps, additive registry and
state-schema columns (no schema-version bump), and colocated tests.

Part of #110325

* fix(agents): rebase reconciliation — preserve swarm state columns

* fix(agents): O(1) collector session index, cheap-first preflight, collector start lifecycle hooks

Autoreview findings: replace the per-request full registry scan with an
index-maintaining run map and gate the persisted-store fallback behind
isSubagentSessionKey; emit subagent_progress/subagent_spawned from the swarm
scheduler start callback so collector children produce balanced plugin
lifecycle events.

* chore(protocol): regenerate Swift gateway models for swarm fields

* fix(agents): lint cleanup — typed catch, explicit microtask flush, no executor return

* fix(agents): knip/test-support/max-lines cleanup for swarm surfaces

* fix(agents): keep tool-catalog ui-safe — callers pass prepared swarmEnabled fact

resolveSwarmConfig value-import in tool-catalog dragged the server graph into
the Control UI bundle via tool-policy-shared (UNLOADABLE_DEPENDENCY on
subpath aliases). Catalog stays pure; the gateway tools-catalog handler
resolves the gate and passes the boolean.

* fix(agents): reconcile swarm spawn pipeline

* fix(agents): refresh swarm tool metadata

* fix(apps): sync swarm tool localization

* style(agents): compact tool display metadata

* fix(plugin-sdk): account for swarm config surface
2026-07-18 23:30:11 -07:00
Peter SteinbergerandGitHub 932e8be06c feat(agents): canonical agent creation with Custodian hatch flow (#111052)
* refactor(agents): centralize agent creation

* feat(ui): add new agent hatch flow

* refactor(agents): keep creation paths lean

* fix(agents): hide internal creation types
2026-07-18 22:50:02 -07:00
Jason (Json)andGitHub 2f7da3057c feat(mcp-apps): support bounded model context updates (#111212)
* feat(mcp-apps): support model context updates

* fix(mcp-apps): satisfy protocol and runtime guards
2026-07-18 23:08:35 -06:00
Peter SteinbergerandGitHub 649e94dd21 feat(apple): copy or save rendered widgets as images from the chat transcript (#110987)
* feat(apple): copy or save rendered widgets as images from the chat transcript

* chore(i18n): regenerate native locale artifacts for widget export strings

* chore(i18n): resync native locale artifacts after main i18n advance
2026-07-18 21:53:40 -07:00
Peter SteinbergerandGitHub c684b13213 feat(gateway): thread authenticated user identity into presence (#111179)
* feat(gateway): thread authenticated user identity into presence

* feat(gateway): regenerate Swift protocol bindings for presence user
2026-07-18 21:06:22 -07:00
Peter SteinbergerandGitHub b57660d024 fix(apps): call chat sessions threads (#111038)
* fix(apps): call chat sessions threads

* test(apps): update thread wording expectations

* fix(i18n): guard retained Android translations
2026-07-18 20:34:12 -07:00
Peter SteinbergerandGitHub 2f00a417ed feat(gateway): session dashboard domain — board RPCs, ticketed widgets, dashboard tool, per-agent persistence (#110960)
* feat(gateway): add session dashboard domain

* test(gateway): cover board event guards

* fix(gateway): authorize board widgets with view tickets

* feat(boards): persist dashboards in agent databases

* test(boards): use tracked SQLite temp directories

* test(gateway): isolate board deletion lifecycle coverage

* fix(boards): harden widget view ticket bindings

* fix(boards): lazily ensure additive board schema

* fix(gateway): complete dashboard integration metadata

* fix(boards): satisfy generated integration checks

* fix(boards): align persistence with repository guards

* fix(boards): retain notice test reset

* fix(protocol): generate dashboard union models

* fix(boards): harden dashboard persistence and serving

* fix(boards): satisfy dashboard CI guardrails
2026-07-18 20:17:51 -07:00