Commit Graph

1371 Commits

Author SHA1 Message Date
openclaw-mantis[bot] 61bc753da3 chore(i18n): refresh native locales (#128759)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-24 08:21:09 -07:00
Kaneki ca3c3db1af fix(android): preserve capture dates and requested photo resolution (#125550)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-08-24 06:39:43 -07:00
WhatsSkiLL fb576e3518 feat(android): group sidebar sessions (#128092)
* fix(android): group drawer sessions

* fix(android): isolate generated locale files

* fix(android): hide empty sidebar groups

---------

Co-authored-by: IWhatsskill <284122573+IWhatsskill@users.noreply.github.com>
2026-08-24 06:34:42 -07:00
Peter Steinberger 0fbb5dd00e fix(android): normalize optional motion date ranges (#128734) 2026-08-24 06:29:54 -07:00
Peter Steinberger 898b1ce4b3 fix(android): fence canceled voice-note permission callbacks (#128733) 2026-08-24 06:23:17 -07:00
Peter Steinberger f90a9c720e fix(android): gateway accent color is fetched but never applied to the app theme (#128702)
* fix(android): apply the gateway accent color to the Claw design theme

The Android app fetched config.ui.seamColor into a StateFlow that no
Compose surface consumed, so gateway accents were silently dropped. The
accent now resolves with Control UI precedence (ui.prefs.accent over
ui.seamColor) and overrides the Claw accent/accentSoft/accentBorder
tokens in ShellScreen and OnboardingFlow; Material You system chrome is
untouched. With no gateway accent set the hardcoded ClawDark/ClawLight
palettes apply unchanged, replacing two mismatched hardcoded defaults.

* fix(android): invoke branding refresh on connect and match gateway accent precedence

ClawSweeper findings: refreshBrandingFromGateway had no call site (the
accent state stayed null), and a present non-string user accent must not
fall through to seamColor per the gateway's nullish selection. The
refresh now runs in the post-connection coroutine alongside wake-word
and exec-approval refreshes.
2026-08-24 05:42:56 -07:00
Peter Steinberger 234df15a6d chore: refresh dependencies after seven-day cooldown (#128414)
* build(deps): refresh dependencies after cooldown

Apply dependency, toolchain, action, image, and exact tool updates released by the inclusive 2026-08-16 seven-day cutoff. Adapt owner boundaries for the resulting CUA, logging, Teams, Markdown, native, and test-harness contract changes while retaining versions blocked by upstream compatibility constraints.

* fix(ui): align markdown renderer env typing

* fix(deps): align postcss and mistral peer contracts

* fix(deps): repair refreshed dependency contracts

* fix(deps): retain tslog startup budget

* fix(ci): verify Android tools with SHA-256

* fix(ci): fence Android SDK cache version
2026-08-24 03:01:54 -07:00
Peter Steinberger e834b355f2 fix(android): prevent expired subagent tasks from reappearing (#128612)
* fix(android): prevent expired subagent tasks from reappearing

Co-authored-by: 李琪0668001400 <li.qi16@xydigit.com>

* test(android): format subagent lifecycle assertions

* style(android): separate subagent lifecycle invariant comment

---------

Co-authored-by: 李琪0668001400 <li.qi16@xydigit.com>
2026-08-24 02:14:51 -07:00
Milton 9b2b195e10 fix(android): enforce location freshness across live updates (#128439)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-08-24 01:37:06 -07:00
Peter Steinberger 53dcaaedec feat(gateway): generic operator roles for non-maintainer access (#128548)
* feat(gateway): generic operator roles for non-maintainer access

Adds gateway.roles: named role bundles over a closed capability set —
sessions.others (none/view/suggest/write), an agents allowlist, and an
operator-scope ceiling. Roles are person-level (additive user_profiles.role
column, SQLite stays at v9); users.setRole (admin-only) assigns them. With
no gateway.roles config, behavior is unchanged for solo deployments.

Enforcement is deny-by-default from a host-minted actor identity
(system vs operator+profileId on server-only client.internal, never
accepted from the wire) and covers every entry point: WS RPCs, OpenAI-compat
and Responses HTTP, tools invocation, cron, questions, usage, task
suggestions, session catalog/sharing/reads. The agents allowlist gates both
session creation and run-start on existing sessions. Subagent completion
announce and descendant wake mint explicit system authority so role
boundaries never silently drop parent notifications.

The enforcement surface is expressed through a narrow policy vocabulary
(operatorSessionCap, hasOperatorBoundary, authorizeSessionSharing) rather
than per-handler policy internals.

* fix(gateway): heal PR CI after rebase onto main

- Break import cycles: extract GatewayOperatorRoleActor leaf contract; merge
  session-group-mutation-targets into session-sharing-target-input.
- Split sessions-suggestions.test.ts (max-lines) into a visibility suite.
- Add users.setRole to the 2026.8 train registry test and regenerate the
  Kotlin protocol client.
- Startup UNAVAILABLE gating now precedes session authorization: session
  stores are not loaded during startup, so authorization reads would deny
  with a misleading non-retryable error.
- sessions.assignOwner keeps its documented visibility-authorized contract
  when no operator role caps the caller; view/suggest-capped roles still
  cannot reassign foreign session ownership.
- Test stubs updated for main's socket readyState guard (#128144) and the
  system-authority arg on channel-native resets.

* test(gateway): chat.send pending-profile dispatch carries its required session target

chat.send requires a non-empty sessionKey at the protocol level; the mutation
pipeline now rejects targetless frames before profile-dependent dispatch, so
the pending-profile test must send a realistic frame.
2026-08-24 01:20:03 -07:00
Peter Steinberger 6530948812 fix(location): reject future-dated cached fixes (#128591) 2026-08-24 00:57:04 -07:00
Kaneki 444d79aea3 fix(android): normalize null calendar and contact write fields (#125527)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: 涧波 <jianbo@digitallifes.org>
2026-08-24 00:33:37 -07:00
hidenori-endo 10050cb07e fix(android): preserve channel sender labels across chat history (#119864)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-08-24 00:24:43 -07:00
Vincent Koc 9046ecea73 fix(talk): isolate cancellation ownership contract (#127186)
* fix(talk): isolate cancellation ownership contract

Co-authored-by: Zhilong Zheng <zhengzhilong1115@gmail.com>

* fix(talk): frame realtime relay output audio

Co-authored-by: Zhilong Zheng <zhengzhilong1115@gmail.com>

* fix(talk): confirm turn-bound provider cancellation

Co-authored-by: Zhilong Zheng <zhengzhilong1115@gmail.com>

* fix(talk): bind legacy iOS output cancellation

Co-authored-by: Zhilong Zheng <zhengzhilong1115@gmail.com>

* fix(talk): close cancellation ownership gaps

Drain dynamically arriving forced-consult results before terminal completion and validate legacy iOS cancellation responses against the active lifecycle.

Co-authored-by: Zhilong Zheng <zhengzhilong1115@gmail.com>

* fix(talk): require Android output identity for cancellation

Co-authored-by: Zhilong Zheng <zhengzhilong1115@gmail.com>

* fix(talk): bind Android cancellation to action turn

Co-authored-by: Zhilong Zheng <zhengzhilong1115@gmail.com>

* test(talk): align relay checks with current main

Co-authored-by: Zhilong Zheng <zhengzhilong1115@gmail.com>

* fix(talk): fence stale iOS output clear

Co-authored-by: Zhilong Zheng <zhengzhilong1115@gmail.com>

---------

Co-authored-by: Zhilong Zheng <zhengzhilong1115@gmail.com>
2026-08-23 03:58:00 -07:00
openclaw-mantis[bot] 0978e27f9d chore(i18n): refresh native locales (#127681)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-21 20:00:27 -07:00
WhatsSkiLL 407930cb6a feat(wear): add direct agent, session, and model pickers (#126863)
* feat(wear): add searchable context pickers

* fix(wear): simplify context picker rows

* fix(wear): prioritize chat actions over context

* fix(wear): keep chat follow above context controls

* fix(wear): keep context labels localized

* fix(wear): refine context picker layout and close

* fix(wear): sync picker locale resources

* fix(wear): negotiate picker search support

---------

Co-authored-by: IWhatsskill <284122573+IWhatsskill@users.noreply.github.com>
2026-08-21 11:54:47 -04:00
Vincent Koc 2405b98b05 fix(android): explicitly target notification intents (#127055) 2026-08-20 23:48:16 -07:00
Peter Steinberger f0881cfaa9 test: trim native test mirrors (#126896) 2026-08-20 17:41:18 -07:00
Dallin Romney d40cbfef47 chore(i18n): refresh native locales (#126696)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-20 09:06:59 -07:00
Peter Steinberger 1bf3e4e9b8 fix(android): gate gateway RPC polling on the hello method catalog (#126540)
* fix(android): gate gateway RPC polling on the hello method catalog

Released 2026.7.x gateways authorize before dispatch and reject unknown
methods with "missing scope: operator.admin", so the app's
"unknown method: X" detectors never fired: outbox sends parked forever
behind an ~800ms sessions.branches.list retry loop and question.list
retried on every health event. Generalize the progress-card negotiation
(3377a21c4e) into a tri-state gatewayAdvertisesMethod seam fed by
hello features.methods and skip sessions.branches.list, question.list,
and progressCard.get when the gateway does not advertise them; branch
scopes reconcile immediately and queued sends flush.

* fix(android): keep the hello method catalog unknown when hello omits features.methods

A successful connect without a usable features.methods list must not read
as a known-empty catalog: parse it as null so gatewayAdvertisesMethod stays
tri-state and the catalog gates no-op instead of skipping documented RPCs.
Pairing capabilities keep positive-advertisement semantics via orEmpty().
Addresses the ClawSweeper P1 on #126540.
2026-08-19 22:56:15 -07:00
Peter Steinberger 0a86702241 feat(github): authorize agent identities from Settings (#126474)
* feat(github): add device authorization lifecycle

* fix(github): harden device authorization lifecycle

* fix(github): refresh native tool display snapshot

* fix(github): refresh config and UI baselines

* refactor(github): break OAuth identity import cycle

* test: make gateway retry deadline assertion scheduler-safe
2026-08-19 17:41:58 -07:00
Peter Steinberger a3ca8466ee fix(ui): refresh device labels after rename (#126432)
* fix(ui): refresh device labels after rename

* fix(ci): classify device label refresh event for mobile

* chore(protocol): regenerate Android gateway events
2026-08-19 14:18:50 -07:00
Peter Steinberger 0606e31d0e feat(gateway): broker GitHub publication (#126306)
* feat(gateway): broker GitHub publication

* refactor(gateway): split publication owners

* fix(gateway): enforce publication branch authority

* fix(gateway): bind publication to remote identity

* fix(gateway): bind publication recovery to remote state

* fix(gateway): preserve publication git state

* fix(gateway): retain publication recovery authority

* fix(gateway): commit publication index atomically

* fix(gateway): narrow publication index errors

* refactor(gateway): keep publication CAS errors private

* fix(gateway): recover publication index transactions

* fix(agents): describe GitHub publication tool

* fix(gateway): harden publication base fetch

* fix(gateway): reject publication filter semantics

* fix(gateway): verify publication creation base

* refactor(agents): align publication tool options

* fix(gateway): isolate publication object lineage

* refactor(gateway): use shared table probe

* test(gateway): keep publication helpers in routed suite

* perf(ui): lazy-load GitHub publication request

* fix(gateway): preserve publication support contracts

* fix(gateway): recover publication before authority checks

* fix(gateway): fence local publication snapshots

* fix(android): format generated protocol models

* fix(gateway): harden publication recovery

* fix(gateway): fence publication recovery

* fix(ui): reset completed publication cycles
2026-08-19 11:05:12 -07:00
Peter Steinberger ae55a4090c refactor(canvas): make the panel a widget presenter (#126030)
* refactor(canvas): retire legacy host and commands

* refactor(apple): narrow shared Canvas contracts

* refactor(macos): keep Canvas as widget presenter

* refactor(ios): remove Canvas client

* refactor(android): remove Canvas client

* refactor(linux): remove Canvas client

* fix(ci): isolate native locale artifacts

* fix(linux): regenerate companion lockfile

* fix(canvas): refresh native tool display metadata

* test(canvas): align coverage with presenter surface

* test(canvas): remove obsolete asset root seam

* test(canvas): stabilize retirement CI coverage

* refactor(swift): remove orphaned resource wrapper

* test(ios): remove retired canvas layout assertion

* fix(macos): reserve retired canvas command namespace

* refactor(macos): isolate canvas command policy

* fix(canvas): select only eligible macOS panels

* fix(canvas): keep panel selection plugin-owned
2026-08-19 08:21:07 -07:00
Peter Steinberger 4af09d4961 feat(ui): unify focused presentation routes (#126143)
* feat(ui): unify focused presentation routes

/focus/<target> replaces unshipped standalone query links across dashboard, terminal, desktop, and native apps.

Gateway-served index assets are anchored so nested documents resolve their bundles from the Control UI base path.

* test(gateway): narrow emitted asset URLs

Fixes check:test-types TS18048/TS2322 by dropping unmatched optional captures before comparing emitted asset URLs.

* test(docs): follow centralized cloud secret guidance

Fixes the stale current-main docs test after #126132 centralized GCP and Hetzner setup in docker-vm-runtime.

* test(ui): retry missing locator reads

The 500ms locator text read can time out while the menu label is still rendering, causing expect.poll to reject instead of using its owning 10s retry window. Treat only Playwright TimeoutError as a missing value so the outer poll retries while page-closure and arbitrary failures still surface.

* test(android): capture TLS probe coroutine

The TLS probe test inferred its coroutine from mutable scope children, racing unrelated child startup and teardown in CI. Capture the exact Job from inside the probe coroutine and join that owner before asserting the stale-attempt guard.

* fix(gateway): preserve plugin focus routes

Keep approval handling ahead of plugin dispatch, but treat focus documents as an unclaimed Control UI fallback after plugin authentication and routing. Exact and prefix plugin routes therefore retain ownership, while unclaimed reads serve the focus document and other methods return 404.

* fix(ui): migrate released terminal links

Preserve stable v2026.7.1 terminal query compatibility by rewriting the root/base ?view=terminal URL once to the canonical /focus/terminal path with history.replace. Keep URL parsing path-only, and leave the removed desktop and dashboard query forms as a hard cut.

* test(codex): assign run-attempt tools shard

Cached filtered configs caused duplicate ownership, and the test lacked a canonical full-suite owner.

* test(ui): keep cloud recovery proof state-owned

The recovery test should assert owner state and reload identity, while dedicated tests own transient alert visibility.

* test(qa): wait for outbound bus state

* fix(qa): reserve gateway ports through staging

* refactor(qa): keep socket creation in gateway owner
2026-08-19 03:41:29 -07:00
Peter Steinberger e71fc902ee fix(gateway): make activeRunIds presence mean a complete exact run set (#126106)
* fix(gateway): make activeRunIds presence mean a complete exact run set

Session rows no longer emit activeRunIds: [] while hasActiveRun is
true. Presence now means the complete exact set of direct run ids;
omission means identities are unavailable (projected/embedded owners);
[] only ever represents proven idle. Consumers stop guessing:
soleActiveSessionRunId() replaces the arbitrary [0] fallbacks in the
observer digest, transcript cache key, activity inspector, and
stale-terminal reconciliation, each falling back to its owner fact.

Follows the maintainer direction from #125983: the field stays as
Gateway-owned exact facts; producer-side liveness/observer projections
are a named follow-up.

* fix(gateway): clear unavailable active run ids in events

* fix(gateway): preserve idle active run sets

* fix(clients): close active run id cache gaps

* test(android): isolate history run snapshot
2026-08-19 02:08:57 -07:00
Peter Steinberger 67750753a2 fix: capture GitHub identity from authenticated sign-in (#126114)
* fix: capture GitHub identity from authenticated sign-in

Automatically persist verified GitHub identities from Cloudflare Access and Tailscale Serve while keeping public Git co-author credit as a separate opt-in.

* test: stabilize cleanup and activity capture

* fix(security): bind GitHub profiles by account id

* test: scope activity capture to route

* fix(security): gate profile requests on identity sync

* fix(security): close pending profile authorization gaps

* test(ui): stabilize terminal continuation menu

* test: stabilize startup recovery timing

* test: keep one Codex attempt tools owner

* fix(plugins): allow profile-independent gateway reads
2026-08-19 01:35:52 -07:00
Peter Steinberger e15d5329fa fix(memory): scope Dream Diary requests to agents (#125936) 2026-08-18 11:54:58 -07:00
Peter Steinberger 4048ae26e0 feat: credit linked session participants as Git co-authors (#125827)
* feat: credit linked session participants as co-authors

Authenticated profiles can link GitHub and receive automatic co-author credit in shared coding sessions.

* style: format rebased co-author registries

* fix: mark profile schema DDL boundary
2026-08-18 07:15:01 -07:00
Dallin Romney c06f2e24d9 chore(apps): refresh native locale artifacts (#125608) 2026-08-18 07:05:02 -07:00
Peter Steinberger b8ff4fe3d7 fix: show sessions waiting for concurrency slots (#125654)
* fix: show sessions waiting for concurrency slots

* test: align queued session integration fixtures

* test: distinguish queued and reactivated followups

* fix: preserve queued state in workboard and android

* fix: project queued status through chat history

* test(ui): keep queued sidebar case under line cap
2026-08-18 02:31:39 -07:00
Peter Steinberger ad475ce33a feat(gateway/ui): command-lane diagnostics with debug page table and global busyness overlay (#125591)
* feat(gateway): expose command lane diagnostics

* feat(ui): add live debug busyness overlay

* fix(ui): show newest events in debug overlay and update diagnostics call-list tests

* test(ui): add lane and status fixtures to the mocked dashboard

* feat(ui): add System busyness entry to the account menu

* fix(gateway/ui): bound lane diagnostics, append-only descriptor, fail-visible lanes load

Addresses ClawSweeper review findings on #125591: diagnostics.lanes moves to
the append-only tail of the descriptor table, the Control UI lanes request
fails visibly instead of masking errors, and the RPC exports only static
lane snapshots plus a bounded dynamic-session aggregate composed in the new
command-lane-diagnostics module.

* chore(protocol): regenerate Kotlin gateway methods for diagnostics.lanes

* test(gateway/ui): register diagnostics.lanes in the 2026.8 train and mock it in the debug e2e
2026-08-18 01:10:32 -07:00
Peter Steinberger 561effac2e docs(apps): time-box the progress-card legacy plan fallback to 2026-10-18 (#125643)
The stream:"plan" fallback on both native platforms is deliberate compatibility
debt with a fixed expiry, not a permanent contract. Record the sunset date, point
each platform at its twin and at the tracking issue, and correct the Android note
to v2026.8.x (the newest released tag also lacks progressCard.get).

Refs #125639
2026-08-17 23:38:55 -07:00
Peter Steinberger af599f2cf7 feat(android): render durable progress card in chat (#125444)
* feat(android): render durable progress card in chat

Remove Android consumption of the legacy stream:"plan" agent events and in-flight plan snapshots.\n\nHandle progressCard.changed through the durable progressCard.get store and remove the Android protocol coverage allowlist entry.

* fix(android): refetch progress card on unattributable poke

The changed event carries the server-derived observer scope key, which the
client only learns from a get response carrying a card. Before that, a
canonical-keyed poke (e.g. global session scope) failed both match checks and
was silently dropped until reconnect. Unknown attribution now triggers an
authoritative refetch instead.

* chore(i18n): refresh native source baseline for progress-card strings

* fix(android): render legacy plan events when the gateway lacks the progress-card store

Released gateways through v2026.7.x emit stream:"plan" events and do not advertise progressCard.get, so retain a negotiated Android fallback.

Remove this branch with the gateway legacy dual-emit after the minimum supported gateway ships the progress-card store.
2026-08-17 18:42:19 -07:00
BYTE 46e44baf46 fix(android): retain pinned sessions in compact picker (#125264)
* fix(android): retain pinned sessions in compact picker

* fix(android): prioritize pinned sessions in compact picker

* fix(android): satisfy ktlint in session picker
2026-08-17 21:39:37 -04:00
Peter Steinberger 6e458d84bf feat(agents): configure per-agent GitHub identities (#125199)
* feat(agents): add managed GitHub identities

* fix(agents): use opaque GitHub setup handles

* style(codex): format managed shell environment call

* refactor(agents): own managed GitHub process identity

* chore(config): refresh baseline after rebase

* fix(ci): satisfy managed GitHub identity gates

* fix(ci): repair managed GitHub identity checks

* test(agents): align GitHub identity CI coverage

* fix(codex): scope login shell isolation

* fix(agents): let managed gh profiles authenticate

* fix(agents): harden GitHub identity setup

* test(gateway): align method suffix counts

* fix(ui): serialize GitHub identity mutations

* fix(protocol): generate GitHub configure requests

* test(ui): restore timers after identity tests

* fix(ui): preserve GitHub identity mutation ownership

* fix(agents): preserve native GitHub CLI auth
2026-08-17 15:54:03 -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
Peter Steinberger 7170a6231a feat(agents): unify agent status into a durable progress_card (#125125)
* feat(agents): unify agent status into a durable progress_card

Replace the write-only update_plan to-do tool and the fragmented plan
rendering with one durable status artifact per session: progress_card
({plan?, markdown?}, replace-on-write, 8 KiB markdown / 50-step caps).
Cards persist in a lazy-additive session_progress_cards table in the
per-agent DB (no schema-version bump), broadcast progressCard.changed,
and render from the store with exactly one live placement per view
(session rail when visible, else the composer-adjacent bar); transcripts
collapse to one-line receipts, and the sidebar hovercard shows other
sessions' cards inline (markdown + <progress>, DOMPurify allowlist, no
iframes). The three stream-derived plan renderers and their dedup
heuristics are deleted.

Codex runs disable the native plan tool per thread
(tools.update_plan.enabled=false) and receive progress_card via the
dynamic-tool bridge; compaction restore now reinjects the card (steps +
bounded markdown). Card writes still emit the legacy plan stream event so
native apps and channels keep working until their per-platform
migrations. Policy names map update_plan -> progress_card; the shipped
tools.updatePlan=false kill switch is honored.

Net -277 production LOC; -480 test LOC.

* test(agents): regenerate Codex prompt snapshots for update_plan thread-config disable

* chore(protocol): allowlist progressCard.changed for native apps pending card migration

* fix(ci): repair progress card integration checks

* fix(codex): canonicalize native progress cards

* test(gateway): reconcile progress card method order

* test(codex): stabilize native approval fixture
2026-08-17 09:44:04 -07:00
Peter Steinberger 27b77a901e feat(ui): make session references first-class links with titled chips and hovercards (#125014)
* feat(sessions): teach session tools the Control UI link rule

Gate guidance on publicOrigin plus enabled Control UI, with exact literal-URL fallback after short-link misses.

* feat(ui): linkify session keys in chat markdown

Match agent session keys structurally in plain text and inline code, then delegate canonical chat navigation.

Allowlist data-session-key through markdown sanitization.

Pathfinder: keep internal Control UI route anchors in-app by removing target="_blank" and external-link rel attributes while preserving external link behavior.

* feat(ui): session hovercard + titled session chips backed by controlUi.sessionPreview

* fix(gateway): scope controlUi.sessionPreview to caller-visible sessions

Hover previews now apply the same createSessionListEntryFilter predicate as
sessions.list, so identity-bearing non-admin callers cannot preview-by-key
incognito rows or non-owner drafts the sidebar hides. Regression test proves
the viewer/admin split; pre-fix run leaked ok-status metadata.

* feat(sessions): carry the session-link rule in tool result envelopes

Deferred-description mode hides prose tool descriptions at decision time. Carry the shared Control UI session-link sentence in successful session lookup result envelopes so every tool mode sees the rule.

* fix(ui): upgrade session chips on appearance, not first pointer event

* fix(android): regenerate gateway protocol methods

* test(gateway): track session preview release train

* perf(ui): lazy-load session hovercard registration

* fix(ui): keep session hovercards off sidebar navigation

* fix(ui): cancel routed session-link navigation

* fix(sessions): advertise forced-literal ~key URLs so short-ID collisions cannot misroute

* test(sessions): update forced-literal guidance expectation

* fix(ui): collision-proof raw-key navigation and SPA-route internal session URLs

* perf(ui): preserve session route lazy boundary

* fix(ui): defer unseeded session-preview fetches to hover intent

* fix(sessions): hard-cap the model-visible session-link base
2026-08-17 04:05:02 -07:00
Víctor Gurbani Carballo daf7cae8c0 fix(android): new chats receive generated titles (#123670)
* fix(android): allow generated session titles

* fix(android): keep unnamed chat titles local

Co-authored-by: victor-gurbani <89997914+victor-gurbani@users.noreply.github.com>

* chore(android): refresh native i18n inventory

Co-authored-by: victor-gurbani <89997914+victor-gurbani@users.noreply.github.com>

* fix(ci): keep fork lint within hosted limits

Co-authored-by: victor-gurbani <89997914+victor-gurbani@users.noreply.github.com>

* test(ci): align prerelease manifest fixture

Co-authored-by: victor-gurbani <89997914+victor-gurbani@users.noreply.github.com>

* fix(android): align chat switcher session titles

Co-authored-by: victor-gurbani <89997914+victor-gurbani@users.noreply.github.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-08-17 03:35:34 -07:00
Peter Steinberger 55ce95fac8 feat(sessions): three-layer session ownership — agent attribution, assignable owner, participants (#125057)
* feat(sessions): stamp agent identity on spawned sessions and return spawn receipts

Agent-spawned sessions recorded the requesting session key as createdActor.id,
so the Control UI creator chip rendered an opaque key. Spawn producers now stamp
the canonical requester agent id; parent-authority validation moves to a new
trusted requesterSessionKey field. projectSessionActor enriches agent actors
with configured identity name/avatar at read time, and visible sessions_spawn
returns a sessionUrl + owner receipt with URL-first acknowledgement guidance.

* feat(sessions): assignable session ownership with owner facet and menus

GitHub-assignee-style ownership: sessions get a mutable owner (defaulting to
the immutable createdActor) stored in additive bare-nullable SQLite columns
with first-use lazy ensure. New operator.write sessions.assignOwner validates
targets, requires an identified caller, authorizes by session visibility, and
records assignedBy/assignedAt inside the write transaction. The sessions agent
tool gains assign_owner; the Control UI adds Assign-to-me/Assign-to menus in
sidebar rows and chat headers, renders the effective owner chip, and the
creator facet/filter now keys on effective owner. Sharing authority stays
anchored on createdActor.

* feat(sessions): record session participants and stack them in the owner chip

Records every distinct external prompter (human profile/channel sender, or a
requesting agent) per session in an additive session_participants table at the
turn-admission boundary — best-effort, deferred, never blocking the turn; the
session's own agent and viewers are never recorded, capped at 32 per session.
The session row projects a bounded participants list (owner excluded) plus a
total count with the same actor enrichment as owner/createdActor. The sidebar
chip becomes a pair-stack when others have prompted (owner front, one peeking
participant or +N behind), the chat header shows the full facepile, and an
authenticated involvingMe list filter adds an Involving-me sidebar predicate.
Participant projection is excluded from logical-session CAS equality so display
history never invalidates session writes.

* fix(sessions): identify built-in agent tool callers for owner assignment

The sessions tool's assign_owner dispatched through the in-process synthetic
client, which carries neither a signed agent-runtime identity nor a human
profile, so agent-initiated reassignment always failed with FORBIDDEN. The
tool now captures its trusted requester agent identity and carries it across
in-process dispatch as internal client state (never wire params); the handler
derives assignedBy as signed runtime identity, then trusted agent-tool caller,
then authenticated human. Live-verified end-to-end on a dev gateway.

* fix(ci): split oversized session modules and refresh prompt snapshots

Split the max-lines offenders at concept boundaries for session equality, tool overrides, and protocol owner schemas. Remove the redundant Number conversion from the node:sqlite participant count. Refresh prompt snapshots after drift from the sessions and sessions_spawn tool description updates.

* fix(ci): restore solo-mode chip suppression and conform new method descriptors

Solo-mode root cause: owner-assignment submenu options reused the permanent owner-chip custom element, so hidden menu avatars were counted as attribution chrome. Menus now use viewer avatars while gateway-gated owner chips remain exclusive to collaborative sessions.

Conform sessions.assignOwner to the 2026.8 descriptor and append-only advertised-method inventories, and regenerate the Swift and Kotlin protocol surfaces.

Keep historical v15/v14 fixtures frozen by stripping the new owner columns; the existing range already excludes the participant table. Replace the new raw SQLite schema probes with synchronous Kysely queries.

Clear max-lines by splitting the organizer host contract, pure agent-navigation projections, and ownership/filtering sidebar cases at their concept boundaries.

* fix(ci): integrate ownership series with latest main surfaces

Wire the sessions-page assign-owner action, merge capability imports, narrow the navigation export scope, and apply sessions-create formatting.

The owner-presence regression came from hidden assign-owner menu avatars emitting data-viewer-id, so owner and menu chrome now opt out of presence markers while real facepiles retain them.

* fix(sessions): scope the involving-me filter to profile-backed participants

Session participant history mixed channel-native sender ids with authenticated Gateway profile ids, so involving-me missed real sessions and could accept numeric collisions.

Record the actor_source namespace at each producer, carry it through the internal SQLite projection, and match authenticated viewers only against profile-backed human participants. Legacy NULL sources fail closed for filtering, while channel ids remain available for display.

* build(ui): raise startup budget baseline for session ownership surfaces

Ownership chips, assignment menus, and the participant stack add ~0.7 KiB
gzip to the startup path; CI compression landed just over the previous
baseline+tolerance. Hard cap (350 KiB) unchanged.

* refactor(sessions): drop raw NULL projection for the lazy actor_source column

The Kysely guardrail rejects typed raw sql snippets outside allowlisted
boundaries; select the lazily-ensured column only when present and let the
row projection treat its absence as unknown/legacy.

* build(ui): refresh combined startup baseline
2026-08-17 02:35:20 -07:00
WhatsSkiLL 657b6e8f49 feat(android): pin gateway-backed session search in the sidebar (#124338)
* fix-android-chat-session-picker

* fix-search-all-android-sessions

* fix-native-i18n-inventory

* fix-android-share-session-browser-policy

* fix(android): show loading during session search

* refactor(android): move gateway-backed session search into the pinned sidebar

The sidebar header and search field no longer scroll away: they sit above
the scrolling sections, and the search field is always visible instead of
hidden behind a toggle. Queries now run through the shared session-browser
search state (debounced gateway search with offline fallback) instead of a
local filter over cached rows, and matching threads replace the section
list while a query is active.

The in-chat bottom-sheet picker is removed: the compact switcher's All
button navigates straight to the Sessions screen again, and the sidebar
owns in-context session search. The shared rememberSessionBrowserSearchState
extraction from the Sessions screen is kept and gains the sidebar as its
second consumer.

* style(android): fix sidebar import ordering for ktlint

---------

Co-authored-by: IWhatsskill <284122573+IWhatsskill@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-08-17 01:22:16 -07:00
Peter Steinberger f59e945013 feat(gateway): move sessions between Gateway and runners (#125036)
* chore: preserve session placement move work

* feat(gateway): move sessions between runners

* test(gateway): align recovery fixture with move barriers

* fix(protocol): format literal-only Swift initializers

* test(ui): prove session move terminal state

* refactor(gateway): narrow session move target fence

* fix(gateway): preserve pending result recovery ownership

* test(workers): migrate reclaim lifecycle fixtures

* refactor(gateway): keep move internals private

* test(gateway): align split bootstrap fixture with moves

* fix(gateway): recover session moves through exact intent

* refactor(gateway): derive move placement subtypes locally
2026-08-17 00:23:13 -07:00
Peter Steinberger 3010318ba3 fix(android): isolate debug app installs (#125099) 2026-08-16 23:36:57 -07:00
Peter Steinberger 4b2aa935f3 fix(android): restore 11sp caption density (#125053) 2026-08-16 22:12:23 -07:00
Peter Steinberger d095113698 refactor(android): collapse the chat's second color palette into ClawTheme (#125020)
* refactor(android): consolidate chat palette

* refactor(android): fold the font family into ClawTheme
2026-08-16 21:31:27 -07:00
Peter Steinberger 2c4651538c improve(android): drop the role title on every chat message (#124985)
* fix(android): let chat bubbles carry message roles

* test(android): prove chat speaker accessibility

* chore(android): refresh native i18n inventory

* ci: shrink assertion safety baseline

* fix(android): satisfy Compose modifier lint
2026-08-16 20:21:59 -07:00
Peter Steinberger eeece038cd fix(android): show plan status and explanation (#124958) 2026-08-16 19:11:10 -07:00
Peter Steinberger 3d152540e3 fix(android): remove completed plan strikethrough (#124916) 2026-08-16 17:18:12 -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