Skip to content

fix(sandbox): seed default workspace templates when bootstrap is skipped#3318

Merged
ericksoa merged 3 commits into
mainfrom
worktree-fix-3240-seed-workspace-templates
May 11, 2026
Merged

fix(sandbox): seed default workspace templates when bootstrap is skipped#3318
ericksoa merged 3 commits into
mainfrom
worktree-fix-3240-seed-workspace-templates

Conversation

@jason-ma-nv

@jason-ma-nv jason-ma-nv commented May 10, 2026

Copy link
Copy Markdown
Contributor

Summary

NemoClaw bakes agents.defaults.skipBootstrap=true into 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-circuits ensureAgentWorkspace() before any of the bundled workspace templates are written, leaving /sandbox/.openclaw/workspace/ empty for users who expect the documented SOUL.md / USER.md / IDENTITY.md / AGENTS.md files to appear after nemoclaw onboard. This PR adds a small seed_default_workspace_templates helper that copies the same bundled templates from the npm-installed OpenClaw package into the workspace whenever the directory is pristine, while still skipping BOOTSTRAP.md so the non-interactive boot contract is preserved.

Related Issue

Fixes #3240

Changes

  • scripts/nemoclaw-start.sh: add seed_default_workspace_templates() that copies AGENTS.md / SOUL.md / IDENTITY.md / USER.md / TOOLS.md / HEARTBEAT.md from $(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.md is intentionally excluded.
  • scripts/nemoclaw-start.sh: invoke the helper from both the non-root entrypoint path (after fix_openclaw_ownership) and the root path (via gosu sandbox so seeded files inherit sandbox:sandbox ownership).
  • 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-diagnostics runPreGatewaySetup helper to keep it consistent with the long list of other entrypoint stubs.

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)

Verification notes

Ran locally in a fresh worktree (with the parent's node_modules and dist/ symlinked in):

  • All 4 new vitest cases pass; the full test/nemoclaw-start.test.ts (49 tests) passes.
  • Per-file 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.
  • The repo-wide Test (CLI) prek hook and npm test both surface pre-existing TS errors in src/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 plain main in 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

    • Empty workspaces can now be automatically seeded with standard template markdown (agents, identity, user, tools, heartbeat); seeding skips interactive bootstrap template, strips YAML frontmatter, and avoids overwriting existing files. Runs in both root and non-root startup paths only when bootstrapping is disabled and workspace is pristine (not a symlink).
  • Tests

    • Added tests covering seeding behavior, idempotency, and symlink safety.

Review Change Stack

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>
@jason-ma-nv jason-ma-nv self-assigned this May 10, 2026
@coderabbitai

coderabbitai Bot commented May 10, 2026

Copy link
Copy Markdown
Contributor

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: 083fcec6-1fde-4654-9f16-87b15b5b0ca4

📥 Commits

Reviewing files that changed from the base of the PR and between 11c1318 and 891e2cd.

📒 Files selected for processing (2)
  • scripts/nemoclaw-start.sh
  • test/nemoclaw-start.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • scripts/nemoclaw-start.sh

📝 Walkthrough

Walkthrough

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

Changes

Workspace Template Seeding

Layer / File(s) Summary
Function Implementation
scripts/nemoclaw-start.sh
New seed_default_workspace_templates() copies bundled template files into empty workspace directories, strips YAML frontmatter, refuses symlinks, and avoids overwriting existing files.
Non-root Startup Call
scripts/nemoclaw-start.sh
Non-root startup now invokes seed_default_workspace_templates after permission normalization and before auth-profile setup.
Root Startup Call (gosu)
scripts/nemoclaw-start.sh
Root startup invokes the seeding helper as sandbox via gosu immediately after multi-agent workspace provisioning.
Unit Tests
test/nemoclaw-start.test.ts
Vitest suite verifies default seeding (AGENTS.md, SOUL.md, IDENTITY.md, USER.md, TOOLS.md, HEARTBEAT.md), excludes BOOTSTRAP.md, preserves existing files, blocks when skipBootstrap unset, and refuses symlinked workspace paths.

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
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I hop where templates were bare,
I plant AGENTS, TOOLS, and HEARTBEAT there,
I skip the bootstrap, guard symlinked ground,
Idempotent seeds safe and sound,
A tiny rabbit's tidy round.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.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 accurately describes the main change: seeding default workspace templates when bootstrap is skipped, which directly addresses the issue.
Linked Issues check ✅ Passed The PR implements the required fix for issue #3240 by adding seed_default_workspace_templates() to populate workspace with SOUL.md, USER.md, IDENTITY.md, AGENTS.md, TOOLS.md, and HEARTBEAT.md when workspace is pristine.
Out of Scope Changes check ✅ Passed All changes align with the stated objective of fixing issue #3240; modifications to nemoclaw-start.sh and test additions are directly scoped to seeding workspace templates.

✏️ 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 worktree-fix-3240-seed-workspace-templates

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

@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 (3)
test/nemoclaw-start.test.ts (1)

1677-1816: ⚡ Quick win

Assert that seed_default_workspace_templates is 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 win

Gate seeding behind skipBootstrap=true to 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, and cloud-e2e jobs 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

📥 Commits

Reviewing files that changed from the base of the PR and between 34d9f61 and 11c1318.

📒 Files selected for processing (2)
  • scripts/nemoclaw-start.sh
  • test/nemoclaw-start.test.ts

@github-actions

Copy link
Copy Markdown
Contributor

Selective E2E Results — ✅ All requested jobs passed

Run: 25649846723
Branch: worktree-fix-3240-seed-workspace-templates
Requested jobs: sandbox-survival-e2e,sandbox-operations-e2e,cloud-onboard-e2e
Summary: 3 passed, 0 failed, 0 skipped

Job Result
cloud-onboard-e2e ✅ success
sandbox-operations-e2e ✅ success
sandbox-survival-e2e ✅ success

@ericksoa ericksoa 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.

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.

@ericksoa ericksoa merged commit 74a09bb into main May 11, 2026
60 checks passed
@miyoungc miyoungc mentioned this pull request May 12, 2026
12 tasks
miyoungc added a commit that referenced this pull request May 12, 2026
## 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

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/NVIDIA/NemoClaw/pull/3375)

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
@wscurran wscurran added the bug-fix PR fixes a bug or regression label Jun 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug-fix PR fixes a bug or regression

Projects

None yet

Development

Successfully merging this pull request may close these issues.

/sandbox/.openclaw/workspace/ is empty

3 participants