fix(cli): preserve shared routes during sandbox upgrades - #7840
Conversation
Signed-off-by: San Dang <sdang@nvidia.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Enterprise Run ID: 📒 Files selected for processing (6)
🚧 Files skipped from review as they are similar to previous changes (3)
📝 WalkthroughWalkthroughChangesThe rebuild flow now reconciles legacy shared-gateway routes, migrates missing credential metadata, revalidates routes before deletion, and aborts safely on drift. Unit, lifecycle, and two-sandbox E2E coverage were added alongside documentation and timeout updates. Shared-route rebuild
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant RebuildPipeline
participant Registry
participant RebuildDestroyPhase
participant OpenShell
RebuildPipeline->>Registry: Commit route preflight
Registry-->>RebuildPipeline: Return route receipt
RebuildPipeline->>RebuildDestroyPhase: Validate receipt before delete
RebuildDestroyPhase->>Registry: Revalidate current route
Registry-->>RebuildDestroyPhase: Return success or drift
RebuildDestroyPhase->>OpenShell: Delete sandbox on success
Possibly related issues
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Comment |
|
🌿 Preview your docs: https://nvidia-preview-pr-7840.docs.buildwithfern.com/nemoclaw |
Code Coverage OverviewLanguages: TypeScript TypeScript / code-coverage/pluginThe overall coverage in commit 91afb03 in the TypeScript / code-coverage/cliThe overall coverage in commit 91afb03 in the Show a code coverage summary of the most impacted files.
Updated |
|
Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually. Contributors can view more details about this message here. |
PR Review Advisor — Blocking findings reportedAdvisor assessment: Blockers require maintainer review 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: Blockers
|
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (4)
src/lib/actions/sandbox/rebuild-route-preflight.test.ts (1)
82-96: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueGuard the derived provider matrix against becoming empty.
remoteProvidersis filtered fromREMOTE_PROVIDER_CONFIG; if that config shape changes (e.g.,credentialEnvmoves),it.eachsilently degenerates and the migration contract stops being exercised. A singleexpect(remoteProviders.length).toBeGreaterThan(0)in a sanity test keeps the matrix honest.🤖 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/sandbox/rebuild-route-preflight.test.ts` around lines 82 - 96, Add a sanity test near the remoteProviders-derived test matrix that asserts remoteProviders.length is greater than zero. Keep the existing it.each migration coverage unchanged, ensuring configuration changes that filter out every provider fail explicitly instead of silently skipping the contract.src/lib/actions/sandbox/rebuild-preflight-guards.ts (1)
187-192: 🗄️ Data Integrity & Integration | 🔵 Trivial | 💤 Low valueDelete-edge revalidation reads the registry without the registry lock.
commitRebuildRoutePreflightperforms its read underwithLock, but this function reads via a bareload(). A concurrent writer can be mid-write when the delete edge reads, so the guard could observe a torn or stale view right before the destructive delete. If the synchronous no-await edge intentionally avoids the lock, a short comment stating that tradeoff would make the asymmetry explicit.🤖 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/sandbox/rebuild-preflight-guards.ts` around lines 187 - 192, Update revalidateRebuildRouteBeforeDelete to read the sandbox registry through the same lock-protected mechanism used by commitRebuildRoutePreflight, preserving synchronous behavior where required. If this delete-edge path must intentionally use the bare load without locking, add a concise comment documenting that tradeoff and the resulting consistency boundary.test/e2e/live/upgrade-stale-sandbox.test.ts (1)
36-39: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low valueCheck the 75-minute cap against the doubled per-sandbox work.
Worst-case inner budgets now sum well past
LIVE_TIMEOUT_MS: install (20 min) + old-base build (20 min) + two creates (15 min each) + readiness waits + the batch rebuild (45 min). A slow-but-healthy run would be killed by the test timeout rather than by any inner boundary.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@test/e2e/live/upgrade-stale-sandbox.test.ts` around lines 36 - 39, Increase LIVE_TIMEOUT_MS to cover the doubled per-sandbox setup and batch rebuild budgets, including readiness waits, so the upgrade-sandboxes test can complete during a slow-but-healthy run without being terminated by the outer timeout.src/lib/actions/sandbox/rebuild-preflight-target-phase.ts (1)
296-301: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winCross-sandbox registry mutation is only reported through the verbose rebuild log.
The migration writes
credentialEnvonto other sandboxes' registry rows, butlog()is the verbose channel, so a default-verbosity rebuild mutates peers with no user-visible notice. Consider surfacing this on the normal output path (as the other cross-sandbox warnings on this page do) so operators can correlate the change.🤖 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/sandbox/rebuild-preflight-target-phase.ts` around lines 296 - 301, The migratedSandboxNames notification in the rebuild preflight flow currently uses verbose log(); switch this cross-sandbox mutation notice to the normal user-visible output path used by nearby cross-sandbox warnings, while preserving the existing message and conditional check in the routePreflight receipt handling.
🤖 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-destroy-phase.test.ts`:
- Around line 208-211: Update the assertion in the rebuild-destroy test to
reject sandbox deletion regardless of argument or options shape. Reuse the
existing expectNoSandboxDelete helper with mocks.runOpenshell, or inspect the
command and its arguments broadly enough to catch every sandbox delete
invocation.
---
Nitpick comments:
In `@src/lib/actions/sandbox/rebuild-preflight-guards.ts`:
- Around line 187-192: Update revalidateRebuildRouteBeforeDelete to read the
sandbox registry through the same lock-protected mechanism used by
commitRebuildRoutePreflight, preserving synchronous behavior where required. If
this delete-edge path must intentionally use the bare load without locking, add
a concise comment documenting that tradeoff and the resulting consistency
boundary.
In `@src/lib/actions/sandbox/rebuild-preflight-target-phase.ts`:
- Around line 296-301: The migratedSandboxNames notification in the rebuild
preflight flow currently uses verbose log(); switch this cross-sandbox mutation
notice to the normal user-visible output path used by nearby cross-sandbox
warnings, while preserving the existing message and conditional check in the
routePreflight receipt handling.
In `@src/lib/actions/sandbox/rebuild-route-preflight.test.ts`:
- Around line 82-96: Add a sanity test near the remoteProviders-derived test
matrix that asserts remoteProviders.length is greater than zero. Keep the
existing it.each migration coverage unchanged, ensuring configuration changes
that filter out every provider fail explicitly instead of silently skipping the
contract.
In `@test/e2e/live/upgrade-stale-sandbox.test.ts`:
- Around line 36-39: Increase LIVE_TIMEOUT_MS to cover the doubled per-sandbox
setup and batch rebuild budgets, including readiness waits, so the
upgrade-sandboxes test can complete during a slow-but-healthy run without being
terminated by the outer timeout.
🪄 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: bb5dee33-5049-4216-8b6d-abf7ad082b2b
📒 Files selected for processing (17)
.github/workflows/e2e.yamldocs/inference/use-shared-gateway-routes.mdxdocs/reference/commands.mdxsrc/lib/actions/sandbox/rebuild-destroy-phase.test.tssrc/lib/actions/sandbox/rebuild-destroy-phase.tssrc/lib/actions/sandbox/rebuild-pipeline.tssrc/lib/actions/sandbox/rebuild-preflight-guards.tssrc/lib/actions/sandbox/rebuild-preflight-phase.tssrc/lib/actions/sandbox/rebuild-preflight-target-phase.tssrc/lib/actions/sandbox/rebuild-route-preflight.test.tstest/e2e/live/upgrade-stale-sandbox-helpers.tstest/e2e/live/upgrade-stale-sandbox.test.tstest/helpers/rebuild-flow-harness.tstest/helpers/rebuild-flow-lifecycle-cases.tstest/helpers/rebuild-flow-test-harness.tstest/helpers/rebuild-flow-test-support.tstools/e2e/workflow-boundary.mts
Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
prekshivyas
left a comment
There was a problem hiding this comment.
Reviewed head 91afb03.
Security review: PASS across secrets/credentials, input validation, authorization, dependencies, logging, cryptography, configuration, security testing, and system security. The shared-route metadata migration is transactional and fails closed before sandbox deletion; targeted CLI tests (144) and type-checking pass.
<!-- markdownlint-disable MD041 --> ## Summary Adds the canonical July 30 release entry for `v0.0.99` before the release tag is captured. The entry covers all 37 merged PRs since `v0.0.98` and bounds experimental or dormant work without presenting it as supported behavior. ## Changes - Adds `docs/changelog/2026-07-30.mdx` with the exact `## v0.0.99` heading, parser-safe MDX SPDX comment, summary, detailed release bullets, and published documentation routes. - Records user-visible recovery, snapshot, shared-route, Hermes, readiness, inference, image, documentation, and release E2E changes. - States that the managed-image selection and startup-profile contracts remain dormant and do not activate buildless onboarding. Source summary: - [#7972](#7972) -> `docs/changelog/2026-07-30.mdx`: Records restored managed OpenClaw configuration modes during recovery. - [#7834](#7834) -> `docs/changelog/2026-07-30.mdx`: Records clone-bound pairing verification after snapshot restore. - [#7975](#7975) -> `docs/changelog/2026-07-30.mdx`: Records managed startup recovery coverage. - [#7960](#7960) -> `docs/changelog/2026-07-30.mdx`: Records dormant startup-profile coordination without activating a supported surface. - [#7856](#7856) -> `docs/changelog/2026-07-30.mdx`: Records persistence of the credential-free OpenClaw startup command. - [#7959](#7959) -> `docs/changelog/2026-07-30.mdx`: Records dormant startup-profile construction without changing onboarding. - [#7946](#7946) -> `docs/changelog/2026-07-30.mdx`: Records the internal startup-profile schema and transport contract. - [#7951](#7951) -> `docs/changelog/2026-07-30.mdx`: Records platform-pull cleanup before managed-image validation. - [#7949](#7949) -> `docs/changelog/2026-07-30.mdx`: Records rejection of retained Hermes `uv` build cache metadata. - [#7597](#7597) -> `docs/changelog/2026-07-30.mdx`: Records separate command and agent first-turn latency evidence. - [#7931](#7931) -> `docs/changelog/2026-07-30.mdx`: Records focused E2E replacement evidence for retired selectors. - [#7950](#7950) -> `docs/changelog/2026-07-30.mdx`: Records exclusion of build-only BuildKit telemetry from the Deep Agents Code probe. - [#7665](#7665) -> `docs/changelog/2026-07-30.mdx`: Records consolidated priority 2 E2E coverage. - [#7911](#7911) -> `docs/changelog/2026-07-30.mdx`: Records the corrected NVIDIA DORI installation pin. - [#7934](#7934) -> `docs/changelog/2026-07-30.mdx`: Records the staging image-family wait before Brev Launchable deployment. - [#7772](#7772) -> `docs/changelog/2026-07-30.mdx`: Records dormant managed-image selection contracts without activating buildless onboarding. - [#7941](#7941) -> `docs/changelog/2026-07-30.mdx`: Records corrected agent-specific provider and policy guidance. - [#7819](#7819) -> `docs/changelog/2026-07-30.mdx`: Records removal of empty Deep Agents Code provider-switch sections. - [#7932](#7932) -> `docs/changelog/2026-07-30.mdx`: Records independent credential-generation E2E execution. - [#7840](#7840) -> `docs/changelog/2026-07-30.mdx`: Records shared-route preservation and pre-delete peer validation during upgrades. - [#7874](#7874) -> `docs/changelog/2026-07-30.mdx`: Records the split between pre-tag release entries and post-tag Announcements. - [#7876](#7876) -> `docs/changelog/2026-07-30.mdx`: Records the writable Hermes runtime root within lockdown. - [#7756](#7756) -> `docs/changelog/2026-07-30.mdx`: Records validated multi-platform managed-image publication. - [#7914](#7914) -> `docs/changelog/2026-07-30.mdx`: Records accepted `uv` version metadata in Hermes image validation. - [#7686](#7686) -> `docs/changelog/2026-07-30.mdx`: Records the explicitly experimental Microsoft Entra runtime identity reference. - [#7869](#7869) -> `docs/changelog/2026-07-30.mdx`: Records classified gateway relaunch quarantine and rebuild guidance. - [#7814](#7814) -> `docs/changelog/2026-07-30.mdx`: Records state restore into replacement sandboxes and SQLite write verification. - [#7839](#7839) -> `docs/changelog/2026-07-30.mdx`: Records quieter onboarding test execution without a user-facing behavior claim. - [#7854](#7854) -> `docs/changelog/2026-07-30.mdx`: Records generalized agent-selection guidance. - [#7845](#7845) -> `docs/changelog/2026-07-30.mdx`: Records isolated CDI test evidence without a user-facing behavior claim. - [#7843](#7843) -> `docs/changelog/2026-07-30.mdx`: Records the corrected Omni sub-agent model ID. - [#7908](#7908) -> `docs/changelog/2026-07-30.mdx`: Records reviewed Hermes and Deep Agents Code dependency pins. - [#7887](#7887) -> `docs/changelog/2026-07-30.mdx`: Records rejection of a symlinked DGX Station release marker. - [#7747](#7747) -> `docs/changelog/2026-07-30.mdx`: Records the internal compute-driver separation without a user-facing behavior claim. - [#7660](#7660) -> `docs/changelog/2026-07-30.mdx`: Records atomic publication of rebuild recovery manifests. - [#7661](#7661) -> `docs/changelog/2026-07-30.mdx`: Records bounded local inference health-response retention. - [#7654](#7654) -> `docs/changelog/2026-07-30.mdx`: Records state preservation across supervisor relaunch recovery. ## 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: `test/changelog-docs.test.ts` validates the dated changelog contract, SPDX comment, version heading, and published routes. - [ ] 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-30.mdx`; the documentation-only diff passed review against `WRITING.md`, the controlled word list, and `docs/CONTRIBUTING.md`. The review covered terminology, structure, active voice, release meaning, product-scope boundaries, and link and code presentation. Changelog tests passed 6/6, and the docs build reported 0 errors with 2 pre-existing warnings. - Agent: Codex CLI <!-- docs-review-head-sha: 200940f --> <!-- docs-review-agents-blob-sha: c052d60 --> ## DGX Station Hardware Evidence - [ ] Tested on DGX Station - Tested commit: - Station profile/scenario: - Result: - Supporting evidence: ## 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 validate:pr` passed after refreshing `origin/main` when hooks were skipped or unavailable - [x] Targeted behavior tests pass for the current change set, or tests are marked not applicable above — command/result or justification: `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 this documentation-only release 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) — result: Build passed with 0 errors and 2 pre-existing 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) --- Signed-off-by: San Dang <sdang@nvidia.com> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Added release notes for v0.0.99 covering snapshot restoration, sandbox recovery, gateway route upgrades, and Hermes security updates. * Documented experimental Microsoft Entra runtime identity support and enhanced readiness checks. * Added details on managed image validation, trusted CI image promotion, and end-to-end release evidence. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
Summary
Prevent legacy multi-sandbox upgrades from destroying the first sandbox when a sibling on the same OpenShell gateway records the same inference route without its credential environment name. Rebuild now migrates only missing canonical credential identities under the registry lock and revalidates the shared route at the delete edge; explicit route conflicts still fail closed before deletion.
Related Issue
Fixes #7798
Changes
Type of Change
Quality Gates
Documentation Writer Review
docs-updateddocs/inference/use-shared-gateway-routes.mdx,docs/reference/commands.mdx;npm run docscompleted with 0 errors.DGX Station Hardware Evidence
scripts/prepare-dgx-station-host.shis unchanged.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 unavailablenpx vitest run --project cli src/lib/actions/sandbox/rebuild-route-preflight.test.ts src/lib/actions/sandbox/rebuild-destroy-phase.test.ts src/lib/actions/sandbox/rebuild-flow.test.ts src/lib/actions/sandbox/rebuild-resume-snapshot.test.ts(144 passed);npm run typecheck:cli;npm run test:titles:check;npm run test:e2e-phases:check; focused E2E-support workflow tests (133 passed); live target discovery passed.npm testfor broad runtime/test-harness changes;npm run checkfor repo-wide validation/coverage changes — command/result: Live Docker/Brev upgrade execution is delegated to the added E2E CI scenario.npm run checksand the source-architecture budget passed locally.npm run docsbuilds without warnings (doc changes only)Signed-off-by: San Dang sdang@nvidia.com
Signed-off-by: Prekshi Vyas prekshiv@nvidia.com
Summary by CodeRabbit