Commit Graph

9148 Commits

Author SHA1 Message Date
Peter Steinberger
e6cba86509 chore(plugin-sdk): refresh API baseline 2026-07-12 11:24:42 +01:00
Peter Steinberger
feff4c7824 fix(plugin-sdk): isolate expect declaration surface 2026-07-12 11:23:43 +01:00
Peter Steinberger
a824078101 fix(channels): tombstone corrupt ingress rows (#105259)
* fix(infra): guard channel ingress queue parseJson against corrupted JSON

* fix(infra): fix type assertion in ingress queue test

* fix(infra): use tagged parse result and validate payload before claiming

* fix(infra): remove unnecessary non-null assertion in ingress queue test

* fix(infra): scan corrupt ingress rows in claimNext

* test(gateway): avoid typed empty mock call tuple access

* fix(infra): tombstone corrupt ingress rows on duplicate enqueue and stale recovery

Two P1 gaps: enqueue() threw on duplicate when the existing row had corrupt
payload_json, and recoverStaleClaims() silently skipped corrupt claimed rows,
leaving them invisible to recovery. Both paths now tombstone the unrecoverable
row as failed with reason "corrupt_payload" and return a proper result.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(infra): resolve lint shadow and await-thenable in recoverStaleClaims

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(channels): tombstone corrupt ingress rows

* test(channels): use explicit placeholder claim tokens

* refactor(channels): name claim token values

* refactor(channels): keep claim projection direct

* fix(channels): preserve active ingress claims

* fix(channels): make corrupt recovery policy-aware

* refactor(channels): name corrupt claim token

* fix(channels): bound corrupt ingress reconciliation

* fix(channels): paginate pending ingress by key

* refactor(telegram): return live owner check directly

* build(plugin-sdk): refresh public export budget

---------

Co-authored-by: Pick-cat <huang.ting3@xydigit.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-12 11:09:52 +01:00
Peter Steinberger
dba78584ff fix(ui): preserve rejected first message when session send fails (#105261)
* fix(ui): preserve rejected first session message

* chore: leave changelog to release closeout

* fix(protocol): regenerate session create result
2026-07-12 11:09:38 +01:00
Peter Steinberger
1999935108 fix(config): restore canonical flat streaming-key resolution and preserve discord preview mode in doctor migration (#105054)
* fix(config): keep flat streaming keys resolving for canonical-flat channels and pin discord preview default in doctor migration

* fix(discord): pin inherited streaming mode for account alias migration and align core streaming test
2026-07-12 11:00:24 +01:00
Peter Steinberger
5b56a1f664 feat(gateway): land remaining durable-approvals stack and repair main gates (#104837)
* feat(gateway): propagate approvals to ancestor sessions with replay

Squash-rebased #103921 segment onto the native-clients tip on current main.
Session-scoped approval events publish sanitized pending/terminal
transitions to opted-in session audiences, with authoritative pending
replay on stream subscribe and durable-expiry reconciliation through the
owning manager. SessionApprovalEvent/Replay wire types export from the
approvals owner module; Swift models regenerated.

(cherry picked from commit 2d1dcf9747044710111d0c730fc46ba6013a165c)
(cherry picked from commit ccf88efd56b513d07599ffcee997bf0cddaf9adc)
(cherry picked from commit 8eb33f59f00ec9ee4625259b76bd7ae60d2cd480)
(cherry picked from commit c297cbc93c8401e9c79c20f242245a194f5dd236)
(cherry picked from commit 93d68f28601ff37d863da4db009504993a22533a)
(cherry picked from commit d285ccd8b2f212bb57e814107e7709c896e96b7d)
(cherry picked from commit 5c536982231402b1b58d1683794ea9948b32d077)
(cherry picked from commit 1646e5b6dc4dd20de54e10f110a5909be18d7d50)
(cherry picked from commit 35cf1b705b247fb282f4d56ffe74bd2fb238221f)
(cherry picked from commit 4f8ef3699d)
(cherry picked from commit 74fbdcc99d5fff062d67760a51dba4ee9e84479b)
(cherry picked from commit 222b285502681d2be14b1819798e9ee5555f431e)
(cherry picked from commit b9e744951f676b600e7c5322bfd04b0e99797c07)
(cherry picked from commit 9e904efde5)
(cherry picked from commit 678f2384fa)
(cherry picked from commit 72842e5cf6)
(cherry picked from commit be74c25e80e84a1f065053766f23efb84822e811)
(cherry picked from commit 93ba8c4b09)
(cherry picked from commit 8f23761372)

* feat(gateway): fail-closed plugin and tool approval gates

Squash-rebased #103932 segment onto the ancestor-propagation tip on
current main. Plugin node.invoke approvals claim a one-shot allow-once
decision before handing execution authority to the policy, so observation
or retry cannot replay a consumed approval; sibling tool gates bind
approval ids to their originating reviewer identity.

(cherry picked from commit 122df0d75281f572c012b6484ed5daf085d1d577)
(cherry picked from commit f23d8ac240a8dcf2a42c4daaae962263975a0ae8)
(cherry picked from commit 8632fb6436a224dac7a9a9ef0216884530de2c24)
(cherry picked from commit d9fe2dd5c53665e5732f5f3da5ed1907a686ade8)
(cherry picked from commit bb139f2c8aa36ddad70413e1ef79ff491a6f2ecd)
(cherry picked from commit 9b3e056b68ea515c7d4baef269289b6670570480)
(cherry picked from commit b11e66b59a7af1f3b08712de06864aed64d349e4)
(cherry picked from commit a12916ee592d03dfa35e86a2aaede4476a5d4e5d)
(cherry picked from commit d699de840fc8346892b9ae244fe3c3e8c4413032)
(cherry picked from commit 9b7e5a9608)
(cherry picked from commit 4b507593f1b2f10b4496984c84a2803b853e5c5e)
(cherry picked from commit 56408a186733c4eeb5aa76bd5907cde7b0cd3d5b)
(cherry picked from commit a4051d6d8353d39d6fa0b5d69c36e06c3cd3e796)
(cherry picked from commit 76829805a7)
(cherry picked from commit a8b493f934)
(cherry picked from commit aceb990597)
(cherry picked from commit a29b0e75482470c53a9fb4fe3f204e14cf71868f)
(cherry picked from commit 2e3be08653)
(cherry picked from commit c9ae3d7202)

* fix: main-gate repairs for the durable-approvals stack

- android: capture createdAtMs on the pending exec-approval write at
  registration; canonical readback after a refresh that already replaced
  the visible rows was dropping the approval instead of surfacing the
  still-pending reconciliation message (#104913 merged without this)
- android: generous CI timeout ceilings in GatewayExecApprovalRuntimeTest
- agents: hermetic model-discovery test via the plugins/provider-runtime
  boundary (lazy plugin-runtime resolution hangs vitest workers since #104770)
- cli: usage-cost settle-budget test asserts the budget bound on every call
  instead of pinning the poll count (fast hosts fit a second poll in 50ms)
- protocol coverage: allowlist session.approval for ios/android (native
  review rides exec.approval push/nudge delivery)
- docs map, native i18n inventory, plugin-sdk api baseline regenerated
2026-07-12 10:51:38 +01:00
Vincent Koc
1592d422ee fix(sqlite): reject orphaned database state before mutation (#105222)
* fix(sqlite): detect foreign key corruption

* docs(sqlite): document foreign key compaction checks

* fix(sqlite): prevent pragma shadow bypass
2026-07-12 17:31:24 +08:00
Vincent Koc
e90929ba41 chore(plugin-sdk): refresh node presence API baseline (#105236) 2026-07-12 17:25:03 +08:00
Peter Steinberger
a8b104c4e3 feat(mac): swap dashboard titlebar buttons with sidebar state (#105175)
* feat(mac): swap dashboard titlebar buttons with sidebar state

The Control UI reports sidebar collapsed/width over a new openclawNav
WKScriptMessage; the titlebar accessory shows toggle+back/forward
right-aligned to the sidebar edge while expanded, and
toggle+search+new-session while collapsed. Search opens the command
palette and + opens the new-session surface via openclaw:native-*
events. Older gateway bundles that never report keep the shipped
toggle/back/forward layout.

Refs #105129

* docs: describe state-dependent mac titlebar buttons
2026-07-12 10:13:36 +01:00
Peter Steinberger
55254c3a0b feat(nodes): route alerts to the active computer (#105083)
* feat(nodes): route alerts by active computer

* fix(ci): allowlist node presence mobile coverage

* test(prompts): refresh node presence snapshots

* fix(macos): await presence reporter actor hop

* fix(macos): type presence test delivery state

* docs(nodes): add active presence guide

* docs(nodes): format presence troubleshooting
2026-07-12 10:05:50 +01:00
Peter Steinberger
17a533ce26 improve(ui): redesign the Automations tab with stats, a table list, and a full-page detail view (#105174)
* feat(ui): redesign Automations tab with stats, table list, and detail tabs

* docs(web): describe redesigned Automations page layout

* fix(ui): global failing-count stat via filtered cron.list and unclipped row menus

* fix(ui): refresh failing-count stat after cron job mutations

* chore(ui): sync locale bundles for automations redesign keys
2026-07-12 09:51:12 +01:00
Peter Steinberger
204d2b176a refactor(agents): compress model prompts and tool instructions (#105095)
* refactor(agents): compress model prompt instructions

* test(agents): align compact prompt assertions

* test(gateway): align compact message prompt assertion

* chore(plugin-sdk): refresh prompt overlay API baseline

* docs(changelog): note prompt instruction compaction

* test(agents): align compact prompt contracts

* test(agents): align CLI prompt contracts

* style(agents): format CLI prompt tests

* fix(qa): prioritize shadow trial workflow

* test(agents): refresh rebased prompt snapshots
2026-07-12 09:45:30 +01:00
Peter Steinberger
18eb472f82 fix(gradium): restrict TTS credential egress (#105169)
* fix(gradium): restrict TTS base URL before sending API keys

* fix(gradium): pin credential egress hostname

* docs(changelog): note Gradium credential guard

* docs(changelog): note Gradium credential guard

---------

Co-authored-by: 张贵萍0668001030 <zhang.guiping@xydigit.com>
2026-07-12 09:43:22 +01:00
Peter Steinberger
9cf4f03afe feat(telegram): add rich outbound location and video notes (#105142)
* feat(telegram): add rich outbound sends

Co-authored-by: Paul Kondratov <paulislava@mail.ru>

* fix(telegram): reject unsupported outbound locations

* fix(telegram): preserve location send semantics

* fix(telegram): preserve cross-context location markers

* fix(outbound): validate standalone locations before decoration

* fix(telegram): project native locations into prompt context

* chore: defer Telegram changelog to release

* fix(telegram): align SDK surface and docs map

---------

Co-authored-by: Paul Kondratov <paulislava@mail.ru>
2026-07-12 09:36:22 +01:00
Peter Steinberger
218dcd815a feat(tooling): enforce noUncheckedIndexedAccess in the extensions lane (NUIA phase 4) (#105132)
* fix(extensions): make indexed access explicit across channel plugins

Transport-payload-safe burn-down: malformed Telegram/Discord/QQ/LINE
and sibling channel input keeps existing skip paths; no synthesized
fields, no new throws in delivery loops. Zalo escape sentinels preserve
literal matches instead of undefined replacements.

* fix(extensions): make indexed access explicit across provider and memory plugins

Stream and model iteration, tool-block guards, capture guards, and
sparse accumulators; singleton model reads carry named invariants.

* fix(extensions): make indexed access explicit across tooling plugins, flip the extensions lane

Remaining plugins (oc-path, qa-lab, browser, logbook, and siblings) plus
the tsconfig.extensions.json flag flip. Cleanup: logbook sampleFrames
NaN index at max=1, QA retry clamp at non-positive attempts, dead Canvas
probe and OpenShell no-op slice removed, twitch test setup leak excluded
from the prod lane.

* refactor(plugin-sdk): expose expectDefined via a focused SDK subpath

Extensions imported @openclaw/normalization-core directly, crossing the
external-plugin packaging boundary (it only worked because the runtime
builder bundles undeclared workspace helpers). expect-runtime joins the
canonical entrypoints JSON, generated exports, API baseline, docs, and
subpath contract test; all 78 extension imports now use the SDK seam.
Two scanner-shaped locals renamed for review-bundle hygiene.

* chore(plugin-sdk): raise surface budgets for the expect-runtime subpath

One new entrypoint with one callable export, added intentionally as the
packaging-honest seam for extension invariant helpers.
2026-07-12 09:17:31 +01:00
Shubhankar Tripathy
43e138cc66 feat(google-meet): retain the full caption transcript per session (#103387) (#103811)
* feat(google-meet): retain bounded transcripts

Co-authored-by: lonexreb <reach2shubhankar@gmail.com>

* chore: leave changelog to release tooling

* fix(google-meet): satisfy transcript CI checks

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-12 09:16:46 +01:00
Peter Steinberger
6fc564278d feat(agents): sessions_search full-text recall over past session transcripts (#105057)
Adds a core sessions_search agent tool backed by a SQLite FTS5 index that
lives next to the transcript rows in the per-agent database. Indexing is
transactional: user/assistant text is indexed inside the same write
transaction that persists the event, deletes drop index rows in the same
transaction, and branch rewinds mark the session dirty so the next search
rebuilds it from the same visible-path resolution sessions_history uses
(which also lazily backfills doctor-migrated databases). Search executes
gateway-side behind an additive sessions.search method with a bounded
session-key allowlist; visibility, sandbox restrictions, and snippet
redaction mirror sessions_history.

Closes #100978
2026-07-12 09:15:41 +01:00
Peter Steinberger
91ca35ba58 ci: make locale parity advisory before release (#105140) 2026-07-12 09:11:57 +01:00
Peter Steinberger
9cda1af020 fix(ui): open the start screen from the sidebar brand (#105046)
* fix(ui): restore sidebar start-screen navigation

* test(ui): align sidebar proof with automations
2026-07-12 09:09:27 +01:00
Peter Steinberger
6038480915 feat(ui): browse Gateway and node folders from one root (#105114)
* feat(ui): browse Gateway and node folders

* chore: keep changelog release-owned

* chore: refresh native i18n inventory

* refactor(macos): isolate node filesystem commands
2026-07-12 09:07:07 +01:00
Peter Steinberger
b6c171901e fix(secrets): harden exec provider diagnostics (#105082) 2026-07-12 09:01:33 +01:00
zw-xysk
0b30a3292f docs(slack): fix channel config examples — use 'enabled' instead of 'allow' to match strict schema (#103491)
* docs(slack): fix channel config examples — use 'enabled' instead of 'allow' to match strict schema

* docs(slack): align config reference channel toggle

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-12 08:38:03 +01:00
destire-mio
f547e2bd85 fix(feishu): drive info finds files past the first page (#104190)
Co-authored-by: destire-mio <248462155+destire-mio@users.noreply.github.com>
2026-07-12 07:24:06 +01:00
Peter Steinberger
cfe95266af feat(ui): redesign cron page as sidebar-first Automations master-detail (#104251)
Rebuilds the Control UI cron page as a sidebar-first Automations master-detail workspace: a task list pane (All/Active/Paused tabs, search, filter popover, curated emoji suggestion cards, scheduler footer) beside a detail pane that edits the selected task inline (prompt, row-style Details/Frequency groups, collapsible Advanced, per-task run history) and shows all-task recent activity when nothing is selected. Create & run now kicks a new task immediately after creation. The modal editor and quick-create wizard are retired; the automation-ideas catalog from #104761 is ported into the new suggestions list. Nav item renamed to Automations and pinned by default; route (/cron) and cron.* RPC contracts unchanged.

Closes #104217

Co-authored-by: Claude <noreply@anthropic.com>
2026-07-12 07:12:26 +01:00
Peter Steinberger
0086763ba4 feat(fleet): harden create, port allocation, drift visibility, and audit guidance (#104814) 2026-07-12 07:02:42 +01:00
soldforaloss
5459a94763 docs(browser): clarify JSON flag placement (#103155)
* docs(browser): clarify JSON flag placement

* docs(browser): align JSON flag examples

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-12 06:58:40 +01:00
Shubhankar Tripathy
86cd9786c8 fix(google-meet): actually leave the Meet call in the browser on leave (#103386) (#103522)
* fix(google-meet): leave browser calls on session end

Co-authored-by: lonexreb <reach2shubhankar@gmail.com>

* fix(google-meet): keep agent browser control in gateway

* chore(google-meet): move release note to pr

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-12 06:50:13 +01:00
Peter Steinberger
d14bb8ec44 fix: resume replay-safe work after gateway restarts (#104997)
* fix: resume replay-safe work after gateway restart

* chore: leave restart note to release process

* fix: sync restart recovery protocol artifacts
2026-07-12 06:37:22 +01:00
Peter Steinberger
a40e43e46e feat(mac): redesign the menu bar critter to match the mascot (#104846)
* feat(mac): redesign menu bar critter to match the mascot

* fix(mac): draw happy-eye arcs upward and guard stale celebration expiry

* docs(mac): update menu bar icon states for critter redesign

* fix(mac): own celebration expiry with a start-only generation counter

* fix(mac): give voice-wake antennae real headroom at 18pt
2026-07-12 06:35:02 +01:00
Peter Steinberger
3d9b912b88 feat: sidebar session state slot, worktree/automation badges, archive disables bound cron jobs (#104730)
* feat(gateway): flag sessions with attached automations and disable bound cron jobs on archive

Session rows now carry hasAutomation, derived from a lifecycle-owned index
over the cron service's in-memory jobs; cron events push refreshed rows so
badges stay live. sessions.patch { archived: true } disables enabled cron
jobs bound to the session (locked binding re-check, internal/operator-admin
callers only); restore intentionally does not re-enable them.

Refs #104700

* feat(ui): sidebar session state slot and worktree/automation badges

The run spinner moves into a leading state slot shared with the unread dot,
keeping the timestamp visible during runs; muted fork/clock badges sit after
the title (outside the trail/action overlap so pinned rows and touch devices
keep them). New strings localized via ui:i18n:sync (English fallback pending
a keyed translation run).

Refs #104700

* test(gateway): pin cron binding broadcast test to the event mechanism

The shard shares one process; session-store state from earlier tests can make
the row load return null, which legitimately produces a keyless refresh
payload. Row-field projection stays covered by session-utils and
session-automation-index tests.
2026-07-12 06:19:01 +01:00
Sally O'Malley
f3971bbd56 feat(mcp): support sandboxed MCP Apps (#69039)
Implement stable opt-in MCP Apps negotiation, caller-specific tool
visibility, bounded ephemeral UI resources, a dedicated-origin double
iframe host, restrictive CSP, configuration, docs, and regression tests.

Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Sally O'Malley <11166065+sallyom@users.noreply.github.com>
2026-07-11 22:04:38 -07:00
Peter Steinberger
dd5928711a feat(ui): fold Skills and Skill Workshop into a Plugins hub (#104834)
* feat(ui): fold Skills and Skill Workshop into a Plugins hub

One sidebar entry (Plugins) now covers plugins, skills, and skill-workshop
routes via a shared hub tab strip (Installed / Discover / Skills / Workshop).
Routes and URLs are unchanged; /settings/plugins gains ?tab= deep links and
the sidebar highlights Plugins for all hub routes.

Also latches Skill Workshop proposal loading so updated() no longer re-kicks
loads while one is pending or after one fails - the early-return finally
used to spin the page at 100% CPU whenever skills.proposals.list stalled.

* feat(mock): plugin catalog and skill-workshop fixtures for the mock harness

* docs(web): describe the Plugins hub tabs in the Control UI guide

* test(ui): backfill initialTab in plugins route-data fixtures

* fix(ui): review fixes for the plugins hub

- plugins route declares loaderDeps on the ?tab= param so query-only
  navigation and back/forward re-run the loader instead of reusing the
  cached match with the previous tab
- catalog tab clicks navigate so the URL and history stay in sync with
  the documented ?tab=discover deep link (local switch stays instant)
- skill-workshop error banner gains a Try again button so a transient
  proposals-list failure is recoverable without remounting the route

* fix(ui): restore the Installed tab on bare plugins URLs in history navigation

* fix(ui): manual-activation hub tablist with cross-route focus hand-off

Arrow keys only move focus now; activation stays on click/Enter so arrowing
can never unmount the strip under the user's focus. Keyboard activation of a
cross-route tab hands focus to the destination strip's active tab, and the
hub-route set uses a Set per lint.

* fix(ui): defer hub-tab focus reclaim until the strip is connected

* fix(ui): skip focus recovery for same-tab hub activation

* docs(css): note the hub-panel flex ownership for the workshop board

* fix(ui): adapt hub test to retired Overview route

* chore(i18n): sync locale bundles for the plugins hub keys

* docs(map): regenerate for the plugins hub section
2026-07-11 22:03:38 -07:00
Vincent Koc
a378f7970b chore: refresh plugin SDK API baseline (#104954) 2026-07-12 12:21:54 +08:00
Vincent Koc
32631fdfac refactor(android): remove retired voice wake stack (#104914)
* refactor(android): remove retired voice wake stack

* chore(android): refresh native i18n inventory
2026-07-12 11:52:51 +08:00
Vincent Koc
ddbec923d4 fix(plugin-sdk): cover the full public API baseline 2026-07-12 05:38:05 +02:00
Vincent Koc
350bac4e0e improve(sqlite): harden state lifecycle and snapshots (#104859)
* fix(sqlite): enable bounded vacuum and hot indexes

* fix(sqlite): serialize shared schema upgrades

* fix(sessions): reject stale transcript rewrites

* fix(sqlite): surface busy checkpoints and refresh registry

* fix(backup): verify sqlite snapshots

* feat(doctor): compact shared sqlite state

* test(sqlite): align hardening helpers

* fix(backup): respect plugin sqlite ownership

* fix(backup): snapshot plugin sqlite opaquely

* fix(doctor): reject mixed sqlite actions

* fix(backup): reject unsafe sqlite snapshots

* fix(sessions): track unconditional transcript replacements

* fix(backup): reject page-aligned sqlite truncation

* fix(backup): reject state-root case aliases

* docs: refresh sqlite maintenance map

* fix(sqlite): register doctor compaction boundary

* fix(sqlite): serialize fresh database initialization

* fix(sqlite): prove main v5 agent upgrade

* perf(sqlite): seek latest transcript messages

* test(sessions): align terminal freshness fixtures with SQLite

* docs: refresh generated map
2026-07-12 11:35:22 +08:00
Vincent Koc
c55ea0b453 docs: refresh generated docs map 2026-07-12 11:24:30 +08:00
Peter Steinberger
ac89350327 feat(apps): review durable approvals on mobile (#104913)
* feat(apps): Android, iPhone, and Watch approval clients

Squash-rebased #103912 segment onto the deep-links tip on current main.
Native approval surfaces: iOS approval presentation with gateway-switch
lease preservation and resolution fencing, watchOS inbox + approval
actions with shipped-shape payload codec, Android approval notices with
publication-tokened dismissal. Native i18n inventory regenerated.

(cherry picked from commit 428a76670ffeede54248b7bd7aa4438e2589851b)
(cherry picked from commit 80225d5707c3645eeea5435f266131037b50ede6)
(cherry picked from commit 2a23b714dc30d773a294aa45adc617e46b80732e)
(cherry picked from commit 9ff1153827769e2cbab7c11c153f0f8634662c28)
(cherry picked from commit 5b25723525bd562e5f97478af492f7b46ad30fd1)
(cherry picked from commit 8c80e8467b5fe89aad0d4c74a0573f1600ed3af9)
(cherry picked from commit ad4037bc9846bf6f082b41c129ee68aa344576c3)
(cherry picked from commit fdf767dd662cff3c8a5a6d571f38f153410651ca)
(cherry picked from commit 00c120376ffd992ea68ce29254a9bc0a25ed1740)
(cherry picked from commit f36a95213e)
(cherry picked from commit e2c25cbe2baacab44d21871d8cb6734704f065ac)
(cherry picked from commit 7c4fda519080486d341a9f4df36d63f9e24b1235)
(cherry picked from commit 1b3d4eda3dc5988012124597f9454ae21fb187a1)
(cherry picked from commit 2a60619722)
(cherry picked from commit 6f0c386567)
(cherry picked from commit 784a5857b7)
(cherry picked from commit cbf294e026841c9bc2799da0fc7db666a69c52db)

* fix(apps): harden approval reconciliation and watch states
2026-07-11 19:59:07 -07:00
Vincent Koc
2f946506bb fix(sessions): restore SQLite terminal freshness 2026-07-12 04:43:33 +02:00
Peter Steinberger
68f0eee5ae fix(ui): harden workspace file editing (#104885)
* fix(ui): retain unsaved workspace file drafts

* fix(ui): reset restored draft hash

* fix(ui): keep all unsaved file drafts

* fix(ui): harden workspace file editing

* fix(ui): canonicalize workspace file identity

* fix(gateway): serialize workspace file saves globally

* chore: keep release notes in PR body

* docs: refresh generated docs map
2026-07-11 19:25:47 -07:00
Peter Steinberger
4eb1f5225c feat(ui): add standalone operator approval links (#103698)
* feat(gateway): standalone approval deep-link page

Squash-rebased #103698 segment onto the typed-actions tip on current main.
Adds the tokenless /approve/{id} standalone approval UI served by the
gateway control-UI router, gateway-store ephemeral login fix (selectGateway
only on changed URL), and approval-page i18n strings.

Drift reconciliation: union-merged i18n translation-memory caches and
regenerated locale metadata via control-ui-i18n sync (33 approvalPage keys
remain English fallbacks in minor locales, as on the original branch).

(cherry picked from commit c82f56011bfe9f0debb8ebe052f14590c187340d)
(cherry picked from commit 80f5636a8b67a3d6a5f330620541a39d4ef3fe6f)
(cherry picked from commit a3e300d337a92bf1b593a0bb52b7ec4549910a21)
(cherry picked from commit 860ad01f9658bba54cb3d59644e5e1a032c0bb3f)
(cherry picked from commit d8b697b28a847950a1797da07fc0ae4c24928492)
(cherry picked from commit 8a654e3271fd5721358812f961a7a7bb386d6726)
(cherry picked from commit 2f776d2e7bf910271fcbd9697597f6f5478b0f30)
(cherry picked from commit 14e64e6e4d763be830830801eeec1a6f17441688)
(cherry picked from commit 4df9ec828d0034fdc76540ff0fe341e599b0f281)
(cherry picked from commit e52968f4ab)
(cherry picked from commit 7214fc25013966f99ff4b2d506aa2f5f789e2113)
(cherry picked from commit c6259ff79787c759c136086e1a54c9ead8e89539)
(cherry picked from commit a58d9f271d27481615f0c94a828704c563d5354f)
(cherry picked from commit dcf1cb6d98)

* fix(ui): preserve approval page gateway auth

* fix(ui): keep approval disconnects fail closed

* style(ui): format approval disconnect copy
2026-07-11 19:16:23 -07:00
Vincent Koc
dfa580e989 fix(plugins): complete session catalog contracts 2026-07-12 03:49:16 +02:00
Peter Steinberger
7a456e362d feat(channels): add typed cross-surface approval actions (#103679)
* fix(gateway): approval registry hardening and protocol-surface follow-ups

Follow-up delta to the merged #103579 head, rebased onto current main:
- gateway-protocol wire types derive from owner-module schema consts
  (types.ts tombstone) and ProtocolSchemas leaves the package index so the
  public plugin-sdk d.ts graph tree-shakes the registry declaration
- approval access authority follows the operator.approvals scope tier with
  reviewerDeviceIds as the opt-in restriction (cross-surface
  first-answer-wins; requester identity gates only legacy adapters)
- plugin node.invoke approvals register directly so unrenderable
  presentations fail closed before request routing
- exec-approval manager reconciliation with #103515 revocation hardening
  (resolution source attribution, one-shot ask-fallback consumption)
- surface-report pins and plugin-sdk API baseline refreshed; Swift models
  regenerated

* feat(channels): add typed operator approval actions

Squash-rebased #103679 segment onto the durable-approval-registry tip on
current main. Typed approval/command/select presentation actions replace
raw-string inference across slack/telegram/discord/matrix/imessage/whatsapp,
approval.resolve carries an explicit kind, and channel adapters map native
callback envelopes through the typed action registry.

Drift reconciliation: deprecated buildExecApprovalInteractiveReply assertions
dropped (#104650 removed the shims); worker_environments bootstrap-column
migration kept alongside the approval resolution_ref backfill; plugin-sdk API
baseline regenerated.

(cherry picked from commit 68765a5d39d2118c88a7a54d00387337912d4494)
(cherry picked from commit 8642ac12af142e4b751f4f30d4b114615e7e5f66)
(cherry picked from commit 036c4bc39499925fc03de16ec9302e346769350a)
(cherry picked from commit 19dc350d6bc34e29a5169c6bc80971b0ad12adde)
(cherry picked from commit fc978b0bad86aef421c79f6a211b25cc1b743c01)
(cherry picked from commit 10de4d1ed5071f9be6ad1ee5d1e32c0fa8c9d11c)
(cherry picked from commit 9a664ced1b1fa740172b258f355f1a82925ae41c)
(cherry picked from commit c5ff69abbf444139e9e007bfa45beb0f00ffea54)
(cherry picked from commit d466a80795)
(cherry picked from commit f5b4fe40dd5c961322f8553cc80b2fdfb3f6503e)
(cherry picked from commit 7340b4749a4cc4c72f7a41cce1bc9cb550cae038)
(cherry picked from commit a151f41808f23ae60b10305ccd2bc959b9169a86)

* fix(approvals): preserve typed transport ownership

* test(imessage): narrow chunked approval text

* refactor(protocol): remove retired type tombstone

* fix(plugin-sdk): align surface budgets after rebase

* docs(changelog): note typed operator approvals

* docs(changelog): defer typed approval release note
2026-07-11 18:31:05 -07:00
Peter Steinberger
11ea4df29c feat(fleet): per-cell disk limits, egress policy, backup/restore, and cell diagnostics (#104828)
* feat(fleet): per-cell disk limits, egress policy, backup/restore, logs, and doctor

- fleet create --disk <size> caps the container writable layer via --storage-opt;
  unsupported storage backends fail create with an actionable support-matrix
  error, and the limit replays across upgrade/restore through a fleet-owned
  container label because Podman inspect has no HostConfig.StorageOpt.
- fleet create --network bridge|internal adds an opt-in no-egress mode on
  Podman (published loopback port keeps working, verified live); Docker
  internal cells are rejected fail-closed because Docker does not publish
  loopback ports on internal networks.
- fleet backup/restore: per-tenant 0600 tar archives with manifest tenant
  binding, symlink/hardlink rejection, byte and path-segment budgets,
  root-bounded extraction, atomic no-overwrite publish, lease fencing, and
  Gateway token rotation on restore; failures preserve displaced data and
  never leave a force-stopped or half-started cell serving silently.
- fleet logs: ownership-asserted, bounded, token-redacted on both streams,
  with a generation re-check so a concurrent restore cannot leak a rotated
  token.
- fleet doctor: read-only per-cell audit of ownership labels, health,
  hardening drift, loopback port binding, token presence, network egress
  mode, and 0700 state-dir permissions; any failed finding exits nonzero.
  Cross-runtime checks are grounded in live-verified Docker 28/Podman 4.9
  inspect shapes (CapDrop vs EffectiveCaps, missing StorageOpt, missing
  network containers map).

Related: #104436 (v1 shipped in #104527)

* fix(fleet): harden streamed log redaction and root restore ownership

- redacting stream writer honors target backpressure, retains secret-prefix
  overlap across forced long-line flushes, and never splits a token between
  emitted chunks
- root-invoked restores repair ownership for explicit non-root user mappings
  instead of leaving root-owned 0700 state trees
- fleet logs merges the shipped --follow streaming surface (#104669) with the
  v1.1 token-redaction contract

* fix(fleet): stream partial log lines live and report phase-accurate restore recovery paths

- the redacting log writer emits safe text on every chunk (retaining only a
  possible token prefix) so unterminated progress output streams immediately
- restore failure notes distinguish pre-swap, displaced, and swapped states so
  operators recover the correct tree, and an unavailable runtime inspection is
  reported as an unverified replacement instead of silence

* fix(fleet): reject backslash archive paths, guard stderr pipes, and validate disk-limit labels in doctor

- restore/backup path rules reject literal backslashes so a tampered entry
  cannot validate as one path and extract as another on POSIX
- fleet logs handles broken pipes on stderr as well as stdout
- fleet doctor fails malformed disk-limit labels that would break
  upgrade/restore replay instead of reporting them as passing
2026-07-11 18:24:01 -07:00
Peter Steinberger
508f6a2996 refactor(config): retire legacy flat streaming keys to doctor-owned migration (#104693)
* chore(config): regenerate bundled channel config metadata for retired flat streaming keys

* refactor(config): retire legacy flat streaming keys to doctor-owned migration

* fix(config): restore zod locale installer dropped in rebase and repin SDK surface
2026-07-11 18:15:03 -07:00
Peter Steinberger
2829fe107c improve(ui): retire the Overview page for a chat-first start screen (#104819)
* feat(ui): replace Overview page with Connection settings and sidebar attention chips

* feat(ui): open new-session drafts on the chat start screen hero

* refactor(ui): drop old overview-hints paths after rename

* chore(i18n): sync control-ui locale bundles for connection/palette/attention keys

* test(ui): expect attention slot above the sidebar update card

* chore(i18n): re-sync locale bundles after rebase onto main

* test(ui): stub sidebar-attention RPCs in app-sidebar unit tests

* test(ui): use a non-secret-shaped token fixture in connection view test

* refactor(ui): destructure gateway connection in connection settings draft

* refactor(ui): keep connection settings code out of secret-scanner shapes

* test(ui): expect Connection in the settings Connections group

* improve(ui): idle-refresh sidebar attention chips for always-visible windows

* chore(i18n): refresh raw-copy baseline after rebase

* docs(ui): note the unknown-route chat fallback covers retired paths
2026-07-11 18:11:14 -07:00
Peter Steinberger
0d84eb4e70 fix(skills): read node-hosted skills from their publishing node (#104832)
* fix(skills): make node skill locators readable

* test(skills): track node skill temp directory

* chore: defer node skill changelog to release process
2026-07-11 17:54:14 -07:00
Peter Steinberger
ecefc6cab6 fix(slack): align App Home with active commands 2026-07-11 17:47:25 -07:00
Peter Steinberger
12f7d9c784 fix(slack): honor configured App Home command
Co-authored-by: Jonathan Tsai <jontsai@users.noreply.github.com>
2026-07-11 17:47:25 -07:00
Peter Steinberger
82667a66e5 feat(ui): editable file panel with CodeMirror and sessions.files.set hash-CAS writes (#104757)
* feat(gateway): add sessions.files.set workspace file write with hash CAS (#104698)

* feat(ui): CodeMirror file editor panel with CAS save + clickable tool-card paths (#104698)

* fix(gateway): issue the file CAS hash only for strict-UTF-8 text (#104698)

* docs(web): document the editable file detail panel (#104698)

* fix(gateway,ui): round-trip BOM and CRLF bytes through the file editor (#104698)

* fix(ui): keep mixed-line-ending files read-only in the file editor (#104698)

* fix(ui): re-gate editability when a conflict reload returns non-editable content (#104698)

* fix(gateway): reject NUL bytes in sessions.files.set replacement content (#104698)

* fix(gateway,ui): regenerate protocol bindings, fix prod types and lint for file editor (#104698)
2026-07-11 17:36:28 -07:00