Skip to content

fix(gateway): suppress announce/reply skip chat leakage#51739

Merged
jalehman merged 2 commits intoopenclaw:mainfrom
Pinghuachiu:fix/announce-skip-final-chat-suppression
Apr 8, 2026
Merged

fix(gateway): suppress announce/reply skip chat leakage#51739
jalehman merged 2 commits intoopenclaw:mainfrom
Pinghuachiu:fix/announce-skip-final-chat-suppression

Conversation

@Pinghuachiu
Copy link
Copy Markdown
Contributor

Summary

  • suppress exact ANNOUNCE_SKIP / REPLY_SKIP control replies in gateway chat delta emission
  • suppress the same control replies in gateway chat final emission
  • add regression coverage for both delta and final chat paths

Why

sessions_send / announce flows can legitimately return ANNOUNCE_SKIP or REPLY_SKIP as internal control replies. Those tokens should stay internal, but they can leak into user-facing chat surfaces unless the gateway suppresses them the same way it already suppresses NO_REPLY.

This is in the same bug family as #45084 and related leakage issues.

Testing

  • pnpm exec vitest run --config vitest.gateway.config.ts src/gateway/server-chat.agent-events.test.ts src/gateway/server.sessions-send.test.ts

Copilot AI review requested due to automatic review settings March 21, 2026 16:32
@openclaw-barnacle openclaw-barnacle Bot added gateway Gateway runtime size: S labels Mar 21, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Mar 21, 2026

Greptile Summary

This PR fixes a leakage bug where internal control tokens ANNOUNCE_SKIP and REPLY_SKIP — returned by sessions_send / announce flows — could surface in user-facing chat delta and final emissions. It follows the same suppression pattern already in place for NO_REPLY by introducing a small isSuppressedControlReplyText helper that centralises all three checks, and wires it into the two relevant gateway code paths.

Key changes:

  • server-chat.ts: New isSuppressedControlReplyText helper extends exact-token suppression from NO_REPLY to also cover ANNOUNCE_SKIP and REPLY_SKIP. Both the delta-emission guard and the final-state resolver now use this helper instead of the narrower isSilentReplyText call.
  • server-chat.agent-events.test.ts: Existing NO_REPLY-only tests are parameterised into it.each tables covering all three suppressed tokens for both the delta and final chat paths — good regression coverage.
  • The token string literals "ANNOUNCE_SKIP" / "REPLY_SKIP" are hardcoded in server-chat.ts rather than imported from src/agents/tools/sessions-send-helpers.ts where they already exist as module-private constants. This is a minor maintainability concern; exporting and sharing those constants would prevent future drift.

Confidence Score: 5/5

  • Safe to merge; the fix is narrow, well-tested, and follows existing suppression patterns exactly.
  • The change is a small, targeted bug-fix with clear tests that mirror the existing NO_REPLY coverage. Both affected code paths are updated consistently, and there are no logic errors or regressions introduced. The only remaining note is a style suggestion about exporting the token constants rather than duplicating string literals — it does not affect correctness.
  • No files require special attention.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/gateway/server-chat.ts
Line: 82-83

Comment:
**Magic strings duplicate unexported constants**

`"ANNOUNCE_SKIP"` and `"REPLY_SKIP"` already exist as module-private constants in `src/agents/tools/sessions-send-helpers.ts`. Because they're not exported, the gateway can't import them — so the same string values are now defined in two separate places. If the canonical token strings ever change, this suppression logic would silently fall out of sync.

Consider exporting those constants from `sessions-send-helpers.ts` (or consolidating them alongside `SILENT_REPLY_TOKEN` in `src/auto-reply/tokens.ts`) so this file can import them directly rather than repeating the literals.

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

Last reviewed commit: "fix(gateway): suppre..."

Comment thread src/gateway/server-chat.ts Outdated
Comment on lines +82 to +83
normalized === "ANNOUNCE_SKIP" ||
normalized === "REPLY_SKIP"
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.

P2 Magic strings duplicate unexported constants

"ANNOUNCE_SKIP" and "REPLY_SKIP" already exist as module-private constants in src/agents/tools/sessions-send-helpers.ts. Because they're not exported, the gateway can't import them — so the same string values are now defined in two separate places. If the canonical token strings ever change, this suppression logic would silently fall out of sync.

Consider exporting those constants from sessions-send-helpers.ts (or consolidating them alongside SILENT_REPLY_TOKEN in src/auto-reply/tokens.ts) so this file can import them directly rather than repeating the literals.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/gateway/server-chat.ts
Line: 82-83

Comment:
**Magic strings duplicate unexported constants**

`"ANNOUNCE_SKIP"` and `"REPLY_SKIP"` already exist as module-private constants in `src/agents/tools/sessions-send-helpers.ts`. Because they're not exported, the gateway can't import them — so the same string values are now defined in two separate places. If the canonical token strings ever change, this suppression logic would silently fall out of sync.

Consider exporting those constants from `sessions-send-helpers.ts` (or consolidating them alongside `SILENT_REPLY_TOKEN` in `src/auto-reply/tokens.ts`) so this file can import them directly rather than repeating the literals.

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

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: bea42b2109

ℹ️ 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".

Comment thread src/gateway/server-chat.ts Outdated
Comment on lines 371 to 374
if (isSuppressedControlReplyText(mergedText)) {
return;
}
if (isSilentReplyLeadFragment(mergedText)) {
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 Suppress streamed prefixes for skip control replies

In emitChatDelta, ANNOUNCE_SKIP and REPLY_SKIP are suppressed only on exact match, while prefix suppression still applies only to NO_REPLY. When a provider streams incremental snapshots (for example AANNOUNCE_ANNOUNCE_SKIP), those intermediate fragments are emitted to chat before the final exact token is suppressed in emitChatFinal, so control text still leaks and can leave a truncated artifact in the UI. Please add lead-fragment suppression for these new skip tokens before broadcasting deltas.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR prevents internal control replies (ANNOUNCE_SKIP / REPLY_SKIP, alongside existing NO_REPLY) from leaking into user-facing Gateway chat streaming (“delta”) and final chat emissions, and expands the Gateway chat event handler tests to cover these regressions.

Changes:

  • Add a centralized suppression predicate for control-reply text in the Gateway chat handler.
  • Apply suppression consistently to both chat delta streaming and chat final emission paths.
  • Expand agent-event handler tests to validate suppression for all three control tokens.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
src/gateway/server-chat.ts Introduces isSuppressedControlReplyText and uses it to suppress control replies for delta + final chat emission.
src/gateway/server-chat.agent-events.test.ts Parameterizes tests to cover NO_REPLY, ANNOUNCE_SKIP, and REPLY_SKIP suppression in delta and final paths.

Comment thread src/gateway/server-chat.ts Outdated
Comment on lines +78 to +85
function isSuppressedControlReplyText(text: string): boolean {
const normalized = text.trim();
return (
isSilentReplyText(normalized, SILENT_REPLY_TOKEN) ||
normalized === "ANNOUNCE_SKIP" ||
normalized === "REPLY_SKIP"
);
}
Copy link

Copilot AI Mar 21, 2026

Choose a reason for hiding this comment

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

The gateway suppression list hard-codes "ANNOUNCE_SKIP" / "REPLY_SKIP". These tokens already have canonical constants + match helpers (isAnnounceSkip/isReplySkip) in src/agents/tools/sessions-send-helpers.ts; duplicating the strings here risks future drift if the tokens change. Consider reusing the shared helpers/exports (or moving the token constants to a small shared module) so all suppression logic stays consistent.

Copilot uses AI. Check for mistakes.
Comment on lines +205 to +227
it.each(["NO_REPLY", "ANNOUNCE_SKIP", "REPLY_SKIP"])(
"does not include %s text in chat final message",
(replyText) => {
const { broadcast, nodeSendToSession, chatRunState, handler, nowSpy } = createHarness({
now: 2_000,
});
chatRunState.registry.add("run-2", { sessionKey: "session-2", clientRunId: "client-2" });

const payload = expectSingleFinalChatPayload(broadcast) as { message?: unknown };
expect(payload.message).toBeUndefined();
expect(sessionChatCalls(nodeSendToSession)).toHaveLength(1);
nowSpy?.mockRestore();
});
handler({
runId: "run-2",
seq: 1,
stream: "assistant",
ts: Date.now(),
data: { text: replyText },
});
emitLifecycleEnd(handler, "run-2");

const payload = expectSingleFinalChatPayload(broadcast) as { message?: unknown };
expect(payload.message).toBeUndefined();
expect(sessionChatCalls(nodeSendToSession)).toHaveLength(1);
nowSpy?.mockRestore();
},
);
Copy link

Copilot AI Mar 21, 2026

Choose a reason for hiding this comment

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

The final-message suppression test only covers exact tokens without surrounding whitespace, but the implementation trims (and other parts of the codebase already treat whitespace-padded ANNOUNCE_SKIP as equivalent). Consider adding whitespace-padded variants (e.g. " ANNOUNCE_SKIP ") to this parameterized test to lock in the intended behavior for the final chat emission path as well.

Copilot uses AI. Check for mistakes.
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: 156f1cb613

ℹ️ 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".

Comment on lines +12 to +14
[SILENT_REPLY_TOKEN]: 2,
ANNOUNCE_SKIP: 3,
REPLY_SKIP: 3,
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 Remove minimum-prefix guard for control-token fragments

emitChatDelta now depends on isSuppressedControlReplyLeadFragment, but the MIN_BARE_PREFIX_LENGTH_BY_TOKEN thresholds mean short streamed prefixes are still emitted ("N" for NO_REPLY, "A"/"AN" for ANNOUNCE_SKIP, "R"/"RE" for REPLY_SKIP). In providers that stream incremental snapshots character-by-character, those early fragments are broadcast before the final exact token is suppressed, so control text can still leak into chat UI. This is also a regression for NO_REPLY, which previously suppressed from the first prefix character.

Useful? React with 👍 / 👎.

@jalehman jalehman force-pushed the fix/announce-skip-final-chat-suppression branch from 156f1cb to 3dfecdd Compare April 8, 2026 22:07
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: 3dfecdd712

ℹ️ 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".

Comment on lines +749 to +753
const res = sanitizeChatHistoryMessage(message, maxChars);
changed ||= res.changed;
// Drop assistant commentary-only entries and exact control replies, but
// keep mixed assistant entries that still carry non-text content.
if (shouldDropAssistantHistoryMessage(message)) {
if (shouldDropAssistantHistoryMessage(res.message)) {
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 Drop control replies before truncating chat history

sanitizeChatHistoryMessages now sanitizes/truncates each message before applying shouldDropAssistantHistoryMessage, so exact control tokens can be mutated before the drop check. For example, with a small chat.history maxChars, NO_REPLY becomes truncated text and no longer matches isSuppressedControlReplyText, causing internal control replies to leak back in history results instead of being filtered.

Useful? React with 👍 / 👎.

Comment on lines +33 to +34
const normalized = text.trim();
return SUPPRESSED_CONTROL_REPLY_TOKENS.some((token) => isSilentReplyText(normalized, token));
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 Match skip control tokens with exact case only

isSuppressedControlReplyText uses isSilentReplyText, which performs case-insensitive matching; this means plain assistant outputs like announce_skip/reply_skip are suppressed in chat/history even though skip handling in sessions-send is exact-case (=== ANNOUNCE_SKIP_TOKEN / === REPLY_SKIP_TOKEN). That mismatch can hide legitimate assistant content and make gateway display behavior diverge from tool control-token semantics.

Useful? React with 👍 / 👎.

Pinghuachiu and others added 2 commits April 8, 2026 15:17
Regeneration-Prompt: |
  Prepare PR 51739 after review found two remaining user-facing leaks in
  gateway chat handling. Keep the original exact-token suppression for
  ANNOUNCE_SKIP and REPLY_SKIP, but also suppress streamed lead fragments
  of those internal control replies so partial deltas do not leak before
  the exact token is assembled. Preserve the pre-existing NO_REPLY behavior,
  including the case where a short reply like "No" is hidden during the
  delta stream but still appears in the final message.

  Reuse the same exact control-token check in chat history sanitization so
  assistant-only ANNOUNCE_SKIP and REPLY_SKIP transcript entries are removed
  on reload while mixed-content or text-precedence cases continue to work.
  Add regression coverage in the gateway agent-events tests for streamed
  prefixes and in the gateway chat-history tests for the new exact tokens,
  then add the required Unreleased changelog entry for the fix.
@jalehman jalehman force-pushed the fix/announce-skip-final-chat-suppression branch from 3dfecdd to 2f53f3b Compare April 8, 2026 22:18
@jalehman jalehman merged commit 68630a9 into openclaw:main Apr 8, 2026
8 checks passed
@jalehman
Copy link
Copy Markdown
Contributor

jalehman commented Apr 8, 2026

Merged via squash.

Thanks @Pinghuachiu!

greidron added a commit to greidron/openclaw that referenced this pull request Apr 10, 2026
* release: mirror bundled channel deps at root (openclaw#63065)

Merged via squash.

Prepared head SHA: ac26799
Co-authored-by: scoootscooob <167050519+scoootscooob@users.noreply.github.com>
Co-authored-by: scoootscooob <167050519+scoootscooob@users.noreply.github.com>
Reviewed-by: @scoootscooob

* fix(test): keep warn log capture under openclaw temp dir

* revert: undo background alive review findings fix

* feat: add qa character vibes eval

* test: stabilize plugin boundary invariants

* test: isolate agent gateway cli command mocks

* test: skip duplicate package boundary wrapper in ci

* test: fix postpublish verifier sidecar handling

* test: keep status tests off live usage probes

* auto-reply: type status auth overrides

* plugins: read contract inventory from manifests

* test: inline cli metadata channel fixture

* ci: skip duplicate full extension shard

* test: isolate discord directory live token env

* test: keep followup runner memory mock complete

* ci: split parallel full suite into leaf shards

* test: guard loader fixtures against broad sdk imports

* test: keep bundled channel entry smokes descriptor-only

* ci: reduce full suite test parallelism

* test: avoid bundled test api smokes in matrix and telegram

* test: keep discord and irc entry smokes descriptor-only

* test: keep web provider artifact coverage manifest-only

* test: keep provider policy artifact coverage narrow

* test: keep web provider artifact test in boundary

* test: keep status message tests off auth auto-detection

* status: avoid plugin lookup for direct channel model overrides

* channels: fast-path direct model override matches

* test: restore manifest-only web provider coverage

* fix: allow blank TLS manual port default (openclaw#63134) (thanks @Tyler-RNG)

* make port optional for TLS manual connections

* fix: restrict manual blank-port fallback to tls

* fix: allow blank TLS manual port default (openclaw#63134) (thanks @Tyler-RNG)

---------

Co-authored-by: Ayaan Zaidi <hi@obviy.us>

* test: fix full suite CI test isolation

* fix: align LLM idle timeout policy

* test: exercise models json file mode without provider discovery

* test: keep shared dm policy contract off channel facades

* test: keep web provider artifact test in boundary

* test: keep kilocode provider tests on plugin-owned helpers

* ci: restore sequential full suite tests

* test: keep public artifact coverage on cheap boundaries

* test: keep openclaw tools registration tests on a fast shell

* test: keep bundled metadata sidecar scan inventory-only

* docs(inferrs): fix Gemma model id from gg-hf-gg to google (openclaw#62586)

* fix: harden bundled plugin dependency release checks

* ci: isolate full suite leaf shards

* test: keep openclaw tools registration policy pure

* fix: support Codex CLI QA auth

* feat: add QA character eval reports

* docs: document QA character eval workflow

* refactor: dedupe media generation tool helpers

* refactor: dedupe internal helper glue

* refactor: dedupe shared helper branches

* refactor: dedupe browser navigation guard tests

* refactor: dedupe config and subagent tests

* refactor: dedupe test helpers and script warning filter

* refactor: dedupe plugin test harnesses

* refactor: dedupe media runtime test mocks

* refactor: dedupe plugin metadata test helpers

* refactor: dedupe firecrawl and directive helpers

* refactor: dedupe exec defaults tests

* refactor: dedupe approval runtime tests

* refactor: dedupe matrix exec approval tests

* refactor: dedupe telegram exec approval tests

* refactor: dedupe doctor codex oauth tests

* refactor: dedupe agent command test fixtures

* refactor: dedupe embedding provider test fixtures

* refactor: share html entity tool call decoding

* fix: keep minimax provider mocks package-local

* test: keep pdf and update-plan registration tests pure

* test: keep model reasoning override coverage on merge helpers

* fix: default OpenAI reasoning effort to high

* test: keep kimi implicit provider tests on provider catalog

* fix(build): prune stale bundled plugin node_modules

* fix(build): address bundled plugin prune review

* fix(build): honor postinstall disable flag

* test: keep chutes implicit provider tests on provider catalog

* fix(plugin-sdk): export channel plugin base

* docs: reorder changelog entries

* test: keep bundled web-search owner checks on public artifacts

* fix(build): keep tsdown prune best-effort

* test: trust gateway exec fixture node path

* fix: keep runtime task test harness behind task seams

* test: explain gateway exec fixture trust

* Reply: surface OAuth reauth failures (openclaw#63217)

Merged via squash.

Prepared head SHA: 68b7ffd
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky

* test: make character eval scenario natural

* feat: add character eval model options

* test: keep pi fs workspace tests on fs tool factories

* test: keep media runtime tests on same-directory provider mocks

* fix(android): auto-resume pairing approval

* fix(android): prefer bootstrap auth on qr pairing

* fix(android): reset auth on new setup codes

* fix(android): tighten pairing retry behavior

* fix(android): prefer stored device auth after pairing

* fix: restore android qr pairing flow (openclaw#63199)

* fix(auto-reply): strip leading NO_REPLY tokens to prevent silent-reply leak (openclaw#63068)

* fix(auto-reply): strip leading NO_REPLY tokens to prevent silent-reply leak

* fix(auto-reply): preserve substantive NO_REPLY leading text

* fix(agents): preserve ACP silent-prefix cumulative deltas

* fix(auto-reply): harden silent-token streaming paths

* fix(auto-reply): normalize glued silent tokens consistently

---------

Co-authored-by: termtek <termtek@ubuntu.tail2b72cd.ts.net>

* fix(gateway): clear auto-fallback model override on session reset (openclaw#63155)

* fix(gateway): clear auto-fallback model override on session reset

When `persistFallbackCandidateSelection()` writes a fallback provider
override with `authProfileOverrideSource: "auto"`, the override was
incorrectly preserved across `/reset` and `/new` commands. This caused
sessions to keep using the fallback provider even after the user changed
the agent config primary provider, because the session store override
takes precedence over the config default.

Now the override fields (`providerOverride`, `modelOverride`,
`authProfileOverride`, `authProfileOverrideSource`,
`authProfileOverrideCompactionCount`) are only carried forward when
`authProfileOverrideSource === "user"` (i.e. explicit `/model` command).
System-driven overrides are dropped on reset so the session picks up the
current config default.

Introduced in cb0a752 ("fix: preserve reset session behavior config")

* fix(gateway): preserve explicit reset model selection

* fix(gateway): track reset model override source

* fix(gateway): preserve legacy reset model overrides

* docs(changelog): add session reset merge note

---------

Co-authored-by: termtek <termtek@ubuntu.tail2b72cd.ts.net>

* test: stabilize ci test isolation

* test: isolate volcengine byteplus auth resolver imports

* fix: patch hono security advisories

* fix: pass system prompt to codex cli

* fix(plugins): prevent untrusted workspace plugins from hijacking bundled provider auth choices [AI] (openclaw#62368)

* fix: address issue

* fix: address review feedback

* docs(changelog): add onboarding auth-choice guard entry

* fix: address PR review feedback

* fix: address PR review feedback

* fix: address PR review feedback

* fix: address PR review feedback

* fix: address PR review feedback

* fix: address PR review feedback

* fix: address PR review feedback

* fix: address PR review feedback

---------

Co-authored-by: Devin Robison <drobison@nvidia.com>

* test: isolate provider runtime test mocks

* feat(plugins): support provider auth aliases

* feat(memory): add grounded REM backfill lane (openclaw#63273)

Merged via squash.

Prepared head SHA: 4450f25
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky

* feat(memory): harden grounded REM extraction (openclaw#63297)

Merged via squash.

Prepared head SHA: e188b7e
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky

* feat(ui): add dreaming diary controls and navigation (openclaw#63298)

Merged via squash.

Prepared head SHA: 0a2ae66
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky

* chore(ui): refresh zh-TW control ui locale

* chore(ui): refresh zh-CN control ui locale

* chore(ui): refresh pt-BR control ui locale

* chore(ui): refresh de control ui locale

* chore(ui): refresh es control ui locale

* chore(ui): refresh ko control ui locale

* chore(ui): refresh ja-JP control ui locale

* chore(ui): refresh fr control ui locale

* docs(matrix): tighten setup and config guidance

* chore(ui): refresh tr control ui locale

* chore(ui): refresh uk control ui locale

* chore(ui): refresh pl control ui locale

* chore(ui): refresh id control ui locale

* test: stabilize full-suite execution

* fix(matrix): contain sync outage failures (openclaw#62779)

Merged via squash.

Prepared head SHA: 901bb76
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras

* Align remote node exec event system messages with untrusted handling (openclaw#62659)

* fix(nodes): downgrade remote exec system events

* docs(changelog): add remote node exec event entry

---------

Co-authored-by: Devin Robison <drobison@nvidia.com>

* test: reuse image generate tool imports

* test: reuse followup runner imports

* docs(config): tighten wording in reference

* test: harden provider mock isolation

* fix(memory): accept embedded dreaming heartbeat tokens

* test: harden Parallels macOS smoke fallback

* build: narrow plugin SDK declaration build

* fix(dotenv): block workspace runtime env vars (openclaw#62660)

* fix(dotenv): block workspace runtime env vars

Co-authored-by: zsx <git@zsxsoft.com>

* docs(changelog): add workspace dotenv runtime-control entry

* fix(dotenv): block workspace gateway port override

---------

Co-authored-by: zsx <git@zsxsoft.com>
Co-authored-by: Devin Robison <drobison@nvidia.com>

* build: stage nostr runtime dependencies

* fix: load QA live provider overrides

* feat: parallelize character eval runs

* auth: avoid external cli sync on profile upsert

* test(doctor): mock memory-core runtime seam

* auth: persist explicit profile upserts directly

* Matrix: report startup failures as errors

* fix(browser): harden browser control override loading (openclaw#62663)

* fix(browser): harden browser control overrides

* fix(lint): prepare boundary artifacts for extension oxlint

* docs(changelog): add browser override hardening entry

* fix(lint): avoid duplicate boundary prep

---------

Co-authored-by: Devin Robison <drobison@nvidia.com>
Co-authored-by: Devin Robison <drobison00@users.noreply.github.com>

* test: reuse exec directive reply imports

* test: reuse verbose directive reply imports

* fix(browser): re-check interaction-driven navigations (openclaw#63226)

* fix(browser): guard interaction-driven navigations

* fix(browser): avoid rechecking unchanged interaction urls

* fix(browser): guard delayed interaction navigations

* fix(browser): guard interaction-driven navigations for full action duration

* fix(browser): avoid waiting on interaction grace timer

* fix(browser): ignore same-document hash-only URL changes in navigation guard

* fix(browser): dedupe interaction nav guards

* fix(browser): guard same-URL reloads in interaction navigation listeners

* docs(changelog): add interaction navigation guard entry

* fix(browser): drop duplicate ssrfPolicy props

* fix(browser): tighten interaction navigation guards

---------

Co-authored-by: Devin Robison <drobison@nvidia.com>

* test: move directive state coverage to pure tests

* fix: enable thinking support for the ollama api (openclaw#62712)

Merged via squash.

Prepared head SHA: c0b9950
Co-authored-by: hoyyeva <63033505+hoyyeva@users.noreply.github.com>
Co-authored-by: BruceMacD <5853428+BruceMacD@users.noreply.github.com>
Reviewed-by: @BruceMacD

* Slack: treat ACP block text as visible output (openclaw#62858)

Merged via squash.

Prepared head SHA: 14f202e
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras

* fix: fail fast on qa live auth errors

* fix: fail fast across qa scenario wait paths

* test: cover qa scenario wait failure replies

* fix: sanitize qa missing-key replies

* test: cover sanitized qa missing-key replies

* fix: align qa wait cursor semantics

* test: cover mixed-traffic qa wait cursors

* fix: classify curated qa missing-key replies

* test: cover curated qa missing-key reply classification

* fix: harden qa missing-key provider messages

* test: cover unsafe qa missing-key providers

* docs(changelog): add qa auth fail-fast entry (openclaw#63333) (thanks @shakkernerd)

* fix(matrix/doctor): migrate legacy channels.matrix.dm.policy 'trusted' (fixes openclaw#62931) (openclaw#62942)

Merged via squash.

Prepared head SHA: d9f553b
Co-authored-by: lukeboyett <46942646+lukeboyett@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras

* Memory/dreaming: feed grounded backfill into short-term promotion (openclaw#63370)

Merged via squash.

Prepared head SHA: 5dfe246
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky

* docs: update unreleased changelog

* fix(gateway): classify dream diary actions

* fix(memory): align dreaming status payloads

* Memory/dreaming: harden grounded backfill follow-ups

* test: reuse inline directive reply imports

* Docs/memory: explain grounded backfill flows

* fix(deps): patch basic-ftp advisory

* test: move inline directive collisions to pure tests

* Slack: dedupe partial streaming replies (openclaw#62859)

Merged via squash.

Prepared head SHA: cbecb50
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras

* test: replace exec directive e2e with pure coverage

* fix(plugins): keep test helpers out of contract barrels (openclaw#63311)

Merged via squash.

Prepared head SHA: 769e90c
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf

* test: move cron heartbeat delivery coverage below full turns

* fix: inter-session messages must not overwrite established external lastRoute (openclaw#58013)

Merged via squash.

Prepared head SHA: 820ea20
Co-authored-by: duqaXxX <12242811+duqaXxX@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman

* fix(gateway): suppress announce/reply skip chat leakage (openclaw#51739)

Merged via squash.

Prepared head SHA: 2f53f3b
Co-authored-by: Pinghuachiu <9033138+Pinghuachiu@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman

* Slack: key turn-local dedupe by dispatch kind

Scope Slack turn-local delivery dedupe by reply dispatch kind so identical tool and final payloads on the same thread do not collapse into one send.

Expose the existing dispatcher kind on the public reply-runtime seam and cover the Slack tracker and preview-fallback paths with regression tests.

* Dreaming: surface grounded scene lane (openclaw#63395)

Merged via squash.

Prepared head SHA: 0c7f586
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky

* test: avoid runtime auth overlays in failure-state coverage

* fix(ci): align ollama thinking expectations

* chore(ui): refresh zh-CN control ui locale

* chore(ui): refresh pt-BR control ui locale

* chore(ui): refresh zh-TW control ui locale

* chore(ui): refresh de control ui locale

* test(docker): reduce e2e log noise

* chore(ui): refresh es control ui locale

* chore(ui): refresh fr control ui locale

* chore(ui): refresh ja-JP control ui locale

* chore(ui): refresh ko control ui locale

* chore(ui): refresh uk control ui locale

* chore(ui): refresh id control ui locale

* chore(ui): refresh pl control ui locale

* chore(ui): refresh tr control ui locale

* fix: restore main ci

* fix(ci): drop silent history before truncation

* docs: reorder unreleased changelog

* test(docker): quiet success-path e2e logs

* style: sort session import

* build: mirror bundled plugin runtime deps

* plugins: load lightweight provider discovery entries

* ci: narrow Windows node test lane

* fix: filter provider auth aliases by plugin trust

* fix: surface delayed browser navigation blocks

* style: format memory and gateway touchups

* Delete docs/plans directory

Unused artifact

* test: avoid remote ollama timeout in api-key preservation coverage

* test: keep auth-choice default-model coverage on lightweight provider

* test: keep undefined-token auth-choice coverage generic

* fix: stabilize character eval and Qwen model routing

* test: keep agent command tests off external auth overlays

* fix openrouter model picker refs (openclaw#63416)

* fix openrouter model picker refs

Signed-off-by: sallyom <somalley@redhat.com>

* test(ui): cover openrouter slash-id /model resolution

---------

Signed-off-by: sallyom <somalley@redhat.com>
Co-authored-by: Vignesh Natarajan <vignesh.natarajan92@gmail.com>

* ci: stabilize macOS and transcript policy tests

* test: keep cli-provider agent command tests off external auth overlays

* chore(lint): clear extension lint regressions and add openclaw#63416 changelog

* test: update modelstudio catalog contract sentinel

* test: update character eval public panel

* fix: repair Windows dev-channel updater

* test: move copilot models-json injection coverage to plan tests

* plugin-sdk: split command status surface

* plugin-sdk: keep command status compatibility path light

* plugin-sdk: drop investigative weixin repro harness

* tests: document config mock choice for eager warmup

* fix: update command-status SDK baseline (openclaw#63174) (thanks @hxy91819)

* test: cap broad live model sweeps

* fix: drop raw gateway chat control replies

* test: make shared-token reload deterministic

* test: isolate agentic suite smoke tests

* test: replace models-config matrix with narrow coverage

* test: isolate onboard skills status mock

* plugins: add lightweight anthropic vertex discovery

* test: isolate model auth module state

* test: isolate subagent registry resume imports

* plugins: keep google provider policy lightweight

* test: keep ollama unreachable discovery on localhost

* test: mock auth profile external overlay in oauth tests

* auth: avoid plugin setup scans during common auth resolution

* fix(logging): break console/logger type cycle

* fix(config): stop owner-display barrel cycles

* fix(commands): split auth choice apply types

* fix(infra): extract exec approvals allowlist types

* fix(commands): split doctor prompt option types

* chore: prepare 2026.4.9-beta.1 release

* chore: refresh config schema version for 2026.4.9-beta.1

* chore: refresh plugin SDK API baseline

* test: run local full suite project shards in parallel

* wizard: add explicit skip option to plugin setup (openclaw#63436)

* Wizard: allow skipping plugin setup

* Agents: reset nodes tool test modules

* tests: reset discord native-command seams in model picker (openclaw#63267)

* ci: tolerate noisy npm pack json output

* test: isolate slack thread-ts recovery

* fix(msteams): isolate channel thread sessions by replyToId (openclaw#58615) (openclaw#62713)

* fix(msteams): isolate thread sessions by replyToId (openclaw#58615)

* fix(msteams): align thread ID extraction + fix test types

* fix(msteams): route thread replies to correct thread via replyToId (openclaw#58030) (openclaw#62715)

* fix(msteams): pin reply target at inbound time to prevent DM/channel leak (openclaw#54520) (openclaw#62716)

* test: keep local full suite serial by default

* chore: prepare 2026.4.9 stable release

* Agents: guard legacy pi transport override

* Agents: restore upstream pi runner sources

---------

Signed-off-by: sallyom <somalley@redhat.com>
Co-authored-by: scoootscooob <zhentongfan@gmail.com>
Co-authored-by: scoootscooob <167050519+scoootscooob@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Nimrod Gutman <nimrod.gutman@gmail.com>
Co-authored-by: Tyler Warburton <Ethan.gold-Steinberg@protonmail.com>
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
Co-authored-by: Eric Curtin <eric.curtin@docker.com>
Co-authored-by: Mariano <mbelinky@gmail.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: Frank Yang <frank.ekn@gmail.com>
Co-authored-by: termtek <termtek@ubuntu.tail2b72cd.ts.net>
Co-authored-by: Pavan Kumar Gondhi <pgondhi@nvidia.com>
Co-authored-by: Devin Robison <drobison@nvidia.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Gustavo Madeira Santana <gumadeiras@gmail.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: Agustin Rivera <31522568+eleqtrizit@users.noreply.github.com>
Co-authored-by: zsx <git@zsxsoft.com>
Co-authored-by: Devin Robison <drobison00@users.noreply.github.com>
Co-authored-by: Eva H <63033505+hoyyeva@users.noreply.github.com>
Co-authored-by: BruceMacD <5853428+BruceMacD@users.noreply.github.com>
Co-authored-by: Shakker <shakkerdroid@gmail.com>
Co-authored-by: lukeboyett <46942646+lukeboyett@users.noreply.github.com>
Co-authored-by: Altay <altay@uinaf.dev>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Co-authored-by: Accunza <12242811+duqaXxX@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Co-authored-by: Pinghuachiu <9033138+Pinghuachiu@users.noreply.github.com>
Co-authored-by: Radek Sienkiewicz <mail@velvetshark.com>
Co-authored-by: Sally O'Malley <somalley@redhat.com>
Co-authored-by: Vignesh Natarajan <vignesh.natarajan92@gmail.com>
Co-authored-by: Mason Huang <masonxhuang@tencent.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
Co-authored-by: pashpashpash <nik@vault77.ai>
Co-authored-by: sudie-codes <suvenkat95@gmail.com>
zhonghe0615 pushed a commit to zhonghe0615/openclaw that referenced this pull request Apr 27, 2026
Merged via squash.

Prepared head SHA: 2f53f3b
Co-authored-by: Pinghuachiu <9033138+Pinghuachiu@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
lovewanwan pushed a commit to lovewanwan/openclaw that referenced this pull request Apr 28, 2026
Merged via squash.

Prepared head SHA: 2f53f3b
Co-authored-by: Pinghuachiu <9033138+Pinghuachiu@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
Merged via squash.

Prepared head SHA: 2f53f3b
Co-authored-by: Pinghuachiu <9033138+Pinghuachiu@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
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 gateway Gateway runtime size: M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants