Skip to content

fix(channels): detach provider + un-apply preset on channels remove#3672

Merged
ericksoa merged 12 commits into
mainfrom
fix/channels-remove-operation
May 18, 2026
Merged

fix(channels): detach provider + un-apply preset on channels remove#3672
ericksoa merged 12 commits into
mainfrom
fix/channels-remove-operation

Conversation

@hunglp6d

@hunglp6d hunglp6d commented May 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Make nemoclaw <sandbox> channels remove <channel> a clean inverse of channels add. Two asymmetries surfaced together on the same path: the bridge provider delete fails with FailedPrecondition against any live sandbox because the code never detached the provider first, and the channel-named policy preset is never un-applied even though channels add auto-applies it.

Related Issue

Fixes #3671

Changes

  • Detach before delete. applyChannelRemoveToGatewayAndRegistry now calls openshell sandbox provider detach <sandbox> <bridge> before openshell provider delete, matching how openshell enforces attachment as a precondition for delete. NotFound / NotAttached are treated as success-equivalent so the path stays idempotent across retries.
  • Surface gateway errors. Detach and delete failures now print the captured openshell stderr/stdout instead of the bare "Failed to delete bridge provider(s)" line, so operators can self-diagnose without re-running the underlying command manually.
  • Symmetric preset cleanup. New helper removeChannelPresetIfPresent mirrors the existing applyChannelPresetIfAvailable. removeSandboxChannel un-applies the channel-named policy preset after the bridge is gone, so the L7 proxy stops allow-listing its upstream API (defense-in-depth — bridge is gone, egress to api.telegram.org should follow). Warns but does not abort if the un-apply fails; bridge teardown is already committed by then.

Type of Change

  • Code change (feature, bug fix, or refactor)
  • Code change with doc updates
  • Doc only (prose changes, no code sample modifications)
  • Doc only (includes code sample changes)

Verification

  • npx prek run --all-files passes
  • npm test passes
  • Tests added or updated for new or changed behavior
  • No secrets, API keys, or credentials committed
  • Docs updated for user-facing behavior changes
  • make docs builds without warnings (doc changes only)
  • Doc pages follow the style guide (doc changes only)
  • New doc pages include SPDX header and frontmatter (new pages only)

Signed-off-by: Hung Le hple@nvidia.com

Summary by CodeRabbit

  • Bug Fixes

    • Ensure bridge providers are detached during live channel removal; aborts if detach cannot complete
    • Provider deletion failures now record detailed diagnostics; “not found” treated as success-equivalent
    • Built-in policy presets matching removed channels are automatically un-applied
    • Onboarding resume now preserves an explicit empty channel set (returns [] instead of null)
  • Tests

    • E2E expanded to multi-provider channel stop/start/remove lifecycle with rebuild and cleanup assertions; timeouts increased
  • Chores

    • Updated parity inventory/map entries to reflect test changes and deferred legacy assertions

Review Change Stack

@copy-pr-bot

copy-pr-bot Bot commented May 18, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@coderabbitai

coderabbitai Bot commented May 18, 2026

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

applyChannelRemoveToGatewayAndRegistry detaches bridge providers before deletion and captures structured detach/delete failures; removeSandboxChannel un-applies a matching built-in policy preset when present; E2E tests and CI job expanded to exercise stop/start/remove lifecycles across agents and messaging channels; onboarding now returns [] instead of null for an explicit empty resume channel set.

Changes

Channel Removal Flow Improvements

Layer / File(s) Summary
Provider detach and deletion with error reporting
src/lib/actions/sandbox/policy-channel.ts
applyChannelRemoveToGatewayAndRegistry adds a pre-delete detach phase that runs openshell sandbox provider detach for bridge providers, collects detach failures excluding "NotFound"/"not attached" and aborts before provider deletion or registry updates if detach fails. Provider deletion failures are collected as structured {name, output} records and logged before aborting registry updates.
Policy preset un-apply integration
src/lib/actions/sandbox/policy-channel.ts
New removeChannelPresetIfPresent(sandboxName, channelName) checks whether channelName is a built-in preset and currently applied; if so, it calls policies.removePreset and logs warnings on failure without aborting. Integrated into removeSandboxChannel after provider removal.
E2E script: helpers, env, assertions
test/e2e/test-channels-stop-start.sh
Refactor into multi-agent lifecycle test with reusable helpers (sandbox ops, openshell wrapper, registry inspection, provider/channel mapping, fake env export, rebuild plumbing), add pass/fail helpers, and increase default timeout.
E2E lifecycle orchestration and live remove checks
test/e2e/test-channels-stop-start.sh
Add generic stop/start/remove helpers and orchestrator that runs baseline, stop+rebuild, start+rebuild, remove+rebuild for OpenClaw and Hermes. Live remove asserts rebuild queued, provider deletion, registry/messagingChannels/credential-hash removal, and policy preset deactivation; post-rebuild asserts channel absence persisted.
CI job and parity docs
.github/workflows/nightly-e2e.yaml, test/e2e/docs/parity-inventory.generated.json, test/e2e/docs/parity-map.yaml
Expand nightly job env with Discord/Slack/WeChat fake credentials and broaden artifact uploads; update parity inventory/map to clear legacy assertions for the consolidated test entry and adjust totals.
Onboard resume empty-set behavior
src/lib/onboard/messaging-reuse.ts, src/lib/onboard/messaging-reuse.test.ts
getNonInteractiveStoredMessagingChannels now returns [] when the stored resume channel set is explicitly empty; tests updated to assert empty-array semantics instead of null.

Possibly related issues

  • #3462 — Changes implement detach-before-delete and preset un-apply behavior that matches the lifecycle and policy/registry state expectations exercised by the added E2E tests.

Possibly Related PRs

  • NVIDIA/NemoClaw#3452: Applies builtin channel presets on channels add, complementary to this PR's un-apply on channels remove.
  • NVIDIA/NemoClaw#3512: Introduces WeChat provider and preset which will exercise the updated remove/detach/preset logic.
  • NVIDIA/NemoClaw#3445: Related to non-interactive messaging resume behavior; both PRs change how empty resume sets are handled.

Suggested labels

enhancement: messaging

Suggested Reviewers

  • cv
  • ericksoa
  • jyaunches

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 I nudged a bridge loose and plucked a preset free,

telegram slipped out the gate and logs sang quietly.
Tests hopped in to chase the crumbs and check the lawn,
rebuilds queued, registries cleaned, the sandbox greeted dawn.
A rabbit's tidy fix — detached, deleted, done.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.89% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: implementing detach and preset un-apply during channels remove operation.
Linked Issues check ✅ Passed The PR comprehensively addresses all five coding requirements from issue #3671: detach before delete, delete provider, update registry, un-apply preset, and surface OpenShell errors.
Out of Scope Changes check ✅ Passed All changes directly support the linked issue objectives: policy-channel refactor for detach/un-apply, E2E test expansion for coverage, test helper updates, and workflow adjustments.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/channels-remove-operation

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented May 18, 2026

Copy link
Copy Markdown
Contributor

E2E Advisor Recommendation

Required E2E: channels-stop-start-e2e
Optional E2E: messaging-providers-e2e, onboard-resume-e2e, network-policy-e2e

Dispatch hint: channels-stop-start-e2e

Auto-dispatched E2E: channels-stop-start-e2e via nightly-e2e.yaml at f86f13d9db7b0aa328219227f8a78ce8fb9c11ffnightly run

Workflow run

Full advisor summary

E2E Recommendation Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E

  • channels-stop-start-e2e (high; timeout 120 minutes): Direct regression gate for this PR: exercises messaging channel stop/start/remove on live sandboxes, provider detach/delete, registry channel and credential-hash cleanup, policy preset removal, and rebuild behavior with token env vars still present across OpenClaw and Hermes.

Optional E2E

  • messaging-providers-e2e (medium; timeout 45 minutes): Useful adjacent confidence for the messaging provider/placeholder/L7-proxy chain after changes to channel provider naming, credential hashes, and messaging channel state. It does not exercise live remove, so it is optional rather than the primary gate.
  • onboard-resume-e2e (medium; timeout 60 minutes): Broad resume/onboarding sanity check for changes in non-interactive messaging reuse semantics. Existing coverage does not explicitly assert messaging sessionChannels=[] behavior, so keep as optional and track missing coverage separately.
  • network-policy-e2e (medium; timeout 45 minutes): Adjacent security-boundary confidence because channel removal now un-applies policy presets and should not leave stale egress allow-lists. The required channels test checks channel preset inactivity, while this broader policy suite validates general policy hot-reload/deny-by-default behavior.

New E2E recommendations

  • onboarding resume with messaging channels (high): No existing E2E explicitly creates an interrupted onboard/resume session with sessionChannels: [] while messaging token env vars are still present, then asserts resume does not rediscover or re-enable token-backed channels.
    • Suggested test: Add a messaging-specific onboard resume E2E that records an explicit empty messaging channel set, resumes non-interactively with TELEGRAM/DISCORD/SLACK/WECHAT token env vars present, and verifies registry plus agent config remain channel-free.
  • scenario-framework parity for dynamic channels assertions (medium): The expanded test-channels-stop-start.sh now emits dynamic PASS/FAIL assertions and parity metadata marks the script as zero-assertion. Migrating this flow would make assertion inventory and selective coverage more reliable.
    • Suggested test: Migrate channels stop/start/remove lifecycle coverage into scenario-framework cases with static assertion IDs for OpenClaw/Hermes and telegram/discord/wechat/slack.

Dispatch hint

  • Workflow: .github/workflows/nightly-e2e.yaml
  • jobs input: channels-stop-start-e2e

@hunglp6d hunglp6d self-assigned this May 18, 2026
@hunglp6d hunglp6d added E2E VRDC Issues and PRs submitted by NVIDIA VRDC test team. labels May 18, 2026
@hunglp6d hunglp6d marked this pull request as ready for review May 18, 2026 02:48
@github-actions

Copy link
Copy Markdown
Contributor

Selective E2E Results — ✅ All requested jobs passed

Run: 26010869634
Target ref: e02eae6aaa1f269e1af3a7a70eb7d129f53bad06
Workflow ref: main
Requested jobs: channels-stop-start-e2e,messaging-providers-e2e,network-policy-e2e
Summary: 3 passed, 0 failed, 0 skipped

Job Result
channels-stop-start-e2e ✅ success
messaging-providers-e2e ✅ success
network-policy-e2e ✅ success

@github-actions

Copy link
Copy Markdown
Contributor

Selective E2E Results — ✅ All requested jobs passed

Run: 26014243607
Target ref: b6d126b944c36cbd1ef078ef0624446bfb35a9a8
Workflow ref: main
Requested jobs: channels-stop-start-e2e
Summary: 0 passed, 0 failed, 0 skipped

Job Result
channels-stop-start-e2e ⚠️ cancelled

@coderabbitai coderabbitai Bot left a comment

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.

🧹 Nitpick comments (1)
test/e2e/test-channels-stop-start.sh (1)

436-447: ⚡ Quick win

Reduce brittle coupling to human-readable CLI text in assertions.

C7a/C7b/C7f depend on exact output phrases; that can fail on wording changes even when behavior is correct. Prefer exit-code + state-based checks (you already have strong state validation in C7c–C8c).

Proposed hardening
-if [ "$remove_rc" -eq 0 ] && grep -q "Removed telegram bridge" /tmp/nc-remove.log; then
+if [ "$remove_rc" -eq 0 ]; then
   pass "C7a: channels remove telegram completed on a live sandbox"
 else
   fail "C7a: channels remove telegram failed"
   tail -30 /tmp/nc-remove.log 2>/dev/null || true
 fi

-if grep -q "Change queued.*remove 'telegram'" /tmp/nc-remove.log; then
-  pass "C7b: channels remove queued rebuild"
-else
-  fail "C7b: channels remove did not queue a rebuild"
-fi
+pass "C7b: rebuild requirement validated by Phase 8 post-remove rebuild checks"

 if nemoclaw "$SANDBOX_NAME" policy-list >/tmp/nc-policy-list-after-remove.log 2>&1; then
   if grep -q "● telegram" /tmp/nc-policy-list-after-remove.log; then
     fail "C7f: telegram policy preset still active after channels remove"
     grep "telegram" /tmp/nc-policy-list-after-remove.log | head -5 || true
-  elif grep -q "telegram" /tmp/nc-policy-list-after-remove.log; then
-    pass "C7f: telegram policy preset no longer active after channels remove"
   else
-    fail "C7f: policy-list did not include telegram preset status"
-    tail -30 /tmp/nc-policy-list-after-remove.log 2>/dev/null || true
+    pass "C7f: telegram policy preset not active after channels remove"
   fi
 else
   fail "C7f: policy-list failed after channels remove"
   tail -30 /tmp/nc-policy-list-after-remove.log 2>/dev/null || true
 fi

Also applies to: 471-480

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/e2e/test-channels-stop-start.sh` around lines 436 - 447, Replace brittle
greps against human-readable CLI text in the C7a/C7b assertions: instead of
checking for exact log phrases in /tmp/nc-remove.log, assert success via the
command exit code (remove_rc == 0) and verify the actual system state or API
(e.g., confirm the telegram channel is absent via the same state-checks used in
C7c–C8c or query the service to ensure the removal and that a rebuild task is
queued) so update the test to use remove_rc and the existing state-validation
functions/commands rather than grep "Removed telegram bridge" or "Change
queued.*remove 'telegram'".
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@test/e2e/test-channels-stop-start.sh`:
- Around line 436-447: Replace brittle greps against human-readable CLI text in
the C7a/C7b assertions: instead of checking for exact log phrases in
/tmp/nc-remove.log, assert success via the command exit code (remove_rc == 0)
and verify the actual system state or API (e.g., confirm the telegram channel is
absent via the same state-checks used in C7c–C8c or query the service to ensure
the removal and that a rebuild task is queued) so update the test to use
remove_rc and the existing state-validation functions/commands rather than grep
"Removed telegram bridge" or "Change queued.*remove 'telegram'".

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 109560e1-fafb-4a00-9521-a304a071c6cb

📥 Commits

Reviewing files that changed from the base of the PR and between e02eae6 and b6d126b.

📒 Files selected for processing (1)
  • test/e2e/test-channels-stop-start.sh

@github-actions

Copy link
Copy Markdown
Contributor

Selective E2E Results — ✅ All requested jobs passed

Run: 26014257036
Target ref: b6d126b944c36cbd1ef078ef0624446bfb35a9a8
Workflow ref: main
Requested jobs: channels-stop-start-e2e
Summary: 0 passed, 0 failed, 0 skipped

Job Result
channels-stop-start-e2e ⚠️ cancelled

@github-actions

Copy link
Copy Markdown
Contributor

Selective E2E Results — ✅ All requested jobs passed

Run: 26014800525
Target ref: c76aa3f32deb803d6b0b82cb686a7caa4718aec3
Workflow ref: main
Requested jobs: channels-stop-start-e2e
Summary: 0 passed, 0 failed, 0 skipped

Job Result
channels-stop-start-e2e ⚠️ cancelled

@github-actions

Copy link
Copy Markdown
Contributor

Selective E2E Results — ❌ Some jobs failed

Run: 26015011736
Target ref: e622d1aab62a71b94ec3907b0abf0cac0718c9b9
Workflow ref: main
Requested jobs: channels-stop-start-e2e
Summary: 0 passed, 1 failed, 0 skipped

Job Result
channels-stop-start-e2e ❌ failure

Failed jobs: channels-stop-start-e2e. Check run artifacts for logs.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
test/e2e/test-channels-stop-start.sh (1)

237-266: 💤 Low value

Consider extracting repeated grep patterns into variables.

The channel_presence() function contains multiple similar grep patterns (lines 246, 249, 252, 255). Extracting these as variables would improve maintainability.

Example refactor
 channel_presence() {
   local channel="$1"
   local out
   if [ "$ACTIVE_AGENT" = "openclaw" ]; then
     out=$(sandbox_exec "python3 -c 'import json,sys; d=json.load(open(\"/sandbox/.openclaw/openclaw.json\")); print(\"yes\" if sys.argv[1] in d.get(\"channels\", {}) else \"no\")' '$channel'" | tail -1) || true
   else
-    local probe
+    local probe_telegram='grep -Eq "^TELEGRAM_BOT_TOKEN=openshell:resolve:env:TELEGRAM_BOT_TOKEN$" /sandbox/.hermes/.env'
+    local probe_discord='grep -Eq "^DISCORD_BOT_TOKEN=openshell:resolve:env:DISCORD_BOT_TOKEN$" /sandbox/.hermes/.env'
+    local probe_wechat='grep -Eq "^WEIXIN_TOKEN=openshell:resolve:env:WECHAT_BOT_TOKEN$" /sandbox/.hermes/.env'
+    local probe_slack='grep -Eq "^SLACK_BOT_TOKEN=xoxb-OPENSHELL-RESOLVE-ENV-SLACK_BOT_TOKEN$" /sandbox/.hermes/.env && grep -Eq "^SLACK_APP_TOKEN=xapp-OPENSHELL-RESOLVE-ENV-SLACK_APP_TOKEN$" /sandbox/.hermes/.env'
+    local probe
     case "$channel" in
-      telegram)
-        probe='grep -Eq "^TELEGRAM_BOT_TOKEN=openshell:resolve:env:TELEGRAM_BOT_TOKEN$" /sandbox/.hermes/.env'
-        ;;
+      telegram) probe="$probe_telegram" ;;
+      discord) probe="$probe_discord" ;;
+      wechat) probe="$probe_wechat" ;;
+      slack) probe="$probe_slack" ;;
-      discord)
-        probe='grep -Eq "^DISCORD_BOT_TOKEN=openshell:resolve:env:DISCORD_BOT_TOKEN$" /sandbox/.hermes/.env'
-        ;;
-      wechat)
-        probe='grep -Eq "^WEIXIN_TOKEN=openshell:resolve:env:WECHAT_BOT_TOKEN$" /sandbox/.hermes/.env'
-        ;;
-      slack)
-        probe='grep -Eq "^SLACK_BOT_TOKEN=xoxb-OPENSHELL-RESOLVE-ENV-SLACK_BOT_TOKEN$" /sandbox/.hermes/.env && grep -Eq "^SLACK_APP_TOKEN=xapp-OPENSHELL-RESOLVE-ENV-SLACK_APP_TOKEN$" /sandbox/.hermes/.env'
-        ;;
     esac
     out=$(sandbox_exec "if [ -r /sandbox/.hermes/.env ]; then if ${probe}; then echo yes; else echo no; fi; else echo missing; fi" | tail -1) || true
   fi
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/e2e/test-channels-stop-start.sh` around lines 237 - 266, The
channel_presence() function repeats nearly identical grep patterns for each
channel; refactor by defining reusable pattern variables (e.g.,
base_env="/sandbox/.hermes/.env", telegram_pat, discord_pat, wechat_pat,
slack_pat) or a single template and then assign probe to that variable inside
each case (cases: telegram, discord, wechat, slack) so sandbox_exec uses the
probe variable as before; update the slack case to combine the two slack
patterns into a single probe variable as well and keep the remaining logic
(sandbox_exec call and out handling) unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/e2e/test-channels-stop-start.sh`:
- Around line 64-73: Remove the duplicate helper functions pass_msg() and
fail_msg() and consolidate to use the existing pass() and fail() helpers
instead: delete the pass_msg and fail_msg function definitions (which are exact
copies of pass and fail) and replace all calls to pass_msg with pass and
fail_msg with fail throughout the script (e.g., the occurrences noted around
lines 291, 294, 297, 310, 313, 316). Ensure the PASS/FAIL/TOTAL counters and
formatting remain handled by the original pass() and fail() functions.

---

Nitpick comments:
In `@test/e2e/test-channels-stop-start.sh`:
- Around line 237-266: The channel_presence() function repeats nearly identical
grep patterns for each channel; refactor by defining reusable pattern variables
(e.g., base_env="/sandbox/.hermes/.env", telegram_pat, discord_pat, wechat_pat,
slack_pat) or a single template and then assign probe to that variable inside
each case (cases: telegram, discord, wechat, slack) so sandbox_exec uses the
probe variable as before; update the slack case to combine the two slack
patterns into a single probe variable as well and keep the remaining logic
(sandbox_exec call and out handling) unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 7817fe34-032c-4ab6-8077-4b740245b1ed

📥 Commits

Reviewing files that changed from the base of the PR and between e622d1a and 7948ec9.

📒 Files selected for processing (6)
  • .github/workflows/nightly-e2e.yaml
  • src/lib/onboard/messaging-reuse.test.ts
  • src/lib/onboard/messaging-reuse.ts
  • test/e2e/docs/parity-inventory.generated.json
  • test/e2e/docs/parity-map.yaml
  • test/e2e/test-channels-stop-start.sh

Comment on lines +64 to +73
pass_msg() {
((PASS++))
((TOTAL++))
printf '\033[32m PASS: %s\033[0m\n' "$1"
}
fail_msg() {
((FAIL++))
((TOTAL++))
printf '\033[31m FAIL: %s\033[0m\n' "$1"
}

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.

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Eliminate duplicate helper functions.

pass_msg() and fail_msg() (lines 64–73) are exact duplicates of pass() and fail() (lines 44–53). This violates DRY and creates maintenance overhead.

♻️ Refactor to remove duplicates

Remove the duplicate functions and use the original pass() and fail() throughout the script:

-pass_msg() {
-  ((PASS++))
-  ((TOTAL++))
-  printf '\033[32m  PASS: %s\033[0m\n' "$1"
-}
-fail_msg() {
-  ((FAIL++))
-  ((TOTAL++))
-  printf '\033[31m  FAIL: %s\033[0m\n' "$1"
-}
-

Then replace all calls to pass_msg with pass and fail_msg with fail throughout the file (lines 291, 294, 297, 310, 313, 316, etc.).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/e2e/test-channels-stop-start.sh` around lines 64 - 73, Remove the
duplicate helper functions pass_msg() and fail_msg() and consolidate to use the
existing pass() and fail() helpers instead: delete the pass_msg and fail_msg
function definitions (which are exact copies of pass and fail) and replace all
calls to pass_msg with pass and fail_msg with fail throughout the script (e.g.,
the occurrences noted around lines 291, 294, 297, 310, 313, 316). Ensure the
PASS/FAIL/TOTAL counters and formatting remain handled by the original pass()
and fail() functions.

@github-actions

Copy link
Copy Markdown
Contributor

Selective E2E Results — ❌ Some jobs failed

Run: 26019980084
Target ref: 7948ec943b030eacceba684c0da4e290302cbeb0
Workflow ref: fix/channels-remove-operation
Requested jobs: channels-stop-start-e2e
Summary: 0 passed, 1 failed, 0 skipped

Job Result
channels-stop-start-e2e ❌ failure

Failed jobs: channels-stop-start-e2e. Check run artifacts for logs.

@github-actions

Copy link
Copy Markdown
Contributor

Selective E2E Results — ❌ Some jobs failed

Run: 26020026934
Target ref: 7948ec943b030eacceba684c0da4e290302cbeb0
Workflow ref: main
Requested jobs: channels-stop-start-e2e,onboard-resume-e2e
Summary: 1 passed, 1 failed, 0 skipped

Job Result
channels-stop-start-e2e ❌ failure
onboard-resume-e2e ✅ success

Failed jobs: channels-stop-start-e2e. Check run artifacts for logs.

@github-actions

Copy link
Copy Markdown
Contributor

Selective E2E Results — ❌ Some jobs failed

Run: 26030365203
Target ref: fix/channels-remove-operation
Requested jobs: channels-stop-start-e2e,onboard-resume-e2e
Summary: 1 passed, 1 failed, 0 skipped

Job Result
channels-stop-start-e2e ❌ failure
onboard-resume-e2e ✅ success

Failed jobs: channels-stop-start-e2e. Check run artifacts for logs.

@github-actions

Copy link
Copy Markdown
Contributor

Selective E2E Results — ✅ All requested jobs passed

Run: 26034610108
Target ref: f86f13d9db7b0aa328219227f8a78ce8fb9c11ff
Workflow ref: fix/channels-remove-operation
Requested jobs: channels-stop-start-e2e
Summary: 1 passed, 0 failed, 0 skipped

Job Result
channels-stop-start-e2e ✅ success

@github-actions

Copy link
Copy Markdown
Contributor

Selective E2E Results — ✅ All requested jobs passed

Run: 26034693378
Target ref: f86f13d9db7b0aa328219227f8a78ce8fb9c11ff
Workflow ref: main
Requested jobs: channels-stop-start-e2e
Summary: 1 passed, 0 failed, 0 skipped

Job Result
channels-stop-start-e2e ✅ success

@ericksoa ericksoa left a comment

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.

Approved after the focused channels lifecycle nightly passed on head f86f13d.

Validation: channels-stop-start-e2e passed in https://github.com/NVIDIA/NemoClaw/actions/runs/26034610108. The job covered both OpenClaw and Hermes across telegram, discord, wechat, and slack, including stop/start/remove plus rebuild verification.

@ericksoa ericksoa merged commit d7bae57 into main May 18, 2026
63 checks passed
ericksoa pushed a commit that referenced this pull request May 18, 2026
## Summary
Updates the NemoClaw documentation for the v0.0.45 release by
summarizing the user-facing changes merged since v0.0.44 and bumping the
docs version metadata.
Refreshes generated user skills so agent-facing references match the
source docs.

## Changes
- Added v0.0.45 release notes covering onboarding recovery, local
inference, channel cleanup, share mount diagnostics, uninstall cleanup,
and security redaction updates.
- Updated command and troubleshooting docs for sandbox name limits, GPU
gateway reuse, DNS preflight behavior, channel removal cleanup, and
share mount path validation.
- Bumped docs version metadata to 0.0.45 and regenerated NemoClaw user
skills from the docs.
- Source summary: #3672 -> `docs/reference/commands.md`: documented
channel removal detaching bridge providers and un-applying channel
policy presets.
- Source summary: #3678 -> `docs/about/release-notes.md`: documented
Ollama streamed usage accounting in the release notes.
- Source summary: #3670 -> `docs/reference/commands.md`,
`docs/reference/troubleshooting.md`: documented safe GPU gateway
replacement behavior.
- Source summary: #3664 -> `docs/about/release-notes.md`: documented
blueprint permission normalization in the release notes.
- Source summary: #3181 -> `docs/reference/troubleshooting.md`:
documented GPU toolkit guidance when host drivers work but passthrough
is disabled.
- Source summary: #3554 -> `docs/about/release-notes.md`: documented
host `openshell-gateway` cleanup during uninstall.
- Source summary: #3651 -> `docs/reference/troubleshooting.md`:
documented the uncached `.invalid` DNS preflight probe.
- Source summary: #3643 -> `docs/reference/commands.md`: included
existing `NEMOCLAW_PROVIDER` interactive-mode behavior in generated
docs.
- Source summary: #3647 -> `docs/reference/commands.md`: documented
remote sandbox path verification for `share mount`.
- Source summary: #3646 -> `docs/reference/commands.md`: included
existing local writable mount target guidance in generated docs.
- Source summary: #3642 -> `docs/inference/use-local-inference.md`,
`docs/reference/commands.md`: documented managed-vLLM model override and
gated-model token checks.
- Source summary: #3639 -> `docs/reference/commands.md`: documented the
63-character sandbox name limit.

## Type of Change
- [ ] Code change (feature, bug fix, or refactor)
- [ ] Code change with doc updates
- [ ] Doc only (prose changes, no code sample modifications)
- [x] Doc only (includes code sample changes)

## Verification
- [ ] `npx prek run --all-files` passes
- [ ] `npm test` passes
- [ ] Tests added or updated for new or changed behavior
- [x] No secrets, API keys, or credentials committed
- [x] Docs updated for user-facing behavior changes
- [x] `make docs` builds without warnings (doc changes only)
- [x] Doc pages follow the [style
guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md)
(doc changes only)
- [ ] New doc pages include SPDX header and frontmatter (new pages only)

Commit hooks passed for the staged files. A standalone `npx prek run
--all-files` attempt was blocked by sandbox access to
`/Users/miyoungc/.cache/prek/prek.log`, so that checkbox is left
unchecked.

---
<!-- DCO sign-off required by CI. Run: git config user.name && git
config user.email -->
Signed-off-by: Miyoung Choi <miyoungc@nvidia.com>

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Documentation**
* Enhanced CLI command reference documentation with clearer guidance on
onboarding, GPU passthrough, inference configuration, channel removal,
and shared mounts.
* Improved troubleshooting sections with better DNS resolution and GPU
passthrough remediation steps.
  * Added documentation for overriding managed vLLM model selection.
* Updated release notes for v0.0.45 reflecting infrastructure and
workflow improvements.

* **Version Bump**
  * Released v0.0.45.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/NVIDIA/NemoClaw/pull/3755?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 -->
ericksoa pushed a commit that referenced this pull request May 20, 2026
<!-- markdownlint-disable MD041 -->
## Summary
Add Test 2 from #3462 — end-to-end coverage for the `onboard empty →
channels add → channels remove` lifecycle. The test asserts against the
baked sandbox image (`openclaw.json`) and the gateway (provider
attachment, policy presets) so regressions cannot hide behind a correct
host-side registry. Companion to Test 1 (`test-channels-stop-start.sh`)
shipped via #3532.

## Related Issue
Closes #3462

## Changes
- New script `test/e2e/test-channels-add-remove.sh` covering Test 2 spec
from #3462:
- **Phase 1**: install + onboard with no messaging channel; verifies
baseline is clean (no bridge provider, no `telegram` in `openclaw.json`,
no telegram preset applied).
- **Phase 3 + 4**: `channels add telegram` + rebuild; asserts the
matching preset auto-applied (#3437 regression gate), bridge provider
exists, `openclaw.json` contains the channel, and the L7 proxy lets
bridge-style traffic through to `api.telegram.org`.
- **Phase 5 + 6**: `channels remove telegram` + rebuild; asserts the
bridge is gone from `openclaw.json`, provider deleted from the gateway,
and the matching preset un-applied (#3671 regression gate for the
detach+delete + symmetric cleanup fix shipped in #3672).
- Egress probe (`telegram_egress_open`) uses `node -e fetch` against a
`/bot*/...` path so it matches the telegram preset's binary + path
scoping. A naïve `curl /` probe would trip both guards and produce a
misleading 403, hiding real regressions.
- Helper `print_policy_list` snapshots the gateway's policy-list output
before every `policy_list_has_preset` assertion so the test transcript
records the actual gateway state alongside each pass/fail line.

## Type of Change
- [x] Code change (feature, bug fix, or refactor)
- [ ] Code change with doc updates
- [ ] Doc only (prose changes, no code sample modifications)
- [ ] Doc only (includes code sample changes)

## Verification
<!-- Check each item you ran and confirmed. Leave unchecked items you
skipped. Doc-only changes do not require npm test unless you ran it. -->
- [ ] `npx prek run --all-files` passes
- [ ] `npm test` passes
- [ ] Tests added or updated for new or changed behavior
- [ ] No secrets, API keys, or credentials committed
- [ ] Docs updated for user-facing behavior changes
- [ ] `make docs` builds without warnings (doc changes only)
- [ ] Doc pages follow the [style
guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md)
(doc changes only)
- [ ] New doc pages include SPDX header and frontmatter (new pages only)

---
<!-- DCO sign-off required by CI. Run: git config user.name && git
config user.email -->
Signed-off-by: Hung Le <hple@nvidia.com>


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Tests**
* Added E2E test covering full add/remove lifecycle for the Telegram
messaging channel with environment prechecks, sandbox setup/teardown,
baseline absence checks, add+rebuild and remove+rebuild verification,
policy/preset/config assertions, and live egress probing through the L7
proxy.

* **Documentation**
* Added parity-map and generated test documentation entries describing
the new Telegram add/remove scenario and its assertions.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/NVIDIA/NemoClaw/pull/3696?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 -->
@wscurran wscurran added area: e2e End-to-end tests, nightly failures, or validation infrastructure bug-fix PR fixes a bug or regression and removed fix labels Jun 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: e2e End-to-end tests, nightly failures, or validation infrastructure bug-fix PR fixes a bug or regression VRDC Issues and PRs submitted by NVIDIA VRDC test team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Channels] channels remove <ch> fails on a live sandbox and leaves the channel's policy preset applied

3 participants