fix(sandbox): seed default workspace templates when bootstrap is skipped#3318
Conversation
NemoClaw sets `agents.defaults.skipBootstrap=true` in openclaw.json so the gateway's first agent turn answers the caller's prompt instead of running OpenClaw's interactive identity-setup conversation. The flag is binary in OpenClaw 2026.4.24, though: it short-circuits ensureAgentWorkspace() before any of the bundled workspace templates (SOUL.md, USER.md, IDENTITY.md, AGENTS.md, TOOLS.md, HEARTBEAT.md) are written, leaving /sandbox/.openclaw/workspace/ empty. Add a `seed_default_workspace_templates` helper that copies the same bundled templates (skipping BOOTSTRAP.md, which would re-trigger the interactive turn) into the workspace whenever the directory is pristine. Wire it into both entrypoint paths — directly in non-root mode and via `gosu sandbox` in root mode so the seeded files inherit sandbox:sandbox ownership. Fixes #3240 Signed-off-by: Jason Ma <jama@nvidia.com> Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Enterprise Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughAdds seed_default_workspace_templates() to copy bundled workspace markdown templates into an empty, non-symlink workspace when bootstrapping is skipped; integrates the helper into non-root and root startup flows and adds tests for normal seeding, idempotency, and symlink safety. ChangesWorkspace Template Seeding
Sequence Diagram(s)sequenceDiagram
participant NonRoot as Non-root Startup
participant RootGosu as Root Startup (gosu sandbox)
participant Seed as seed_default_workspace_templates
participant Templates as BundledTemplatesDir
participant Workspace as /sandbox/.openclaw/workspace
NonRoot->>Seed: call after permission normalization
RootGosu->>Seed: call via gosu after provisioning
Seed->>Templates: read template markdown files
Seed->>Workspace: write selected files if workspace exists, empty, and not a symlink
Seed-->>NonRoot: return status
Seed-->>RootGosu: return status
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (3)
test/nemoclaw-start.test.ts (1)
1677-1816: ⚡ Quick winAssert that
seed_default_workspace_templatesis actually invoked in both startup paths.The harness defines a no-op stub, but current assertions don’t verify call-through. A regression removing the call sites could pass unnoticed.
Small assertion upgrade
- 'seed_default_workspace_templates() { :; }', + 'seed_default_workspace_templates() { echo "ORDER:seed"; }', ... expect(setup.result.stdout).toContain("ORDER:configure"); + expect(setup.result.stdout).toContain("ORDER:seed"); expect(setup.result.stdout).toContain("VALIDATE:");🤖 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/nemoclaw-start.test.ts` around lines 1677 - 1816, The test defines a no-op stub seed_default_workspace_templates() but doesn't assert it was invoked; modify runPreGatewaySetup's generated script to make seed_default_workspace_templates emit a recognizable marker (e.g., printf "ORDER:seed_default_workspace_templates\n" or "SEED_CALLED") when invoked, then update the final assertions in the "installs and validates..." test to check setup.result.stdout contains that marker (reference seed_default_workspace_templates and runPreGatewaySetup to locate where the stub is emitted and where to add the new expect on setup.result.stdout).scripts/nemoclaw-start.sh (2)
1486-1522: ⚡ Quick winGate seeding behind
skipBootstrap=trueto avoid changing bootstrap-enabled behavior.Right now seeding runs for any pristine workspace. If a config intentionally enables bootstrap, this may pre-populate files (without
BOOTSTRAP.md) and alter first-run behavior.Suggested guard (example)
seed_default_workspace_templates() { local workspace_dir="${1:-/sandbox/.openclaw/workspace}" local templates_dir="${2:-}" + local config_file="/sandbox/.openclaw/openclaw.json" + + # Only backfill when bootstrap is explicitly skipped. + if [ -f "$config_file" ]; then + python3 - "$config_file" <<'PY' >/dev/null 2>&1 || return 0 +import json, sys +cfg = json.load(open(sys.argv[1], "r", encoding="utf-8")) +raise SystemExit(0 if cfg.get("agents", {}).get("defaults", {}).get("skipBootstrap") is True else 1) +PY + fi + [ -e "$workspace_dir" ] || return 0 if [ -L "$workspace_dir" ]; then🤖 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 `@scripts/nemoclaw-start.sh` around lines 1486 - 1522, The seeding function seed_default_workspace_templates should only run when skipBootstrap=true to avoid altering bootstrap-enabled first-run behavior; add an early guard at the top of seed_default_workspace_templates that checks the skipBootstrap environment/config variable (e.g. [ "${skipBootstrap:-}" != "true" ] && return 0) before any workspace checks, so the rest of the function (the symlink check, pristine directory check, template_dir resolution, and file copy loop for AGENTS.md SOUL.md IDENTITY.md USER.md TOOLS.md HEARTBEAT.md) only executes when skipBootstrap is explicitly set to "true".
1476-1765: Run targeted E2E for this entrypoint change before merge.This script is startup-critical and some failure modes won’t be covered by unit tests alone; run the recommended
sandbox-survival-e2e,sandbox-operations-e2e, andcloud-e2ejobs for confidence.As per coding guidelines
scripts/nemoclaw-start.sh: “This file is a sandbox entrypoint script. Changes affect every sandbox boot and are invisible to unit tests … E2E test recommendation: sandbox-survival-e2e, sandbox-operations-e2e, cloud-e2e.”🤖 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 `@scripts/nemoclaw-start.sh` around lines 1476 - 1765, The change touches the sandbox entrypoint and must be verified by running the recommended end-to-end suites before merging: run sandbox-survival-e2e, sandbox-operations-e2e, and cloud-e2e to exercise startup/privilege paths; focus checks on migrate_legacy_layout, seed_default_workspace_templates, provision_agent_workspaces, and the non-root vs root branches (including gosu sandbox launch, gateway boot, and tmp/gateway log handling) to ensure no startup regressions or permission/ownership failures; fix any failures uncovered and only merge once all E2E jobs pass.
🤖 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 `@scripts/nemoclaw-start.sh`:
- Around line 1486-1522: The seeding function seed_default_workspace_templates
should only run when skipBootstrap=true to avoid altering bootstrap-enabled
first-run behavior; add an early guard at the top of
seed_default_workspace_templates that checks the skipBootstrap
environment/config variable (e.g. [ "${skipBootstrap:-}" != "true" ] && return
0) before any workspace checks, so the rest of the function (the symlink check,
pristine directory check, template_dir resolution, and file copy loop for
AGENTS.md SOUL.md IDENTITY.md USER.md TOOLS.md HEARTBEAT.md) only executes when
skipBootstrap is explicitly set to "true".
- Around line 1476-1765: The change touches the sandbox entrypoint and must be
verified by running the recommended end-to-end suites before merging: run
sandbox-survival-e2e, sandbox-operations-e2e, and cloud-e2e to exercise
startup/privilege paths; focus checks on migrate_legacy_layout,
seed_default_workspace_templates, provision_agent_workspaces, and the non-root
vs root branches (including gosu sandbox launch, gateway boot, and tmp/gateway
log handling) to ensure no startup regressions or permission/ownership failures;
fix any failures uncovered and only merge once all E2E jobs pass.
In `@test/nemoclaw-start.test.ts`:
- Around line 1677-1816: The test defines a no-op stub
seed_default_workspace_templates() but doesn't assert it was invoked; modify
runPreGatewaySetup's generated script to make seed_default_workspace_templates
emit a recognizable marker (e.g., printf
"ORDER:seed_default_workspace_templates\n" or "SEED_CALLED") when invoked, then
update the final assertions in the "installs and validates..." test to check
setup.result.stdout contains that marker (reference
seed_default_workspace_templates and runPreGatewaySetup to locate where the stub
is emitted and where to add the new expect on setup.result.stdout).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: b68fac50-3e2e-4745-967c-a550a1729deb
📒 Files selected for processing (2)
scripts/nemoclaw-start.shtest/nemoclaw-start.test.ts
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Selective E2E Results — ✅ All requested jobs passedRun: 25649846723
|
ericksoa
left a comment
There was a problem hiding this comment.
Approved after reviewing the current head and follow-up hardening. The workspace seeding is now gated on skipBootstrap, strips OpenClaw template frontmatter, preserves no-clobber and symlink safety behavior, and is covered by focused local tests plus green PR checks and targeted nightly E2E.
## Summary Refreshes the release-prep docs for v0.0.39 based on changes merged since the Friday 4pm doc refresh. Updates the source docs, bumps the docs version metadata, and regenerates the NemoClaw user skills from the refreshed docs. ## Changes - #3314 -> `docs/get-started/prerequisites.md`, `docs/get-started/quickstart.md`, `docs/reference/troubleshooting.md`: Documents installer Docker setup, Docker group activation, and retry guidance. - #3317 -> `docs/get-started/quickstart.md`, `docs/reference/commands.md`: Documents the DGX Spark and DGX Station express install prompt and `NEMOCLAW_NO_EXPRESS`. - #3328 and #3329 -> `docs/security/best-practices.md`, `docs/deployment/sandbox-hardening.md`: Updates sandbox capability hardening docs for the stricter bounding-set and `setpriv` step-down behavior. - #3330, #3335, and #3346 -> `docs/inference/use-local-inference.md`: Documents Windows-host Ollama relaunch behavior, NIM key passthrough, early health-fail diagnostics, and mixed-GPU preflight detail. - #2406, #2883, #3001, #3244, #3267, #3318, #3320, and #3354 -> `docs/about/release-notes.md`: Adds the v0.0.39 release-prep section while keeping the v0.0.38 release notes intact. - Advances the release-prep docs metadata from v0.0.38 to v0.0.39. - Regenerates `.agents/skills/nemoclaw-user-*` from the updated source docs. ## Type of Change - [ ] Code change (feature, bug fix, or refactor) - [ ] Code change with doc updates - [ ] Doc only (prose changes, no code sample modifications) - [x] Doc only (includes code sample changes) ## Verification - [x] `npx prek run --all-files` passes - [ ] `npm test` passes - [ ] Tests added or updated for new or changed behavior - [x] No secrets, API keys, or credentials committed - [x] Docs updated for user-facing behavior changes - [x] `make docs` builds without warnings (doc changes only) - [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: Miyoung Choi <miyoungc@nvidia.com> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes v0.0.39 * **New Features** * Host alias management commands for easier configuration * Sandbox GPU control options during onboarding * Update command with check and confirmation modes * **Documentation** * Enhanced Linux installer guidance with Docker and group membership handling * Expanded troubleshooting for permission and connectivity issues * Improved capability-dropping security documentation * Updated inference model switching commands * Brev environment-specific troubleshooting * **Improvements** * DGX Spark/Station express install flow * Windows Ollama relay and health-check enhancements * NVIDIA NIM preflight GPU reporting [](https://app.coderabbit.ai/change-stack/NVIDIA/NemoClaw/pull/3375) <!-- end of auto-generated comment: release notes by coderabbit.ai -->
Summary
NemoClaw bakes
agents.defaults.skipBootstrap=trueinto the openclaw.json shipped in every sandbox image to suppress OpenClaw's interactive identity-setup turn on first boot. In OpenClaw 2026.4.24 that flag is binary — it short-circuitsensureAgentWorkspace()before any of the bundled workspace templates are written, leaving/sandbox/.openclaw/workspace/empty for users who expect the documentedSOUL.md/USER.md/IDENTITY.md/AGENTS.mdfiles to appear afternemoclaw onboard. This PR adds a smallseed_default_workspace_templateshelper that copies the same bundled templates from the npm-installed OpenClaw package into the workspace whenever the directory is pristine, while still skippingBOOTSTRAP.mdso the non-interactive boot contract is preserved.Related Issue
Fixes #3240
Changes
scripts/nemoclaw-start.sh: addseed_default_workspace_templates()that copiesAGENTS.md/SOUL.md/IDENTITY.md/USER.md/TOOLS.md/HEARTBEAT.mdfrom$(npm root -g)/openclaw/dist/docs/reference/templates/into the workspace if-and-only-if the workspace dir is empty and not a symlink.BOOTSTRAP.mdis intentionally excluded.scripts/nemoclaw-start.sh: invoke the helper from both the non-root entrypoint path (afterfix_openclaw_ownership) and the root path (viagosu sandboxso seeded files inheritsandbox:sandboxownership).test/nemoclaw-start.test.ts: add three behavior tests covering the happy path, the no-clobber guarantee for non-empty workspaces, and the symlink refusal. Also stub the new function in the existing Telegram-diagnosticsrunPreGatewaySetuphelper to keep it consistent with the long list of other entrypoint stubs.Type of Change
Verification
npx prek run --all-filespassesnpm testpassesmake docsbuilds without warnings (doc changes only)Verification notes
Ran locally in a fresh worktree (with the parent's
node_modulesanddist/symlinked in):test/nemoclaw-start.test.ts(49 tests) passes.npx prek run --files scripts/nemoclaw-start.sh test/nemoclaw-start.test.ts:shellcheck,Source-shape test budget,SPDX license headers,Biome,markdownlint,gitleaks, all pass.Test (CLI)prek hook andnpm testboth surface pre-existing TS errors insrc/lib/commands/setup.ts,src/lib/recover-cli-command.ts, etc. (Cannot find module '@oclif/core'plus a handful of property errors). These reproduce on plainmainin the same worktree, so they are not caused by this PR — but I left those boxes unchecked rather than claim a green run I did not actually get. CI will give a clean signal.Signed-off-by: Jason Ma jama@nvidia.com
Summary by CodeRabbit
New Features
Tests