Skip to content

Ollama/Kimi: apply Moonshot payload compatibility#44274

Merged
vincentkoc merged 5 commits intomainfrom
vincentkoc-code/fix-ollama-kimi-tool-routing
Mar 12, 2026
Merged

Ollama/Kimi: apply Moonshot payload compatibility#44274
vincentkoc merged 5 commits intomainfrom
vincentkoc-code/fix-ollama-kimi-tool-routing

Conversation

@vincentkoc
Copy link
Copy Markdown
Member

Summary

  • extend the Moonshot/Kimi payload compatibility wrapper to Ollama-hosted Kimi models such as kimi-k2.5:cloud
  • normalize tool_choice and thinking for those Ollama Kimi variants the same way native Moonshot Kimi already does
  • add focused regression coverage for ollama/kimi-k2.5:cloud
  • add an unreleased changelog entry

Linked Issue/PR

Repro + Verification

  • pnpm exec vitest run src/agents/pi-embedded-runner-extraparams.test.ts
  • pnpm format src/agents/pi-embedded-runner/moonshot-stream-wrappers.ts src/agents/pi-embedded-runner/extra-params.ts src/agents/pi-embedded-runner-extraparams.test.ts CHANGELOG.md
  • pnpm build

@vincentkoc vincentkoc self-assigned this Mar 12, 2026
@openclaw-barnacle openclaw-barnacle bot added agents Agent runtime and tooling size: S maintainer Maintainer-authored PR labels Mar 12, 2026
@vincentkoc vincentkoc marked this pull request as ready for review March 12, 2026 17:39
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 12, 2026

Greptile Summary

This PR extends the existing Moonshot payload compatibility wrapper (which normalizes thinking and rewrites incompatible tool_choice values) to also cover Ollama-hosted Kimi models such as kimi-k2.5:cloud. The change is minimal and surgical: a new shouldApplyMoonshotPayloadCompat helper replaces the single hard-coded provider === "moonshot" check in extra-params.ts, and two focused regression tests are added.

  • The logic is correct: resolveMoonshotThinkingType and createMoonshotThinkingWrapper are reused as-is, ensuring parity with native Moonshot behavior.
  • The new helper normalizes provider/model IDs (trim + toLowerCase) before comparing, which is a small defensive improvement over the prior exact-match.
  • Tests cover both the thinking-enabled path (with tool_choice rewrite) and the thinking-disabled path.
  • The startsWith("kimi-") prefix used for the Ollama path is intentionally broad but could inadvertently match future Kimi model variants that don't support the Moonshot thinking API — worth documenting or tightening if more Kimi model families are added to Ollama.

Confidence Score: 5/5

  • This PR is safe to merge — the change is minimal, well-tested, and follows existing patterns.
  • The change is small (one replaced conditional, one new helper function, two new tests) with no modifications to existing logic. The new code path is fully exercised by the added tests, and the underlying wrapper functions (createMoonshotThinkingWrapper, resolveMoonshotThinkingType) are unchanged and already battle-tested for the native Moonshot provider.
  • No files require special attention.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/agents/pi-embedded-runner/moonshot-stream-wrappers.ts
Line: 64

Comment:
**`kimi-` prefix may be overly broad**

The `startsWith("kimi-")` check will match any Ollama-hosted model whose ID begins with `kimi-` (e.g. a hypothetical `kimi-audio` or `kimi-vision` variant that has no thinking/tool_choice semantics). Applying the Moonshot wrapper to such a model would silently inject `thinking: { type: "enabled" | "disabled" }` into its payload, which could confuse APIs that don't expect it.

If the intent is specifically to cover cloud-routed Kimi reasoning models, a narrower guard (e.g. also checking for the `:cloud` tag, or an allowlist of known model prefixes like `kimi-k`) would avoid inadvertent matches:

```ts
return (
  normalizedProvider === "ollama" &&
  normalizedModelId.startsWith("kimi-k") &&
  normalizedModelId.includes(":cloud")
);
```

If the broader match is intentional to future-proof for other Kimi variants, a brief comment explaining that decision would help maintainers understand the tradeoff.

How can I resolve this? If you propose a fix, please make it concise.

Last reviewed commit: 976e7bc

// Ollama Cloud exposes Kimi variants through OpenAI-compatible model IDs such
// as `kimi-k2.5:cloud`, but they still need the same payload normalization as
// native Moonshot endpoints when thinking/tool_choice are enabled together.
return normalizedProvider === "ollama" && normalizedModelId.startsWith("kimi-");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kimi- prefix may be overly broad

The startsWith("kimi-") check will match any Ollama-hosted model whose ID begins with kimi- (e.g. a hypothetical kimi-audio or kimi-vision variant that has no thinking/tool_choice semantics). Applying the Moonshot wrapper to such a model would silently inject thinking: { type: "enabled" | "disabled" } into its payload, which could confuse APIs that don't expect it.

If the intent is specifically to cover cloud-routed Kimi reasoning models, a narrower guard (e.g. also checking for the :cloud tag, or an allowlist of known model prefixes like kimi-k) would avoid inadvertent matches:

return (
  normalizedProvider === "ollama" &&
  normalizedModelId.startsWith("kimi-k") &&
  normalizedModelId.includes(":cloud")
);

If the broader match is intentional to future-proof for other Kimi variants, a brief comment explaining that decision would help maintainers understand the tradeoff.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agents/pi-embedded-runner/moonshot-stream-wrappers.ts
Line: 64

Comment:
**`kimi-` prefix may be overly broad**

The `startsWith("kimi-")` check will match any Ollama-hosted model whose ID begins with `kimi-` (e.g. a hypothetical `kimi-audio` or `kimi-vision` variant that has no thinking/tool_choice semantics). Applying the Moonshot wrapper to such a model would silently inject `thinking: { type: "enabled" | "disabled" }` into its payload, which could confuse APIs that don't expect it.

If the intent is specifically to cover cloud-routed Kimi reasoning models, a narrower guard (e.g. also checking for the `:cloud` tag, or an allowlist of known model prefixes like `kimi-k`) would avoid inadvertent matches:

```ts
return (
  normalizedProvider === "ollama" &&
  normalizedModelId.startsWith("kimi-k") &&
  normalizedModelId.includes(":cloud")
);
```

If the broader match is intentional to future-proof for other Kimi variants, a brief comment explaining that decision would help maintainers understand the tradeoff.

How can I resolve this? If you propose a fix, please make it concise.

@katoue

This comment was marked as spam.

@vincentkoc
Copy link
Copy Markdown
Member Author

Good payload compatibility extension. Applying Moonshot/Kimi normalization (tool_choice, thinking) to Ollama-hosted variants (kimi-k2.5:cloud) unifies tool handling across hosting environments. This should help with the Kimi tool issues reported in isolated cron. Fixes #41519.

@katoue PLEASE stop spamming!!!

@vincentkoc vincentkoc merged commit 1492ad2 into main Mar 12, 2026
27 of 28 checks passed
@vincentkoc vincentkoc deleted the vincentkoc-code/fix-ollama-kimi-tool-routing branch March 12, 2026 18:17
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 59f9b9b3ef

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


### Fixes

- Ollama/Kimi Cloud: apply the Moonshot Kimi payload compatibility wrapper to Ollama-hosted Kimi models like `kimi-k2.5:cloud`, so tool routing no longer breaks when thinking is enabled. (#41519) Thanks @vincentkoc.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Append this fix entry to end of Fixes section

The repository guideline in AGENTS.md says new changelog items must be appended to the end of the active section, but this new ### Fixes entry is inserted at the top; that violates the project’s required changelog ordering and causes avoidable churn in the unreleased block. Please move this line to the end of the current ### Fixes list.

Useful? React with 👍 / 👎.

mukhtharcm pushed a commit to teconomix/openclaw that referenced this pull request Mar 12, 2026
* Runner: extend Moonshot payload compat to Ollama Kimi

* Changelog: note Ollama Kimi tool routing

* Tests: cover Ollama Kimi payload compat

* Runner: narrow Ollama Kimi payload compat
steipete pushed a commit to BruceMacD/openclaw that referenced this pull request Mar 13, 2026
* Runner: extend Moonshot payload compat to Ollama Kimi

* Changelog: note Ollama Kimi tool routing

* Tests: cover Ollama Kimi payload compat

* Runner: narrow Ollama Kimi payload compat
dvrshil pushed a commit to JosepLee/openclaw that referenced this pull request Mar 14, 2026
* Runner: extend Moonshot payload compat to Ollama Kimi

* Changelog: note Ollama Kimi tool routing

* Tests: cover Ollama Kimi payload compat

* Runner: narrow Ollama Kimi payload compat
fabianbaier added a commit to yourclaw/openclaw that referenced this pull request Mar 19, 2026
* Skills: normalize emoji presentation across outputs

* Terminal: consume unsupported escape bytes in tables

* fix(terminal): stabilize skills table width across Terminal.app and iTerm (#42849)

* Terminal: measure grapheme display width

* Tests: cover grapheme terminal width

* Terminal: wrap table cells by grapheme width

* Tests: cover emoji table alignment

* Terminal: refine table wrapping and width handling

* Terminal: stop shrinking CLI tables by one column

* Skills: use Terminal-safe emoji in list output

* Changelog: note terminal skills table fixes

* Skills: normalize emoji presentation across outputs

* Terminal: consume unsupported escape bytes in tables

* fix(gateway): enforce caller-scope subsetting in device.token.rotate

device.token.rotate accepted attacker-controlled scopes and forwarded
them to rotateDeviceToken without verifying the caller held those
scopes. A pairing-scoped token could rotate up to operator.admin on
any already-paired device whose approvedScopes included admin.

Add a caller-scope subsetting check before rotateDeviceToken: the
requested scopes must be a subset of client.connect.scopes via the
existing roleScopesAllow helper. Reject with missing scope: <scope>
if not.

Also add server.device-token-rotate-authz.test.ts covering both the
priv-esc path and the admin-to-node-invoke chain.

Fixes GHSA-4jpw-hj22-2xmc

* fix(gateway): propagate real gateway client into plugin subagent runtime

Plugin subagent dispatch used a hardcoded synthetic client carrying
operator.admin, operator.approvals, and operator.pairing for all
runtime.subagent.* calls. Plugin HTTP routes with auth:"plugin" require
no gateway auth by design, so an unauthenticated external request could
drive admin-only gateway methods (sessions.delete, agent.run) through
the subagent runtime.

Propagate the real gateway client into the plugin runtime request scope
when one is available. Plugin HTTP routes now run inside a scoped
runtime client: auth:"plugin" routes receive a non-admin synthetic
operator.write client; gateway-authenticated routes retain admin-capable
scopes. The security boundary is enforced at the HTTP handler level.

Fixes GHSA-xw77-45gv-p728

* fix(agents): add nodes to owner-only tool policy fallbacks

The nodes tool was missing from OWNER_ONLY_TOOL_NAME_FALLBACKS in
tool-policy.ts. applyOwnerOnlyToolPolicy() correctly removed gateway
and cron for non-owners but kept nodes, which internally issues
privileged gateway calls: node.pair.approve (operator.pairing) and
node.invoke (operator.write).

A non-owner sender could approve pending node pairings and invoke
arbitrary node commands, extending to system.run on paired nodes.

Add nodes to the fallback owner-only set. Non-owners no longer receive
the nodes tool after policy application; owners retain it.

Fixes GHSA-r26r-9hxr-r792

* Onboard: add Ollama auth flow and improve model defaults

Add Ollama as a auth provider in onboarding with Cloud + Local mode
selection, browser-based sign-in via /api/me, smart model suggestions
per mode, and graceful fallback when the default model is unavailable.

- Extract shared ollama-models.ts
- Auto-pull missing models during onboarding
- Non-interactive mode support for CI/automation

Closes #8239
Closes #3494

Co-Authored-By: Jeffrey Morgan <[email protected]>

* fix: tighten Ollama onboarding cloud handling (#41529) (thanks @BruceMacD)

* Fix env proxy bootstrap for model traffic (#43248)

* Fix env proxy bootstrap for model traffic

* Address proxy dispatcher review followups

* Fix proxy env precedence for empty lowercase vars

* fix(telegram): clear stale retain before transient final fallback (#41763)

Merged via squash.

Prepared head SHA: c0940838bce6c4ed052579a4773b934c08826e0a
Co-authored-by: obviyus <[email protected]>
Co-authored-by: obviyus <[email protected]>
Reviewed-by: @obviyus

* fix(voice-call): add speed and instructions to OpenAI TTS config schema (#39226)

Merged via squash.

Prepared head SHA: 775e3063b58d4629f59021798ab1c7222ff069d9
Co-authored-by: ademczuk <[email protected]>
Co-authored-by: obviyus <[email protected]>
Reviewed-by: @obviyus

* fix(signal): add missing accountUuid to Zod config schema (#35578)

Merged via squash.

Prepared head SHA: 39e8e9ad62f65fa70e1a660e65f19d9452ae0412
Co-authored-by: ingyukoh <[email protected]>
Co-authored-by: altaywtf <[email protected]>
Reviewed-by: @altaywtf

* fix(config): add missing editMessage and createForumTopic to Telegram actions schema (#35498)

Merged via squash.

Prepared head SHA: 631fc14832402c5a6659fdb1a24a37ae67832ed0
Co-authored-by: ingyukoh <[email protected]>
Co-authored-by: altaywtf <[email protected]>
Reviewed-by: @altaywtf

* fix(agents): check billing errors before context overflow heuristics (#40409)

Merged via squash.

Prepared head SHA: c88f89c462d87957a4c6c51a23ab997fd307059d
Co-authored-by: ademczuk <[email protected]>
Co-authored-by: altaywtf <[email protected]>
Reviewed-by: @altaywtf

* feat(memory): add gemini-embedding-2-preview support (#42501)

Merged via squash.

Prepared head SHA: c57b1f8ba2ca65f4946afe94a9137ee8c05c8c64
Co-authored-by: BillChirico <[email protected]>
Co-authored-by: gumadeiras <[email protected]>
Reviewed-by: @gumadeiras

* fix: use unknown instead of rate_limit as default cooldown reason (#42911)

Merged via squash.

Prepared head SHA: bebf6704d7b02b9a32935c0006eac2d76694fec0
Co-authored-by: VibhorGautam <[email protected]>
Co-authored-by: altaywtf <[email protected]>
Reviewed-by: @altaywtf

* fix(discord): add missing autoThread to DiscordGuildChannelConfig type (#35608)

Merged via squash.

Prepared head SHA: e62b88bb01bf13ba2759c51095be07c3a47536dc
Co-authored-by: ingyukoh <[email protected]>
Co-authored-by: altaywtf <[email protected]>
Reviewed-by: @altaywtf

* fix(agents): prevent false billing error replacing valid response text (#40616)

Merged via squash.

Prepared head SHA: 05179362b439ff3b0330df3eb6a28aa05396ea9d
Co-authored-by: ingyukoh <[email protected]>
Co-authored-by: altaywtf <[email protected]>
Reviewed-by: @altaywtf

* memory: normalize Gemini embeddings (#43409)

Merged via squash.

Prepared head SHA: 70613e022540b4d923d55c3a6ca51715cc6f46c4
Co-authored-by: gumadeiras <[email protected]>
Co-authored-by: gumadeiras <[email protected]>
Reviewed-by: @gumadeiras

* fix: recognize Venice 402 billing errors for model fallback (#43205)

Merged via squash.

Prepared head SHA: 1f6b10b9d934235e71f279f888292139c4a85aa6
Co-authored-by: Squabble9 <[email protected]>
Co-authored-by: altaywtf <[email protected]>
Reviewed-by: @altaywtf

* fix: restore web tools to coding profile (#43436)

* fix: restore web tools to coding profile

* fix: tighten tool catalog regression assertion

* chore: refresh dependencies except carbon

* test(agents): cover openai responses phase replay

* fix(ollama): share model context discovery

* fix(onboard): default custom Ollama URL to native API

* docs(ollama): align onboarding guidance with code

* test: align pi-ai oauth mocks

* fix(ws): preserve payload overrides

* fix(gateway): run before_tool_call for HTTP tools

* test(gateway): widen before tool hook mock typing (#43476)

* test(gateway): widen before tool hook mock typing

* chore: update pnpm.lock

* Gateway/Dashboard: surface config validation issues (#42664)

Merged via squash.

Prepared head SHA: 43f66cdcf04a14d5381a5a2f14e291a52a8b7389
Co-authored-by: huntharo <[email protected]>
Co-authored-by: huntharo <[email protected]>
Reviewed-by: @huntharo

* Memory: add multimodal image and audio indexing (#43460)

Merged via squash.

Prepared head SHA: a994c07190a2062322f459c928b6cd74f9803d88
Co-authored-by: gumadeiras <[email protected]>
Co-authored-by: gumadeiras <[email protected]>
Reviewed-by: @gumadeiras

* fix(hooks): add missing trigger and channelId to agent_end, llm_input, and llm_output hook contexts (#42362)

Merged via squash.

Prepared head SHA: e6d7b7e31aa6ae12813b4609adb6e569a4084d08
Co-authored-by: zhoulf1006 <[email protected]>
Co-authored-by: hydro13 <[email protected]>
Reviewed-by: @hydro13

* Memory: revalidate multimodal files before indexing

* preserve openai phase param

* chore: bump version to 2026.3.10

* fix(terminal): sanitize skills JSON and fallback on legacy Windows (#43520)

* Terminal: use ASCII borders on legacy Windows consoles

* Skills: sanitize JSON output for control bytes

* Changelog: credit terminal follow-up fixes

* Update CHANGELOG.md

* Update CHANGELOG.md

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* Skills: strip remaining escape sequences from JSON output

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* fix: repair bundled plugin dirs after npm install

* fix(daemon): replace bootout with kickstart -k for launchd restarts on macOS

On macOS, launchctl bootout permanently unloads the LaunchAgent plist.
Even with KeepAlive: true, launchd cannot respawn a service whose plist
has been removed from its registry. This left users with a dead gateway
requiring manual 'openclaw gateway install' to recover.

Affected trigger paths:
- openclaw gateway restart from an agent session (#43311)
- SIGTERM on config reload (#43406)
- Gateway self-restart via SIGTERM (#43035)
- Hot reload on channel config change (#43049)

Switch restartLaunchAgent() to launchctl kickstart -k, which force-kills
and restarts the service without unloading the plist. When the restart
originates from inside the launchd-managed process tree, delegate to a
new detached handoff helper (launchd-restart-handoff.ts) to avoid the
caller being killed mid-command. Self-restart paths in process-respawn.ts
now schedule the detached start-after-exit handoff before exiting instead
of relying on exit/KeepAlive timing.

Fixes #43311, #43406, #43035, #43049

* fix(gateway): enforce browser origin check regardless of proxy headers

In trusted-proxy mode, enforceOriginCheckForAnyClient was set to false
whenever proxy headers were present. This allowed browser-originated
WebSocket connections from untrusted origins to bypass origin validation
entirely, as the check only ran for control-ui and webchat client types.

An attacker serving a page from an untrusted origin could connect through
a trusted reverse proxy, inherit proxy-injected identity, and obtain
operator.admin access via the sharedAuthOk / roleCanSkipDeviceIdentity
path without any origin restriction.

Remove the hasProxyHeaders exemption so origin validation runs for all
browser-originated connections regardless of how the request arrived.

Fixes GHSA-5wcw-8jjv-m286

* fix: harden state dir permissions during onboard

* fix(whatsapp): trim leading whitespace in direct outbound sends (#43539)

Trim leading whitespace from direct WhatsApp text and media caption sends.

Also guard empty text-only web sends after trimming.

* fix(node-host): extend script-runner set and add fail-closed guard for mutable-file approval

tsx, jiti, ts-node, ts-node-esm, vite-node, and esno were not recognized
as interpreter-style script runners in invoke-system-run-plan.ts. These
runners produced mutableFileOperand: null, causing invoke-system-run.ts
to skip revalidation entirely. A mutated script payload would execute
without the approval binding check that node ./run.js already enforced.

Two-part fix:
- Add tsx, jiti, and related TypeScript/ESM loaders to the known script
  runner set so they produce a valid mutableFileOperand from the planner
- Add a fail-closed runtime guard in invoke-system-run.ts that denies
  execution when a script run should have a mutable-file binding but the
  approval plan is missing it, preventing unknown future runners from
  silently bypassing revalidation

Fixes GHSA-qc36-x95h-7j53

* fix(daemon): address clanker review findings for kickstart restart

Bug 1 (high): replace fixed sleep 1 with caller-PID polling in both
kickstart and start-after-exit handoff modes. The helper now waits until
kill -0 $caller_pid fails before issuing launchctl kickstart -k.

Bug 2 (medium): gate enable+bootstrap fallback on isLaunchctlNotLoaded().
Only attempt re-registration when kickstart -k fails because the job is
absent; all other kickstart failures now re-throw the original error.

Follows up on 3c0fd3dffe.
Fixes #43311, #43406, #43035, #43049

* fix(cli): handle scheduled gateway restarts consistently

* test(cli): update daemon coverage restart contract

* fix: harden openai websocket replay

* fix(discord): enforce users/roles allowlist in reaction ingress

References GHSA-9vvh-2768-c8vp.

* test: fix websocket tool shape coverage

* fix: isolate plugin discovery env from global state

* fix(sandbox): anchor fs-bridge writeFile commit to canonical parent path

Refs: GHSA-xvx8-77m6-gwg6

* feat: expose runtime version in gateway status

* fix(acp): rehydrate restarted main ACP sessions (#43285)

Merged via squash.

Prepared head SHA: f06318e58fe3e3fedd70426ca7eeecf6d71bb604
Co-authored-by: frankekn <[email protected]>
Co-authored-by: frankekn <[email protected]>
Reviewed-by: @frankekn

* fix(context-engine): guard compact() throw + fire hooks for ownsCompaction engines (#41361)

Merged via squash.

Prepared head SHA: 0957b32dc63b16d710403565953b77bfbd2bd987
Co-authored-by: davidrudduck <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman

* docs: reorder unreleased changelog by user impact

* OpenRouter: surface free Hunter and Healer stealth models for the next week (#43642)

* Models: add temporary Hunter and Healer alpha to OpenRouter catalog

* Add temporary OpenRouter stealth catalog entries

---------

Co-authored-by: Tak Hoffman <[email protected]>

* docs: update 2026.3.11 release examples

* build: sync versions to 2026.3.11

* fix(telegram): avoid polling restart hang after stall detection

* fix: clear telegram polling cleanup timers

* build: bump openclaw to 2026.3.11-beta.1

* docs: update Raspberry Pi dashboard access instructions (#43584)

* docs(pi): update dashboard access instructions

* docs(i18n): refresh raspberry pi source hash

* docs: clarify Raspberry Pi dashboard access

* fix: clarify Raspberry Pi dashboard access (#43584) (thanks @neeravmakwana)

---------

Co-authored-by: Neerav Makwana <[email protected]>
Co-authored-by: Ayaan Zaidi <[email protected]>

* build: prepare 2026.3.11 release

* fix(browser): restore proxy attachment media size cap (#43684)

* browser: honor shared proxy file size cap

* test(browser): cover proxy file size cap

* docs(changelog): note browser proxy size cap fix

* Infra: block GIT_EXEC_PATH in host env sanitizer (#43685)

* Infra: block GIT_EXEC_PATH in host env sanitizer

* Changelog: note host env hardening

* Security: escape invisible exec approval format chars (#43687)

* Infra: escape invisible exec approval chars

* Gateway: sanitize exec approval display text

* Tests: cover sanitized exec approval payloads

* Tests: cover sanitized exec approval forwarding

* Changelog: note exec approval prompt hardening

* Infra: cap device tokens to approved scopes (#43686)

* Infra: cap device tokens to approved scopes

* Changelog: note device token hardening

* Update CHANGELOG.md

* Update CHANGELOG.md

* Tests: clean up temp git helper directory

* Infra: fail closed without device scope baseline

* style: format changelog

* fix(macos): add NSRemindersUsageDescription for apple-reminders skill

Fixes #5090

Without this plist key, macOS silently denies Reminders access when
running through OpenClaw.app, preventing the apple-reminders skill
from requesting permission.

(cherry picked from commit e5774471c851b773dd2bffd51dd5d28d95a8a7ca)

* Changelog: note Reminders permission fix

* fix(imessage): dedupe reflected self-chat duplicates (#38440)

* iMessage: drop reflected self-chat duplicates

* Changelog: add iMessage self-chat echo dedupe entry

* iMessage: keep self-chat dedupe scoped to final group identity

* iMessage: harden self-chat cache

* iMessage: sanitize self-chat duplicate logs

* iMessage: scope group self-chat dedupe by sender

* iMessage: move self-chat cache identity into cache

* iMessage: hash full self-chat text

* Update CHANGELOG.md

* fix(agents): enforce sandboxed session_status visibility (#43754)

* agents: guard sandboxed session_status access

* test(agents): cover sandboxed session_status scope

* docs(changelog): credit session_status hardening

* agents: preflight sandboxed session_status checks

* test(agents): cover session_status existence oracle

* agents: preserve legacy session_status tree keys

* test(agents): cover legacy session_status tree keys

* Update CHANGELOG.md

* fix: prevent duplicate assistant messages in TUI (fixes #35278) (#35364)

* fix: prevent duplicate assistant messages in TUI (fixes #35278)

When startAssistant() is called multiple times with the same runId,
it was creating duplicate AssistantMessageComponent instances instead
of reusing the existing one. This caused messages to appear twice in
the terminal UI.

The fix checks if a component already exists for the runId before
creating a new one. If it exists, we update its text instead of
appending a duplicate component.

Test coverage includes verification that:
- Only one component is created when startAssistant is called twice
- The second text replaces the first
- Component count remains 1 (prevents regression)

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <[email protected]>
Co-Authored-By: Happy <[email protected]>

* Changelog: add TUI duplicate-render fix entry

---------

Co-authored-by: 沐沐 <[email protected]>
Co-authored-by: Claude <[email protected]>
Co-authored-by: Happy <[email protected]>
Co-authored-by: Vincent Koc <[email protected]>

* fix(cron): prevent duplicate proactive delivery on transient retry (#40646)

* fix(cron): prevent duplicate proactive delivery on transient retry

* refactor: scope skipQueue to retryTransient path only

Non-retrying direct delivery (structured content / thread) keeps the
write-ahead queue so recoverPendingDeliveries can replay after a crash.

Addresses review feedback from codex-connector.

* fix: preserve write-ahead queue on initial delivery attempt

The first call through retryTransientDirectCronDelivery now keeps the
write-ahead queue entry so recoverPendingDeliveries can replay after a
crash.  Only subsequent retry attempts set skipQueue to prevent
duplicate sends.

Addresses second codex-connector review on ea5ae5c.

* ci: retrigger checks

* Cron: bypass write-ahead queue for direct isolated delivery

* Tests: assert isolated cron skipQueue invariants

* Changelog: add cron duplicate-delivery fix entry

---------

Co-authored-by: Vincent Koc <[email protected]>

* fix(bluebubbles): dedupe reflected self-chat duplicates (#38442)

* BlueBubbles: drop reflected self-chat duplicates

* Changelog: add BlueBubbles self-chat echo dedupe entry

* BlueBubbles: gate self-chat cache and expand coverage

* BlueBubbles: require explicit sender ids for self-chat dedupe

* BlueBubbles: harden self-chat cache

* BlueBubbles: move self-chat cache identity into cache

* BlueBubbles: gate self-chat cache to confirmed outbound sends

* Update CHANGELOG.md

* BlueBubbles: bound self-chat cache input work

* Tests: cover BlueBubbles cache cap under cleanup throttle

* BlueBubbles: canonicalize self-chat DM scope

* Tests: cover BlueBubbles mixed self-chat scope aliases

* fix(mattermost): prevent duplicate messages when block streaming + threading are active (#41362)

* fix(mattermost): prevent duplicate messages when block streaming + threading are active

Remove replyToId from createBlockReplyPayloadKey so identical content is
deduplicated regardless of threading target. Add explicit threading dock
to the Mattermost plugin with resolveReplyToMode reading from config
(default "all"), and add replyToMode to the Mattermost config schema.

Fixes #41219

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* fix(mattermost): address PR review — per-account replyToMode and test clarity

Read replyToMode from the merged per-account config via
resolveMattermostAccount so account-level overrides are honored in
multi-account setups. Add replyToMode to MattermostAccountConfig type.
Rename misleading test to clarify it exercises shouldDropFinalPayloads
short-circuit, not payload key dedup.

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* Replies: keep block-pipeline reply targets distinct

* Tests: cover block reply target-aware dedupe

* Update CHANGELOG.md

---------

Co-authored-by: Claude Opus 4.6 <[email protected]>
Co-authored-by: Vincent Koc <[email protected]>

* Models: enforce source-managed SecretRef markers in models.json (#43759)

Merged via squash.

Prepared head SHA: 4a065ef5d849273756ceb0dd241ca24ca9e621ca
Co-authored-by: joshavant <[email protected]>
Co-authored-by: joshavant <[email protected]>
Reviewed-by: @joshavant

* BlueBubbles: require confirmed outbound for self-chat cache

* Agents: recover malformed Anthropic-compatible tool call args (#42835)

* Agents: recover malformed anthropic tool call args

* Agents: add malformed tool call regression test

* Changelog: note Kimi tool call arg recovery

* Agents: repair toolcall end message snapshots

* Agents: narrow Kimi tool call arg repair

* Infra: tighten exec allowlist glob matching (#43798)

* Infra: tighten exec allowlist glob matching

* Changelog: note GHSA-f8r2 exec allowlist fix

* fix: scope telegram polling restart to telegram errors (#43799)

* fix: scope telegram polling restart to telegram errors

* fix: make telegram error tagging best-effort

* fix: scope telegram polling restart to telegram errors (#43799)

* feat(ui): add chat infrastructure modules (slice 1/3 of dashboard-v2) (#41497)

* feat(ui): add chat infrastructure modules (slice 1 of dashboard-v2)

New self-contained chat modules extracted from dashboard-v2-structure:

- chat/slash-commands.ts: slash command definitions and completions
- chat/slash-command-executor.ts: execute slash commands via gateway RPC
- chat/slash-command-executor.node.test.ts: test coverage
- chat/speech.ts: speech-to-text (STT) support
- chat/input-history.ts: per-session input history navigation
- chat/pinned-messages.ts: pinned message management
- chat/deleted-messages.ts: deleted message tracking
- chat/export.ts: shared exportChatMarkdown helper
- chat-export.ts: re-export shim for backwards compat

Gateway fix:
- Restore usage/cost stripping in chat.history sanitization
- Add test coverage for sanitization behavior

These modules are additive and tree-shaken — no existing code
imports them yet. They will be wired in subsequent slices.

* Update ui/src/ui/chat/export.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* fix(ui): address review feedback on chat infra slice

- export.ts: handle array content blocks (Claude API format) instead
  of silently exporting empty strings
- slash-command-executor.ts: restrict /kill all to current session's
  subagent subtree instead of all sessions globally
- slash-command-executor.ts: only count truly aborted runs (check
  aborted !== false) in /kill summary

* fix: scope /kill <id> to current session subtree and preserve usage.cost in chat.history

- Restrict /kill <id> matching to only subagents belonging to the current
  session's agent subtree (P1 review feedback)
- Preserve nested usage.cost in chat.history sanitization so cost badges
  remain available (P2 review feedback)

* fix(ui): tighten slash kill scoping

* fix(ui): support legacy slash kill scopes

* fix(ci): repair pr branch checks

* Gateway: harden chat abort and export

* UI: align slash commands with session tree scope

* UI: resolve session aliases for slash command lookups

* Update .gitignore

* Cron: use shared nested lane resolver

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: Vincent Koc <[email protected]>

* Agents: clear invalidated Kimi tool arg repair (#43824)

* Tests: extend exec allowlist glob coverage

* Gateway: keep spawned workspace overrides internal (#43801)

* Gateway: keep spawned workspace overrides internal

* Changelog: note GHSA-2rqg agent boundary fix

* Gateway: persist spawned workspace inheritance in sessions

* Agents: clean failed lineage spawn state

* Tests: cover lineage attachment cleanup

* Tests: cover lineage thread cleanup

* Gateway: block profile mutations via browser.request (#43800)

* Gateway: block profile mutations via browser.request

* Changelog: note GHSA-vmhq browser request fix

* Gateway: normalize browser.request profile guard paths

* feat(llm-task): add thinking override

Co-authored-by: Xaden Ryan <[email protected]>

* feat(ui): utilities, theming, and i18n updates (slice 2/3 of dashboard-v2) (#41500)

* feat(ui): add utilities, theming, and i18n updates (slice 2 of dashboard-v2)

UI utilities and theming improvements extracted from dashboard-v2-structure:

Icons & formatting:
- icons.ts: expanded icon set for new dashboard views
- format.ts: date/number formatting helpers
- tool-labels.ts: human-readable tool name mappings

Theming:
- theme.ts: enhanced theme resolution and system theme support
- theme-transition.ts: simplified transition logic
- storage.ts: theme parsing improvements for settings persistence

Navigation & types:
- navigation.ts: extended tab definitions for dashboard-v2
- app-view-state.ts: expanded view state management
- types.ts: new type definitions (HealthSummary, ModelCatalogEntry, etc.)

Components:
- components/dashboard-header.ts: reusable header component

i18n:
- Updated en, pt-BR, zh-CN, zh-TW locales with new dashboard strings

All changes are additive or backwards-compatible. Build passes.
Part of #36853.

* ui: fix theme and locale review regressions

* ui: fix review follow-ups for dashboard tabs

* ui: allowlist locale password placeholder false positives

* ui: fix theme mode and locale regressions

* Vincentkoc code/pr 41500 route fix (#43829)

* UI: keep unfinished settings routes hidden

* UI: normalize light theme data token

* UI: restore cron type compatibility

---------

Co-authored-by: Vincent Koc <[email protected]>

* Docs: clarify llm-task thinking presets

* Refactor: trim duplicate gateway/onboarding helpers and dead utils (#43871)

* Gateway: share input provenance schema

* Onboarding: dedupe top-level channel patching

* Utils: remove unused path helpers

* Protocol: refresh generated gateway models

* feat(zalouser): add markdown-to-Zalo text style parsing (#43324)

* feat(zalouser): add markdown-to-Zalo text style parsing

Parse markdown formatting (bold, italic, strikethrough, headings, lists,
code blocks, blockquotes, custom color/style tags) into Zalo native
TextStyle ranges so outbound messages render with rich formatting.

- Add text-styles.ts with parseZalouserTextStyles() converter
- Wire markdown mode into send pipeline (sendMessageZalouser)
- Export TextStyle enum and Style type from zca-client
- Add textMode/textStyles to ZaloSendOptions
- Pass textStyles through sendZaloTextMessage to zca-js API
- Enable textMode:"markdown" in outbound sendText/sendMedia and monitor
- Add comprehensive tests for parsing, send, and channel integration

* fix(zalouser): harden markdown text parsing

* fix(zalouser): mirror zca-js text style types

* fix(zalouser): support tilde fenced code blocks

* fix(zalouser): handle quoted fenced code blocks

* fix(zalouser): preserve literal quote lines in code fences

* fix(zalouser): support indented quoted fences

* fix(zalouser): preserve quoted markdown blocks

* fix(zalouser): rechunk formatted messages

* fix(zalouser): preserve markdown structure across chunks

* fix(zalouser): honor chunk limits and CRLF fences

* fix(failover): add missing network errno patterns to text-based timeout classifier (#42830)

Merged via squash.

Prepared head SHA: 91761487e8825c0fd6582a762d04bba04f726a85
Co-authored-by: jnMetaCode <[email protected]>
Co-authored-by: altaywtf <[email protected]>
Reviewed-by: @altaywtf

* fix: preserve sandbox write payload stdin (#43876)

Merged via squash.

Prepared head SHA: a10fd4b21c78ec57411e6a4f387f16b1441660c2
Co-authored-by: glitch418x <[email protected]>
Co-authored-by: altaywtf <[email protected]>
Reviewed-by: @altaywtf

* fix: stop main-session UI replies inheriting channel routes

* fix: stop main-session UI replies inheriting channel routes (#43918)

* fix: add zalouser outbound chunker

* fix(doctor): canonicalize gateway service entrypoint paths (#43882)

Merged via squash.

Prepared head SHA: 9f530d2a86b5d30822d4419db7cffae6a560ddca
Co-authored-by: ngutman <[email protected]>
Co-authored-by: ngutman <[email protected]>
Reviewed-by: @ngutman

* docs: add Kubernetes install guide, setup script, and manifests (#34492)

* add docs and manifests for k8s install

Signed-off-by: sallyom <[email protected]>

* changelog

Signed-off-by: sallyom <[email protected]>

---------

Signed-off-by: sallyom <[email protected]>

* feat(mattermost): add replyToMode support (off | first | all) (#29587)

Merged via squash.

Prepared head SHA: 4a67791f53b1109959082738429471b7a5bc93b8
Co-authored-by: teconomix <[email protected]>
Co-authored-by: mukhtharcm <[email protected]>
Reviewed-by: @mukhtharcm

* fix(telegram): allow fallback models in /model validation (#40105)

Merged via squash.

Prepared head SHA: de07585e03cba06897d50c1d79fbe09d326c6ac9
Co-authored-by: avirweb <[email protected]>
Co-authored-by: velvet-shark <[email protected]>
Reviewed-by: @velvet-shark

* fix: carry observed overflow token counts into compaction (#40357)

Merged via squash.

Prepared head SHA: b99eed4329bda45083cdedc2386c2c4041c034be
Co-authored-by: rabsef-bicrym <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman

* fix(status): resolve context window by provider-qualified key, prefer max on bare-id collision, solve #35976 (#36389)

Merged via squash.

Prepared head SHA: f8cf752c59708fb388fd200276115277e8b217d6
Co-authored-by: haoruilee <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman

* Agents: adapt pi-ai oauth and payload hooks

* build: default to Node 24 and keep Node 22 compat

* build: raise Node 22 compatibility floor to 22.16

* build: align Node 22 guidance with 22.16 minimum

* ci: harden pnpm sticky cache on PRs

* ci: restore PR pnpm cache fallback

* ci: tighten cache docs and node22 gate

* fix(mattermost): pass mediaLocalRoots through reply delivery (#44021)

Merged via squash.

Prepared head SHA: 856f11f129f7d6a4bc8f23e8d13c786ecb871f52
Co-authored-by: LyleLiu666 <[email protected]>
Co-authored-by: mukhtharcm <[email protected]>
Reviewed-by: @mukhtharcm

* Hardening: require LINE webhook signatures (#44090)

* LINE: require webhook signatures in express handler

* LINE: require webhook signatures in node handler

* LINE: update express signature tests

* LINE: update node signature tests

* Changelog: note LINE webhook hardening

* LINE: validate signatures before parsing webhook bodies

* LINE: reject missing signatures before body reads

* Security: preserve Feishu reaction chat type (#44088)

* Feishu: preserve looked-up chat type

* Feishu: fail closed on ambiguous reaction chats

* Feishu: cover reaction chat type fallback

* Changelog: note Feishu reaction hardening

* Feishu: fail closed without resolved chat type

* Feishu: normalize reaction chat type at runtime

* Hardening: tighten preauth WebSocket handshake limits (#44089)

* Gateway: tighten preauth handshake limits

* Changelog: note WebSocket preauth hardening

* Gateway: count preauth frame bytes accurately

* Gateway: cap WebSocket payloads before auth

* Hardening: normalize Unicode command obfuscation detection (#44091)

* Exec: cover unicode obfuscation cases

* Exec: normalize unicode obfuscation detection

* Changelog: note exec detection hardening

* Exec: strip unicode tag character obfuscation

* Exec: harden unicode suppression and length guards

* Exec: require path boundaries for safe URL suppressions

* Security: require Feishu webhook encrypt key (#44087)

* Feishu: require webhook encrypt key in schema

* Feishu: cover encrypt key webhook validation

* Feishu: enforce encrypt key at startup

* Feishu: add webhook forgery regression test

* Feishu: collect encrypt key during onboarding

* Docs: require Feishu webhook encrypt key

* Changelog: note Feishu webhook hardening

* Docs: clarify Feishu encrypt key screenshot

* Feishu: treat webhook encrypt key as secret input

* Feishu: resolve encrypt key only in webhook mode

* Subagents: stop retrying external completion timeouts (#41235) (#43847)

* Changelog: add subagent announce timeout note

* Tests: cover subagent completion timeout no-retry

* Subagents: stop retrying external completion timeouts

* Config: update subagent announce timeout default docs

* Tests: use fake timers for subagent timeout retry guard

* docs: sync Feishu secretref credential matrix

## Summary

- Problem: `src/secrets/target-registry.test.ts` fails on latest `main` because the runtime registry includes Feishu `encryptKey` paths that the docs matrix and surface reference omit.
- Why it matters: the docs/runtime sync guard currently blocks prep and merge work for unrelated PRs, including `#25558`.
- What changed: regenerated the secretref credential matrix and updated the surface reference to include both Feishu `encryptKey` paths.
- What did NOT change (scope boundary): no runtime registry behavior, config semantics, or channel handling changed.

## Change Type (select all)

- [x] Bug fix
- [ ] Feature
- [ ] Refactor
- [x] Docs
- [ ] Security hardening
- [ ] Chore/infra

## Scope (select all touched areas)

- [ ] Gateway / orchestration
- [ ] Skills / tool execution
- [ ] Auth / tokens
- [ ] Memory / storage
- [x] Integrations
- [ ] API / contracts
- [ ] UI / DX
- [ ] CI/CD / infra

## Linked Issue/PR

- Closes #
- Related #25558

## User-visible / Behavior Changes

None.

## Security Impact (required)

- New permissions/capabilities? `No`
- Secrets/tokens handling changed? `No`
- New/changed network calls? `No`
- Command/tool execution surface changed? `No`
- Data access scope changed? `No`
- If any `Yes`, explain risk + mitigation:

## Repro + Verification

### Environment

- OS: macOS
- Runtime/container: Node.js repo checkout
- Model/provider: N/A
- Integration/channel (if any): Feishu docs/runtime registry sync
- Relevant config (redacted): none

### Steps

1. Check out latest `main` before this change.
2. Run `./node_modules/.bin/vitest run --config vitest.unit.config.ts src/secrets/target-registry.test.ts`.
3. Apply this docs-only sync change and rerun the same command.

### Expected

- The target registry stays in sync with the generated docs matrix and the test passes.

### Actual

- Before this change, the test failed because `channels.feishu.encryptKey` and `channels.feishu.accounts.*.encryptKey` were missing from the docs artifacts.

## Evidence

Attach at least one:

- [x] Failing test/log before + passing after
- [ ] Trace/log snippets
- [ ] Screenshot/recording
- [ ] Perf numbers (if relevant)

## Human Verification (required)

What you personally verified (not just CI), and how:

- Verified scenarios: confirmed the failure on plain latest `main`, applied only these docs entries in a clean bootstrapped worktree, and reran `./node_modules/.bin/vitest run --config vitest.unit.config.ts src/secrets/target-registry.test.ts` to green.
- Edge cases checked: verified both top-level Feishu `encryptKey` and account-scoped `encryptKey` paths are present in the matrix and surface reference.
- What you did **not** verify: full repo test suite and CI beyond the targeted regression.

## Review Conversations

- [x] I replied to or resolved every bot review conversation I addressed in this PR.
- [x] I left unresolved only the conversations that still need reviewer or maintainer judgment.

If a bot review conversation is addressed by this PR, resolve that conversation yourself. Do not leave bot review conversation cleanup for maintainers.

## Compatibility / Migration

- Backward compatible? `Yes`
- Config/env changes? `No`
- Migration needed? `No`
- If yes, exact upgrade steps:

## Failure Recovery (if this breaks)

- How to disable/revert this change quickly: revert this commit.
- Files/config to restore: `docs/reference/secretref-user-supplied-credentials-matrix.json` and `docs/reference/secretref-credential-surface.md`
- Known bad symptoms reviewers should watch for: the target-registry docs sync test failing again for missing Feishu `encryptKey` entries.

## Risks and Mitigations

- Risk: the markdown surface reference could drift from the generated matrix again in a later credential-shape change.
  - Mitigation: `src/secrets/target-registry.test.ts` continues to guard docs/runtime sync.

* Compaction Runner: emit transcript updates post-compact (#25558)

Merged via squash.

Prepared head SHA: 8a858436ed31805124a9d096bd93ab90e5423672
Co-authored-by: rodrigouroz <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman

* Plugins: fix env-aware root resolution and caching (#44046)

Merged via squash.

Prepared head SHA: 6e8852a188b0eaa4d6cf0bb71829023e0e0ed82b
Co-authored-by: gumadeiras <[email protected]>
Co-authored-by: gumadeiras <[email protected]>
Reviewed-by: @gumadeiras

* feat: add sessions_yield tool for cooperative turn-ending (#36537)

Merged via squash.

Prepared head SHA: 75d9204c863792226389a4d33eeb40c4e842528d
Co-authored-by: jriff <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman

* Moonshot: respect explicit baseUrl for CN endpoint so platform.moonshot.cn keys authenticate (#33637) (#33696)

* Moonshot: respect explicit baseUrl for CN endpoint so platform.moonshot.cn keys authenticate (#33637)

* Moonshot: address review - remove dead constant, import canonical URLs (#33696)

* Plugins: require explicit trust for workspace-discovered plugins (#44174)

* Plugins: disable implicit workspace plugin auto-load

* Tests: cover workspace plugin trust gating

* Changelog: note workspace plugin trust hardening

* Plugins: keep workspace trust gate ahead of memory slot defaults

* Tests: cover workspace memory-slot trust bypass

* fix(providers): respect user-configured baseUrl for kimi-coding (#36647)

* fix(providers): respect user-configured baseUrl for kimi-coding

The kimi-coding provider was built exclusively from
`buildKimiCodingProvider()` defaults, ignoring any user-specified
`baseUrl` or other overrides in `openclaw.json` providers config.
This caused 404 errors when users configured a custom endpoint.

Now merge `explicitProviders["kimi-coding"]` on top of defaults,
matching the pattern used by ollama/vllm. User's `baseUrl`, `api`,
and `models` take precedence; env/profile API key still wins.

Fixes #36353

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* Tests: use Kimi implicit provider harness

---------

Co-authored-by: Claude Opus 4.6 <[email protected]>
Co-authored-by: Vincent Koc <[email protected]>

* feat(push): add iOS APNs relay gateway (#43369)

* feat(push): add ios apns relay gateway

* fix(shared): avoid oslog string concatenation

# Conflicts:
#	apps/shared/OpenClawKit/Sources/OpenClawKit/GatewayChannel.swift

* fix(push): harden relay validation and invalidation

* fix(push): persist app attest state before relay registration

* fix(push): harden relay invalidation and url handling

* feat(push): use scoped relay send grants

* feat(push): configure ios relay through gateway config

* feat(push): bind relay registration to gateway identity

* fix(push): tighten ios relay trust flow

* fix(push): bound APNs registration fields (#43369) (thanks @ngutman)

* fix(ios): add live activity horizontal padding

* Zalo: rate limit invalid webhook secret guesses before auth (#44173)

* Zalo: rate limit webhook guesses before auth

* Tests: cover pre-auth Zalo webhook rate limiting

* Changelog: note Zalo pre-auth rate limiting

* Zalo: preserve auth-before-content-type response ordering

* Tests: cover auth-before-content-type webhook ordering

* Zalo: split auth and unauth webhook rate-limit buckets

* Tests: cover auth bucket split for Zalo webhook rate limiting

* Zalo: use trusted proxy client IP for webhook rate limiting

* Tests: cover trusted proxy client IP rate limiting for Zalo

* docs: clarify gateway HTTP trust boundary

* Gateway: harden custom session-store discovery (#44176)

Merged via squash.

Prepared head SHA: 52ebbf5188b47386f2a78ac4715993bc082e911b
Co-authored-by: gumadeiras <[email protected]>
Co-authored-by: gumadeiras <[email protected]>
Reviewed-by: @gumadeiras

* fix(ci): harden docker builds and unblock config docs

* fix: make node-llama-cpp optional for npm installs

* fix: canonicalize openrouter native model keys

* runner: infer names from malformed toolCallId variants (#34485)

Merged via squash.

Prepared head SHA: 150ea1a7c90de3232f72498d851719c4dfb00b43
Co-authored-by: yuweuii <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman

* Gateway: preserve discovered session store paths

* docs: reorder unreleased changelog

* fix(node-host): harden ambiguous approval operand binding (#44247)

* fix(node-host): harden approval operand binding

* test(node-host): cover approval parser hardening

* docs(changelog): note approval hardening GHSA cluster

* Update CHANGELOG.md

* fix(node-host): remove dead approval parser entries

* test(node-host): cover bunx approval wrapper

* fix(node-host): unwrap pnpm shim exec forms

* test(node-host): cover pnpm shim wrappers

* Kimi Coding: set default subscription user agent (#44248)

* Providers: set default Kimi coding user agent

* Tests: cover Kimi coding header overrides

* Changelog: note Kimi coding user agent

* Tests: satisfy Kimi provider fixture type

* Update CHANGELOG.md

* Providers: preserve Kimi headers through models merge

* feat(ui): dashboard-v2 views refactor (slice 3/3 of dashboard-v2) (#41503)

* feat(ui): add chat infrastructure modules (slice 1 of dashboard-v2)

New self-contained chat modules extracted from dashboard-v2-structure:

- chat/slash-commands.ts: slash command definitions and completions
- chat/slash-command-executor.ts: execute slash commands via gateway RPC
- chat/slash-command-executor.node.test.ts: test coverage
- chat/speech.ts: speech-to-text (STT) support
- chat/input-history.ts: per-session input history navigation
- chat/pinned-messages.ts: pinned message management
- chat/deleted-messages.ts: deleted message tracking
- chat/export.ts: shared exportChatMarkdown helper
- chat-export.ts: re-export shim for backwards compat

Gateway fix:
- Restore usage/cost stripping in chat.history sanitization
- Add test coverage for sanitization behavior

These modules are additive and tree-shaken — no existing code
imports them yet. They will be wired in subsequent slices.

* feat(ui): add utilities, theming, and i18n updates (slice 2 of dashboard-v2)

UI utilities and theming improvements extracted from dashboard-v2-structure:

Icons & formatting:
- icons.ts: expanded icon set for new dashboard views
- format.ts: date/number formatting helpers
- tool-labels.ts: human-readable tool name mappings

Theming:
- theme.ts: enhanced theme resolution and system theme support
- theme-transition.ts: simplified transition logic
- storage.ts: theme parsing improvements for settings persistence

Navigation & types:
- navigation.ts: extended tab definitions for dashboard-v2
- app-view-state.ts: expanded view state management
- types.ts: new type definitions (HealthSummary, ModelCatalogEntry, etc.)

Components:
- components/dashboard-header.ts: reusable header component

i18n:
- Updated en, pt-BR, zh-CN, zh-TW locales with new dashboard strings

All changes are additive or backwards-compatible. Build passes.
Part of #36853.

* feat(ui): dashboard-v2 views refactor (slice 3 of dashboard-v2)

Complete views refactor from dashboard-v2-structure, building on
slice 1 (chat infra, #41497) and slice 2 (utilities/theming, #41500).

Core app wiring:
- app.ts: updated host component with new state properties
- app-render.ts: refactored render pipeline for new dashboard layout
- app-render.helpers.ts: extracted render helpers
- app-settings.ts: theme listener lifecycle fix, cron runs on tab load
- app-gateway.ts: refactored chat event handling
- app-chat.ts: slash command integration

New views:
- views/command-palette.ts: command palette (Cmd+K)
- views/login-gate.ts: authentication gate
- views/bottom-tabs.ts: mobile tab navigation
- views/overview-*.ts: modular overview dashboard (cards, attention,
  event log, hints, log tail, quick actions)
- views/agents-panels-overview.ts: agent overview panel

Refactored views:
- views/chat.ts: major refactor with STT, slash commands, search,
  export, pinned messages, input history
- views/config.ts: restructured config management
- views/agents.ts: streamlined agent management
- views/overview.ts: modular composition from sub-views
- views/sessions.ts: enhanced session management

Controllers:
- controllers/health.ts: new health check controller
- controllers/models.ts: new model catalog controller
- controllers/agents.ts: tools catalog improvements
- controllers/config.ts: config form enhancements

Tests & infrastructure:
- Updated test helpers, browser tests, node tests
- vite.config.ts: build configuration updates
- markdown.ts: rendering improvements

Build passes ✅ | 44 files | +6,626/-1,499
Part of #36853. Depends on #41497 and #41500.

* UI: fix chat review follow-ups

* fix(ui): repair chat clear and attachment regressions

* fix(ui): address remaining chat review comments

* fix(ui): address review follow-ups

* fix(ui): replay queued local slash commands

* fix(ui): repair control-ui type drift

* fix(ui): restore control UI styling

* feat(ui): enhance layout and styling for config and topbar components

- Updated grid layout for the config layout to allow full-width usage.
- Introduced new styles for top tabs and search components to improve usability.
- Added theme mode toggle styling for better visual integration.
- Implemented tests for layout and theme mode components to ensure proper rendering and functionality.

* feat(ui): add config file opening functionality and enhance styles

- Implemented a new handler to open the configuration file using the default application based on the operating system.
- Updated various CSS styles across components for improved visual consistency and usability, including adjustments to padding, margins, and font sizes.
- Introduced new styles for the data table and sidebar components to enhance layout and interaction.
- Added tests for the collapsed navigation rail to ensure proper functionality in different states.

* refactor(ui): update CSS styles for improved layout and consistency

- Simplified font-body declaration in base.css for cleaner code.
- Adjusted transition properties in components.css for better readability.
- Added new .workspace-link class in components.css for enhanced link styling.
- Changed config layout from grid to flex in config.css for better responsiveness.
- Updated related tests to reflect layout changes in config-layout.browser.test.ts.

* feat(ui): enhance theme handling and loading states in chat interface

- Updated CSS to support new theme mode attributes for better styling consistency across light and dark themes.
- Introduced loading skeletons in the chat view to improve user experience during data fetching.
- Refactored command palette to manage focus more effectively, enhancing accessibility.
- Added tests for the appearance theme picker and loading states to ensure proper rendering and functionality.

* refactor(ui): streamline ephemeral state management in chat and config views

- Introduced interfaces for ephemeral state in chat and config views to encapsulate related variables.
- Refactored state management to utilize a single object for better organization and maintainability.
- Removed legacy state variables and updated related functions to reference the new state structure.
- Enhanced readability and consistency across the codebase by standardizing state handling.

* chore: remove test files to reduce PR scope

* fix(ui): resolve type errors in debug props and chat search

* refactor(ui): remove stream mode functionality across various components

- Eliminated stream mode related translations and CSS styles to streamline the user interface.
- Updated multiple components to remove references to stream mode, enhancing code clarity and maintainability.
- Adjusted rendering logic in views to ensure consistent behavior without stream mode.
- Improved overall readability by cleaning up unused variables and props.

* fix(ui): add msg-meta CSS and fix rebase type errors

* fix(ui): add CSS for chat footer action buttons (TTS, delete) and msg-meta

* feat(ui): add delete confirmation with remember-decision checkbox

* fix(ui): delete confirmation with remember, attention icon sizing

* fix(ui): open delete confirm popover to the left (not clipped)

* fix(ui): show all nav items in collapsed sidebar, remove gap

* fix(ui): address P1/P2 review feedback — session queue clear, kill scope, palette guard, stop button

* fix(ui): address Greptile re-review — kill scope, queue flush, idle handling, parallel fetch

- SECURITY: /kill <target> now enforces session tree scope (not just /kill all)
- /kill reports idle sessions gracefully instead of throwing
- Queue continues draining after local slash commands
- /model fetches sessions.list + models.list in parallel (perf fix)

* fix(ui): style update banner close button — SVG stroke + sizing

* fix(ui): update layout styles for sidebar and content spacing

* UI: restore colon slash command parsing

* UI: restore slash command session queries

* Refactor thinking resolution: Introduce resolveThinkingDefaultForModel function and update model-selection to utilize it. Add tests for new functionality in thinking.test.ts.

* fix(ui): constrain welcome state logo size, add missing CSS for new session view

---------

Co-authored-by: Vincent Koc <[email protected]>

* fix: restore protocol outputs and stabilize Windows path CI (#44266)

* fix(ci): restore protocol outputs and stabilize Windows path test

Regenerate the Swift protocol models so protocol:check stops failing on main.
Align the session target test helper with the sync production realpath behavior so Windows does not compare runneradmin and RUNNER~1 spellings for the same file.

Regeneration-Prompt: |
  Investigate the failing checks from merged PR #34485 and confirm whether they still affect current main before changing code. Keep the fix tight: do not alter runtime behavior beyond what is required to clear the reproduced CI regressions. Commit the generated Swift protocol outputs for the PushTestResult transport field because protocol:check was failing from stale generated files on main. Also fix the Windows-only session target test by making its helper use the same synchronous realpath behavior as production discovery, so path spelling differences like runneradmin versus RUNNER~1 do not cause a false assertion failure.

* fix(ci): align session target realpath behavior on Windows

Use native realpath for sync session target discovery so it matches the async path on Windows, and update the session target test helper to assert against the same canonical path form.

Regeneration-Prompt: |
  After opening the follow-up PR for the CI regressions from merged PR #34485, inspect the new failing Windows shard instead of assuming the first fix covered every case. Keep scope limited to the session target path mismatch exposed by CI. Fix the inconsistency at the source by making sync session target discovery use the same native realpath canonicalization as the async discovery path on Windows, then update the test helper to match that shared behavior and verify the touched file with targeted tests and file-scoped lint/format checks.

* test: make merge config fixtures satisfy provider type

After rebasing the PR onto current origin/main, the merge helper test fixtures no longer satisfied ProviderConfig because the anthropic provider examples were missing required provider and model fields. Add a shared fully-typed model fixture and explicit anthropic baseUrl values so the test keeps full type coverage under tsgo.

Regeneration-Prompt: |
  Rebase the PR branch for #44266 onto the current origin/main because the failing CI error only reproduced on the merge ref. Re-run the type-check path and inspect src/agents/models-config.merge.test.ts at the exact compiler lines instead of weakening types globally. Keep the fix test-only: make the anthropic ProviderConfig fixtures structurally valid by supplying the required baseUrl and full model definition fields, and keep the shared fixture typed so tsgo accepts it without unknown casts.

* fix: align Windows session store test expectations

* chore(changelog): update CHANGELOG.md to include new features in dashboard-v2, highlighting the refreshed gateway dashboard with modular views and enhanced chat tools (#41503)

* Ollama/Kimi: apply Moonshot payload compatibility (#44274)

* Runner: extend Moonshot payload compat to Ollama Kimi

* Changelog: note Ollama Kimi tool routing

* Tests: cover Ollama Kimi payload compat

* Runner: narrow Ollama Kimi payload compat

* onboard(minimax): flatten auth to 4 direct choices, unify CN/Global under single provider (#44284)

Replace the multi-step MiniMax onboarding wizard with 4 flat options:
- MiniMax Global — OAuth (minimax.io)
- MiniMax Global — API Key (minimax.io)
- MiniMax CN — OAuth (minimaxi.com)
- MiniMax CN — API Key (minimaxi.com)

Storage changes:
- Unify CN and Global under provider "minimax" (baseUrl distinguishes region)
- Profiles: minimax:global / minimax:cn (both regions can coexist)
- Model ref: minimax/MiniMax-M2.5 (no more minimax-cn/ prefix)
- Remove LM Studio local mode and Lightning/Highspeed choice

Backward compatibility:
- Keep minimax-cn in provider-env-vars for existing configs
- Accept minimax-cn as legacy tokenProvider in CI pipelines
- Error with migration hint for removed auth choices in non-interactive mode
- Warn when dual-profile overwrites shared provider baseUrl

Made-with: Cursor

* Gateway/ws: clear unbound scopes for shared-token auth (#44306)

* Gateway/ws: clear unbound shared-auth scopes

* Gateway/auth: cover shared-token scope stripping

* Changelog: add shared-token scope stripping entry

* Gateway/ws: preserve allowed control-ui scopes

* Gateway/auth: assert control-ui admin scopes survive allowed device-less auth

* Gateway/auth: cover shared-password scope stripping

* fix: format CSS files for oxfmt (#44313)

* Commands: require owner for /config and /debug (#44305)

* Commands: add non-owner gate helper

* Commands: enforce owner-only config and debug

* Commands/test: cover owner-only config and debug

* Changelog: add owner-only config debug entry

* Commands/test: split config owner gating section

* Commands: redact sender ids in verbose command logs

* Commands: preserve internal read-only config access

* Commands/test: keep operator.write config show coverage non-owner

* fix(runtime): duplicate messages, share singleton state across bundled chunks (#43683)

* Tests: add fresh module import helper

* Process: share command queue runtime state

* Agents: share embedded run runtime state

* Reply: share followup queue runtime state

* Reply: share followup drain callback state

* Reply: share queued message dedupe state

* Reply: share inbound dedupe state

* Tests: cover shared command queue runtime state

* Tests: cover shared embedded run runtime state

* Tests: cover shared followup queue runtime state

* Tests: cover shared inbound dedupe state

* Tests: cover shared Slack thread participation state

* Slack: share sent thread participation state

* Tests: document fresh import helper

* Telegram: share draft stream runtime state

* Tests: cover shared Telegram draft stream state

* Telegram: share sent message cache state

* Tests: cover shared Telegram sent message cache

* Telegram: share thread binding runtime state

* Tests: cover shared Telegram thread binding state

* Tests: avoid duplicate shared queue reset

* refactor(runtime): centralize global singleton access

* refactor(runtime): preserve undefined global singleton values

* test(runtime): cover undefined global singleton values

---------

Co-authored-by: Nimrod Gutman <[email protected]>

* fix(sandbox): restore spawned workspace handoff (#44307)

* feat(context-engine): plumb sessionKey into all ContextEngine methods (#44157)

Merged via squash.

Prepared head SHA: 0b341f6f4ce487055d8bc0c0d335c42577941592
Co-authored-by: jalehman <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman

* docs: codify American English spelling convention (#44159)

* fix(failover): classify z.ai network_error stop reason as retryable timeout (#43884)

Merged via squash.

Prepared head SHA: 9660f6cd5bcb8d073fc5575bbba2bf3792b29de3
Co-authored-by: hougangdev <[email protected]>
Co-authored-by: altaywtf <[email protected]>
Reviewed-by: @altaywtf

* fix(failover): classify ZenMux quota-refresh 402 as rate_limit (#43917)

Merged via squash.

Prepared head SHA: 1d58a36a774d06b1493971e8f14f9abc806be6b0
Co-authored-by: bwjoke <[email protected]>
Co-authored-by: altaywtf <[email protected]>
Reviewed-by: @altaywtf

* Compaction Runner: wire post-compaction memory sync (#25561)

Merged via squash.

Prepared head SHA: 6d2bc02cc16429a19b041acd353c08dd2404335f
Co-authored-by: rodrigouroz <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman

* fix(gateway): honor trusted proxy hook auth rate limits

* fix(security): audit unrestricted hook agent routing

* refactor(gateway): move request client ip resolution to net

* refactor(gateway): cache hook proxy config in runtime state

* refactor(security): reuse hook agent routing normalization

* refactor(test): share hook request handler fixtures

* fix(failover): classify HTTP 422 as format and OpenRouter credits as billing (#43823)

Merged via squash.

Prepared head SHA: 4f48e977fe06c5662753d3900fe94f1835cc2dce
Co-authored-by: jnMetaCode <[email protected]>
Co-authored-by: altaywtf <[email protected]>
Reviewed-by: @altaywtf

* fix: skip cache-ttl append after compaction to prevent double compaction (#28548)

Merged via squash.

Prepared head SHA: a4114a52bcff6ed4057cc54d3c629bd723f3d420
Co-authored-by: MoerAI <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman

* fix: switch pairing setup codes to bootstrap tokens

* feat: modularize provider plugin architecture

* docs: explain plugin architecture

* fix(ci): restore generated protocol swift outputs (#44411)

Regenerate the Swift protocol models so PushTestResult keeps the transport field required by the current gateway schema, and update protocol:check to diff both generated Swift destinations because the generator writes both files.

Regeneration-Prompt: |
  Investigate the protocol CI failure on current origin/main rather than assuming the earlier fix still held. Confirm whether the generated Swift outputs drifted from the TypeScript gateway schema, identify whether the regression was reintroduced by a later commit, and keep the patch minimal: restore the generated Swift outputs from the existing schema and tighten the protocol check so it verifies every Swift file the generator writes.

* fix(security): harden nodes owner-only tool gating

* refactor: share openai-compatible local discovery

* refactor: remove legacy provider apply shims

* refactor: split non-interactive auth choice providers

* refactor: split simple api-key auth providers

* test: cover provider plugin boundaries

* refactor: unify gateway connect auth selection

* refactor: trim bootstrap token metadata

* refactor: extract websocket handshake auth helpers

* refactor: clarify pairing setup auth labels

* deps: bump openclaw to 2026.3.11

Raise internal OpenClaw constraints to 2026.3.11 and regenerate pnpm lockfile to remove the vulnerable 2026.3.8 resolution.

* fix: harden windows npm runtime path

* feat: add --no-test flag to prepare-gates

Allows skipping the full test suite during prepare phase.
Testing is deferred to the dedicated Test phase in the pipeline.

* fix(node-host): fail closed on ruby approval preload flags

* feat: add fast mode toggle for OpenAI models

* Revert "feat: add --no-test flag to prepare-gates"

This reverts commit ee6bdb3bab26f2796943c6cac03d8f62a5664937.

* feat: add Anthropic fast mode support

* fix: harden windows native updates

* feat: add windows update package spec override

* fix(hooks): dedupe repeated agent deliveries by idempotency key (#44438)

* Hooks: add hook idempotency key resolution

* Hooks: dedupe repeated agent deliveries by idempotency key

* Tests: cover hook idempotency dedupe

* Changelog: note hook idempotency dedupe

* Hooks: cap hook idempotency key length

* Gateway: hash hook replay cache keys

* Tests: cover hook replay key hardening

* fix(hooks): fail closed on unreadable loader paths (#44437)

* Hooks: fail closed on unreadable loader paths

* Changelog: note hooks loader hardening

* Tests: cover sanitized hook loader logs

* Hooks: use realpath containment for legacy loaders

* Hooks: sanitize unreadable workspace log path

* fix(models): keep codex spark codex-only

* test(live): add codex instructions to spark probe

* fix(security): strip Mongolian selectors in exec obfuscation detector

* Gateway: preserve trusted-proxy browser scopes

* build: update deps and fix vitest 4 regressions

* build: sync bundled plugin versions

* refactor: add non-interactive provider plugin setup

* refactor: validate provider plugin metadata

* fix(zalouser): require ids for group allowlist auth

* fix: avoid ineffective dynamic imports

* fix(mac): adopt canonical session key and add reset triggers (#10898)

Add shared native chat handling for /new, /reset, and /clear.

This also aligns main session key handling in the shared chat UI and includes follow-up test and CI fixes needed to keep the branch mergeable.

Co-authored-by: Nachx639 <[email protected]>
Co-authored-by: Luke <[email protected]>

* test: resolve rebase conflicts in gateway coverage

* chore: prepare 2026.3.12 release

* refactor(zalouser): reuse shared name matching helper

* feat(zalouser): audit mutable group allowlists

* fix(routing): require ids for slack and msteams allowlists

* fix: quiet Telegram command overflow retry logs

* fix(memory): fail closed for Windows qmd wrappers

* docs(ollama): update onboarding flow

Co-Authored-By: Jeffrey Morgan <[email protected]>
(cherry picked from commit e8ca2ff4e522f2d971801a537b3c4fdfecde0711)

* fix: align Ollama onboarding docs before landing (#43473) (thanks @BruceMacD)

(cherry picked from commit 19fa274343a102ca85c7679ec28c5a3503a99f55)

* docs: reorder latest release changelog

* test: stabilize hooks loader log assertion on Windows
…
0x666c6f added a commit to 0x666c6f/openclaw that referenced this pull request Mar 26, 2026
…claw#57)

* fix(gateway): run before_tool_call for HTTP tools

* test(gateway): widen before tool hook mock typing (#43476)

* test(gateway): widen before tool hook mock typing

* chore: update pnpm.lock

* Gateway/Dashboard: surface config validation issues (#42664)

Merged via squash.

Prepared head SHA: 43f66cdcf04a14d5381a5a2f14e291a52a8b7389
Co-authored-by: huntharo <[email protected]>
Co-authored-by: huntharo <[email protected]>
Reviewed-by: @huntharo

* Memory: add multimodal image and audio indexing (#43460)

Merged via squash.

Prepared head SHA: a994c07190a2062322f459c928b6cd74f9803d88
Co-authored-by: gumadeiras <[email protected]>
Co-authored-by: gumadeiras <[email protected]>
Reviewed-by: @gumadeiras

* fix(hooks): add missing trigger and channelId to agent_end, llm_input, and llm_output hook contexts (#42362)

Merged via squash.

Prepared head SHA: e6d7b7e31aa6ae12813b4609adb6e569a4084d08
Co-authored-by: zhoulf1006 <[email protected]>
Co-authored-by: hydro13 <[email protected]>
Reviewed-by: @hydro13

* Memory: revalidate multimodal files before indexing

* preserve openai phase param

* chore: bump version to 2026.3.10

* fix(terminal): sanitize skills JSON and fallback on legacy Windows (#43520)

* Terminal: use ASCII borders on legacy Windows consoles

* Skills: sanitize JSON output for control bytes

* Changelog: credit terminal follow-up fixes

* Update CHANGELOG.md

* Update CHANGELOG.md

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* Skills: strip remaining escape sequences from JSON output

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* fix: repair bundled plugin dirs after npm install

* fix(daemon): replace bootout with kickstart -k for launchd restarts on macOS

On macOS, launchctl bootout permanently unloads the LaunchAgent plist.
Even with KeepAlive: true, launchd cannot respawn a service whose plist
has been removed from its registry. This left users with a dead gateway
requiring manual 'openclaw gateway install' to recover.

Affected trigger paths:
- openclaw gateway restart from an agent session (#43311)
- SIGTERM on config reload (#43406)
- Gateway self-restart via SIGTERM (#43035)
- Hot reload on channel config change (#43049)

Switch restartLaunchAgent() to launchctl kickstart -k, which force-kills
and restarts the service without unloading the plist. When the restart
originates from inside the launchd-managed process tree, delegate to a
new detached handoff helper (launchd-restart-handoff.ts) to avoid the
caller being killed mid-command. Self-restart paths in process-respawn.ts
now schedule the detached start-after-exit handoff before exiting instead
of relying on exit/KeepAlive timing.

Fixes #43311, #43406, #43035, #43049

* fix(gateway): enforce browser origin check regardless of proxy headers

In trusted-proxy mode, enforceOriginCheckForAnyClient was set to false
whenever proxy headers were present. This allowed browser-originated
WebSocket connections from untrusted origins to bypass origin validation
entirely, as the check only ran for control-ui and webchat client types.

An attacker serving a page from an untrusted origin could connect through
a trusted reverse proxy, inherit proxy-injected identity, and obtain
operator.admin access via the sharedAuthOk / roleCanSkipDeviceIdentity
path without any origin restriction.

Remove the hasProxyHeaders exemption so origin validation runs for all
browser-originated connections regardless of how the request arrived.

Fixes GHSA-5wcw-8jjv-m286

* fix: harden state dir permissions during onboard

* fix(whatsapp): trim leading whitespace in direct outbound sends (#43539)

Trim leading whitespace from direct WhatsApp text and media caption sends.

Also guard empty text-only web sends after trimming.

* fix(node-host): extend script-runner set and add fail-closed guard for mutable-file approval

tsx, jiti, ts-node, ts-node-esm, vite-node, and esno were not recognized
as interpreter-style script runners in invoke-system-run-plan.ts. These
runners produced mutableFileOperand: null, causing invoke-system-run.ts
to skip revalidation entirely. A mutated script payload would execute
without the approval binding check that node ./run.js already enforced.

Two-part fix:
- Add tsx, jiti, and related TypeScript/ESM loaders to the known script
  runner set so they produce a valid mutableFileOperand from the planner
- Add a fail-closed runtime guard in invoke-system-run.ts that denies
  execution when a script run should have a mutable-file binding but the
  approval plan is missing it, preventing unknown future runners from
  silently bypassing revalidation

Fixes GHSA-qc36-x95h-7j53

* fix(daemon): address clanker review findings for kickstart restart

Bug 1 (high): replace fixed sleep 1 with caller-PID polling in both
kickstart and start-after-exit handoff modes. The helper now waits until
kill -0 $caller_pid fails before issuing launchctl kickstart -k.

Bug 2 (medium): gate enable+bootstrap fallback on isLaunchctlNotLoaded().
Only attempt re-registration when kickstart -k fails because the job is
absent; all other kickstart failures now re-throw the original error.

Follows up on 3c0fd3dffe.
Fixes #43311, #43406, #43035, #43049

* fix(cli): handle scheduled gateway restarts consistently

* test(cli): update daemon coverage restart contract

* fix: harden openai websocket replay

* fix(discord): enforce users/roles allowlist in reaction ingress

References GHSA-9vvh-2768-c8vp.

* test: fix websocket tool shape coverage

* fix: isolate plugin discovery env from global state

* fix(sandbox): anchor fs-bridge writeFile commit to canonical parent path

Refs: GHSA-xvx8-77m6-gwg6

* feat: expose runtime version in gateway status

* fix(acp): rehydrate restarted main ACP sessions (#43285)

Merged via squash.

Prepared head SHA: f06318e58fe3e3fedd70426ca7eeecf6d71bb604
Co-authored-by: frankekn <[email protected]>
Co-authored-by: frankekn <[email protected]>
Reviewed-by: @frankekn

* fix(context-engine): guard compact() throw + fire hooks for ownsCompaction engines (#41361)

Merged via squash.

Prepared head SHA: 0957b32dc63b16d710403565953b77bfbd2bd987
Co-authored-by: davidrudduck <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman

* docs: reorder unreleased changelog by user impact

* OpenRouter: surface free Hunter and Healer stealth models for the next week (#43642)

* Models: add temporary Hunter and Healer alpha to OpenRouter catalog

* Add temporary OpenRouter stealth catalog entries

---------

Co-authored-by: Tak Hoffman <[email protected]>

* docs: update 2026.3.11 release examples

* build: sync versions to 2026.3.11

* fix(telegram): avoid polling restart hang after stall detection

* fix: clear telegram polling cleanup timers

* build: bump openclaw to 2026.3.11-beta.1

* docs: update Raspberry Pi dashboard access instructions (#43584)

* docs(pi): update dashboard access instructions

* docs(i18n): refresh raspberry pi source hash

* docs: clarify Raspberry Pi dashboard access

* fix: clarify Raspberry Pi dashboard access (#43584) (thanks @neeravmakwana)

---------

Co-authored-by: Neerav Makwana <[email protected]>
Co-authored-by: Ayaan Zaidi <[email protected]>

* build: prepare 2026.3.11 release

* fix(browser): restore proxy attachment media size cap (#43684)

* browser: honor shared proxy file size cap

* test(browser): cover proxy file size cap

* docs(changelog): note browser proxy size cap fix

* Infra: block GIT_EXEC_PATH in host env sanitizer (#43685)

* Infra: block GIT_EXEC_PATH in host env sanitizer

* Changelog: note host env hardening

* Security: escape invisible exec approval format chars (#43687)

* Infra: escape invisible exec approval chars

* Gateway: sanitize exec approval display text

* Tests: cover sanitized exec approval payloads

* Tests: cover sanitized exec approval forwarding

* Changelog: note exec approval prompt hardening

* Infra: cap device tokens to approved scopes (#43686)

* Infra: cap device tokens to approved scopes

* Changelog: note device token hardening

* Update CHANGELOG.md

* Update CHANGELOG.md

* Tests: clean up temp git helper directory

* Infra: fail closed without device scope baseline

* style: format changelog

* fix(macos): add NSRemindersUsageDescription for apple-reminders skill

Fixes #5090

Without this plist key, macOS silently denies Reminders access when
running through OpenClaw.app, preventing the apple-reminders skill
from requesting permission.

(cherry picked from commit e5774471c851b773dd2bffd51dd5d28d95a8a7ca)

* Changelog: note Reminders permission fix

* fix(imessage): dedupe reflected self-chat duplicates (#38440)

* iMessage: drop reflected self-chat duplicates

* Changelog: add iMessage self-chat echo dedupe entry

* iMessage: keep self-chat dedupe scoped to final group identity

* iMessage: harden self-chat cache

* iMessage: sanitize self-chat duplicate logs

* iMessage: scope group self-chat dedupe by sender

* iMessage: move self-chat cache identity into cache

* iMessage: hash full self-chat text

* Update CHANGELOG.md

* fix(agents): enforce sandboxed session_status visibility (#43754)

* agents: guard sandboxed session_status access

* test(agents): cover sandboxed session_status scope

* docs(changelog): credit session_status hardening

* agents: preflight sandboxed session_status checks

* test(agents): cover session_status existence oracle

* agents: preserve legacy session_status tree keys

* test(agents): cover legacy session_status tree keys

* Update CHANGELOG.md

* fix: prevent duplicate assistant messages in TUI (fixes #35278) (#35364)

* fix: prevent duplicate assistant messages in TUI (fixes #35278)

When startAssistant() is called multiple times with the same runId,
it was creating duplicate AssistantMessageComponent instances instead
of reusing the existing one. This caused messages to appear twice in
the terminal UI.

The fix checks if a component already exists for the runId before
creating a new one. If it exists, we update its text instead of
appending a duplicate component.

Test coverage includes verification that:
- Only one component is created when startAssistant is called twice
- The second text replaces the first
- Component count remains 1 (prevents regression)

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <[email protected]>
Co-Authored-By: Happy <[email protected]>

* Changelog: add TUI duplicate-render fix entry

---------

Co-authored-by: 沐沐 <[email protected]>
Co-authored-by: Claude <[email protected]>
Co-authored-by: Happy <[email protected]>
Co-authored-by: Vincent Koc <[email protected]>

* fix(cron): prevent duplicate proactive delivery on transient retry (#40646)

* fix(cron): prevent duplicate proactive delivery on transient retry

* refactor: scope skipQueue to retryTransient path only

Non-retrying direct delivery (structured content / thread) keeps the
write-ahead queue so recoverPendingDeliveries can replay after a crash.

Addresses review feedback from codex-connector.

* fix: preserve write-ahead queue on initial delivery attempt

The first call through retryTransientDirectCronDelivery now keeps the
write-ahead queue entry so recoverPendingDeliveries can replay after a
crash.  Only subsequent retry attempts set skipQueue to prevent
duplicate sends.

Addresses second codex-connector review on ea5ae5c.

* ci: retrigger checks

* Cron: bypass write-ahead queue for direct isolated delivery

* Tests: assert isolated cron skipQueue invariants

* Changelog: add cron duplicate-delivery fix entry

---------

Co-authored-by: Vincent Koc <[email protected]>

* fix(bluebubbles): dedupe reflected self-chat duplicates (#38442)

* BlueBubbles: drop reflected self-chat duplicates

* Changelog: add BlueBubbles self-chat echo dedupe entry

* BlueBubbles: gate self-chat cache and expand coverage

* BlueBubbles: require explicit sender ids for self-chat dedupe

* BlueBubbles: harden self-chat cache

* BlueBubbles: move self-chat cache identity into cache

* BlueBubbles: gate self-chat cache to confirmed outbound sends

* Update CHANGELOG.md

* BlueBubbles: bound self-chat cache input work

* Tests: cover BlueBubbles cache cap under cleanup throttle

* BlueBubbles: canonicalize self-chat DM scope

* Tests: cover BlueBubbles mixed self-chat scope aliases

* fix(mattermost): prevent duplicate messages when block streaming + threading are active (#41362)

* fix(mattermost): prevent duplicate messages when block streaming + threading are active

Remove replyToId from createBlockReplyPayloadKey so identical content is
deduplicated regardless of threading target. Add explicit threading dock
to the Mattermost plugin with resolveReplyToMode reading from config
(default "all"), and add replyToMode to the Mattermost config schema.

Fixes #41219

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* fix(mattermost): address PR review — per-account replyToMode and test clarity

Read replyToMode from the merged per-account config via
resolveMattermostAccount so account-level overrides are honored in
multi-account setups. Add replyToMode to MattermostAccountConfig type.
Rename misleading test to clarify it exercises shouldDropFinalPayloads
short-circuit, not payload key dedup.

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* Replies: keep block-pipeline reply targets distinct

* Tests: cover block reply target-aware dedupe

* Update CHANGELOG.md

---------

Co-authored-by: Claude Opus 4.6 <[email protected]>
Co-authored-by: Vincent Koc <[email protected]>

* Models: enforce source-managed SecretRef markers in models.json (#43759)

Merged via squash.

Prepared head SHA: 4a065ef5d849273756ceb0dd241ca24ca9e621ca
Co-authored-by: joshavant <[email protected]>
Co-authored-by: joshavant <[email protected]>
Reviewed-by: @joshavant

* BlueBubbles: require confirmed outbound for self-chat cache

* Agents: recover malformed Anthropic-compatible tool call args (#42835)

* Agents: recover malformed anthropic tool call args

* Agents: add malformed tool call regression test

* Changelog: note Kimi tool call arg recovery

* Agents: repair toolcall end message snapshots

* Agents: narrow Kimi tool call arg repair

* Infra: tighten exec allowlist glob matching (#43798)

* Infra: tighten exec allowlist glob matching

* Changelog: note GHSA-f8r2 exec allowlist fix

* fix: scope telegram polling restart to telegram errors (#43799)

* fix: scope telegram polling restart to telegram errors

* fix: make telegram error tagging best-effort

* fix: scope telegram polling restart to telegram errors (#43799)

* feat(ui): add chat infrastructure modules (slice 1/3 of dashboard-v2) (#41497)

* feat(ui): add chat infrastructure modules (slice 1 of dashboard-v2)

New self-contained chat modules extracted from dashboard-v2-structure:

- chat/slash-commands.ts: slash command definitions and completions
- chat/slash-command-executor.ts: execute slash commands via gateway RPC
- chat/slash-command-executor.node.test.ts: test coverage
- chat/speech.ts: speech-to-text (STT) support
- chat/input-history.ts: per-session input history navigation
- chat/pinned-messages.ts: pinned message management
- chat/deleted-messages.ts: deleted message tracking
- chat/export.ts: shared exportChatMarkdown helper
- chat-export.ts: re-export shim for backwards compat

Gateway fix:
- Restore usage/cost stripping in chat.history sanitization
- Add test coverage for sanitization behavior

These modules are additive and tree-shaken — no existing code
imports them yet. They will be wired in subsequent slices.

* Update ui/src/ui/chat/export.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* fix(ui): address review feedback on chat infra slice

- export.ts: handle array content blocks (Claude API format) instead
  of silently exporting empty strings
- slash-command-executor.ts: restrict /kill all to current session's
  subagent subtree instead of all sessions globally
- slash-command-executor.ts: only count truly aborted runs (check
  aborted !== false) in /kill summary

* fix: scope /kill <id> to current session subtree and preserve usage.cost in chat.history

- Restrict /kill <id> matching to only subagents belonging to the current
  session's agent subtree (P1 review feedback)
- Preserve nested usage.cost in chat.history sanitization so cost badges
  remain available (P2 review feedback)

* fix(ui): tighten slash kill scoping

* fix(ui): support legacy slash kill scopes

* fix(ci): repair pr branch checks

* Gateway: harden chat abort and export

* UI: align slash commands with session tree scope

* UI: resolve session aliases for slash command lookups

* Update .gitignore

* Cron: use shared nested lane resolver

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: Vincent Koc <[email protected]>

* Agents: clear invalidated Kimi tool arg repair (#43824)

* Tests: extend exec allowlist glob coverage

* Gateway: keep spawned workspace overrides internal (#43801)

* Gateway: keep spawned workspace overrides internal

* Changelog: note GHSA-2rqg agent boundary fix

* Gateway: persist spawned workspace inheritance in sessions

* Agents: clean failed lineage spawn state

* Tests: cover lineage attachment cleanup

* Tests: cover lineage thread cleanup

* Gateway: block profile mutations via browser.request (#43800)

* Gateway: block profile mutations via browser.request

* Changelog: note GHSA-vmhq browser request fix

* Gateway: normalize browser.request profile guard paths

* feat(llm-task): add thinking override

Co-authored-by: Xaden Ryan <[email protected]>

* feat(ui): utilities, theming, and i18n updates (slice 2/3 of dashboard-v2) (#41500)

* feat(ui): add utilities, theming, and i18n updates (slice 2 of dashboard-v2)

UI utilities and theming improvements extracted from dashboard-v2-structure:

Icons & formatting:
- icons.ts: expanded icon set for new dashboard views
- format.ts: date/number formatting helpers
- tool-labels.ts: human-readable tool name mappings

Theming:
- theme.ts: enhanced theme resolution and system theme support
- theme-transition.ts: simplified transition logic
- storage.ts: theme parsing improvements for settings persistence

Navigation & types:
- navigation.ts: extended tab definitions for dashboard-v2
- app-view-state.ts: expanded view state management
- types.ts: new type definitions (HealthSummary, ModelCatalogEntry, etc.)

Components:
- components/dashboard-header.ts: reusable header component

i18n:
- Updated en, pt-BR, zh-CN, zh-TW locales with new dashboard strings

All changes are additive or backwards-compatible. Build passes.
Part of #36853.

* ui: fix theme and locale review regressions

* ui: fix review follow-ups for dashboard tabs

* ui: allowlist locale password placeholder false positives

* ui: fix theme mode and locale regressions

* Vincentkoc code/pr 41500 route fix (#43829)

* UI: keep unfinished settings routes hidden

* UI: normalize light theme data token

* UI: restore cron type compatibility

---------

Co-authored-by: Vincent Koc <[email protected]>

* Docs: clarify llm-task thinking presets

* Refactor: trim duplicate gateway/onboarding helpers and dead utils (#43871)

* Gateway: share input provenance schema

* Onboarding: dedupe top-level channel patching

* Utils: remove unused path helpers

* Protocol: refresh generated gateway models

* feat(zalouser): add markdown-to-Zalo text style parsing (#43324)

* feat(zalouser): add markdown-to-Zalo text style parsing

Parse markdown formatting (bold, italic, strikethrough, headings, lists,
code blocks, blockquotes, custom color/style tags) into Zalo native
TextStyle ranges so outbound messages render with rich formatting.

- Add text-styles.ts with parseZalouserTextStyles() converter
- Wire markdown mode into send pipeline (sendMessageZalouser)
- Export TextStyle enum and Style type from zca-client
- Add textMode/textStyles to ZaloSendOptions
- Pass textStyles through sendZaloTextMessage to zca-js API
- Enable textMode:"markdown" in outbound sendText/sendMedia and monitor
- Add comprehensive tests for parsing, send, and channel integration

* fix(zalouser): harden markdown text parsing

* fix(zalouser): mirror zca-js text style types

* fix(zalouser): support tilde fenced code blocks

* fix(zalouser): handle quoted fenced code blocks

* fix(zalouser): preserve literal quote lines in code fences

* fix(zalouser): support indented quoted fences

* fix(zalouser): preserve quoted markdown blocks

* fix(zalouser): rechunk formatted messages

* fix(zalouser): preserve markdown structure across chunks

* fix(zalouser): honor chunk limits and CRLF fences

* fix(failover): add missing network errno patterns to text-based timeout classifier (#42830)

Merged via squash.

Prepared head SHA: 91761487e8825c0fd6582a762d04bba04f726a85
Co-authored-by: jnMetaCode <[email protected]>
Co-authored-by: altaywtf <[email protected]>
Reviewed-by: @altaywtf

* fix: preserve sandbox write payload stdin (#43876)

Merged via squash.

Prepared head SHA: a10fd4b21c78ec57411e6a4f387f16b1441660c2
Co-authored-by: glitch418x <[email protected]>
Co-authored-by: altaywtf <[email protected]>
Reviewed-by: @altaywtf

* fix: stop main-session UI replies inheriting channel routes

* fix: stop main-session UI replies inheriting channel routes (#43918)

* fix: add zalouser outbound chunker

* fix(doctor): canonicalize gateway service entrypoint paths (#43882)

Merged via squash.

Prepared head SHA: 9f530d2a86b5d30822d4419db7cffae6a560ddca
Co-authored-by: ngutman <[email protected]>
Co-authored-by: ngutman <[email protected]>
Reviewed-by: @ngutman

* docs: add Kubernetes install guide, setup script, and manifests (#34492)

* add docs and manifests for k8s install

Signed-off-by: sallyom <[email protected]>

* changelog

Signed-off-by: sallyom <[email protected]>

---------

Signed-off-by: sallyom <[email protected]>

* feat(mattermost): add replyToMode support (off | first | all) (#29587)

Merged via squash.

Prepared head SHA: 4a67791f53b1109959082738429471b7a5bc93b8
Co-authored-by: teconomix <[email protected]>
Co-authored-by: mukhtharcm <[email protected]>
Reviewed-by: @mukhtharcm

* fix(telegram): allow fallback models in /model validation (#40105)

Merged via squash.

Prepared head SHA: de07585e03cba06897d50c1d79fbe09d326c6ac9
Co-authored-by: avirweb <[email protected]>
Co-authored-by: velvet-shark <[email protected]>
Reviewed-by: @velvet-shark

* fix: carry observed overflow token counts into compaction (#40357)

Merged via squash.

Prepared head SHA: b99eed4329bda45083cdedc2386c2c4041c034be
Co-authored-by: rabsef-bicrym <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman

* fix(status): resolve context window by provider-qualified key, prefer max on bare-id collision, solve #35976 (#36389)

Merged via squash.

Prepared head SHA: f8cf752c59708fb388fd200276115277e8b217d6
Co-authored-by: haoruilee <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman

* Agents: adapt pi-ai oauth and payload hooks

* build: default to Node 24 and keep Node 22 compat

* build: raise Node 22 compatibility floor to 22.16

* build: align Node 22 guidance with 22.16 minimum

* ci: harden pnpm sticky cache on PRs

* ci: restore PR pnpm cache fallback

* ci: tighten cache docs and node22 gate

* fix(mattermost): pass mediaLocalRoots through reply delivery (#44021)

Merged via squash.

Prepared head SHA: 856f11f129f7d6a4bc8f23e8d13c786ecb871f52
Co-authored-by: LyleLiu666 <[email protected]>
Co-authored-by: mukhtharcm <[email protected]>
Reviewed-by: @mukhtharcm

* Hardening: require LINE webhook signatures (#44090)

* LINE: require webhook signatures in express handler

* LINE: require webhook signatures in node handler

* LINE: update express signature tests

* LINE: update node signature tests

* Changelog: note LINE webhook hardening

* LINE: validate signatures before parsing webhook bodies

* LINE: reject missing signatures before body reads

* Security: preserve Feishu reaction chat type (#44088)

* Feishu: preserve looked-up chat type

* Feishu: fail closed on ambiguous reaction chats

* Feishu: cover reaction chat type fallback

* Changelog: note Feishu reaction hardening

* Feishu: fail closed without resolved chat type

* Feishu: normalize reaction chat type at runtime

* Hardening: tighten preauth WebSocket handshake limits (#44089)

* Gateway: tighten preauth handshake limits

* Changelog: note WebSocket preauth hardening

* Gateway: count preauth frame bytes accurately

* Gateway: cap WebSocket payloads before auth

* Hardening: normalize Unicode command obfuscation detection (#44091)

* Exec: cover unicode obfuscation cases

* Exec: normalize unicode obfuscation detection

* Changelog: note exec detection hardening

* Exec: strip unicode tag character obfuscation

* Exec: harden unicode suppression and length guards

* Exec: require path boundaries for safe URL suppressions

* Security: require Feishu webhook encrypt key (#44087)

* Feishu: require webhook encrypt key in schema

* Feishu: cover encrypt key webhook validation

* Feishu: enforce encrypt key at startup

* Feishu: add webhook forgery regression test

* Feishu: collect encrypt key during onboarding

* Docs: require Feishu webhook encrypt key

* Changelog: note Feishu webhook hardening

* Docs: clarify Feishu encrypt key screenshot

* Feishu: treat webhook encrypt key as secret input

* Feishu: resolve encrypt key only in webhook mode

* Subagents: stop retrying external completion timeouts (#41235) (#43847)

* Changelog: add subagent announce timeout note

* Tests: cover subagent completion timeout no-retry

* Subagents: stop retrying external completion timeouts

* Config: update subagent announce timeout default docs

* Tests: use fake timers for subagent timeout retry guard

* docs: sync Feishu secretref credential matrix

## Summary

- Problem: `src/secrets/target-registry.test.ts` fails on latest `main` because the runtime registry includes Feishu `encryptKey` paths that the docs matrix and surface reference omit.
- Why it matters: the docs/runtime sync guard currently blocks prep and merge work for unrelated PRs, including `#25558`.
- What changed: regenerated the secretref credential matrix and updated the surface reference to include both Feishu `encryptKey` paths.
- What did NOT change (scope boundary): no runtime registry behavior, config semantics, or channel handling changed.

## Change Type (select all)

- [x] Bug fix
- [ ] Feature
- [ ] Refactor
- [x] Docs
- [ ] Security hardening
- [ ] Chore/infra

## Scope (select all touched areas)

- [ ] Gateway / orchestration
- [ ] Skills / tool execution
- [ ] Auth / tokens
- [ ] Memory / storage
- [x] Integrations
- [ ] API / contracts
- [ ] UI / DX
- [ ] CI/CD / infra

## Linked Issue/PR

- Closes #
- Related #25558

## User-visible / Behavior Changes

None.

## Security Impact (required)

- New permissions/capabilities? `No`
- Secrets/tokens handling changed? `No`
- New/changed network calls? `No`
- Command/tool execution surface changed? `No`
- Data access scope changed? `No`
- If any `Yes`, explain risk + mitigation:

## Repro + Verification

### Environment

- OS: macOS
- Runtime/container: Node.js repo checkout
- Model/provider: N/A
- Integration/channel (if any): Feishu docs/runtime registry sync
- Relevant config (redacted): none

### Steps

1. Check out latest `main` before this change.
2. Run `./node_modules/.bin/vitest run --config vitest.unit.config.ts src/secrets/target-registry.test.ts`.
3. Apply this docs-only sync change and rerun the same command.

### Expected

- The target registry stays in sync with the generated docs matrix and the test passes.

### Actual

- Before this change, the test failed because `channels.feishu.encryptKey` and `channels.feishu.accounts.*.encryptKey` were missing from the docs artifacts.

## Evidence

Attach at least one:

- [x] Failing test/log before + passing after
- [ ] Trace/log snippets
- [ ] Screenshot/recording
- [ ] Perf numbers (if relevant)

## Human Verification (required)

What you personally verified (not just CI), and how:

- Verified scenarios: confirmed the failure on plain latest `main`, applied only these docs entries in a clean bootstrapped worktree, and reran `./node_modules/.bin/vitest run --config vitest.unit.config.ts src/secrets/target-registry.test.ts` to green.
- Edge cases checked: verified both top-level Feishu `encryptKey` and account-scoped `encryptKey` paths are present in the matrix and surface reference.
- What you did **not** verify: full repo test suite and CI beyond the targeted regression.

## Review Conversations

- [x] I replied to or resolved every bot review conversation I addressed in this PR.
- [x] I left unresolved only the conversations that still need reviewer or maintainer judgment.

If a bot review conversation is addressed by this PR, resolve that conversation yourself. Do not leave bot review conversation cleanup for maintainers.

## Compatibility / Migration

- Backward compatible? `Yes`
- Config/env changes? `No`
- Migration needed? `No`
- If yes, exact upgrade steps:

## Failure Recovery (if this breaks)

- How to disable/revert this change quickly: revert this commit.
- Files/config to restore: `docs/reference/secretref-user-supplied-credentials-matrix.json` and `docs/reference/secretref-credential-surface.md`
- Known bad symptoms reviewers should watch for: the target-registry docs sync test failing again for missing Feishu `encryptKey` entries.

## Risks and Mitigations

- Risk: the markdown surface reference could drift from the generated matrix again in a later credential-shape change.
  - Mitigation: `src/secrets/target-registry.test.ts` continues to guard docs/runtime sync.

* Compaction Runner: emit transcript updates post-compact (#25558)

Merged via squash.

Prepared head SHA: 8a858436ed31805124a9d096bd93ab90e5423672
Co-authored-by: rodrigouroz <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman

* Plugins: fix env-aware root resolution and caching (#44046)

Merged via squash.

Prepared head SHA: 6e8852a188b0eaa4d6cf0bb71829023e0e0ed82b
Co-authored-by: gumadeiras <[email protected]>
Co-authored-by: gumadeiras <[email protected]>
Reviewed-by: @gumadeiras

* feat: add sessions_yield tool for cooperative turn-ending (#36537)

Merged via squash.

Prepared head SHA: 75d9204c863792226389a4d33eeb40c4e842528d
Co-authored-by: jriff <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman

* Moonshot: respect explicit baseUrl for CN endpoint so platform.moonshot.cn keys authenticate (#33637) (#33696)

* Moonshot: respect explicit baseUrl for CN endpoint so platform.moonshot.cn keys authenticate (#33637)

* Moonshot: address review - remove dead constant, import canonical URLs (#33696)

* Plugins: require explicit trust for workspace-discovered plugins (#44174)

* Plugins: disable implicit workspace plugin auto-load

* Tests: cover workspace plugin trust gating

* Changelog: note workspace plugin trust hardening

* Plugins: keep workspace trust gate ahead of memory slot defaults

* Tests: cover workspace memory-slot trust bypass

* fix(providers): respect user-configured baseUrl for kimi-coding (#36647)

* fix(providers): respect user-configured baseUrl for kimi-coding

The kimi-coding provider was built exclusively from
`buildKimiCodingProvider()` defaults, ignoring any user-specified
`baseUrl` or other overrides in `openclaw.json` providers config.
This caused 404 errors when users configured a custom endpoint.

Now merge `explicitProviders["kimi-coding"]` on top of defaults,
matching the pattern used by ollama/vllm. User's `baseUrl`, `api`,
and `models` take precedence; env/profile API key still wins.

Fixes #36353

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* Tests: use Kimi implicit provider harness

---------

Co-authored-by: Claude Opus 4.6 <[email protected]>
Co-authored-by: Vincent Koc <[email protected]>

* feat(push): add iOS APNs relay gateway (#43369)

* feat(push): add ios apns relay gateway

* fix(shared): avoid oslog string concatenation

# Conflicts:
#	apps/shared/OpenClawKit/Sources/OpenClawKit/GatewayChannel.swift

* fix(push): harden relay validation and invalidation

* fix(push): persist app attest state before relay registration

* fix(push): harden relay invalidation and url handling

* feat(push): use scoped relay send grants

* feat(push): configure ios relay through gateway config

* feat(push): bind relay registration to gateway identity

* fix(push): tighten ios relay trust flow

* fix(push): bound APNs registration fields (#43369) (thanks @ngutman)

* fix(ios): add live activity horizontal padding

* Zalo: rate limit invalid webhook secret guesses before auth (#44173)

* Zalo: rate limit webhook guesses before auth

* Tests: cover pre-auth Zalo webhook rate limiting

* Changelog: note Zalo pre-auth rate limiting

* Zalo: preserve auth-before-content-type response ordering

* Tests: cover auth-before-content-type webhook ordering

* Zalo: split auth and unauth webhook rate-limit buckets

* Tests: cover auth bucket split for Zalo webhook rate limiting

* Zalo: use trusted proxy client IP for webhook rate limiting

* Tests: cover trusted proxy client IP rate limiting for Zalo

* docs: clarify gateway HTTP trust boundary

* Gateway: harden custom session-store discovery (#44176)

Merged via squash.

Prepared head SHA: 52ebbf5188b47386f2a78ac4715993bc082e911b
Co-authored-by: gumadeiras <[email protected]>
Co-authored-by: gumadeiras <[email protected]>
Reviewed-by: @gumadeiras

* fix(ci): harden docker builds and unblock config docs

* fix: make node-llama-cpp optional for npm installs

* fix: canonicalize openrouter native model keys

* runner: infer names from malformed toolCallId variants (#34485)

Merged via squash.

Prepared head SHA: 150ea1a7c90de3232f72498d851719c4dfb00b43
Co-authored-by: yuweuii <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman

* Gateway: preserve discovered session store paths

* docs: reorder unreleased changelog

* fix(node-host): harden ambiguous approval operand binding (#44247)

* fix(node-host): harden approval operand binding

* test(node-host): cover approval parser hardening

* docs(changelog): note approval hardening GHSA cluster

* Update CHANGELOG.md

* fix(node-host): remove dead approval parser entries

* test(node-host): cover bunx approval wrapper

* fix(node-host): unwrap pnpm shim exec forms

* test(node-host): cover pnpm shim wrappers

* Kimi Coding: set default subscription user agent (#44248)

* Providers: set default Kimi coding user agent

* Tests: cover Kimi coding header overrides

* Changelog: note Kimi coding user agent

* Tests: satisfy Kimi provider fixture type

* Update CHANGELOG.md

* Providers: preserve Kimi headers through models merge

* feat(ui): dashboard-v2 views refactor (slice 3/3 of dashboard-v2) (#41503)

* feat(ui): add chat infrastructure modules (slice 1 of dashboard-v2)

New self-contained chat modules extracted from dashboard-v2-structure:

- chat/slash-commands.ts: slash command definitions and completions
- chat/slash-command-executor.ts: execute slash commands via gateway RPC
- chat/slash-command-executor.node.test.ts: test coverage
- chat/speech.ts: speech-to-text (STT) support
- chat/input-history.ts: per-session input history navigation
- chat/pinned-messages.ts: pinned message management
- chat/deleted-messages.ts: deleted message tracking
- chat/export.ts: shared exportChatMarkdown helper
- chat-export.ts: re-export shim for backwards compat

Gateway fix:
- Restore usage/cost stripping in chat.history sanitization
- Add test coverage for sanitization behavior

These modules are additive and tree-shaken — no existing code
imports them yet. They will be wired in subsequent slices.

* feat(ui): add utilities, theming, and i18n updates (slice 2 of dashboard-v2)

UI utilities and theming improvements extracted from dashboard-v2-structure:

Icons & formatting:
- icons.ts: expanded icon set for new dashboard views
- format.ts: date/number formatting helpers
- tool-labels.ts: human-readable tool name mappings

Theming:
- theme.ts: enhanced theme resolution and system theme support
- theme-transition.ts: simplified transition logic
- storage.ts: theme parsing improvements for settings persistence

Navigation & types:
- navigation.ts: extended tab definitions for dashboard-v2
- app-view-state.ts: expanded view state management
- types.ts: new type definitions (HealthSummary, ModelCatalogEntry, etc.)

Components:
- components/dashboard-header.ts: reusable header component

i18n:
- Updated en, pt-BR, zh-CN, zh-TW locales with new dashboard strings

All changes are additive or backwards-compatible. Build passes.
Part of #36853.

* feat(ui): dashboard-v2 views refactor (slice 3 of dashboard-v2)

Complete views refactor from dashboard-v2-structure, building on
slice 1 (chat infra, #41497) and slice 2 (utilities/theming, #41500).

Core app wiring:
- app.ts: updated host component with new state properties
- app-render.ts: refactored render pipeline for new dashboard layout
- app-render.helpers.ts: extracted render helpers
- app-settings.ts: theme listener lifecycle fix, cron runs on tab load
- app-gateway.ts: refactored chat event handling
- app-chat.ts: slash command integration

New views:
- views/command-palette.ts: command palette (Cmd+K)
- views/login-gate.ts: authentication gate
- views/bottom-tabs.ts: mobile tab navigation
- views/overview-*.ts: modular overview dashboard (cards, attention,
  event log, hints, log tail, quick actions)
- views/agents-panels-overview.ts: agent overview panel

Refactored views:
- views/chat.ts: major refactor with STT, slash commands, search,
  export, pinned messages, input history
- views/config.ts: restructured config management
- views/agents.ts: streamlined agent management
- views/overview.ts: modular composition from sub-views
- views/sessions.ts: enhanced session management

Controllers:
- controllers/health.ts: new health check controller
- controllers/models.ts: new model catalog controller
- controllers/agents.ts: tools catalog improvements
- controllers/config.ts: config form enhancements

Tests & infrastructure:
- Updated test helpers, browser tests, node tests
- vite.config.ts: build configuration updates
- markdown.ts: rendering improvements

Build passes ✅ | 44 files | +6,626/-1,499
Part of #36853. Depends on #41497 and #41500.

* UI: fix chat review follow-ups

* fix(ui): repair chat clear and attachment regressions

* fix(ui): address remaining chat review comments

* fix(ui): address review follow-ups

* fix(ui): replay queued local slash commands

* fix(ui): repair control-ui type drift

* fix(ui): restore control UI styling

* feat(ui): enhance layout and styling for config and topbar components

- Updated grid layout for the config layout to allow full-width usage.
- Introduced new styles for top tabs and search components to improve usability.
- Added theme mode toggle styling for better visual integration.
- Implemented tests for layout and theme mode components to ensure proper rendering and functionality.

* feat(ui): add config file opening functionality and enhance styles

- Implemented a new handler to open the configuration file using the default application based on the operating system.
- Updated various CSS styles across components for improved visual consistency and usability, including adjustments to padding, margins, and font sizes.
- Introduced new styles for the data table and sidebar components to enhance layout and interaction.
- Added tests for the collapsed navigation rail to ensure proper functionality in different states.

* refactor(ui): update CSS styles for improved layout and consistency

- Simplified font-body declaration in base.css for cleaner code.
- Adjusted transition properties in components.css for better readability.
- Added new .workspace-link class in components.css for enhanced link styling.
- Changed config layout from grid to flex in config.css for better responsiveness.
- Updated related tests to reflect layout changes in config-layout.browser.test.ts.

* feat(ui): enhance theme handling and loading states in chat interface

- Updated CSS to support new theme mode attributes for better styling consistency across light and dark themes.
- Introduced loading skeletons in the chat view to improve user experience during data fetching.
- Refactored command palette to manage focus more effectively, enhancing accessibility.
- Added tests for the appearance theme picker and loading states to ensure proper rendering and functionality.

* refactor(ui): streamline ephemeral state management in chat and config views

- Introduced interfaces for ephemeral state in chat and config views to encapsulate related variables.
- Refactored state management to utilize a single object for better organization and maintainability.
- Removed legacy state variables and updated related functions to reference the new state structure.
- Enhanced readability and consistency across the codebase by standardizing state handling.

* chore: remove test files to reduce PR scope

* fix(ui): resolve type errors in debug props and chat search

* refactor(ui): remove stream mode functionality across various components

- Eliminated stream mode related translations and CSS styles to streamline the user interface.
- Updated multiple components to remove references to stream mode, enhancing code clarity and maintainability.
- Adjusted rendering logic in views to ensure consistent behavior without stream mode.
- Improved overall readability by cleaning up unused variables and props.

* fix(ui): add msg-meta CSS and fix rebase type errors

* fix(ui): add CSS for chat footer action buttons (TTS, delete) and msg-meta

* feat(ui): add delete confirmation with remember-decision checkbox

* fix(ui): delete confirmation with remember, attention icon sizing

* fix(ui): open delete confirm popover to the left (not clipped)

* fix(ui): show all nav items in collapsed sidebar, remove gap

* fix(ui): address P1/P2 review feedback — session queue clear, kill scope, palette guard, stop button

* fix(ui): address Greptile re-review — kill scope, queue flush, idle handling, parallel fetch

- SECURITY: /kill <target> now enforces session tree scope (not just /kill all)
- /kill reports idle sessions gracefully instead of throwing
- Queue continues draining after local slash commands
- /model fetches sessions.list + models.list in parallel (perf fix)

* fix(ui): style update banner close button — SVG stroke + sizing

* fix(ui): update layout styles for sidebar and content spacing

* UI: restore colon slash command parsing

* UI: restore slash command session queries

* Refactor thinking resolution: Introduce resolveThinkingDefaultForModel function and update model-selection to utilize it. Add tests for new functionality in thinking.test.ts.

* fix(ui): constrain welcome state logo size, add missing CSS for new session view

---------

Co-authored-by: Vincent Koc <[email protected]>

* fix: restore protocol outputs and stabilize Windows path CI (#44266)

* fix(ci): restore protocol outputs and stabilize Windows path test

Regenerate the Swift protocol models so protocol:check stops failing on main.
Align the session target test helper with the sync production realpath behavior so Windows does not compare runneradmin and RUNNER~1 spellings for the same file.

Regeneration-Prompt: |
  Investigate the failing checks from merged PR #34485 and confirm whether they still affect current main before changing code. Keep the fix tight: do not alter runtime behavior beyond what is required to clear the reproduced CI regressions. Commit the generated Swift protocol outputs for the PushTestResult transport field because protocol:check was failing from stale generated files on main. Also fix the Windows-only session target test by making its helper use the same synchronous realpath behavior as production discovery, so path spelling differences like runneradmin versus RUNNER~1 do not cause a false assertion failure.

* fix(ci): align session target realpath behavior on Windows

Use native realpath for sync session target discovery so it matches the async path on Windows, and update the session target test helper to assert against the same canonical path form.

Regeneration-Prompt: |
  After opening the follow-up PR for the CI regressions from merged PR #34485, inspect the new failing Windows shard instead of assuming the first fix covered every case. Keep scope limited to the session target path mismatch exposed by CI. Fix the inconsistency at the source by making sync session target discovery use the same native realpath canonicalization as the async discovery path on Windows, then update the test helper to match that shared behavior and verify the touched file with targeted tests and file-scoped lint/format checks.

* test: make merge config fixtures satisfy provider type

After rebasing the PR onto current origin/main, the merge helper test fixtures no longer satisfied ProviderConfig because the anthropic provider examples were missing required provider and model fields. Add a shared fully-typed model fixture and explicit anthropic baseUrl values so the test keeps full type coverage under tsgo.

Regeneration-Prompt: |
  Rebase the PR branch for #44266 onto the current origin/main because the failing CI error only reproduced on the merge ref. Re-run the type-check path and inspect src/agents/models-config.merge.test.ts at the exact compiler lines instead of weakening types globally. Keep the fix test-only: make the anthropic ProviderConfig fixtures structurally valid by supplying the required baseUrl and full model definition fields, and keep the shared fixture typed so tsgo accepts it without unknown casts.

* fix: align Windows session store test expectations

* chore(changelog): update CHANGELOG.md to include new features in dashboard-v2, highlighting the refreshed gateway dashboard with modular views and enhanced chat tools (#41503)

* Ollama/Kimi: apply Moonshot payload compatibility (#44274)

* Runner: extend Moonshot payload compat to Ollama Kimi

* Changelog: note Ollama Kimi tool routing

* Tests: cover Ollama Kimi payload compat

* Runner: narrow Ollama Kimi payload compat

* onboard(minimax): flatten auth to 4 direct choices, unify CN/Global under single provider (#44284)

Replace the multi-step MiniMax onboarding wizard with 4 flat options:
- MiniMax Global — OAuth (minimax.io)
- MiniMax Global — API Key (minimax.io)
- MiniMax CN — OAuth (minimaxi.com)
- MiniMax CN — API Key (minimaxi.com)

Storage changes:
- Unify CN and Global under provider "minimax" (baseUrl distinguishes region)
- Profiles: minimax:global / minimax:cn (both regions can coexist)
- Model ref: minimax/MiniMax-M2.5 (no more minimax-cn/ prefix)
- Remove LM Studio local mode and Lightning/Highspeed choice

Backward compatibility:
- Keep minimax-cn in provider-env-vars for existing configs
- Accept minimax-cn as legacy tokenProvider in CI pipelines
- Error with migration hint for removed auth choices in non-interactive mode
- Warn when dual-profile overwrites shared provider baseUrl

Made-with: Cursor

* Gateway/ws: clear unbound scopes for shared-token auth (#44306)

* Gateway/ws: clear unbound shared-auth scopes

* Gateway/auth: cover shared-token scope stripping

* Changelog: add shared-token scope stripping entry

* Gateway/ws: preserve allowed control-ui scopes

* Gateway/auth: assert control-ui admin scopes survive allowed device-less auth

* Gateway/auth: cover shared-password scope stripping

* fix: format CSS files for oxfmt (#44313)

* Commands: require owner for /config and /debug (#44305)

* Commands: add non-owner gate helper

* Commands: enforce owner-only config and debug

* Commands/test: cover owner-only config and debug

* Changelog: add owner-only config debug entry

* Commands/test: split config owner gating section

* Commands: redact sender ids in verbose command logs

* Commands: preserve internal read-only config access

* Commands/test: keep operator.write config show coverage non-owner

* fix(runtime): duplicate messages, share singleton state across bundled chunks (#43683)

* Tests: add fresh module import helper

* Process: share command queue runtime state

* Agents: share embedded run runtime state

* Reply: share followup queue runtime state

* Reply: share followup drain callback state

* Reply: share queued message dedupe state

* Reply: share inbound dedupe state

* Tests: cover shared command queue runtime state

* Tests: cover shared embedded run runtime state

* Tests: cover shared followup queue runtime state

* Tests: cover shared inbound dedupe state

* Tests: cover shared Slack thread participation state

* Slack: share sent thread participation state

* Tests: document fresh import helper

* Telegram: share draft stream runtime state

* Tests: cover shared Telegram draft stream state

* Telegram: share sent message cache state

* Tests: cover shared Telegram sent message cache

* Telegram: share thread binding runtime state

* Tests: cover shared Telegram thread binding state

* Tests: avoid duplicate shared queue reset

* refactor(runtime): centralize global singleton access

* refactor(runtime): preserve undefined global singleton values

* test(runtime): cover undefined global singleton values

---------

Co-authored-by: Nimrod Gutman <[email protected]>

* fix(sandbox): restore spawned workspace handoff (#44307)

* feat(context-engine): plumb sessionKey into all ContextEngine methods (#44157)

Merged via squash.

Prepared head SHA: 0b341f6f4ce487055d8bc0c0d335c42577941592
Co-authored-by: jalehman <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman

* docs: codify American English spelling convention (#44159)

* fix(failover): classify z.ai network_error stop reason as retryable timeout (#43884)

Merged via squash.

Prepared head SHA: 9660f6cd5bcb8d073fc5575bbba2bf3792b29de3
Co-authored-by: hougangdev <[email protected]>
Co-authored-by: altaywtf <[email protected]>
Reviewed-by: @altaywtf

* fix(failover): classify ZenMux quota-refresh 402 as rate_limit (#43917)

Merged via squash.

Prepared head SHA: 1d58a36a774d06b1493971e8f14f9abc806be6b0
Co-authored-by: bwjoke <[email protected]>
Co-authored-by: altaywtf <[email protected]>
Reviewed-by: @altaywtf

* Compaction Runner: wire post-compaction memory sync (#25561)

Merged via squash.

Prepared head SHA: 6d2bc02cc16429a19b041acd353c08dd2404335f
Co-authored-by: rodrigouroz <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman

* fix(gateway): honor trusted proxy hook auth rate limits

* fix(security): audit unrestricted hook agent routing

* refactor(gateway): move request client ip resolution to net

* refactor(gateway): cache hook proxy config in runtime state

* refactor(security): reuse hook agent routing normalization

* refactor(test): share hook request handler fixtures

* fix(failover): classify HTTP 422 as format and OpenRouter credits as billing (#43823)

Merged via squash.

Prepared head SHA: 4f48e977fe06c5662753d3900fe94f1835cc2dce
Co-authored-by: jnMetaCode <[email protected]>
Co-authored-by: altaywtf <[email protected]>
Reviewed-by: @altaywtf

* fix: skip cache-ttl append after compaction to prevent double compaction (#28548)

Merged via squash.

Prepared head SHA: a4114a52bcff6ed4057cc54d3c629bd723f3d420
Co-authored-by: MoerAI <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman

* fix: switch pairing setup codes to bootstrap tokens

* feat: modularize provider plugin architecture

* docs: explain plugin architecture

* fix(ci): restore generated protocol swift outputs (#44411)

Regenerate the Swift protocol models so PushTestResult keeps the transport field required by the current gateway schema, and update protocol:check to diff both generated Swift destinations because the generator writes both files.

Regeneration-Prompt: |
  Investigate the protocol CI failure on current origin/main rather than assuming the earlier fix still held. Confirm whether the generated Swift outputs drifted from the TypeScript gateway schema, identify whether the regression was reintroduced by a later commit, and keep the patch minimal: restore the generated Swift outputs from the existing schema and tighten the protocol check so it verifies every Swift file the generator writes.

* fix(security): harden nodes owner-only tool gating

* refactor: share openai-compatible local discovery

* refactor: remove legacy provider apply shims

* refactor: split non-interactive auth choice providers

* refactor: split simple api-key auth providers

* test: cover provider plugin boundaries

* refactor: unify gateway connect auth selection

* refactor: trim bootstrap token metadata

* refactor: extract websocket handshake auth helpers

* refactor: clarify pairing setup auth labels

* deps: bump openclaw to 2026.3.11

Raise internal OpenClaw constraints to 2026.3.11 and regenerate pnpm lockfile to remove the vulnerable 2026.3.8 resolution.

* fix: harden windows npm runtime path

* feat: add --no-test flag to prepare-gates

Allows skipping the full test suite during prepare phase.
Testing is deferred to the dedicated Test phase in the pipeline.

* fix(node-host): fail closed on ruby approval preload flags

* feat: add fast mode toggle for OpenAI models

* Revert "feat: add --no-test flag to prepare-gates"

This reverts commit ee6bdb3bab26f2796943c6cac03d8f62a5664937.

* feat: add Anthropic fast mode support

* fix: harden windows native updates

* feat: add windows update package spec override

* fix(hooks): dedupe repeated agent deliveries by idempotency key (#44438)

* Hooks: add hook idempotency key resolution

* Hooks: dedupe repeated agent deliveries by idempotency key

* Tests: cover hook idempotency dedupe

* Changelog: note hook idempotency dedupe

* Hooks: cap hook idempotency key length

* Gateway: hash hook replay cache keys

* Tests: cover hook replay key hardening

* fix(hooks): fail closed on unreadable loader paths (#44437)

* Hooks: fail closed on unreadable loader paths

* Changelog: note hooks loader hardening

* Tests: cover sanitized hook loader logs

* Hooks: use realpath containment for legacy loaders

* Hooks: sanitize unreadable workspace log path

* fix(models): keep codex spark codex-only

* test(live): add codex instructions to spark probe

* fix(security): strip Mongolian selectors in exec obfuscation detector

* Gateway: preserve trusted-proxy browser scopes

* build: update deps and fix vitest 4 regressions

* build: sync bundled plugin versions

* refactor: add non-interactive provider plugin setup

* refactor: validate provider plugin metadata

* fix(zalouser): require ids for group allowlist auth

* fix: avoid ineffective dynamic imports

* fix(mac): adopt canonical session key and add reset triggers (#10898)

Add shared native chat handling for /new, /reset, and /clear.

This also aligns main session key handling in the shared chat UI and includes follow-up test and CI fixes needed to keep the branch mergeable.

Co-authored-by: Nachx639 <[email protected]>
Co-authored-by: Luke <[email protected]>

* test: resolve rebase conflicts in gateway coverage

* chore: prepare 2026.3.12 release

* refactor(zalouser): reuse shared name matching helper

* feat(zalouser): audit mutable group allowlists

* fix(routing): require ids for slack and msteams allowlists

* fix: quiet Telegram command overflow retry logs

* fix(memory): fail closed for Windows qmd wrappers

* docs(ollama): update onboarding flow

Co-Authored-By: Jeffrey Morgan <[email protected]>
(cherry picked from commit e8ca2ff4e522f2d971801a537b3c4fdfecde0711)

* fix: align Ollama onboarding docs before landing (#43473) (thanks @BruceMacD)

(cherry picked from commit 19fa274343a102ca85c7679ec28c5a3503a99f55)

* docs: reorder latest release changelog

* test: stabilize hooks loader log assertion on Windows

* fix: import oauth types from the oauth entrypoint

* refactor(agents): replace console.warn with SubsystemLogger in compaction-safeguard.ts (#9974)

Merged via squash.

Prepared head SHA: 35dcc5ba354ad7f058d796846bda9d1f8a416e04
Co-authored-by: dinakars777 <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman

* fix: clarify windows onboarding gateway health

* fix(gateway): strip unbound scopes for shared-auth connects

* test(commands): align slash-command config persistence coverage

* fix: use build-stage image for docker live tests

* test: harden plugin env-scoped fixtures

* fix(cron): avoid false legacy payload kind migrations

* fix(cron): compare raw value not trimmed in normalizePayloadKind

* fix: stop false cron payload-kind warnings in doctor (#44012) (thanks @shuicici)

* fix(memory): stop forcing Windows qmd cmd shims

* test: harden plugin fixture permissions on macos

* fix(feishu): fail closed on webhook signature checks

* test(qmd): make windows cli fixtures explicit

* test(gateway): avoid hoisted reply mock tdz

* fix: fall back to a startup entry for windows gateway install

* Slack: support Block Kit payloads in agent replies (#44592)

* Slack: route reply blocks through outbound adapter

* Slack: cover Block Kit outbound payloads

* Changelog: add Slack Block Kit agent reply entry

* fix: enable fast mode for isolated cron runs

* fix(acp): preserve final assistant message snapshot before end_turn (#44597)

Process messageData via handleDeltaEvent for both delta and final states
before resolving the turn, so ACP clients no longer drop the last visible
assistant text when the gateway sends the final message body on the
terminal chat event.

Closes #15377
Based on #17615

Co-authored-by: PJ Eby <[email protected]>

* fix: narrow Slack outbound blocks opt type

* changelog: move ACP final-snapshot entry to active 2026.3.12 section

* fix(ci): restore full gate

* UI: fix control chat logo fallback

* test(qmd): make windows cli fixtures explicit

* UI: fix mounted avatar meta fallback

* fix(ui): resolve control chat avatar fallback

* fix(ui): harden avatar fallback regressions

* test(ui): add jsdom runtime for vitest dom suites

* fix(ui): restore native web /status

* feat: show status reaction during context compaction (#35474)

Merged via squash.

Prepared head SHA: 145a7b7c4e1939718c41a300899ae813bd9c511b
Co-authored-by: Cypherm <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman

* fix(plugins): normalize bundled provider ids

* test(proxy): make env proxy tests windows-safe

* chore: update appcast for 2026.3.12 release

* fix(compaction): use full-session token count for post-compaction sanity check (#28347)

Merged via squash.

Prepared head SHA: cf4eab1c51e6b8890e23c2d7172313c40cd2fe04
Co-authored-by: efe-arv <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman

* chore: bump version to 2026.3.13

* test(utils): await temp dir cleanup in async tests

* fix(telegram): thread media transport policy into SSRF (#44639)

* fix(telegram): preserve media download transport policy

* refactor(telegram): thread media transport policy

* fix(telegram): sync fallback media policy

* fix: note telegram media transport fix (#44639)

* fix: handle Discord gateway metadata fetch failures (#44397)

Merged via squash.

Prepared head SHA: edd17c0effe4f90887ac94ce549f44a69fe19eb2
Co-authored-by: jalehman <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman

* fix: harden windows gateway fallback launch

* test: fix windows startup fallback mock typing

* docs: move post-release changelog entries to Unreleased (#44691)

4 entries were added to the 2026.3.12 section after the v2026.3.12
tag was cut. Move them to ## Unreleased where they belong.

Verified: 2026.3.12 section now matches the 74 entries present at
the v2026.3.12 release tag (28d64c48e).

* fix(android): clip CommandBlock accent bar to rounded container bounds

* fix: recover outbound plugins from the active registry

* test: stabilize sanitize session history smoke checks

* feat(android): redesign onboarding flow UI

- Welcome: replace bullet list with icon+subtitle feature cards
- Gateway: simplify to single instruction line, collapse advanced by default, remove verbose developer text
- Permissions: group into System/Media/Personal Data sections, rewrite subtitles to plain English, style "Not granted" with warning color
- Review: replace plain text fields with icon cards matching Welcome style, add colored status cards for connect/pairing states
- Remove redundant "FIRST RUN" label, "Step X of 4" text, and StepRailWrap dividers

* fix(session): preserve `lastAccountId` and `lastThreadId` on session reset

* fix: add gateway session reset routing coverage (#44773) (thanks @Lanfei)

* Updated default model from openai-codex/gpt-5.3-codex to openai-codex/gpt-5.4 in tests. (#44367)

Merged via squash.

Prepared head SHA: c372ba691b9964dc986c3a4880a7413ab8fb23f7
Co-authored-by: jrrcdev <[email protected]>
Co-authored-by: dvrshil <[email protected]>
Reviewed-by: @dvrshil

* fix: address delivery dedupe review follow-ups (#44666)

Merged via squash.

Prepared head SHA: 8e6d254cc4781df66ee02b683c4ad72b5a633502
Co-authored-by: frankekn <[email protected]>
Co-authored-by: frankekn <[email protected]>
Reviewed-by: @frankekn

* CLI: align xhigh thinking help text (#44819)

Merged via squash.

Prepared head SHA: ff1f12717692d7745b34c5aef7c1dde3c6a4500d
Co-authored-by: frankekn <[email protected]>
Co-authored-by: frankekn <[email protected]>
Reviewed-by: @frankekn

* docs: fix changelog credit for xhigh help (#44874)

* fix(sre:PLA-815): drop accidental node_modules from sync branch

* fix(agents): drop Anthropic thinking blocks on replay (#44843)

* agents: drop Anthropic thinking blocks on replay

* fix: extend anthropic replay sanitization openclaw#44429 thanks @jmcte

* fix: extend anthropic replay sanitization openclaw#44843 thanks @jmcte

* test: add bedrock replay sanitization coverage openclaw#44843

* test: cover anthropic provider drop-thinking hints openclaw#44843

---------

Co-authored-by: johnmteneyckjr <[email protected]>

* docs: fix session key :dm: → :direct (#26506)

* ci(sre:PLA-815): remove secrets job from ci workflow

* feat(android): redesign Connect tab with unified status cards

Merge endpoint and status into a single grouped card with icons.
Split connect/disconnect into context-aware buttons.

* feat(android): add speaker label and status pill to Voice tab

Add text label under speaker toggle, balance layout with matching
spacer column, and wrap status text in a colored pill.

* feat(android): compact chat composer layout

Remove MESSAGE label and divider, let text field auto-size instead
of fixed 92dp, and merge Detail/Attach into the bottom action row.

* feat(android): soften chat role labels and deduplicate session header

Rename role labels to You/OpenClaw/System, update streaming label to
OpenClaw · Live, and remove the redundant SESSION row + Connected pill
since the top bar and chip row already convey both.

* feat(android): consolidate Settings…
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling maintainer Maintainer-authored PR size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]:fix(ollama): kimi-k2.5:cloud tool routing fails - extend fix to all Kimi variants

2 participants