Skip to content

feat: show status reaction during context compaction#35474

Merged
jalehman merged 6 commits intoopenclaw:mainfrom
Cypherm:feat/compaction-status-reaction
Mar 13, 2026
Merged

feat: show status reaction during context compaction#35474
jalehman merged 6 commits intoopenclaw:mainfrom
Cypherm:feat/compaction-status-reaction

Conversation

@Cypherm
Copy link
Copy Markdown
Contributor

@Cypherm Cypherm commented Mar 5, 2026

Closes #35545

Summary

When context auto-compaction runs on Telegram/Discord, the bot appears frozen for 10-30s with no feedback. This PR adds a (writing) status reaction during compaction so users know the bot is still working.

  • Adds compacting state to StatusReactionController with emoji (debounced, same pattern as setThinking)
  • Adds onCompactionStart/onCompactionEnd callbacks to GetReplyOptions
  • Wires existing onAgentEvent compaction events (stream: "compaction", phase: "start"/"end") to the status reaction system
  • On compaction end, resumes thinking reaction so the status flow continues naturally
  • Applies to both Telegram and Discord channels
  • Telegram variants: ["✍", "🤔", "🤯"] (all in Telegram's supported reaction set)

Files changed

File Change
src/channels/status-reactions.ts Add compacting emoji type + setCompacting() method
src/telegram/status-reaction-variants.ts Add compacting emoji variants
src/auto-reply/types.ts Add onCompactionStart/End callbacks
src/auto-reply/reply/agent-runner-execution.ts Wire compaction events to callbacks
src/telegram/bot-message-dispatch.ts Pass setCompacting via callbacks
src/discord/monitor/message-handler.process.ts Same wiring for Discord

Test plan

  • pnpm build passes
  • pnpm tsgo passes (type check)
  • pnpm check passes (lint/format)
  • Existing status reaction tests pass (51/51)
  • Manual test on Telegram: send long conversation to trigger compaction, observe reaction
  • Manual test: verify reaction switches back to 🤔/👍 after compaction completes
  • Edge case: compaction with status reactions disabled — no crash

🤖 Generated with Claude Code

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 5, 2026

Greptile Summary

This PR adds a status reaction during context auto-compaction so users see visual feedback instead of the bot appearing frozen for 10-30 seconds on Telegram and Discord.

The implementation is clean and consistent across all layers:

  • A new compacting emoji type and setCompacting() method are added to StatusReactionController, following the exact same debounced scheduleEmoji pattern as setThinking
  • onCompactionStart/onCompactionEnd callbacks are threaded through GetReplyOptions and wired to the existing evt.stream === "compaction" event handler in the agent runner
  • Both Telegram and Discord correctly restore the thinking reaction on compaction end so the status flow continues naturally
  • All three Telegram variants (, 🤔, 🤯) are confirmed present in TELEGRAM_SUPPORTED_REACTION_EMOJIS
  • The compacting emoji is correctly added to the knownEmojis set, ensuring Discord's removeReaction cleanup covers it

No critical issues found. The PR is well-scoped and preserves all existing behavior.

Confidence Score: 5/5

  • This PR is safe to merge — it adds purely additive UX feedback with no changes to core agent logic.
  • All changes follow existing patterns precisely. The new setCompacting() method is debounced (same as setThinking), abort-signal guards are applied consistently per platform conventions (Telegram uses ternary null-guards, Discord uses explicit abort checks), the emoji and both fallback variants are in Telegram's supported set, and the knownEmojis set is updated so Discord cleanup works correctly. The autoCompactionCompleted flag logic is unchanged. No new state machines or error paths are introduced.
  • No files require special attention.

Last reviewed commit: 97c50d8

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: 97c50d8b6b

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +779 to +783
onCompactionEnd: async () => {
if (isProcessAborted(abortSignal)) {
return;
}
await statusReactions.setThinking();
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Cancel queued compacting state when compaction ends

If compaction finishes before the debounce window, setCompacting() can still be queued when this callback runs. Calling setThinking() here does not reliably cancel that queued update when the current reaction is already thinking, because scheduleEmoji returns early on the dedupe path and keeps the existing debounce timer in createStatusReactionController (src/channels/status-reactions.ts). In that case, is applied after compaction has ended, so users see an incorrect status reaction for the rest of the run.

Useful? React with 👍 / 👎.

@openclaw-barnacle openclaw-barnacle bot added channel: discord Channel integration: discord channel: telegram Channel integration: telegram size: S labels Mar 7, 2026
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: 3e79516d06

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +319 to +321
function cancelPending(): void {
clearDebounceTimer();
pendingEmoji = "";
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Cancel enqueued compacting reaction when compaction ends

cancelPending() only clears the debounce timer and pendingEmoji, so it cannot cancel a compacting update that has already been enqueued by scheduleEmoji. In Discord/Telegram runs where reaction API calls are slow (so chainPromise is backed up), the compaction timer can fire, enqueue , then onCompactionEnd calls cancelPending() + setThinking() while currentEmoji is still 🤔 and dedupes; the queued then applies afterward and leaves an incorrect compaction reaction until another state transition occurs.

Useful? React with 👍 / 👎.

@Cypherm
Copy link
Copy Markdown
Contributor Author

Cypherm commented Mar 7, 2026

Addressed the race condition flagged by Codex — added cancelPending() to StatusReactionController that clears the debounce timer before transitioning back to thinking state in onCompactionEnd. This prevents a queued ✍ from firing after compaction has already ended.

@Cypherm Cypherm force-pushed the feat/compaction-status-reaction branch 2 times, most recently from 6a927a2 to 55f2f9e Compare March 12, 2026 09:50
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: 55f2f9e80b

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

error: normalizeEmoji(overrides?.error) ?? DEFAULT_EMOJIS.error,
stallSoft: normalizeEmoji(overrides?.stallSoft) ?? DEFAULT_EMOJIS.stallSoft,
stallHard: normalizeEmoji(overrides?.stallHard) ?? DEFAULT_EMOJIS.stallHard,
compacting: normalizeEmoji(overrides?.compacting) ?? DEFAULT_EMOJIS.compacting,
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Allow configuring compacting status reaction emoji

This adds a new compacting reaction override path (overrides?.compacting) but the config contract still omits that key (src/config/types.messages.ts:52-61) and the strict zod schema for messages.statusReactions.emojis rejects unknown fields (src/config/zod-schema.session.ts:163-173). In practice, users who try to set messages.statusReactions.emojis.compacting will fail config validation, so this new status cannot be customized like the other reaction states.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 465ca0b — added compacting to both the config type (StatusReactionsEmojiConfig) and the zod schema.

@jalehman jalehman force-pushed the feat/compaction-status-reaction branch from 465ca0b to 6e81063 Compare March 13, 2026 03:24
jalehman added a commit to Cypherm/openclaw that referenced this pull request Mar 13, 2026
Regeneration-Prompt: |
  Prepare openclaw#35474 for merge after review identified two nits and a required changelog entry. Keep the runtime behavior intact. Update the Telegram config help text so the new messages.statusReactions.emojis.compacting key is documented, add focused regression coverage proving the compacting state is surfaced and the cancelPending race is handled in the shared status-reaction controller plus the Discord and Telegram dispatch paths, and append the required user-facing changelog entry for the current release block with (openclaw#35474) thanks @Cypherm. When touching tests, preserve the existing harness structure and make isolated Vitest runs stable under hoisted mocks.
jalehman added a commit to Cypherm/openclaw that referenced this pull request Mar 13, 2026
Regeneration-Prompt: |
  Prepare openclaw#35474 for merge after review identified two nits and a required changelog entry. Keep the runtime behavior intact. Update the Telegram config help text so the new messages.statusReactions.emojis.compacting key is documented, add focused regression coverage proving the compacting state is surfaced and the cancelPending race is handled in the shared status-reaction controller plus the Discord and Telegram dispatch paths, and append the required user-facing changelog entry for the current release block with (openclaw#35474) thanks @Cypherm. When touching tests, preserve the existing harness structure and make isolated Vitest runs stable under hoisted mocks.
@jalehman jalehman force-pushed the feat/compaction-status-reaction branch from 6e81063 to 59c7326 Compare March 13, 2026 03:35
jalehman added a commit to Cypherm/openclaw that referenced this pull request Mar 13, 2026
Regeneration-Prompt: |
  After rebasing the prepare branch for openclaw#35474 onto newer origin/main, pnpm test started failing in src/daemon/schtasks.test.ts because readScheduledTaskCommand now returns sourcePath from the newer fallback-to-startup-entry work. Keep runtime code unchanged and update only the stale expectations so the tests assert the returned sourcePath via resolveTaskScriptPath(env) alongside the existing command parsing fields.
@openclaw-barnacle openclaw-barnacle bot added the gateway Gateway runtime label Mar 13, 2026
jalehman added a commit to Cypherm/openclaw that referenced this pull request Mar 13, 2026
Regeneration-Prompt: |
  Prepare openclaw#35474 for merge after review identified two nits and a required changelog entry. Keep the runtime behavior intact. Update the Telegram config help text so the new messages.statusReactions.emojis.compacting key is documented, add focused regression coverage proving the compacting state is surfaced and the cancelPending race is handled in the shared status-reaction controller plus the Discord and Telegram dispatch paths, and append the required user-facing changelog entry for the current release block with (openclaw#35474) thanks @Cypherm. When touching tests, preserve the existing harness structure and make isolated Vitest runs stable under hoisted mocks.
@jalehman jalehman force-pushed the feat/compaction-status-reaction branch from 59c7326 to 7cd48cf Compare March 13, 2026 03:38
@openclaw-barnacle openclaw-barnacle bot removed the gateway Gateway runtime label Mar 13, 2026
jalehman added a commit to Cypherm/openclaw that referenced this pull request Mar 13, 2026
Regeneration-Prompt: |
  Prepare openclaw#35474 for merge after review identified two nits and a required changelog entry. Keep the runtime behavior intact. Update the Telegram config help text so the new messages.statusReactions.emojis.compacting key is documented, add focused regression coverage proving the compacting state is surfaced and the cancelPending race is handled in the shared status-reaction controller plus the Discord and Telegram dispatch paths, and append the required user-facing changelog entry for the current release block with (openclaw#35474) thanks @Cypherm. When touching tests, preserve the existing harness structure and make isolated Vitest runs stable under hoisted mocks.
@jalehman jalehman force-pushed the feat/compaction-status-reaction branch from 7cd48cf to 3200782 Compare March 13, 2026 03:41
jalehman added a commit to Cypherm/openclaw that referenced this pull request Mar 13, 2026
Regeneration-Prompt: |
  Prepare openclaw#35474 for merge after review identified two nits and a required changelog entry. Keep the runtime behavior intact. Update the Telegram config help text so the new messages.statusReactions.emojis.compacting key is documented, add focused regression coverage proving the compacting state is surfaced and the cancelPending race is handled in the shared status-reaction controller plus the Discord and Telegram dispatch paths, and append the required user-facing changelog entry for the current release block with (openclaw#35474) thanks @Cypherm. When touching tests, preserve the existing harness structure and make isolated Vitest runs stable under hoisted mocks.
@jalehman jalehman force-pushed the feat/compaction-status-reaction branch from 3200782 to d4c751f Compare March 13, 2026 03:44
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: d4c751f2ac

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +319 to +322
function cancelPending(): void {
clearDebounceTimer();
pendingEmoji = "";
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Cancel queued compacting update before resuming thinking

cancelPending() only clears the debounce timer and pendingEmoji, so it cannot stop a compacting transition that has already been queued into chainPromise by the debounce callback. In slow Discord/Telegram reaction paths (or any backlog in setReaction/removeReaction), onCompactionEnd calls cancelPending() and then setThinking(), but setThinking() deduplicates when currentEmoji is still thinking; the previously queued compacting update then runs afterward and shows after compaction has ended.

Useful? React with 👍 / 👎.

jalehman added a commit to Cypherm/openclaw that referenced this pull request Mar 13, 2026
Regeneration-Prompt: |
  Prepare openclaw#35474 for merge after review identified two nits and a required changelog entry. Keep the runtime behavior intact. Update the Telegram config help text so the new messages.statusReactions.emojis.compacting key is documented, add focused regression coverage proving the compacting state is surfaced and the cancelPending race is handled in the shared status-reaction controller plus the Discord and Telegram dispatch paths, and append the required user-facing changelog entry for the current release block with (openclaw#35474) thanks @Cypherm. When touching tests, preserve the existing harness structure and make isolated Vitest runs stable under hoisted mocks.
jalehman added a commit to Cypherm/openclaw that referenced this pull request Mar 13, 2026
Regeneration-Prompt: |
  After refreshing dependencies in the PR openclaw#35474 prep worktree, the full test suite started failing in src/infra/net/proxy-fetch.test.ts even though the file passed in isolation once the env state was reset correctly. The helper gives lowercase proxy env vars precedence over uppercase ones, even when the lowercase values are explicitly empty, so the uppercase-only test cases must delete the lowercase vars instead of blanking them. Keep runtime code unchanged and tighten only the two affected tests so they model the intended env precedence accurately.
jalehman added a commit to Cypherm/openclaw that referenced this pull request Mar 13, 2026
Regeneration-Prompt: |
  While preparing openclaw#35474 against a moving origin/main, pnpm check started failing in ui/src/ui/views/agents-utils.test.ts because AgentIdentityResult now requires agentId and name in addition to avatar. Keep runtime code unchanged and update only the test fixture in the avatar-resolution case so it satisfies the full AgentIdentityResult shape.
@jalehman jalehman force-pushed the feat/compaction-status-reaction branch from d4c751f to 97ac1cf Compare March 13, 2026 03:55
@openclaw-barnacle openclaw-barnacle bot added the app: web-ui App: web-ui label Mar 13, 2026
Cypherm and others added 6 commits March 12, 2026 20:56
When context auto-compaction runs, the bot appears frozen for 10-30s
with no feedback. This adds a ✍ (writing) status reaction during
compaction so users know the bot is still working.

- Add `compacting` state to StatusReactionController with ✍ emoji
- Add `onCompactionStart`/`onCompactionEnd` callbacks to GetReplyOptions
- Wire existing compaction events to the status reaction system
- Apply to both Telegram and Discord channels

Co-Authored-By: Claude Opus 4.6 <[email protected]>
When compaction finishes before the debounce window (700ms), the queued
setCompacting() emoji could fire after compaction ended, showing ✍
instead of 🤔. This adds cancelPending() to StatusReactionController
and calls it in onCompactionEnd before setThinking() to prevent the
race condition.

Addresses review feedback from chatgpt-codex-connector.
Allow users to customize the compacting status reaction emoji via
messages.statusReactions.emojis.compacting in config.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Regeneration-Prompt: |
  Prepare openclaw#35474 for merge after review identified two nits and a required changelog entry. Keep the runtime behavior intact. Update the Telegram config help text so the new messages.statusReactions.emojis.compacting key is documented, add focused regression coverage proving the compacting state is surfaced and the cancelPending race is handled in the shared status-reaction controller plus the Discord and Telegram dispatch paths, and append the required user-facing changelog entry for the current release block with (openclaw#35474) thanks @Cypherm. When touching tests, preserve the existing harness structure and make isolated Vitest runs stable under hoisted mocks.
Regeneration-Prompt: |
  After refreshing dependencies in the PR openclaw#35474 prep worktree, the full test suite started failing in src/infra/net/proxy-fetch.test.ts even though the file passed in isolation once the env state was reset correctly. The helper gives lowercase proxy env vars precedence over uppercase ones, even when the lowercase values are explicitly empty, so the uppercase-only test cases must delete the lowercase vars instead of blanking them. Keep runtime code unchanged and tighten only the two affected tests so they model the intended env precedence accurately.
Regeneration-Prompt: |
  While preparing openclaw#35474 against a moving origin/main, pnpm check started failing in ui/src/ui/views/agents-utils.test.ts because AgentIdentityResult now requires agentId and name in addition to avatar. Keep runtime code unchanged and update only the test fixture in the avatar-resolution case so it satisfies the full AgentIdentityResult shape.
@jalehman jalehman force-pushed the feat/compaction-status-reaction branch from 97ac1cf to 145a7b7 Compare March 13, 2026 03:58
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: 145a7b7c4e

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +78 to +79
delete process.env.https_proxy;
delete process.env.http_proxy;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Avoid deleting unstubbed proxy env vars in tests

These tests directly run delete process.env.https_proxy/http_proxy, but cleanup relies on vi.unstubAllEnvs(), which only restores keys that were set via vi.stubEnv. On CI hosts that start with lowercase proxy vars, this permanently mutates process env for the rest of the worker and can make later tests run under the wrong network settings. Stub these keys to empty strings (or snapshot/restore explicitly) instead of deleting them.

Useful? React with 👍 / 👎.

@jalehman jalehman merged commit 61d219c into openclaw:main Mar 13, 2026
27 of 29 checks passed
frankekn pushed a commit to jmcte/openclaw that referenced this pull request Mar 13, 2026
Merged via squash.

Prepared head SHA: 145a7b7
Co-authored-by: Cypherm <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman
dvrshil pushed a commit to JosepLee/openclaw that referenced this pull request Mar 14, 2026
Merged via squash.

Prepared head SHA: 145a7b7
Co-authored-by: Cypherm <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman
sbezludny pushed a commit to sbezludny/openclaw that referenced this pull request Mar 14, 2026
Merged via squash.

Prepared head SHA: 145a7b7
Co-authored-by: Cypherm <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman
Interstellar-code pushed a commit to Interstellar-code/operator1 that referenced this pull request Mar 16, 2026
Merged via squash.

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

(cherry picked from commit 61d219c)
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…
sbezludny pushed a commit to sbezludny/openclaw that referenced this pull request Mar 27, 2026
Merged via squash.

Prepared head SHA: 145a7b7
Co-authored-by: Cypherm <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app: web-ui App: web-ui channel: discord Channel integration: discord channel: telegram Channel integration: telegram size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

UX: no feedback during context auto-compaction (10-30s freeze)

2 participants