Skip to content

fix(whatsapp): clarify inbound group diagnostics#83846

Closed
neeravmakwana wants to merge 3 commits into
openclaw:mainfrom
neeravmakwana:fix-whatsapp-inbound-diagnostics-83779
Closed

fix(whatsapp): clarify inbound group diagnostics#83846
neeravmakwana wants to merge 3 commits into
openclaw:mainfrom
neeravmakwana:fix-whatsapp-inbound-diagnostics-83779

Conversation

@neeravmakwana

Copy link
Copy Markdown
Contributor

Summary

  • Problem: WhatsApp Web startup said it was listening for personal inbound messages even though the monitor observes DM and group traffic, and the group allowlist drop diagnostic did not tell operators how to route observed-but-unregistered groups.
  • Solution: Replace the DM-only startup wording with listener-scope diagnostics that distinguish no group allowlist, wildcard group admission, and explicit configured group counts.
  • What changed: Unregistered group drops now name channels.whatsapp.groups, preserve the current sender-authorization warning, and the WhatsApp docs troubleshooting section calls out the observed-before-routing behavior.
  • What did NOT change (scope boundary): Runtime admission policy, groupPolicy, groupAllowFrom, allowFrom, mention gating, and session routing controls are unchanged.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

Motivation

Operators can see group traffic arriving in the WhatsApp Web monitor while OpenClaw intentionally drops groups that are not admitted by channels.whatsapp.groups. The old startup and drop diagnostics made that look like DM-only listening or unexplained message loss.

Real behavior proof (required for external PRs)

  • Behavior addressed: WhatsApp inbound diagnostics now describe DM plus group observation/routing accurately, and unregistered group drops explain the required config without changing runtime policy.

  • Real environment tested: macOS local OpenClaw source checkout, Node/Vitest test harness for the WhatsApp Web monitor and config group-policy path.

  • Exact steps or command run after this patch: node scripts/run-vitest.mjs extensions/whatsapp/src/auto-reply/web-auto-reply-monitor.test.ts src/config/group-policy.test.ts

  • Evidence after fix (screenshot, recording, terminal capture, console output, redacted runtime log, linked artifact, or copied live output):

    Listening for WhatsApp inbound messages (DM + all groups; no group allowlist configured).
    Listening for WhatsApp inbound messages (DM + all groups; wildcard configured).
    Listening for WhatsApp inbound messages (DM + 2 configured groups).
    Dropping message from unregistered WhatsApp group 123@g.us. Add the group JID to channels.whatsapp.groups, or add "*" there to admit all groups. Sender authorization still applies.
    
  • Observed result after fix: The focused WhatsApp/config regression run passed with 2 test files and 42 tests, including assertions for the startup diagnostic variants and the unregistered-group drop message.

  • What was not tested: A live credentialed WhatsApp session was not run; the change is limited to diagnostics/docs and preserves the existing tested routing policy.

  • Before evidence (optional but encouraged):

    Listening for personal WhatsApp inbound messages.
    Skipping group message 123@g.us (not in allowlist)
    

Root Cause (if applicable)

  • Root cause: The listener startup log was written as if the WhatsApp Web monitor only listened for personal DMs, while later group admission logic can observe group traffic and drop it before session routing.
  • Missing detection / guardrail: Existing group-policy tests asserted the drop behavior but did not assert the operator-facing diagnostics.
  • Contributing context (if known): channels.whatsapp.groups is both the per-group config map and group membership allowlist; groupAllowFrom only handles sender authorization inside admitted groups.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: extensions/whatsapp/src/auto-reply/web-auto-reply-monitor.test.ts
  • Scenario the test should lock in: Startup diagnostics do not imply DM-only listening, and unregistered group drops explain channels.whatsapp.groups while preserving the block.
  • Why this is the smallest reliable guardrail: The change is diagnostic-only on top of existing group-gating behavior.
  • Existing test that already covers this (if any): src/config/group-policy.test.ts covers the group allowlist policy itself.
  • If no new test is added, why not: N/A

User-visible / Behavior Changes

WhatsApp logs and docs are clearer for group messages that are observed by the monitor but dropped before routing because the group is not registered in channels.whatsapp.groups. No runtime routing, authorization, or security behavior changes.

Diagram (if applicable)

Before:
WhatsApp Web monitor observes group -> group not in groups allowlist -> vague skip log

After:
WhatsApp Web monitor observes group -> group not in groups allowlist -> drop log names channels.whatsapp.groups and notes sender authorization still applies

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: N/A

Security/runtime controls unchanged: channels.whatsapp.groups still gates group membership admission; groupPolicy and groupAllowFrom still gate sender authorization; mention gating still applies after group admission.

Repro + Verification

Environment

  • OS: macOS
  • Runtime/container: local Node/Vitest via repo test wrapper
  • Model/provider: N/A
  • Integration/channel (if any): WhatsApp
  • Relevant config (redacted): tests cover no groups, wildcard groups["*"], and explicit group allowlist entries

Steps

  1. Compare previous diagnostics from origin/main with the new WhatsApp listener/drop diagnostic strings.
  2. Run the focused WhatsApp monitor and group-policy tests.
  3. Run docs/list, whitespace, and changed checks.

Expected

  • Startup log describes WhatsApp inbound scope without implying DM-only listening.
  • Group allowlist drops identify channels.whatsapp.groups and keep sender-authorization expectations explicit.
  • Existing group blocking behavior remains unchanged.

Actual

  • Expected diagnostics are asserted in tests.
  • Focused tests and changed checks pass.

Evidence

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Verification run:

git diff --check
pnpm docs:list
node scripts/run-vitest.mjs extensions/whatsapp/src/auto-reply/web-auto-reply-monitor.test.ts src/config/group-policy.test.ts
pnpm check:changed

Human Verification (required)

  • Verified scenarios: startup log text for no group allowlist, wildcard group admission, explicit group count; unregistered group drop message; current group-policy allowlist behavior.
  • Edge cases checked: no groups, groups["*"], multiple explicit groups, unregistered group blocked with observable diagnostic.
  • What you did not verify: live WhatsApp credentials, QR login, or a real phone/device session.

Review Conversations

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

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? No
  • Migration needed? No
  • If yes, exact upgrade steps: N/A

Risks and Mitigations

  • Risk: Operators could interpret wildcard admission as bypassing all group controls.
    • Mitigation: The drop diagnostic and docs state that sender authorization still applies through groupPolicy and groupAllowFrom.

Out of scope

  • Changing WhatsApp group routing or admission behavior.
  • Auto-registering observed groups.
  • Running a live credentialed WhatsApp E2E lane.

Made with Cursor

@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation channel: whatsapp-web Channel integration: whatsapp-web size: XS triage: mock-only-proof Candidate: PR proof only shows tests, mocks, snapshots, lint, typecheck, or CI. labels May 19, 2026
@clawsweeper

clawsweeper Bot commented May 19, 2026

Copy link
Copy Markdown
Contributor

Codex review: passed.

Workflow note: Future ClawSweeper reviews update this same comment in place.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

Summary
The PR updates WhatsApp Web inbound startup/drop diagnostics, adds a small listener-log helper and tests, and documents group allowlist troubleshooting.

Reproducibility: yes. Source inspection on current main shows the DM-only startup log and vague group-drop diagnostic while the existing group policy path observes and gates group messages before routing.

PR rating
Overall: 🐚 platinum hermit
Proof: 🐚 platinum hermit
Patch quality: 🐚 platinum hermit
Summary: Good normal PR: proof is overridden/sufficient, the patch is focused and policy-aligned, and the only current blocker is merge state rather than code correctness.

Rank-up moves:

  • Resolve the dirty merge state against current main, then let exact-head CI/automerge run again.
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

PR egg
✨ Hatched: 💎 rare Brave Test Hopper

        /\     /\            
      _/  \___/  \_          
     /  ( o   o )  \         
    |      \_/      |        
    |   /\  ===  /\ |        
     \_/  \_____/  \_/       
        _/|_| |_|\_          
       /__| | | |__\         
          ' ' ' '            
         /_/     \_\         
       `-----------'         
 *===================*       

Rarity: 💎 rare.
Trait: polishes edge cases.
Share on X: post this hatch
Copy: My PR egg hatched a 💎 rare Brave Test Hopper in ClawSweeper.

What is this egg doing here?
  • Eggs appear after the PR passes real-behavior proof. It is here for vibes, not verdicts: it does not change labels, ratings, merge decisions, or automation.
  • The shell reacts to review momentum: open follow-up work warms it up, re-review makes it wobble, and a clean final review lets it hatch.
  • How to hatch it: reach status: 👀 ready for maintainer look or status: 🚀 automerge armed; that usually means sufficient real-behavior proof, no blocking P0/P1/P2 findings, no security attention needed, and clean correctness.
  • The hatch is seeded from this repository and PR number, so the same PR keeps the same creature; the reviewed head SHA can only change safe visual details.
  • Rarity is just collectible sparkle: 🥚 common, 🌱 uncommon, 💎 rare, ✨ glimmer, and 🌈 legendary.

Real behavior proof
Override: A maintainer applied proof: override for this PR.

Risk before merge
Why this matters: - Live GitHub metadata reports a dirty merge state, so conflicts or a rebase/update must be handled before the opted-in automerge path can land the exact head.

Maintainer options:

  1. Decide the mitigation before merge
    Resolve the dirty merge state, then land the focused diagnostics/docs/test update through exact-head CI while preserving the existing WhatsApp routing and sender-authorization contracts.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Next step before merge
No code repair lane is needed, but the live PR API reports a dirty merge state that needs maintainer or contributor conflict resolution before automerge can proceed.

Security
Cleared: The diff only changes WhatsApp diagnostic text, docs, and tests, and adds no dependency, permission, secret, network, or execution-surface change.

Review details

Best possible solution:

Resolve the dirty merge state, then land the focused diagnostics/docs/test update through exact-head CI while preserving the existing WhatsApp routing and sender-authorization contracts.

Do we have a high-confidence way to reproduce the issue?

Yes. Source inspection on current main shows the DM-only startup log and vague group-drop diagnostic while the existing group policy path observes and gates group messages before routing.

Is this the best way to solve the issue?

Yes. The PR uses the existing resolved WhatsApp inbound policy as the source of truth for diagnostic wording and adds focused tests/docs without changing routing behavior.

Label justifications:

  • P3: This is a low-risk WhatsApp diagnostics and docs improvement with no runtime policy change.

What I checked:

  • Current main startup diagnostic is misleading: Current main still logs Listening for personal WhatsApp inbound messages. even though the monitor path also observes group messages before policy gating. (extensions/whatsapp/src/auto-reply/monitor.ts:564, e9989f3a92e5)
  • Current main group-drop diagnostic is vague: The group gating path drops unregistered groups with the old not in allowlist message and no channels.whatsapp.groups guidance. (extensions/whatsapp/src/auto-reply/monitor/group-gating.ts:116, e9989f3a92e5)
  • Existing policy contract supports the PR shape: Current group policy resolution already distinguishes disabled groups, explicit/wildcard group maps, and the sender-filter bypass when groupAllowFrom is configured. (src/config/group-policy.ts:385, e9989f3a92e5)
  • PR diff uses resolved WhatsApp policy facts: The branch calls resolveWhatsAppInboundPolicy at monitor startup and formats the diagnostic from resolved groups, groupPolicy, and sender allowlist state instead of duplicating routing policy. (extensions/whatsapp/src/auto-reply/monitor.ts:543, d012a009e74a)
  • Focused tests cover the operator-visible diagnostics: The PR adds listener diagnostic assertions for open, disabled, empty allowlist, sender-filter, wildcard, and explicit group states, plus an assertion for the clarified unregistered-group drop log. (extensions/whatsapp/src/auto-reply/web-auto-reply-monitor.test.ts:118, d012a009e74a)
  • Real behavior proof is present and overridden: The PR has proof: override and proof: sufficient; the author also posted sanitized installed-build terminal output for the updated startup/drop strings and unchanged shouldProcess=false group drop result. (d012a009e74a)

Likely related people:

  • Takhoffman: Current-main blame on the affected startup and group-gating lines points to Tak Hoffman in the shallow checkout, and Takhoffman also requested automerge on this PR. (role: recent area contributor and reviewer; confidence: medium; commits: c92ebd6a4104; files: extensions/whatsapp/src/auto-reply/monitor.ts, extensions/whatsapp/src/auto-reply/monitor/group-gating.ts)
  • Marcus Castro: Commit 458a526... introduced the resolved WhatsApp inbound policy and rewired the monitor/group-gating paths that this PR now uses for diagnostics. (role: feature-history owner; confidence: high; commits: 458a52610a4d; files: extensions/whatsapp/src/inbound-policy.ts, extensions/whatsapp/src/auto-reply/monitor.ts, extensions/whatsapp/src/auto-reply/monitor/group-gating.ts)
  • Peter Steinberger: git shortlog shows the most commits across the central WhatsApp/docs files sampled for this review, making Peter a useful routing candidate for this surface. (role: frequent area contributor; confidence: medium; commits: 50a2481652b6; files: docs/channels/whatsapp.md, extensions/whatsapp/src/auto-reply/monitor.ts, extensions/whatsapp/src/auto-reply/monitor/group-gating.ts)

Codex review notes: model gpt-5.5, reasoning high; reviewed against e9989f3a92e5.

@neeravmakwana neeravmakwana marked this pull request as ready for review May 19, 2026 01:24
@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P3 Low-priority cleanup, docs, polish, ergonomics, or speculative work. labels May 19, 2026
@neeravmakwana

Copy link
Copy Markdown
Contributor Author

Local install real behavior proof

Installed/updated the local wrapper to the current PR branch build:

~/.local/bin/openclaw --version
OpenClaw 2026.5.19 (5774f2a)

Ran a sanitized local behavior probe against the PR branch checkout. No .env values or credentials were printed.

install.version:
  OpenClaw 2026.5.19 (5774f2a) via ~/.local/bin/openclaw
startup.log.no_groups:
  Listening for WhatsApp inbound messages (DM + all groups; no group allowlist configured).
startup.log.wildcard:
  Listening for WhatsApp inbound messages (DM + all groups; wildcard configured).
startup.log.explicit_groups:
  Listening for WhatsApp inbound messages (DM + 2 configured groups).
group_drop.result:
  shouldProcess=false
group_drop.log:
  Dropping message from unregistered WhatsApp group 123@g.us. Add the group JID to channels.whatsapp.groups, or add "*" there to admit all groups. Sender authorization still applies.

This proves the changed diagnostics on the installed local build and confirms the existing runtime control remains unchanged: the unregistered group is not routed.

@neeravmakwana neeravmakwana marked this pull request as draft May 19, 2026 01:42
@neeravmakwana neeravmakwana marked this pull request as ready for review May 19, 2026 01:43
@neeravmakwana

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented May 19, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels May 19, 2026
@openclaw-barnacle openclaw-barnacle Bot added size: S and removed size: XS proof: sufficient ClawSweeper judged the real behavior proof convincing. labels May 19, 2026
@neeravmakwana

Copy link
Copy Markdown
Contributor Author

Addressed the ClawSweeper finding about policy-state correctness in the startup diagnostic.

What changed:

  • formatWhatsAppInboundListeningLog now takes resolved groupPolicy and sender-filter facts instead of deriving scope only from channels.whatsapp.groups.
  • The startup log now distinguishes these states:
    • groupPolicy: "disabled" -> groups disabled
    • groupPolicy: "allowlist" with no sender allowlist -> group inbound blocked by empty allowlist
    • sender-filter bypass/admission -> all groups with sender allowlist configured
    • wildcard group admission -> all groups with wildcard configured
    • explicit group allowlist -> configured group count
  • monitorWebChannel now builds the startup diagnostic from resolveWhatsAppInboundPolicy(...), so the log follows the same resolved defaults/fallbacks as runtime admission.
  • Tests now cover disabled, fail-closed allowlist, sender-filter, wildcard, and explicit-group diagnostic states.

Security/runtime controls unchanged:

  • channels.whatsapp.groups still gates group membership admission.
  • groupPolicy and groupAllowFrom / allowFrom still gate sender authorization.
  • Mention gating and session routing behavior are unchanged.
  • No new permissions, secrets handling, network calls, dependencies, or execution surface.

Verification run after the fix:

git diff --check
node scripts/run-vitest.mjs extensions/whatsapp/src/auto-reply/web-auto-reply-monitor.test.ts src/config/group-policy.test.ts
pnpm docs:list
pnpm check:changed
pnpm build

Focused test result:

Test Files  2 passed (2)
Tests       42 passed (42)

Changed check result:

[check:changed] lanes=extensions, extensionTests, docs
Found 0 warnings and 0 errors.
Import cycle check: 0 runtime value cycle(s).

Updated local installed-build proof, sanitized:

~/.local/bin/openclaw --version
OpenClaw 2026.5.19 (d012a00)

install.version:
  OpenClaw 2026.5.19 (d012a00) via ~/.local/bin/openclaw
startup.log.open_no_groups:
  Listening for WhatsApp inbound messages (DM + all groups; no group allowlist configured).
startup.log.disabled:
  Listening for WhatsApp inbound messages (DM + groups disabled by groupPolicy).
startup.log.fail_closed_allowlist:
  Listening for WhatsApp inbound messages (DM + group inbound blocked by empty groupPolicy allowlist).
startup.log.sender_filter:
  Listening for WhatsApp inbound messages (DM + all groups; sender allowlist configured).
startup.log.wildcard:
  Listening for WhatsApp inbound messages (DM + all groups; wildcard configured).
startup.log.explicit_groups:
  Listening for WhatsApp inbound messages (DM + 2 configured groups).
group_drop.result:
  shouldProcess=false
group_drop.log:
  Dropping message from unregistered WhatsApp group 123@g.us. Add the group JID to channels.whatsapp.groups, or add "*" there to admit all groups. Sender authorization still applies.

No .env values or credentials were read or printed. A live credentialed WhatsApp session remains out of scope for this diagnostics-only change.

@clawsweeper re-review

@neeravmakwana neeravmakwana marked this pull request as draft May 19, 2026 02:08
@clawsweeper

clawsweeper Bot commented May 19, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@neeravmakwana neeravmakwana marked this pull request as ready for review May 19, 2026 02:11
@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels May 19, 2026
@Takhoffman

Copy link
Copy Markdown
Contributor

@clawsweeper automerge

@Takhoffman Takhoffman added the proof: override Maintainer override for the external PR real behavior proof gate. label May 19, 2026
@openclaw-barnacle openclaw-barnacle Bot removed the triage: mock-only-proof Candidate: PR proof only shows tests, mocks, snapshots, lint, typecheck, or CI. label May 19, 2026
@clawsweeper clawsweeper Bot added the clawsweeper:automerge Maintainer opted this PR into bounded ClawSweeper-reviewed automerge label May 19, 2026
@clawsweeper

clawsweeper Bot commented May 19, 2026

Copy link
Copy Markdown
Contributor

🦞🔧
ClawSweeper automerge is enabled.

Draft PRs stay fix-only until GitHub marks them ready for review. Pause with /clawsweeper stop.

Automerge progress:

  • 2026-05-19 02:27:49 UTC review queued d012a009e74a (queued)
  • 2026-05-19 02:34:26 UTC review passed d012a009e74a (structured ClawSweeper verdict: pass (sha=d012a009e74aab96a70976dc46fb544c64a75...)

@clawsweeper clawsweeper Bot added status: 🚀 automerge armed This PR is in ClawSweeper's automerge lane. and removed proof: sufficient ClawSweeper judged the real behavior proof convincing. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels May 19, 2026
@clawsweeper

clawsweeper Bot commented May 19, 2026

Copy link
Copy Markdown
Contributor

ClawSweeper 🐠 reef update

Thanks for the useful work here. ClawSweeper could not update this branch directly, so the replacement PR is the writable swim lane for the same fix path.

Why replacement: ClawSweeper could not update the source PR branch directly; GitHub did not grant sufficient push rights to the bot for that branch.
Replacement PR: #83969
Why close: this run explicitly closes the superseded source PR after the credited replacement PR is open, so review continues in one place.
This source PR is being closed only under the explicit source-close setting for this ClawSweeper run.
The replacement PR carries the original credit trail forward.
Co-author credit kept:

fish notes: model gpt-5.5, reasoning high; reviewed against 0da24e3.

@clawsweeper clawsweeper Bot closed this May 19, 2026
eleboucher pushed a commit to eleboucher/homelab that referenced this pull request May 21, 2026
…026.5.20) (#615)

This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [ghcr.io/openclaw/openclaw](https://openclaw.ai) ([source](https://github.com/openclaw/openclaw)) | patch | `2026.5.19` → `2026.5.20` |

---

> ⚠️ **Warning**
>
> Some dependencies could not be looked up. Check the [Dependency Dashboard](issues/567) for more information.

---

### Release Notes

<details>
<summary>openclaw/openclaw (ghcr.io/openclaw/openclaw)</summary>

### [`v2026.5.20`](https://github.com/openclaw/openclaw/blob/HEAD/CHANGELOG.md#2026520)

[Compare Source](openclaw/openclaw@v2026.5.19...v2026.5.20)

##### Changes

- Exec approvals: remove the old `cat SKILL.md && printf ... && <skill-wrapper>` allowlist compatibility path so skill files must be loaded with the read tool and only the real skill executable is auto-allowed.
- Discord: let voice sessions follow configured Discord users into voice channels, with allowed-channel checks, multi-user handoff, bounded reconciliation, and DAVE recovery preservation. ([#&#8203;84264](openclaw/openclaw#84264)) Thanks [@&#8203;fuller-stack-dev](https://github.com/fuller-stack-dev).
- Discord/voice: include bounded `IDENTITY.md`, `USER.md`, and `SOUL.md` profile context in realtime voice session instructions by default, with `voice.realtime.bootstrapContextFiles: []` available to disable it. ([#&#8203;84499](openclaw/openclaw#84499)) Thanks [@&#8203;fuller-stack-dev](https://github.com/fuller-stack-dev).
- Dependencies: bump the bundled Codex harness to `@openai/codex` `0.132.0` and refresh the app-server model-list docs for the new catalog.
- CLI/policy: add the bundled Policy plugin for policy-backed channel conformance checks, doctor lint findings, and opt-in workspace repair. ([#&#8203;80407](openclaw/openclaw#80407)) Thanks [@&#8203;giodl73-repo](https://github.com/giodl73-repo).
- Agents/config: allow `agents.list[].experimental.localModelLean` so lean local-model mode can be enabled for one configured agent instead of globally.
- Providers/xAI: add device-code OAuth login so remote and headless setups can authorize xAI without a localhost browser callback. ([#&#8203;84005](openclaw/openclaw#84005)) Thanks [@&#8203;fuller-stack-dev](https://github.com/fuller-stack-dev).
- Providers/OpenRouter: honor provider-level `params.provider` routing policy for OpenRouter requests, with model and agent params overriding the defaults. Thanks [@&#8203;amknight](https://github.com/amknight).

##### Fixes

- CLI/tasks: include stale-running task maintenance decisions in `openclaw tasks maintenance --json` so retained and reconcile candidates explain backing-session, cron, CLI, and wedged-subagent state. ([#&#8203;84691](openclaw/openclaw#84691)) Thanks [@&#8203;efpiva](https://github.com/efpiva).
- Codex app-server: keep system-prompt reports working when bootstrap hooks provide workspace files with only a path and content, so hook-supplied SOUL/IDENTITY/TOOLS/USER context still reports injected characters correctly. ([#&#8203;84736](openclaw/openclaw#84736)) Thanks [@&#8203;JARVIS-Glasses](https://github.com/JARVIS-Glasses).
- Providers/MiniMax music: stop advertising `durationSeconds` control and remove prompt-injected duration hints, so `music_generate` reports MiniMax duration as an unsupported override instead of suggesting MiniMax can enforce track length. Fixes [#&#8203;84508](openclaw/openclaw#84508). Thanks [@&#8203;neeravmakwana](https://github.com/neeravmakwana).
- Doctor: warn when sandbox tool policy hides configured MCP server tools before provider requests. ([#&#8203;84699](openclaw/openclaw#84699)) Thanks [@&#8203;nxmxbbd](https://github.com/nxmxbbd).
- WhatsApp: update Baileys to `7.0.0-rc12`.
- Build: suppress per-locale `rolldown-plugin-dts:fake-js` CommonJS dts warnings emitted while bundling the intentionally-inlined `zod/v4/locales/*.d.cts` files, so `pnpm build` output stays readable after the 0.25.1 plugin bump. Thanks [@&#8203;romneyda](https://github.com/romneyda).
- CLI/nodes: route lazy plugin-registration logs to stderr for JSON-mode `openclaw nodes` commands so stdout stays parseable. ([#&#8203;84684](openclaw/openclaw#84684)) Thanks [@&#8203;TurboTheTurtle](https://github.com/TurboTheTurtle).
- Approvals: route manual `/approve` decisions through the trusted approval runtime so active exec and plugin approvals no longer look unknown or expired.
- Mac app: update the About settings copyright year to 2026. ([#&#8203;84385](openclaw/openclaw#84385)) Thanks [@&#8203;pejmanjohn](https://github.com/pejmanjohn).
- Dependencies: update `@openclaw/fs-safe` to `0.2.7` so OpenClaw's default Python-helper-off policy keeps best-effort Node write fallbacks for private stores, secret writes, run logs, and media attachments on Linux/macOS.
- Infra/secrets: restore the fail-closed contract for `tryReadSecretFileSync` so credential loaders that pass `rejectSymlink: true` (Telegram, LINE, Zalo, IRC, Nextcloud Talk tokens) refuse symlinked credential files instead of silently accepting them, and the infra-state CI shard's secret-file symlink test passes again. Thanks [@&#8203;romneyda](https://github.com/romneyda).
- Browser: honor the configured image sanitization limit for screenshots and labeled snapshots so browser-captured images follow the same resize policy as other image results. ([#&#8203;84595](openclaw/openclaw#84595))
- Doctor: remove unrecognized `models.providers.*.models[*].compat.thinkingFormat` values during `doctor --fix` so stale provider model config can validate after upgrade. Fixes [#&#8203;77803](openclaw/openclaw#77803).
- Doctor: warn when `openclaw.json` stores plaintext secret-bearing config fields, including model provider API keys and sensitive provider headers. ([#&#8203;84718](openclaw/openclaw#84718)) Thanks [@&#8203;lukaIvanic](https://github.com/lukaIvanic).
- Status: show the configured default, session-selected model, reason, clear hint, and docs link when a session remains pinned to a model that differs from `agents.defaults.model.primary`.
- WebChat: clear stale typing indicators when session change events mark the active chat run complete.
- Mac app: keep local packaging signed with a stable app identity for permission testing and fix Control UI production builds under current Vite/Highlight.js exports.
- macOS app: update the embedded Peekaboo bridge to 3.2.1 so OpenClaw-hosted UI automation works with current Peekaboo CLI capture flows.
- Cron: deliver preferred final assistant output for successful scheduled runs when trailing plain tool warnings remain in diagnostics instead of marking the run failed.
- fix(mattermost): fail closed on missing channel type \[AI]. ([#&#8203;84091](openclaw/openclaw#84091)) Thanks [@&#8203;pgondhi987](https://github.com/pgondhi987).
- Recheck rebuilt system.run argv \[AI]. ([#&#8203;84090](openclaw/openclaw#84090)) Thanks [@&#8203;pgondhi987](https://github.com/pgondhi987).
- CLI: keep the private QA subcommand out of exported command descriptors unless `OPENCLAW_ENABLE_PRIVATE_QA_CLI=1`, so root help and subcommand markers match runtime registration. ([#&#8203;84519](openclaw/openclaw#84519))
- CLI/cron: bound `openclaw cron show` job lookup pagination so non-advancing or unbounded `cron.list` responses fail instead of hanging the command. Fixes [#&#8203;83856](openclaw/openclaw#83856). ([#&#8203;83989](openclaw/openclaw#83989))
- Agents/messages: stop message-tool-only turns after a successful source-channel `message` send while keeping transcript mirrors under the session write lock. ([#&#8203;84289](openclaw/openclaw#84289))
- Agents: filter silent heartbeat response-tool transcript artifacts out of embedded context snapshots so later user turns are not polluted by heartbeat no-op messages. ([#&#8203;83477](openclaw/openclaw#83477)) Thanks [@&#8203;fuller-stack-dev](https://github.com/fuller-stack-dev).
- Agents/OpenAI: log repeated strict tool-schema downgrade diagnostics once per provider/model/tool signature, reducing duplicate debug noise while preserving `strict=false` fallback behavior. Fixes [#&#8203;82930](openclaw/openclaw#82930). ([#&#8203;82933](openclaw/openclaw#82933)) Thanks [@&#8203;galiniliev](https://github.com/galiniliev).
- Agents/code mode: spell out the `exec` tool's JavaScript/TypeScript, no Node module, and catalog-bridge constraints in model-visible schema text so agents can use enabled tools without trial-and-error. ([#&#8203;84269](openclaw/openclaw#84269)) Thanks [@&#8203;Kaspre](https://github.com/Kaspre).
- Codex: give `image_generate` dynamic-tool calls a 120s default watchdog when no per-call or configured image timeout is set, so image generation no longer falls back to the generic 30s bridge timeout. ([#&#8203;84254](openclaw/openclaw#84254)) Thanks [@&#8203;moritzmmayerhofer](https://github.com/moritzmmayerhofer).
- Codex: avoid duplicate dynamic tool terminal diagnostics while large diagnostic backlogs drain without blocking tool responses. ([#&#8203;82937](openclaw/openclaw#82937)) Thanks [@&#8203;galiniliev](https://github.com/galiniliev).
- CLI/message: include a stable top-level `messageId` in `openclaw message --json` output when channel sends return one. ([#&#8203;84191](openclaw/openclaw#84191)) Thanks [@&#8203;100menotu001](https://github.com/100menotu001).
- Cron: preserve legacy top-level array `jobs.json` stores when loading or adding scheduled jobs so old cron jobs are no longer treated as an empty store during upgrade. Fixes [#&#8203;60799](openclaw/openclaw#60799). ([#&#8203;84433](openclaw/openclaw#84433)) Thanks [@&#8203;IWhatsskill](https://github.com/IWhatsskill).
- Gateway/agents: use an agent's `identity.name` in Gateway agent summaries when `agents.list[].name` is unset, so configured agent labels remain visible in clients. ([#&#8203;84355](openclaw/openclaw#84355); refs [#&#8203;57835](openclaw/openclaw#57835)) Thanks [@&#8203;luoyanglang](https://github.com/luoyanglang).
- Channels/replies: keep normal `/verbose` failed-tool progress compact in message-tool replies and prevent late text-only tool output from appearing after the final answer. ([#&#8203;84303](openclaw/openclaw#84303)) Thanks [@&#8203;VACInc](https://github.com/VACInc).
- Plugins/hooks: apply a default 30-second timeout to `before_compaction` and `after_compaction` hooks so a hung plugin handler no longer blocks compaction completion. ([#&#8203;84153](openclaw/openclaw#84153))
- Discord: preserve disabled presentation buttons when adapting and rendering Discord message controls. ([#&#8203;84188](openclaw/openclaw#84188)) Thanks [@&#8203;100menotu001](https://github.com/100menotu001).
- Twitch: add a test-only client-manager registry reset helper so non-isolated Twitch tests can clear cached managers between cases. Fixes [#&#8203;83887](openclaw/openclaw#83887). ([#&#8203;84244](openclaw/openclaw#84244)) Thanks [@&#8203;hclsys](https://github.com/hclsys).
- Cron: run main-session scheduled work on a cron-owned wake lane while preserving reply delivery context, so background cron turns no longer block human main-session chat. Fixes [#&#8203;82766](openclaw/openclaw#82766). ([#&#8203;82767](openclaw/openclaw#82767)) Thanks [@&#8203;galiniliev](https://github.com/galiniliev).
- Cron: use structured embedded-run denial metadata for isolated scheduled tasks so blocked exec requests fail the job without treating ordinary assistant prose as a denial. ([#&#8203;84067](openclaw/openclaw#84067)) Thanks [@&#8203;abnershang](https://github.com/abnershang).
- Cron: keep recovered tool warnings diagnostic for successful scheduled runs so final cron output is delivered instead of being replaced by a post-processing warning. ([#&#8203;84045](openclaw/openclaw#84045)) Thanks [@&#8203;abnershang](https://github.com/abnershang).
- Plugins/perf: thread explicit plugin discovery results through `loadBundledCapabilityRuntimeRegistry`, `resolveBundledPluginSources`, and `listChannelCatalogEntries` so callers that already hold a discovery result skip redundant filesystem walks. Thanks [@&#8203;SebTardif](https://github.com/SebTardif).
- harden update restart script creation \[AI]. ([#&#8203;84088](openclaw/openclaw#84088)) Thanks [@&#8203;pgondhi987](https://github.com/pgondhi987).
- Docker: keep the bundled Codex plugin in official release image keep lists so the default OpenAI agent harness remains available after Docker pruning. Fixes [#&#8203;83613](openclaw/openclaw#83613). ([#&#8203;83626](openclaw/openclaw#83626)) Thanks [@&#8203;YuanHanzhong](https://github.com/YuanHanzhong).
- CLI/channels: preserve the first line of `openclaw channels logs` output when the rolling tail window starts exactly on a line boundary, mirroring the already-fixed `readLogSlice` behavior in `src/logging/log-tail.ts`.
- Control UI: treat terminal session status as authoritative over stale active-run flags so completed terminal runs stop showing abort/live UI. ([#&#8203;84057](openclaw/openclaw#84057))
- CLI: preserve embedded equals signs in inline root option values instead of truncating after the second separator. ([#&#8203;83995](openclaw/openclaw#83995)) Thanks [@&#8203;ThiagoCAltoe](https://github.com/ThiagoCAltoe).
- Matrix/config: accept `messages.queue.byChannel.matrix` queue overrides and keep queue provider schema/type keys aligned for Matrix, Google Chat, and Mattermost. Thanks [@&#8203;bdjben](https://github.com/bdjben).
- CLI: format `openclaw acp client` failures through the shared error formatter so object-shaped errors stay readable instead of printing `[object Object]`. Fixes [#&#8203;83904](openclaw/openclaw#83904). ([#&#8203;84080](openclaw/openclaw#84080))
- Providers/Ollama: default unknown-capabilities models to tool-capable so discovered native Ollama models can use tools when `/api/show` omits capabilities. ([#&#8203;84055](openclaw/openclaw#84055)) Thanks [@&#8203;dutifulbob](https://github.com/dutifulbob).
- Installer/Windows: launch `install.ps1` onboarding as an attached child process so fresh native Windows installs do not freeze visibly at `Starting setup...` or corrupt the wizard's terminal rendering.
- CLI/update: keep restart health checks working across one-version CLI/Gateway protocol skew and use the managed Gateway service Node for all follow-up commands even when the package root is unchanged, so `openclaw update` no longer silently switches the gateway to a different Node binary when multiple Node installations are present. Thanks [@&#8203;amknight](https://github.com/amknight).
- CLI/gateway: include the running Gateway version in `gateway status` JSON output, preserving existing server metadata while falling back to status RPC data for read probes. Fixes [#&#8203;56222](openclaw/openclaw#56222). Thanks [@&#8203;galiniliev](https://github.com/galiniliev).
- Memory/search: close local embedding providers when active-memory searches time out so pending local model loads and embedding contexts are aborted and released. ([#&#8203;83858](openclaw/openclaw#83858)) Thanks [@&#8203;brokemac79](https://github.com/brokemac79).
- CLI/nodes: request pending node surface approval scopes before `openclaw nodes approve` so exec-capable node approval can use admin-scoped Gateway credentials instead of failing with `missing scope: operator.admin`. ([#&#8203;84392](openclaw/openclaw#84392)) Thanks [@&#8203;joshavant](https://github.com/joshavant).
- Gateway: reject slow node event sends before outbound buffers grow unbounded and log the rejected payload diagnostic. ([#&#8203;84387](openclaw/openclaw#84387)) Thanks [@&#8203;samzong](https://github.com/samzong).
- Agents: include bounded trajectory queued-writer diagnostics in `pi-trajectory-flush` timeout warnings so flush stalls show pending writes, queued bytes, and append state. Fixes [#&#8203;82961](openclaw/openclaw#82961). ([#&#8203;82962](openclaw/openclaw#82962)) Thanks [@&#8203;galiniliev](https://github.com/galiniliev).
- Agents/subagents: recover stale completion announces by retrying unsupported transcript-wait wakes without transcript waiting and forcing a message-tool handoff when the requester run is already stale. Fixes [#&#8203;83699](openclaw/openclaw#83699). ([#&#8203;83700](openclaw/openclaw#83700)) Thanks [@&#8203;galiniliev](https://github.com/galiniliev).
- Agents/subagents: constrain wildcard subagent target allowlists to configured agents while preserving explicitly listed compatibility targets. Fixes [#&#8203;84040](openclaw/openclaw#84040). ([#&#8203;84357](openclaw/openclaw#84357)) Thanks [@&#8203;joshavant](https://github.com/joshavant).
- Providers/Anthropic: route Anthropic model refs selected with Claude CLI auth through the Claude CLI runtime so shorthand refs such as `anthropic/opus-4.7` no longer fall back to embedded Anthropic billing. Fixes [#&#8203;84222](openclaw/openclaw#84222). ([#&#8203;84374](openclaw/openclaw#84374)) Thanks [@&#8203;joshavant](https://github.com/joshavant).
- Agents: honor explicit `models.providers.<id>.timeoutSeconds` values above the default idle watchdog for cloud and self-hosted providers, so long first-token waits no longer fall back at \~120s when the provider timeout is higher. ([#&#8203;83979](openclaw/openclaw#83979)) Thanks [@&#8203;yujiawei](https://github.com/yujiawei).
- Agents/Codex: keep encrypted Responses reasoning replay provenance-bound so stale mirrored Codex transcripts drop invalid encrypted content before request assembly while preserving matching same-session replay. Fixes [#&#8203;83836](openclaw/openclaw#83836). ([#&#8203;84367](openclaw/openclaw#84367)) Thanks [@&#8203;joshavant](https://github.com/joshavant).
- Agents/subagents: skip stale embedded-run wake probes for dormant completion requesters, so late subagent completions go straight to requester-agent/direct handoff instead of producing `reason=no_active_run` queue noise. ([#&#8203;82964](openclaw/openclaw#82964)) Thanks [@&#8203;galiniliev](https://github.com/galiniliev).
- CLI: retry config snapshot reads after a transient failure so one rejected read no longer poisons later commands in the same process. ([#&#8203;83931](openclaw/openclaw#83931)) Thanks [@&#8203;honor2030](https://github.com/honor2030).
- Media: decode URL path basenames before using them as remote media fallback filenames, so files like `My%20Report.pdf` are surfaced as `My Report.pdf`. Fixes [#&#8203;84050](openclaw/openclaw#84050). ([#&#8203;84052](openclaw/openclaw#84052)) Thanks [@&#8203;jbetala7](https://github.com/jbetala7).
- WhatsApp: clarify inbound group diagnostics so observed but unregistered groups point to `channels.whatsapp.groups` without changing routing or sender authorization. ([#&#8203;83846](openclaw/openclaw#83846)) Thanks [@&#8203;neeravmakwana](https://github.com/neeravmakwana).
- WhatsApp: drain pending outbound deliveries on a 30s periodic timer in addition to the reconnect handler, so messages enqueued while the provider is already connected no longer wait for the next reconnect to send. ([#&#8203;79083](openclaw/openclaw#79083)) Thanks [@&#8203;Oviemudiaga](https://github.com/Oviemudiaga).
- CLI/TUI: include gateway plugin slash commands in TUI autocomplete, so connected sessions can suggest plugin-owned commands exposed by the running Gateway. ([#&#8203;83640](openclaw/openclaw#83640)) Thanks [@&#8203;se7en-agent](https://github.com/se7en-agent).
- Gateway/mobile: restore QR setup-code handoff of bounded operator tokens for iOS and Android onboarding while keeping admin and pairing scopes out of bootstrap. ([#&#8203;83684](openclaw/openclaw#83684)) Thanks [@&#8203;ngutman](https://github.com/ngutman).
- iOS: repair Release archive compilation for the TestFlight build. ([#&#8203;84255](openclaw/openclaw#84255)) Thanks [@&#8203;ngutman](https://github.com/ngutman).
- Agents/compaction: bound plugin-owned CLI transcript compaction with the host safety timeout so a hung context engine can no longer stall post-turn cleanup. ([#&#8203;84083](openclaw/openclaw#84083)) Thanks [@&#8203;100yenadmin](https://github.com/100yenadmin).
- Control UI/usage: truncate long context skill, tool, and file names in the usage panel while keeping the full name available on hover. ([#&#8203;42197](openclaw/openclaw#42197)) Thanks [@&#8203;Rain120](https://github.com/Rain120).
- Codex: respect explicit `models auth order set` and `config.auth.order` precedence over stale `lastGood` in `/codex account`, and show `no working credential` when every explicit-order profile is ineligible instead of marking a lower-ranked profile as active. Fixes [#&#8203;84386](openclaw/openclaw#84386). ([#&#8203;84412](openclaw/openclaw#84412)) Thanks [@&#8203;openperf](https://github.com/openperf).
- Agents: honor `messages.suppressToolErrors` for mutating tool failures so configured chat surfaces do not receive separate warning payloads. ([#&#8203;81561](openclaw/openclaw#81561)) Thanks [@&#8203;moeedahmed](https://github.com/moeedahmed).
- Agents/fallback: surface billing guidance for mixed rate-limit plus billing fallback exhaustion instead of generic failure copy. Fixes [#&#8203;79396](openclaw/openclaw#79396). ([#&#8203;79489](openclaw/openclaw#79489)) Thanks [@&#8203;aayushprsingh](https://github.com/aayushprsingh).

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these updates again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xMDEuMSIsInVwZGF0ZWRJblZlciI6IjQzLjEwMS4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJyZW5vdmF0ZS9jb250YWluZXIiLCJ0eXBlL3BhdGNoIl19-->

Reviewed-on: https://git.erwanleboucher.dev/eleboucher/homelab/pulls/615
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: whatsapp-web Channel integration: whatsapp-web clawsweeper:automerge Maintainer opted this PR into bounded ClawSweeper-reviewed automerge docs Improvements or additions to documentation P3 Low-priority cleanup, docs, polish, ergonomics, or speculative work. proof: override Maintainer override for the external PR real behavior proof gate. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. size: S status: 🚀 automerge armed This PR is in ClawSweeper's automerge lane.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Misleading log: Listening for personal WhatsApp inbound messages — group messages received but not routed

2 participants