Skip to content

refactor(onboard): extract config sync helpers#3299

Merged
cv merged 55 commits into
mainfrom
refactor/onboard-config-sync
May 12, 2026
Merged

refactor(onboard): extract config sync helpers#3299
cv merged 55 commits into
mainfrom
refactor/onboard-config-sync

Conversation

@cv
Copy link
Copy Markdown
Collaborator

@cv cv commented May 9, 2026

Summary

Extract sandbox config sync script helpers out of the large onboarding module. This continues the onboarding cleanup stack by isolating selection-config script generation and temp-file writing behind a focused module with direct tests.

Changes

  • Add src/lib/onboard/config-sync.ts for sandbox config sync script construction and sync script temp-file creation.
  • Update src/lib/onboard.ts to import the config sync helpers while preserving existing exports and call sites.
  • Add unit tests covering the generated sync script contents and mkdtemp-backed script file behavior.

Type of Change

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

Verification

  • npx prek run --all-files passes
  • npm test passes
  • Tests added or updated for new or changed behavior
  • No secrets, API keys, or credentials committed
  • Docs updated for user-facing behavior changes
  • make 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: Carlos Villela cvillela@nvidia.com

Summary by CodeRabbit

  • Refactor

    • Reorganized onboarding into smaller modules for clearer sandbox setup flow.
  • New Features

    • Added sandbox configuration sync utilities that generate and securely write sync scripts.
    • Added selection-drift detection to report when a sandbox’s provider or model differs from requested values.
  • Tests

    • Added comprehensive tests covering config sync and selection-drift behaviors.

Review Change Stack

@cv cv self-assigned this May 9, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 9, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 157b3b24-1e0c-4343-a98b-b57b3b2811b9

📥 Commits

Reviewing files that changed from the base of the PR and between e776625 and e6d0c46.

📒 Files selected for processing (1)
  • src/lib/onboard.ts

📝 Walkthrough

Walkthrough

This PR extracts selection-drift detection and config-sync script generation from src/lib/onboard.ts into two dedicated modules with tests. Selection-drift downloads and parses an existing sandbox config to compare provider/model; config-sync generates and writes a bash script to persist ProviderSelectionConfig. Onboard imports these modules and updates the drift call to pass { runOpenshell }.

Changes

Onboarding Helper Modularization

Layer / File(s) Summary
Selection-drift detection module and tests
src/lib/onboard/selection-drift.ts, src/lib/onboard/selection-drift.test.ts
New module exports SelectionDrift result type and helper functions to locate sandbox config via OpenShell, download and parse it, and compute drift between requested and existing provider/model values. Tests validate config discovery, download failures, successful reads with cleanup, and drift computation including unknown states.
Config-sync helpers module and tests
src/lib/onboard/config-sync.ts, src/lib/onboard/config-sync.test.ts
New module exports functions to generate bash script that writes ProviderSelectionConfig to ~/.nemoclaw/config.json and fixes permissions on /sandbox/.openclaw, and a helper to persist the script to a secure temporary file. Tests verify script content and structure, temp file lifecycle, and permission enforcement.
Onboard.ts refactoring and integration
src/lib/onboard.ts, test/onboard.test.ts
Main onboard file adds imports from new modules, removes inline implementations, replaces local SelectionDrift type with imported version, updates getSelectionDrift call to pass { runOpenshell } option, and removes now-delegated config-sync helpers. Test validation confirms call signatures and unknown behavior are correctly implemented in new modules.

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant getSelectionDrift
  participant readSandboxSelectionConfig
  participant OpenShell
  participant findSelectionConfigPath
  
  Caller->>getSelectionDrift: sandboxName, requestedProvider, requestedModel, {runOpenshell}
  getSelectionDrift->>readSandboxSelectionConfig: sandboxName, deps
  readSandboxSelectionConfig->>OpenShell: download sandbox config
  alt download succeeds
    OpenShell-->>readSandboxSelectionConfig: temp directory
    readSandboxSelectionConfig->>findSelectionConfigPath: locate config.json
    findSelectionConfigPath-->>readSandboxSelectionConfig: config path or null
    alt config found and valid
      readSandboxSelectionConfig-->>getSelectionDrift: ProviderSelectionConfig
      getSelectionDrift->>getSelectionDrift: compare provider/model
      getSelectionDrift-->>Caller: SelectionDrift with changed flags
    else config invalid
      readSandboxSelectionConfig-->>getSelectionDrift: null
      getSelectionDrift-->>Caller: SelectionDrift with unknown=true
    end
  else download fails
    OpenShell-->>readSandboxSelectionConfig: null
    readSandboxSelectionConfig-->>getSelectionDrift: null
    getSelectionDrift-->>Caller: SelectionDrift with unknown=true
  end
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A rabbit peeks at code, then grins,
Modules split where logic thins,
Drift detected, scripts written neat,
Tests ensure the paths all meet,
Hooray — the sandbox steps are complete!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main refactoring: extracting config sync helpers into a dedicated module, which aligns with the primary changes of moving buildSandboxConfigSyncScript and writeSandboxConfigSyncFile to a new src/lib/onboard/config-sync.ts file.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/onboard-config-sync

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

@cv cv marked this pull request as draft May 9, 2026 01:23
@copy-pr-bot
Copy link
Copy Markdown

copy-pr-bot Bot commented May 9, 2026

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.

@copy-pr-bot
Copy link
Copy Markdown

copy-pr-bot Bot commented May 9, 2026

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@cv cv added v0.0.40 Release target and removed v0.0.39 Release target labels May 12, 2026
@github-actions
Copy link
Copy Markdown
Contributor

E2E Advisor Recommendation

Required E2E: cloud-onboard-e2e
Optional E2E: double-onboard-e2e, onboard-resume-e2e, onboard-repair-e2e, openclaw-inference-switch-e2e, sandbox-survival-e2e, gpu-double-onboard-e2e

Dispatch hint: cloud-onboard-e2e,double-onboard-e2e,onboard-resume-e2e,onboard-repair-e2e,openclaw-inference-switch-e2e,sandbox-survival-e2e

Workflow run

Full advisor summary

Pi Semantic E2E Advisor

Base: origin/refactor/onboard-selection-drift
Head: HEAD
Confidence: high

Required E2E

  • cloud-onboard-e2e: Primary end-to-end exercise of the NemoClaw onboarding wizard where buildSandboxConfigSyncScript and writeSandboxConfigSyncFile are actually invoked to write ~/.nemoclaw/config.json and normalize /sandbox/.openclaw permissions inside the sandbox. This is the closest guardrail against a require/module-binding regression introduced by the extraction.

Optional E2E

  • double-onboard-e2e: Re-onboarding re-runs the sandbox config sync step, so it catches any regression in the extracted script path across repeat flows.
  • onboard-resume-e2e: Resume path re-enters the selection/config-sync portion of onboard; useful confidence that the new module is loaded correctly on partial state.
  • onboard-repair-e2e: Repair flow re-invokes onboarding helpers; covers the refactored require graph in a recovery scenario.
  • openclaw-inference-switch-e2e: Branch name references selection-drift; switching inference provider/model exercises the recreate-for-drift path that calls buildSandboxConfigSyncScript with the new ProviderSelectionConfig.
  • sandbox-survival-e2e: Exercises sandbox bring-up plus gateway restart recovery; verifies that post-refactor onboard produces a healthy sandbox that survives restarts.
  • gpu-double-onboard-e2e: GPU re-onboard path also exercises the sandbox config sync; useful optional coverage for the Ollama-backed selection drift case.

New E2E recommendations

  • None.

Dispatch hint

  • Workflow: .github/workflows/nightly-e2e.yaml
  • jobs input: cloud-onboard-e2e,double-onboard-e2e,onboard-resume-e2e,onboard-repair-e2e,openclaw-inference-switch-e2e,sandbox-survival-e2e

@cv cv changed the base branch from refactor/onboard-selection-drift to main May 12, 2026 21:36
@cv cv marked this pull request as ready for review May 12, 2026 21:36
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/lib/onboard.ts (1)

5959-5959: Consider a real onboarding E2E for the new getSelectionDrift() wiring.

This branch controls sandbox reuse vs. recreation, so an end-to-end pass like cloud-e2e or sandbox-operations-e2e would add confidence that the extracted helper still preserves the old decision path under a live gateway/sandbox.

As per coding guidelines, src/lib/onboard.ts: "This file contains core onboarding logic. Changes here affect the full sandbox creation and configuration flow."

🤖 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.ts` at line 5959, Add a focused end-to-end test that
validates the new getSelectionDrift wiring preserves the original sandbox reuse
vs recreation decision path under a live gateway; specifically exercise the
onboarding flow that calls getSelectionDrift(sandboxName, provider, model, {
runOpenshell }) and assert the sandbox is reused or recreated as expected.
Create or extend an existing E2E suite (e.g., cloud-e2e or
sandbox-operations-e2e) to run the full onboarding flow against a real
gateway/sandbox, mock only external dependencies not part of the gateway, and
cover both branches (reuse and recreate) to ensure behavior parity with the
previous implementation. Ensure the test reproduces conditions that lead to each
branch by controlling inputs (sandboxName, provider, model, runOpenshell) and
verifies side effects (sandbox ID, creation timestamp, or gateway responses)
rather than internal implementation details. Run the new test in CI alongside
other onboarding E2Es to catch regressions in src/lib/onboard.ts affecting
sandbox lifecycle decisions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/lib/onboard/selection-drift.test.ts`:
- Line 51: The test's assertion hardcodes a forward slash and will fail on
Windows; update the expectation in selection-drift.test.ts (the
expect.stringMatching(...) for the path returned from the function that uses
`${tmpDir}${path.sep}`) to be platform-agnostic by either using a regex that
accepts both separators (e.g. match [\/\\] at the end) or, better, compare the
basename (using path.basename) instead of the full path so the test does not
depend on path.sep.

In `@src/lib/onboard/selection-drift.ts`:
- Around line 51-52: Move the fs.mkdtempSync call into the try block so creation
failures are caught and handled by getSelectionDrift's existing error path;
declare tmpDir (e.g., let tmpDir: string | undefined) before the try, assign it
inside the try via fs.mkdtempSync(...), and in the finally block check tmpDir is
defined before attempting cleanup to avoid referencing an uninitialized
variable.

---

Nitpick comments:
In `@src/lib/onboard.ts`:
- Line 5959: Add a focused end-to-end test that validates the new
getSelectionDrift wiring preserves the original sandbox reuse vs recreation
decision path under a live gateway; specifically exercise the onboarding flow
that calls getSelectionDrift(sandboxName, provider, model, { runOpenshell }) and
assert the sandbox is reused or recreated as expected. Create or extend an
existing E2E suite (e.g., cloud-e2e or sandbox-operations-e2e) to run the full
onboarding flow against a real gateway/sandbox, mock only external dependencies
not part of the gateway, and cover both branches (reuse and recreate) to ensure
behavior parity with the previous implementation. Ensure the test reproduces
conditions that lead to each branch by controlling inputs (sandboxName,
provider, model, runOpenshell) and verifies side effects (sandbox ID, creation
timestamp, or gateway responses) rather than internal implementation details.
Run the new test in CI alongside other onboarding E2Es to catch regressions in
src/lib/onboard.ts affecting sandbox lifecycle decisions.
🪄 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: 7d8e1238-d387-44ff-82f9-8419ab6b2c63

📥 Commits

Reviewing files that changed from the base of the PR and between fc4a227 and 948f11e.

📒 Files selected for processing (8)
  • src/lib/onboard.ts
  • src/lib/onboard/compatible-endpoint-smoke.test.ts
  • src/lib/onboard/compatible-endpoint-smoke.ts
  • src/lib/onboard/config-sync.test.ts
  • src/lib/onboard/config-sync.ts
  • src/lib/onboard/selection-drift.test.ts
  • src/lib/onboard/selection-drift.ts
  • test/onboard.test.ts

Comment thread src/lib/onboard/selection-drift.test.ts Outdated
Comment thread src/lib/onboard/selection-drift.ts Outdated
@cv
Copy link
Copy Markdown
Collaborator Author

cv commented May 12, 2026

Addressed CodeRabbit's actionable inline comments in e776625:

  • Made the selection-drift temp-download path assertion platform-agnostic by checking the temp directory basename instead of hardcoding /.
  • Moved fs.mkdtempSync into the guarded try path and made cleanup conditional on successful temp-dir creation.
  • Added a regression test for temp-dir creation failure returning null without invoking OpenShell.

Validation run locally:

  • npm run typecheck:cli
  • npx vitest run src/lib/onboard/selection-drift.test.ts
  • npx vitest run test/onboard.test.ts --testNamePattern "interactive mode (reuses existing sandbox|deletes and recreates sandbox)|detects provider/model drift|prompts before destructive"

I did not add a new live gateway E2E for the nitpick in this refactor commit; the PR already has focused compiled-onboard coverage for reuse/recreate behavior, and the E2E advisor has identified cloud-onboard-e2e as the required validation workflow for live sandbox coverage.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/lib/onboard.ts (1)

5967-5967: Optional pre-merge safeguard: run the recommended onboarding E2Es.

Given this touches core onboarding flow, the targeted nightly E2E set is a good final confidence check.

As per coding guidelines, src/lib/onboard.ts is core onboarding logic and includes an explicit E2E test recommendation list.

🤖 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.ts` at line 5967, This change touches core onboarding logic
(the getSelectionDrift call using sandboxName, provider, model), so add a short
pre-merge safeguard: insert a clear comment or PR checklist entry adjacent to
the getSelectionDrift invocation reminding reviewers to run the recommended
onboarding nightly E2E suite (or link the specific E2E list), and/or update CI
config to include that targeted E2E job for changes under the onboarding module;
ensure the comment references getSelectionDrift, sandboxName, provider, and
model so reviewers know exactly where the E2E verification is required.
🤖 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.ts`:
- Line 5967: This change touches core onboarding logic (the getSelectionDrift
call using sandboxName, provider, model), so add a short pre-merge safeguard:
insert a clear comment or PR checklist entry adjacent to the getSelectionDrift
invocation reminding reviewers to run the recommended onboarding nightly E2E
suite (or link the specific E2E list), and/or update CI config to include that
targeted E2E job for changes under the onboarding module; ensure the comment
references getSelectionDrift, sandboxName, provider, and model so reviewers know
exactly where the E2E verification is required.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 85225b66-f66d-48ca-8fa4-83bb32b5a1e0

📥 Commits

Reviewing files that changed from the base of the PR and between 948f11e and e776625.

📒 Files selected for processing (3)
  • src/lib/onboard.ts
  • src/lib/onboard/selection-drift.test.ts
  • src/lib/onboard/selection-drift.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/lib/onboard/selection-drift.test.ts
  • src/lib/onboard/selection-drift.ts

Copy link
Copy Markdown
Contributor

@ericksoa ericksoa left a comment

Choose a reason for hiding this comment

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

Reviewed the current head e6d0c46. The helper extraction preserves the existing onboarding behavior while improving testability by injecting runOpenshell into selection-drift reads; the config sync script is unchanged in behavior and still avoids rewriting OpenClaw config. CodeRabbit's earlier findings are resolved on this head.\n\nLocal validation passed: npm run build:cli, npm run typecheck:cli, npm run format:check, npm run checks, npx vitest run src/lib/onboard/config-sync.test.ts src/lib/onboard/selection-drift.test.ts --testTimeout 60000, and npx vitest run test/onboard.test.ts --testTimeout 60000. Required GitHub checks are green.

@cv cv merged commit ef8b231 into main May 12, 2026
20 of 21 checks passed
@cv cv deleted the refactor/onboard-config-sync branch May 27, 2026 21:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

refactor This is a refactor of the code and/or architecture. v0.0.40 Release target

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants