fix(upgrade-sandboxes): keep --check read-only and target the recorded gateway (#7279)#7284
Conversation
…d gateway (#7279) `nemoclaw upgrade-sandboxes --check` is documented read-only, but when a registered sandbox's recorded gateway differs from the ambient NEMOCLAW_GATEWAY_PORT default it started a new OpenShell gateway and switched the active gateway to it, stranding the sandbox (a later `nemoclaw uninstall` then targets the wrong gateway). This happens for a sandbox recorded in the ambient-port registry while bound to a non-default gateway (e.g. onboarded under NEMOCLAW_GATEWAY_PORT=18080 → `nemoclaw-18080`), then checked with no env so the ambient default resolves to `nemoclaw`. Root cause: `upgradeSandboxes()` pinned the target to `resolveGatewayName(getGatewayPort())` and ran the recovering preflight (`captureSandboxListWithGatewayPreflightOrExit` → `recoverNamedGatewayRuntime`, which `gateway select`s and starts the gateway) before the `checkOnly` early-return. Fix, scoped to `--check`: - Add `captureNamedGatewaySandboxListReadOnly` (openshell-sandbox-list.ts): a `sandbox list -g <name>` that targets a named gateway without selecting it and never recovers/starts. State-RPC drift still blocks; a down gateway is non-fatal (empty output → sandbox reported unobserved), mirroring `probeGatewayHealth`. - In check mode, resolve the target from the registered sandboxes' `resolveSandboxGatewayName` binding (a single distinct recorded gateway) rather than the ambient port, and use the read-only list. The mutating auto path is unchanged. Verified live: reproduced the gateway start + active-switch on the recorded mismatch state (v0.0.84 and main), then confirmed the fix leaves the active gateway untouched, targets the recorded `nemoclaw-18080` gateway read-only, and reports the sandbox correctly. Signed-off-by: Yanyun Liao <yanyunl@nvidia.com>
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthrough
ChangesSandbox check gateway flow
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant Operator
participant upgradeSandboxes
participant ReadOnlyGatewayList
participant OpenShell
Operator->>upgradeSandboxes: run upgrade-sandboxes --check
upgradeSandboxes->>ReadOnlyGatewayList: resolve and query recorded gateway
ReadOnlyGatewayList->>OpenShell: sandbox list -g gateway
OpenShell-->>ReadOnlyGatewayList: sandbox state or drift result
ReadOnlyGatewayList-->>upgradeSandboxes: read-only list
upgradeSandboxes-->>Operator: report sandbox status
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
src/lib/actions/upgrade-sandboxes.ts (1)
223-236: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConsider warning on invalid persisted gateway bindings, like the sibling helper does.
resolveCheckGatewayNamesilently discardsresolveSandboxGatewayNamethrows via an emptycatch, whereasisPreparedRecoveryCandidate(lines 171-178) warns viaconsole.warnon the same failure mode. Since--checkexists specifically to surface diagnostic problems, silently falling back to the ambient default when all/some recorded bindings are corrupt hides a signal an operator running--checkwould want to see.♻️ Proposed fix to surface invalid bindings
for (const sandbox of sandboxes) { try { recorded.add(resolveSandboxGatewayName(sandbox)); - } catch { - // Invalid persisted binding — never drive a list against it. + } catch { + console.warn( + ` Warning: sandbox ${JSON.stringify(sandbox.name)} has an invalid persisted gateway binding; excluding it from check-mode gateway resolution.`, + ); } }🤖 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/actions/upgrade-sandboxes.ts` around lines 223 - 236, Update resolveCheckGatewayName so its catch block warns with console.warn when resolveSandboxGatewayName fails, matching the warning behavior in isPreparedRecoveryCandidate while still excluding invalid bindings and returning the existing recorded-or-fallback gateway selection.src/lib/actions/upgrade-sandboxes-preflight.test.ts (1)
131-152: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winAdd coverage for the ambiguous/no-recorded-gateway fallback branch.
resolveCheckGatewayName's docstring (src/lib/actions/upgrade-sandboxes.ts, lines 213-222) explicitly documents that several distinct recorded gateways (or none) fall back to the ambient default, but no test in this suite exercises multiple sandboxes with differinggatewayPort/gatewayNamebindings (or all-invalid bindings) to confirm that fallback actually fires.🤖 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/actions/upgrade-sandboxes-preflight.test.ts` around lines 131 - 152, Add tests for the ambiguous gateway fallback in the upgrade-sandboxes preflight suite, using multiple sandboxes with differing valid gatewayPort/gatewayName bindings and a separate case where all bindings are invalid or absent. Verify resolveCheckGatewayName falls back to the ambient default and the preflight uses that fallback path, while preserving the existing recorded-gateway behavior.
🤖 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/upgrade-sandboxes-preflight.test.ts`:
- Line 116: Update the test title in the `it` block to append the local issue
reference `(`#7279`)` as the final suffix, matching the sibling tests while
preserving the existing behavior-oriented wording.
---
Nitpick comments:
In `@src/lib/actions/upgrade-sandboxes-preflight.test.ts`:
- Around line 131-152: Add tests for the ambiguous gateway fallback in the
upgrade-sandboxes preflight suite, using multiple sandboxes with differing valid
gatewayPort/gatewayName bindings and a separate case where all bindings are
invalid or absent. Verify resolveCheckGatewayName falls back to the ambient
default and the preflight uses that fallback path, while preserving the existing
recorded-gateway behavior.
In `@src/lib/actions/upgrade-sandboxes.ts`:
- Around line 223-236: Update resolveCheckGatewayName so its catch block warns
with console.warn when resolveSandboxGatewayName fails, matching the warning
behavior in isPreparedRecoveryCandidate while still excluding invalid bindings
and returning the existing recorded-or-fallback gateway selection.
🪄 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: 97a2b463-203a-4ee5-b608-db93bde3d85a
📒 Files selected for processing (4)
src/lib/actions/upgrade-sandboxes-preflight.test.tssrc/lib/actions/upgrade-sandboxes.tssrc/lib/openshell-sandbox-list.test.tssrc/lib/openshell-sandbox-list.ts
PR Review Advisor — InformationalAdvisor assessment: Informational / high confidence Model lanes
Nemotron output stays in workflow artifacts and does not change the assessment above. E2E guidanceAdvisory only. E2E / PR Gate selects and runs jobs independently. Recommended E2E: 1 optional E2E recommendation
This automated review informs maintainers. Warnings and suggestions do not require a response. A maintainer decides whether to merge. |
…harness (#7279) The recovery-harness check-mode cases (createRecoveryHarness) spied only the recovering preflight, so after routing --check through the new captureNamedGatewaySandboxListReadOnly they reached the real openshell adapter. Locally the drift preflight returned null and the list stayed non-fatal, but in CI the state-RPC drift preflight fired and process.exit(1) aborted the run. Stub captureNamedGatewaySandboxListReadOnly in the harness with the same Error-phase output as the recovering preflight so a check-mode run never touches the real adapter and classifies identically to the auto path. Signed-off-by: Yanyun Liao <yanyunl@nvidia.com>
|
CI note: the red |
…k-readonly-gateway
…k-readonly-gateway
Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
…k-readonly-gateway
|
🌿 Preview your docs: https://nvidia-preview-pr-7284.docs.buildwithfern.com/nemoclaw |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/lib/actions/upgrade-sandboxes-recovery.test.ts (1)
552-580: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAvoid coupling this test to private call shape.
The exact context objects and
toHaveBeenNthCalledWithordering can break on harmless orchestration changes without proving a user-visible outcome. Keep a narrow assertion for the recorded gateway if needed, but prefer asserting the resulting check behavior and that gateway mutation/recovery boundaries remain untouched.🤖 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/actions/upgrade-sandboxes-recovery.test.ts` around lines 552 - 580, Update the test for upgradeSandboxes in check mode to avoid asserting exact readOnlyListSpy context objects and call ordering. Assert the user-visible check outcome, retain only a narrow gateway-recording assertion if needed, and continue verifying that liveListSpy and rebuildSpy are not called.Source: Path instructions
🤖 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 `@docs/manage-sandboxes/update-sandboxes.mdx`:
- Around line 88-89: Rewrite the `upgrade-sandboxes --check` documentation in
direct, second-person wording, addressing the reader as “you” rather than
describing command behavior impersonally. Use the shared host CLI form
established by the surrounding MDX guidance, and preserve the behavior involving
recorded gateways and `NEMOCLAW_GATEWAY_PORT`.
---
Nitpick comments:
In `@src/lib/actions/upgrade-sandboxes-recovery.test.ts`:
- Around line 552-580: Update the test for upgradeSandboxes in check mode to
avoid asserting exact readOnlyListSpy context objects and call ordering. Assert
the user-visible check outcome, retain only a narrow gateway-recording assertion
if needed, and continue verifying that liveListSpy and rebuildSpy are not
called.
🪄 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: 8f97fc7b-c6fb-429d-8030-44c78c822385
📒 Files selected for processing (2)
docs/manage-sandboxes/update-sandboxes.mdxsrc/lib/actions/upgrade-sandboxes-recovery.test.ts
…k-readonly-gateway Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
<!-- markdownlint-disable MD041 --> ## Summary This PR adds the canonical dated release entry for NemoClaw v0.0.94 before the tag is cut. The entry reconciles all 26 commits since v0.0.93 and links each user-visible change to its owning documentation. ## Changes - Add `docs/changelog/2026-07-24.mdx` with the exact `## v0.0.94` heading, parser-safe SPDX comment, release summary, and detailed bullets. - Record sandbox restore and update behavior, onboarding and inference changes, network policy behavior, security evidence, Hermes build performance, DGX Station guidance, and E2E validation changes. - Preserve `docs/` as the source of truth without changing the AI-agent documentation routing skill. - Use [E2E run 30075443016](https://github.com/NVIDIA/NemoClaw/actions/runs/30075443016) for release QA evidence at exact tested SHA `04e6dfa883071dda9df429c66e73168e1a995cba`. ### Source summary - [#7461](#7461) -> `docs/changelog/2026-07-24.mdx`: Record the ownership-preserving Hermes image layer reduction and hosted timing comparison. - [#7460](#7460) -> `docs/changelog/2026-07-24.mdx`: Record removal of candidate Hermes swap setup from E2E validation. - [#7458](#7458) -> `docs/security/fern-5.80.1-dependency-review.md`, `docs/changelog/2026-07-24.mdx`: Record the reviewed Fern CLI update. - [#7457](#7457) -> `docs/changelog/2026-07-24.mdx`: Record periodic runner-pressure telemetry. - [#7455](#7455) -> `docs/changelog/2026-07-24.mdx`: Record non-blocking absent Fern previews. - [#7450](#7450) -> `docs/changelog/2026-07-24.mdx`: Record stable cancellation handling for live-test child processes. - [#7449](#7449) -> `docs/changelog/2026-07-24.mdx`: Record parallel plugin EXDEV coverage. - [#7448](#7448) -> `docs/changelog/2026-07-24.mdx`: Record isolated long-running E2E lanes. - [#7444](#7444) -> `docs/changelog/2026-07-24.mdx`: Record exact-head Hermes swap validation. - [#7437](#7437) -> `docs/manage-sandboxes/backup-restore.mdx`, `docs/changelog/2026-07-24.mdx`: Record gateway pairing and authenticated verification after cross-sandbox restore. - [#7436](#7436) -> `docs/manage-sandboxes/backup-restore.mdx`, `docs/reference/commands.mdx`, `docs/changelog/2026-07-24.mdx`: Record selected stale-state cleanup and Hermes virtual-environment access repair. - [#7385](#7385) -> `docs/network-policy/customize-network-policy.mdx`, `docs/changelog/2026-07-24.mdx`: Record the read-only agent-variant route check. - [#7371](#7371) -> `docs/changelog/2026-07-24.mdx`: Record host-artifact verification for session exports. - [#7359](#7359) -> `docs/changelog/2026-07-24.mdx`: Record platform validation for managed vLLM model overrides. - [#7356](#7356) -> `docs/changelog/2026-07-24.mdx`: Record token-shaped value redaction for `sandbox doctor --json`. - [#7354](#7354) -> `docs/security/advisory-early-warning.md`, `docs/changelog/2026-07-24.mdx`: Record advisory correlation and retained audit provenance. - [#7352](#7352) -> `docs/network-policy/customize-network-policy.mdx`, `docs/network-policy/integration-policy-examples.mdx`, `docs/reference/commands.mdx`, `docs/changelog/2026-07-24.mdx`: Record preset reapplication and bounded `tls: skip` guidance. - [#7345](#7345) -> `docs/security/openclaw-2026.6.10-dependency-review.md`, `docs/security/openclaw-2026.7.1-dependency-review.md`, `docs/changelog/2026-07-24.mdx`: Record reviewed npm audit exception enforcement. - [#7340](#7340) -> `docs/network-policy/customize-network-policy.mdx`, `docs/changelog/2026-07-24.mdx`: Record the repaired CLI-reference route. - [#7334](#7334) -> `docs/get-started/dgx-station-preparation.mdx`, `docs/changelog/2026-07-24.mdx`: Record the qualified OTA metadata fallback and narrowed override wording. - [#7322](#7322) -> `docs/changelog/2026-07-24.mdx`: Reconcile the gateway source tag added to plugin registration banners. - [#7284](#7284) -> `docs/manage-sandboxes/update-sandboxes.mdx`, `docs/changelog/2026-07-24.mdx`: Record read-only `upgrade-sandboxes --check` behavior and recorded-gateway selection. - [#7277](#7277) -> `docs/changelog/2026-07-24.mdx`: Reconcile deterministic gateway TCP refusal coverage. - [#7234](#7234) -> `docs/reference/troubleshooting.mdx`, `docs/changelog/2026-07-24.mdx`: Record preserved DGX Spark managed vLLM Express intent on resume. - [#7185](#7185) -> `docs/reference/troubleshooting.mdx`, `docs/changelog/2026-07-24.mdx`: Record IPv4 fallback DNS selection and exact resolver probing. - [#6820](#6820) -> `docs/reference/commands.mdx`, `docs/changelog/2026-07-24.mdx`: Record the versioned, redacted `--events=jsonl` onboarding stream. ## Type of Change - [ ] Code change (feature, bug fix, or refactor) - [ ] Code change with doc updates - [x] Doc only (prose changes, no code sample modifications) - [ ] Doc only (includes code sample changes) ## Quality Gates - [ ] Tests added or updated for changed behavior - [x] Existing tests cover changed behavior — justification: `npx vitest run test/changelog-docs.test.ts` passed 6/6 tests. - [ ] Tests not applicable — justification: - [x] Docs updated for user-facing behavior changes - [ ] Docs not applicable — justification: - [ ] 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: - [ ] Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue: ## Documentation Writer Review - [x] Documentation writer subagent reviewed the completed changes - Result: `docs-updated` - Evidence: `docs/changelog/2026-07-24.mdx`; the writing rules, documentation style, exact release range, skip terms, published routes, and product scope were reviewed; the changelog test passed 6/6; `npm run docs` passed with route checking OK, zero errors, and two existing warnings. - Agent: Codex Desktop <!-- docs-review-head-sha: 65368f9 --> <!-- docs-review-agents-blob-sha: 9c9b36d --> ## DGX Station Hardware Evidence - [ ] Tested on DGX Station - Tested commit: Not applicable - Station profile/scenario: Not applicable - Result: Not applicable - Supporting evidence: Not applicable. This PR does not change `scripts/prepare-dgx-station-host.sh`. ## Verification - [x] PR description includes a `Signed-off-by:` line 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 - [x] Targeted behavior tests pass for the current change set, or tests are marked not applicable above — `npx vitest run test/changelog-docs.test.ts` passed 6/6 tests. - [ ] Applicable broad gate passed — `npm test` for broad runtime/test-harness changes; `npm run check` for repo-wide validation/coverage changes — command/result: Not applicable to the dated changelog entry. - [x] Quality Gates section completed with required justifications or waivers - [x] No secrets, API keys, or credentials committed - [ ] `npm run docs` builds without warnings (doc changes only). The build passed with zero errors and two existing Fern warnings. - [x] Doc pages follow the [style guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md) (doc changes only) - [ ] New doc pages include SPDX header and frontmatter (new pages only). Native dated changelog entries use the required parser-safe MDX SPDX comment and no frontmatter. --- Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Added the v0.0.94 release changelog. * Documented improvements to sandbox snapshot and restore behavior. * Added updates for gateway selection, policy comparisons, onboarding event output, and DGX recovery workflows. * Documented enhanced diagnostics redaction, npm audit provenance, image assembly performance, and validation stability improvements. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
Summary
nemoclaw upgrade-sandboxes --checkis documented as a read-only check, but it started a new OpenShell gateway and switched the active gateway, stranding sandboxes registered under a different (non-default-port) gateway — and a laternemoclaw uninstall --yesthen targeted the wrong gateway and left the sandbox behind.The trigger is a sandbox that is visible to the ambient-port registry while bound to a non-default gateway (recorded
gatewayName/gatewayPort). Running the check with noNEMOCLAW_GATEWAY_PORTresolves the ambient default tonemoclaw, which does not match the sandbox's recordednemoclaw-18080.Root cause
upgradeSandboxes()pinned its target toresolveGatewayName(getGatewayPort())(the ambient default) and ran the recovering preflight —captureSandboxListWithGatewayPreflightOrExit→recoverNamedGatewayRuntime, whichgateway selects the target and starts it ([2/8] Starting OpenShell gateway) — before thecheckOnlyearly-return. So--checkmutated gateway state even though it never rebuilds anything.Fix (scoped to
--check; the auto/rebuild path is unchanged)openshell-sandbox-list.ts— addcaptureNamedGatewaySandboxListReadOnly: asandbox list -g <name>that targets a named gateway without selecting it and never recovers/starts. State-RPC drift still blocks (shared detectors); a down/unreachable gateway is non-fatal (empty output → sandbox reported unobserved), mirroringstatus'sprobeGatewayHealth.upgrade-sandboxes.ts— in check mode, resolve the target from the registered sandboxes'resolveSandboxGatewayNamebinding (the single distinct recorded gateway) instead of the ambient port, and query it read-only. With several distinct recorded gateways (or none) it keeps the ambient default — the read-only query avoids any mutation either way.Testing
openshell-sandbox-list.test.ts,upgrade-sandboxes-preflight.test.ts,upgrade-sandboxes-recovery.test.ts): the read-only helper lists-g <name>and never callsrecoverNamedGatewayRuntime, stays non-fatal when the gateway is down, still exits on state-RPC drift, and handles both the initial and absent-sandbox confirmation reads without the recovering preflight.--checktargets the sandbox's recordednemoclaw-18080instead of the ambientnemoclaw. The paired guard confirms that the auto path is unchanged.nemoclaw-18080— reproduces the defect on bothv0.0.84andmain:--check(no env) prints[2/8] Starting OpenShell gateway+Active gateway set to 'nemoclaw'and flips the active gateway fromnemoclaw-18080tonemoclaw. With this change,--checkleaves the active gateway onnemoclaw-18080, emits none of those side effects, targetsnemoclaw-18080read-only, and reports the sandbox correctly (as running, where the buggy path misreported it as stopped).Closes #7279
Summary by CodeRabbit
upgrade-sandboxes --checkto pin reads to the single recorded gateway from registry sandboxes.--checkperforms inspection only and how gateway selection is determined.Type of Change
Quality Gates
b6016a991against all nine security categories. No findings. Gateway bindings remain namespace and port validated, and OpenShell receives the gateway name as a separate argument.Documentation Writer Review
docs-updateddocs/manage-sandboxes/update-sandboxes.mdxaccurately documents thatupgrade-sandboxes --checkdoes not start, recover, or select a gateway and queries the single recorded gateway when unambiguous.npm run docscompleted with 0 errors and 2 repository warnings;git diff --checkpassed.Verification
Signed-off-by:line and every commit appears asVerifiedin GitHubpre-commit,commit-msg, andpre-pushhooks passed, ornpm run check:diffpassed when hooks were skipped or unavailablenpm run docs, andnpm run check:diffpassed.npm testfor broad runtime/test-harness changes;npm run checkfor repo-wide validation/coverage changes — command/result:npm run docsbuilds without warnings (doc changes only)Signed-off-by: Yanyun Liao yanyunl@nvidia.com