…ter rebuild (#4403)
## Summary
Fixes #4314
Fixes #4390
This is now the unified messaging-channel PR: it keeps the original
#4403 runtime verification path and folds in the full #4400 OpenClaw
channel activation / plugin-build / E2E coverage set.
OpenClaw 2026.5.22+ no longer auto-starts a messaging bridge from the
account-level `enabled` flag alone — the channel must also be marked
enabled at the top level for the bridge module to load. NemoClaw#4189
fixed this for Slack (PR #4222); the same gap silently produced "no
Telegram process / no logs" for Telegram (#4314, #4390) and would
silently break Discord too.
This PR:
- Bakes `channels.<name>.enabled: true` for Telegram, Discord, Slack,
and WhatsApp in generated `openclaw.json`.
- Enables matching `plugins.entries.<channel>` records so OpenClaw
discovers selected messaging providers through its real channel/plugin
path.
- Pins external OpenClaw messaging plugins at image build time with
`scripts/openclaw-build-messaging-plugins.py` instead of relying on
unversioned `openclaw doctor --fix` catalog drift.
- Adds a gated Telegram startup-grace diagnostic breadcrumb when the
bridge fails to log startup within the grace window.
- Adds a post-rebuild runtime check to `nemoclaw <sandbox> channels add
<channel>` for verifiable OpenClaw channels (telegram/discord/slack),
surfacing missing enabled flags, missing startup breadcrumbs, and
credential/startup warnings.
- Extends messaging-provider E2E coverage with generated activation
checks, `openclaw channels list --all --json` runtime discovery checks,
pinned plugin build coverage, fake provider APIs, and optional live
Telegram/Discord/Slack `openclaw message send` paths when repository
secrets are configured.
- Keeps WeChat out of upfront generated channel config; WeChat remains
on the existing late seed path after plugin install.
## Reproduction (issue #4390 + #4314)
Before the fix, generated config with Telegram selected during
onboarding:
```json
"channels": { "telegram": { "accounts": { "default": { ... } } } }
```
No top-level `enabled: true` meant OpenClaw skipped loading the bridge.
No Telegram process spawned, `/sandbox/.openclaw/telegram/` stayed
empty, and no startup/error breadcrumb appeared.
After the fix:
```json
"channels": { "telegram": { "enabled": true, "accounts": { "default": { ..., "enabled": true } } } }
```
The bridge module is loadable, diagnostics can report silent startup
failure, and `channels add telegram` probes the rebuilt runtime instead
of leaving users with radio silence.
## Test plan
Local validation on the unified branch:
- [x] `python3 -m py_compile scripts/generate-openclaw-config.py
scripts/openclaw-build-messaging-plugins.py`
- [x] `NEMOCLAW_MESSAGING_CHANNELS_B64=$(printf '%s'
'["telegram","discord","slack","whatsapp"]' | base64 | tr -d '\n')
OPENCLAW_VERSION=2026.5.22 python3
scripts/openclaw-build-messaging-plugins.py --dry-run`
- [x] `bash -n test/e2e/test-messaging-providers.sh
test/e2e/lib/discord-rest-policy-proof.sh
test/e2e/lib/slack-api-proof.sh test/e2e/lib/telegram-api-proof.sh`
- [x] `git diff --check HEAD~1..HEAD`
- [x] `npm ci --ignore-scripts`
- [x] `npm run build:cli`
- [x] `npx vitest run test/generate-openclaw-config.test.ts
test/openclaw-build-messaging-plugins.test.ts
test/sandbox-build-context.test.ts test/sandbox-provisioning.test.ts
test/channels-add-preset.test.ts test/telegram-diagnostics.test.ts
test/e2e-script-workflow.test.ts test/validate-e2e-coverage.test.ts` —
160 passed
Live Telegram bot E2E was not run from the local triage worktree because
no Telegram bot credential is available locally; the PR wires optional
live repository secrets through the nightly reusable workflow and keeps
hermetic fake-provider proofs for CI.
## DCO
```
Signed-off-by: Yimo Jiang <yimoj@nvidia.com>
```
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Startup watchdog emits a single breadcrumb when an OpenClaw gateway
bridge fails to start within a configurable grace period.
* Post-channel-add now verifies bridged channels after a rebuild.
* Image/sandbox build now includes a messaging-plugin installer to
pin/install provider plugins.
* **Bug Fixes**
* Ensure channels, accounts, and plugin entries are marked enabled so
bridges activate reliably.
* **Tests**
* Expanded regression/E2E coverage with fake provider APIs, startup
diagnostics, and live-credential wiring for Telegram/Discord/Slack.
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/NVIDIA/NemoClaw/pull/4403?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)
<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Signed-off-by: Yimo Jiang <yimoj@nvidia.com>
Co-authored-by: Aaron Erickson <aerickson@nvidia.com>
Summary
openclaw.jsonfor Telegram, Discord, Slack, and WhatsApp.plugins.entries.<channel>records so OpenClaw discovers selected messaging providers through its real channel/plugin path.test/e2e/test-messaging-providers.shto verify both generated activation andopenclaw channels list --all --jsonruntime discovery for Telegram, Discord, Slack, and WhatsApp.Refs #4251
Test Plan
python3 -m py_compile scripts/generate-openclaw-config.pygit diff --checkbash -n test/e2e/test-messaging-providers.shnpm test -- test/generate-openclaw-config.test.tsnpm test -- test/nemoclaw-start.test.tsnpm test -- test/seed-wechat-accounts.test.tsnpm test -- test/onboard-messaging.test.ts -t "non-interactive setupMessagingChannels returns channels with tokens|setupSelectedMessagingChannels|wechat|whatsapp"npm test -- test/validate-e2e-coverage.test.ts test/e2e-scenario/framework-tests/e2e-coverage-report.test.tsnpm run build:cliSummary by CodeRabbit
Tests
Chores