Fail closed when bundled trusted tool policy registry, registration, owner id, evaluation, or decision reads fail, so malformed trusted-policy state cannot crash diagnostics or accidentally allow a tool call.
Route before-tool-call diagnostics through guarded trusted-policy readers and keep healthy no-op policy behavior unchanged.
Add focused host-hook contract and before-tool-call e2e coverage for the new fail-closed paths.
PR: #88394
Adds broad inline comments and JSDoc for CLI, cron, outbound/channel, plugin SDK, ACP, shared helpers, net policy, and related utility contracts. Proof: git diff --check on latest exact head plus focused cron tests passed; CI had no failing checks observed before merge attempt.
Fixes#88521.
Expose finalized inbound reply metadata on plugin-visible hook payloads so before_dispatch and message hooks can implement reply-aware behavior without channel-specific workarounds.
Return unknown config.schema.lookup paths as an in-band agent gateway tool result instead of throwing into channel warning surfaces.
The direct gateway RPC still reports INVALID_REQUEST, preserving the existing protocol contract, while the agent-facing gateway tool returns schema_path_not_found for exploratory misses.
Fixes#88813.
Thanks @ksj3421.
Reported by @cjalden.
* test(agents): include Ollama in small live model matrix
* test: avoid Ollama cloud key in local live runs
* test: recognize Ollama env secret refs
* test: type Ollama live key fixtures
* test: prevent Ollama cloud auth in local live probes
* test: preserve equivalent Ollama live credentials
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Restore TUI switch-back adoption for backgrounded visible chat-send runs by surfacing a bounded `chat.history.inFlightRun` snapshot.
The snapshot keeps the run id even when buffered text is empty or over budget, filters live text through the same projection path as streaming chat, scopes bare global history to the default agent, and excludes hidden internal agent runs.
Proof:
- node scripts/run-vitest.mjs run src/gateway/chat-abort.test.ts src/tui/tui-session-actions.test.ts
- node scripts/run-tsgo.mjs -p tsconfig.core.json
- pnpm --silent exec oxfmt --check src/gateway/chat-abort.ts src/gateway/chat-abort.test.ts src/gateway/server-methods/chat.ts src/tui/tui-session-actions.ts src/tui/tui-session-actions.test.ts
- .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main
- CI: Real behavior proof, TUI PTY, dependency guard, OpenGrep precise diff, workflow sanity passed on PR head 2b8bf5f214.
Co-authored-by: William Liu <william@williamliu.ai>
Respect explicit PI/OpenClaw runtime policy when deciding whether Codex plugin diagnostics are actionable.
Diagnostics now use the resolved OpenAI route: intentional PI and custom OpenAI-compatible routes suppress only the missing `plugins.entries.codex` noise, while enabled/stale Codex policy still warns.
Proof: focused doctor/config/agent routing Vitest coverage, full lint, test types, dependency checks, isolated live doctor configs, autoreview clean, and GitHub CI green at c5a84de4ca.
Fixes#88706.
Co-authored-by: Elfka Toruviel <aeb31988340aa87b@toruviel.online>
Fixes#88333
Preserves contributor workspace contents when an attested workspace disappears or is partially regenerated, and clears OpenClaw-owned attestation state on delete/reset/uninstall.
Co-authored-by: Andy Ye <35905412+TurboTheTurtle@users.noreply.github.com>
Resolve gateway auth SecretRef targets in status deep audit.
The static secret target coverage now includes gateway auth and remote token/password keys for both status and security audit scans. Focused status/secret-target tests passed, Auto Review reported no actionable findings, and CI is running on rebased head 41b052a181.
Fixes#87815
* fix(config): skip state-dir dotenv values that are unresolved shell references
readStateDirDotEnvVarsFromStateDir accepted any non-empty value from the
state-dir .env file and passed it into the managed service env. When a value
contains an unresolved shell variable reference such as "${SUPERMEMORY_KEY}"
or "$MY_VAR", dotenv preserves the literal string. The value then reaches
the LaunchAgent/systemd wrapper as a single-quoted literal, so the credential
is never resolved.
Add containsUnresolvedShellReference() and skip any value matching
$IDENTIFIER, ${...}, or $(...) in parseStateDirDotEnvContent(). Real credential
values (e.g. "sm_abc123") are unaffected.
Fixes#88274
* fix(config): narrow shell-reference detector to whole-value patterns only
The previous /$[\w{(]/ regex matched any value containing $ followed by
a word character, which would incorrectly drop real credentials that merely
contain a dollar sign (e.g. a password like abc$2!xyz).
Replace with isUnresolvedShellReference() that only matches values whose
ENTIRE content is a recognised reference form:
- $VAR_NAME (simple reference)
- ${VAR_NAME} (brace-form reference)
- $(command) (command substitution)
Add a regression test that verifies dollar-bearing real secrets are kept.
* fix(config): use letter/underscore-anchored pattern to avoid matching dollar-numbers
$100, $2, etc. are NOT shell variable references — shell variable names must
begin with a letter or underscore. The previous /^$[\w_]/ would match them.
Change to /^$[A-Za-z_]\w*$/ so only genuine named-variable references like
$MY_VAR are rejected. Dollar-number sequences are now preserved.
* fix(daemon): drop stale systemd env-file refs for skipped state-dir dotenv keys
When a state-dir .env value is an unresolved shell reference ($VAR/${VAR}/$(cmd))
the parser skips it from the managed environment. A prior install could have
written that literal reference into gateway.systemd.env; because the skipped key
no longer appeared in the incoming env or the managed-key removal sets, the stale
literal survived re-stage and could override fresh inline Environment= values.
Surface the skipped shell-reference keys from the state-dir dotenv parser and add
them to the systemd env-file managed-key removal set so re-staging strips the
obsolete literal while preserving operator-only secrets that were never managed
via state-dir .env. launchd regenerates its env file wholesale, so it is
unaffected.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(config): skip quoted shell parameter dotenv refs
* fix(config): preserve lowercase dollar-prefixed dotenv literals
* fix(daemon): clear stale unresolved systemd env refs
* fix(daemon): avoid re-staging unresolved file env refs
* fix(daemon): drop unresolved file env refs inline
* fix(daemon): drop inline-and-file unresolved env refs
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Preserve the active per-plugin managed npm project when npm-backed install validation blocks a candidate after npm has already mutated local state.
This snapshots package.json, package-lock.json, and node_modules before managed npm installs, restores that exact project state on failed validation, and rolls back staged npm-pack archives so blocked pack installs do not leave candidate debris.
Validation:
- OPENCLAW_VITEST_MAX_WORKERS=1 node scripts/run-vitest.mjs src/plugins/install.npm-spec.test.ts
- pnpm tsgo:core && pnpm tsgo:core:test
- node scripts/run-oxlint.mjs src/plugins/install.ts src/plugins/install.npm-spec.test.ts
- .agents/skills/autoreview/scripts/autoreview --mode local
- GitHub CI 26729255950
- Crabbox run_26e9f9f7591c
Thanks @zhuisDEV.
Co-authored-by: Brian <95547369+zhuisDEV@users.noreply.github.com>