* fix(cron): hint after disable about list filtering disabled jobs by default
* fix(cron): use !params.enabled in disable-hint guard for oxlint compliance
* docs(cron): clarify disabled jobs in list output
* fix(cron): keep disable hint interactive
* test(cron): use exported store snapshot helper
* test(cron): create disable-list regression job via service
* docs(cron): defer list default contract wording
* test(cron): tighten disable list coverage
Co-authored-by: Kate Stahnke <35552+kate@users.noreply.github.com>
* docs(cron): document enabled-only list default
Co-authored-by: Kate Stahnke <35552+kate@users.noreply.github.com>
---------
Co-authored-by: Kate <35552+kate@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
A Gateway timeout or closed connection now fails the command with an
actionable stderr hint instead of silently re-running the whole turn
embedded under a fresh gateway-fallback-* session. The silent fallback
could double-execute side effects (the Gateway may still finish an
accepted turn), returned context-free answers to --session-key callers,
and ran with the CLI host's local config. --local remains the only
embedded execution path.
Also deletes the resultMetaOverrides plumbing (the fallback was its only
writer) and the fallback marker fields added in #111645.
Channel plugins declare package env triggers in manifests, and ambient
environment variables count as "channel configured". A dev gateway
(gateway run --dev) inherits the operator's shell, so real channel
credentials silently configured channels and could connect development
instances to live services (observed with reef and a Telegram-range
connection during isolated stress testing).
Dev mode now drops presence signals whose only sources are env or
manifest-env across activation planning, auto-enable, autostart, health
recovery, readiness, reloads, and startup warnings. Explicit
channels.<id> config still works, --dev-ambient-channels restores the
old behavior, and startup logs the suppressed channel ids once. Non-dev
gateways are unchanged.
* fix(plugins): load newest managed generation when a prior install lingers
An upgrade writes a plugin's new version into a distinct managed project
directory (an `__openclaw-generation__` dir) without removing the previous one.
The persisted install record keeps pointing at the older, still-present
directory, so `mergeRecoveredManagedNpmRecord` falls through to returning the
persisted record and the runtime imports the stale version even though the newer
generation is installed. `isUnavailableManagedNpmInstallRecord` only self-heals
when the persisted path is gone, so an upgrading install (both directories
present) is not covered — `plugins inspect <id> --runtime` reports the old
version and `install`/`update` appear to silently no-op.
- Recovery now selects the highest-version record per plugin id across the
legacy flat dir and any generation dirs, instead of whichever project root
sorts last (generation-dir suffixes are hashes, so on-disk order is unrelated
to version).
- When the recovered managed install is a strictly newer version at a different
path, repoint to it, reusing the metadata merge the unavailable-path branch
uses. The repoint is gated to persisted records that live inside the managed
npm root, so intentional custom/outside npm installs are left untouched.
This is a recovery-layer self-heal, so it also repairs installs that already
diverged from an earlier upgrade.
Refs #107228
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(plugins): honor active managed generations
Recover ambiguous managed installs by package recency only when no usable active ledger path exists, and let doctor retire non-authoritative generations safely.
Co-authored-by: Peter Lindsey <peter@lindsey.jp>
* test(plugins): use shared temp cleanup
* fix(plugins): compare active paths per platform
* fix(plugins): use managed install timestamps
* test(plugins): timestamp managed project roots
* test(plugins): exclude retired legacy recovery
* refactor(plugins): keep recovery candidate private
---------
Co-authored-by: Peter Lindsey <peter@lindsey.jp>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* fix: bound misc unbounded fs.readFile calls; remove unused fs import
* fix: decode buffer to string before passing to string consumers
readRegularFile and readRegularFileSync return { buffer, stat },
not a string. All 4 new call sites passed the raw object to functions
expecting a string (JSON.parse, RegExp.test, template literals, etc.),
causing TS2345 type errors and runtime failures.
Fix each call by extracting .buffer and calling .toString('utf8')
before passing the result to string consumers.
* style: fix oxfmt formatting in config-set-input.ts
* fix: bound config and trajectory metadata reads
Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>
* refactor: isolate bounded read ownership
Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* fix(gateway): emit config.changed from the reload committer for every accepted write
Agent config_set, CLI, and doctor writes reach the gateway through the file
watcher's reload path, which never broadcast config.changed - only direct RPC
writes did. Move the broadcast to a single onConfigCandidateCommitted hook in
the reload committer so all writers notify connected UIs, including
runtime-skipped commits (writer-intent echo suppression, reload mode off),
and delete the duplicate RPC-side broadcasts.
* feat(ui): sync chat follow-up and commentary prefs across devices
Add chatPersistCommentary and chatFollowUpMode to the ui.prefs sync surface
(schema, types, docs) with clearable null removal for the follow-up override.
Rewrite server-prefs around a descriptor table so a synced pref is one entry
instead of five hand-written code sites. Caption synced rows/sections
(chat prefs, theme, language) and refresh the stale Settings subtitle.
* refactor(ui): dedupe settings constants, drop dead composer branch, refresh copy and docs
Derive the Security tool-profile options from PROFILE_OPTIONS and General's
thinking levels from BASE_THINKING_LEVELS instead of parallel literals.
Remove the unused composer mode:"model" branch, the orphaned
.config-view-toggle CSS family, and stale quick-settings wording. Add static
settings-search entries for the Sessions and Managed Worktrees pages plus a
provenance-row test, and update docs/cli/openclaw.md to describe the current
system-agent config-write policy (denylist roots, route-backing plugin guard,
per-agent routing escalations).
* chore: refresh plugin SDK API baseline after rebase onto current main
* fix(secrets): use resolveStateDir for .env path to cover legacy .clawdbot dir
* fix(secrets): replace override-based legacy .env test with true automatic fallback, add apply-path coverage
* fix(config-cli): emit JSON error on config get --json for missing paths
When is used with a nonexistent
path, the command emits no JSON on stdout, only a text error on stderr.
This breaks automated consumers that expect machine-readable errors.
Fix: output JSON to stdout before exit(1) when
opts.json is set. This matches the existing JSON error output pattern
already used by runConfigValidate and handleConfigMutationError.
Also re-throw synthetic exit errors in the catch block so the
--json branch's writeRuntimeJson+exit is not caught and re-emitted
as a text error.
* fix(config-cli): use typed ExitError signal instead of __exit__ string sentinel
* fix(secrets): reuse resolved stateDir for .env path in audit
* fix(secrets): pass resolved stateDir into apply .env scrubbing, add root-switch regression
* test(config-cli): migrate remaining __exit__ sentinel to ExitError
* fix(secrets): cover config and state dotenv roots
* style(secrets): format dotenv path helper
* test(secrets): track temporary directories
* test(config): expect typed exit for missing patch files
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Peter Steinberger <peter@steipete.me>
* perf(sqlite): gate schema version before integrity scans and quarantine terminal open failures
* feat(gateway): refuse incompatible database schemas at boot and verify integrity in the background
* feat(update): refuse installing builds that cannot open the current databases
* docs: add database schema reference with version history and downgrade guidance
* test(update): tolerate optional runner options in git-mutation mocks
* refactor(update): split npm package-target metadata out of update-check
* chore: model verifier internals for knip and regenerate docs map
* chore(i18n): resync stale iOS localization catalog
* chore: allowlist read-only preflight and verifier raw SQLite access
* feat(onboarding): persist app recommendations once
* feat(onboarding): add self-naming birth sequence
* chore(wizard): hoist bootstrap-defer imports to the top of the module
* docs(bootstrap): persist agreed identity into IDENTITY.md and SOUL.md as well
* docs: regenerate docs map after onboarding plan merge
* fix(wizard): reuse a pending stored offer instead of rescanning apps
* fix(onboard): deduplicate bootstrap recommendations