Skip to content

fix(rebuild): isolate ambient onboard env from sandbox recreate (#5735) - #5787

Merged
cv merged 4 commits into
mainfrom
fix/5735-auto-rebuild-env-isolation
Jun 25, 2026
Merged

fix(rebuild): isolate ambient onboard env from sandbox recreate (#5735)#5787
cv merged 4 commits into
mainfrom
fix/5735-auto-rebuild-env-isolation

Conversation

@yimoj

@yimoj yimoj commented Jun 25, 2026

Copy link
Copy Markdown
Collaborator

Summary

The installer runs upgrade-sandboxes --auto immediately after onboarding. When the operator had exported a different agent/provider for that onboard (e.g. NEMOCLAW_AGENT=langchain-deepagents-code + NEMOCLAW_PROVIDER_KEY=sk-...), those ambient values leaked into every existing sandbox's rebuild: the old OpenClaw sandbox was backed up, deleted, then recreated as the wrong agent (Deep Agents) with an invalid key — destroying the sandbox before a failed/mismatched recreate, while the installer still printed a clean "Installation complete" banner. A rebuild must recreate a sandbox from its own recorded registry/session config, never from an unrelated onboard's ambient env.

Related Issue

Fixes #5735

Changes

  • Isolate ambient onboard-selection env during recreateNEMOCLAW_AGENT, NEMOCLAW_PROVIDER, NEMOCLAW_PROVIDER_KEY, NEMOCLAW_ENDPOINT_URL, NEMOCLAW_MODEL are removed for the duration of the onboard --resume recreate (restored in finally), so the registry-pinned session and the already-registered gateway provider win. New rebuild-env-isolation.ts helper.
  • Surface the agent mismatch before any destructive backup/delete.
  • Pin authoritative resume fieldscredentialEnv from the target registry provider; repin the endpoint from the provider's canonical config when the loaded session belongs to a different sandbox.
  • Fail closed before delete when a non-matching session targets a custom OpenAI/Anthropic-compatible provider whose base URL exists only in its own session (nvidia-router and known remotes stay registry/blueprint-derivable and are not aborted).
  • Installer severity — a failed upgrade-sandboxes --auto no longer prints a clean completion banner; it reports "completed with warnings" plus the affected sandbox / backup path / recovery commands.

Type of Change

  • Code change (feature, bug fix, or refactor)

Verification

  • PR description includes the DCO sign-off declaration and every commit appears as Verified in GitHub
  • Git hooks passed during commit and push, or npx prek run --from-ref main --to-ref HEAD passes
  • Targeted tests pass for changed behavior
  • Tests added or updated for new or changed behavior
  • No secrets, API keys, or credentials committed

Real-CLI E2E (live gateway, isolated dedicated-port gateway + temp registry): created a real OpenClaw nvidia-prod sandbox, marked it stale, exported the reporter's NEMOCLAW_AGENT=langchain-deepagents-code + NEMOCLAW_PROVIDER_KEY=sk-..., and ran ./bin/nemoclaw.js upgrade-sandboxes --auto.

  • Pre-fix: the OpenClaw sandbox was deleted and recreated as Deep Agents (registry agent=langchain-deepagents-code) with incomplete state restore — data loss.
  • Post-fix: the same command logged "Ignoring ambient NEMOCLAW_AGENT=… — rebuilding as its recorded agent 'openclaw'" and rebuilt it as OpenClaw, staying Ready.

Targeted unit tests: rebuild-env-isolation.test.ts, rebuild-flow.test.ts (env isolation + custom-endpoint pre-delete abort + nvidia-router/known-remote proceed), install-upgrade-sandboxes-severity.test.ts, plus repro-2201.test.ts and the sandbox/onboard suites. tsc -p tsconfig.cli.json clean; reviewed with codex review --uncommitted (findings addressed).


Signed-off-by: Yimo Jiang yimoj@nvidia.com

Summary by CodeRabbit

  • New Features
    • Added helpers to sanitize and isolate ambient recreate-selection environment values during sandbox rebuild/resume.
    • Rebuild now derives a consistent onboard --resume configuration, with conditional endpoint pinning and safer resume/session updates.
    • Installer now reports “completed with warnings” when automatic sandbox upgrades fail.
  • Bug Fixes
    • Prevented ambient onboarding variables from steering recreate/resume behavior.
    • Installer now returns a non-zero status when the auto-upgrade did not finish.
  • Tests
    • Added/extended Vitest coverage for env isolation, rebuild edge cases, and installer banner/exit-code severity.

Supersedes #5770 (reopened from NVIDIA/NemoClaw branch so trusted advisor workflows can run).

The installer runs `upgrade-sandboxes --auto` right after onboarding. When the
operator exported a different agent/provider for that onboard (e.g.
NEMOCLAW_AGENT=langchain-deepagents-code, NEMOCLAW_PROVIDER_KEY=sk-...), those
ambient values leaked into each existing sandbox's rebuild: the old OpenClaw
sandbox was backed up, deleted, then recreated as the wrong agent (Deep Agents)
with an invalid key — destroying the sandbox before a failed/mismatched
recreate, while the installer still printed a clean completion banner.

A rebuild must recreate a sandbox from its own recorded registry/session
config, never from an unrelated onboard's ambient env.

- Isolate NEMOCLAW_AGENT/PROVIDER/PROVIDER_KEY/ENDPOINT_URL/MODEL for the
  duration of the `onboard --resume` recreate so the registry-pinned session
  (and the already-registered gateway provider) wins. Restored in `finally`.
- Surface the agent mismatch before any destructive backup/delete.
- Pin credentialEnv from the target registry provider, and repin the endpoint
  from the provider's canonical config when the loaded session belongs to a
  different sandbox.
- Fail closed *before* delete when a non-matching session targets a
  custom/OpenAI-compatible provider whose base URL is only in its own session
  (nvidia-router and known remotes remain registry/blueprint-derivable, so they
  are not aborted).
- Installer: a failed `upgrade-sandboxes --auto` no longer prints a clean
  "Installation complete" banner; it reports completion with warnings and
  recovery guidance.

Proven end-to-end through the real worktree CLI against a live gateway: with the
contaminating Deep Agents env set, pre-fix `upgrade-sandboxes --auto` deleted an
OpenClaw sandbox and recreated it as Deep Agents (incomplete state restore);
post-fix the same command rebuilt it as OpenClaw and it stayed Ready.

Signed-off-by: Yimo Jiang <yimoj@nvidia.com>
@github-code-quality

github-code-quality Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

The overall coverage in the fix/5735-auto-rebuil... branch is 96%. Coverage data for the main branch is not yet available.

Show a code coverage summary of the most covered files.
File main fix/5735-auto-rebuil... 2b3ff51 +/-
nemoclaw/src/se...cret-scanner.ts 100%
nemoclaw/src/commands/slash.ts 100%
nemoclaw/src/li...bprocess-env.ts 100%
nemoclaw/src/bl...eprint/state.ts 98%
nemoclaw/src/onboard/config.ts 98%
nemoclaw/src/bl...int/snapshot.ts 97%
nemoclaw/src/bl...print/runner.ts 95%
nemoclaw/src/co...ration-state.ts 94%
nemoclaw/src/bl...ate-networks.ts 94%
nemoclaw/src/index.ts 94%

TypeScript / code-coverage/cli

The overall coverage in the fix/5735-auto-rebuil... branch is 47%. Coverage data for the main branch is not yet available.

Show a code coverage summary of the most covered files.
File main fix/5735-auto-rebuil... 2b3ff51 +/-
src/lib/state/o...oard-session.ts 91%
src/lib/inference/local.ts 76%
src/lib/actions...dbox/rebuild.ts 72%
src/lib/sandbox/config.ts 72%
src/lib/onboard/preflight.ts 64%
src/lib/actions...licy-channel.ts 60%
src/lib/state/sandbox.ts 55%
src/lib/onboard...er-gpu-patch.ts 50%
src/lib/policy/index.ts 49%
src/lib/onboard.ts 19%

Updated June 25, 2026 15:20 UTC
Code Coverage is in Public Preview. Learn more and provide us with your feedback.

@coderabbitai

coderabbitai Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

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: e00b9260-1a1c-4418-bb1f-55e458045504

📥 Commits

Reviewing files that changed from the base of the PR and between 64ad0fa and 2b3ff51.

📒 Files selected for processing (6)
  • src/lib/actions/sandbox/rebuild-env-isolation.test.ts
  • src/lib/actions/sandbox/rebuild-env-isolation.ts
  • src/lib/actions/sandbox/rebuild-flow.test.ts
  • src/lib/actions/sandbox/rebuild-resume-config.test.ts
  • src/lib/actions/sandbox/rebuild-resume-config.ts
  • src/lib/actions/sandbox/rebuild.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/lib/actions/sandbox/rebuild-env-isolation.test.ts
  • src/lib/actions/sandbox/rebuild-env-isolation.ts

📝 Walkthrough

Walkthrough

Adds ambient recreate environment isolation and rebuild resume preflight for sandbox rebuilds, updates rebuild tests for mismatched and routed sessions, and changes installer completion messaging to flag failed auto-upgrades with recovery guidance.

Changes

Sandbox rebuild isolation and installer warning banner

Layer / File(s) Summary
Ambient recreate env isolation
src/lib/actions/sandbox/rebuild-env-isolation.ts, src/lib/actions/sandbox/rebuild-env-isolation.test.ts
AMBIENT_RECREATE_ENV_VARS is added with assessment and restore helpers, and tests cover mismatch detection, empty-value filtering, cleanup, and idempotent restore.
Rebuild resume config
src/lib/actions/sandbox/rebuild-resume-config.ts, src/lib/actions/sandbox/rebuild-resume-config.test.ts
Registry-backed provider, credential, and endpoint resolution is extracted for rebuild resume, with fail-closed custom-endpoint handling and tests for local, remote, and session-matching behavior.
Recreate isolation and repinning
src/lib/actions/sandbox/rebuild.ts, src/lib/actions/sandbox/rebuild-flow.test.ts
rebuildSandbox now computes resume config before destructive steps, repins session fields from that config, isolates ambient recreate env during onboard --resume, and adds scenarios for mismatched sessions, canonical endpoints, routed targets, and recreate failure logging.
Installer upgrade failure status
scripts/install.sh, test/install-upgrade-sandboxes-severity.test.ts
install.sh tracks failed upgrade-sandboxes --auto runs, changes print_done() output, and the new test file covers the success, warning, and fatal-exit paths.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested labels

area: install

Suggested reviewers

  • cv
  • prekshivyas

Poem

🐇 I hopped through rebuilds, soft and sly,
and tucked the stray env vars nearby.
When upgrades wobble, banners glow,
with rabbit notes on how to go.
🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 73.68% 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 matches the main change: isolating ambient onboard env during sandbox recreate.
Linked Issues check ✅ Passed The PR addresses the installer's destructive auto-rebuild bug with env isolation, pre-delete validation, and clearer failure reporting.
Out of Scope Changes check ✅ Passed The changes stay focused on rebuild safety, env isolation, and install failure reporting with no obvious unrelated additions.

✏️ 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/5735-auto-rebuild-env-isolation

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

@github-actions

github-actions Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor — Changes requested

Merge posture: Do not merge yet
Primary next action: Fix PRA-3: Rebuild still deletes the old sandbox before replacement health is proven; then add or justify PRA-T1.
Open items: 1 required · 3 warnings · 0 suggestions · 8 test follow-ups
Since last review: 3 prior items resolved · 2 still apply · 1 new item found

Action checklist

  • PRA-3 Fix: Rebuild still deletes the old sandbox before replacement health is proven in src/lib/actions/sandbox/rebuild.ts
  • PRA-1 Resolve or justify: Source-of-truth review needed: Delete-then-recreate rebuild architecture
  • PRA-2 Resolve or justify: Source-of-truth review needed: Ambient env and global session contamination during rebuild recreate
  • PRA-4 Resolve or justify: Ambient recreate isolation is still a localized env-list workaround in src/lib/actions/sandbox/rebuild-env-isolation.ts:26
  • PRA-T1 Add or justify test follow-up: Runtime validation
  • PRA-T2 Add or justify test follow-up: Runtime validation
  • PRA-T3 Add or justify test follow-up: Runtime validation
  • PRA-T4 Add or justify test follow-up: Acceptance clause
  • PRA-T5 Add or justify test follow-up: Acceptance clause
  • PRA-T6 Add or justify test follow-up: Acceptance clause
  • PRA-T7 Add or justify test follow-up: Acceptance clause
  • PRA-T8 Add or justify test follow-up: Delete-then-recreate rebuild architecture

Findings index

ID Severity Category Location Required action
PRA-1 Resolve/justify architecture Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
PRA-2 Resolve/justify architecture Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
PRA-3 Required acceptance src/lib/actions/sandbox/rebuild.ts Implement a true health-before-delete flow for the auto-rebuild path, or change the auto-upgrade behavior so it refuses destructive recreate classes that cannot be verified before delete. If OpenShell same-name semantics make true side-by-side replacement impossible, the current PR needs an explicit maintainer-accepted design change in code/behavior that prevents automatic destructive recreate for the residual failure class rather than treating backup/recovery as success.
PRA-4 Resolve/justify security src/lib/actions/sandbox/rebuild-env-isolation.ts:26 Prefer moving the invariant to the source boundary in this PR if feasible: make rebuild recreate call `onboard --resume` with an explicit registry-derived config object or constrained env map and have resume ignore ambient selection env. If that is too large, centralize the authoritative onboard-selection env definitions with the onboard code that reads them, derive `AMBIENT_RECREATE_ENV_VARS` from that source, and add a regression for the additional provider-staging env knobs so drift is caught.

🚨 Required before merge

Address these before merging unless a maintainer explicitly overrides the advisor with rationale.

PRA-3 Required — Rebuild still deletes the old sandbox before replacement health is proven

  • Location: src/lib/actions/sandbox/rebuild.ts
  • Category: acceptance
  • Problem: The PR adds useful pre-delete validation for credentials, registry/session-derived provider/model/endpoint config, messaging plan staging, live-state resolution, and base-image build. However, the destructive order is still backup, `openshell sandbox delete`, registry removal, and only then `await onboard(recreateOpts)`. The changed test `marks recreate onboarding failures as terminal and preserves retry cleanup` explicitly preserves the residual path where preconditions pass, delete proceeds, and `onboard()` then fails.
  • Impact: A residual runtime failure after deterministic preflights pass can still leave an operator without a live sandbox and only a backup/retry path. In installer auto-upgrade, that remains a high-risk sandbox lifecycle availability/data-loss failure mode and does not satisfy the linked issue clause requiring the new image to be built and verified healthy before destroying the old container/image.
  • Required action: Implement a true health-before-delete flow for the auto-rebuild path, or change the auto-upgrade behavior so it refuses destructive recreate classes that cannot be verified before delete. If OpenShell same-name semantics make true side-by-side replacement impossible, the current PR needs an explicit maintainer-accepted design change in code/behavior that prevents automatic destructive recreate for the residual failure class rather than treating backup/recovery as success.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Read `rebuildSandbox` around the destructive section: it logs `Deleting old sandbox...`, calls `runOpenshell(["sandbox", "delete", sandboxName], ...)`, then calls `removeSandboxRegistryEntry(sandboxName)`, and only later calls `await onboard(recreateOpts)`. Then read `src/lib/actions/sandbox/rebuild-flow.test.ts` case `marks recreate onboarding failures as terminal and preserves retry cleanup`, which asserts recovery messaging after the post-delete failure.
  • Missing regression test: Add a rebuild-flow regression for a residual runtime failure after credential, endpoint, messaging, live-state, and base-image preflights pass, and assert the required behavior: either the old sandbox is not deleted until a replacement has passed the same readiness/health checks, or installer auto-upgrade refuses that recreate before delete. The current test proves recovery messaging for the unsafe order, not atomicity.
  • Done when: The required change is committed and verification passes: Read `rebuildSandbox` around the destructive section: it logs `Deleting old sandbox...`, calls `runOpenshell(["sandbox", "delete", sandboxName], ...)`, then calls `removeSandboxRegistryEntry(sandboxName)`, and only later calls `await onboard(recreateOpts)`. Then read `src/lib/actions/sandbox/rebuild-flow.test.ts` case `marks recreate onboarding failures as terminal and preserves retry cleanup`, which asserts recovery messaging after the post-delete failure.
  • Evidence: Linked issue clause: “If recreate has to happen, build the new image and verify it healthy BEFORE destroying the old container/image. Only destroy the old one after the new one is up.” Linked issue comment: “Related open issues: [Ubuntu]nemoclaw rebuild is not atomic — sandbox destroyed before recreate step can fail, leaving user without a working sandbox (only backup remains) #2273 [Ubuntu]nemoclaw rebuild is not atomic — sandbox destroyed before recreate step can fail, leaving user without a working sandbox (only backup remains)”. Current diff still calls `onboard(recreateOpts)` after delete and registry removal.
Review findings by urgency: 1 required fix, 3 items to resolve/justify, 0 in-scope improvements

⚠️ Resolve or justify before merge

Investigate these in the current review; either fix them, explain why they are not applicable, or document the accepted risk.

PRA-1 Resolve/justify — Source-of-truth review needed: Delete-then-recreate rebuild architecture

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as needs_followup.
  • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
  • Recommended action: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Missing regression test: Current tests cover recovery after post-delete `onboard()` failure, but not old-sandbox preservation or health-before-delete.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Evidence: Covered by blocker finding: delete and registry removal still precede `await onboard(recreateOpts)`.

PRA-2 Resolve/justify — Source-of-truth review needed: Ambient env and global session contamination during rebuild recreate

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as needs_followup.
  • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
  • Recommended action: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Missing regression test: New tests cover core env isolation/restoration and registry-derived session pinning, but not all nearby provider-staging env knobs.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Evidence: Covered by warning finding: `AMBIENT_RECREATE_ENV_VARS` is a fixed local list while onboard provider staging reads additional env-driven fields.

PRA-4 Resolve/justify — Ambient recreate isolation is still a localized env-list workaround

  • Location: src/lib/actions/sandbox/rebuild-env-isolation.ts:26
  • Category: security
  • Problem: The PR correctly removes the main reported ambient inputs (`NEMOCLAW_AGENT`, `NEMOCLAW_PROVIDER`, `NEMOCLAW_PROVIDER_KEY`, `NEMOCLAW_ENDPOINT_URL`, `NEMOCLAW_MODEL`) around `onboard --resume` and documents the removal condition. The source boundary still remains `onboard --resume` reading global `process.env` and singleton session state, and the contract test only pins this local list. Nearby onboard provider staging reads other environment knobs such as `NEMOCLAW_E2E_USE_HOSTED_INFERENCE`, `NEMOCLAW_COMPAT_MODEL`, `NEMOCLAW_CLOUD_EXPERIMENTAL_MODEL`, and `NEMOCLAW_PREFERRED_API`, so future or indirect selection env reads can bypass this wrapper without touching rebuild code.
  • Impact: A new or overlooked onboard-selection environment variable could reintroduce cross-sandbox provider/model/endpoint contamination during destructive rebuilds. Because the recreate happens after the old sandbox may be deleted, this drift has direct sandbox lifecycle and data-loss impact.
  • Recommended action: Prefer moving the invariant to the source boundary in this PR if feasible: make rebuild recreate call `onboard --resume` with an explicit registry-derived config object or constrained env map and have resume ignore ambient selection env. If that is too large, centralize the authoritative onboard-selection env definitions with the onboard code that reads them, derive `AMBIENT_RECREATE_ENV_VARS` from that source, and add a regression for the additional provider-staging env knobs so drift is caught.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Compare `AMBIENT_RECREATE_ENV_VARS` in `src/lib/actions/sandbox/rebuild-env-isolation.ts` with the env reads in `src/lib/onboard/providers.ts` around hosted inference staging and non-interactive provider/model selection. Then inspect `src/lib/actions/sandbox/rebuild-flow.test.ts` env-isolation cases; they cover the core five vars but not the hosted/compat model staging knobs.
  • Missing regression test: Add a recreate test with a non-matching prior onboard env that sets `NEMOCLAW_E2E_USE_HOSTED_INFERENCE=1`, `NEMOCLAW_COMPAT_MODEL`, `NEMOCLAW_CLOUD_EXPERIMENTAL_MODEL`, and `NEMOCLAW_PREFERRED_API` alongside unrelated credentials, and assert the target sandbox still rebuilds from registry/session-derived provider/model/endpoint or aborts before delete.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Compare `AMBIENT_RECREATE_ENV_VARS` in `src/lib/actions/sandbox/rebuild-env-isolation.ts` with the env reads in `src/lib/onboard/providers.ts` around hosted inference staging and non-interactive provider/model selection. Then inspect `src/lib/actions/sandbox/rebuild-flow.test.ts` env-isolation cases; they cover the core five vars but not the hosted/compat model staging knobs.
  • Evidence: `rebuild-env-isolation.ts` documents that `onboard --resume` still reads global `process.env` and that this wrapper is removable only when resume accepts explicit config. `src/lib/onboard/providers.ts` reads and mutates additional env-driven hosted inference/model fields outside the pinned five-var isolation list.

💡 In-scope improvements

These are lower-risk, not throwaway. Prefer fixing them in this PR when they are local to changed code; defer only with rationale or a linked follow-up.

  • None.
Test follow-ups to resolve or justify

If these cover changed behavior, prefer adding them in this PR; otherwise state why existing coverage is enough or link the follow-up.

  • PRA-T1 Runtime validation — Exercise a real or controlled rebuild where residual `onboard --resume` failure occurs after credential, endpoint, messaging, live-state, and base-image preflights pass; assert the old sandbox is preserved until replacement health succeeds, or assert installer auto-upgrade refuses that recreate before delete.. The changed behavior spans installer shell, real OpenShell gateway state, Docker/image lifecycle, registry/session state, and `onboard --resume`. The added unit and mocked flow tests are strong for deterministic branches, but runtime validation is still warranted for the sandbox lifecycle boundary.
  • PRA-T2 Runtime validation — Exercise rebuild recreate with ambient `NEMOCLAW_E2E_USE_HOSTED_INFERENCE=1`, `NEMOCLAW_COMPAT_MODEL`, `NEMOCLAW_CLOUD_EXPERIMENTAL_MODEL`, and `NEMOCLAW_PREFERRED_API` set from an unrelated onboard; assert the target sandbox rebuild uses registry/session-derived provider/model/endpoint or aborts before delete.. The changed behavior spans installer shell, real OpenShell gateway state, Docker/image lifecycle, registry/session state, and `onboard --resume`. The added unit and mocked flow tests are strong for deterministic branches, but runtime validation is still warranted for the sandbox lifecycle boundary.
  • PRA-T3 Runtime validation — Exercise the `scripts/install.sh` `main` auto-upgrade call site with a stub CLI runner that makes `upgrade-sandboxes --auto` fail; assert `_UPGRADE_SANDBOXES_FAILED` is set and the final installer exit is non-zero with recovery guidance.. The changed behavior spans installer shell, real OpenShell gateway state, Docker/image lifecycle, registry/session state, and `onboard --resume`. The added unit and mocked flow tests are strong for deterministic branches, but runtime validation is still warranted for the sandbox lifecycle boundary.
  • PRA-T4 Acceptance clause — Auto-rebuild should be **atomic**, OR perform a **recreate-precheck BEFORE destroying anything**. — add test evidence or identify existing coverage. The PR adds pre-delete checks through `preflightRebuildCredentials`, `prepareRebuildResumeConfig`, messaging plan staging, live-state resolution, and `ensureRebuildAgentBaseImage`. It is not atomic: delete and registry removal still precede `onboard(recreateOpts)`.
  • PRA-T5 Acceptance clause — Each sandbox's rebuild should source its own recorded config (provider, model, API key reference) from registry state, NOT the ambient `NEMOCLAW_PROVIDER_KEY` env or the just-completed onboard session. — add test evidence or identify existing coverage. The main reported envs are isolated during recreate and session fields are pinned from `resumeConfig`; tests assert ambient agent/provider-key/endpoint/provider/model are absent inside mocked onboard and restored after. The source boundary still uses a local env-list wrapper rather than making `onboard --resume` ignore all ambient selection env by construction.
  • PRA-T6 Acceptance clause — If recreate has to happen, build the new image and verify it healthy BEFORE destroying the old container/image. Only destroy the old one after the new one is up. — add test evidence or identify existing coverage. `rebuildSandbox` still deletes the old sandbox and removes its registry entry before `await onboard(recreateOpts)`. The post-delete failure test asserts recovery guidance, not health-before-delete behavior.
  • PRA-T7 Acceptance clause — Related open issues: - [[Ubuntu]nemoclaw rebuild is not atomic — sandbox destroyed before recreate step can fail, leaving user without a working sandbox (only backup remains) #2273 [Ubuntu]nemoclaw rebuild is not atomic — sandbox destroyed before recreate step can fail, leaving user without a working sandbox (only backup remains)] — add test evidence or identify existing coverage. The PR reduces precondition-class failures and improves recovery reporting, but the residual non-atomic destroy-before-recreate failure path remains and is covered only as fatal recovery messaging.
  • PRA-T8 Delete-then-recreate rebuild architecture — Current tests cover recovery after post-delete `onboard()` failure, but not old-sandbox preservation or health-before-delete.. Covered by blocker finding: delete and registry removal still precede `await onboard(recreateOpts)`.
Since last review details

Current findings, using the urgency labels above:

PRA-1 Resolve/justify — Source-of-truth review needed: Delete-then-recreate rebuild architecture

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as needs_followup.
  • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
  • Recommended action: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Missing regression test: Current tests cover recovery after post-delete `onboard()` failure, but not old-sandbox preservation or health-before-delete.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Evidence: Covered by blocker finding: delete and registry removal still precede `await onboard(recreateOpts)`.

PRA-2 Resolve/justify — Source-of-truth review needed: Ambient env and global session contamination during rebuild recreate

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as needs_followup.
  • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
  • Recommended action: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Missing regression test: New tests cover core env isolation/restoration and registry-derived session pinning, but not all nearby provider-staging env knobs.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Evidence: Covered by warning finding: `AMBIENT_RECREATE_ENV_VARS` is a fixed local list while onboard provider staging reads additional env-driven fields.

PRA-3 Required — Rebuild still deletes the old sandbox before replacement health is proven

  • Location: src/lib/actions/sandbox/rebuild.ts
  • Category: acceptance
  • Problem: The PR adds useful pre-delete validation for credentials, registry/session-derived provider/model/endpoint config, messaging plan staging, live-state resolution, and base-image build. However, the destructive order is still backup, `openshell sandbox delete`, registry removal, and only then `await onboard(recreateOpts)`. The changed test `marks recreate onboarding failures as terminal and preserves retry cleanup` explicitly preserves the residual path where preconditions pass, delete proceeds, and `onboard()` then fails.
  • Impact: A residual runtime failure after deterministic preflights pass can still leave an operator without a live sandbox and only a backup/retry path. In installer auto-upgrade, that remains a high-risk sandbox lifecycle availability/data-loss failure mode and does not satisfy the linked issue clause requiring the new image to be built and verified healthy before destroying the old container/image.
  • Required action: Implement a true health-before-delete flow for the auto-rebuild path, or change the auto-upgrade behavior so it refuses destructive recreate classes that cannot be verified before delete. If OpenShell same-name semantics make true side-by-side replacement impossible, the current PR needs an explicit maintainer-accepted design change in code/behavior that prevents automatic destructive recreate for the residual failure class rather than treating backup/recovery as success.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Read `rebuildSandbox` around the destructive section: it logs `Deleting old sandbox...`, calls `runOpenshell(["sandbox", "delete", sandboxName], ...)`, then calls `removeSandboxRegistryEntry(sandboxName)`, and only later calls `await onboard(recreateOpts)`. Then read `src/lib/actions/sandbox/rebuild-flow.test.ts` case `marks recreate onboarding failures as terminal and preserves retry cleanup`, which asserts recovery messaging after the post-delete failure.
  • Missing regression test: Add a rebuild-flow regression for a residual runtime failure after credential, endpoint, messaging, live-state, and base-image preflights pass, and assert the required behavior: either the old sandbox is not deleted until a replacement has passed the same readiness/health checks, or installer auto-upgrade refuses that recreate before delete. The current test proves recovery messaging for the unsafe order, not atomicity.
  • Done when: The required change is committed and verification passes: Read `rebuildSandbox` around the destructive section: it logs `Deleting old sandbox...`, calls `runOpenshell(["sandbox", "delete", sandboxName], ...)`, then calls `removeSandboxRegistryEntry(sandboxName)`, and only later calls `await onboard(recreateOpts)`. Then read `src/lib/actions/sandbox/rebuild-flow.test.ts` case `marks recreate onboarding failures as terminal and preserves retry cleanup`, which asserts recovery messaging after the post-delete failure.
  • Evidence: Linked issue clause: “If recreate has to happen, build the new image and verify it healthy BEFORE destroying the old container/image. Only destroy the old one after the new one is up.” Linked issue comment: “Related open issues: [Ubuntu]nemoclaw rebuild is not atomic — sandbox destroyed before recreate step can fail, leaving user without a working sandbox (only backup remains) #2273 [Ubuntu]nemoclaw rebuild is not atomic — sandbox destroyed before recreate step can fail, leaving user without a working sandbox (only backup remains)”. Current diff still calls `onboard(recreateOpts)` after delete and registry removal.

PRA-4 Resolve/justify — Ambient recreate isolation is still a localized env-list workaround

  • Location: src/lib/actions/sandbox/rebuild-env-isolation.ts:26
  • Category: security
  • Problem: The PR correctly removes the main reported ambient inputs (`NEMOCLAW_AGENT`, `NEMOCLAW_PROVIDER`, `NEMOCLAW_PROVIDER_KEY`, `NEMOCLAW_ENDPOINT_URL`, `NEMOCLAW_MODEL`) around `onboard --resume` and documents the removal condition. The source boundary still remains `onboard --resume` reading global `process.env` and singleton session state, and the contract test only pins this local list. Nearby onboard provider staging reads other environment knobs such as `NEMOCLAW_E2E_USE_HOSTED_INFERENCE`, `NEMOCLAW_COMPAT_MODEL`, `NEMOCLAW_CLOUD_EXPERIMENTAL_MODEL`, and `NEMOCLAW_PREFERRED_API`, so future or indirect selection env reads can bypass this wrapper without touching rebuild code.
  • Impact: A new or overlooked onboard-selection environment variable could reintroduce cross-sandbox provider/model/endpoint contamination during destructive rebuilds. Because the recreate happens after the old sandbox may be deleted, this drift has direct sandbox lifecycle and data-loss impact.
  • Recommended action: Prefer moving the invariant to the source boundary in this PR if feasible: make rebuild recreate call `onboard --resume` with an explicit registry-derived config object or constrained env map and have resume ignore ambient selection env. If that is too large, centralize the authoritative onboard-selection env definitions with the onboard code that reads them, derive `AMBIENT_RECREATE_ENV_VARS` from that source, and add a regression for the additional provider-staging env knobs so drift is caught.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Compare `AMBIENT_RECREATE_ENV_VARS` in `src/lib/actions/sandbox/rebuild-env-isolation.ts` with the env reads in `src/lib/onboard/providers.ts` around hosted inference staging and non-interactive provider/model selection. Then inspect `src/lib/actions/sandbox/rebuild-flow.test.ts` env-isolation cases; they cover the core five vars but not the hosted/compat model staging knobs.
  • Missing regression test: Add a recreate test with a non-matching prior onboard env that sets `NEMOCLAW_E2E_USE_HOSTED_INFERENCE=1`, `NEMOCLAW_COMPAT_MODEL`, `NEMOCLAW_CLOUD_EXPERIMENTAL_MODEL`, and `NEMOCLAW_PREFERRED_API` alongside unrelated credentials, and assert the target sandbox still rebuilds from registry/session-derived provider/model/endpoint or aborts before delete.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Compare `AMBIENT_RECREATE_ENV_VARS` in `src/lib/actions/sandbox/rebuild-env-isolation.ts` with the env reads in `src/lib/onboard/providers.ts` around hosted inference staging and non-interactive provider/model selection. Then inspect `src/lib/actions/sandbox/rebuild-flow.test.ts` env-isolation cases; they cover the core five vars but not the hosted/compat model staging knobs.
  • Evidence: `rebuild-env-isolation.ts` documents that `onboard --resume` still reads global `process.env` and that this wrapper is removable only when resume accepts explicit config. `src/lib/onboard/providers.ts` reads and mutates additional env-driven hosted inference/model fields outside the pinned five-var isolation list.

Workflow run details

This is an automated, non-binding review; it still expects maintainers and agents to respond to each required or warning item. Treat suggestions as current-PR improvements when they touch changed code; defer only with maintainer rationale or a linked follow-up. A human maintainer must make the final merge decision.

@github-actions

github-actions Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

E2E Advisor Recommendation

Required E2E: upgrade-stale-sandbox-e2e, rebuild-openclaw-e2e, onboard-resume-e2e, onboard-repair-e2e, cloud-onboard-e2e
Optional E2E: sandbox-operations-e2e, inference-routing-e2e, credential-sanitization-e2e

Dispatch hint: upgrade-stale-sandbox-e2e,rebuild-openclaw-e2e,onboard-resume-e2e,onboard-repair-e2e,cloud-onboard-e2e

Workflow run

Full advisor summary

E2E Recommendation Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E

  • upgrade-stale-sandbox-e2e (high): This PR directly changes installer post-onboard upgrade-sandboxes handling and destructive rebuild recovery. The existing stale/upgrade E2E is the closest live coverage for installer-driven sandbox upgrade and recovery semantics.
  • rebuild-openclaw-e2e (high): rebuild.ts, rebuild resume config, and ambient env isolation all affect the live OpenClaw rebuild path: backup, delete, onboard --resume recreate, provider/model restoration, and post-rebuild recovery.
  • onboard-resume-e2e (medium): The changed rebuild path bootstraps and pins onboard session state before invoking onboard --resume. Resume compatibility paths must be validated end-to-end, not only by unit tests.
  • onboard-repair-e2e (medium): The PR changes failure handling for resume/recreate after destructive rebuild and installer upgrade failures. The repair E2E validates recovery from interrupted or failed onboarding sessions.
  • cloud-onboard-e2e (high): scripts/install.sh changed final installer success/failure behavior after hosted onboarding. A hosted cloud onboarding run should verify the normal installer path still completes cleanly with the new finalize_install flow.

Optional E2E

  • sandbox-operations-e2e (medium): Useful adjacent confidence for general sandbox lifecycle commands after changes to destructive rebuild/recreate behavior, but less targeted than rebuild-openclaw-e2e.
  • inference-routing-e2e (medium): Optional coverage for provider and endpoint routing behavior because rebuild-resume-config now classifies routed, local, known remote, and custom endpoint providers.
  • credential-sanitization-e2e (medium): Optional security confidence for credential boundary behavior because the PR changes credential-env resolution and isolates ambient provider-key variables during rebuild recreate.

New E2E recommendations

  • installer upgrade/rebuild contamination (high): No existing E2E appears to exactly reproduce an installer that onboards one agent/provider while ambient NEMOCLAW_AGENT/NEMOCLAW_PROVIDER/NEMOCLAW_ENDPOINT_URL remain set, then auto-upgrades a pre-existing different sandbox and verifies the recreated sandbox keeps its registry agent/provider/model.
    • Suggested test: installer-upgrade-sandbox-ambient-env-isolation-e2e
  • installer failed auto-upgrade severity (high): Unit tests exercise print_done/finalize_install, but a live installer E2E that forces upgrade-sandboxes --auto to fail after a pre-existing sandbox delete would validate the real operator-visible non-zero exit and recovery guidance.
    • Suggested test: installer-auto-upgrade-failure-nonzero-e2e
  • custom endpoint rebuild fail-closed (medium): The PR adds logic to abort before destructive delete when a custom-compatible endpoint cannot be recovered from a matching session. A live E2E would ensure the sandbox remains intact in that user-facing failure mode.
    • Suggested test: rebuild-custom-endpoint-missing-session-fail-closed-e2e

Dispatch hint

  • Workflow: .github/workflows/nightly-e2e.yaml
  • jobs input: upgrade-stale-sandbox-e2e,rebuild-openclaw-e2e,onboard-resume-e2e,onboard-repair-e2e,cloud-onboard-e2e

@github-actions

github-actions Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Vitest E2E Scenario Recommendation

Required Vitest E2E scenarios: onboard-resume-vitest, onboard-repair-vitest, upgrade-stale-sandbox-vitest, sandbox-rebuild-vitest
Optional Vitest E2E scenarios: rebuild-hermes-vitest

Dispatch required Vitest E2E scenarios:

  • gh workflow run e2e-vitest-scenarios.yaml --ref <pr-head-ref> --field jobs=onboard-resume-vitest
  • gh workflow run e2e-vitest-scenarios.yaml --ref <pr-head-ref> --field jobs=onboard-repair-vitest
  • gh workflow run e2e-vitest-scenarios.yaml --ref <pr-head-ref> --field jobs=upgrade-stale-sandbox-vitest
  • gh workflow run e2e-vitest-scenarios.yaml --ref <pr-head-ref> --field jobs=sandbox-rebuild-vitest

Workflow run

Full Vitest E2E advisor summary

Vitest E2E Scenario Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required Vitest E2E scenarios

  • onboard-resume-vitest: The rebuild changes pin and isolate persisted session state before invoking onboard --resume; resume compatibility paths must run the dedicated live resume Vitest job.
    • Dispatch: gh workflow run e2e-vitest-scenarios.yaml --ref <pr-head-ref> --field jobs=onboard-resume-vitest
  • onboard-repair-vitest: The rebuild resume-config changes can affect repair/backstop behavior from persisted sessions, including custom endpoint and conflicting resume-input handling; repair is required for these resume paths.
    • Dispatch: gh workflow run e2e-vitest-scenarios.yaml --ref <pr-head-ref> --field jobs=onboard-repair-vitest
  • upgrade-stale-sandbox-vitest: The PR changes install-time stale sandbox upgrade failure severity and the rebuild path used by upgrade-sandboxes; this job exercises stale sandbox detection and rebuild through live Docker/OpenShell/NemoClaw boundaries.
    • Dispatch: gh workflow run e2e-vitest-scenarios.yaml --ref <pr-head-ref> --field jobs=upgrade-stale-sandbox-vitest
  • sandbox-rebuild-vitest: The core src/lib/actions/sandbox/rebuild.ts path now resolves/isolates recreate config before destructive delete; this job exercises the live nemoclaw rebuild path, state preservation, registry refresh, and backup hygiene.
    • Dispatch: gh workflow run e2e-vitest-scenarios.yaml --ref <pr-head-ref> --field jobs=sandbox-rebuild-vitest

Optional Vitest E2E scenarios

  • rebuild-hermes-vitest: Adjacent agent-specific rebuild coverage for Hermes/custom-provider state. Useful because the recreate-config code touches provider/endpoint/session handling, but optional because the primary changed failure mode is OpenClaw stale/upgrade rebuild.
    • Dispatch: gh workflow run e2e-vitest-scenarios.yaml --ref <pr-head-ref> --field jobs=rebuild-hermes-vitest

Relevant changed files

  • scripts/install.sh
  • src/lib/actions/sandbox/rebuild-env-isolation.ts
  • src/lib/actions/sandbox/rebuild-resume-config.ts
  • src/lib/actions/sandbox/rebuild.ts

@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

🤖 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/actions/sandbox/rebuild-flow.test.ts`:
- Around line 498-535: The test cleanup is deleting NEMOCLAW_AGENT and
NEMOCLAW_PROVIDER_KEY unconditionally, which can wipe out values that were
already present in the worker. In rebuild-flow.test.ts, update the affected test
blocks around createRebuildFlowHarness and rebuildSandbox to snapshot the
original process.env values before overriding them, then restore the previous
values in finally (or delete only if they were originally unset). Apply the same
save/restore pattern anywhere the test mutates COMPATIBLE_API_KEY and
NVIDIA_INFERENCE_API_KEY as well.
🪄 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: 330cbc6f-b694-4a7e-acc5-50cfb2e41214

📥 Commits

Reviewing files that changed from the base of the PR and between e3b8325 and b0079da.

📒 Files selected for processing (6)
  • scripts/install.sh
  • src/lib/actions/sandbox/rebuild-env-isolation.test.ts
  • src/lib/actions/sandbox/rebuild-env-isolation.ts
  • src/lib/actions/sandbox/rebuild-flow.test.ts
  • src/lib/actions/sandbox/rebuild.ts
  • test/install-upgrade-sandboxes-severity.test.ts

Comment thread src/lib/actions/sandbox/rebuild-flow.test.ts Outdated
yimoj added 2 commits June 25, 2026 08:56
…te (#5735)

CodeRabbit: the rebuild-flow tests overwrote NEMOCLAW_AGENT/PROVIDER_KEY/
COMPATIBLE_API_KEY/NVIDIA_INFERENCE_API_KEY and unconditionally deleted them in
`finally`, which would wipe a value a worker already had set. Snapshot the prior
values and reinstate them exactly (unset stays unset) via a branchless
`snapshotEnv` helper — branchless so it also keeps the changed-test-file
if-statement guardrail green.

Signed-off-by: Yimo Jiang <yimoj@nvidia.com>
…5735)

Address the PR Review Advisor required/justify items for the auto-upgrade
rebuild path:

- Installer (PRA-5): a failed post-onboard `upgrade-sandboxes --auto` now
  propagates a fatal/non-zero installer result. Extract `finalize_install()`
  which prints the completion summary + recovery guidance and then exits via
  the fatal `error` path when `_UPGRADE_SANDBOXES_FAILED=true`, so automation
  and operators cannot treat a destructive upgrade failure as success.
- Rebuild (PRA-6/PRA-9): consolidate the recreate preconditions into a single
  pre-delete trust boundary, `prepareRebuildResumeConfig()`. It assesses ambient
  onboard-selection env, fails closed for an undeterminable custom endpoint, and
  resolves the exact provider/model/credential/endpoint BEFORE any destructive
  backup/delete; the post-delete session rewrite merely applies that result.
  OpenShell recreates with the same sandbox name (no side-by-side replacement),
  so this validate-before-delete + preserved-backup recovery is the achievable
  atomicity guarantee — documented in the helper.
- Security (PRA-7): sanitize the untrusted `NEMOCLAW_AGENT` value before
  printing the ignored-ambient-agent message via `sanitizeEnvValueForDisplay()`
  (strip control/ANSI, single line, length-capped) so it cannot inject terminal
  output.

Tests: installer fatal-exit cases (PRA-T1), recreate-failure backup-recovery
contract (PRA-T2), and env-value sanitization (PRA-T3).

Signed-off-by: Yimo Jiang <yimoj@nvidia.com>
@yimoj

yimoj commented Jun 25, 2026

Copy link
Copy Markdown
Collaborator Author

PR Review Advisor response (#5735)

Latest push addresses the advisor worklist. Summary of how each item is resolved or justified.

Required — fixed in code

PRA-5 / PRA-T1 / PRA-T7 — failed auto-upgrade now propagates a fatal installer exit.
scripts/install.sh extracts finalize_install() (called by main), which runs print_done and then, when _UPGRADE_SANDBOXES_FAILED=true, calls the fatal error path so the installer exits non-zero. The "completed with warnings" banner, affected-sandbox name, and recovery guidance are still printed first. New install-upgrade-sandboxes-severity.test.ts cases assert finalize_install exits non-zero while still printing the recovery guidance (and exits zero on success).

PRA-6 / PRA-T2 / PRA-T5 / PRA-T6 — pre-delete recreate-config validation, with the atomicity limit documented.
A literal build-new-then-delete-old flow is not possible here: OpenShell recreates with the same sandbox name, so the old and new sandbox cannot coexist — there is no name under which to bring up and health-check a replacement while the original still exists (this is also the #2273 non-atomicity root). Instead the PR makes the full set of recreate preconditions run before any destructive work, now consolidated in the new prepareRebuildResumeConfig(...) trust boundary:

  • credential availability (preflightRebuildCredentials),
  • exact provider/model/credential/endpoint resolution + custom-endpoint determinability (prepareRebuildResumeConfig),
  • agent base image build (ensureRebuildAgentBaseImage).

The provider/model/credential/endpoint the recreate will use is now resolved and validated before delete and merely applied to the session afterward (previously resolved post-delete). The only residual failure window is a transient runtime fault inside onboard after all preconditions pass; that path is covered by the preserved state backup and the printed onboard --resume / snapshot restore recovery steps — now asserted by the strengthened recreate-failure test (PRA-T2). Precondition-class failures (missing credential, undeterminable custom endpoint) abort before delete (existing abort tests).

PRA-7 / PRA-T3 — sanitize the printed NEMOCLAW_AGENT.
The ignored-ambient-agent message now passes the untrusted env value through sanitizeEnvValueForDisplay(), which strips control/C1 characters (including ESC, neutering ANSI), collapses whitespace to a single line, and caps length — so a crafted NEMOCLAW_AGENT cannot inject a fake status line. New unit tests cover newline + ANSI + NUL inputs.

In-scope improvement — fixed

PRA-9 — extracted prepareRebuildResumeConfig(...). The ambient-env assessment, custom-endpoint fail-closed preflight, and provider/model/credential/endpoint resolution now live in a single named, exported helper called before delete; the post-delete session rewrite just applies its result. Call order (before delete, before onboard()) is preserved; existing tests exercise it.

Resolve / justify — source-of-truth framing

PRA-1 (installer severity), PRA-2 (delete-then-recreate), PRA-3 (ambient env/global session), PRA-4 (custom-endpoint preflight), PRA-8 (contamination contract):

  • Invalid state: an unrelated onboard's ambient selection env (NEMOCLAW_AGENT/PROVIDER/PROVIDER_KEY/ENDPOINT_URL/MODEL) or a non-matching global onboard session steering a target sandbox's recreate; and a destructive auto-upgrade reported as success.
  • Source boundary: onboard --resume's provider/agent/credential/endpoint resolution reads process.env and a single global onboard session; and the installer's main flow exit status.
  • Source-fix constraint: onboard --resume is a ~12k-line entrypoint shared by every onboarding path and is under a CI net-neutral growth guardrail; reworking it to consume an explicit per-invocation rebuild config (instead of env + global session) is a large cross-cutting change beyond this data-loss fix and would touch unrelated onboarding flows. Likewise OpenShell same-name recreate prevents true side-by-side atomicity (see PRA-6).
  • Mitigation in this PR (kept at the rebuild boundary, fail-closed): the rebuild pins the registry-derived config into the session and isolates the ambient selection env only for the recreate window, and aborts before delete when the recreate config is undeterminable; the installer now exits fatally on failed auto-upgrade.
  • Regression tests: rebuild-env-isolation.test.ts, rebuild-flow.test.ts (env isolation + restore, custom-endpoint pre-delete abort, known-remote endpoint repin, routed-provider proceed, recreate-failure recovery), install-upgrade-sandboxes-severity.test.ts (fatal exit), plus the real-CLI E2E below.
  • Removal condition: the rebuild-side env isolation + custom-endpoint preflight can be removed once onboard --resume accepts an explicit registry-derived recreate config that ignores ambient selection env and per-sandbox custom endpoints are persisted in registry state; the same-name delete-before-create sequence can be relaxed once OpenShell supports building/verifying a replacement under a temporary name before swapping.

PRA-T4 — runtime/CLI validation that upgrade-sandboxes --auto rebuilds from registry-pinned config under conflicting ambient env. Covered by the real-CLI E2E already performed on a live gateway (isolated dedicated gateway port + temp registry): with NEMOCLAW_AGENT=langchain-deepagents-code + NEMOCLAW_PROVIDER_KEY=sk-… exported, pre-fix upgrade-sandboxes --auto deleted an OpenClaw sandbox and recreated it as Deep Agents (registry agent flipped, incomplete restore); post-fix the same command logged "Ignoring ambient NEMOCLAW_AGENT…", rebuilt it as OpenClaw, and the sandbox stayed Ready with caller env restored.

PRA-T8 — #2273 atomicity: addressed as far as the same-name OpenShell constraint allows (precondition validation before delete + backup-based recovery for the residual transient window), documented above.

CodeRabbit

The env-restore thread is addressed (branchless snapshotEnv restores prior worker values) and CodeRabbit confirmed the fix; verified still current against the latest code.


Signed-off-by: Yimo Jiang yimoj@nvidia.com

@wscurran wscurran added area: onboarding Onboarding FSM, provider setup, sandbox launch, or first-run flow area: sandbox OpenShell sandbox lifecycle, runtime, config, or recovery bug-fix PR fixes a bug or regression labels Jun 25, 2026
@wscurran

Copy link
Copy Markdown
Contributor

…on contract (#5735)

Address the round-2 PR Review Advisor items for the auto-upgrade rebuild path.

- PRA-5 (improvement): extract the pre-delete recreate trust boundary —
  SESSION_ONLY_ENDPOINT_PROVIDER_NAMES, getRebuildEndpointFromRegistry,
  RebuildResumeConfig, prepareRebuildResumeConfig, isLocalInferenceProvider,
  getRebuildCredentialEnvFromRegistry — into a focused
  `rebuild-resume-config.ts` module with direct unit tests. Call order before
  backup/delete and env isolation around onboard() are unchanged; rebuild.ts
  shrinks accordingly.
- PRA-4: document the source boundary, sync requirement, and removal condition
  for the ambient-env isolation list in `rebuild-env-isolation.ts`; add a
  contract test pinning AMBIENT_RECREATE_ENV_VARS and a matching-session
  custom-endpoint regression with hostile ambient NEMOCLAW_ENDPOINT_URL/
  PROVIDER/MODEL (session config used, ambient absent during recreate, caller
  env restored).

Architecture/atomicity items (delete-then-recreate, ambient/session
contamination) are justified in the PR discussion; the residual
health-before-delete window is constrained by OpenShell same-name recreate and
tracked in #5801.

Signed-off-by: Yimo Jiang <yimoj@nvidia.com>
@yimoj

yimoj commented Jun 25, 2026

Copy link
Copy Markdown
Collaborator Author

PR Review Advisor response — round 2 (#5735)

Thanks — the latest advisor run resolved 5 prior items. This push addresses the remaining ones.

PRA-5 (improvement) — done

Extracted SESSION_ONLY_ENDPOINT_PROVIDER_NAMES, getRebuildEndpointFromRegistry, RebuildResumeConfig, prepareRebuildResumeConfig (plus isLocalInferenceProvider / getRebuildCredentialEnvFromRegistry) into a focused src/lib/actions/sandbox/rebuild-resume-config.ts module, with new direct unit tests (rebuild-resume-config.test.ts: local/routed/known-remote/custom endpoint classification, credential resolution, matching vs non-matching session, ambient-mismatch assessment). Call order is unchanged — the helper still runs before backup/delete, and env isolation around onboard() is untouched.

PRA-4 (resolve/justify) — documented + tested

  • Invalid state / source boundary: onboard --resume reads onboard-selection env from global process.env; an unrelated onboard's vars could steer a rebuild recreate.
  • Source-fix constraint: making onboard --resume consume an explicit registry-derived config is a large change to the shared, growth-guarded ~12k-line entrypoint, out of scope for this data-loss fix.
  • Mitigation kept fail-closed at the rebuild boundary, and the isolated env list is now centralized + documented in rebuild-env-isolation.ts with each source read enumerated, plus a contract test (AMBIENT_RECREATE_ENV_VARS pinned) so adding a new onboard-selection env var forces a conscious update here.
  • New regression test: a matching-session custom-endpoint rebuild with hostile ambient NEMOCLAW_ENDPOINT_URL / NEMOCLAW_PROVIDER / NEMOCLAW_MODEL asserts the session's recorded endpoint/provider/model are used, the ambient values are absent during recreate, and the caller env is restored afterward.
  • Removal condition documented in code: delete the isolation once resume accepts an explicit registry-derived config.

PRA-1, PRA-2 (resolve/justify) — re-affirmed

Same source-of-truth framing as PRA-4 / the round-1 comment: invalid state = ambient env / global session steering recreate (and delete-then-recreate ordering); source boundary = onboard --resume + OpenShell same-name recreate; mitigation = fail-closed pre-delete validation + fatal installer exit + preserved-backup recovery; removal conditions linked below.

PRA-3 (Required, atomicity) — achievable validation done; maintainer override for the residual window

The destructive order (delete-before-recreate) is an OpenShell architectural constraint: recreate reuses the same sandbox name, so a replacement cannot be built and health-checked while the original still exists — true side-by-side health-before-delete is not possible in this PR without a new OpenShell capability.

What this PR does instead, before any delete:

  • credential availability (preflightRebuildCredentials),
  • full provider/model/credential/endpoint resolution + custom-endpoint determinability (prepareRebuildResumeConfig, fail-closed),
  • agent base image build (ensureRebuildAgentBaseImage),
  • and, on any failure after delete, a preserved state backup + explicit fatal recovery (onboard --resume / snapshot restore), with the installer now exiting non-zero (PRA-5).

This catches the determinable failure classes before destruction; the residual window is a transient runtime fault inside onboard after all preconditions pass. Eliminating it requires an OpenShell build-verify-swap-under-temporary-name capability, which I've filed as a follow-up: #5801 (with the removal condition). As the maintainer on this issue I'm taking an explicit advisor override for PRA-3 on that basis: the genuine atomic fix is a cross-cutting OpenShell change tracked in #5801, while this PR removes the reported data-loss path (ambient/session contamination + silent installer success) and makes the residual window fatal + recoverable rather than silent.

Test follow-ups


Signed-off-by: Yimo Jiang yimoj@nvidia.com

@cv cv self-assigned this Jun 25, 2026
@cv
cv merged commit 6f4a305 into main Jun 25, 2026
45 checks passed
@cv
cv deleted the fix/5735-auto-rebuild-env-isolation branch June 25, 2026 22:27
@wscurran wscurran added the NV QA Bugs found by the NVIDIA QA Team label Jun 26, 2026
Hadar301 pushed a commit to Hadar301/NemoClaw-OpenShift that referenced this pull request Jul 12, 2026
…IA#5735) (NVIDIA#5787)

## Summary

The installer runs `upgrade-sandboxes --auto` immediately after
onboarding. When the operator had exported a different agent/provider
for that onboard (e.g. `NEMOCLAW_AGENT=langchain-deepagents-code` +
`NEMOCLAW_PROVIDER_KEY=sk-...`), those ambient values leaked into every
existing sandbox's rebuild: the old OpenClaw sandbox was backed up,
**deleted, then recreated as the wrong agent (Deep Agents) with an
invalid key** — destroying the sandbox before a failed/mismatched
recreate, while the installer still printed a clean "Installation
complete" banner. A rebuild must recreate a sandbox from its own
recorded registry/session config, never from an unrelated onboard's
ambient env.

## Related Issue

Fixes NVIDIA#5735

## Changes

- **Isolate ambient onboard-selection env during recreate** —
`NEMOCLAW_AGENT`, `NEMOCLAW_PROVIDER`, `NEMOCLAW_PROVIDER_KEY`,
`NEMOCLAW_ENDPOINT_URL`, `NEMOCLAW_MODEL` are removed for the duration
of the `onboard --resume` recreate (restored in `finally`), so the
registry-pinned session and the already-registered gateway provider win.
New `rebuild-env-isolation.ts` helper.
- **Surface the agent mismatch before any destructive backup/delete.**
- **Pin authoritative resume fields** — `credentialEnv` from the target
registry provider; repin the endpoint from the provider's canonical
config when the loaded session belongs to a different sandbox.
- **Fail closed before delete** when a non-matching session targets a
custom OpenAI/Anthropic-compatible provider whose base URL exists only
in its own session (`nvidia-router` and known remotes stay
registry/blueprint-derivable and are not aborted).
- **Installer severity** — a failed `upgrade-sandboxes --auto` no longer
prints a clean completion banner; it reports "completed with warnings"
plus the affected sandbox / backup path / recovery commands.

## Type of Change

- [x] Code change (feature, bug fix, or refactor)

## Verification

- [x] PR description includes the DCO sign-off declaration and every
commit appears as `Verified` in GitHub
- [x] Git hooks passed during commit and push, or `npx prek run
--from-ref main --to-ref HEAD` passes
- [x] Targeted tests pass for changed behavior
- [x] Tests added or updated for new or changed behavior
- [x] No secrets, API keys, or credentials committed

**Real-CLI E2E (live gateway, isolated dedicated-port gateway + temp
registry):** created a real OpenClaw `nvidia-prod` sandbox, marked it
stale, exported the reporter's
`NEMOCLAW_AGENT=langchain-deepagents-code` +
`NEMOCLAW_PROVIDER_KEY=sk-...`, and ran `./bin/nemoclaw.js
upgrade-sandboxes --auto`.
- **Pre-fix:** the OpenClaw sandbox was deleted and recreated as **Deep
Agents** (registry `agent=langchain-deepagents-code`) with incomplete
state restore — data loss.
- **Post-fix:** the same command logged *"Ignoring ambient
NEMOCLAW_AGENT=… — rebuilding as its recorded agent 'openclaw'"* and
rebuilt it as **OpenClaw**, staying `Ready`.

Targeted unit tests: `rebuild-env-isolation.test.ts`,
`rebuild-flow.test.ts` (env isolation + custom-endpoint pre-delete abort
+ nvidia-router/known-remote proceed),
`install-upgrade-sandboxes-severity.test.ts`, plus `repro-2201.test.ts`
and the sandbox/onboard suites. `tsc -p tsconfig.cli.json` clean;
reviewed with `codex review --uncommitted` (findings addressed).

---

Signed-off-by: Yimo Jiang <yimoj@nvidia.com>


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

* **New Features**
* Added helpers to sanitize and isolate ambient recreate-selection
environment values during sandbox rebuild/resume.
* Rebuild now derives a consistent `onboard --resume` configuration,
with conditional endpoint pinning and safer resume/session updates.
* Installer now reports “completed with warnings” when automatic sandbox
upgrades fail.
* **Bug Fixes**
* Prevented ambient onboarding variables from steering recreate/resume
behavior.
* Installer now returns a non-zero status when the auto-upgrade did not
finish.
* **Tests**
* Added/extended Vitest coverage for env isolation, rebuild edge cases,
and installer banner/exit-code severity.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---
Supersedes NVIDIA#5770 (reopened from NVIDIA/NemoClaw branch so trusted
advisor workflows can run).

---------

Signed-off-by: Yimo Jiang <yimoj@nvidia.com>
cv added a commit that referenced this pull request Jul 15, 2026
…#5801) (#6835)

## Summary

When a rebuild's recreate step hits a transient fault **after** the old
sandbox was deleted but **before** create recorded its name, the printed
manual-recovery step 2 (`nemoclaw onboard --resume`) fails verbatim with
`no sandbox name was recorded. Re-run with --name`, even though the next
printed line asserts the command "will recreate sandbox '<name>'". This
carries `--name <sandbox>` on the resume retry form so the documented
recovery runs as printed.

## Related Issue

Addresses the residual-recovery gap discussed in #5801 (the non-atomic
rebuild window from #2273 / #5787). This does not close #5801 — the
atomic build-verify-swap it asks for still needs upstream work — it
makes the existing preserved-backup mitigation actually followable.

## Changes

- `src/lib/actions/sandbox/rebuild-mcp-phase.ts`: the no-MCP `onboard
--resume` fallback in `printMcpRebuildRetryCommand` now emits `--name
<sandbox>`. The MCP-bearing form already carried the name via the
`<name> rebuild` subcommand; only this fallback dropped it.
- Tests updated/added in `rebuild-mcp-phase.test.ts` and the shared
`test/helpers/rebuild-flow-recovery-cases.ts` to lock the sandbox name
into the printed resume command.

No new abstraction, config, or fallback path — a one-argument fix to an
existing printed command.

## Type of Change

- [x] Code change (feature, bug fix, or refactor)

## Quality Gates
- [x] Tests added or updated for changed behavior
- [x] Docs not applicable — justification: no user-facing docs describe
this internal recovery print; the change makes an existing printed
command runnable.
- [x] Sensitive paths changed (security, policy, credentials, preflight,
onboarding, inference, runner, sandbox, or messaging)
- [ ] Sensitive-path review completed or maintainer-approved waiver
recorded — reviewer/approval link/justification: **requesting maintainer
review; change is limited to recovery-guidance text plus its tests, no
lifecycle/side-effect behavior.**

## Verification
- [x] PR description includes the DCO sign-off declaration and every
commit appears as `Verified` in GitHub
- [x] Normal `pre-commit`, `commit-msg`, and `pre-push` hooks passed, or
`npm run check:diff` passed when hooks were skipped or unavailable —
`npm run check:diff` exit 0
- [x] Targeted behavior tests pass for the current change set — `npx
vitest run src/lib/actions/sandbox/rebuild-mcp-phase.test.ts` (9 passed)
and every rebuild-flow / recovery-helper file consuming the shared
assertion passes in isolation (rebuild-flow.test.ts plus the 8
`rebuild-*` files that use `rebuild-flow-recovery-cases.ts`). Note for
honesty: running all of those files together under full parallel load
intermittently trips pre-existing 5000 ms-timeout flakiness in unrelated
DCode/provider tests (`rebuild-dcode-*`,
`rebuild-local-provider-recreate`); those pass individually, live in
files this change does not modify (it only edits a print function and
its two test files), and fail with variable membership run-to-run — the
signature of a load/timeout flake rather than a regression.
- [x] Quality Gates section completed with required justifications or
waivers
- [x] No secrets, API keys, or credentials committed

### Reproduction / evidence

Verified by execution on `main` (`3de1de6b1`), docker driver, with a
shim that fails only `openshell sandbox create` (a post-delete transient
fault):

- **Before:** rebuild prints `2. Run: nemoclaw onboard --resume
--tool-disclosure progressive`; running it verbatim fails with `Cannot
resume non-interactive onboard: ... no sandbox name was recorded. Re-run
with --name <sandbox>`.
- **After:** the compiled printer emits `nemoclaw onboard --resume
--name rebuild-probe --tool-disclosure progressive`; that exact command
completed recovery live (sandbox returned `Ready`/healthy), followed by
`snapshot restore` of the preserved backup (14 directories, 1 file).

---
Signed-off-by: Hokonoken <41166525+Hokonoken@users.noreply.github.com>

Signed-off-by: Hokonoken <41166525+Hokonoken@users.noreply.github.com>
Co-authored-by: Carlos Villela <cvillela@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: onboarding Onboarding FSM, provider setup, sandbox launch, or first-run flow area: sandbox OpenShell sandbox lifecycle, runtime, config, or recovery bug-fix PR fixes a bug or regression NV QA Bugs found by the NVIDIA QA Team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Ubuntu][Upgrade] installer auto-rebuild destroys existing sandboxes then fails to recreate when ambient env/session does not match the original config

3 participants