Skip to content

fix(onboard): recreate on fresh model drift#6317

Closed
chengjiew wants to merge 4 commits into
mainfrom
fix/6311_fresh_reonboard_model
Closed

fix(onboard): recreate on fresh model drift#6317
chengjiew wants to merge 4 commits into
mainfrom
fix/6311_fresh_reonboard_model

Conversation

@chengjiew

@chengjiew chengjiew commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Summary

Recreate an existing ready sandbox during fresh onboarding when the selected provider/model differs from the registry metadata. This prevents nemoclaw status from showing the new model while the live in-sandbox agent keeps running the previous startup configuration.

Related Issue

Fixes #6311

Changes

  • Detect provider/model drift from the sandbox registry before deciding whether sandbox setup may reuse an existing sandbox.
  • Force the normal recreate path for fresh/re-onboard provider/model drift while preserving registry metadata until recreate backup/deletion runs.
  • Add regression coverage for fresh provider/model drift and the lower sandbox resume decision.

Type of Change

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

Quality Gates

  • Tests added or updated for changed behavior
  • Existing tests cover changed behavior — justification:
  • Tests not applicable — justification:
  • Docs updated for user-facing behavior changes
  • Docs not applicable — justification: behavior now matches the existing fresh/re-onboard expectation; no CLI surface or user workflow text changed.
  • 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: self-reviewed the onboarding/sandbox recreate boundary; patch only changes reuse/recreate decision logic and preserves existing registry state until the established recreate backup/deletion path.
  • Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue:

Verification

  • PR description includes the DCO sign-off declaration and every commit appears as Verified in GitHub
  • Normal pre-commit, commit-msg, and pre-push hooks passed, or npm run check:diff passed when hooks were skipped or unavailable
  • Targeted behavior tests pass for the current change set, or tests are marked not applicable above — command/result or justification: NPM_CONFIG_CACHE=/tmp/nemoclaw-6311-npm-cache npx vitest run src/lib/onboard/machine/handlers/sandbox.test.ts src/lib/onboard/machine/handlers/sandbox-resume.test.ts --project cli passed, 40 tests.
  • Applicable broad gate passed — npm test for broad runtime/test-harness changes; npm run check for repo-wide validation/coverage changes — command/result: NPM_CONFIG_CACHE=/tmp/nemoclaw-6311-npm-cache npm run typecheck:cli passed.
  • Quality Gates section completed with required justifications or waivers
  • No secrets, API keys, or credentials committed
  • npm run docs builds without warnings (doc changes only)
  • Doc pages follow the style guide (doc changes only)
  • New doc pages include SPDX header and frontmatter (new pages only)

Signed-off-by: Chengjie Wang chengjiew@nvidia.com

Summary by CodeRabbit

  • Bug Fixes
    • Improved sandbox reuse decisions when the selected provider or model changes, including when prior provider/model metadata is missing or malformed.
    • Fresh runs now recreate existing sandboxes instead of reusing incompatible ones, with clearer messaging.
    • Recreate/restore now preserves state/skills while intentionally skipping restoration of generated config.toml to ensure the newly selected model is used.
    • Provider/model drift no longer removes registry entries, improving safety.
  • Documentation
    • Updated quickstart and command reference to reflect the new provider/model drift and config.toml restore behavior.
  • Tests
    • Added coverage for provider/model drift and fresh-run recreation behavior.

Signed-off-by: Chengjie Wang <chengjiew@nvidia.com>
@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@chengjiew, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 31 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 27a4b5e2-5ff8-4a4d-95e0-7c61eb5ecd70

📥 Commits

Reviewing files that changed from the base of the PR and between 5dc7631 and 290b1a2.

📒 Files selected for processing (3)
  • src/lib/onboard.ts
  • src/lib/state/sandbox.ts
  • test/deepagents-config-restore.test.ts
📝 Walkthrough

Walkthrough

This PR adds provider/model drift detection to sandbox resume handling and recreates sandboxes when the stored provider/model differs from the requested configuration. Recreate flows now preserve state while skipping restoration of config.toml, and the related docs and tests are updated accordingly.

Changes

Provider/model drift recreate flow

Layer / File(s) Summary
Drift detection helper
src/lib/onboard/machine/handlers/sandbox-drift.ts, src/lib/onboard/machine/handlers/sandbox-drift.test.ts, src/lib/onboard/machine/handlers/sandbox-test-fixtures.ts
Adds providerModelConfigChanged and tests for null, mismatched, missing, and malformed provider/model metadata; fixtures now include provider/model fields.
Resume decision on provider/model drift
src/lib/onboard/machine/handlers/sandbox-resume.ts, src/lib/onboard/machine/handlers/sandbox-resume.test.ts
Extends resume signals and recreate decisions, adds provider/model drift handling before existing resume checks, and updates tests for the new recreate path and notes.
Sandbox wiring and restore skip
src/lib/onboard/machine/handlers/sandbox.ts, src/lib/onboard/types.ts, src/lib/state/sandbox.ts, src/lib/onboard.ts, src/lib/onboard/machine/handlers/sandbox.test.ts, test/snapshot.test.ts, docs/get-started/quickstart-langchain-deepagents-code.mdx, docs/reference/commands-nemohermes.mdx, docs/reference/commands.mdx
Threads drift detection through sandbox handling, adds skip-restore state plumbing, skips restoring config.toml on recreate, and updates tests and docs to match the new restore behavior.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Suggested labels: bug-fix

Suggested reviewers: cjagwani, prekshivyas

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The config-set-cli-dispatch wait timeout change is unrelated to the onboarding model-drift fix. Remove that unrelated timeout tweak or explain why it is required for this onboarding fix.
✅ 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 is concise and accurately summarizes the fresh model-drift recreation fix.
Linked Issues check ✅ Passed The changes detect provider/model drift on fresh re-onboard, recreate the sandbox, and avoid restoring config.toml, matching #6311.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/6311_fresh_reonboard_model

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

@github-code-quality

github-code-quality Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

The overall coverage in the branch is 96%. Coverage data for the branch is not yet available.

Show a code coverage summary of the most covered files.
File dd78c51 +/-
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 branch is 71%. Coverage data for the branch is not yet available.

Show a code coverage summary of the most covered files.
File dd78c51 +/-
src/lib/shields...nsition-lock.ts 87%
src/lib/actions...all/run-plan.ts 81%
src/lib/state/o...oard-session.ts 81%
src/lib/onboard/preflight.ts 71%
src/lib/state/sandbox.ts 71%
src/lib/onboard...er-gpu-patch.ts 69%
src/lib/shields/index.ts 68%
src/lib/policy/index.ts 66%
src/lib/actions...licy-channel.ts 60%
src/lib/onboard.ts 24%

Updated July 06, 2026 10:28 UTC
Code Coverage is in Public Preview. Learn more and provide us with your feedback.

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

E2E Advisor Recommendation

Required E2E: onboard-resume, onboard-repair, cloud-onboard
Optional E2E: sandbox-operations

Dispatch hint: onboard-resume,onboard-repair,cloud-onboard

Workflow run

Full advisor summary

E2E Recommendation Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E

  • onboard-resume (live sandbox lifecycle; approximately 45 minute job timeout): Required by the onboarding resume rule: the PR changes sandbox resume decision signals and state-machine handling for reuse/recreate decisions.
  • onboard-repair (live sandbox lifecycle; approximately 75 minute job timeout): Required by the onboarding resume rule: changed decision ordering can interact with not-ready recorded sandbox repair and recreation paths.
  • cloud-onboard (hosted inference plus live sandbox lifecycle; approximately 70 minute job timeout): The sandbox state handler is used by full hosted onboarding, and the new provider/model drift recreation behavior can affect complete real user onboarding flows.

Optional E2E

  • sandbox-operations (live sandbox operations; approximately 60 minute job timeout): Useful adjacent confidence for sandbox lifecycle operations because the PR changes registry-preserving recreation behavior, but the resume-specific jobs are the merge-blocking coverage.

New E2E recommendations

  • provider/model drift recreation (high): Existing required E2E targets validate broad resume, repair, and full hosted onboarding, but may not explicitly assert the new fresh-run case where an existing ready sandbox with stored provider/model drift is recreated while preserving the registry row.
    • Suggested test: Add or extend a live onboarding E2E scenario to seed an existing sandbox registry entry with old provider/model values, run fresh onboarding with a different provider/model, and assert recreate=true behavior plus no direct registry removal.

Dispatch hint

  • Workflow: .github/workflows/e2e.yaml
  • jobs input: onboard-resume,onboard-repair,cloud-onboard

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

E2E Target Recommendation

Required E2E targets: onboard-resume, onboard-repair
Optional E2E targets: None

Dispatch required E2E targets:

  • gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=onboard-resume
  • gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=onboard-repair

Workflow run

Full E2E target advisor summary

E2E Target Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E targets

  • onboard-resume: Changes touch src/lib/onboard/machine sandbox resume handling and live slice orchestration. The onboarding resume rule requires the onboard-resume live E2E job for resume state-machine paths.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=onboard-resume
  • onboard-repair: The sandbox resume decision ordering now affects persisted sandbox recreation and can interact with repair/backstop behavior from persisted sessions, so onboard-repair is required and not optional for this state-machine resume path.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=onboard-repair

Optional E2E targets

  • None.

Relevant changed files

  • src/lib/onboard/machine/handlers/sandbox-resume.test.ts
  • src/lib/onboard/machine/handlers/sandbox-resume.ts
  • src/lib/onboard/machine/handlers/sandbox.test.ts
  • src/lib/onboard/machine/handlers/sandbox.ts

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor (Nemotron Ultra) — Changes requested

Merge posture: Do not merge yet
Primary next action: Fix PRA-2: Test monolith grew by 42 lines (now 850 lines) without extraction; then add or justify PRA-T1.
Open items: 1 required · 3 warnings · 4 suggestions · 7 test follow-ups
Since last review: 0 prior items resolved · 0 still apply · 7 new items found

Action checklist

  • PRA-2 Fix: Test monolith grew by 42 lines (now 850 lines) without extraction in src/lib/onboard/machine/handlers/sandbox.test.ts:167
  • PRA-1 Resolve or justify: Source-of-truth review needed: providerModelConfigChanged() null handling
  • PRA-3 Resolve or justify: Implementation monolith grew by 19 lines (now 700 lines) in src/lib/onboard/machine/handlers/sandbox.ts:1
  • PRA-4 Resolve or justify: Merge conflict risk with open PR feat(agents): introduce Firecrawl web search support #6273 (Firecrawl web search) in src/lib/onboard/machine/handlers/sandbox.ts:1
  • 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: Missing integration test for resume provider/model drift (resume=true)
  • PRA-T5 Add or justify test follow-up: Missing test for legacy registry entry missing provider/model fields
  • PRA-T6 Add or justify test follow-up: Acceptance clause
  • PRA-T7 Add or justify test follow-up: providerModelConfigChanged() null handling
  • PRA-5 In-scope improvement: Missing test for 'onboard' fallback path (fresh=false, resume=false) in src/lib/onboard/machine/handlers/sandbox-resume.ts:102
  • PRA-6 In-scope improvement: providerModelConfigChanged treats missing registry provider/model as no-drift in src/lib/onboard/machine/handlers/sandbox.ts:180
  • PRA-7 In-scope improvement: Missing integration test for resume provider/model drift (resume=true) in src/lib/onboard/machine/handlers/sandbox.test.ts:167
  • PRA-8 In-scope improvement: Missing test for legacy registry entry missing provider/model fields in src/lib/onboard/machine/handlers/sandbox.test.ts:167

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 Required architecture src/lib/onboard/machine/handlers/sandbox.test.ts:167 Extract sandbox handler tests into focused files (e.g., sandbox-resume.integration.test.ts, sandbox-recreate.test.ts, sandbox-messaging.test.ts) or justify why growth is acceptable in this PR.
PRA-3 Resolve/justify architecture src/lib/onboard/machine/handlers/sandbox.ts:1 Review whether providerModelConfigChanged and related drift helpers can be extracted to a shared sandbox-drift.ts module, similar to how sandbox-resume.ts was extracted.
PRA-4 Resolve/justify workflow src/lib/onboard/machine/handlers/sandbox.ts:1 Coordinate with PR #6273 author. Consider rebasing this PR on top of #6273 or vice versa to resolve conflicts early.
PRA-5 Improvement correctness src/lib/onboard/machine/handlers/sandbox-resume.ts:102 Add a test case for the 'onboard' fallback path (fresh=false, resume=false, providerModelConfigChanged=true) to verify note shows '[onboard]' and behavior is correct.
PRA-6 Improvement correctness src/lib/onboard/machine/handlers/sandbox.ts:180 Verify that createSandbox() always writes provider/model to registry. If not, fix at source (sandbox-create-plan.ts or createSandbox caller) so drift detection is reliable for all sandboxes.
PRA-7 Improvement tests src/lib/onboard/machine/handlers/sandbox.test.ts:167 Add integration test: 'recreates on resume when provider/model drifts' with resume=true, fresh=false.
PRA-8 Improvement tests src/lib/onboard/machine/handlers/sandbox.test.ts:167 Add integration test for legacy registry entry missing provider/model fields — verify drift detection still works or document limitation.

🚨 Required before merge

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

PRA-2 Required — Test monolith grew by 42 lines (now 850 lines) without extraction

  • Location: src/lib/onboard/machine/handlers/sandbox.test.ts:167
  • Category: architecture
  • Problem: sandbox.test.ts added integration test for fresh provider/model drift but file is already a monolith hotspot (808 lines at base). Each PR adding tests without extraction compounds maintenance burden and makes focused testing harder.
  • Impact: Harder to run focused tests; increased CI time; harder to review changes; risk of flaky tests coupling unrelated behaviors.
  • Required action: Extract sandbox handler tests into focused files (e.g., sandbox-resume.integration.test.ts, sandbox-recreate.test.ts, sandbox-messaging.test.ts) or justify why growth is acceptable in this PR.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Run `wc -l src/lib/onboard/machine/handlers/sandbox.test.ts` — shows 850 lines. Check git history for prior extraction attempts.
  • Missing regression test: No regression test needed — this is a code organization finding. Extraction would be validated by existing test suite passing.
  • Done when: The required change is committed and verification passes: Run `wc -l src/lib/onboard/machine/handlers/sandbox.test.ts` — shows 850 lines. Check git history for prior extraction attempts.
  • Evidence: Diff shows +42 lines in sandbox.test.ts. Drift context reports baseLines: 808, headLines: 850, delta: 42, severity: blocker.
Review findings by urgency: 1 required fix, 3 items to resolve/justify, 4 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: providerModelConfigChanged() null handling

  • 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: Add test: sandbox created without provider/model in registry (legacy) + fresh run with new provider/model → should still recreate (currently may not).
  • 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: providerModelConfigChanged() at sandbox.ts:180-187 returns false when existingProvider===null || existingModel===null

PRA-3 Resolve/justify — Implementation monolith grew by 19 lines (now 700 lines)

  • Location: src/lib/onboard/machine/handlers/sandbox.ts:1
  • Category: architecture
  • Problem: sandbox.ts added providerModelConfigChanged helper and fresh signal wiring. File is a warning-level monolith hotspot (681 lines at base).
  • Impact: Harder to review changes; risk of coupling unrelated logic; future extractions will be harder.
  • Recommended action: Review whether providerModelConfigChanged and related drift helpers can be extracted to a shared sandbox-drift.ts module, similar to how sandbox-resume.ts was extracted.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Run `wc -l src/lib/onboard/machine/handlers/sandbox.ts` — shows 700 lines. Compare with sandbox-resume.ts (197 lines) which was successfully extracted.
  • Missing regression test: No regression test needed — this is a code organization finding.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Run `wc -l src/lib/onboard/machine/handlers/sandbox.ts` — shows 700 lines. Compare with sandbox-resume.ts (197 lines) which was successfully extracted.
  • Evidence: Diff shows +19 lines in sandbox.ts. Drift context reports baseLines: 681, headLines: 700, delta: 19, severity: warning.

PRA-4 Resolve/justify — Merge conflict risk with open PR #6273 (Firecrawl web search)

💡 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.

PRA-5 Improvement — Missing test for 'onboard' fallback path (fresh=false, resume=false)

  • Location: src/lib/onboard/machine/handlers/sandbox-resume.ts:102
  • Category: correctness
  • Problem: Note template uses ternary: fresh ? 'fresh' : resume ? 'resume' : 'onboard'. The 'onboard' fallback triggers when fresh=false and resume=false — represents a plain onboard run targeting existing sandbox with drift. Not tested.
  • Impact: Unverified code path; note may show wrong label; behavior may differ from fresh/resume paths.
  • Suggested action: Add a test case for the 'onboard' fallback path (fresh=false, resume=false, providerModelConfigChanged=true) to verify note shows '[onboard]' and behavior is correct.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Call decideSandboxResume with {fresh:false, resume:false, sandboxStepComplete:true, providerModelConfigChanged:true, sandboxReuseState:'ready'} and verify note contains '[onboard]'.
  • Missing regression test: Add unit test: 'recreates on plain onboard when provider/model drifts' with fresh=false, resume=false expecting note containing '[onboard]'.
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: sandbox-resume.ts:102 note template: `[${signals.fresh ? "fresh" : signals.resume ? "resume" : "onboard"}]`. No test covers fresh=false, resume=false.

PRA-6 Improvement — providerModelConfigChanged treats missing registry provider/model as no-drift

  • Location: src/lib/onboard/machine/handlers/sandbox.ts:180
  • Category: correctness
  • Problem: providerModelConfigChanged() returns false when existing.provider or existing.model is null (sandbox.ts:180-187). This means old registry entries without provider/model fields won't trigger recreation on drift. Workaround handles common case but doesn't fix root cause: registry entries should always have provider/model populated at sandbox creation.
  • Impact: Legacy sandboxes created before provider/model tracking will silently reuse instead of recreating on drift — same bug as Issue [All Platforms][Onboard] --fresh re-onboard keeps the old in-sandbox model — nemoclaw status shows the new model while the agent still runs the previous one #6311 for old sandboxes.
  • Suggested action: Verify that createSandbox() always writes provider/model to registry. If not, fix at source (sandbox-create-plan.ts or createSandbox caller) so drift detection is reliable for all sandboxes.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Search for updateSandboxRegistry calls in sandbox-create-plan.ts and sandbox.ts — confirm provider/model are always written.
  • Missing regression test: Add test: sandbox created without provider/model in registry (legacy) + fresh run with new provider/model → should still recreate (currently may not).
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: providerModelConfigChanged() at sandbox.ts:180-187 returns false when existingProvider===null || existingModel===null.

PRA-7 Improvement — Missing integration test for resume provider/model drift (resume=true)

  • Location: src/lib/onboard/machine/handlers/sandbox.test.ts:167
  • Category: tests
  • Problem: Integration test covers fresh drift (fresh=true) but not resume drift (resume=true). Both paths use same decision function but may have different side effects.
  • Impact: Resume drift path untested at integration level; could have different registry/messaging behavior.
  • Suggested action: Add integration test: 'recreates on resume when provider/model drifts' with resume=true, fresh=false.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Run vitest with filter for new test name; verify createSandbox called with recreate:true and removeRegistryEntry:false.
  • Missing regression test: Add integration test in sandbox.test.ts: 'recreates an existing ready sandbox on resume provider/model drift' with resume=true, fresh=false.
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: Only fresh drift integration test exists (sandbox.test.ts:167-189). Resume drift not covered.

PRA-8 Improvement — Missing test for legacy registry entry missing provider/model fields

  • Location: src/lib/onboard/machine/handlers/sandbox.test.ts:167
  • Category: tests
  • Problem: No test verifies drift detection behavior when registry entry lacks provider/model (legacy sandbox). Current code treats null as no-drift — may silently fail to recreate.
  • Impact: Users with pre-existing sandboxes may not get drift recreation; same symptom as Issue [All Platforms][Onboard] --fresh re-onboard keeps the old in-sandbox model — nemoclaw status shows the new model while the agent still runs the previous one #6311.
  • Suggested action: Add integration test for legacy registry entry missing provider/model fields — verify drift detection still works or document limitation.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Create test with getSandboxRegistryEntry returning {name: 'old', toolDisclosure: 'progressive'} (no provider/model) + fresh run with new provider/model → check if recreate triggered.
  • Missing regression test: Add test: 'recreates legacy sandbox without provider/model in registry when fresh drift detected' — expects recreate decision.
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: providerModelConfigChanged() returns false for null provider/model (sandbox.ts:180-187). No test covers this case.
Simplification opportunities: 3 possible cuts, net -52 lines possible

These are safe simplification checks only. Do not remove validation, security controls, data-loss prevention, or required tests.

  • PRA-2 delete (src/lib/onboard/machine/handlers/sandbox.test.ts:167): Extract integration tests into separate files by behavior domain
    • Replacement: Multiple focused test files (sandbox-resume.integration.test.ts, sandbox-recreate.test.ts, sandbox-messaging.test.ts)
    • Net: -42 lines
    • Safety boundary: All existing tests must continue to pass; no behavior changes
  • PRA-3 shrink (src/lib/onboard/machine/handlers/sandbox.ts:1): providerModelConfigChanged() helper (7 lines) and drift detection logic
    • Replacement: Shared sandbox-drift.ts module with pure drift-detection functions
    • Net: -7 lines
    • Safety boundary: Credential validation before registry mutation (sandbox.ts:597-599) must remain in recreate path
  • PRA-6 native (src/lib/onboard/machine/handlers/sandbox.ts:180): Workaround null-check logic in providerModelConfigChanged
    • Replacement: Guarantee provider/model always written at sandbox creation; simplify to direct string comparison
    • Net: -3 lines
    • Safety boundary: Must not break existing sandboxes; migration path needed for legacy entries
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 — Add integration test for resume provider/model drift (resume=true, fresh=false). Runtime/sandbox/infrastructure paths need behavioral runtime validation: provider/model drift detection affects sandbox lifecycle (recreate vs reuse) which involves Docker/OpenShell operations not fully covered by unit mocks.
  • PRA-T2 Runtime validation — Add integration test for legacy registry entry missing provider/model fields. Runtime/sandbox/infrastructure paths need behavioral runtime validation: provider/model drift detection affects sandbox lifecycle (recreate vs reuse) which involves Docker/OpenShell operations not fully covered by unit mocks.
  • PRA-T3 Runtime validation — Add unit test for plain onboard (fresh=false, resume=false) drift path. Runtime/sandbox/infrastructure paths need behavioral runtime validation: provider/model drift detection affects sandbox lifecycle (recreate vs reuse) which involves Docker/OpenShell operations not fully covered by unit mocks.
  • PRA-T4 Missing integration test for resume provider/model drift (resume=true) — Add integration test: 'recreates on resume when provider/model drifts' with resume=true, fresh=false.
  • PRA-T5 Missing test for legacy registry entry missing provider/model fields — Add integration test for legacy registry entry missing provider/model fields — verify drift detection still works or document limitation.
  • PRA-T6 Acceptance clause — Plain onboard (non-fresh, non-resume) with provider/model drift should recreate — add test evidence or identify existing coverage. Code handles it (note shows '[onboard]') but no test covers fresh=false, resume=false path
  • PRA-T7 providerModelConfigChanged() null handling — Add test: sandbox created without provider/model in registry (legacy) + fresh run with new provider/model → should still recreate (currently may not).. providerModelConfigChanged() at sandbox.ts:180-187 returns false when existingProvider===null || existingModel===null
Since last review details

Current findings, using the urgency labels above:

PRA-1 Resolve/justify — Source-of-truth review needed: providerModelConfigChanged() null handling

  • 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: Add test: sandbox created without provider/model in registry (legacy) + fresh run with new provider/model → should still recreate (currently may not).
  • 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: providerModelConfigChanged() at sandbox.ts:180-187 returns false when existingProvider===null || existingModel===null

PRA-2 Required — Test monolith grew by 42 lines (now 850 lines) without extraction

  • Location: src/lib/onboard/machine/handlers/sandbox.test.ts:167
  • Category: architecture
  • Problem: sandbox.test.ts added integration test for fresh provider/model drift but file is already a monolith hotspot (808 lines at base). Each PR adding tests without extraction compounds maintenance burden and makes focused testing harder.
  • Impact: Harder to run focused tests; increased CI time; harder to review changes; risk of flaky tests coupling unrelated behaviors.
  • Required action: Extract sandbox handler tests into focused files (e.g., sandbox-resume.integration.test.ts, sandbox-recreate.test.ts, sandbox-messaging.test.ts) or justify why growth is acceptable in this PR.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Run `wc -l src/lib/onboard/machine/handlers/sandbox.test.ts` — shows 850 lines. Check git history for prior extraction attempts.
  • Missing regression test: No regression test needed — this is a code organization finding. Extraction would be validated by existing test suite passing.
  • Done when: The required change is committed and verification passes: Run `wc -l src/lib/onboard/machine/handlers/sandbox.test.ts` — shows 850 lines. Check git history for prior extraction attempts.
  • Evidence: Diff shows +42 lines in sandbox.test.ts. Drift context reports baseLines: 808, headLines: 850, delta: 42, severity: blocker.

PRA-3 Resolve/justify — Implementation monolith grew by 19 lines (now 700 lines)

  • Location: src/lib/onboard/machine/handlers/sandbox.ts:1
  • Category: architecture
  • Problem: sandbox.ts added providerModelConfigChanged helper and fresh signal wiring. File is a warning-level monolith hotspot (681 lines at base).
  • Impact: Harder to review changes; risk of coupling unrelated logic; future extractions will be harder.
  • Recommended action: Review whether providerModelConfigChanged and related drift helpers can be extracted to a shared sandbox-drift.ts module, similar to how sandbox-resume.ts was extracted.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Run `wc -l src/lib/onboard/machine/handlers/sandbox.ts` — shows 700 lines. Compare with sandbox-resume.ts (197 lines) which was successfully extracted.
  • Missing regression test: No regression test needed — this is a code organization finding.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Run `wc -l src/lib/onboard/machine/handlers/sandbox.ts` — shows 700 lines. Compare with sandbox-resume.ts (197 lines) which was successfully extracted.
  • Evidence: Diff shows +19 lines in sandbox.ts. Drift context reports baseLines: 681, headLines: 700, delta: 19, severity: warning.

PRA-4 Resolve/justify — Merge conflict risk with open PR #6273 (Firecrawl web search)

PRA-5 Improvement — Missing test for 'onboard' fallback path (fresh=false, resume=false)

  • Location: src/lib/onboard/machine/handlers/sandbox-resume.ts:102
  • Category: correctness
  • Problem: Note template uses ternary: fresh ? 'fresh' : resume ? 'resume' : 'onboard'. The 'onboard' fallback triggers when fresh=false and resume=false — represents a plain onboard run targeting existing sandbox with drift. Not tested.
  • Impact: Unverified code path; note may show wrong label; behavior may differ from fresh/resume paths.
  • Suggested action: Add a test case for the 'onboard' fallback path (fresh=false, resume=false, providerModelConfigChanged=true) to verify note shows '[onboard]' and behavior is correct.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Call decideSandboxResume with {fresh:false, resume:false, sandboxStepComplete:true, providerModelConfigChanged:true, sandboxReuseState:'ready'} and verify note contains '[onboard]'.
  • Missing regression test: Add unit test: 'recreates on plain onboard when provider/model drifts' with fresh=false, resume=false expecting note containing '[onboard]'.
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: sandbox-resume.ts:102 note template: `[${signals.fresh ? "fresh" : signals.resume ? "resume" : "onboard"}]`. No test covers fresh=false, resume=false.

PRA-6 Improvement — providerModelConfigChanged treats missing registry provider/model as no-drift

  • Location: src/lib/onboard/machine/handlers/sandbox.ts:180
  • Category: correctness
  • Problem: providerModelConfigChanged() returns false when existing.provider or existing.model is null (sandbox.ts:180-187). This means old registry entries without provider/model fields won't trigger recreation on drift. Workaround handles common case but doesn't fix root cause: registry entries should always have provider/model populated at sandbox creation.
  • Impact: Legacy sandboxes created before provider/model tracking will silently reuse instead of recreating on drift — same bug as Issue [All Platforms][Onboard] --fresh re-onboard keeps the old in-sandbox model — nemoclaw status shows the new model while the agent still runs the previous one #6311 for old sandboxes.
  • Suggested action: Verify that createSandbox() always writes provider/model to registry. If not, fix at source (sandbox-create-plan.ts or createSandbox caller) so drift detection is reliable for all sandboxes.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Search for updateSandboxRegistry calls in sandbox-create-plan.ts and sandbox.ts — confirm provider/model are always written.
  • Missing regression test: Add test: sandbox created without provider/model in registry (legacy) + fresh run with new provider/model → should still recreate (currently may not).
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: providerModelConfigChanged() at sandbox.ts:180-187 returns false when existingProvider===null || existingModel===null.

PRA-7 Improvement — Missing integration test for resume provider/model drift (resume=true)

  • Location: src/lib/onboard/machine/handlers/sandbox.test.ts:167
  • Category: tests
  • Problem: Integration test covers fresh drift (fresh=true) but not resume drift (resume=true). Both paths use same decision function but may have different side effects.
  • Impact: Resume drift path untested at integration level; could have different registry/messaging behavior.
  • Suggested action: Add integration test: 'recreates on resume when provider/model drifts' with resume=true, fresh=false.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Run vitest with filter for new test name; verify createSandbox called with recreate:true and removeRegistryEntry:false.
  • Missing regression test: Add integration test in sandbox.test.ts: 'recreates an existing ready sandbox on resume provider/model drift' with resume=true, fresh=false.
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: Only fresh drift integration test exists (sandbox.test.ts:167-189). Resume drift not covered.

PRA-8 Improvement — Missing test for legacy registry entry missing provider/model fields

  • Location: src/lib/onboard/machine/handlers/sandbox.test.ts:167
  • Category: tests
  • Problem: No test verifies drift detection behavior when registry entry lacks provider/model (legacy sandbox). Current code treats null as no-drift — may silently fail to recreate.
  • Impact: Users with pre-existing sandboxes may not get drift recreation; same symptom as Issue [All Platforms][Onboard] --fresh re-onboard keeps the old in-sandbox model — nemoclaw status shows the new model while the agent still runs the previous one #6311.
  • Suggested action: Add integration test for legacy registry entry missing provider/model fields — verify drift detection still works or document limitation.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Create test with getSandboxRegistryEntry returning {name: 'old', toolDisclosure: 'progressive'} (no provider/model) + fresh run with new provider/model → check if recreate triggered.
  • Missing regression test: Add test: 'recreates legacy sandbox without provider/model in registry when fresh drift detected' — expects recreate decision.
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: providerModelConfigChanged() returns false for null provider/model (sandbox.ts:180-187). No test covers this case.

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 Jul 6, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor — Blocked

Merge posture: Do not merge until addressed
Primary next action: Fix PRA-2: Registry drift is not the source of truth for the stale live agent config in #6311; then add or justify PRA-T1.
Open items: 1 required · 2 warnings · 0 suggestions · 8 test follow-ups
Top item: Verify or fix stale in-sandbox config after fresh provider/model recreate

Action checklist

  • PRA-2 Fix: Registry drift is not the source of truth for the stale live agent config in [All Platforms][Onboard] --fresh re-onboard keeps the old in-sandbox model — nemoclaw status shows the new model while the agent still runs the previous one #6311 in src/lib/onboard/machine/handlers/sandbox.ts:400
  • PRA-1 Resolve or justify: Source-of-truth review needed: Fresh/re-onboard provider-model drift handling
  • PRA-3 Resolve or justify: Missing or malformed registry provider/model metadata is treated as reusable in src/lib/onboard/machine/handlers/sandbox.ts:306
  • 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: Runtime validation
  • PRA-T5 Add or justify test follow-up: Runtime validation
  • 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: Acceptance clause

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 Required acceptance src/lib/onboard/machine/handlers/sandbox.ts:400 Make the live agent configuration the enforced source of truth for this bug path. For provider/model drift, either prevent generated inference config files such as Deep Agents `config.toml` from being restored stale, rewrite them after restore, or verify the post-recreate in-sandbox config matches the requested provider/model before recording success. Keep the registry update after the live config has been generated or validated.
PRA-3 Resolve/justify security src/lib/onboard/machine/handlers/sandbox.ts:306 Fail closed for provider/model fidelity when a sandbox name exists and the registry entry lacks valid provider/model metadata, or derive the comparison from an authoritative live source. If legacy rows must be tolerated, explicitly backfill only after validating the live sandbox selection matches the requested selection.

🚨 Required before merge

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

PRA-2 Required — Registry drift is not the source of truth for the stale live agent config in #6311

  • Location: src/lib/onboard/machine/handlers/sandbox.ts:400
  • Category: acceptance
  • Problem: The new provider/model decision is based on `registryEntry.provider` and `registryEntry.model`, then the handler only tests that `createSandbox` is called with `{ recreate: true }`. The linked issue says `nemoclaw status` already reports the new provider/model while `/sandbox/.deepagents/config.toml` still contains the old provider/model after restore. Nearby source also shows Deep Agents declares `config.toml` as a restorable state file, and the generic recreate path restores backup state after sandbox creation. The current diff does not change restore filtering, does not inspect or rewrite the live agent config, and does not add a regression that proves status and the in-sandbox config agree after `--fresh` re-onboard.
  • Impact: A fresh re-onboard can still appear successful and record the requested provider/model while the agent uses a stale restored config, invalidating model comparison workflows and preserving the exact misleading status/live-runtime split reported by the issue.
  • Required action: Make the live agent configuration the enforced source of truth for this bug path. For provider/model drift, either prevent generated inference config files such as Deep Agents `config.toml` from being restored stale, rewrite them after restore, or verify the post-recreate in-sandbox config matches the requested provider/model before recording success. Keep the registry update after the live config has been generated or validated.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Read `agents/langchain-deepagents-code/manifest.yaml` for `state_files: - path: config.toml`, then read `src/lib/onboard.ts` around the backup/restore path that calls `sandboxState.restoreSandboxState(...)`; compare that with this PR's `providerModelConfigChanged(...)` call in `src/lib/onboard/machine/handlers/sandbox.ts` and the added tests, which only assert the mocked `createSandbox` arguments.
  • Missing regression test: Add a test named `fresh provider/model drift does not restore stale Deep Agents config.toml from pre-recreate backup` or `fresh re-onboard rewrites Deep Agents config.toml after workspace restore so it contains the requested provider/model`; the test should model a backup containing the old model and assert the final in-sandbox/generated config and registry/status metadata both contain the new selection.
  • Done when: The required change is committed and verification passes: Read `agents/langchain-deepagents-code/manifest.yaml` for `state_files: - path: config.toml`, then read `src/lib/onboard.ts` around the backup/restore path that calls `sandboxState.restoreSandboxState(...)`; compare that with this PR's `providerModelConfigChanged(...)` call in `src/lib/onboard/machine/handlers/sandbox.ts` and the added tests, which only assert the mocked `createSandbox` arguments.
  • Evidence: Issue [All Platforms][Onboard] --fresh re-onboard keeps the old in-sandbox model — nemoclaw status shows the new model while the agent still runs the previous one #6311 states: "status and the in-sandbox config disagree" and "the restored state includes the old agent inference config, overriding the newly requested one." The diff adds registry comparison in `providerModelConfigChanged(...)` and handler coverage for `createSandbox(..., { recreate: true, ... })`, but no restore/config assertion.
Review findings by urgency: 1 required fix, 2 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: Fresh/re-onboard provider-model drift handling

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as missing.
  • 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: Missing: add coverage that creates or simulates a backup with old Deep Agents `config.toml`, performs fresh same-name provider/model re-onboard, and asserts the final live config and status metadata both contain the new selection.
  • 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: The issue identifies restore of old inference config as the stale source. The diff compares `registryEntry.provider/model` and tests mocked `createSandbox` arguments, not final live config.

PRA-3 Resolve/justify — Missing or malformed registry provider/model metadata is treated as reusable

  • Location: src/lib/onboard/machine/handlers/sandbox.ts:306
  • Category: security
  • Problem: `providerModelConfigChanged(...)` only reports drift when an existing registry provider or model is a string and differs from the requested value. If either field is absent, null, or malformed, the helper returns false for that field. On a completed ready sandbox with no other drift signals, that can preserve reuse even though the sandbox lifecycle cannot prove the live sandbox was created for the requested provider/model.
  • Impact: Older, corrupted, or partially migrated registry rows can bypass the new provider/model recreation guard. In a sandbox lifecycle path, fail-open reuse of an unverified inference selection can continue running the wrong model while host-side metadata appears current.
  • Recommended action: Fail closed for provider/model fidelity when a sandbox name exists and the registry entry lacks valid provider/model metadata, or derive the comparison from an authoritative live source. If legacy rows must be tolerated, explicitly backfill only after validating the live sandbox selection matches the requested selection.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read `providerModelConfigChanged(...)` and confirm that `existingProvider === null` and `existingModel === null` both make the function return false unless the other present field differs.
  • Missing regression test: Add `fresh ready sandbox with missing registry provider/model metadata recreates or validates live selection before reuse` and `resume ready sandbox with malformed provider/model registry metadata does not silently reuse`.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read `providerModelConfigChanged(...)` and confirm that `existingProvider === null` and `existingModel === null` both make the function return false unless the other present field differs.
  • Evidence: The helper computes `existingProvider` and `existingModel` with `typeof ... === "string" ? ... : null`, then only compares non-null values to the requested provider/model.

💡 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 — fresh provider/model drift does not restore stale Deep Agents config.toml from pre-recreate backup. The changed path controls sandbox lifecycle and recreate semantics. Unit tests cover decision routing, but the reported bug spans backup, delete/recreate, restore, agent config generation, and status/live-config agreement.
  • PRA-T2 Runtime validation — fresh re-onboard rewrites Deep Agents config.toml after workspace restore so it contains the requested provider/model. The changed path controls sandbox lifecycle and recreate semantics. Unit tests cover decision routing, but the reported bug spans backup, delete/recreate, restore, agent config generation, and status/live-config agreement.
  • PRA-T3 Runtime validation — fresh re-onboard detects or repairs status/config mismatch when registry provider/model already matches the requested selection. The changed path controls sandbox lifecycle and recreate semantics. Unit tests cover decision routing, but the reported bug spans backup, delete/recreate, restore, agent config generation, and status/live-config agreement.
  • PRA-T4 Runtime validation — fresh ready sandbox with missing registry provider/model metadata recreates or validates live selection before reuse. The changed path controls sandbox lifecycle and recreate semantics. Unit tests cover decision routing, but the reported bug spans backup, delete/recreate, restore, agent config generation, and status/live-config agreement.
  • PRA-T5 Runtime validation — resume ready sandbox with malformed provider/model registry metadata does not silently reuse. The changed path controls sandbox lifecycle and recreate semantics. Unit tests cover decision routing, but the reported bug spans backup, delete/recreate, restore, agent config generation, and status/live-config agreement.
  • PRA-T6 Acceptance clause — On nemoclaw **v0.0.74**, re-onboarding an existing sandbox to a new provider/model with `--fresh` completes successfully (rc=0) but the agent inside the sandbox keeps running the **previous** model, while `nemoclaw status` reports the **new** model. — add test evidence or identify existing coverage. The diff detects provider/model differences from registry metadata and forces a recreate intent, but it does not verify the agent inside the sandbox is no longer using the previous model.
  • PRA-T7 Acceptance clause — The two disagree and there is no signal to the user that the agent is not on the model status claims. — add test evidence or identify existing coverage. The new decision emits `Provider/model selection changed; recreating sandbox.`, but there is no post-recreate status-vs-live-config check that would signal disagreement.
  • PRA-T8 Acceptance clause — During the re-onboard the CLI prints `Restoring workspace state from pre-recreate backup...`, and the restored state includes the old agent inference config, overriding the newly requested one. — add test evidence or identify existing coverage. The changed files do not alter backup/restore behavior or test restored agent inference config. Nearby `agents/langchain-deepagents-code/manifest.yaml` declares `config.toml` as a restorable state file.

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/lib/onboard/machine/handlers/sandbox-resume.ts (1)

63-75: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

canReuseSandbox's provider/model check is now unreachable.

decideSandboxResume (lines 151-152) returns early via providerModelDriftDecision whenever providerModelConfigChanged is true, before canReuseSandbox is ever invoked. The !signals.providerModelConfigChanged clause added at line 66 can therefore never evaluate to false in practice — it's dead defensive code given the current call order.

Low priority since it's harmless and could be read as an intentional invariant guard against future reordering.

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

In `@src/lib/onboard/machine/handlers/sandbox-resume.ts` around lines 63 - 75, The
provider/model guard in canReuseSandbox is unreachable because
decideSandboxResume already exits via providerModelDriftDecision when
providerModelConfigChanged is true. Remove the redundant
!signals.providerModelConfigChanged check from canReuseSandbox, or if you want
to keep it as an invariant guard, make that intent explicit in canReuseSandbox
and ensure it matches the current call order in decideSandboxResume.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/lib/onboard/machine/handlers/sandbox-resume.ts`:
- Around line 63-75: The provider/model guard in canReuseSandbox is unreachable
because decideSandboxResume already exits via providerModelDriftDecision when
providerModelConfigChanged is true. Remove the redundant
!signals.providerModelConfigChanged check from canReuseSandbox, or if you want
to keep it as an invariant guard, make that intent explicit in canReuseSandbox
and ensure it matches the current call order in decideSandboxResume.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: a3ce2d02-d835-46f1-a10c-8de456c08acc

📥 Commits

Reviewing files that changed from the base of the PR and between f0d2549 and dd78c51.

📒 Files selected for processing (4)
  • src/lib/onboard/machine/handlers/sandbox-resume.test.ts
  • src/lib/onboard/machine/handlers/sandbox-resume.ts
  • src/lib/onboard/machine/handlers/sandbox.test.ts
  • src/lib/onboard/machine/handlers/sandbox.ts

@wscurran wscurran added the v0.0.88 Release target label Jul 6, 2026
chengjiew added 2 commits July 7, 2026 01:01
Signed-off-by: Chengjie Wang <chengjiew@nvidia.com>
Signed-off-by: Chengjie Wang <chengjiew@nvidia.com>
@apurvvkumaria

Copy link
Copy Markdown
Collaborator

Thanks @chengjiew for the original investigation and implementation direction. #6332 supersedes this PR with live DCode identity validation, ownership-aware managed re-onboard restore, post-restore registry gating, and missing-metadata/custom-image coverage. Chengjie is credited as a co-author on the replacement commit.

Signed-off-by: Chengjie Wang <chengjiew@nvidia.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
test/snapshot.test.ts (1)

1396-1396: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use literal : for PATH, not path.delimiter.

Based on learnings, this test suite prefers the established POSIX separator : when building process.env.PATH, since these tests only run on Linux CI runners (Windows is limited to WSL e2e tests elsewhere).

♻️ Suggested fix
-      process.env.PATH = `${binDir}${path.delimiter}${oldPath || ""}`;
+      process.env.PATH = `${binDir}:${oldPath || ""}`;
🤖 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/snapshot.test.ts` at line 1396, The PATH setup in this snapshot test is
using a platform-dependent separator via path.delimiter, but this suite expects
the POSIX literal ":" because it runs on Linux CI. Update the PATH assignment in
the test setup to build the string with ":" directly, keeping the existing
binDir and oldPath handling intact.

Source: Learnings

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

Nitpick comments:
In `@test/snapshot.test.ts`:
- Line 1396: The PATH setup in this snapshot test is using a platform-dependent
separator via path.delimiter, but this suite expects the POSIX literal ":"
because it runs on Linux CI. Update the PATH assignment in the test setup to
build the string with ":" directly, keeping the existing binDir and oldPath
handling intact.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 7e71b935-c758-4c8f-8927-50e40128b9eb

📥 Commits

Reviewing files that changed from the base of the PR and between dd78c51 and 5dc7631.

📒 Files selected for processing (15)
  • docs/get-started/quickstart-langchain-deepagents-code.mdx
  • docs/reference/commands-nemohermes.mdx
  • docs/reference/commands.mdx
  • src/lib/onboard.ts
  • src/lib/onboard/machine/handlers/sandbox-drift.test.ts
  • src/lib/onboard/machine/handlers/sandbox-drift.ts
  • src/lib/onboard/machine/handlers/sandbox-resume.test.ts
  • src/lib/onboard/machine/handlers/sandbox-resume.ts
  • src/lib/onboard/machine/handlers/sandbox-test-fixtures.ts
  • src/lib/onboard/machine/handlers/sandbox.test.ts
  • src/lib/onboard/machine/handlers/sandbox.ts
  • src/lib/onboard/types.ts
  • src/lib/state/sandbox.ts
  • test/package-contract/cli/config-set-cli-dispatch.test.ts
  • test/snapshot.test.ts
✅ Files skipped from review due to trivial changes (2)
  • docs/get-started/quickstart-langchain-deepagents-code.mdx
  • docs/reference/commands-nemohermes.mdx
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/lib/onboard/machine/handlers/sandbox-resume.test.ts
  • src/lib/onboard/machine/handlers/sandbox.test.ts

@chengjiew chengjiew closed this Jul 6, 2026
apurvvkumaria added a commit that referenced this pull request Jul 6, 2026
## Summary

Keep managed Deep Agents Code runtime routing aligned with the
provider/model selected during same-name re-onboarding. The fix treats
the live `dcode identity` result as authoritative, reconciles
mixed-ownership `config.toml` state without restoring stale routing, and
publishes registry metadata only after the restored runtime is verified.

## Related Issue

Closes #6311

Supersedes #6317. This incorporates and extends @chengjiew's original
drift/recreate investigation; Chengjie is credited as a co-author on the
commit.

## Changes

- Recreate stock managed DCode sandboxes when live route, provider,
model, or endpoint identity is stale or unreadable; refuse unverifiable
reuse when the registry row is absent.
- Restore only four bounded display preferences from backed-up DCode
config: three booleans and the enumerated thread sort order. Keep fresh
`models`, `update`, and generated provider metadata authoritative, and
drop free-form or behavior-bearing backup settings.
- Perform the merge with bounded TOML parsing, regular-file checks,
same-directory staging, inode revalidation, `fsync`, and atomic
replacement.
- Validate the live restored selection before writing registry/status
metadata, and leave custom-image plus ordinary snapshot/rebuild restore
behavior unchanged.
- Keep generic hotspots bounded by extracting gateway failure handling,
DCode resume policy, and caller-authorized state-file restore policy
into focused modules.
- Add unit, handler, restore-boundary, and orchestration regression
coverage plus user-facing documentation.

## Type of Change

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

## Quality Gates

- [x] Tests added or updated for changed behavior
- [ ] Existing tests cover changed behavior — justification:
- [ ] Tests not applicable — justification:
- [x] Docs updated for user-facing behavior changes
- [ ] Docs not applicable — justification:
- [x] Sensitive paths changed (security, policy, credentials, preflight,
onboarding, inference, runner, sandbox, or messaging)
- [x] Sensitive-path review completed or maintainer-approved waiver
recorded — reviewer/approval link/justification: independent reviews
checked live identity parsing, restore ordering, custom-image
provenance, file safety, same-user atomic-replace assumptions, and
registry publication; all confirmed blockers were resolved.
- [ ] Non-success, skipped, or missing CI check accepted by maintainer —
check name, approval link, and follow-up issue:

## 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
- [x] Targeted behavior tests pass for the current change set, or tests
are marked not applicable above — command/result or justification:
focused CLI suites 67/67; snapshot, OpenClaw restore, and spawned
gateway integrations 53/53; final restore/finalization follow-ups 22/22
and prepared-context integration 2/2.
- [x] 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; this is a
scoped DCode onboarding/restore fix, and the targeted suites plus normal
repository hooks cover the changed boundaries.
- [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) — passed
with 0 errors and 2 existing unspecified 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)

---
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>


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

* **New Features**
* Managed Deep Agents Code onboarding and resume now verify live `dcode
identity` to detect selection drift and recreate sandboxes when
selections are unreadable or mismatched.
* Managed restores can merge backed-up `config.toml` while keeping
freshly generated model routing and provider metadata authoritative.
* **Bug Fixes**
* Prevents unverified managed DCode reuse when the expected registry
entry is missing.
* Improves gateway-start failure output by redacting sensitive
diagnostics and printing clearer remediation commands.
* **Documentation**
* Updated quickstart and command reference for revised restore behavior
and non-interactive recreation rules.
* **Tests**
* Added coverage for managed config merge ownership, selection drift,
and sandbox finalization/resume flows.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Chengjie Wang <chengjiew@nvidia.com>
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
Co-authored-by: Chengjie Wang <chengjiew@nvidia.com>
Co-authored-by: Carlos Villela <cvillela@nvidia.com>
@chengjiew

Copy link
Copy Markdown
Contributor Author

Thanks @apurvvkumaria, makes sense to me.

I’m good with superseding this PR in favor of #6332, and I appreciate you preserving the co-author credit.

@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 Jul 7, 2026
Hadar301 pushed a commit to Hadar301/NemoClaw-OpenShift that referenced this pull request Jul 12, 2026
## Summary

Keep managed Deep Agents Code runtime routing aligned with the
provider/model selected during same-name re-onboarding. The fix treats
the live `dcode identity` result as authoritative, reconciles
mixed-ownership `config.toml` state without restoring stale routing, and
publishes registry metadata only after the restored runtime is verified.

## Related Issue

Closes NVIDIA#6311

Supersedes NVIDIA#6317. This incorporates and extends @chengjiew's original
drift/recreate investigation; Chengjie is credited as a co-author on the
commit.

## Changes

- Recreate stock managed DCode sandboxes when live route, provider,
model, or endpoint identity is stale or unreadable; refuse unverifiable
reuse when the registry row is absent.
- Restore only four bounded display preferences from backed-up DCode
config: three booleans and the enumerated thread sort order. Keep fresh
`models`, `update`, and generated provider metadata authoritative, and
drop free-form or behavior-bearing backup settings.
- Perform the merge with bounded TOML parsing, regular-file checks,
same-directory staging, inode revalidation, `fsync`, and atomic
replacement.
- Validate the live restored selection before writing registry/status
metadata, and leave custom-image plus ordinary snapshot/rebuild restore
behavior unchanged.
- Keep generic hotspots bounded by extracting gateway failure handling,
DCode resume policy, and caller-authorized state-file restore policy
into focused modules.
- Add unit, handler, restore-boundary, and orchestration regression
coverage plus user-facing documentation.

## Type of Change

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

## Quality Gates

- [x] Tests added or updated for changed behavior
- [ ] Existing tests cover changed behavior — justification:
- [ ] Tests not applicable — justification:
- [x] Docs updated for user-facing behavior changes
- [ ] Docs not applicable — justification:
- [x] Sensitive paths changed (security, policy, credentials, preflight,
onboarding, inference, runner, sandbox, or messaging)
- [x] Sensitive-path review completed or maintainer-approved waiver
recorded — reviewer/approval link/justification: independent reviews
checked live identity parsing, restore ordering, custom-image
provenance, file safety, same-user atomic-replace assumptions, and
registry publication; all confirmed blockers were resolved.
- [ ] Non-success, skipped, or missing CI check accepted by maintainer —
check name, approval link, and follow-up issue:

## 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
- [x] Targeted behavior tests pass for the current change set, or tests
are marked not applicable above — command/result or justification:
focused CLI suites 67/67; snapshot, OpenClaw restore, and spawned
gateway integrations 53/53; final restore/finalization follow-ups 22/22
and prepared-context integration 2/2.
- [x] 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; this is a
scoped DCode onboarding/restore fix, and the targeted suites plus normal
repository hooks cover the changed boundaries.
- [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) — passed
with 0 errors and 2 existing unspecified 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)

---
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>


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

* **New Features**
* Managed Deep Agents Code onboarding and resume now verify live `dcode
identity` to detect selection drift and recreate sandboxes when
selections are unreadable or mismatched.
* Managed restores can merge backed-up `config.toml` while keeping
freshly generated model routing and provider metadata authoritative.
* **Bug Fixes**
* Prevents unverified managed DCode reuse when the expected registry
entry is missing.
* Improves gateway-start failure output by redacting sensitive
diagnostics and printing clearer remediation commands.
* **Documentation**
* Updated quickstart and command reference for revised restore behavior
and non-interactive recreation rules.
* **Tests**
* Added coverage for managed config merge ownership, selection drift,
and sandbox finalization/resume flows.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Chengjie Wang <chengjiew@nvidia.com>
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
Co-authored-by: Chengjie Wang <chengjiew@nvidia.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 v0.0.88 Release target

Projects

None yet

3 participants