Summary:
- The PR removes `max` from OpenRouter DeepSeek V4 thinking profiles, maps stale OpenRouter `max` overrides to `xhigh`, preserves direct DeepSeek behavior, and updates docs, tests, and changelog.
- Reproducibility: yes. Source inspection on current main shows OpenRouter DeepSeek V4 advertises `max` and se ... ffort: "max"`, matching the linked 400 logs; I did not need a live OpenRouter request for this assist pass.
Automerge notes:
- Ran the ClawSweeper repair loop before final review.
- Addressed earlier ClawSweeper review findings before merge.
- Included post-review commit in the final squash: docs(changelog): credit OpenRouter duplicate fix
- Included post-review commit in the final squash: fix(openrouter): keep DeepSeek V4 reasoning effort valid
Validation:
- ClawSweeper review passed for head becdea4223.
- Required merge gates passed before the squash merge.
Prepared head SHA: becdea4223
Review: https://github.com/openclaw/openclaw/pull/77423#issuecomment-4372880583
Co-authored-by: sallyom <somalley@redhat.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
* Harden Windows command wrapper resolution
* clawsweeper: route Windows cmd.exe wrapper through getWindowsInstallRoots
Replace the local SystemRoot/windir/SYSTEMROOT/WINDIR scan in
resolveTrustedWindowsCmdExe with the shared getWindowsInstallRoots()
resolver from src/infra/windows-install-roots.ts. The shared resolver
already rejects UNC paths, root-relative values, semicolon-delimited
path-lists, and missing-drive-letter roots, and prefers registry-derived
roots over env, so the wrapper-launch trust boundary now matches the
existing Windows install-root boundary on main.
Tests:
- _resetWindowsInstallRootsForTests in beforeEach so cached roots track
per-test process.env mutations
- expectedTrustedCmdExe helper now joins the resolved systemRoot, so the
expected wrapper executable matches the production resolver on Linux
CI (where it falls back to DEFAULT_WINDOWS_SYSTEM_ROOT)
- new "rejects unsafe Windows root values" test covers UNC,
semicolon-delimited path-list, root-relative, and bare-relative
SystemRoot inputs
* Add CHANGELOG entry for #77472 Windows command wrapper hardening
* clawsweeper: stub registry probe in Windows wrapper tests
On real Windows CI runners getWindowsInstallRoots() reads the canonical
SystemRoot from the registry (e.g. C:\WINDOWS) before falling back to
process.env, which shadowed the env-only setup in the ComSpec-poisoning
and unsafe-root tests and produced casing mismatches like
"C:\WINDOWS\System32\cmd.exe" vs the expected "C:\Windows\...". Pass a
queryRegistryValue stub returning null in beforeEach (and inside the
unsafe-root loop) so install-root resolution is fully driven by the
test's process.env setup on every platform.
* clawsweeper: overwrite WINDIR alongside SystemRoot in unsafe-root test
Real Windows runners did not honor `delete process.env.windir`, so the
unsafe-root iteration's WINDIR fallback still resolved to the canonical
`C:\WINDOWS` and produced a casing mismatch against the expected default
`C:\Windows\System32\cmd.exe`. Set both `SystemRoot` and `WINDIR` to the
unsafe payload so every install-root env source is rejected by
`normalizeWindowsInstallRoot` and the resolver falls through to
`DEFAULT_WINDOWS_SYSTEM_ROOT`.
* Harden update environment path resolution
* docs(changelog): credit windows update env path hardening
Adds the user-facing Unreleased Fixes entry for the workspace LOCALAPPDATA
blocklist + portable Git path-prepend hardening change in this PR.
Summary:
- Adds a plugin-owned CLI backend argument rewrite hook and wires Anthropic `claude-cli` to translate non-off `/think` levels into Claude Code `--effort`, with docs, changelog, API baseline, and tests.
- Reproducibility: yes. Current main has a high-confidence source reproduction: choose `claude-cli`, set a non ... builds argv from backend args that contain no `--effort` even though `thinkLevel` exists on the run params.
Automerge notes:
- No ClawSweeper repair was needed after automerge opt-in.
Validation:
- ClawSweeper review passed for head be17754009.
- Required merge gates passed before the squash merge.
Prepared head SHA: be17754009
Review: https://github.com/openclaw/openclaw/pull/77410#issuecomment-4372812685
Co-authored-by: stainlu <stainlu@newtype-ai.org>
* feat: generalize pending-final-delivery for subagents and main session
(cherry picked from commit 677fcbfaf87c8cd6de8b5bd02099b29b7d49e916)
* feat(agents): implement Phase 2 durable final delivery for main sessions
(cherry picked from commit b4e39f0ddf6dbd3f0d3b9226df8e714ad722f751)
* fix(agents): narrow heartbeat deferral to pending final delivery
* fix(agents): clear final delivery after dispatch
* fix(agents): gate durable delivery retry capture
---------
Co-authored-by: Mert Basar <MertBasar0@users.noreply.github.com>
Summary:
- The PR publishes enabled plugin-declared skill directories into a generated `~/.openclaw/plugin-skills` syml ... plugin-skill precedence, cleans stale generated links, adds regression coverage, and updates the changelog.
- Reproducibility: yes. source-based. Current main resolves plugin-declared skill directories for prompt loadi ... ble generated discovery path, and the linked issue provides a concrete ENOENT path for a plugin `SKILL.md`.
Automerge notes:
- Ran the ClawSweeper repair loop before final review.
- Included post-review commit in the final squash: fix: resolve issue #77296
- Included post-review commit in the final squash: fix: publish plugin manifest skills for agent discovery
- Included post-review commit in the final squash: fix(clawsweeper): address review for automerge-openclaw-openclaw-7732…
Validation:
- ClawSweeper review passed for head 0f52865ee3.
- Required merge gates passed before the squash merge.
Prepared head SHA: 0f52865ee3
Review: https://github.com/openclaw/openclaw/pull/77328#issuecomment-4371415857
Co-authored-by: zhang-guiping <zhang.guiping@xydigit.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
The display sanitizer's long-token chunker (`\S{33,}` -> 32-char chunks
joined by spaces) was injecting literal spaces inside inline code spans,
fenced code blocks, and bare identifiers it didn't recognize. Tokens like
`requireConfirmationForMutatingActions`, `ubuntu-budgie-desktop-environment`,
and `binary_sensor.sense_energy_monitor_power` rendered with mid-word
spaces, contaminating copy/paste of package names, entity IDs, and shell
line-continuations.
Fix:
- Make sanitizer code-aware: split text into fenced/inline-code segments
and prose, and only run the chunker on prose segments. Code regions
pass through verbatim.
- Widen `isCopySensitiveToken` to use the punctuation-stripped candidate
for all classification, and accept any `FILE_LIKE_RE` token that
contains `_`, `-`, or `.` (covers package names, dotted IDs, kebab
flags). Picks up the goals of #69340 and #39565.
- Skip chunking for symbol-only runs (box-drawing rows, dashes, equals)
so table borders aren't corrupted.
- Preserve the original goal of narrow-terminal protection: long
unidentifiable prose tokens (e.g. accidental base64 dumps) are still
chunked so they don't blow out terminal layout.
Security ordering preserved: ANSI strip / control-char strip / binary
redaction still run on the whole string before segmentation, so code
regions cannot smuggle escapes, control characters, or binary garbage
past the sanitizer.
16 new regression tests cover: camelCase config keys in inline code,
hyphenated package names (bare and in code), dotted entity IDs (bare
and in code), backtick and tilde fenced blocks, base64-like blobs in
code, prose-token chunking unchanged, prose-around-code mixed content,
box-drawing horizontal rules, multi-line shell `\\` continuations,
plus three explicit security-ordering tests asserting ANSI/control/
binary stripping still runs inside code segments.
Fixes#48432, #39505.
Supersedes #69340, #39565 (carries forward both ideas in a more
general fix). Carries forward the code-fence-aware approach from the
closed#48445.
* fix(tui): abort run during pre-event waiting gap
Track the runId returned from chat.send so pressing Esc while `activeChatRunId` is still null aborts the in-flight run instead of repeatedly printing "no active run". Identified in #1296.
* fix(tui): drop redundant comment on pendingChatRunId set
Summary:
- This PR routes direct APNs HTTP/2 sends through an APNs allowlisted managed-proxy CONNECT wrapper, adds APNs proxy validation/docs/guardrails, and expands regression and live-test coverage.
- Reproducibility: yes. source-reproducible: current main `sendApnsRequest()` still uses raw `http2.connect(au ... nly covers HTTP/global-agent/Undici hooks. I did not run a live APNs reproduction in this read-only review.
Automerge notes:
- PR branch already contained follow-up commit before automerge: test: guard raw HTTP2 APNs connections
- PR branch already contained follow-up commit before automerge: test: guard raw HTTP2 with OpenGrep
- PR branch already contained follow-up commit before automerge: lint: ban raw HTTP2 imports
- PR branch already contained follow-up commit before automerge: fix: use managed proxy state for APNs
- PR branch already contained follow-up commit before automerge: test: exercise APNs active proxy state
- PR branch already contained follow-up commit before automerge: fix: reject conflicting managed proxy activation
Validation:
- ClawSweeper review passed for head dab7c86a75.
- Required merge gates passed before the squash merge.
Prepared head SHA: dab7c86a75
Review: https://github.com/openclaw/openclaw/pull/74905#issuecomment-4350181159
Co-authored-by: jesse-merhi <79823012+jesse-merhi@users.noreply.github.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>