Skip to content

fix(onboard): detach sandbox providers before rebuild deletes the sandbox#4943

Merged
cv merged 8 commits into
mainfrom
fix/4890-rebuild-detach-providers
Jun 8, 2026
Merged

fix(onboard): detach sandbox providers before rebuild deletes the sandbox#4943
cv merged 8 commits into
mainfrom
fix/4890-rebuild-detach-providers

Conversation

@laitingsheng
Copy link
Copy Markdown
Contributor

@laitingsheng laitingsheng commented Jun 8, 2026

Summary

nemoclaw onboard rebuilds (and nemoclaw <name> destroy) tore down the sandbox without first detaching its attached messaging and search providers, so the immediately-following provider delete (driven by either the destroy cleanup loop or upsertMessagingProviders({replaceExisting: true}) on rebuild) hit FailedPrecondition: provider '<name>' is attached to sandbox(es): <sandbox> and the per-failure process.exit(1) aborted onboard. The same orphan-attachment also broke onboard --resume when the previous sandbox had been pruned out from under NemoClaw.

This PR adds an explicit sandbox provider detach pass over the shared per-sandbox provider suffix set before every destructive lifecycle step, recovers from any residual FailedPrecondition by parsing the attached-sandbox list out of the diagnostic and forcing a per-sandbox detach + retry, and surfaces destroy-time residuals with a manual cleanup hint.

Related Issue

Fixes #4890

Changes

  • New src/lib/onboard/sandbox-provider-cleanup.ts:
    • SANDBOX_PROVIDER_SUFFIXES shared suffix set (now includes brave-search).
    • detachSandboxProviders() — best-effort detach across the suffix set, with a tightened tolerance regex that only accepts NotAttached / "not attached" and provider-scoped NotFound / "not found"; bare sandbox-not-found is intentionally not tolerated so stale-attachment failures stay visible.
    • runSandboxProviderPreDeleteCleanup() — wraps the detach pass, redacts and length-caps any non-tolerated failure output through the injected warn channel, and returns the failure list to callers that want stricter semantics.
    • parseAttachedSandboxes() + recoverAttachedProvider() — parse a FailedPrecondition diagnostic of the shape provider 'X' is attached to sandbox(es): A, B and detach the provider from each named sandbox, even when the local pre-delete pass couldn't reach the now-missing sandbox (resume case).
  • src/lib/onboard.ts rebuild path now calls runSandboxProviderPreDeleteCleanup(sandboxName) immediately before runOpenshell(["sandbox", "delete", ...]), and again right before upsertMessagingProviders({replaceExisting: true}) so the --resume-after-prune path also clears stale attachments before the replace-existing provider deletes run.
  • src/lib/onboard/providers.ts upsertProvider recovery: on a provider delete FailedPrecondition with an attached-sandbox list, force the detach via recoverAttachedProvider and retry the delete before failing.
  • src/lib/actions/sandbox/destroy.ts consumes the shared constant in place of its previous hard-coded suffix list (which adds brave-search to the destroy-time cleanup), runs runSandboxProviderPreDeleteCleanup before its own sandbox delete, captures the result, and prints a loud manual-cleanup hint at the end if any non-tolerated detach failures occurred.
  • Tests: 17 helper unit tests (full suffix coverage, NotAttached spelling, sandbox-not-found is not tolerated, redaction, length cap, parser shapes, recovery success / partial / failure), 1 providers integration test asserting the full get → delete → recover → delete → create chain on FailedPrecondition, 1 CLI integration test asserting the destroy path issues all six detach calls before sandbox delete, and the existing test/destroy-cleanup-sandbox-services.test.ts assertion for the expanded suffix list.

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
  • npm run 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: Tinson Lai tinsonl@nvidia.com

Summary by CodeRabbit

  • Bug Fixes

    • Sandbox deletion now detaches all associated per-sandbox providers (including search providers) before removal; emits warnings/hints if detach failures remain.
    • Provider deletion now attempts recovery when a provider is attached to sandboxes by detaching bindings and retrying delete.
  • New Features

    • Adds a pre-delete provider cleanup step when deleting/recreating sandboxes to improve detach reliability.
  • Tests

    • Added/expanded tests for detach ordering, recovery flows, diagnostic parsing, warning/truncation, and the extended provider suffix set.

…dbox

Signed-off-by: Tinson Lai <tinsonl@nvidia.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 8, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 991b1e6e-c802-4b8c-9217-02d22edcad1d

📥 Commits

Reviewing files that changed from the base of the PR and between 0304c79 and 5287070.

📒 Files selected for processing (1)
  • src/lib/onboard.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/lib/onboard.ts

📝 Walkthrough

Walkthrough

Adds a shared SANDBOX_PROVIDER_SUFFIXES contract and a pre-delete cleanup that best-effort detaches per-sandbox providers; onboard and destroy flows invoke the cleanup before sandbox deletion and tests cover tolerant-not-found cases, failures, redaction, length-capping, and ordering.

Changes

Sandbox Provider Cleanup Before Deletion

Layer / File(s) Summary
Core provider detach utility and suffix contract
src/lib/onboard/sandbox-provider-cleanup.ts
Exports SANDBOX_PROVIDER_SUFFIXES, run/deps/result types, and implements detachSandboxProviders, parseAttachedSandboxes, recoverAttachedProvider, runSandboxProviderPreDeleteCleanup, deleteProviderWithRecovery, and emitProviderDetachResidualHint.
Pre-deletion provider detachment in onboard flow
src/lib/onboard.ts
Imports and calls runSandboxProviderPreDeleteCleanup(sandboxName, { runOpenshell, redact }) immediately before openshell sandbox delete in the recreate path and runs a tolerant pre-delete call at the recreate boundary.
Shared provider suffix usage in destroy path
src/lib/actions/sandbox/destroy.ts
cleanupSandboxServices() now iterates SANDBOX_PROVIDER_SUFFIXES; destroySandbox() invokes runSandboxProviderPreDeleteCleanup before openshell sandbox delete and emits warnings for any residual detach failures.
Provider replace recovery in upsert flow
src/lib/onboard/providers.ts, src/lib/onboard/providers.test.ts
When openshell provider delete fails during replaceExisting, callers use deleteProviderWithRecovery to parse attached sandboxes, run per-sandbox detach recovery, retry delete, and surface recovery failure details; tests cover success and error paths.
Test coverage and CLI ordering check
test/sandbox-provider-cleanup.test.ts, test/cli/destroy-detach-order.test.ts
Adds unit tests for suffix list, detach behaviors, parsing/recovery, delete-with-retry, warning redaction/length-capping and ordering; adds a CLI regression test asserting detach commands occur before sandbox delete.
Regression test update for brave search provider
test/destroy-cleanup-sandbox-services.test.ts
Updates expected provider-deletion targets to include regression-2717-brave-search in the existing cleanup test.
sequenceDiagram
  participant CLI as CLI (onboard/destroy)
  participant PreDelete as runSandboxProviderPreDeleteCleanup
  participant OpenShell as runOpenshell
  CLI->>PreDelete: runSandboxProviderPreDeleteCleanup(sandboxName, { runOpenshell, redact })
  PreDelete->>OpenShell: sandbox provider detach <sandbox>-<suffix>  (iterates SANDBOX_PROVIDER_SUFFIXES)
  OpenShell-->>PreDelete: exit status + stdout/stderr
  PreDelete->>CLI: return { detached, failures } (warn emitted for failures)
  CLI->>OpenShell: openshell sandbox delete <sandbox>  (runs after detach pass)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested labels

area: onboarding

Suggested reviewers

  • prekshivyas
  • cv

Poem

🐰 I nibble suffix lists at dawn and tug loose every tether,
I hush the noisy stderr lines and trim them light as feather.
Before the sandbox slips away I hop and sweep each port,
No stale provider stays to block the gate — I tidy every sort.
🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 53.33% 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 accurately describes the main change: ensuring sandbox providers are detached before destructive operations (rebuild/delete).
Linked Issues check ✅ Passed The PR fully addresses issue #4890's requirements: automatic provider detachment before sandbox deletion, FailedPrecondition error prevention, and integrated cleanup into onboarding workflows.
Out of Scope Changes check ✅ Passed All changes are directly aligned with issue #4890: new sandbox-provider-cleanup utilities, integration into destroy/onboard flows, provider recovery logic, and comprehensive tests.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/4890-rebuild-detach-providers

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

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 8, 2026

PR Review Advisor

Findings: 2 needs attention, 6 worth checking, 0 nice ideas
Since last review: 0 prior items resolved, 5 still apply, 0 new items found

Review findings

🛠️ Needs attention

  • Destroy can still drop retry state after provider detach failures (src/lib/actions/sandbox/destroy.ts:457): The destroy path records non-tolerated provider detach failures, but still proceeds through sandbox delete, best-effort provider deletion, shields cleanup, registry removal, and onboard session clearing before printing the residual hint. If OpenShell leaves provider attachments or gateway-held credentials behind while sandbox deletion succeeds, NemoClaw can remove the local registry/session state needed to retry the detach-then-delete cleanup accurately.
    • Recommendation: Treat non-tolerated detach failures as hard pre-delete failures, or verify provider detach/delete succeeded before removing registry and session state. If best-effort destroy is intentional, persist enough residual retry metadata before clearing state and add a regression test proving the manual remediation remains actionable after cleanup.
    • Evidence: destroySandbox() calls runSandboxProviderPreDeleteCleanup(), stores detachOutcome, then calls runOpenshell(["sandbox", "delete", sandboxName]), cleanupSandboxServices(), cleanupShieldsDestroyArtifacts(), removeSandboxRegistryEntry(), and session clearing before emitProviderDetachResidualHint(). cleanupSandboxServices() deletes providers with ignoreError: true and suppressed stdio.
  • Provider test hotspot grew by another 102 lines (src/lib/onboard/providers.test.ts:271): The changed provider test module is already a large-file hotspot and this PR adds another 102 lines. The deterministic monolith scan marked this growth as needing attention before merge.
    • Recommendation: Offset the growth by extracting the new FailedPrecondition recovery scenarios into a focused test file for sandbox-provider cleanup/provider recovery, or otherwise split the provider lifecycle tests so this hotspot does not keep accumulating unrelated cases.
    • Evidence: Monolith scan: src/lib/onboard/providers.test.ts baseLines=351, headLines=453, delta=102, severity=blocker. The new tests append provider delete recovery and final-error scenarios to the existing provider helper suite.

🔎 Worth checking

  • Source-of-truth review needed: src/lib/onboard/sandbox-provider-cleanup.ts pre-delete provider detach workaround: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: sandbox-provider-cleanup.ts documents the invalid state and removal condition; onboard.ts and destroy.ts call runSandboxProviderPreDeleteCleanup(). The missing production onboarding coverage is tracked by the production ordering finding.
  • Source-of-truth review needed: src/lib/onboard/sandbox-provider-cleanup.ts tolerated detach diagnostic parsing: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: TOLERATED_DETACH_OUTPUT_RE includes a broad 'not attached' branch, and test/sandbox-provider-cleanup.test.ts asserts no failure for an unrelated internal gateway error containing those words.
  • Source-of-truth review needed: src/lib/actions/sandbox/destroy.ts advisory handling after pre-delete cleanup failures: The advisor marked localized patch analysis as missing.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: destroySandbox() emits the residual hint only after cleanupSandboxServices(), cleanupShieldsDestroyArtifacts(), removeSandboxRegistryEntry(), and onboard session clearing.
  • Broad 'not attached' tolerance can suppress unrelated gateway errors (src/lib/onboard/sandbox-provider-cleanup.ts:47): The cleanup helper still classifies any diagnostic containing the words 'not attached' as success-equivalent. In this provider/credential lifecycle path, that can hide unrelated gateway or provider errors and leave provider attachments or gateway-side credential state in an unexpected state.
    • Recommendation: Tighten the tolerance to canonical OpenShell detach/provider diagnostics, preferably structured status codes. Until structured results are available, require provider/detach context around the 'not attached' text and make unrelated gateway wording appear in result.failures.
    • Evidence: TOLERATED_DETACH_OUTPUT_RE includes /\bnot\s+attached\b/i. test/sandbox-provider-cleanup.test.ts has a case named 'does not tolerate unrelated gateway errors that incidentally contain not attached', but the assertion expects that no failure is recorded for an unrelated internal gateway error containing those words.
  • Negative coverage currently documents the unsafe tolerance instead of preventing it (test/sandbox-provider-cleanup.test.ts:146): The new negative test name says unrelated gateway errors containing 'not attached' should not be tolerated, but the assertion expects the helper to tolerate that error. This makes the broad parser behavior harder to catch in future changes.
    • Recommendation: Change the test expectation so unrelated gateway errors with incidental 'not attached' wording appear in result.failures, then tighten TOLERATED_DETACH_OUTPUT_RE until the test passes.
    • Evidence: The test constructs 'Error: internal gateway error: shield sentry is not attached...' and then expects result.failures.some((f) => f.name === 'yankee-telegram-bridge').toBe(false).
  • Production onboard recreate and resume ordering is not directly covered (src/lib/onboard.ts:3204): The linked bug is in the real onboarding recreate/resume path, but the new tests cover the helper, provider helper, and destroy CLI path rather than the production createSandbox sequence in the high-churn onboard monolith. This leaves the most important acceptance path vulnerable to future refactor drift.
    • Recommendation: Add a focused production-path contract test, or extract a small recreate cleanup plan helper and test it through createSandbox. Assert that <sandbox>-telegram-bridge and <sandbox>-brave-search are detached before sandbox delete and before upsertMessagingProviders(..., { replaceExisting: true }) deletes or creates providers, including the resume-after-prune path.
    • Evidence: src/lib/onboard.ts calls runSandboxProviderPreDeleteCleanup() before sandbox delete and again before replaceExisting provider upserts. Existing tests simulate helper ordering, provider delete recovery, and destroy CLI ordering, but do not exercise the production onboarding recreate/resume call site.

🌱 Nice ideas

  • None.
Consider writing more tests for
  • **Runtime validation** — Production onboard recreate path detaches <sandbox>-telegram-bridge and <sandbox>-brave-search before sandbox delete and before upsertMessagingProviders(..., { replaceExisting: true }) deletes or creates providers.. The change crosses NemoClaw/OpenShell sandbox, provider, credential, destroy, and onboarding lifecycle boundaries. Unit tests and a destroy CLI ordering test improve confidence, but production recreate/resume paths, parser negative behavior, and failure-state preservation still need behavior-specific validation.
  • **Runtime validation** — onboard --resume after the sandbox was pruned tolerates missing sandbox during pre-upsert cleanup, then recovers provider delete FailedPrecondition by detaching the listed sandbox and retrying delete.. The change crosses NemoClaw/OpenShell sandbox, provider, credential, destroy, and onboarding lifecycle boundaries. Unit tests and a destroy CLI ordering test improve confidence, but production recreate/resume paths, parser negative behavior, and failure-state preservation still need behavior-specific validation.
  • **Runtime validation** — Destroy with a non-tolerated provider detach failure exits before registry/session removal or persists enough residual retry metadata before clearing local state.. The change crosses NemoClaw/OpenShell sandbox, provider, credential, destroy, and onboarding lifecycle boundaries. Unit tests and a destroy CLI ordering test improve confidence, but production recreate/resume paths, parser negative behavior, and failure-state preservation still need behavior-specific validation.
  • **Runtime validation** — Tolerated detach parsing rejects unrelated gateway errors that merely contain the words 'not attached' outside a canonical provider-detach diagnostic.. The change crosses NemoClaw/OpenShell sandbox, provider, credential, destroy, and onboarding lifecycle boundaries. Unit tests and a destroy CLI ordering test improve confidence, but production recreate/resume paths, parser negative behavior, and failure-state preservation still need behavior-specific validation.
  • **Runtime validation** — Issue [DGX Spark][Ubuntu 24.04] Sandbox deletion leaves stale providers causing onboard --resume to fail #4890 reproduction with Brave enabled tolerates custom provider profile 'brave' already exists and clears the spark-nemo-telegram-bridge attachment before provider recreation.. The change crosses NemoClaw/OpenShell sandbox, provider, credential, destroy, and onboarding lifecycle boundaries. Unit tests and a destroy CLI ordering test improve confidence, but production recreate/resume paths, parser negative behavior, and failure-state preservation still need behavior-specific validation.
  • **Negative coverage currently documents the unsafe tolerance instead of preventing it** — Change the test expectation so unrelated gateway errors with incidental 'not attached' wording appear in result.failures, then tighten TOLERATED_DETACH_OUTPUT_RE until the test passes.
  • **Production onboard recreate and resume ordering is not directly covered** — Add a focused production-path contract test, or extract a small recreate cleanup plan helper and test it through createSandbox. Assert that <sandbox>-telegram-bridge and <sandbox>-brave-search are detached before sandbox delete and before upsertMessagingProviders(..., { replaceExisting: true }) deletes or creates providers, including the resume-after-prune path.
  • **Acceptance clause:** When NemoClaw recreates a sandbox during onboarding, it deletes the sandbox container but leaves associated messaging providers (Telegram bridge, Brave Search) attached in the OpenShell gateway. — add test evidence or identify existing coverage. SANDBOX_PROVIDER_SUFFIXES now includes telegram-bridge and brave-search, and onboard.ts calls runSandboxProviderPreDeleteCleanup() before sandbox delete. Helper tests verify suffix coverage, but the production onboarding recreate path itself is not directly covered by a contract test.
Since last review details

Current findings:

  • Source-of-truth review needed: src/lib/onboard/sandbox-provider-cleanup.ts pre-delete provider detach workaround: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: sandbox-provider-cleanup.ts documents the invalid state and removal condition; onboard.ts and destroy.ts call runSandboxProviderPreDeleteCleanup(). The missing production onboarding coverage is tracked by the production ordering finding.
  • Source-of-truth review needed: src/lib/onboard/sandbox-provider-cleanup.ts tolerated detach diagnostic parsing: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: TOLERATED_DETACH_OUTPUT_RE includes a broad 'not attached' branch, and test/sandbox-provider-cleanup.test.ts asserts no failure for an unrelated internal gateway error containing those words.
  • Source-of-truth review needed: src/lib/actions/sandbox/destroy.ts advisory handling after pre-delete cleanup failures: The advisor marked localized patch analysis as missing.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: destroySandbox() emits the residual hint only after cleanupSandboxServices(), cleanupShieldsDestroyArtifacts(), removeSandboxRegistryEntry(), and onboard session clearing.
  • Destroy can still drop retry state after provider detach failures (src/lib/actions/sandbox/destroy.ts:457): The destroy path records non-tolerated provider detach failures, but still proceeds through sandbox delete, best-effort provider deletion, shields cleanup, registry removal, and onboard session clearing before printing the residual hint. If OpenShell leaves provider attachments or gateway-held credentials behind while sandbox deletion succeeds, NemoClaw can remove the local registry/session state needed to retry the detach-then-delete cleanup accurately.
    • Recommendation: Treat non-tolerated detach failures as hard pre-delete failures, or verify provider detach/delete succeeded before removing registry and session state. If best-effort destroy is intentional, persist enough residual retry metadata before clearing state and add a regression test proving the manual remediation remains actionable after cleanup.
    • Evidence: destroySandbox() calls runSandboxProviderPreDeleteCleanup(), stores detachOutcome, then calls runOpenshell(["sandbox", "delete", sandboxName]), cleanupSandboxServices(), cleanupShieldsDestroyArtifacts(), removeSandboxRegistryEntry(), and session clearing before emitProviderDetachResidualHint(). cleanupSandboxServices() deletes providers with ignoreError: true and suppressed stdio.
  • Provider test hotspot grew by another 102 lines (src/lib/onboard/providers.test.ts:271): The changed provider test module is already a large-file hotspot and this PR adds another 102 lines. The deterministic monolith scan marked this growth as needing attention before merge.
    • Recommendation: Offset the growth by extracting the new FailedPrecondition recovery scenarios into a focused test file for sandbox-provider cleanup/provider recovery, or otherwise split the provider lifecycle tests so this hotspot does not keep accumulating unrelated cases.
    • Evidence: Monolith scan: src/lib/onboard/providers.test.ts baseLines=351, headLines=453, delta=102, severity=blocker. The new tests append provider delete recovery and final-error scenarios to the existing provider helper suite.
  • Broad 'not attached' tolerance can suppress unrelated gateway errors (src/lib/onboard/sandbox-provider-cleanup.ts:47): The cleanup helper still classifies any diagnostic containing the words 'not attached' as success-equivalent. In this provider/credential lifecycle path, that can hide unrelated gateway or provider errors and leave provider attachments or gateway-side credential state in an unexpected state.
    • Recommendation: Tighten the tolerance to canonical OpenShell detach/provider diagnostics, preferably structured status codes. Until structured results are available, require provider/detach context around the 'not attached' text and make unrelated gateway wording appear in result.failures.
    • Evidence: TOLERATED_DETACH_OUTPUT_RE includes /\bnot\s+attached\b/i. test/sandbox-provider-cleanup.test.ts has a case named 'does not tolerate unrelated gateway errors that incidentally contain not attached', but the assertion expects that no failure is recorded for an unrelated internal gateway error containing those words.
  • Negative coverage currently documents the unsafe tolerance instead of preventing it (test/sandbox-provider-cleanup.test.ts:146): The new negative test name says unrelated gateway errors containing 'not attached' should not be tolerated, but the assertion expects the helper to tolerate that error. This makes the broad parser behavior harder to catch in future changes.
    • Recommendation: Change the test expectation so unrelated gateway errors with incidental 'not attached' wording appear in result.failures, then tighten TOLERATED_DETACH_OUTPUT_RE until the test passes.
    • Evidence: The test constructs 'Error: internal gateway error: shield sentry is not attached...' and then expects result.failures.some((f) => f.name === 'yankee-telegram-bridge').toBe(false).
  • Production onboard recreate and resume ordering is not directly covered (src/lib/onboard.ts:3204): The linked bug is in the real onboarding recreate/resume path, but the new tests cover the helper, provider helper, and destroy CLI path rather than the production createSandbox sequence in the high-churn onboard monolith. This leaves the most important acceptance path vulnerable to future refactor drift.
    • Recommendation: Add a focused production-path contract test, or extract a small recreate cleanup plan helper and test it through createSandbox. Assert that <sandbox>-telegram-bridge and <sandbox>-brave-search are detached before sandbox delete and before upsertMessagingProviders(..., { replaceExisting: true }) deletes or creates providers, including the resume-after-prune path.
    • Evidence: src/lib/onboard.ts calls runSandboxProviderPreDeleteCleanup() before sandbox delete and again before replaceExisting provider upserts. Existing tests simulate helper ordering, provider delete recovery, and destroy CLI ordering, but do not exercise the production onboarding recreate/resume call site.

Workflow run details

This is an automated advisory review. A human maintainer must make the final merge decision.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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 `@src/lib/onboard.ts`:
- Around line 3205-3212: The new explanatory comment block around the sandbox
deletion/ provider-detach logic (referencing "sandbox delete" and the follow-up
`provider delete` driven by `upsertMessagingProviders` with `replaceExisting:
true`) added near the sandbox teardown code is causing +20 net lines; trim or
relocate it to keep net file growth within CI budget—either shorten the comment
to a one- or two-line summary, move the full explanation to a nearby README or a
single shared comment at top of the file, or offset by removing or consolidating
other non-essential comments in the same region (also apply the same trimming
for the similar block around lines referenced near `upsertMessagingProviders` at
the second occurrence).
🪄 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: 2fd74ae6-b656-421c-8d08-9a6895645c13

📥 Commits

Reviewing files that changed from the base of the PR and between ec408c8 and c9ebd89.

📒 Files selected for processing (5)
  • src/lib/actions/sandbox/destroy.ts
  • src/lib/onboard.ts
  • src/lib/onboard/sandbox-provider-cleanup.ts
  • test/destroy-cleanup-sandbox-services.test.ts
  • test/sandbox-provider-cleanup.test.ts

Comment thread src/lib/onboard.ts Outdated
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 8, 2026

E2E Advisor Recommendation

Required E2E: messaging-providers-e2e, token-rotation-e2e, sandbox-operations-e2e, brave-search-e2e
Optional E2E: channels-add-remove-e2e, rebuild-openclaw-e2e

Dispatch hint: messaging-providers-e2e,token-rotation-e2e,sandbox-operations-e2e,brave-search-e2e

Auto-dispatched E2E: messaging-providers-e2e, token-rotation-e2e, sandbox-operations-e2e, brave-search-e2e via nightly-e2e.yaml at 52870703b60bf4040a78cc45da87114bff7f5019nightly run

Workflow run

Full advisor summary

E2E Recommendation Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E

  • messaging-providers-e2e (high (~75 min timeout)): Covers the real messaging provider/placeholder/L7-proxy pipeline for Telegram, Discord, Slack, and WeChat, includes rebuild and final destroy cleanup, and is the highest-signal E2E for changed provider attach/delete behavior.
  • token-rotation-e2e (medium-high (~45 min timeout)): Exercises credential rotation followed by re-onboard/rebuild, which drives provider replacement with replaceExisting and should catch regressions in deleteProviderWithRecovery and stale attachment handling.
  • sandbox-operations-e2e (high (~60 min timeout)): Focused lifecycle suite with multi-sandbox onboarding and destroy cleanup. It validates that the new destroy-time provider detach pass does not break live sandbox deletion, registry state, or OpenShell sandbox cleanup.
  • brave-search-e2e (medium-high (requires BRAVE_API_KEY)): The cleanup suffix set now includes brave-search; this is the existing E2E that creates and uses the Brave Search provider through onboard and should catch provider lifecycle regressions specific to search.

Optional E2E

  • channels-add-remove-e2e (high (~75 min timeout)): Adjacent confidence for channel add/remove plus rebuild with gateway credential reuse; useful because the PR changes provider detachment/deletion around rebuilds, but messaging-providers and token-rotation cover the merge-blocking provider lifecycle risks more directly.
  • rebuild-openclaw-e2e (high (~60 min timeout)): Useful generic rebuild confidence that the new pre-delete cleanup does not regress non-messaging OpenClaw rebuild/state-restore flows.

New E2E recommendations

  • OpenShell stale provider attachment recovery (high): Existing E2Es cover normal provider lifecycle but do not intentionally create an orphaned provider attachment that makes openshell provider delete fail with FailedPrecondition, then verify NemoClaw detaches the listed sandbox(s), retries delete, and completes onboard/rebuild/destroy.
    • Suggested test: Add a hermetic provider-attachment recovery E2E that creates a per-sandbox provider, forces or simulates stale OpenShell attachment state, runs rebuild/destroy, and asserts provider detach/delete recovery plus sanitized residual hints.
  • destroy-time provider cleanup assertions (medium): Current sandbox operations E2E verifies sandbox removal, but not that per-sandbox OpenShell providers including *-brave-search are detached/deleted before or after destroy in the live gateway.
    • Suggested test: Extend sandbox-operations or add a focused destroy-provider-cleanup E2E that onboards with messaging/search providers, destroys the sandbox, and asserts openshell provider get <sandbox>-telegram-bridge and <sandbox>-brave-search are absent or detached.

Dispatch hint

  • Workflow: nightly-e2e.yaml
  • jobs input: messaging-providers-e2e,token-rotation-e2e,sandbox-operations-e2e,brave-search-e2e

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 8, 2026

E2E Scenario Advisor Recommendation

Required scenario E2E: ubuntu-repo-cloud-openclaw-slack, ubuntu-repo-cloud-openclaw-brave, ubuntu-repo-cloud-openclaw-token-rotation, ubuntu-repo-cloud-openclaw-double-provider-switch
Optional scenario E2E: ubuntu-repo-cloud-openclaw-telegram, ubuntu-repo-cloud-openclaw-discord, ubuntu-repo-cloud-hermes-slack

Dispatch required scenario E2E:

  • gh workflow run e2e-scenarios.yaml --ref <pr-head-ref> --field scenarios=ubuntu-repo-cloud-openclaw-slack
  • gh workflow run e2e-scenarios.yaml --ref <pr-head-ref> --field scenarios=ubuntu-repo-cloud-openclaw-brave
  • gh workflow run e2e-scenarios.yaml --ref <pr-head-ref> --field scenarios=ubuntu-repo-cloud-openclaw-token-rotation
  • gh workflow run e2e-scenarios.yaml --ref <pr-head-ref> --field scenarios=ubuntu-repo-cloud-openclaw-double-provider-switch

Workflow run

Full scenario advisor summary

E2E Scenario Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required scenario E2E

  • ubuntu-repo-cloud-openclaw-slack: Primary scenario coverage for per-sandbox messaging provider attach/detach cleanup. Slack is a strong target because the changed provider cleanup surface includes both slack-bridge and slack-app suffixes, plus destroy teardown exercises src/lib/actions/sandbox/destroy.ts.
    • Dispatch: gh workflow run e2e-scenarios.yaml --ref <pr-head-ref> --field scenarios=ubuntu-repo-cloud-openclaw-slack
  • ubuntu-repo-cloud-openclaw-brave: The change adds shared cleanup coverage for the brave-search per-sandbox provider suffix and modifies provider replacement/recreate behavior; this is the smallest routed scenario that exercises the Brave web-search provider path.
    • Dispatch: gh workflow run e2e-scenarios.yaml --ref <pr-head-ref> --field scenarios=ubuntu-repo-cloud-openclaw-brave
  • ubuntu-repo-cloud-openclaw-token-rotation: Provider delete/recovery and pre-delete cleanup changes affect credential rotation/rebuild flows; this scenario directly targets provider rotation isolation after onboarding changes.
    • Dispatch: gh workflow run e2e-scenarios.yaml --ref <pr-head-ref> --field scenarios=ubuntu-repo-cloud-openclaw-token-rotation
  • ubuntu-repo-cloud-openclaw-double-provider-switch: The onboard provider upsert path now uses deleteProviderWithRecovery during replaceExisting flows; the double-provider-switch lifecycle is the targeted routed scenario for repeated onboarding/provider-switch behavior.
    • Dispatch: gh workflow run e2e-scenarios.yaml --ref <pr-head-ref> --field scenarios=ubuntu-repo-cloud-openclaw-double-provider-switch

Optional scenario E2E

  • ubuntu-repo-cloud-openclaw-telegram: Adjacent messaging-provider coverage for the same shared detach/delete cleanup on a different bridge implementation.
    • Dispatch: gh workflow run e2e-scenarios.yaml --ref <pr-head-ref> --field scenarios=ubuntu-repo-cloud-openclaw-telegram
  • ubuntu-repo-cloud-openclaw-discord: Adjacent messaging-provider coverage for the same shared detach/delete cleanup on Discord-specific bridge wiring.
    • Dispatch: gh workflow run e2e-scenarios.yaml --ref <pr-head-ref> --field scenarios=ubuntu-repo-cloud-openclaw-discord
  • ubuntu-repo-cloud-hermes-slack: Optional cross-agent validation of the Slack messaging provider cleanup surface under Hermes onboarding rather than OpenClaw.
    • Dispatch: gh workflow run e2e-scenarios.yaml --ref <pr-head-ref> --field scenarios=ubuntu-repo-cloud-hermes-slack

Relevant changed files

  • src/lib/actions/sandbox/destroy.ts
  • src/lib/onboard.ts
  • src/lib/onboard/providers.ts
  • src/lib/onboard/sandbox-provider-cleanup.ts

@laitingsheng laitingsheng added area: sandbox OpenShell sandbox lifecycle, runtime, config, or recovery bug-fix PR fixes a bug or regression labels Jun 8, 2026
… destroy

Signed-off-by: Tinson Lai <tinsonl@nvidia.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 8, 2026

Selective E2E Results — ✅ All requested jobs passed

Run: 27128281702
Target ref: c9ebd89906cfca41a22c212f1701c8d1a695ee78
Workflow ref: main
Requested jobs: token-rotation-e2e,brave-search-e2e,messaging-providers-e2e
Summary: 2 passed, 0 failed, 0 skipped

Job Result
brave-search-e2e ✅ success
messaging-providers-e2e ✅ success
token-rotation-e2e ⚠️ cancelled

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
test/sandbox-provider-cleanup.test.ts (1)

15-26: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Fix the mock signature to match the actual RunOpenshell type.

The mock function on line 20 only accepts one argument (args: Argv), but the actual RunOpenshell type accepts two: (args: string[], opts?: Record<string, unknown>). This causes a TypeScript compilation error at line 192 where the mock is called with both arguments, as confirmed by the static analysis hint.

The actual RunOpenshell signature from destroy.ts lines 55-58 is:

type RunOpenshell = (
  args: string[],
  opts?: Record<string, unknown>,
) => { status: number | null };
🔧 Proposed fix
 function buildRunOpenshell(
   responses: Map<string, RunResult>,
   defaultResponse: RunResult = { status: 0 },
 ) {
   const calls: Argv[] = [];
-  const fn = vi.fn((args: Argv) => {
+  const fn = vi.fn((args: Argv, _opts?: Record<string, unknown>) => {
     calls.push(args);
     const key = args.join(" ");
     return responses.get(key) ?? defaultResponse;
   });
   return { runOpenshell: fn, calls };
 }

Note: The parameter is prefixed with _ since it's unused, following the coding guideline for unused variables in TypeScript.

🤖 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/sandbox-provider-cleanup.test.ts` around lines 15 - 26, The mock in
buildRunOpenshell has the wrong signature — change the vi.fn to match the real
RunOpenshell type so it accepts (args: string[], opts?: Record<string, unknown>)
and preserve tracking of calls; specifically update the anonymous function used
for runOpenshell to (args: string[], _opts?: Record<string, unknown>) => {
calls.push(args as Argv); const key = args.join(" "); return responses.get(key)
?? defaultResponse; } so runOpenshell and buildRunOpenshell match the
RunOpenshell signature and TypeScript no longer errors when the second opts
argument is passed.

Sources: Coding guidelines, Linters/SAST tools

🧹 Nitpick comments (1)
src/lib/onboard/sandbox-provider-cleanup.ts (1)

38-39: 💤 Low value

Consider adding word boundaries to lowercase variants for precision.

The regex correctly matches camelCase variants with word boundaries (\bNotFound\b, \bNotAttached\b) but lacks them for lowercase variants (not\s+found, not\s+attached). This could theoretically match partial words like "not foundational", though in the specific context of OpenShell provider detach errors this is unlikely.

For maximum precision, consider:

-const TOLERATED_DETACH_OUTPUT_RE =
-  /\bNotFound\b|\bNotAttached\b|not\s+found|not\s+attached/i;
+const TOLERATED_DETACH_OUTPUT_RE =
+  /\bNotFound\b|\bNotAttached\b|\bnot\s+found\b|\bnot\s+attached\b/i;

Given the narrow domain and the upstream tolerance pattern, this is optional.

🤖 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 `@src/lib/onboard/sandbox-provider-cleanup.ts` around lines 38 - 39, The
current TOLERATED_DETACH_OUTPUT_RE constant lacks word boundaries around the
lowercase alternatives ("not\s+found" and "not\s+attached"), which can match
unintended substrings; update the regex in TOLERATED_DETACH_OUTPUT_RE to use
word boundaries around those alternatives (e.g., \bnot\s+found\b and
\bnot\s+attached\b) while preserving the existing \bNotFound\b, \bNotAttached\b
variants and the case‑insensitive flag so the pattern remains precise and
tolerant.
🤖 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.

Outside diff comments:
In `@test/sandbox-provider-cleanup.test.ts`:
- Around line 15-26: The mock in buildRunOpenshell has the wrong signature —
change the vi.fn to match the real RunOpenshell type so it accepts (args:
string[], opts?: Record<string, unknown>) and preserve tracking of calls;
specifically update the anonymous function used for runOpenshell to (args:
string[], _opts?: Record<string, unknown>) => { calls.push(args as Argv); const
key = args.join(" "); return responses.get(key) ?? defaultResponse; } so
runOpenshell and buildRunOpenshell match the RunOpenshell signature and
TypeScript no longer errors when the second opts argument is passed.

---

Nitpick comments:
In `@src/lib/onboard/sandbox-provider-cleanup.ts`:
- Around line 38-39: The current TOLERATED_DETACH_OUTPUT_RE constant lacks word
boundaries around the lowercase alternatives ("not\s+found" and
"not\s+attached"), which can match unintended substrings; update the regex in
TOLERATED_DETACH_OUTPUT_RE to use word boundaries around those alternatives
(e.g., \bnot\s+found\b and \bnot\s+attached\b) while preserving the existing
\bNotFound\b, \bNotAttached\b variants and the case‑insensitive flag so the
pattern remains precise and tolerant.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: ad397301-b80b-4813-bdec-78db40796975

📥 Commits

Reviewing files that changed from the base of the PR and between c9ebd89 and b75164c.

📒 Files selected for processing (4)
  • src/lib/actions/sandbox/destroy.ts
  • src/lib/onboard.ts
  • src/lib/onboard/sandbox-provider-cleanup.ts
  • test/sandbox-provider-cleanup.test.ts

Signed-off-by: Tinson Lai <tinsonl@nvidia.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
test/cli/destroy-detach-order.test.ts (1)

21-23: 💤 Low value

Consider adding cleanup for the temporary directory.

The test creates a temporary directory but doesn't explicitly clean it up after completion. While the OS will eventually clean /tmp, adding an explicit cleanup (e.g., fs.rmSync(home, { recursive: true }) in an afterEach or try-finally block) would improve test hygiene.

🤖 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/cli/destroy-detach-order.test.ts` around lines 21 - 23, The test creates
a temporary directory assigned to the variable home but never removes it; add
explicit cleanup by removing home after the test (e.g., call fs.rmSync(home, {
recursive: true, force: true }) in an afterEach or finally block) so the temp
directory is deleted; update the test harness around the code that creates home
(or the surrounding describe/it) to ensure fs.rmSync runs even on failure.
🤖 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/cli/destroy-detach-order.test.ts`:
- Around line 21-23: The test creates a temporary directory assigned to the
variable home but never removes it; add explicit cleanup by removing home after
the test (e.g., call fs.rmSync(home, { recursive: true, force: true }) in an
afterEach or finally block) so the temp directory is deleted; update the test
harness around the code that creates home (or the surrounding describe/it) to
ensure fs.rmSync runs even on failure.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: b07f9e2d-9202-4ca7-b60b-e06aff998f2d

📥 Commits

Reviewing files that changed from the base of the PR and between b75164c and 97f340d.

📒 Files selected for processing (3)
  • src/lib/onboard/sandbox-provider-cleanup.ts
  • test/cli/destroy-detach-order.test.ts
  • test/sandbox-provider-cleanup.test.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • test/sandbox-provider-cleanup.test.ts
  • src/lib/onboard/sandbox-provider-cleanup.ts

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 8, 2026

Selective E2E Results — ✅ All requested jobs passed

Run: 27129306865
Target ref: b75164cf69d31015152345ddaf83a8531db0b058
Workflow ref: main
Requested jobs: token-rotation-e2e,messaging-providers-e2e,brave-search-e2e,sandbox-operations-e2e
Summary: 4 passed, 0 failed, 0 skipped

Job Result
brave-search-e2e ✅ success
messaging-providers-e2e ✅ success
sandbox-operations-e2e ✅ success
token-rotation-e2e ✅ success

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 8, 2026

Selective E2E Results — ✅ All requested jobs passed

Run: 27130844850
Target ref: 97f340d9348c77a380bde71a82e25f4406a2087d
Workflow ref: main
Requested jobs: token-rotation-e2e,cloud-e2e,brave-search-e2e
Summary: 3 passed, 0 failed, 0 skipped

Job Result
brave-search-e2e ✅ success
cloud-e2e ✅ success
token-rotation-e2e ✅ success

…ach before resume upsert

Signed-off-by: Tinson Lai <tinsonl@nvidia.com>
…dbox list and retrying delete

Signed-off-by: Tinson Lai <tinsonl@nvidia.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 8, 2026

Selective E2E Results — ✅ All requested jobs passed

Run: 27133989585
Target ref: 7a1a1e1b9a0d849b39d9f4917d7ddd2bafe4b18b
Workflow ref: main
Requested jobs: sandbox-operations-e2e,messaging-providers-e2e,token-rotation-e2e,brave-search-e2e
Summary: 4 passed, 0 failed, 0 skipped

Job Result
brave-search-e2e ✅ success
messaging-providers-e2e ✅ success
sandbox-operations-e2e ✅ success
token-rotation-e2e ✅ success

…me detach, surface recovery failures

Signed-off-by: Tinson Lai <tinsonl@nvidia.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 8, 2026

Selective E2E Results — ✅ All requested jobs passed

Run: 27135372965
Target ref: 78b68f5a9dfe7e40ba53d3fa3d63c5027323e050
Workflow ref: main
Requested jobs: token-rotation-e2e,sandbox-operations-e2e,messaging-providers-e2e,brave-search-e2e
Summary: 4 passed, 0 failed, 0 skipped

Job Result
brave-search-e2e ✅ success
messaging-providers-e2e ✅ success
sandbox-operations-e2e ✅ success
token-rotation-e2e ✅ success

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
src/lib/onboard/providers.test.ts (2)

409-409: ⚡ Quick win

Use consistent type casting for process.exit mock.

For better type safety and consistency with the existing test at line 298-300, consider using as typeof process.exit instead of as never.

♻️ Suggested improvement for consistency
-    process.exit = ((code?: number) => {
+    process.exit = ((code?: number | string | null) => {
-      throw new Error(`exit(${code})`);
+      throw new Error(`exit(${code ?? 1})`);
-    }) as never;
+    }) as typeof process.exit;
🤖 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 `@src/lib/onboard/providers.test.ts` at line 409, The test replaces
process.exit with a mock using an unsafe cast; update the mock assignment of
process.exit (the line assigning process.exit = ((code?: number) => { ... })) to
use a consistent and type-safe cast "as typeof process.exit" instead of "as
never" so the mocked function matches the original process.exit signature and
aligns with the earlier test pattern.

398-398: 💤 Low value

Consider using const for immutable variable.

Since originalExit is never reassigned, const would more clearly communicate the immutability intent.

♻️ Optional style improvement
-    let originalExit: typeof process.exit = process.exit;
+    const originalExit: typeof process.exit = process.exit;
🤖 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 `@src/lib/onboard/providers.test.ts` at line 398, Change the declaration of the
test variable originalExit from a mutable binding to an immutable one by
replacing "let originalExit: typeof process.exit = process.exit" with a const
declaration (retain the type annotation typeof process.exit and the assigned
value), so the intent that originalExit is never reassigned is explicit in the
test setup for the providers tests.
🤖 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 `@src/lib/onboard/providers.test.ts`:
- Line 409: The test replaces process.exit with a mock using an unsafe cast;
update the mock assignment of process.exit (the line assigning process.exit =
((code?: number) => { ... })) to use a consistent and type-safe cast "as typeof
process.exit" instead of "as never" so the mocked function matches the original
process.exit signature and aligns with the earlier test pattern.
- Line 398: Change the declaration of the test variable originalExit from a
mutable binding to an immutable one by replacing "let originalExit: typeof
process.exit = process.exit" with a const declaration (retain the type
annotation typeof process.exit and the assigned value), so the intent that
originalExit is never reassigned is explicit in the test setup for the providers
tests.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 58be8791-aa4a-4e52-a3d3-ba29ce01aac0

📥 Commits

Reviewing files that changed from the base of the PR and between 78b68f5 and c4ec55a.

📒 Files selected for processing (6)
  • src/lib/actions/sandbox/destroy.ts
  • src/lib/onboard.ts
  • src/lib/onboard/providers.test.ts
  • src/lib/onboard/providers.ts
  • src/lib/onboard/sandbox-provider-cleanup.ts
  • test/sandbox-provider-cleanup.test.ts
🚧 Files skipped from review as they are similar to previous changes (5)
  • src/lib/onboard/providers.ts
  • src/lib/onboard.ts
  • src/lib/actions/sandbox/destroy.ts
  • test/sandbox-provider-cleanup.test.ts
  • src/lib/onboard/sandbox-provider-cleanup.ts

…alidate parsed sandbox names

Signed-off-by: Tinson Lai <tinsonl@nvidia.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 8, 2026

Selective E2E Results — ✅ All requested jobs passed

Run: 27136992165
Target ref: c4ec55ab52ea0d3b8b62cdf34dbf4b17c0d5fd06
Workflow ref: main
Requested jobs: token-rotation-e2e,brave-search-e2e,sandbox-operations-e2e
Summary: 2 passed, 0 failed, 0 skipped

Job Result
brave-search-e2e ✅ success
sandbox-operations-e2e ✅ success
token-rotation-e2e ⚠️ cancelled

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 8, 2026

Selective E2E Results — ✅ All requested jobs passed

Run: 27137705209
Target ref: 0304c79f69436e14c1f563b0f976ec1135ea021b
Workflow ref: main
Requested jobs: token-rotation-e2e,channels-add-remove-e2e,brave-search-e2e,sandbox-operations-e2e
Summary: 4 passed, 0 failed, 0 skipped

Job Result
brave-search-e2e ✅ success
channels-add-remove-e2e ✅ success
sandbox-operations-e2e ✅ success
token-rotation-e2e ✅ success

@cv cv merged commit e353c8c into main Jun 8, 2026
38 checks passed
@cv cv deleted the fix/4890-rebuild-detach-providers branch June 8, 2026 15:11
@cv cv added the v0.0.61 Release target label Jun 8, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 8, 2026

Selective E2E Results — ✅ All requested jobs passed

Run: 27147228417
Target ref: 52870703b60bf4040a78cc45da87114bff7f5019
Workflow ref: main
Requested jobs: messaging-providers-e2e,token-rotation-e2e,sandbox-operations-e2e,brave-search-e2e
Summary: 4 passed, 0 failed, 0 skipped

Job Result
brave-search-e2e ✅ success
messaging-providers-e2e ✅ success
sandbox-operations-e2e ✅ success
token-rotation-e2e ✅ success

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: sandbox OpenShell sandbox lifecycle, runtime, config, or recovery bug-fix PR fixes a bug or regression v0.0.61 Release target

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[DGX Spark][Ubuntu 24.04] Sandbox deletion leaves stale providers causing onboard --resume to fail

2 participants