Commit Graph

5144 Commits

Author SHA1 Message Date
Peter Steinberger 5c6bccff4a feat(macos): enable Computer Control by default and diagnose stale Accessibility grants (#115280)
* feat(macos): enable and diagnose computer control

* docs(macos): explain computer control permissions

* chore: refresh macOS i18n and docs indexes

* test: update macOS computer control i18n fixture
2026-07-28 13:00:32 -04:00
Peter Steinberger 40fb1ca27e fix: schema-version refusal blames a downgrade that never happened and cannot identify the stale install (#115232)
* fix(state): name the refusing install in schema and exec-approval refusals

The newer-schema refusal told operators not to downgrade and to upgrade
OpenClaw, neither of which is actionable when two builds share one release
version string. It now names the install root that refused, both schema
versions, and warns that a linked source checkout reports its git HEAD even
when its built dist is older.

The exec-approvals gate told operators to run `openclaw doctor --fix` without
naming the state directory, so a bare invocation repaired the default root
while the scoped install stayed blocked. Both the TypeScript gate and its
Swift sibling now scope the command to the blocked state directory.

Refs #115008

* fix(gateway): name the refusing install in the startup schema refusal

* fix(mac): keep the exec-approvals gate message buildable on iOS

* fix(exec-approvals): shell-quote the state directory in the repair command

* fix(exec-approvals): state the repair directory in prose so every shell can follow it
2026-07-28 12:21:43 -04:00
Vincent Koc d92062b970 fix(android): respect locale in compact labels 2026-07-28 23:49:44 +08:00
Vincent Koc 92971c3278 chore(i18n): refresh gateway discovery catalogs 2026-07-28 23:48:57 +08:00
Vincent Koc 289c8ff992 fix(apple): localize gateway discovery status 2026-07-28 23:48:57 +08:00
dongdong 84555934f6 fix: preserve OpenClaw profile env in macOS launch-at-login plist (#99752)
* fix(macos): preserve profile env in launch-at-login plist

* fix(macos): preserve login profile environment

Co-authored-by: Jasmine Zhang <jasminezhang@JasminedeMac-mini.local>

* test(macos): isolate launch agent PATH coverage

Co-authored-by: Jasmine Zhang <jasminezhang@JasminedeMac-mini.local>

---------

Co-authored-by: Jasmine Zhang <jasminezhang@JasminedeMac-mini.local>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-28 11:32:42 -04:00
Cihat Gündüz c3fba2bb20 fix(ios): forgetting a paired gateway does nothing (#114083)
* fix(ios): forgetting a paired gateway does nothing

Confirming "Forget Gateway" in Settings never removed the gateway. The
confirmation dialog derived its isPresented binding from the payload it
later needed and cleared that payload on dismissal, so by the time the
destructive button's action ran, forgetPendingGateway() found nil at its
opening guard and returned without calling forgetGateway(stableID:).
Nothing was logged either, because the failure branch was never reached.

Hand the entry to the action through the dialog's presenting: parameter
instead of reading it back from view state, and take it as a parameter
rather than looking it up. Everything downstream is unchanged; it simply
runs now.

* Shorten the dialog comment to one line

The three-line version repeated in prose what the next line already shows.
What is worth keeping is the trap: someone simplifying this back to reading
the entry from view state reintroduces the bug.

* fix(ios): harden forget gateway payload handoff

Co-authored-by: Cihat Gündüz <anthropic@fline.dev>

* test(ios): run gateway settings source guards

* test(ios): allow forget dialog state cleanup

* test(ci): provide rg in PR review fixture

---------

Co-authored-by: Cihat Gündüz <anthropic@fline.dev>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-28 09:59:23 -04:00
Bryan Tegomoh, MD, MPH 15866acef5 Refresh macOS skills after node reconnect (#107660)
* Refresh macOS skills after node reconnect

* fix(macos): queue skills refresh during reconnect

* chore(i18n): refresh native skills inventory

* fix(macos): refresh skills from gateway invalidations

Co-authored-by: Bryan Tegomoh <bryan.tegomoh@gmail.com>

* fix(android): update gateway event catalog

Co-authored-by: Bryan Tegomoh <bryan.tegomoh@gmail.com>

* refactor(skills): keep remote eligibility helper bounded

Co-authored-by: Bryan Tegomoh <bryan.tegomoh@gmail.com>

* ci(test): pin model shard worker budget

Co-authored-by: Bryan Tegomoh <bryan.tegomoh@gmail.com>

* ci(test): isolate network-sensitive agent suites

Co-authored-by: Bryan Tegomoh <bryan.tegomoh@gmail.com>

* test: align isolated prefix routing expectation

Co-authored-by: Bryan Tegomoh <bryan.tegomoh@gmail.com>

* test(macos): isolate gateway process test port

Co-authored-by: Bryan Tegomoh <bryan.tegomoh@gmail.com>

* fix(macos): recover skills after failed refresh

Co-authored-by: Bryan Tegomoh <bryan.tegomoh@gmail.com>

* fix(ci): avoid duplicate agent test routing

Co-authored-by: Bryan Tegomoh <bryan.tegomoh@gmail.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-28 09:10:45 -04:00
Chris M. 37bddc75cc fix(android): finish Wear OS release readiness [AI-assisted] (#110425)
* fix(android): harden Wear release quality

* fix(android): use Wear minimum touch targets

Co-authored-by: Chris Mish <chrism@promethean-dynamic.com>

* fix(android): localize Wear accessibility actions

Co-authored-by: Chris Mish <chrism@promethean-dynamic.com>

* fix(android): preserve dictation without live voice

Co-authored-by: Chris Mish <chrism@promethean-dynamic.com>

* fix(android): isolate Wear locale source changes

Co-authored-by: Chris Mish <chrism@promethean-dynamic.com>

* fix(android): keep Wear dictate preview exclusive

Co-authored-by: Chris Mish <chrism@promethean-dynamic.com>

* fix(android): separate large-font Wear hit targets

Co-authored-by: Chris Mish <chrism@promethean-dynamic.com>

* test(pr): isolate review artifact ripgrep fixture

* ci: extend embedded-agent fork watchdog

* refactor(android): clarify Wear voice action availability

* style(android): preserve Wear locale source lines

* chore(i18n): refresh native source inventory

* style(android): restore Wear label indentation

---------

Co-authored-by: Chris Mish <chrism@promethean-dynamic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-28 05:41:53 -04:00
Peter Steinberger 2025c3d1b8 feat(system-agent): give Ask OpenClaw ambient page context (#114943)
* feat(ui): add custodian page context

* fix(system-agent): keep planner input free of the pending-proposal marker

* fix(system-agent): preserve context-free call shape

* refactor(system-agent): isolate page context boundaries

* fix(gateway): canonicalize UI context

* fix(gateway): enforce ASCII page context
2026-07-28 05:30:44 -04:00
Vincent Koc 9fbe9abc86 fix(ci): restore Android CodeQL compatibility (#115095) 2026-07-28 11:24:22 +02:00
Vincent Koc f8ed8ecf4f fix(security): harden CodeQL-reported boundaries (#115055)
* fix(security): harden CodeQL-reported boundaries

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

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

* chore: keep release changelog owned

* refactor(macos): split managed image loading

* test(apple): prove managed image header policy

* test(native): stabilize managed image proof

* test(apple): satisfy strict concurrency checks

---------

Co-authored-by: Francesco Giannicola <francescogiannicola1@gmail.com>
2026-07-28 04:39:53 -04:00
Vincent Koc 9000da0451 refactor(android): remove unused Wear voice button (#115061) 2026-07-28 16:19:34 +08:00
Nick 5d4ff17d7d fix: macOS reports CLI-only Tailscale as not installed (#114179)
* fix(macos): detect CLI-only Tailscale

* fix(macos): distinguish Tailscale app and CLI installs

Co-authored-by: Nick <18488428+nickxma@users.noreply.github.com>

* chore(macos): refresh native i18n inventory

* test(pr): provide rg in artifact fixture

* fix(macos): gate Tailscale interface evidence

* chore(pr): drop superseded fixture shim

* chore(macos): realign native i18n inventory

* refactor(macos): keep Tailscale status guidance generic

---------

Co-authored-by: Nick <18488428+nickxma@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-28 04:00:18 -04:00
Peter Steinberger 86e92486aa fix(macos): stop replacement handoff retry storms (#114975)
* fix(macos): bound app replacement handoffs

* chore: leave release notes to release flow

* chore(macos): refresh native i18n inventory

* chore(apps): sync native i18n inventory

* fix(macos): revalidate terminal replacement target
2026-07-28 03:21:25 -04:00
Vincent Koc 5c9564c428 fix(i18n): refresh native source baseline 2026-07-28 08:54:52 +02:00
Peter Steinberger 2ed2e46763 fix(mac): cache gateway profile registry and isolate dev keychain items (#114956) 2026-07-28 02:36:25 -04:00
Peter Steinberger 4b59f06d27 fix(mac): bound node worker crash retries (#114974) 2026-07-28 02:22:27 -04:00
Vincent Koc 7838c6a6fd fix(apps): fence stale mobile delivery state 2026-07-28 08:15:52 +02:00
Peter Steinberger a4d60af42b fix: sharpen working-claw silhouette into a toothed pincer (#114939) 2026-07-28 01:18:36 -04:00
Peter Steinberger 01f6ad67d5 chore(i18n): refresh native locale catalogs (#114915)
* chore(i18n): refresh native locale catalogs

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

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

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

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

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

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

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

* fix(android): reuse Compose motion scale

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

* fix(android): keep system motion scale authoritative

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

* test(cli): raise root help deadlock guard

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-28 00:38:50 -04:00
Peter Steinberger 1e3a4a69b5 fix: preserve native trace heading typography (#103436)
* fix(ios): preserve native trace heading typography

* test(ios): attach trace heading visual proof

* test(ios): import shared chat UI for visual proof
2026-07-28 00:01:44 -04:00
Yiğit ERDOĞAN dae1817a17 fix: block CXXCPP host env override (#112684)
CPP was added to blockedEverywhereKeys in #112560, but its Autoconf twin
CXXCPP was not. Autoconf defines the preprocessor selectors as a pair —
AC_PROG_CPP sets CPP, AC_PROG_CXXCPP sets CXXCPP — and this list already
carries the compiler pair CC/CXX for the same reason.

Measured on current main: CC, CXX and CPP all report dangerous, while
CXXCPP lands in no category at all (blockedPrefixes is only DYLD_, LD_
and BASH_FUNC_, so no prefix rule covers it either).
2026-07-27 23:58:41 -04:00
NianJiu aa26ecfac1 fix(android): Wear Talk works after exiting and reopening (#112383)
* fix(android): scope Wear Talk client to ViewModel

* test(android): exercise Wear ViewModel factory lifecycle

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

---------

Co-authored-by: NianJiuZst <180004567+NianJiuZst@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-27 23:35:10 -04:00
metaforismo a84ea8b732 fix(ios): suppress stale delayed UI actions (#113062)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-27 23:19:07 -04:00
haruai b168e4b5ed fix: align macos remote url validation copy (#98548)
* fix: align macos remote url validation copy

* fix(macos): match remote URL guidance to policy

Co-authored-by: haruaiclone-droid <281899875+haruaiclone-droid@users.noreply.github.com>

* chore(i18n): refresh native source inventory

Co-authored-by: haruaiclone-droid <281899875+haruaiclone-droid@users.noreply.github.com>

---------

Co-authored-by: haruaiclone-droid <281899875+haruaiclone-droid@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-27 23:18:41 -04:00
dependabot[bot] 9fbbe2cc98 build(deps): bump the swift-deps group across 1 directory with 2 updates (#114452)
Bumps the swift-deps group with 2 updates in the /apps/macos directory: [github.com/steipete/peekaboo](https://github.com/steipete/Peekaboo) and [github.com/pointfreeco/swift-concurrency-extras](https://github.com/pointfreeco/swift-concurrency-extras).


Updates `github.com/steipete/peekaboo` from 3.9.6 to 3.9.8
- [Release notes](https://github.com/steipete/Peekaboo/releases)
- [Commits](https://github.com/steipete/Peekaboo/compare/v3.9.6...v3.9.8)

Updates `github.com/pointfreeco/swift-concurrency-extras` from 1.4.0 to 1.4.1
- [Release notes](https://github.com/pointfreeco/swift-concurrency-extras/releases)
- [Commits](https://github.com/pointfreeco/swift-concurrency-extras/compare/1.4.0...1.4.1)

---
updated-dependencies:
- dependency-name: github.com/steipete/peekaboo
  dependency-version: 3.9.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swift-deps
- dependency-name: github.com/pointfreeco/swift-concurrency-extras
  dependency-version: 1.4.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swift-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-27 21:58:03 -04:00
dependabot[bot] 52bf653427 build(deps): bump the android-deps group across 1 directory with 5 updates (#113083)
Bumps the android-deps group with 5 updates in the /apps/android directory:

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



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

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

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

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

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

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

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

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-27 21:51:56 -04:00
Peter Steinberger 313daad549 perf(gateway): warm handler families and cache identity avatars (#114754)
* perf(gateway): warm handler families and cache identity avatars

* chore: drop changelog edit (release-generation-owned)

* fix(ci): regenerate protocol models, satisfy knip, absorb sidecar drift

- commit regenerated Swift GatewayModels for the additive cron.list param
- split the avatar data-url cache into assistant-avatar-cache.ts so its
  factory has a production consumer (knip production scan)
- de-export prewarm family names/type; test now drives fake families only
- postReadySidecarCount 2 -> 3: main added a post-ready sidecar in parallel
2026-07-27 19:37:13 -04:00
Peter Steinberger f85a458a45 refactor(mobile): consolidate native gateway and voice lifecycles (#114671)
* refactor(mobile): consolidate native lifecycle ownership

* fix(ci): cover Codex prewarm and chat lifecycle proof
2026-07-27 14:52:02 -04:00
Peter Steinberger 14d8c2439f feat(ui): offer normally-absent core files instead of flagging them missing (#114559)
* feat(ui): offer normally-absent core files instead of flagging them missing

The Agents core-files editor rendered every unwritten workspace file as a
permanently-badged MISSING tab, so an ordinary workspace looked broken. Absence
is only a fault for required files; SOUL.md, USER.md, and MEMORY.md are normal
to be absent until written.

agents.files.list now marks those entries expectedAbsent, and the editor keeps
them out of the tab strip behind an add picker that creates the file on save.
A missing AGENTS.md still shows as a fault.

* chore(protocol): regenerate Swift gateway models for expectedAbsent

* fix(gateway): carry expectedAbsent through agents.files.get

Clients merge the get response over the listed entry, so a missing-file get
that dropped the flag made a file picked from the add picker re-render as a
MISSING fault. Caught by live Control UI proof, not by the unit tests.
2026-07-27 09:16:10 -04:00
Peter Steinberger 56d9802f6e fix(mobile): prevent stale reconnect, approval and voice cancellation (#114549)
* fix(mobile): fence reconnect, approval and voice cancellation

* fix(mobile): refresh native localization source inventory

* test(android): advance cancelled voice finalizer scheduler

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

* fix(sessions): sync native observer source inventory

* fix(android): satisfy observer ownership formatting gate
2026-07-27 08:39:29 -04:00
Peter Steinberger 91f04499f5 fix(sessions): defer agent self-archive until run completion (#114522) 2026-07-27 07:46:22 -04:00
Peter Steinberger 981b4cc3fe fix(mac): redesign onboarding remote-gateway detail section (#114494)
* fix(mac): redesign onboarding remote-gateway detail section

* chore(i18n): refresh native inventory for onboarding redesign
2026-07-27 06:36:02 -04:00
Peter Steinberger c56689416e fix(ui): scope global route resolution by agent 2026-07-27 05:43:19 -04:00
Peter Steinberger 45095c51b4 chore(i18n): refresh native source baseline 2026-07-27 05:43:19 -04:00
Peter Steinberger 64bf485ba2 fix(sessions): scope observer state by agent 2026-07-27 05:43:19 -04:00
Peter Steinberger 6a3696000e fix(android): prefer selected observer owner 2026-07-27 05:43:19 -04:00
Peter Steinberger 51f228f6fe fix(ui): preserve agent-owned session navigation
Add agent ownership to observer digests, scope global observer delivery and reconciliation, and centralize application session selection across navigation and reconnects.

Co-authored-by: xbrxr03 <abrarhabib03@gmail.com>
2026-07-27 05:43:19 -04:00
Peter Steinberger 5a8db91459 fix(macos): keep polling gateway-executed wizard steps (#114383)
* fix(macos): keep polling gateway-executed wizard steps

* docs(ui): note the prebuilt control-UI bundle in live verification

* test(macos): fail fast when gateway progress polling stalls

* chore(i18n): refresh native source inventory anchors
2026-07-27 04:33:09 -04:00
Peter Steinberger 079ac9390d refactor(ios): simplify node and Watch lifecycle ownership (#114366)
* refactor(ios): centralize node lifecycle owners

* fix(ios): sync native localization source inventory

* test(ios): prove gateway and notification lifecycles in simulator

* fix(ios): preserve voice upgrade and correlate watch snapshots
2026-07-27 03:23:31 -04:00
Peter Steinberger ab3e9645e7 fix(linux): recover corrupt gateway identity (#114359) 2026-07-27 02:17:08 -04:00
Peter Lee 0406e66369 fix(ui): keep stable chat rows in insertion order and only sort live tool/stream items by timestamp (#113266)
* fix(ui): keep stable chat rows in insertion order and only sort live tool/stream items by timestamp

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

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

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

* fix(ui): preserve reconnecting run order

* fix(ui): preserve causal terminal ordering

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

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

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

* fix(ui): restore reconnecting chat run identity

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

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

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

* chore(i18n): refresh native source baseline

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

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

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-27 02:08:22 -04:00
Peter Steinberger b65dae1511 fix(linux): surface manual update results (#114312) 2026-07-27 01:26:28 -04:00
Peter Steinberger de92c557f1 fix(linux): serialize tray gateway operations (#114291) 2026-07-27 01:06:03 -04:00
Peter Steinberger 8b66fc103d feat(ui): durable session board face and dashboards index (#114262)
* feat(ui): durable session board face and dashboards index

Board face lived only in client-side boardSessionViews, capped at 50 entries,
so the preference never followed the user to another device, evicted as
sessions accumulated, and could not be seen as a set.

Persist it as SessionEntry.boardFace, which rides the existing entry_json blob
and so needs no SQLite schema change or version bump. Expose it on the session
list row and add it to the sessions.patch write-scope allowlist alongside label,
pinned, and archived: setting your own view preference is user-level chat
organization, not policy. Unknown patch fields still fail closed to
operator.admin.

Generic navigation now reads the stored face, so the sidebar and session list
open a thread on the face you left it on. boardSessionViews keeps only
activeTabId and reopenDockByTab, which are genuinely per-device.

Add /dashboards listing threads whose preferred face is dashboard. Filtering
runs server-side in filterSessionEntries before pagination, because the client
holds only a capped page and a client-side filter would silently omit
dashboards.

* test(protocol): assert the pre-rename face param is rejected

The gateway-protocol validator test still passed the pre-rename 'face' key,
which the closed schema rejects. Use boardFace, and pin the old name as a
negative case so it cannot silently return.

* chore(protocol): regenerate Swift bindings and docs map for boardFace

Adding boardFace to the sessions schema changes two committed generated
artifacts: the Swift gateway models (pnpm protocol:gen:swift) and the docs map
(pnpm docs:map:gen), which now lists the dashboards index section.
2026-07-27 00:35:34 -04:00
Peter Steinberger 730b341f3f fix(linux): keep Quick Chat on screen across DPI and widget resizes (#114271)
Two geometry defects found while stress-testing the companion.

Positioning mixed coordinate spaces. `work_area()` is physical pixels of the
monitor Quick Chat is moving to, but `inner_size()` is physical pixels at the
scale of the monitor it is on now. A 640pt window on a 2x display reports
1280px, so invoking it on a 1x 1920px display centred using 1280 and landed it
320px left of centre. Re-express the window size in the target monitor's scale
first; equal scales give a ratio of 1, so single-monitor setups are untouched
to the pixel.

Widget growth resized without re-anchoring. `quickchat_set_expanded` resizes
and then repositions, but the widget path only resized, keeping the old top
edge. Growing from 360pt to 440pt in a 440pt work area left the bottom 80pt
off-screen and unreachable. `resize_window_if_needed` now reports whether it
actually changed the height so the caller re-anchors only on a real resize,
rather than moving the window when nothing changed.
2026-07-27 00:05:52 -04:00