Commit Graph

1827 Commits

Author SHA1 Message Date
Peter Steinberger
ff9cb0f679 fix(onboarding): leave session.dmScope unset so the personal-agent default "main" applies (#110225)
* fix(onboarding): leave session.dmScope unset so the personal-agent default "main" applies

* chore(onboarding): document deliberate dmScope personal-agent default

* docs(security): align formal-verification dmScope claim with the personal-agent default
2026-07-18 03:54:45 +01:00
Peter Steinberger
1607da89b7 fix: Claude CLI turns avoid observability overhead when unused (#110246)
* perf(agents): gate Claude CLI diagnostics on listeners

* refactor(infra): keep diagnostic listener state private

* fix(agents): bound serialized Claude diagnostics

* chore: remove release-owned changelog entry
2026-07-18 00:51:32 +01:00
Peter Steinberger
5bab0c2ea8 feat(slack): support running as a real Slack user (user identity) (#109837)
* feat(slack): add user-identity config surface (session token/cookie)

Introduce an account-level identity discriminator ("bot" default | "user") for
the Slack channel, plus sessionToken/sessionCookie secret fields for the
browser-session (user) path. Schema enforces structural coupling only
(identity="user" rejects appToken/signingSecret/relay/non-default mode);
credential presence is deferred to runtime like bot/app tokens. Account entries
inherit the top-level identity. Adds env fallback (SLACK_SESSION_TOKEN/COOKIE,
default account only), secret-contract registration, provenance *Source fields,
and UI hints. Config surface only; resolver/transport are later phases.

* refactor(slack): identity-aware operation-token resolver + dedup

Route Slack read/write token selection through a single identity-aware
resolveSlackOperationToken: identity="user" selects the browser-session token
for both operations (companion cookie attached later at client construction),
identity="bot" keeps the exact userToken/botToken + userTokenReadOnly behavior.
Delete the duplicated token-selection gate in action-runtime and route direct
sends/DM opens through the shared resolver with identity-neutral error wording.
Behavior-neutral for bot identity; net non-test LOC -2.

* refactor(slack): retarget user identity to xoxp + companion app

Replace the abandoned browser-session (xoxc/xoxd) approach for identity="user"
with the official path: authenticate as the human via the existing userToken
(xoxp) while a companion app (appToken/socket or signingSecret/http) carries
events. Remove sessionToken/sessionCookie config, env vars, secret-contract
entries, resolver fields, and their tests. Invert the schema coupling so
identity="user" permits the companion-app transport credentials, and drop the
now-vestigial user-identity structural guard entirely (identity is a permissive
discriminator; credential presence is a runtime concern). Resolver returns the
user token for user-identity reads and writes. Behavior-neutral for bot
identity.

* feat(slack): user-identity provider transport (xoxp + companion app)

Wire the identity="user" event transport. The companion Slack app runs Socket
Mode (appToken) or HTTP (signingSecret) while Bolt authenticates as the human
via the user token (no bot token). Startup auth.test runs on the user token and
its user_id becomes the self/mention target and self-send dedupe id (Bolt's
lazy per-event authorize populates context.botUserId=user_id, so the existing
self-event middleware drops the human's own messages). Identity-aware token
requirements and diagnostics; the bot-token identity warning is suppressed for
user identity. Behavior-neutral for identity="bot".

* feat(slack): user-identity setup, doctor, and docs

Add the setup wizard, doctor/status, and documentation for identity="user".
The wizard collects a user token plus the companion-app transport credential
(app token for socket, signing secret for http) and only persists identity when
"user" so bot setups keep byte-identical generated config; doctor validates the
user token via auth.test and warns on a missing transport credential; account
inspection reports user-token status. Message actions are gated on the active
identity's credential so user accounts expose actions. Docs add the exact
companion-app recipe (user scopes, on-behalf-of-user message events, socket/http
examples, the DM/group-DM-only-via-user-scope note, and self-send dedupe).
Behavior-neutral for identity="bot".

* test(slack): isolate user-identity provider tests to fix parallel flake

The new user-identity provider tests shared the globalThis-stored Slack test
client/handlers across files under parallel isolate:false, so their reaction
closures could reference a prior file's state and intermittently fail sibling
monitor tests (monitor.tool-result reactions). Track started monitors and
abort/await them all in afterEach (even on failed assertions), reset the shared
auth.test/mock state, and dispose the global Slack test runtime per file via a
new disposeSlackTestRuntime helper. Full Slack suite green across repeated
parallel runs.

* fix(slack): regenerate channel config metadata after rebase

* fix(slack): resolve setup consistent-return and doctor dead-export lint

* style: format install script test

* docs(slack): regenerate docs map for user-identity section

* test(slack): use renamed createSlackBoltApp token param in interop test

The rebase folded main's new wrapReceiver test into the renamed
createSlackBoltApp signature (botToken -> token); update the call site.
2026-07-17 23:23:21 +01:00
Alex Knight
ddb4ed9a47 feat: trace Claude Code CLI model calls (#108304)
* feat: trace Claude CLI model calls

* fix: align Claude CLI trace hierarchy

* fix: distinguish model request and turn telemetry

* fix: satisfy diagnostics CI checks

* fix: distinguish agent-turn telemetry

---------

Authored-by: Alex Knight <15041791+amknight@users.noreply.github.com>
2026-07-18 06:23:49 +10:00
Peter Steinberger
5366b6de81 refactor: store gateway restart recovery in SQLite (#110014)
* refactor: move restart sentinel state to sqlite

* fix: satisfy restart sentinel architecture gates

* test: avoid cold startup migration timeout

* fix: bound durable restart notice retries

* test: type restart notice contention mock

* fix: detect legacy restart sentinel before reads

* fix: keep delivery attempt result internal

* fix: narrow restart sentinel preflight guard
2026-07-17 17:43:22 +01:00
xingzhou
0a868179e4 fix(session): stop repeated restart recovery after retry budget (#96230)
* fix(session): bound restart recovery across gateway restarts

Co-authored-by: Mason Huang <masonxhuang@proton.me>

* style(session): format restart recovery changes

* fix(session): fence recovery notice state

* test(session): align internal recovery types

* test(session): type recovery completion fixture

* style(session): satisfy recovery lint rules

* test(plugin-sdk): split recovery boundary coverage

* test(plugin-sdk): use tracked recovery temp dirs

* fix(session): preserve stale admission errors

* fix(session): close recovery lifecycle races

* fix(session): rotate rejected recovery dispatch ids

* fix(session): enforce recovery quarantine boundaries

* fix(session): close restart recovery exhaustion gaps

* fix(session): preserve recovery command narrowing

* test(session): type restart recovery fixtures

* fix(session): enforce restart recovery quarantine

* fix(session): close restart recovery races

* fix(session): type recovery lifecycle state

* fix(session): enforce recovery ownership fences

* fix(session): fence recovery lifecycle completion

* fix(session): quarantine cross-process recovery

* fix(session): retire stale recovery ownership

* fix(session): restore rejected recovery admission

* fix(session): preserve restored recovery target

* fix(session): retry pending recovery races

* fix(session): preserve concurrent recovery aborts

* fix(session): quarantine recovery lifecycle state

* fix(session): settle exact recovery delivery fences

* fix(session): keep recovery restoration internal

* fix(session): close recovery admission races

* fix(session): retry durable recovery rollback

* fix(session): guard cached recovery settlement

* fix(session): close recovery ownership gaps

* fix(session): resume after delayed recovery rollback

* fix(session): finalize unrecoverable restart state

* fix(session): retry admitted recovery restoration

* fix(session): preserve recovery cleanup guarantees

* fix(session): restore failed terminal settlement

* chore(plugin-sdk): refresh API baseline

* fix(session): close recovery owner retry races

* test(session): type recovery owner fixture

* refactor(session): remove obsolete owner validator

* fix(session): preserve explicit abort recovery

---------

Co-authored-by: Mason Huang <masonxhuang@proton.me>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-17 15:36:09 +01:00
Peter Steinberger
b319493a52 improve: let Code Mode use declared tool result shapes (#109813)
* feat(agents): add Code Mode output contracts

* perf(agents): defer untrusted tool schemas

* chore(plugin-sdk): refresh API baseline

* fix(agents): preserve deferred schema markers

* fix(agents): preserve policy-blocked tool results

* fix(agents): preserve nullable output contracts

* fix(agents): reject policy blocks from success contracts

* fix(agents): preserve output contracts through normalization

* test(agents): type normalized tool fixtures

* fix(agents): validate catalog results before projection

* fix(agents): keep result snapshots internal

* fix(agents): fail closed on unrenderable unions

* fix(agents): preserve empty result markers

* test(agents): keep result fixture discriminator literal

* test(agents): use native own-property check
2026-07-17 14:46:37 +01:00
Peter Steinberger
da69daeb72 feat(onboarding): recommend plugins and skills from installed apps (#109668)
* feat(onboarding): recommend plugins and skills from installed apps

Scan installed macOS apps during classic onboarding (TCC-free), gather
candidates from official catalogs + ClawHub search, let the configured
model pick genuine matches, and offer an opt-in multiselect install step.
Adds a device.apps node-host command (default-off sharing, Android-parity
envelope) so remote gateways can request a paired Mac's inventory, and a
wizard.appRecommendations kill switch. Custom setup-inference completions
no longer inherit the 32-token verification-probe output cap.

* feat(onboarding): recommend apps in guided flow

* fix(onboarding): harden app recommendations against ClawHub self-promotion

Third-party ClawHub skills are never pre-selected regardless of model tier
(publisher-controlled listing text reaches the matcher prompt and could
promote itself); their labels now say they install third-party code.
Installed-app scans follow symlinked .app bundles. Matcher output stays
bounded by the resolved model's own maxTokens budget (documented invariant).

* fix(onboarding): key official catalog candidates by resolved plugin id

Real catalog entries are package manifests without a top-level id; keying the
candidate map and channel/provider classification by entry.id collapsed the
whole official catalog into one undefined-keyed entry, so no official plugin
or channel was ever recommended. Regression test runs against the bundled
catalogs.

* fix(onboarding): satisfy lint, types, deadcode, and migration gates

Split the guided-onboarding test into a self-contained custodian suite to stay
under max-lines. Narrow app-recommendation exports (drop dead node-payload
normalizer, unexport internal types/helpers, route candidate tests through the
public API), replace map-spread with a helper, unexport device.apps result
types, add installedAppsSharing to node-host migration expectations, cast the
wizard multiselect mock, and regenerate the docs map.

* test(onboarding): register new live test in the shard classifier
2026-07-17 14:07:59 +01:00
WhatsSkiLL
4d3b18811e feat(android): add Wear real-time Talk controls (#109483)
* feat(android): add Wear real-time Talk controls

* fix(android): satisfy Wear Talk CI checks

* fix(talk): remove unused client language parameter

* fix(android): harden Wear realtime Talk routing

Co-authored-by: IWhatsskill <284122573+IWhatsskill@users.noreply.github.com>

* chore(android): refresh Wear Talk metadata

* chore(android): align native i18n baseline

---------

Co-authored-by: IWhatsskill <284122573+IWhatsskill@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-17 13:46:05 +01:00
DinoMC
017217bae3 fix(heartbeat): remember silent task results for the next user turn (#95838)
* fix(heartbeat): retain silent task outcomes

Co-authored-by: DinoMC <9079110+DinoMC@users.noreply.github.com>

* fix(heartbeat): keep outcome type internal

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-17 13:24:48 +01:00
Peter Steinberger
f3d1f02dc1 refactor: move MCP OAuth state to SQLite (#109844)
* refactor(mcp): move OAuth state to SQLite

* refactor(mcp): tighten OAuth module boundaries

* chore: refresh PR merge ref

* fix(mcp): align storage docs and merge checks

* fix(mcp): surface OAuth reauthorization status
2026-07-17 12:15:16 +01:00
Peter Steinberger
a83ed13204 feat(onboard): guided onboarding becomes the custodian flow (#109841)
* feat(onboard): guided onboarding becomes the custodian flow

Question zero asks for discovery consent up front (full access recommended,
guarded asks once or configures manually; persisted as wizard.accessMode and
honored on reruns). Discovery quietly collects auto-ladder failures into one
summary with details behind 'See other options', quips about detected coding
agents, and announces the working route as a default with an easy undo.
After inference and the memory offer (skipped when discovery was declined),
fresh installs auto-apply the standard setup plan and hatch the agent
directly in the terminal; configured installs (pre-existing model or gateway
config) stay verification-only and never reinstall or restart the Gateway
service. Setup-apply failures fall back to the conversational chat.
Remote-gateway onboarding keeps its legacy chat handoff explicitly.
listManualSetupInferenceOptions lists manual providers without scanning.

* docs(onboarding): add custodian redesign implementation plan (living doc)

* docs: regenerate docs map for onboarding-redesign page
2026-07-17 11:36:41 +01:00
Peter Steinberger
3fee3cc6fa docs(gateway): expand rate limiting into a full reference page 2026-07-16 22:36:23 -07:00
Peter Steinberger
d54da31541 fix(gateway): surface retryAfterMs on rate-limited auth rejections and document rate limiting (#109630)
* fix(gateway): surface retryAfterMs on rate-limited auth rejections and document rate limiting

* docs: refresh generated docs map

* chore: defer release-owned changelog entry
2026-07-16 21:44:43 -07:00
snowzlmbot
17c2ce05d8 fix(secrets): keep startup alive when TTS SecretRefs are missing (#101265)
* fix(secrets): degrade missing TTS SecretRefs at startup

* test(secrets): keep non-activating startup strict

* test(secrets): mark denied key fixture synthetic

* test(secrets): use synthetic TTS key fixture

* test(secrets): use neutral TTS key placeholder

* test(secrets): isolate TTS key placeholder

* test(secrets): shorten TTS ref fixture name

* test(secrets): normalize synthetic credential fixtures

* test(secrets): isolate optional redaction coverage

* fix(secrets): preserve degraded TTS ref ownership

* refactor(secrets): keep optional resolver internal

* test(secrets): cover default provider alias misses

* test(secrets): pin explicit provider ownership

* style(secrets): format optional assignment imports

* refactor(secrets): keep optional metadata private

* style(secrets): restore collector file header

* fix(secrets): isolate unavailable SecretRef owners

Co-authored-by: snowzlmbot <293528334+snowzlmbot@users.noreply.github.com>

* test(secrets): complete provider fixtures

* style(status): avoid degraded path shadowing

* style(secrets): satisfy runtime lint

* refactor(secrets): keep error codes internal

* fix(secrets): keep unowned assignments fail closed

* fix(secrets): preserve provider resolution batching

* fix(secrets): normalize stalled resolution errors

* fix(secrets): reject provider limit violations

---------

Co-authored-by: snowzlmbot <293528334+snowzlmbot@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 21:07:01 -07:00
Peter Steinberger
b44bab171d docs(sandbox): document multiple folders per agent (#109530)
* docs(sandbox): document multiple agent folders

* style(docs): format sandbox examples

* docs: refresh generated map
2026-07-16 19:40:25 -07:00
iloveleon19
382d570cbf feat(channels): add unified implicit mention policy (#108829)
* feat(mattermost): add thread.requireExplicitMention to opt out of thread auto-follow

Mattermost treats any reply in a thread the bot has participated in as an
implicit mention, so requireMention only gates the first message and the bot
then answers follow-ups addressed to other people for the participation TTL.
Slack exposes channels.slack.thread.requireExplicitMention for exactly this;
Mattermost had no equivalent and its strict schema rejected the key.

Add channels.mattermost.thread.requireExplicitMention (channel + per-account),
mirroring Slack. When set, thread participation no longer counts as a mention.
Default (unset/false) keeps today's auto-follow behavior unchanged.

Related: #108269

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

* feat(channels): add implicit mention policy foundation

* feat(channels): unify implicit mention policy

Co-authored-by: leon <dodoma0919@gmail.com>

* refactor(channels): keep implicit policy inside evaluator

* fix(channels): use exported implicit mention type

* chore(channels): satisfy extension lint

* fix(config): break implicit mention type cycle

* fix(plugin-sdk): account for implicit mention config export

* refactor(config): isolate implicit mention schema

* chore(plugin-sdk): align implicit mention surface budget

* fix(config): remove unused schema re-export

---------

Co-authored-by: leon <dodoma0919@gmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 17:16:01 -07:00
Peter Steinberger
333409908d docs: define SecretRef failure isolation policy (#109430) 2026-07-16 17:05:20 -07:00
Peter Steinberger
349f78776d fix(models): refresh bundled provider catalogs (#109410)
* fix(models): refresh bundled provider catalogs

* docs(models): refresh generated docs map

* fix(xiaomi): keep provider helper private

* chore(release): defer catalog release note
2026-07-16 16:47:25 -07:00
Peter Steinberger
0f32033d78 fix(ui): add thinking level to new cloud sessions (#108679) 2026-07-15 23:54:00 -07:00
Peter Steinberger
d8b723fb00 fix: channel turns recover safely after gateway restart (#108283)
* fix(gateway): recover channel turns safely after restart

* refactor(gateway): keep recovery identity internal

* refactor(gateway): keep recovery metadata private

* fix(gateway): preserve recovery action authority

* fix(gateway): close recovery lifecycle gaps

* fix(gateway): fail closed on missing delivery receipts

* fix(gateway): fail closed on unmirrorable replies

* fix(gateway): persist terminal delivery intent

* fix(gateway): align recovery lifecycle types

* fix(gateway): require exact terminal thread receipt

* fix(gateway): close recovered terminal tool calls

* test(gateway): type terminal tool correlation

* fix(gateway): satisfy restart recovery CI contracts

* fix(gateway): require terminal tool correlation

* fix(agents): scope recovery receipts to source turns

* fix(gateway): fail closed without restart correlation

* fix(gateway): dedupe terminal source redelivery

* fix(agents): keep recovery tool results causal

* test(auto-reply): clean recovery fixture directories

* fix(gateway): allow live terminal sends without recovery claims

* fix(agents): reconcile delivered sends through restart aborts

* fix(agents): keep recovery continuations in source turns

* fix(agents): keep source-less sends non-terminal

* fix(auto-reply): dedupe active source redelivery

* fix(agents): harden recovery receipt contracts

* fix(agents): admit terminal recovery successors

* docs(recovery): document canonical receipt ownership

* fix(agents): fail closed on stale turn authority

* test(auto-reply): assert rebound session state

* fix(plugins): keep restart recovery hook list internal
2026-07-15 23:01:26 -07:00
Peter Steinberger
b624abfc69 fix(discord): stop channel presence greetings for unrelated guild members (#108448)
* fix(discord): scope presence wakes to channel viewers

* chore: remove release-owned changelog entry

* fix(discord): bound presence permission lookups

* test(discord): bind presence fetch mock

* fix(discord): keep presence lookup overflow retryable
2026-07-15 13:51:48 -07:00
Peter Steinberger
126b549a26 feat: run and reclaim cloud worker sessions from Control UI (#108398)
* feat(gateway): finish cloud worker session reclaim

* chore(gateway): refresh cloud worker artifacts

* fix(gateway): preserve recovery environment narrowing

* test(gateway): complete worker tunnel mock

* fix(gateway): harden cloud worker recovery

* fix(gateway): serialize forced worker teardown

* fix(gateway): handle replaced workspace directories

* fix(gateway): preserve forced destroy receiver

* test(ui): cover cloud worker reclaim flow

* fix(gateway): close final worker recovery races

* fix(ci): align cloud worker generated surfaces

* test(gateway): satisfy worker queue lint

* fix(gateway): recheck remote workspace after lease fence

* chore: move cloud worker release note to PR
2026-07-15 11:24:04 -07:00
Peter Steinberger
a97bdfb687 feat(agents): narrow gateway tool to read-only config
Phase 3 of #107237. Removes config.apply/config.patch/restart from the
regular-agent gateway tool (mirroring Phase 2's update.run removal); only
config.get and config.schema.lookup reads remain. Persistent config changes
and restarts now go exclusively through the human-approved openclaw
delegation path — closing the last unmediated agent config-write surface.
gateway stays owner-only/control-plane gated (config reads expose secrets and
host topology). Legacy setups can re-enable writes via the existing per-agent
tool allowlist; no new config key. Net -2271 LOC.

Refs #107237
2026-07-15 01:56:31 -07:00
Peter Steinberger
f3e6042119 fix(ui): preserve explicit steer queue mode (#108121) 2026-07-15 01:09:55 -07:00
clawsweeper[bot]
3a208a5068 fix(discord): prevent presence wake floods after reconnects (#107969)
* feat(discord): throttle online-presence events after gateway reconnects

After a Discord gateway (re)connect the presence replay burst emitted one
system event per member, waking the agent each time. Add a per-account
emission gate: a post-reconnect suppression window (default 5 min), a
sliding-window burst limit (default 8/60s, logged once per episode), and
a configurable per-user greeting cooldown (default 8h). New guild
presenceEvents knobs: cooldownSeconds, reconnectSuppressSeconds,
burstLimit, burstWindowSeconds.

* fix(discord): preserve presence throttle retries

* fix(discord): preserve presence throttle retries

* fix(discord): scope presence throttle per guild

Co-authored-by: openclaw-clawsweeper[bot] <openclaw-clawsweeper[bot]@users.noreply.github.com>

* fix(discord): keep presence gate internals private

Co-authored-by: openclaw-clawsweeper[bot] <openclaw-clawsweeper[bot]@users.noreply.github.com>

---------

Co-authored-by: openclaw-clawsweeper[bot] <openclaw-clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Peter Steinberger <peter@steipete.me>
2026-07-14 22:02:53 -07:00
Monkey-wusky
4a9a556a3a fix(config): reject zero-value resetArchiveRetention to prevent silent data loss (#104516)
* fix(config): reject zero-value resetArchiveRetention to prevent silent data loss

* fix: add braces to guard clauses for curly lint rule

* fix: normalize numeric values and cover pruneAfter fallback in migration

* fix: reject zero-value pruneAfter at schema level to close fallback gap

* fix: independently check and repair both retention fields in migration

* fix: split doctor diagnostics into field-specific rules and messages

* fix: remove unused local in migration test helper

* fix: repair 5 lint errors (curly braces, zero-fraction, narrow value)

* fix(doctor): rewrite zero resetArchiveRetention to false instead of deleting it

Deleting a zero resetArchiveRetention caused the runtime to fall back to
pruneAfter (default 30d), which contradicted the doctor output that
claimed archives would be kept indefinitely.  Only an explicit false
value produces indefinite retention per the documented schema.

- P1: Rewrite zero resetArchiveRetention to false in the doctor
  migration apply callback, matching the promised indefinite-retention
  behavior.
- P3: Update the pruneAfter rule warning to describe eligible
  stale/non-preserved session entries instead of "all sessions".

* fix(config): repair zero retention safely

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Peter Steinberger <peter@steipete.me>
2026-07-14 21:47:40 -07:00
Peter Steinberger
4f0e131cd2 feat(ui): run sessions on cloud workers (#107670)
* feat(ui): add cloud session targets

* test(ui): cover cloud session attachments

* test(ui): use recovery token fixture

* test(ui): record cloud locale fallbacks

* fix(ui): harden cloud session recovery

* fix(ui): track cloud handoff phase

* fix(ui): close cloud recovery escape paths

* fix(ui): finish cloud recovery hardening

* fix(ui): recover ambiguous cloud session creation

* fix(ui): isolate stale cloud creation recovery

* test(ui): preserve cloud recovery literals

* fix(ui): complete cloud session release artifacts

* chore: move cloud release note to PR body

* docs(ui): name cloud session menu exactly
2026-07-14 12:44:11 -07:00
Shakker
e63e49b1b0 fix: prevent Bonjour probe retry loops (#107710)
Prevents duplicate Bonjour advertisement attempts by delegating probing, conflict resolution, retries, and interface republishing to ciao.

Related: #98448

Prepared head SHA: 4bd1638acf

Co-authored-by: Shakker <165377636+shakkernerd@users.noreply.github.com>
Reviewed-by: @shakkernerd
2026-07-14 19:28:47 +01:00
Jesse Merhi
00364ee777 improve: warn before non-ClawHub plugin installs (#102197)
Merged via squash.

Prepared head SHA: e08d9e737d
Co-authored-by: jesse-merhi <79823012+jesse-merhi@users.noreply.github.com>
Co-authored-by: jesse-merhi <79823012+jesse-merhi@users.noreply.github.com>
Reviewed-by: @jesse-merhi
2026-07-15 03:25:36 +10:00
Peter Steinberger
084d1d9637 feat(control-ui): upload files into terminals (#107364)
* feat(control-ui): add terminal file uploads

* fix(control-ui): protect Windows terminal uploads

* fix(control-ui): satisfy terminal upload gates

* chore(ui): translate terminal upload labels

* fix(control-ui): reject unknown Windows upload shells

* fix(control-ui): harden Windows upload paths

* fix(control-ui): retry terminal upload cleanup

* chore(ui): reconcile locale translation memory

* fix(control-ui): validate terminal upload inputs

* fix(control-ui): retry failed upload cleanup

* chore(ui): refresh terminal upload locale metadata

* fix(terminal): integrate uploads with session recovery

* refactor(control-ui): isolate terminal upload transport

* fix(control-ui): keep upload helper types private
2026-07-14 09:33:39 -07:00
Peter Steinberger
5f13921c26 fix: preserve Fable thinking on Claude CLI routes (#107636)
* fix(anthropic): preserve Claude CLI effort on root gateways

* chore: leave release notes to release workflow
2026-07-14 09:15:21 -07:00
Peter Steinberger
6d31c162f9 fix: keep root Claude live sessions usable (#107606)
* fix(agents): support Claude live sessions as root

* chore: leave release notes to release workflow
2026-07-14 08:46:58 -07:00
Peter Steinberger
2ecc6b6b6b fix(ui): show restart banner for unapplied config (#107577)
* fix(ui): derive config apply state from gateway

* test(ui): align applied config hash coverage

* test(ui): follow config autosave flow

* fix(ui): guard applied config refreshes

* fix(ui): reconcile patched config revisions

* fix(ui): prevent stale config apply polling

* chore: leave release notes to release flow

* refactor(config): split applied revision helpers

* style(config): format gateway methods

* fix(i18n): refresh Korean native glossary hash
2026-07-14 08:43:35 -07:00
Peter Steinberger
21d548a7ff fix: harden cloud worker admission and remote turns (#107043)
* fix(cloud-workers): harden worker dispatch

* fix(cloud-workers): enforce Crabbox AWS admission contract

* fix(cloud-workers): sanitize inference terminals

* fix(cloud-workers): bound inference stream work

* fix(cloud-workers): reject unresolved tool deltas

* refactor(cloud-workers): isolate terminal projection

* fix(cloud-workers): satisfy extension lint

* fix(cloud-workers): reject forbidden leases before polling

* fix(cloud-workers): keep helper types internal

* fix(gateway): reject late tool call deltas

* fix(crabbox): clean invalid inspected leases

* refactor(crabbox): extract inspect parser

* style(crabbox): format worker provider

* fix(crabbox): close worker lease cleanup gaps

* docs(cloud-workers): correct runtime contracts

* docs(cloud-workers): match runtime error
2026-07-14 07:24:43 -07:00
Peter Steinberger
f59a0352b3 feat(discord): route online presence arrivals to agents (#107451)
* feat(discord): add online presence agent events

* fix(discord): harden presence event payloads

* fix(discord): satisfy presence lint contracts

* fix(heartbeat): run notification event wakes

* fix(discord): use wake heartbeat contract

* fix(discord): harden presence snapshot delivery

* chore: remove release-owned changelog entry

* fix(discord): remove unused presence type export

* fix(discord): keep presence config below loc limit

* fix(discord): reserve presence cooldown atomically
2026-07-14 07:22:11 -07:00
Peter Steinberger
d79573d457 fix: avoid redundant image-model calls for vision agents (#107311)
* fix: route native image inspection directly

* fix: narrow image fallback route

* style: satisfy image tool size ratchet

* test: align image fallback auth coverage

* fix: complete native image routing
2026-07-14 02:54:34 -07:00
Michael Appel
18ec9ce8f7 fix: block workspace dotenv endpoint overrides [AI] (#103914)
* fix: block workspace dotenv endpoint overrides

* docs: clarify workspace endpoint env sources

* style: format dotenv suffix blocklist

---------

Co-authored-by: Pavan Kumar Gondhi <pavangondhi@gmail.com>
2026-07-14 12:51:15 +05:30
Peter Steinberger
eb7c151d07 improve(doctor): keep regular runs problem-focused and compact (#106968)
A regular openclaw doctor run buried findings under healthy-state noise:
wizard banner, skills/plugins inventory boxes, healthy confirmations,
per-skill install hints, identical per-agent model-auth boxes, and one
warning line per stale plugin config path.

Doctor now prints problems and fixes only: security/Claude CLI notes are
silent when healthy, plugins box lists only errored ids, unusable skills
collapse to a count plus name list, model-auth findings aggregate across
agents with (agents: ...) attribution, and stale plugins.allow/deny/entries
references group into one line. Inventory stays in openclaw skills check,
openclaw plugins list, openclaw security audit, and openclaw models status.
docs/gateway/doctor.md updated.
2026-07-13 19:25:29 -07:00
Peter Steinberger
b573a3b767 docs(fleet): remove MVP framing 2026-07-13 17:56:18 -07:00
Qiong
8592b87c39 fix(node-pairing): require operator.admin to approve fs.listDir nodes (#105936) (#106004)
* fix(node-pairing): require operator.admin to approve fs.listDir nodes (#105936)

* fix(gateway): align node command authorization

---------

Co-authored-by: joshavant <830519+joshavant@users.noreply.github.com>
2026-07-13 16:40:55 -05:00
Peter Steinberger
995c75baa0 fix(ci): restore current-main quality gates (#106751)
* fix(ci): restore Control UI quality gates

* fix(ci): repair dead export cleanup fallout

* fix(ci): repair latest main quality gates

* fix(ci): satisfy current-main gate contracts

* docs: format Cloud Workers guide

* test: isolate context lookup module
2026-07-13 13:54:03 -07:00
Peter Steinberger
6029bf1690 docs(cloud-workers): add the Cloud Workers gateway page
Explains dispatching sessions to ephemeral cloud machines: what runs
where, cloudWorkers profile configuration (crabbox provider, setup
command, bundle vs npm install channels), sessions.dispatch usage, the
security model (closed ingress, minted credentials, host-key pinning,
epoch fencing, CAS transcripts), and troubleshooting from the live AWS
E2E.
2026-07-13 13:05:02 -07:00
Peter Steinberger
246cb48849 docs(cron): remove retired run-log settings 2026-07-13 11:41:27 -07:00
Peter Steinberger
59003634ad refactor(cron): retire cron_run_logs; ledger-owned retention and cancellation
Stops the legacy run-log dual-write, auto-imports remaining rows and drops
the table at state-DB open (table-presence guard: self-heals downgrade
round-trips), keeps the newest 2000 terminal runs per job in the ledger,
retires cron.runLog config via doctor, and moves live-run cancellation to
src/cron behind the shared task control seam.

Part 2 of 2 for #106041.
2026-07-13 11:41:27 -07:00
Peter Steinberger
e98c7dfbcb feat(cloud-workers): session placement, dispatch, and worker turn routing (#106332)
* feat(gateway-protocol): add session placement schema

Closed state discriminator for session execution placement (local/requested/provisioning/syncing/starting/active/draining/reconciling/reclaimed/failed), sessions.dispatch params, and worker-admission transcript/live cursor extensions. Swift protocol models mirror the schema.

* feat(state): add worker session placement table

worker_session_placements rows carry placement state, transition generation, worker ownership metadata, ACK cursors, and the turn claim columns used for atomic admission.

* feat(cloud-workers): add durable placement state machine store

SQLite-backed placement store split by concern: state table (placement-state), discriminated record types + shape invariants (placement-record), row codec + CAS transition values (placement-row-codec), atomic turn-claim admission/release/waiters (placement-turn-claims), and lifecycle CAS transitions (placement-store).

* feat(cloud-workers): sync workspaces and attach sessions to worker environments

Environment service session attachment + turn credentials, tunnel workspace commands over a dedicated SSH runner, and git/plain workspace sync into $HOME/.openclaw-worker/workspaces with an immutable manifest. Symlink escapes are rejected locally before transfer (macOS openrsync stat-fails them opaquely) and again by the remote manifest guard.

* feat(worker): run one-shot embedded turns from launch descriptors

Worker runtime executes a single embedded turn from a stdin launch descriptor and reports completed/failed/fenced on stdout for the gateway launcher. Terminal lifecycle live events are deferred past the final transcript flush; transcript projection helpers are shared via transcript-message instead of duplicated in the runtime.

* feat(cloud-workers): dispatch placements and route worker turns

Dispatch service drives local->requested->provisioning->syncing->starting->active with failure teardown (placement-dispatch-failure) and restart/runtime recovery incl. lost-worker reclaim (placement-dispatch-recovery). Worker turn launcher claims the placement turn atomically, builds a windowed launch descriptor (worker-turn-payload), runs the remote one-shot worker, and reconciles the committed transcript; agent runners route turns through the session placement admission provider.

* feat(gateway): expose session placement RPCs and startup reconciliation

sessions.dispatch RPC with lifecycle admission barriers, operator-facing placement projection on session listings, placement-aware session reset guard, and startup/interval reconciliation wiring for worker placements.
2026-07-13 08:03:53 -07:00
Peter Steinberger
df3fe6a4f2 feat(worktrees): configurable cleanup limits (max count, max total size) with Settings UI (#106224)
Config surface worktrees.cleanup.{maxCount,maxTotalSizeGb} (0/unset disables),
enforced by hourly gc, worktrees.gc RPC, and openclaw worktrees gc: least
recently active session/Workboard worktrees are snapshotted and removed until
count and total size fit. Manual worktrees, live locks, run leases, and active
session owners are never limit-evicted. Settings -> Worktrees gains a Cleanup
section with debounced, quota-aware stepper controls. Closes #106213.
2026-07-13 06:00:33 -07:00
Vincent Koc
e474ba38e8 fix(sqlite): serialize offline maintenance with gateway (#106210) 2026-07-13 18:15:32 +08:00
Peter Steinberger
6cd1133858 feat(cloud-workers): openclaw worker mode running the embedded loop on the box (#105865)
* feat(cloud-workers): add restricted worker runtime

* test(cloud-workers): cover worker runtime contracts

* docs(cloud-workers): document worker mode

* fix(worker): bound connection lifecycle

* fix(worker): serialize transcript flushes

* fix(worker): fail stop stale transcript bases

* fix(worker): degrade lossy live streaming

* test(worker): cover inference reconnect fencing

* refactor(worker): split RPC clients

* refactor(worker): split connection transport

* refactor(worker): split embedded runtime

* refactor(worker): narrow worker module exports
2026-07-13 02:34:31 -07:00
Peter Steinberger
bafabba0df fix(gateway): preserve Control UI turns across restarts (#106151)
* fix(gateway): preserve Control UI turns across restart

* perf(sessions): index restart recovery state

* fix(sessions): avoid replaying pre-admitted turns

* fix(sessions): index per-entry recovery status

* fix(sessions): guard restart failure notices

* fix(sessions): preserve terminal claims across admissions

* fix(sessions): retry failed recovery notices

* fix(sessions): harden restart retry ownership

* fix(gateway): tighten restart recovery typing

* fix(sessions): close restart recovery races

* refactor(sessions): split restart recovery ownership

* chore(sessions): clean restart recovery lint

* chore: drop release-owned changelog entry

* fix(gateway): satisfy restart recovery guards

* test(gateway): cover Control UI durable admission
2026-07-13 02:08:56 -07:00