From a245a754e82d409415b1ea0e87cc489e592147de Mon Sep 17 00:00:00 2001 From: Miyoung Choi Date: Thu, 16 Jul 2026 16:28:59 -0700 Subject: [PATCH 01/17] docs: split starter prompt platform instructions Signed-off-by: Miyoung Choi --- docs/CONTRIBUTING.md | 2 + docs/resources/prompt-assets/dgx-spark.md | 29 ++++++++ docs/resources/prompt-assets/dgx-station.md | 34 +++++++++ docs/resources/prompt-assets/windows-wsl.md | 23 ++++++ docs/resources/starter-prompt.md | 56 +++------------ test/starter-prompt-docs.test.ts | 78 ++++++++++++++++----- 6 files changed, 160 insertions(+), 62 deletions(-) create mode 100644 docs/resources/prompt-assets/dgx-spark.md create mode 100644 docs/resources/prompt-assets/dgx-station.md create mode 100644 docs/resources/prompt-assets/windows-wsl.md diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 239ec84d136..70c9002d9b9 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -131,6 +131,8 @@ If the tag does not point to a commit on `main`, the job stops before installing The canonical coding-agent installation prompt lives in `docs/resources/starter-prompt.md`. Edit that Markdown file instead of placing prompt text in a React component. +Keep conditional platform instructions in focused Markdown files under `docs/resources/prompt-assets/` and link to their raw GitHub URLs from the starter prompt. +The main prompt should tell the coding agent when to load each asset and should not repeat the asset's detailed instructions. Downstream consumers can pin the source with a raw URL such as `https://raw.githubusercontent.com/NVIDIA/NemoClaw//docs/resources/starter-prompt.md`. The Markdown SPDX comment is part of that raw file but does not appear when Markdown is rendered. diff --git a/docs/resources/prompt-assets/dgx-spark.md b/docs/resources/prompt-assets/dgx-spark.md new file mode 100644 index 00000000000..6fffeb4d885 --- /dev/null +++ b/docs/resources/prompt-assets/dgx-spark.md @@ -0,0 +1,29 @@ + + +# DGX Spark Express Instructions + +Use these instructions only after hardware detection confirms DGX Spark. + +Ask: "Do you want the recommended Express Install?" +Choices: + +1. Yes, use the platform's Express model and required Balanced policy. +2. No, let me choose the runtime and model. + +If Express is selected: + +- Use managed vLLM and set `NEMOCLAW_PROVIDER=install-vllm`. +- Leave `NEMOCLAW_VLLM_MODEL` unset so the installed maintained release selects its current Spark Express model. +- Explain container and model download sizes before asking permission. +- Report the model selected by the installed release. +- Balanced policy is required; set `NEMOCLAW_POLICY_TIER=balanced`, `NEMOCLAW_NON_INTERACTIVE=1`, and the selected `NEMOCLAW_AGENT`. +- Set `NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1` only after explaining the notice and receiving approval. +- Set `NEMOCLAW_YES=1` only after both the separate download approval and final install approval. +- Set `NEMOCLAW_NON_INTERACTIVE_SUDO_MODE=prompt` only when required and a secure sudo prompt is available. +- Ask separately for sandbox name, web search, messaging when the selected agent supports it, download approval, and final install approval. + +If Express is declined, continue with the normal provider selection. +Offer existing vLLM when a ready server is detected, managed vLLM, supported local Ollama, and every hosted or compatible provider supported by the selected agent. diff --git a/docs/resources/prompt-assets/dgx-station.md b/docs/resources/prompt-assets/dgx-station.md new file mode 100644 index 00000000000..4c1204ae644 --- /dev/null +++ b/docs/resources/prompt-assets/dgx-station.md @@ -0,0 +1,34 @@ + + +# DGX Station Express Instructions + +Use these instructions only after hardware detection confirms DGX Station. + +Ask: "Do you want the recommended Express Install?" +Choices: + +1. Yes, use the platform's Express model and required Balanced policy. +2. No, let me choose the runtime and model. + +If Express is selected: + +- Use managed vLLM and set `NEMOCLAW_PROVIDER=install-vllm`. +- Explicitly set `NEMOCLAW_VLLM_MODEL=nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B-NVFP4`. +- Do not leave the model unset; the ordinary managed-vLLM default can select DeepSeek and would not reproduce Express. +- Disclose that the model download is approximately 352 GB, in addition to the vLLM container and temporary download space. +- Verify the model-cache filesystem and Docker storage have sufficient capacity. +- Warn that DGX Station managed deployment has deferred end-to-end physical-hardware validation. +- Describe it as an evaluation path, not a validated production deployment. +- Explain that startup may fail despite passing initial checks. +- Ask separately for approval of the approximately 352 GB download. +- Balanced policy is required; set `NEMOCLAW_POLICY_TIER=balanced`, `NEMOCLAW_NON_INTERACTIVE=1`, and the selected `NEMOCLAW_AGENT`. +- Set `NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1` only after explaining the notice and receiving approval. +- Set `NEMOCLAW_YES=1` only after both the separate download approval and final install approval. +- Set `NEMOCLAW_NON_INTERACTIVE_SUDO_MODE=prompt` only when required and a secure sudo prompt is available. +- Ask separately for sandbox name, web search, messaging when the selected agent supports it, download approval, and final install approval. + +If Express is declined, continue with the normal provider selection. +Offer existing vLLM when a ready server is detected, managed vLLM, supported local Ollama, and every hosted or compatible provider supported by the selected agent. diff --git a/docs/resources/prompt-assets/windows-wsl.md b/docs/resources/prompt-assets/windows-wsl.md new file mode 100644 index 00000000000..c47fe144e7a --- /dev/null +++ b/docs/resources/prompt-assets/windows-wsl.md @@ -0,0 +1,23 @@ + + +# Windows WSL Express Instructions + +Use these instructions only after official detection identifies Windows WSL. + +Offer the maintained Windows Express path before the normal provider menu. +Explain that it uses Windows-host Ollama through Docker Desktop WSL integration. + +If Express is selected: + +- Set `NEMOCLAW_PROVIDER=install-windows-ollama` and let the installed release choose its maintained Ollama model. +- Balanced policy is required; set `NEMOCLAW_POLICY_TIER=balanced`, `NEMOCLAW_NON_INTERACTIVE=1`, and the selected `NEMOCLAW_AGENT`. +- Set `NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1` only after explaining the notice and receiving approval. +- Set `NEMOCLAW_YES=1` only after both the separate download approval and final install approval. +- Set `NEMOCLAW_NON_INTERACTIVE_SUDO_MODE=prompt` only when required and a secure sudo prompt is available. +- Ask separately for sandbox name, web search, messaging when the selected agent supports it, download approval, and final install approval. +- Do not start a second Ollama service on the same port. + +If Express is declined, continue with the normal provider selection and offer every provider supported by the selected agent on Windows WSL. diff --git a/docs/resources/starter-prompt.md b/docs/resources/starter-prompt.md index 894194121fe..4e0ff878a3c 100644 --- a/docs/resources/starter-prompt.md +++ b/docs/resources/starter-prompt.md @@ -62,53 +62,20 @@ Use `NEMOCLAW_AGENT=langchain-deepagents-code` or `nemo-deepagents onboard` for - Offer a user-local alternative only when official documentation supports it for that exact operation. - Do not silently use user-local Ollama for a system Ollama upgrade when the old system service would remain active. -## DGX Express Install +## Platform-Specific Instructions -If DGX Spark or DGX Station is detected, ask: "Do you want the recommended Express Install?" -Choices: - -1. Yes, use the platform's Express model and required Balanced policy. -2. No, let me choose the runtime and model. - -If DGX Spark Express is selected: - -- Use managed vLLM and set `NEMOCLAW_PROVIDER=install-vllm`. -- Leave `NEMOCLAW_VLLM_MODEL` unset so the installed maintained release selects its current Spark Express model. -- Explain container and model download sizes before asking permission. -- Report the model selected by the installed release. - -If DGX Station Express is selected: - -- Use managed vLLM. -- Explicitly select `nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B-NVFP4`. -- Do not leave the model unset; the ordinary managed-vLLM default can select DeepSeek and would not reproduce Express. -- Set `NEMOCLAW_PROVIDER=install-vllm`. -- Set `NEMOCLAW_VLLM_MODEL=nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B-NVFP4`. -- Disclose that the model download is approximately 352 GB, in addition to the vLLM container and temporary download space. -- Verify the model-cache filesystem and Docker storage have sufficient capacity. -- Warn that DGX Station managed deployment has deferred end-to-end physical-hardware validation. -- Describe it as an evaluation path, not a validated production deployment. -- Explain that startup may fail despite passing initial checks. -- Ask separately for approval of the approximately 352 GB download. - -For both Express paths: - -- Balanced policy is required for Express; set `NEMOCLAW_POLICY_TIER=balanced`, `NEMOCLAW_NON_INTERACTIVE=1`, and the selected `NEMOCLAW_AGENT`. -- Set `NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1` only after explaining the notice and receiving approval. -- Set `NEMOCLAW_YES=1` only after both the separate download approval and final install approval. -- Set `NEMOCLAW_NON_INTERACTIVE_SUDO_MODE=prompt` only when required and a secure sudo prompt is available. -- Ask separately for sandbox name, web search, messaging when the selected agent supports it, download approval, and final install approval. +After the readiness check, load exactly one matching instruction asset before provider selection: -## Windows WSL Express Install +- Confirmed DGX Spark: [DGX Spark Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/main/docs/resources/prompt-assets/dgx-spark.md). +- Confirmed DGX Station: [DGX Station Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/main/docs/resources/prompt-assets/dgx-station.md). +- Officially detected Windows WSL: [Windows WSL Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/main/docs/resources/prompt-assets/windows-wsl.md). -If official detection identifies Windows WSL, offer the maintained Windows Express path before the normal provider menu. -Explain that it uses Windows-host Ollama through Docker Desktop WSL integration. -If selected, set `NEMOCLAW_PROVIDER=install-windows-ollama`, collect the same separate approvals, and let the installed release choose its maintained Ollama model. -Do not start a second Ollama service on the same port. +Read the matching raw Markdown file completely and follow it before continuing. +Do not load a platform asset for any other computer. ## Runtime and Provider Selection -If Express is declined on DGX Spark, DGX Station, or GB300, ask: "Which inference runtime or provider would you like?" +If no platform asset applies, or its Express path is declined, ask: "Which inference runtime or provider would you like?" Choices: 1. Existing vLLM, only when a ready server is detected on `localhost:8000`. @@ -133,6 +100,7 @@ On ordinary supported macOS or Linux: - Do not hide Ollama merely because the computer is not DGX or GB300. - Omit managed vLLM unless current official support permits it for the detected hardware. +When a platform asset applies, follow its local-runtime eligibility and model instructions. On other platforms, show every provider supported by the selected agent and platform. Renumber choices after filtering and do not hide hosted providers behind another menu. Ask required model, endpoint, credential, and download questions one at a time. @@ -141,7 +109,6 @@ Ask required model, endpoint, credential, and download questions one at a time. - Fetch current model choices from the selected agent's official Markdown documentation. - The selected maintained NemoClaw release is authoritative for supported slugs and arguments. -- Managed-vLLM examples include `qwen3.6-27b`, `qwen3.6-35b-a3b-nvfp4`, `nemotron-3-nano-4b`, `deepseek-v4-flash`, and gated `deepseek-r1-distill-70b`. - For Ollama, ask permission to inspect installed models and offer NemoClaw's memory-aware recommendation first. - Current Ollama starter examples include `qwen3.6:35b`, `nemotron-3-nano:30b`, and `qwen3.5:9b`. - Explain download size and storage requirements, then ask separately for permission. @@ -200,8 +167,7 @@ Use this provider mapping for non-interactive setup: - Anthropic-compatible: `NEMOCLAW_PROVIDER=anthropicCompatible`, endpoint, model, `COMPATIBLE_ANTHROPIC_API_KEY`. - Ollama: `NEMOCLAW_PROVIDER=ollama`, optional `NEMOCLAW_MODEL`. - Existing vLLM: `NEMOCLAW_PROVIDER=vllm`. -- Managed vLLM: `NEMOCLAW_PROVIDER=install-vllm`; leave `NEMOCLAW_VLLM_MODEL` unset for DGX Spark Express, set it to `nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B-NVFP4` for DGX Station Express, or use an approved optional override for non-Express setup. -- Windows WSL Express: `NEMOCLAW_PROVIDER=install-windows-ollama`. +- Managed vLLM: `NEMOCLAW_PROVIDER=install-vllm`; use an approved optional model override only when the selected platform supports it. Do not offer Hermes Provider for OpenClaw or Deep Agents. @@ -247,7 +213,7 @@ Use `channels add` and rebuild only for channels omitted from initial onboarding ## Policy, Approval, and Verification -- For Express, state that Balanced policy is required, keep `NEMOCLAW_POLICY_TIER=balanced`, and skip the policy-tier question. +- If a loaded platform asset selects Express, follow its policy requirement and skip the policy-tier question. - For non-Express installation, ask for Balanced, Restricted, or Open policy. - Explain that messaging and web-search selections add required endpoints. - Before installation, summarize platform, administrator access, agent, Express choice, provider, exact model, validation warning, downloads, storage, sandbox, web search, messaging, policy, credential names without their values, and system changes. diff --git a/test/starter-prompt-docs.test.ts b/test/starter-prompt-docs.test.ts index ada41527ce3..3387f7e04c8 100644 --- a/test/starter-prompt-docs.test.ts +++ b/test/starter-prompt-docs.test.ts @@ -21,6 +21,20 @@ const __dirname = path.dirname(__filename); const repoRoot = path.resolve(__dirname, ".."); const starterPromptMarkdownSource = path.join(repoRoot, "docs", "resources", "starter-prompt.md"); +const promptAssets = { + dgxSpark: { + path: "docs/resources/prompt-assets/dgx-spark.md", + url: "https://raw.githubusercontent.com/NVIDIA/NemoClaw/main/docs/resources/prompt-assets/dgx-spark.md", + }, + dgxStation: { + path: "docs/resources/prompt-assets/dgx-station.md", + url: "https://raw.githubusercontent.com/NVIDIA/NemoClaw/main/docs/resources/prompt-assets/dgx-station.md", + }, + windowsWsl: { + path: "docs/resources/prompt-assets/windows-wsl.md", + url: "https://raw.githubusercontent.com/NVIDIA/NemoClaw/main/docs/resources/prompt-assets/windows-wsl.md", + }, +} as const; const localCredentialFormSource = path.join( repoRoot, "docs", @@ -148,6 +162,10 @@ function readStarterPrompt(): string { ); } +function readPromptAsset(asset: (typeof promptAssets)[keyof typeof promptAssets]): string { + return read(asset.path); +} + function urlsIn(content: string): URL[] { return Array.from(content.matchAll(/https?:\/\/[^\s"'<>;]+/g), ([match]) => new URL(match)); } @@ -605,43 +623,69 @@ describe("starter prompt docs CTA", () => { ); expect(promptSource).toContain("OpenRouter: `NEMOCLAW_PROVIDER=openrouter`"); expect(promptSource).toContain("Existing vLLM: `NEMOCLAW_PROVIDER=vllm`"); - expect(promptSource).toContain( - "Windows WSL Express: `NEMOCLAW_PROVIDER=install-windows-ollama`", - ); - expect(promptSource).toContain( + }); + + it("routes platform-only Express instructions to raw prompt assets (#6990)", () => { + const promptSource = readStarterPrompt(); + const sparkSource = readPromptAsset(promptAssets.dgxSpark); + const stationSource = readPromptAsset(promptAssets.dgxStation); + const windowsSource = readPromptAsset(promptAssets.windowsWsl); + + for (const asset of Object.values(promptAssets)) { + expect(promptSource).toContain(asset.url); + } + + expect(promptSource).toContain("load exactly one matching instruction asset"); + expect(promptSource).toContain("Read the matching raw Markdown file completely"); + expect(promptSource).toContain("Do not load a platform asset for any other computer."); + expect(promptSource).not.toContain("approximately 352 GB"); + expect(promptSource).not.toContain("NEMOCLAW_PROVIDER=install-windows-ollama"); + expect(promptSource).not.toContain( "NEMOCLAW_VLLM_MODEL=nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B-NVFP4", ); - expect(promptSource).toContain( + + expect(sparkSource).toContain( "Leave `NEMOCLAW_VLLM_MODEL` unset so the installed maintained release selects its current Spark Express model.", ); - expect(promptSource).toContain( - "Set `NEMOCLAW_YES=1` only after both the separate download approval and final install approval.", + expect(stationSource).toContain( + "NEMOCLAW_VLLM_MODEL=nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B-NVFP4", ); + expect(stationSource).toContain("approximately 352 GB"); + expect(windowsSource).toContain("NEMOCLAW_PROVIDER=install-windows-ollama"); + expect(windowsSource).toContain("Do not start a second Ollama service on the same port."); }); it("aligns messaging and policy questions with agent support and Express mode (#6990)", () => { const promptSource = readStarterPrompt(); + const expressAssets = [ + readPromptAsset(promptAssets.dgxSpark), + readPromptAsset(promptAssets.dgxStation), + readPromptAsset(promptAssets.windowsWsl), + ]; expect(promptSource).toContain( "include messaging in the first sandbox build when the selected agent supports it", ); - expect(promptSource).toContain( - "Ask separately for sandbox name, web search, messaging when the selected agent supports it, download approval, and final install approval.", - ); expect(promptSource).toContain("Skip messaging for Deep Agents."); expect(promptSource).toContain( - "Balanced policy is required for Express; set `NEMOCLAW_POLICY_TIER=balanced`", - ); - expect(promptSource).toContain( - "For Express, state that Balanced policy is required, keep `NEMOCLAW_POLICY_TIER=balanced`, and skip the policy-tier question.", + "If a loaded platform asset selects Express, follow its policy requirement and skip the policy-tier question.", ); expect(promptSource).toContain( "For non-Express installation, ask for Balanced, Restricted, or Open policy.", ); expect(promptSource).not.toContain("\n- Ask for Balanced, Restricted, or Open policy.\n"); - expect(promptSource).toContain( - "Managed vLLM: `NEMOCLAW_PROVIDER=install-vllm`; leave `NEMOCLAW_VLLM_MODEL` unset for DGX Spark Express, set it to `nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B-NVFP4` for DGX Station Express", - ); + + for (const assetSource of expressAssets) { + expect(assetSource).toContain( + "Balanced policy is required; set `NEMOCLAW_POLICY_TIER=balanced`", + ); + expect(assetSource).toContain( + "Ask separately for sandbox name, web search, messaging when the selected agent supports it, download approval, and final install approval.", + ); + expect(assetSource).toContain( + "Set `NEMOCLAW_YES=1` only after both the separate download approval and final install approval.", + ); + } }); it("rejects missing, ambiguous, and unsafe credential schemas (#5048)", async () => { From 15468e109742817483dbb0c368a47f787b34a892 Mon Sep 17 00:00:00 2001 From: San Dang Date: Fri, 17 Jul 2026 08:51:45 +0700 Subject: [PATCH 02/17] docs: align express prompts with installer defaults --- docs/resources/prompt-assets/dgx-spark.md | 23 +++++++++--------- docs/resources/prompt-assets/dgx-station.md | 26 ++++++++------------- docs/resources/prompt-assets/windows-wsl.md | 21 +++++++++++------ test/starter-prompt-docs.test.ts | 26 +++++++++++---------- 4 files changed, 50 insertions(+), 46 deletions(-) diff --git a/docs/resources/prompt-assets/dgx-spark.md b/docs/resources/prompt-assets/dgx-spark.md index 6fffeb4d885..8e9efd4c7e7 100644 --- a/docs/resources/prompt-assets/dgx-spark.md +++ b/docs/resources/prompt-assets/dgx-spark.md @@ -7,23 +7,24 @@ Use these instructions only after hardware detection confirms DGX Spark. -Ask: "Do you want the recommended Express Install?" +Explain that Express keeps the selected agent, uses local vLLM with the default Qwen model, leaves optional setup at its defaults, and downloads the vLLM container and model. +Include the third-party-software notice, then ask: "Run Express install with these settings?" Choices: -1. Yes, use the platform's Express model and required Balanced policy. +1. Yes, use the DGX Spark Express defaults. 2. No, let me choose the runtime and model. If Express is selected: -- Use managed vLLM and set `NEMOCLAW_PROVIDER=install-vllm`. -- Leave `NEMOCLAW_VLLM_MODEL` unset so the installed maintained release selects its current Spark Express model. -- Explain container and model download sizes before asking permission. -- Report the model selected by the installed release. -- Balanced policy is required; set `NEMOCLAW_POLICY_TIER=balanced`, `NEMOCLAW_NON_INTERACTIVE=1`, and the selected `NEMOCLAW_AGENT`. -- Set `NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1` only after explaining the notice and receiving approval. -- Set `NEMOCLAW_YES=1` only after both the separate download approval and final install approval. -- Set `NEMOCLAW_NON_INTERACTIVE_SUDO_MODE=prompt` only when required and a secure sudo prompt is available. -- Ask separately for sandbox name, web search, messaging when the selected agent supports it, download approval, and final install approval. +- Set `NEMOCLAW_PROVIDER=install-vllm`. +- Leave `NEMOCLAW_VLLM_MODEL` and `NEMOCLAW_MODEL` unset so the installed release selects its DGX Spark default, currently `nvidia/Qwen3.6-35B-A3B-NVFP4`. +- Set `NEMOCLAW_AGENT` to the agent already selected in the starter prompt. +- Set `NEMOCLAW_NON_INTERACTIVE=1`, `NEMOCLAW_NON_INTERACTIVE_SUDO_MODE=prompt`, `NEMOCLAW_YES=1`, and `NEMOCLAW_POLICY_MODE=suggested`. +- Set `NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1` when Express is accepted. +- Leave `NEMOCLAW_SANDBOX_NAME`, `NEMOCLAW_POLICY_TIER`, web-search settings, and messaging settings unset so the installer applies the remaining Express defaults. +- Treat the Express confirmation as approval for the disclosed notice, downloads, and installation, and skip the later final-permission prompt. +- Do not ask again for the agent or ask separate questions for model, sandbox name, web search, messaging, policy, download approval, or final installation approval. +- After installation, report the model selected by the installed release. If Express is declined, continue with the normal provider selection. Offer existing vLLM when a ready server is detected, managed vLLM, supported local Ollama, and every hosted or compatible provider supported by the selected agent. diff --git a/docs/resources/prompt-assets/dgx-station.md b/docs/resources/prompt-assets/dgx-station.md index 4c1204ae644..963b7e5d050 100644 --- a/docs/resources/prompt-assets/dgx-station.md +++ b/docs/resources/prompt-assets/dgx-station.md @@ -7,28 +7,22 @@ Use these instructions only after hardware detection confirms DGX Station. -Ask: "Do you want the recommended Express Install?" +Explain that Express uses the default local inference setup with Nemotron 3 Ultra in vLLM, then ask: "Do you want the recommended Express Install?" Choices: -1. Yes, use the platform's Express model and required Balanced policy. +1. Yes, use the DGX Station Express defaults. 2. No, let me choose the runtime and model. If Express is selected: -- Use managed vLLM and set `NEMOCLAW_PROVIDER=install-vllm`. -- Explicitly set `NEMOCLAW_VLLM_MODEL=nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B-NVFP4`. -- Do not leave the model unset; the ordinary managed-vLLM default can select DeepSeek and would not reproduce Express. -- Disclose that the model download is approximately 352 GB, in addition to the vLLM container and temporary download space. -- Verify the model-cache filesystem and Docker storage have sufficient capacity. -- Warn that DGX Station managed deployment has deferred end-to-end physical-hardware validation. -- Describe it as an evaluation path, not a validated production deployment. -- Explain that startup may fail despite passing initial checks. -- Ask separately for approval of the approximately 352 GB download. -- Balanced policy is required; set `NEMOCLAW_POLICY_TIER=balanced`, `NEMOCLAW_NON_INTERACTIVE=1`, and the selected `NEMOCLAW_AGENT`. -- Set `NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1` only after explaining the notice and receiving approval. -- Set `NEMOCLAW_YES=1` only after both the separate download approval and final install approval. -- Set `NEMOCLAW_NON_INTERACTIVE_SUDO_MODE=prompt` only when required and a secure sudo prompt is available. -- Ask separately for sandbox name, web search, messaging when the selected agent supports it, download approval, and final install approval. +- Set `NEMOCLAW_PROVIDER=install-vllm`. +- Set `NEMOCLAW_VLLM_MODEL=nemotron-3-ultra-550b-a55b` and `NEMOCLAW_MODEL=nvidia/nemotron-3-ultra-550b-a55b`. +- Set `NEMOCLAW_AGENT` to the agent already selected in the starter prompt. +- Set `NEMOCLAW_NON_INTERACTIVE=1`, `NEMOCLAW_NON_INTERACTIVE_SUDO_MODE=prompt`, `NEMOCLAW_YES=1`, and `NEMOCLAW_POLICY_MODE=suggested`. +- Set `NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1` when Express is accepted. +- Leave `NEMOCLAW_SANDBOX_NAME`, `NEMOCLAW_POLICY_TIER`, web-search settings, and messaging settings unset so the installer applies the remaining Express defaults. +- Treat the Express confirmation as approval for the described setup and installation, and skip the later final-permission prompt. +- Do not ask again for the agent or ask separate questions for model, sandbox name, web search, messaging, policy, download approval, or final installation approval. If Express is declined, continue with the normal provider selection. Offer existing vLLM when a ready server is detected, managed vLLM, supported local Ollama, and every hosted or compatible provider supported by the selected agent. diff --git a/docs/resources/prompt-assets/windows-wsl.md b/docs/resources/prompt-assets/windows-wsl.md index c47fe144e7a..a1574327985 100644 --- a/docs/resources/prompt-assets/windows-wsl.md +++ b/docs/resources/prompt-assets/windows-wsl.md @@ -8,16 +8,23 @@ Use these instructions only after official detection identifies Windows WSL. Offer the maintained Windows Express path before the normal provider menu. -Explain that it uses Windows-host Ollama through Docker Desktop WSL integration. +Explain that Express keeps the selected agent, uses Windows-host Ollama with its memory-aware default model, leaves optional setup at its defaults, and installs or starts Ollama and downloads the model when needed. +Include the third-party-software notice, then ask: "Run Express install with these settings?" +Choices: + +1. Yes, use the Windows WSL Express defaults. +2. No, let me choose the runtime and model. If Express is selected: -- Set `NEMOCLAW_PROVIDER=install-windows-ollama` and let the installed release choose its maintained Ollama model. -- Balanced policy is required; set `NEMOCLAW_POLICY_TIER=balanced`, `NEMOCLAW_NON_INTERACTIVE=1`, and the selected `NEMOCLAW_AGENT`. -- Set `NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1` only after explaining the notice and receiving approval. -- Set `NEMOCLAW_YES=1` only after both the separate download approval and final install approval. -- Set `NEMOCLAW_NON_INTERACTIVE_SUDO_MODE=prompt` only when required and a secure sudo prompt is available. -- Ask separately for sandbox name, web search, messaging when the selected agent supports it, download approval, and final install approval. +- Set `NEMOCLAW_PROVIDER=install-windows-ollama`. +- Leave `NEMOCLAW_MODEL` unset so the installed release chooses its memory-aware Ollama model. +- Set `NEMOCLAW_AGENT` to the agent already selected in the starter prompt. +- Set `NEMOCLAW_NON_INTERACTIVE=1`, `NEMOCLAW_NON_INTERACTIVE_SUDO_MODE=prompt`, `NEMOCLAW_YES=1`, and `NEMOCLAW_POLICY_MODE=suggested`. +- Set `NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1` when Express is accepted. +- Leave `NEMOCLAW_SANDBOX_NAME`, `NEMOCLAW_POLICY_TIER`, web-search settings, and messaging settings unset so the installer applies the remaining Express defaults. +- Treat the Express confirmation as approval for the disclosed notice, downloads, and installation, and skip the later final-permission prompt. +- Do not ask again for the agent or ask separate questions for model, sandbox name, web search, messaging, policy, download approval, or final installation approval. - Do not start a second Ollama service on the same port. If Express is declined, continue with the normal provider selection and offer every provider supported by the selected agent on Windows WSL. diff --git a/test/starter-prompt-docs.test.ts b/test/starter-prompt-docs.test.ts index 3387f7e04c8..c9e6a9a4562 100644 --- a/test/starter-prompt-docs.test.ts +++ b/test/starter-prompt-docs.test.ts @@ -644,18 +644,16 @@ describe("starter prompt docs CTA", () => { "NEMOCLAW_VLLM_MODEL=nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B-NVFP4", ); - expect(sparkSource).toContain( - "Leave `NEMOCLAW_VLLM_MODEL` unset so the installed maintained release selects its current Spark Express model.", - ); - expect(stationSource).toContain( - "NEMOCLAW_VLLM_MODEL=nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B-NVFP4", - ); - expect(stationSource).toContain("approximately 352 GB"); + expect(sparkSource).toContain("nvidia/Qwen3.6-35B-A3B-NVFP4"); + expect(sparkSource).toContain("Leave `NEMOCLAW_VLLM_MODEL` and `NEMOCLAW_MODEL` unset"); + expect(stationSource).toContain("NEMOCLAW_VLLM_MODEL=nemotron-3-ultra-550b-a55b"); + expect(stationSource).toContain("NEMOCLAW_MODEL=nvidia/nemotron-3-ultra-550b-a55b"); + expect(stationSource).toContain("default local inference setup with Nemotron 3 Ultra in vLLM"); expect(windowsSource).toContain("NEMOCLAW_PROVIDER=install-windows-ollama"); expect(windowsSource).toContain("Do not start a second Ollama service on the same port."); }); - it("aligns messaging and policy questions with agent support and Express mode (#6990)", () => { + it("uses installer Express defaults without collecting optional onboarding choices (#6990)", () => { const promptSource = readStarterPrompt(); const expressAssets = [ readPromptAsset(promptAssets.dgxSpark), @@ -664,7 +662,7 @@ describe("starter prompt docs CTA", () => { ]; expect(promptSource).toContain( - "include messaging in the first sandbox build when the selected agent supports it", + "Next ask which agent I want: OpenClaw, Hermes, or LangChain Deep Agents Code.", ); expect(promptSource).toContain("Skip messaging for Deep Agents."); expect(promptSource).toContain( @@ -677,14 +675,18 @@ describe("starter prompt docs CTA", () => { for (const assetSource of expressAssets) { expect(assetSource).toContain( - "Balanced policy is required; set `NEMOCLAW_POLICY_TIER=balanced`", + "`NEMOCLAW_NON_INTERACTIVE=1`, `NEMOCLAW_NON_INTERACTIVE_SUDO_MODE=prompt`, `NEMOCLAW_YES=1`, and `NEMOCLAW_POLICY_MODE=suggested`", + ); + expect(assetSource).toContain( + "Set `NEMOCLAW_AGENT` to the agent already selected in the starter prompt.", ); expect(assetSource).toContain( - "Ask separately for sandbox name, web search, messaging when the selected agent supports it, download approval, and final install approval.", + "Leave `NEMOCLAW_SANDBOX_NAME`, `NEMOCLAW_POLICY_TIER`, web-search settings, and messaging settings unset", ); expect(assetSource).toContain( - "Set `NEMOCLAW_YES=1` only after both the separate download approval and final install approval.", + "Do not ask again for the agent or ask separate questions for model, sandbox name, web search, messaging, policy, download approval, or final installation approval.", ); + expect(assetSource).not.toContain("NEMOCLAW_POLICY_TIER=balanced"); } }); From 2a7a890bb0630bdc763ec005be9ab8c0a68565af Mon Sep 17 00:00:00 2001 From: San Dang Date: Fri, 17 Jul 2026 10:41:23 +0700 Subject: [PATCH 03/17] docs: improve starter prompt platform detection --- docs/resources/starter-prompt.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/resources/starter-prompt.md b/docs/resources/starter-prompt.md index 4e0ff878a3c..bb0886f6b1d 100644 --- a/docs/resources/starter-prompt.md +++ b/docs/resources/starter-prompt.md @@ -13,7 +13,8 @@ I do not know how to use a terminal. - Ask exactly one question at a time. - Use clickable choices when supported; otherwise show one short numbered list and wait. -- Start by asking: "What computer are you using?" Choices: macOS, Windows, Linux. +- Detect the operating system and whether it is WSL using read-only checks. +- Ask which computer I am using only if the environment cannot be determined reliably. - Next ask which agent I want: OpenClaw, Hermes, or LangChain Deep Agents Code. - Never ask me to run commands myself, except the one workstation-side `ssh -N -L` command needed to open a remote credential form securely. - Explain each command in plain language, ask permission, then run it for me. @@ -47,7 +48,8 @@ Use `NEMOCLAW_AGENT=langchain-deepagents-code` or `nemo-deepagents onboard` for - On Linux, ask permission to run a read-only readiness check before provider selection. - Check distribution, architecture, product and firmware identity, GPU and memory, NVIDIA driver, Container Toolkit, Docker, Node.js, disk space, existing NemoClaw, Ollama, vLLM, relevant ports, and administrator access. - Classify the computer as DGX Spark, DGX Station, NVIDIA GB300, another NVIDIA computer, ordinary macOS/Linux, or unknown. -- Do not identify DGX Spark or DGX Station from the GPU name alone; combine product, firmware, architecture, and GPU evidence. +- Do not identify DGX Spark from the GPU name alone; combine product, firmware, architecture, and GPU evidence. +- Classify a system as DGX Station when its firmware identifies a Station GB300 platform, or when its exact OEM model is documented by NVIDIA or the manufacturer as based on DGX Station architecture. - A confirmed NVIDIA GB300 can independently qualify for expanded local-runtime choices. - If uncertain, explain that and let NemoClaw's official preflight make the final platform decision. @@ -66,9 +68,9 @@ Use `NEMOCLAW_AGENT=langchain-deepagents-code` or `nemo-deepagents onboard` for After the readiness check, load exactly one matching instruction asset before provider selection: -- Confirmed DGX Spark: [DGX Spark Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/main/docs/resources/prompt-assets/dgx-spark.md). -- Confirmed DGX Station: [DGX Station Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/main/docs/resources/prompt-assets/dgx-station.md). -- Officially detected Windows WSL: [Windows WSL Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/main/docs/resources/prompt-assets/windows-wsl.md). +- Confirmed DGX Spark: [DGX Spark Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/15468e109742817483dbb0c368a47f787b34a892/docs/resources/prompt-assets/dgx-spark.md). +- Confirmed DGX Station: [DGX Station Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/15468e109742817483dbb0c368a47f787b34a892/docs/resources/prompt-assets/dgx-station.md). +- Officially detected Windows WSL: [Windows WSL Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/15468e109742817483dbb0c368a47f787b34a892/docs/resources/prompt-assets/windows-wsl.md). Read the matching raw Markdown file completely and follow it before continuing. Do not load a platform asset for any other computer. From c8778b0e8d92e860b1d8e62245a03a4efcdeb319 Mon Sep 17 00:00:00 2001 From: San Dang Date: Fri, 17 Jul 2026 10:56:03 +0700 Subject: [PATCH 04/17] docs: use main prompt asset links --- docs/resources/starter-prompt.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/resources/starter-prompt.md b/docs/resources/starter-prompt.md index bb0886f6b1d..1aad47ca377 100644 --- a/docs/resources/starter-prompt.md +++ b/docs/resources/starter-prompt.md @@ -68,9 +68,9 @@ Use `NEMOCLAW_AGENT=langchain-deepagents-code` or `nemo-deepagents onboard` for After the readiness check, load exactly one matching instruction asset before provider selection: -- Confirmed DGX Spark: [DGX Spark Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/15468e109742817483dbb0c368a47f787b34a892/docs/resources/prompt-assets/dgx-spark.md). -- Confirmed DGX Station: [DGX Station Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/15468e109742817483dbb0c368a47f787b34a892/docs/resources/prompt-assets/dgx-station.md). -- Officially detected Windows WSL: [Windows WSL Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/15468e109742817483dbb0c368a47f787b34a892/docs/resources/prompt-assets/windows-wsl.md). +- Confirmed DGX Spark: [DGX Spark Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/main/docs/resources/prompt-assets/dgx-spark.md). +- Confirmed DGX Station: [DGX Station Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/main/docs/resources/prompt-assets/dgx-station.md). +- Officially detected Windows WSL: [Windows WSL Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/main/docs/resources/prompt-assets/windows-wsl.md). Read the matching raw Markdown file completely and follow it before continuing. Do not load a platform asset for any other computer. From e2dffc192a6f8a05b1a2f3afb142d39864a0a688 Mon Sep 17 00:00:00 2001 From: San Dang Date: Fri, 17 Jul 2026 11:16:49 +0700 Subject: [PATCH 05/17] docs: restore station express safeguards --- docs/resources/prompt-assets/dgx-station.md | 6 +++++- test/starter-prompt-docs.test.ts | 6 ++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/docs/resources/prompt-assets/dgx-station.md b/docs/resources/prompt-assets/dgx-station.md index 963b7e5d050..b9d6b6e55fd 100644 --- a/docs/resources/prompt-assets/dgx-station.md +++ b/docs/resources/prompt-assets/dgx-station.md @@ -7,7 +7,11 @@ Use these instructions only after hardware detection confirms DGX Station. -Explain that Express uses the default local inference setup with Nemotron 3 Ultra in vLLM, then ask: "Do you want the recommended Express Install?" +Explain that Express uses the default local inference setup with Nemotron 3 Ultra in vLLM. +Disclose that it downloads the pinned vLLM container and approximately 352 GB of model data. +Verify that the model-cache filesystem and Docker storage have enough capacity before continuing. +Explain that DGX Station remains an evaluation path with deferred end-to-end validation on physical hardware, so startup may still fail after readiness checks. +Include the third-party-software notice, then ask: "Do you want the recommended Express Install?" Choices: 1. Yes, use the DGX Station Express defaults. diff --git a/test/starter-prompt-docs.test.ts b/test/starter-prompt-docs.test.ts index c9e6a9a4562..f08af8a5be5 100644 --- a/test/starter-prompt-docs.test.ts +++ b/test/starter-prompt-docs.test.ts @@ -649,6 +649,12 @@ describe("starter prompt docs CTA", () => { expect(stationSource).toContain("NEMOCLAW_VLLM_MODEL=nemotron-3-ultra-550b-a55b"); expect(stationSource).toContain("NEMOCLAW_MODEL=nvidia/nemotron-3-ultra-550b-a55b"); expect(stationSource).toContain("default local inference setup with Nemotron 3 Ultra in vLLM"); + expect(stationSource).toContain("approximately 352 GB of model data"); + expect(stationSource).toContain("model-cache filesystem and Docker storage"); + expect(stationSource).toContain("have enough capacity before continuing"); + expect(stationSource).toContain("evaluation path with deferred end-to-end validation"); + expect(stationSource).toContain("startup may still fail after readiness checks"); + expect(stationSource).toContain("third-party-software notice"); expect(windowsSource).toContain("NEMOCLAW_PROVIDER=install-windows-ollama"); expect(windowsSource).toContain("Do not start a second Ollama service on the same port."); }); From 91594b99b5a931d3761f55c08c06eaa3e2767e87 Mon Sep 17 00:00:00 2001 From: San Dang Date: Fri, 17 Jul 2026 11:18:37 +0700 Subject: [PATCH 06/17] docs: pin express prompt assets --- docs/resources/starter-prompt.md | 6 +++--- test/starter-prompt-docs.test.ts | 14 +++++++++++--- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/docs/resources/starter-prompt.md b/docs/resources/starter-prompt.md index 1aad47ca377..53f11df8b67 100644 --- a/docs/resources/starter-prompt.md +++ b/docs/resources/starter-prompt.md @@ -68,9 +68,9 @@ Use `NEMOCLAW_AGENT=langchain-deepagents-code` or `nemo-deepagents onboard` for After the readiness check, load exactly one matching instruction asset before provider selection: -- Confirmed DGX Spark: [DGX Spark Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/main/docs/resources/prompt-assets/dgx-spark.md). -- Confirmed DGX Station: [DGX Station Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/main/docs/resources/prompt-assets/dgx-station.md). -- Officially detected Windows WSL: [Windows WSL Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/main/docs/resources/prompt-assets/windows-wsl.md). +- Confirmed DGX Spark: [DGX Spark Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/e2dffc192a6f8a05b1a2f3afb142d39864a0a688/docs/resources/prompt-assets/dgx-spark.md). +- Confirmed DGX Station: [DGX Station Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/e2dffc192a6f8a05b1a2f3afb142d39864a0a688/docs/resources/prompt-assets/dgx-station.md). +- Officially detected Windows WSL: [Windows WSL Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/e2dffc192a6f8a05b1a2f3afb142d39864a0a688/docs/resources/prompt-assets/windows-wsl.md). Read the matching raw Markdown file completely and follow it before continuing. Do not load a platform asset for any other computer. diff --git a/test/starter-prompt-docs.test.ts b/test/starter-prompt-docs.test.ts index f08af8a5be5..bdbbd1f530d 100644 --- a/test/starter-prompt-docs.test.ts +++ b/test/starter-prompt-docs.test.ts @@ -21,18 +21,19 @@ const __dirname = path.dirname(__filename); const repoRoot = path.resolve(__dirname, ".."); const starterPromptMarkdownSource = path.join(repoRoot, "docs", "resources", "starter-prompt.md"); +const promptAssetRevision = "e2dffc192a6f8a05b1a2f3afb142d39864a0a688"; const promptAssets = { dgxSpark: { path: "docs/resources/prompt-assets/dgx-spark.md", - url: "https://raw.githubusercontent.com/NVIDIA/NemoClaw/main/docs/resources/prompt-assets/dgx-spark.md", + url: `https://raw.githubusercontent.com/NVIDIA/NemoClaw/${promptAssetRevision}/docs/resources/prompt-assets/dgx-spark.md`, }, dgxStation: { path: "docs/resources/prompt-assets/dgx-station.md", - url: "https://raw.githubusercontent.com/NVIDIA/NemoClaw/main/docs/resources/prompt-assets/dgx-station.md", + url: `https://raw.githubusercontent.com/NVIDIA/NemoClaw/${promptAssetRevision}/docs/resources/prompt-assets/dgx-station.md`, }, windowsWsl: { path: "docs/resources/prompt-assets/windows-wsl.md", - url: "https://raw.githubusercontent.com/NVIDIA/NemoClaw/main/docs/resources/prompt-assets/windows-wsl.md", + url: `https://raw.githubusercontent.com/NVIDIA/NemoClaw/${promptAssetRevision}/docs/resources/prompt-assets/windows-wsl.md`, }, } as const; const localCredentialFormSource = path.join( @@ -631,8 +632,15 @@ describe("starter prompt docs CTA", () => { const stationSource = readPromptAsset(promptAssets.dgxStation); const windowsSource = readPromptAsset(promptAssets.windowsWsl); + expect(promptAssetRevision).toMatch(/^[0-9a-f]{40}$/); for (const asset of Object.values(promptAssets)) { expect(promptSource).toContain(asset.url); + const assetUrl = new URL(asset.url); + expect(assetUrl.origin).toBe("https://raw.githubusercontent.com"); + expect(assetUrl.pathname).toMatch( + /^\/NVIDIA\/NemoClaw\/[0-9a-f]{40}\/docs\/resources\/prompt-assets\/[^/]+\.md$/, + ); + expect(assetUrl.pathname).toContain(`/${promptAssetRevision}/`); } expect(promptSource).toContain("load exactly one matching instruction asset"); From f515f7982096d94da44063c488cb959aab4bfefc Mon Sep 17 00:00:00 2001 From: San Dang Date: Fri, 17 Jul 2026 11:26:54 +0700 Subject: [PATCH 07/17] docs: address express prompt review --- docs/resources/starter-prompt.md | 5 +++-- test/starter-prompt-docs.test.ts | 37 +++++++++++++++++++++----------- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/docs/resources/starter-prompt.md b/docs/resources/starter-prompt.md index 53f11df8b67..c18011995e9 100644 --- a/docs/resources/starter-prompt.md +++ b/docs/resources/starter-prompt.md @@ -218,8 +218,9 @@ Use `channels add` and rebuild only for channels omitted from initial onboarding - If a loaded platform asset selects Express, follow its policy requirement and skip the policy-tier question. - For non-Express installation, ask for Balanced, Restricted, or Open policy. - Explain that messaging and web-search selections add required endpoints. -- Before installation, summarize platform, administrator access, agent, Express choice, provider, exact model, validation warning, downloads, storage, sandbox, web search, messaging, policy, credential names without their values, and system changes. -- Ask for final permission. +- Before non-Express installation, summarize platform, administrator access, agent, provider, exact model, validation warning, downloads, storage, sandbox, web search, messaging, policy, credential names without their values, and system changes. +- Ask for final permission before non-Express installation. +- For Express, treat the platform asset's confirmation as final permission and do not ask again. - Set `NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1` and `NEMOCLAW_YES=1` only after their approvals. - Keep credentials in the approved environment and never display them. - Verify the command and version, sandbox status, provider, model, `inference.local`, GPU access when applicable, messaging bridges when configured, and dashboard route when available. diff --git a/test/starter-prompt-docs.test.ts b/test/starter-prompt-docs.test.ts index bdbbd1f530d..101ce7cc5cf 100644 --- a/test/starter-prompt-docs.test.ts +++ b/test/starter-prompt-docs.test.ts @@ -22,19 +22,18 @@ const repoRoot = path.resolve(__dirname, ".."); const starterPromptMarkdownSource = path.join(repoRoot, "docs", "resources", "starter-prompt.md"); const promptAssetRevision = "e2dffc192a6f8a05b1a2f3afb142d39864a0a688"; + +function definePromptAsset(assetPath: string): { path: string; url: string } { + return { + path: assetPath, + url: `https://raw.githubusercontent.com/NVIDIA/NemoClaw/${promptAssetRevision}/${assetPath}`, + }; +} + const promptAssets = { - dgxSpark: { - path: "docs/resources/prompt-assets/dgx-spark.md", - url: `https://raw.githubusercontent.com/NVIDIA/NemoClaw/${promptAssetRevision}/docs/resources/prompt-assets/dgx-spark.md`, - }, - dgxStation: { - path: "docs/resources/prompt-assets/dgx-station.md", - url: `https://raw.githubusercontent.com/NVIDIA/NemoClaw/${promptAssetRevision}/docs/resources/prompt-assets/dgx-station.md`, - }, - windowsWsl: { - path: "docs/resources/prompt-assets/windows-wsl.md", - url: `https://raw.githubusercontent.com/NVIDIA/NemoClaw/${promptAssetRevision}/docs/resources/prompt-assets/windows-wsl.md`, - }, + dgxSpark: definePromptAsset("docs/resources/prompt-assets/dgx-spark.md"), + dgxStation: definePromptAsset("docs/resources/prompt-assets/dgx-station.md"), + windowsWsl: definePromptAsset("docs/resources/prompt-assets/windows-wsl.md"), } as const; const localCredentialFormSource = path.join( repoRoot, @@ -685,6 +684,10 @@ describe("starter prompt docs CTA", () => { expect(promptSource).toContain( "For non-Express installation, ask for Balanced, Restricted, or Open policy.", ); + expect(promptSource).toContain( + "For Express, treat the platform asset's confirmation as final permission and do not ask again.", + ); + expect(promptSource).toContain("Ask for final permission before non-Express installation."); expect(promptSource).not.toContain("\n- Ask for Balanced, Restricted, or Open policy.\n"); for (const assetSource of expressAssets) { @@ -700,6 +703,16 @@ describe("starter prompt docs CTA", () => { expect(assetSource).toContain( "Do not ask again for the agent or ask separate questions for model, sandbox name, web search, messaging, policy, download approval, or final installation approval.", ); + expect(assetSource).toContain( + "Set `NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1` when Express is accepted.", + ); + expect(assetSource).toContain("Treat the Express confirmation as approval"); + const noticeIndex = assetSource.indexOf("Include the third-party-software notice"); + const confirmationIndex = assetSource.indexOf("Choices:"); + const acceptanceIndex = assetSource.indexOf("Set `NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1`"); + expect(noticeIndex).toBeGreaterThan(-1); + expect(confirmationIndex).toBeGreaterThan(noticeIndex); + expect(acceptanceIndex).toBeGreaterThan(confirmationIndex); expect(assetSource).not.toContain("NEMOCLAW_POLICY_TIER=balanced"); } }); From c96d984fc49e338d8319d262bc36ff16a24dcbbb Mon Sep 17 00:00:00 2001 From: San Dang Date: Fri, 17 Jul 2026 15:54:42 +0700 Subject: [PATCH 08/17] docs: align Station Express with lkg model Signed-off-by: San Dang --- docs/resources/prompt-assets/dgx-station.md | 6 +++--- test/starter-prompt-docs.test.ts | 9 +++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/docs/resources/prompt-assets/dgx-station.md b/docs/resources/prompt-assets/dgx-station.md index b9d6b6e55fd..26784f042ff 100644 --- a/docs/resources/prompt-assets/dgx-station.md +++ b/docs/resources/prompt-assets/dgx-station.md @@ -7,8 +7,8 @@ Use these instructions only after hardware detection confirms DGX Station. -Explain that Express uses the default local inference setup with Nemotron 3 Ultra in vLLM. -Disclose that it downloads the pinned vLLM container and approximately 352 GB of model data. +Explain that Express uses the default local inference setup with DeepSeek V4 Flash in vLLM. +Disclose that it downloads the pinned vLLM container and model data. Verify that the model-cache filesystem and Docker storage have enough capacity before continuing. Explain that DGX Station remains an evaluation path with deferred end-to-end validation on physical hardware, so startup may still fail after readiness checks. Include the third-party-software notice, then ask: "Do you want the recommended Express Install?" @@ -20,7 +20,7 @@ Choices: If Express is selected: - Set `NEMOCLAW_PROVIDER=install-vllm`. -- Set `NEMOCLAW_VLLM_MODEL=nemotron-3-ultra-550b-a55b` and `NEMOCLAW_MODEL=nvidia/nemotron-3-ultra-550b-a55b`. +- Set `NEMOCLAW_VLLM_MODEL=deepseek-v4-flash` and `NEMOCLAW_MODEL=deepseek-ai/DeepSeek-V4-Flash`. - Set `NEMOCLAW_AGENT` to the agent already selected in the starter prompt. - Set `NEMOCLAW_NON_INTERACTIVE=1`, `NEMOCLAW_NON_INTERACTIVE_SUDO_MODE=prompt`, `NEMOCLAW_YES=1`, and `NEMOCLAW_POLICY_MODE=suggested`. - Set `NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1` when Express is accepted. diff --git a/test/starter-prompt-docs.test.ts b/test/starter-prompt-docs.test.ts index 101ce7cc5cf..cc1fcd2a15a 100644 --- a/test/starter-prompt-docs.test.ts +++ b/test/starter-prompt-docs.test.ts @@ -653,10 +653,11 @@ describe("starter prompt docs CTA", () => { expect(sparkSource).toContain("nvidia/Qwen3.6-35B-A3B-NVFP4"); expect(sparkSource).toContain("Leave `NEMOCLAW_VLLM_MODEL` and `NEMOCLAW_MODEL` unset"); - expect(stationSource).toContain("NEMOCLAW_VLLM_MODEL=nemotron-3-ultra-550b-a55b"); - expect(stationSource).toContain("NEMOCLAW_MODEL=nvidia/nemotron-3-ultra-550b-a55b"); - expect(stationSource).toContain("default local inference setup with Nemotron 3 Ultra in vLLM"); - expect(stationSource).toContain("approximately 352 GB of model data"); + expect(stationSource).toContain("NEMOCLAW_VLLM_MODEL=deepseek-v4-flash"); + expect(stationSource).toContain("NEMOCLAW_MODEL=deepseek-ai/DeepSeek-V4-Flash"); + expect(stationSource).toContain("default local inference setup with DeepSeek V4 Flash in vLLM"); + expect(stationSource).toContain("downloads the pinned vLLM container and model data"); + expect(stationSource).not.toContain("nemotron-3-ultra"); expect(stationSource).toContain("model-cache filesystem and Docker storage"); expect(stationSource).toContain("have enough capacity before continuing"); expect(stationSource).toContain("evaluation path with deferred end-to-end validation"); From 7953cac5cbeeb8c2ac5f882e72085caad292b03c Mon Sep 17 00:00:00 2001 From: San Dang Date: Fri, 17 Jul 2026 15:56:52 +0700 Subject: [PATCH 09/17] docs: repin platform prompt assets Signed-off-by: San Dang --- docs/resources/starter-prompt.md | 6 +++--- test/starter-prompt-docs.test.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/resources/starter-prompt.md b/docs/resources/starter-prompt.md index c18011995e9..468417f8d6a 100644 --- a/docs/resources/starter-prompt.md +++ b/docs/resources/starter-prompt.md @@ -68,9 +68,9 @@ Use `NEMOCLAW_AGENT=langchain-deepagents-code` or `nemo-deepagents onboard` for After the readiness check, load exactly one matching instruction asset before provider selection: -- Confirmed DGX Spark: [DGX Spark Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/e2dffc192a6f8a05b1a2f3afb142d39864a0a688/docs/resources/prompt-assets/dgx-spark.md). -- Confirmed DGX Station: [DGX Station Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/e2dffc192a6f8a05b1a2f3afb142d39864a0a688/docs/resources/prompt-assets/dgx-station.md). -- Officially detected Windows WSL: [Windows WSL Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/e2dffc192a6f8a05b1a2f3afb142d39864a0a688/docs/resources/prompt-assets/windows-wsl.md). +- Confirmed DGX Spark: [DGX Spark Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/c96d984fc49e338d8319d262bc36ff16a24dcbbb/docs/resources/prompt-assets/dgx-spark.md). +- Confirmed DGX Station: [DGX Station Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/c96d984fc49e338d8319d262bc36ff16a24dcbbb/docs/resources/prompt-assets/dgx-station.md). +- Officially detected Windows WSL: [Windows WSL Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/c96d984fc49e338d8319d262bc36ff16a24dcbbb/docs/resources/prompt-assets/windows-wsl.md). Read the matching raw Markdown file completely and follow it before continuing. Do not load a platform asset for any other computer. diff --git a/test/starter-prompt-docs.test.ts b/test/starter-prompt-docs.test.ts index cc1fcd2a15a..21a5f0dc291 100644 --- a/test/starter-prompt-docs.test.ts +++ b/test/starter-prompt-docs.test.ts @@ -21,7 +21,7 @@ const __dirname = path.dirname(__filename); const repoRoot = path.resolve(__dirname, ".."); const starterPromptMarkdownSource = path.join(repoRoot, "docs", "resources", "starter-prompt.md"); -const promptAssetRevision = "e2dffc192a6f8a05b1a2f3afb142d39864a0a688"; +const promptAssetRevision = "c96d984fc49e338d8319d262bc36ff16a24dcbbb"; function definePromptAsset(assetPath: string): { path: string; url: string } { return { From a068500ab085d112d08711cb893984d8a720d2ef Mon Sep 17 00:00:00 2001 From: Apurv Kumaria Date: Fri, 17 Jul 2026 04:00:24 -0700 Subject: [PATCH 10/17] docs: correct Station DeepSeek install guidance Co-authored-by: Miyoung Choi Signed-off-by: Apurv Kumaria --- docs/CONTRIBUTING.md | 6 + docs/resources/prompt-assets/dgx-station.md | 43 +++++-- docs/resources/starter-prompt.md | 16 +-- test/starter-prompt-docs.test.ts | 118 +++++++++++++++++--- 4 files changed, 148 insertions(+), 35 deletions(-) diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 70c9002d9b9..bdad88a487a 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -133,6 +133,12 @@ The canonical coding-agent installation prompt lives in `docs/resources/starter- Edit that Markdown file instead of placing prompt text in a React component. Keep conditional platform instructions in focused Markdown files under `docs/resources/prompt-assets/` and link to their raw GitHub URLs from the starter prompt. The main prompt should tell the coding agent when to load each asset and should not repeat the asset's detailed instructions. +Use one shared immutable commit SHA for every platform-asset URL in a starter-prompt revision. +The contributor who changes any platform asset owns the corresponding pin update. +First commit the updated assets, starter-prompt behavior, tests, and pinned-content digests without changing the existing URLs. +Then use that commit's SHA in every platform-asset URL, update `promptAssetRevision` and every pinned SHA-256 value in `test/starter-prompt-docs.test.ts`, and commit the repin as one atomic follow-up. +Never mix asset URLs from different revisions or point an asset URL at a commit that predates its content. +The offline pinned-content test intentionally fails between the content commit and the repin commit so stale raw instructions cannot reach the final PR head unnoticed. Downstream consumers can pin the source with a raw URL such as `https://raw.githubusercontent.com/NVIDIA/NemoClaw//docs/resources/starter-prompt.md`. The Markdown SPDX comment is part of that raw file but does not appear when Markdown is rendered. diff --git a/docs/resources/prompt-assets/dgx-station.md b/docs/resources/prompt-assets/dgx-station.md index 26784f042ff..929f46fe4bf 100644 --- a/docs/resources/prompt-assets/dgx-station.md +++ b/docs/resources/prompt-assets/dgx-station.md @@ -3,30 +3,49 @@ SPDX-License-Identifier: Apache-2.0 --> -# DGX Station Express Instructions +# DGX Station DeepSeek Instructions Use these instructions only after hardware detection confirms DGX Station. -Explain that Express uses the default local inference setup with DeepSeek V4 Flash in vLLM. -Disclose that it downloads the pinned vLLM container and model data. -Verify that the model-cache filesystem and Docker storage have enough capacity before continuing. -Explain that DGX Station remains an evaluation path with deferred end-to-end validation on physical hardware, so startup may still fail after readiness checks. -Include the third-party-software notice, then ask: "Do you want the recommended Express Install?" +The provider-preseeded DeepSeek path below is not the installer Express path and is allowed only on an already-prepared DGX Station. + +Before asking for consent, explain all of these boundaries: + +- The official `--station-deepseek` installer flow may install or change NVIDIA open driver `610.43.02`, Docker CE `29.6.1` with Buildx, NVIDIA Container Toolkit `1.19.1`, and the reviewed factory `dkms` transition from `3.0.11-1ubuntu13` to `1:3.4.0-1ubuntu1`. +- Official Station preparation may add the trusted local account to the `docker` group, which grants root-equivalent control and is suitable only for a trusted single-user development host. +- Official Station preparation may require an operator-controlled reboot and resumes only with the exact accepted NemoClaw revision. +- Both Station paths may install Node.js and the NemoClaw CLI, download a pinned vLLM container and DeepSeek V4 Flash model data, require enough space on the model-cache filesystem and Docker storage, and create a sandbox with suggested policy defaults. +- DGX Station remains an evaluation path with deferred end-to-end validation on physical hardware, so startup may still fail after readiness checks. + +Ask permission to run the selected maintained release's `scripts/prepare-dgx-station-host.sh --check` and `scripts/prepare-dgx-station-host.sh --verify` readiness modes. +The checks must not apply repairs, and `--verify` may pull a pinned Ubuntu acceptance image and start short-lived GPU test containers. +Treat the host as prepared only when both modes succeed and confirm the exact Station GB300 platform, generic Ubuntu 24.04 ARM64 image, pinned driver and package versions, packaged CDI lifecycle, `nvidia.com/gpu=all`, and real CDI and `--gpus all` container access. + +If either readiness mode fails, reports a mismatch, is unavailable, or has an inconclusive outcome: + +- Do not set `NEMOCLAW_PROVIDER`, `NEMOCLAW_VLLM_MODEL`, `NEMOCLAW_MODEL`, `NEMOCLAW_NON_INTERACTIVE`, `NEMOCLAW_YES`, or `NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE`. +- Explain that the only supported next step is the official installer with `--station-deepseek`, which owns pinned Station preparation and exact-revision reboot resume, then ask permission to start it. +- Let the official installer present its third-party-software notice and complete confirmation summary. +- Keep the official confirmation visible as the single active question, wait for the user's response, and do not pre-answer or suppress it. +- If a secure interactive terminal is unavailable, stop instead of falling back to the provider-preseeded path. + +If and only if both readiness modes succeed, explain that the prepared-host path skips Station host preparation, uses DeepSeek V4 Flash in vLLM, and downloads the pinned vLLM container and model data. +Include the third-party-software notice, then ask: "Run the prepared-host DeepSeek install with these settings?" Choices: -1. Yes, use the DGX Station Express defaults. +1. Yes, use the prepared-host DeepSeek defaults. 2. No, let me choose the runtime and model. -If Express is selected: +If the prepared-host DeepSeek path is selected: - Set `NEMOCLAW_PROVIDER=install-vllm`. - Set `NEMOCLAW_VLLM_MODEL=deepseek-v4-flash` and `NEMOCLAW_MODEL=deepseek-ai/DeepSeek-V4-Flash`. - Set `NEMOCLAW_AGENT` to the agent already selected in the starter prompt. - Set `NEMOCLAW_NON_INTERACTIVE=1`, `NEMOCLAW_NON_INTERACTIVE_SUDO_MODE=prompt`, `NEMOCLAW_YES=1`, and `NEMOCLAW_POLICY_MODE=suggested`. -- Set `NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1` when Express is accepted. -- Leave `NEMOCLAW_SANDBOX_NAME`, `NEMOCLAW_POLICY_TIER`, web-search settings, and messaging settings unset so the installer applies the remaining Express defaults. -- Treat the Express confirmation as approval for the described setup and installation, and skip the later final-permission prompt. +- Set `NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1` when the prepared-host DeepSeek path is accepted. +- Leave `NEMOCLAW_SANDBOX_NAME`, `NEMOCLAW_POLICY_TIER`, web-search settings, and messaging settings unset so the installer applies the remaining maintained defaults. +- Treat the prepared-host confirmation as approval for the disclosed downloads, sandbox creation, and installation, and skip the later final-permission prompt. - Do not ask again for the agent or ask separate questions for model, sandbox name, web search, messaging, policy, download approval, or final installation approval. -If Express is declined, continue with the normal provider selection. +If the prepared-host DeepSeek path is declined, continue with the normal provider selection. Offer existing vLLM when a ready server is detected, managed vLLM, supported local Ollama, and every hosted or compatible provider supported by the selected agent. diff --git a/docs/resources/starter-prompt.md b/docs/resources/starter-prompt.md index 468417f8d6a..e071ba39ea5 100644 --- a/docs/resources/starter-prompt.md +++ b/docs/resources/starter-prompt.md @@ -69,7 +69,7 @@ Use `NEMOCLAW_AGENT=langchain-deepagents-code` or `nemo-deepagents onboard` for After the readiness check, load exactly one matching instruction asset before provider selection: - Confirmed DGX Spark: [DGX Spark Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/c96d984fc49e338d8319d262bc36ff16a24dcbbb/docs/resources/prompt-assets/dgx-spark.md). -- Confirmed DGX Station: [DGX Station Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/c96d984fc49e338d8319d262bc36ff16a24dcbbb/docs/resources/prompt-assets/dgx-station.md). +- Confirmed DGX Station: [DGX Station installation instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/c96d984fc49e338d8319d262bc36ff16a24dcbbb/docs/resources/prompt-assets/dgx-station.md). - Officially detected Windows WSL: [Windows WSL Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/c96d984fc49e338d8319d262bc36ff16a24dcbbb/docs/resources/prompt-assets/windows-wsl.md). Read the matching raw Markdown file completely and follow it before continuing. @@ -77,7 +77,7 @@ Do not load a platform asset for any other computer. ## Runtime and Provider Selection -If no platform asset applies, or its Express path is declined, ask: "Which inference runtime or provider would you like?" +If no platform asset applies, or its offered install path is declined, ask: "Which inference runtime or provider would you like?" Choices: 1. Existing vLLM, only when a ready server is detected on `localhost:8000`. @@ -119,7 +119,7 @@ Ask required model, endpoint, credential, and download questions one at a time. ## Avoid Interactive Menus - Collect every choice before running the installer. -- Ask one question at a time for model, endpoint, sandbox name, web search, messaging when the selected agent supports it, policy when Express is not selected, credentials, administrator access, and downloads. +- Ask one question at a time for model, endpoint, sandbox name, web search, messaging when the selected agent supports it, policy when no platform-asset install path is selected, credentials, administrator access, and downloads. - Use non-interactive environment variables whenever supported. - Never leave a command waiting at `Choose [1]:`. - If a choice cannot be supplied non-interactively, stop before starting and explain the supported alternative. @@ -215,12 +215,12 @@ Use `channels add` and rebuild only for channels omitted from initial onboarding ## Policy, Approval, and Verification -- If a loaded platform asset selects Express, follow its policy requirement and skip the policy-tier question. -- For non-Express installation, ask for Balanced, Restricted, or Open policy. +- If a loaded platform asset selects its approved install path, follow its policy requirement and skip the policy-tier question. +- For installation outside an accepted platform-asset path, ask for Balanced, Restricted, or Open policy. - Explain that messaging and web-search selections add required endpoints. -- Before non-Express installation, summarize platform, administrator access, agent, provider, exact model, validation warning, downloads, storage, sandbox, web search, messaging, policy, credential names without their values, and system changes. -- Ask for final permission before non-Express installation. -- For Express, treat the platform asset's confirmation as final permission and do not ask again. +- Before installation outside an accepted platform-asset path, summarize platform, administrator access, agent, provider, exact model, validation warning, downloads, storage, sandbox, web search, messaging, policy, credential names without their values, and system changes. +- Ask for final permission before installation outside an accepted platform-asset path. +- For an accepted platform-asset install path, treat the asset's confirmation as final permission and do not ask again. - Set `NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1` and `NEMOCLAW_YES=1` only after their approvals. - Keep credentials in the approved environment and never display them. - Verify the command and version, sandbox status, provider, model, `inference.local`, GPU access when applicable, messaging bridges when configured, and dashboard route when available. diff --git a/test/starter-prompt-docs.test.ts b/test/starter-prompt-docs.test.ts index 21a5f0dc291..1a64fe1c9a5 100644 --- a/test/starter-prompt-docs.test.ts +++ b/test/starter-prompt-docs.test.ts @@ -21,19 +21,37 @@ const __dirname = path.dirname(__filename); const repoRoot = path.resolve(__dirname, ".."); const starterPromptMarkdownSource = path.join(repoRoot, "docs", "resources", "starter-prompt.md"); +// These digests record the exact asset bytes at promptAssetRevision so normal tests +// can detect stale immutable links without fetching raw.githubusercontent.com. const promptAssetRevision = "c96d984fc49e338d8319d262bc36ff16a24dcbbb"; -function definePromptAsset(assetPath: string): { path: string; url: string } { +type PromptAsset = { + path: string; + pinnedSha256: string; + url: string; +}; + +function definePromptAsset(assetPath: string, pinnedSha256: string): PromptAsset { return { path: assetPath, + pinnedSha256, url: `https://raw.githubusercontent.com/NVIDIA/NemoClaw/${promptAssetRevision}/${assetPath}`, }; } const promptAssets = { - dgxSpark: definePromptAsset("docs/resources/prompt-assets/dgx-spark.md"), - dgxStation: definePromptAsset("docs/resources/prompt-assets/dgx-station.md"), - windowsWsl: definePromptAsset("docs/resources/prompt-assets/windows-wsl.md"), + dgxSpark: definePromptAsset( + "docs/resources/prompt-assets/dgx-spark.md", + "806e87f2ae7e4a4be731c7ce3b1ecde9ff8be170563d4338a5f79f76ce25e034", // gitleaks:allow -- pinned prompt-asset SHA-256 + ), + dgxStation: definePromptAsset( + "docs/resources/prompt-assets/dgx-station.md", + "c6bd3f8006f36a944cd4fbe8b89027b58ec16f583b85368fae1b11cca2569142", // gitleaks:allow -- pinned prompt-asset SHA-256 + ), + windowsWsl: definePromptAsset( + "docs/resources/prompt-assets/windows-wsl.md", + "7719b81e9304ac7cd924a9fe487a154846660557e50a0f1524f2b0dc87e729ab", // gitleaks:allow -- pinned prompt-asset SHA-256 + ), } as const; const localCredentialFormSource = path.join( repoRoot, @@ -625,7 +643,20 @@ describe("starter prompt docs CTA", () => { expect(promptSource).toContain("Existing vLLM: `NEMOCLAW_PROVIDER=vllm`"); }); - it("routes platform-only Express instructions to raw prompt assets (#6990)", () => { + it("keeps local prompt assets aligned with their immutable offline digests (#6990)", () => { + for (const asset of Object.values(promptAssets)) { + const localSource = readPromptAsset(asset); + const localSha256 = createHash("sha256").update(localSource).digest("hex"); + + expect(asset.pinnedSha256).toMatch(/^[0-9a-f]{64}$/); + expect( + localSha256, + `${asset.path} no longer matches the content pinned at ${promptAssetRevision}; commit the asset content, then repin every platform URL and digest to that commit`, + ).toBe(asset.pinnedSha256); + } + }); + + it("routes platform-only installation instructions to raw prompt assets (#6990)", () => { const promptSource = readStarterPrompt(); const sparkSource = readPromptAsset(promptAssets.dgxSpark); const stationSource = readPromptAsset(promptAssets.dgxStation); @@ -655,11 +686,23 @@ describe("starter prompt docs CTA", () => { expect(sparkSource).toContain("Leave `NEMOCLAW_VLLM_MODEL` and `NEMOCLAW_MODEL` unset"); expect(stationSource).toContain("NEMOCLAW_VLLM_MODEL=deepseek-v4-flash"); expect(stationSource).toContain("NEMOCLAW_MODEL=deepseek-ai/DeepSeek-V4-Flash"); - expect(stationSource).toContain("default local inference setup with DeepSeek V4 Flash in vLLM"); + expect(stationSource).toContain( + "provider-preseeded DeepSeek path below is not the installer Express path", + ); expect(stationSource).toContain("downloads the pinned vLLM container and model data"); expect(stationSource).not.toContain("nemotron-3-ultra"); expect(stationSource).toContain("model-cache filesystem and Docker storage"); - expect(stationSource).toContain("have enough capacity before continuing"); + expect(stationSource).toContain("scripts/prepare-dgx-station-host.sh --check"); + expect(stationSource).toContain("scripts/prepare-dgx-station-host.sh --verify"); + expect(stationSource).toContain("The checks must not apply repairs"); + expect(stationSource).toContain("If either readiness mode fails"); + expect(stationSource).toContain("Do not set `NEMOCLAW_PROVIDER`"); + expect(stationSource).toContain("official installer with `--station-deepseek`"); + expect(stationSource).toContain( + "Let the official installer present its third-party-software notice and complete confirmation summary.", + ); + expect(stationSource).toContain("If a secure interactive terminal is unavailable, stop"); + expect(stationSource).toContain("Keep the official confirmation visible"); expect(stationSource).toContain("evaluation path with deferred end-to-end validation"); expect(stationSource).toContain("startup may still fail after readiness checks"); expect(stationSource).toContain("third-party-software notice"); @@ -667,31 +710,38 @@ describe("starter prompt docs CTA", () => { expect(windowsSource).toContain("Do not start a second Ollama service on the same port."); }); - it("uses installer Express defaults without collecting optional onboarding choices (#6990)", () => { + it("uses approved platform defaults without collecting optional onboarding choices (#6990)", () => { const promptSource = readStarterPrompt(); - const expressAssets = [ + const platformAssets = [ readPromptAsset(promptAssets.dgxSpark), readPromptAsset(promptAssets.dgxStation), readPromptAsset(promptAssets.windowsWsl), ]; + const expressAssets = [ + readPromptAsset(promptAssets.dgxSpark), + readPromptAsset(promptAssets.windowsWsl), + ]; + const stationSource = readPromptAsset(promptAssets.dgxStation); expect(promptSource).toContain( "Next ask which agent I want: OpenClaw, Hermes, or LangChain Deep Agents Code.", ); expect(promptSource).toContain("Skip messaging for Deep Agents."); expect(promptSource).toContain( - "If a loaded platform asset selects Express, follow its policy requirement and skip the policy-tier question.", + "If a loaded platform asset selects its approved install path, follow its policy requirement and skip the policy-tier question.", + ); + expect(promptSource).toContain( + "For installation outside an accepted platform-asset path, ask for Balanced, Restricted, or Open policy.", ); expect(promptSource).toContain( - "For non-Express installation, ask for Balanced, Restricted, or Open policy.", + "For an accepted platform-asset install path, treat the asset's confirmation as final permission and do not ask again.", ); expect(promptSource).toContain( - "For Express, treat the platform asset's confirmation as final permission and do not ask again.", + "Ask for final permission before installation outside an accepted platform-asset path.", ); - expect(promptSource).toContain("Ask for final permission before non-Express installation."); expect(promptSource).not.toContain("\n- Ask for Balanced, Restricted, or Open policy.\n"); - for (const assetSource of expressAssets) { + for (const assetSource of platformAssets) { expect(assetSource).toContain( "`NEMOCLAW_NON_INTERACTIVE=1`, `NEMOCLAW_NON_INTERACTIVE_SUDO_MODE=prompt`, `NEMOCLAW_YES=1`, and `NEMOCLAW_POLICY_MODE=suggested`", ); @@ -704,6 +754,10 @@ describe("starter prompt docs CTA", () => { expect(assetSource).toContain( "Do not ask again for the agent or ask separate questions for model, sandbox name, web search, messaging, policy, download approval, or final installation approval.", ); + expect(assetSource).not.toContain("NEMOCLAW_POLICY_TIER=balanced"); + } + + for (const assetSource of expressAssets) { expect(assetSource).toContain( "Set `NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1` when Express is accepted.", ); @@ -714,8 +768,42 @@ describe("starter prompt docs CTA", () => { expect(noticeIndex).toBeGreaterThan(-1); expect(confirmationIndex).toBeGreaterThan(noticeIndex); expect(acceptanceIndex).toBeGreaterThan(confirmationIndex); - expect(assetSource).not.toContain("NEMOCLAW_POLICY_TIER=balanced"); } + + expect(stationSource).toContain( + "Set `NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1` when the prepared-host DeepSeek path is accepted.", + ); + expect(stationSource).toContain("Treat the prepared-host confirmation as approval"); + + const stationDisclosureIndex = stationSource.indexOf( + "official `--station-deepseek` installer flow may install or change", + ); + const stationDockerGroupIndex = stationSource.indexOf( + "`docker` group, which grants root-equivalent control", + ); + const stationRebootIndex = stationSource.indexOf("operator-controlled reboot"); + const stationNoticeIndex = stationSource.indexOf("Include the third-party-software notice"); + const stationConfirmationIndex = stationSource.indexOf("Choices:"); + const stationFailClosedIndex = stationSource.indexOf("If either readiness mode fails"); + const stationPreparedGateIndex = stationSource.indexOf( + "If and only if both readiness modes succeed", + ); + const stationProviderSetIndex = stationSource.indexOf("- Set `NEMOCLAW_PROVIDER=install-vllm`"); + const stationAcceptanceIndex = stationSource.indexOf( + "Set `NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1`", + ); + expect(stationDisclosureIndex).toBeGreaterThan(-1); + expect(stationDockerGroupIndex).toBeGreaterThan(stationDisclosureIndex); + expect(stationRebootIndex).toBeGreaterThan(stationDockerGroupIndex); + expect(stationNoticeIndex).toBeGreaterThan(stationRebootIndex); + expect(stationConfirmationIndex).toBeGreaterThan(stationNoticeIndex); + expect(stationPreparedGateIndex).toBeGreaterThan(stationFailClosedIndex); + expect(stationProviderSetIndex).toBeGreaterThan(stationPreparedGateIndex); + expect(stationAcceptanceIndex).toBeGreaterThan(stationConfirmationIndex); + expect(stationSource).toContain("NVIDIA open driver `610.43.02`"); + expect(stationSource).toContain("Docker CE `29.6.1` with Buildx"); + expect(stationSource).toContain("NVIDIA Container Toolkit `1.19.1`"); + expect(stationSource).toContain("from `3.0.11-1ubuntu13` to `1:3.4.0-1ubuntu1`"); }); it("rejects missing, ambiguous, and unsafe credential schemas (#5048)", async () => { From cf8c3781021c469468ad7c1a5f5d8297fa45265a Mon Sep 17 00:00:00 2001 From: Apurv Kumaria Date: Fri, 17 Jul 2026 04:02:24 -0700 Subject: [PATCH 11/17] docs: repin platform prompt assets Co-authored-by: Miyoung Choi Signed-off-by: Apurv Kumaria --- docs/resources/starter-prompt.md | 6 +++--- test/starter-prompt-docs.test.ts | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/resources/starter-prompt.md b/docs/resources/starter-prompt.md index e071ba39ea5..c654245faa5 100644 --- a/docs/resources/starter-prompt.md +++ b/docs/resources/starter-prompt.md @@ -68,9 +68,9 @@ Use `NEMOCLAW_AGENT=langchain-deepagents-code` or `nemo-deepagents onboard` for After the readiness check, load exactly one matching instruction asset before provider selection: -- Confirmed DGX Spark: [DGX Spark Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/c96d984fc49e338d8319d262bc36ff16a24dcbbb/docs/resources/prompt-assets/dgx-spark.md). -- Confirmed DGX Station: [DGX Station installation instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/c96d984fc49e338d8319d262bc36ff16a24dcbbb/docs/resources/prompt-assets/dgx-station.md). -- Officially detected Windows WSL: [Windows WSL Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/c96d984fc49e338d8319d262bc36ff16a24dcbbb/docs/resources/prompt-assets/windows-wsl.md). +- Confirmed DGX Spark: [DGX Spark Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/a068500ab085d112d08711cb893984d8a720d2ef/docs/resources/prompt-assets/dgx-spark.md). +- Confirmed DGX Station: [DGX Station installation instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/a068500ab085d112d08711cb893984d8a720d2ef/docs/resources/prompt-assets/dgx-station.md). +- Officially detected Windows WSL: [Windows WSL Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/a068500ab085d112d08711cb893984d8a720d2ef/docs/resources/prompt-assets/windows-wsl.md). Read the matching raw Markdown file completely and follow it before continuing. Do not load a platform asset for any other computer. diff --git a/test/starter-prompt-docs.test.ts b/test/starter-prompt-docs.test.ts index 1a64fe1c9a5..bcaf21dc9b2 100644 --- a/test/starter-prompt-docs.test.ts +++ b/test/starter-prompt-docs.test.ts @@ -23,7 +23,7 @@ const repoRoot = path.resolve(__dirname, ".."); const starterPromptMarkdownSource = path.join(repoRoot, "docs", "resources", "starter-prompt.md"); // These digests record the exact asset bytes at promptAssetRevision so normal tests // can detect stale immutable links without fetching raw.githubusercontent.com. -const promptAssetRevision = "c96d984fc49e338d8319d262bc36ff16a24dcbbb"; +const promptAssetRevision = "a068500ab085d112d08711cb893984d8a720d2ef"; type PromptAsset = { path: string; @@ -46,7 +46,7 @@ const promptAssets = { ), dgxStation: definePromptAsset( "docs/resources/prompt-assets/dgx-station.md", - "c6bd3f8006f36a944cd4fbe8b89027b58ec16f583b85368fae1b11cca2569142", // gitleaks:allow -- pinned prompt-asset SHA-256 + "709cd3cea599f31bf8d8b08cf3ac1ad90db6a03e810e2a0964c5551ed9196719", // gitleaks:allow -- pinned prompt-asset SHA-256 ), windowsWsl: definePromptAsset( "docs/resources/prompt-assets/windows-wsl.md", From 3f04330bf4ea90174d1d86095bde52251fd7f4e3 Mon Sep 17 00:00:00 2001 From: Apurv Kumaria Date: Fri, 17 Jul 2026 04:15:03 -0700 Subject: [PATCH 12/17] docs: clarify Station readiness consent Co-authored-by: Miyoung Choi Signed-off-by: Apurv Kumaria --- docs/resources/prompt-assets/dgx-station.md | 5 ++- test/starter-prompt-docs.test.ts | 47 +++++++++++++++++++-- 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/docs/resources/prompt-assets/dgx-station.md b/docs/resources/prompt-assets/dgx-station.md index 929f46fe4bf..93aaa891615 100644 --- a/docs/resources/prompt-assets/dgx-station.md +++ b/docs/resources/prompt-assets/dgx-station.md @@ -17,8 +17,11 @@ Before asking for consent, explain all of these boundaries: - Both Station paths may install Node.js and the NemoClaw CLI, download a pinned vLLM container and DeepSeek V4 Flash model data, require enough space on the model-cache filesystem and Docker storage, and create a sandbox with suggested policy defaults. - DGX Station remains an evaluation path with deferred end-to-end validation on physical hardware, so startup may still fail after readiness checks. +Both `--check` and `--verify` are read-only readiness modes, and neither applies repairs. +`--verify` requires the pinned acceptance image to already be present locally and fails if the image is missing; it does not pull the image. +`--verify` starts short-lived GPU test containers through both CDI (`nvidia.com/gpu=all`) and Docker `--gpus all`. + Ask permission to run the selected maintained release's `scripts/prepare-dgx-station-host.sh --check` and `scripts/prepare-dgx-station-host.sh --verify` readiness modes. -The checks must not apply repairs, and `--verify` may pull a pinned Ubuntu acceptance image and start short-lived GPU test containers. Treat the host as prepared only when both modes succeed and confirm the exact Station GB300 platform, generic Ubuntu 24.04 ARM64 image, pinned driver and package versions, packaged CDI lifecycle, `nvidia.com/gpu=all`, and real CDI and `--gpus all` container access. If either readiness mode fails, reports a mismatch, is unavailable, or has an inconclusive outcome: diff --git a/test/starter-prompt-docs.test.ts b/test/starter-prompt-docs.test.ts index bcaf21dc9b2..fe65debd3b9 100644 --- a/test/starter-prompt-docs.test.ts +++ b/test/starter-prompt-docs.test.ts @@ -694,10 +694,51 @@ describe("starter prompt docs CTA", () => { expect(stationSource).toContain("model-cache filesystem and Docker storage"); expect(stationSource).toContain("scripts/prepare-dgx-station-host.sh --check"); expect(stationSource).toContain("scripts/prepare-dgx-station-host.sh --verify"); - expect(stationSource).toContain("The checks must not apply repairs"); + const stationPermissionIndex = stationSource.indexOf( + "Ask permission to run the selected maintained release's", + ); + const stationReadOnlyDisclosureIndex = stationSource.indexOf( + "Both `--check` and `--verify` are read-only readiness modes, and neither applies repairs.", + ); + const stationImageDisclosureIndex = stationSource.indexOf( + "`--verify` requires the pinned acceptance image to already be present locally", + ); + const stationContainerDisclosureIndex = stationSource.indexOf( + "`--verify` starts short-lived GPU test containers through both CDI", + ); + expect(stationPermissionIndex).toBeGreaterThan(-1); + for (const disclosureIndex of [ + stationReadOnlyDisclosureIndex, + stationImageDisclosureIndex, + stationContainerDisclosureIndex, + ]) { + expect(disclosureIndex).toBeGreaterThan(-1); + expect(disclosureIndex).toBeLessThan(stationPermissionIndex); + } + expect(stationSource).not.toMatch(/--verify[^.\n]*\b(?:may|can|will)\s+pull\b/i); expect(stationSource).toContain("If either readiness mode fails"); - expect(stationSource).toContain("Do not set `NEMOCLAW_PROVIDER`"); - expect(stationSource).toContain("official installer with `--station-deepseek`"); + const stationFailureIndex = stationSource.indexOf("If either readiness mode fails"); + const stationFallbackIndex = stationSource.indexOf( + "only supported next step is the official installer with `--station-deepseek`", + stationFailureIndex, + ); + expect(stationFailureIndex).toBeGreaterThan(-1); + expect(stationFallbackIndex).toBeGreaterThan(stationFailureIndex); + const stationFailureInstructions = stationSource.slice( + stationFailureIndex, + stationFallbackIndex, + ); + expect(stationFailureInstructions).toContain("- Do not set "); + for (const environmentName of [ + "NEMOCLAW_PROVIDER", + "NEMOCLAW_VLLM_MODEL", + "NEMOCLAW_MODEL", + "NEMOCLAW_NON_INTERACTIVE", + "NEMOCLAW_YES", + "NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE", + ]) { + expect(stationFailureInstructions).toContain(`\`${environmentName}\``); + } expect(stationSource).toContain( "Let the official installer present its third-party-software notice and complete confirmation summary.", ); From 96daed6c161c1c940f81d9544c89c7851316c7a1 Mon Sep 17 00:00:00 2001 From: Apurv Kumaria Date: Fri, 17 Jul 2026 04:16:21 -0700 Subject: [PATCH 13/17] docs: repin platform prompt assets Co-authored-by: Miyoung Choi Signed-off-by: Apurv Kumaria --- docs/resources/starter-prompt.md | 6 +++--- test/starter-prompt-docs.test.ts | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/resources/starter-prompt.md b/docs/resources/starter-prompt.md index c654245faa5..c799571d536 100644 --- a/docs/resources/starter-prompt.md +++ b/docs/resources/starter-prompt.md @@ -68,9 +68,9 @@ Use `NEMOCLAW_AGENT=langchain-deepagents-code` or `nemo-deepagents onboard` for After the readiness check, load exactly one matching instruction asset before provider selection: -- Confirmed DGX Spark: [DGX Spark Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/a068500ab085d112d08711cb893984d8a720d2ef/docs/resources/prompt-assets/dgx-spark.md). -- Confirmed DGX Station: [DGX Station installation instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/a068500ab085d112d08711cb893984d8a720d2ef/docs/resources/prompt-assets/dgx-station.md). -- Officially detected Windows WSL: [Windows WSL Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/a068500ab085d112d08711cb893984d8a720d2ef/docs/resources/prompt-assets/windows-wsl.md). +- Confirmed DGX Spark: [DGX Spark Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/3f04330bf4ea90174d1d86095bde52251fd7f4e3/docs/resources/prompt-assets/dgx-spark.md). +- Confirmed DGX Station: [DGX Station installation instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/3f04330bf4ea90174d1d86095bde52251fd7f4e3/docs/resources/prompt-assets/dgx-station.md). +- Officially detected Windows WSL: [Windows WSL Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/3f04330bf4ea90174d1d86095bde52251fd7f4e3/docs/resources/prompt-assets/windows-wsl.md). Read the matching raw Markdown file completely and follow it before continuing. Do not load a platform asset for any other computer. diff --git a/test/starter-prompt-docs.test.ts b/test/starter-prompt-docs.test.ts index fe65debd3b9..fe8b355be0e 100644 --- a/test/starter-prompt-docs.test.ts +++ b/test/starter-prompt-docs.test.ts @@ -23,7 +23,7 @@ const repoRoot = path.resolve(__dirname, ".."); const starterPromptMarkdownSource = path.join(repoRoot, "docs", "resources", "starter-prompt.md"); // These digests record the exact asset bytes at promptAssetRevision so normal tests // can detect stale immutable links without fetching raw.githubusercontent.com. -const promptAssetRevision = "a068500ab085d112d08711cb893984d8a720d2ef"; +const promptAssetRevision = "3f04330bf4ea90174d1d86095bde52251fd7f4e3"; type PromptAsset = { path: string; @@ -46,7 +46,7 @@ const promptAssets = { ), dgxStation: definePromptAsset( "docs/resources/prompt-assets/dgx-station.md", - "709cd3cea599f31bf8d8b08cf3ac1ad90db6a03e810e2a0964c5551ed9196719", // gitleaks:allow -- pinned prompt-asset SHA-256 + "5e85a64ebd98e70c1e891877a7a87b43a50d731115ec643109854aaadfab631d", // gitleaks:allow -- pinned prompt-asset SHA-256 ), windowsWsl: definePromptAsset( "docs/resources/prompt-assets/windows-wsl.md", From f3682a5be7069e58303d3345e682424d5c2453b2 Mon Sep 17 00:00:00 2001 From: Apurv Kumaria Date: Fri, 17 Jul 2026 04:58:21 -0700 Subject: [PATCH 14/17] docs(station): disclose verify container effects Co-authored-by: Miyoung Choi Signed-off-by: Apurv Kumaria --- docs/resources/prompt-assets/dgx-station.md | 4 ++-- test/starter-prompt-docs.test.ts | 13 +++++++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/docs/resources/prompt-assets/dgx-station.md b/docs/resources/prompt-assets/dgx-station.md index 93aaa891615..fd26167e689 100644 --- a/docs/resources/prompt-assets/dgx-station.md +++ b/docs/resources/prompt-assets/dgx-station.md @@ -17,9 +17,9 @@ Before asking for consent, explain all of these boundaries: - Both Station paths may install Node.js and the NemoClaw CLI, download a pinned vLLM container and DeepSeek V4 Flash model data, require enough space on the model-cache filesystem and Docker storage, and create a sandbox with suggested policy defaults. - DGX Station remains an evaluation path with deferred end-to-end validation on physical hardware, so startup may still fail after readiness checks. -Both `--check` and `--verify` are read-only readiness modes, and neither applies repairs. +Both `--check` and `--verify` are non-repairing readiness modes, and neither applies host repairs. `--verify` requires the pinned acceptance image to already be present locally and fails if the image is missing; it does not pull the image. -`--verify` starts short-lived GPU test containers through both CDI (`nvidia.com/gpu=all`) and Docker `--gpus all`. +`--verify` is not read-only: it starts short-lived GPU test containers through both CDI (`nvidia.com/gpu=all`) and Docker `--gpus all`, consumes GPU and temporary Docker storage, and may create Docker state and logs. Ask permission to run the selected maintained release's `scripts/prepare-dgx-station-host.sh --check` and `scripts/prepare-dgx-station-host.sh --verify` readiness modes. Treat the host as prepared only when both modes succeed and confirm the exact Station GB300 platform, generic Ubuntu 24.04 ARM64 image, pinned driver and package versions, packaged CDI lifecycle, `nvidia.com/gpu=all`, and real CDI and `--gpus all` container access. diff --git a/test/starter-prompt-docs.test.ts b/test/starter-prompt-docs.test.ts index fe8b355be0e..0c80c623e3c 100644 --- a/test/starter-prompt-docs.test.ts +++ b/test/starter-prompt-docs.test.ts @@ -697,18 +697,23 @@ describe("starter prompt docs CTA", () => { const stationPermissionIndex = stationSource.indexOf( "Ask permission to run the selected maintained release's", ); - const stationReadOnlyDisclosureIndex = stationSource.indexOf( - "Both `--check` and `--verify` are read-only readiness modes, and neither applies repairs.", + const stationNonRepairingDisclosureIndex = stationSource.indexOf( + "Both `--check` and `--verify` are non-repairing readiness modes, and neither applies host repairs.", ); const stationImageDisclosureIndex = stationSource.indexOf( "`--verify` requires the pinned acceptance image to already be present locally", ); const stationContainerDisclosureIndex = stationSource.indexOf( - "`--verify` starts short-lived GPU test containers through both CDI", + "`--verify` is not read-only: it starts short-lived GPU test containers through both CDI", + ); + expect(stationSource).toContain("consumes GPU and temporary Docker storage"); + expect(stationSource).toContain("may create Docker state and logs"); + expect(stationSource).not.toContain( + "Both `--check` and `--verify` are read-only readiness modes", ); expect(stationPermissionIndex).toBeGreaterThan(-1); for (const disclosureIndex of [ - stationReadOnlyDisclosureIndex, + stationNonRepairingDisclosureIndex, stationImageDisclosureIndex, stationContainerDisclosureIndex, ]) { From d1ed74470c47c52a0838a585dc3f9c8ae3783499 Mon Sep 17 00:00:00 2001 From: Apurv Kumaria Date: Fri, 17 Jul 2026 05:00:02 -0700 Subject: [PATCH 15/17] docs(station): repin prompt assets Co-authored-by: Miyoung Choi Signed-off-by: Apurv Kumaria --- docs/resources/starter-prompt.md | 6 +++--- test/starter-prompt-docs.test.ts | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/resources/starter-prompt.md b/docs/resources/starter-prompt.md index c799571d536..e0c0f595890 100644 --- a/docs/resources/starter-prompt.md +++ b/docs/resources/starter-prompt.md @@ -68,9 +68,9 @@ Use `NEMOCLAW_AGENT=langchain-deepagents-code` or `nemo-deepagents onboard` for After the readiness check, load exactly one matching instruction asset before provider selection: -- Confirmed DGX Spark: [DGX Spark Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/3f04330bf4ea90174d1d86095bde52251fd7f4e3/docs/resources/prompt-assets/dgx-spark.md). -- Confirmed DGX Station: [DGX Station installation instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/3f04330bf4ea90174d1d86095bde52251fd7f4e3/docs/resources/prompt-assets/dgx-station.md). -- Officially detected Windows WSL: [Windows WSL Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/3f04330bf4ea90174d1d86095bde52251fd7f4e3/docs/resources/prompt-assets/windows-wsl.md). +- Confirmed DGX Spark: [DGX Spark Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/f3682a5be7069e58303d3345e682424d5c2453b2/docs/resources/prompt-assets/dgx-spark.md). +- Confirmed DGX Station: [DGX Station installation instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/f3682a5be7069e58303d3345e682424d5c2453b2/docs/resources/prompt-assets/dgx-station.md). +- Officially detected Windows WSL: [Windows WSL Express instructions](https://raw.githubusercontent.com/NVIDIA/NemoClaw/f3682a5be7069e58303d3345e682424d5c2453b2/docs/resources/prompt-assets/windows-wsl.md). Read the matching raw Markdown file completely and follow it before continuing. Do not load a platform asset for any other computer. diff --git a/test/starter-prompt-docs.test.ts b/test/starter-prompt-docs.test.ts index 0c80c623e3c..48690117ada 100644 --- a/test/starter-prompt-docs.test.ts +++ b/test/starter-prompt-docs.test.ts @@ -23,7 +23,7 @@ const repoRoot = path.resolve(__dirname, ".."); const starterPromptMarkdownSource = path.join(repoRoot, "docs", "resources", "starter-prompt.md"); // These digests record the exact asset bytes at promptAssetRevision so normal tests // can detect stale immutable links without fetching raw.githubusercontent.com. -const promptAssetRevision = "3f04330bf4ea90174d1d86095bde52251fd7f4e3"; +const promptAssetRevision = "f3682a5be7069e58303d3345e682424d5c2453b2"; type PromptAsset = { path: string; @@ -46,7 +46,7 @@ const promptAssets = { ), dgxStation: definePromptAsset( "docs/resources/prompt-assets/dgx-station.md", - "5e85a64ebd98e70c1e891877a7a87b43a50d731115ec643109854aaadfab631d", // gitleaks:allow -- pinned prompt-asset SHA-256 + "82a47519f415c0c3ad1d6c5cb30dcb33de846026661d8da88054385b9789f3b5", // gitleaks:allow -- pinned prompt-asset SHA-256 ), windowsWsl: definePromptAsset( "docs/resources/prompt-assets/windows-wsl.md", From 3a8554f3bf278e6a28c72fc7a2f936c0982f634b Mon Sep 17 00:00:00 2001 From: Apurv Kumaria Date: Fri, 17 Jul 2026 10:16:45 -0700 Subject: [PATCH 16/17] test(docs): verify pinned prompt asset blobs Co-authored-by: Miyoung Choi Signed-off-by: Apurv Kumaria --- docs/CONTRIBUTING.md | 5 +- test/starter-prompt-docs.test.ts | 214 +++++++++++++++++++++++++++++-- 2 files changed, 209 insertions(+), 10 deletions(-) diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index bdad88a487a..22352e3ae96 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -135,10 +135,11 @@ Keep conditional platform instructions in focused Markdown files under `docs/res The main prompt should tell the coding agent when to load each asset and should not repeat the asset's detailed instructions. Use one shared immutable commit SHA for every platform-asset URL in a starter-prompt revision. The contributor who changes any platform asset owns the corresponding pin update. -First commit the updated assets, starter-prompt behavior, tests, and pinned-content digests without changing the existing URLs. +First commit the updated assets, starter-prompt behavior, and related tests without changing the existing URLs, `promptAssetRevision`, or pinned SHA-256 values. Then use that commit's SHA in every platform-asset URL, update `promptAssetRevision` and every pinned SHA-256 value in `test/starter-prompt-docs.test.ts`, and commit the repin as one atomic follow-up. Never mix asset URLs from different revisions or point an asset URL at a commit that predates its content. -The offline pinned-content test intentionally fails between the content commit and the repin commit so stale raw instructions cannot reach the final PR head unnoticed. +The exact-revision test compares each local asset byte-for-byte with its Git blob at `promptAssetRevision`, so the intermediate content commit intentionally fails until the atomic repin follow-up points every URL, revision, and digest at that content commit. +Updating only a local digest does not prove what the pinned revision contains. Downstream consumers can pin the source with a raw URL such as `https://raw.githubusercontent.com/NVIDIA/NemoClaw//docs/resources/starter-prompt.md`. The Markdown SPDX comment is part of that raw file but does not appear when Markdown is rendered. diff --git a/test/starter-prompt-docs.test.ts b/test/starter-prompt-docs.test.ts index 48690117ada..4862052a837 100644 --- a/test/starter-prompt-docs.test.ts +++ b/test/starter-prompt-docs.test.ts @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 +import { spawnSync } from "node:child_process"; import { createHash } from "node:crypto"; import fs from "node:fs"; import os from "node:os"; @@ -21,8 +22,8 @@ const __dirname = path.dirname(__filename); const repoRoot = path.resolve(__dirname, ".."); const starterPromptMarkdownSource = path.join(repoRoot, "docs", "resources", "starter-prompt.md"); -// These digests record the exact asset bytes at promptAssetRevision so normal tests -// can detect stale immutable links without fetching raw.githubusercontent.com. +// CI resolves this exact Git commit and byte-compares its prompt-asset blobs with +// the local files. The digests independently assert those same immutable bytes. const promptAssetRevision = "f3682a5be7069e58303d3345e682424d5c2453b2"; type PromptAsset = { @@ -53,6 +54,94 @@ const promptAssets = { "7719b81e9304ac7cd924a9fe487a154846660557e50a0f1524f2b0dc87e729ab", // gitleaks:allow -- pinned prompt-asset SHA-256 ), } as const; +const platformPromptAssetRoutes = [ + { asset: promptAssets.dgxSpark, label: "Confirmed DGX Spark" }, + { asset: promptAssets.dgxStation, label: "Confirmed DGX Station" }, + { asset: promptAssets.windowsWsl, label: "Officially detected Windows WSL" }, +] as const; + +type GitResult = { + status: number | null; + stdout: Buffer; +}; + +type GitRunner = (args: readonly string[], timeoutMs?: number) => GitResult; + +const runGit: GitRunner = (args, timeoutMs = 10_000) => { + const result = spawnSync("git", [...args], { + cwd: repoRoot, + env: { ...process.env, GIT_NO_REPLACE_OBJECTS: "1" }, + maxBuffer: 4 * 1024 * 1024, + timeout: timeoutMs, + }); + return { + status: result.status, + stdout: Buffer.isBuffer(result.stdout) ? result.stdout : Buffer.from(result.stdout ?? ""), + }; +}; + +function resolvePromptAssetRevision(revision: string, git: GitRunner = runGit): void { + if (!/^[0-9a-f]{40}$/.test(revision)) { + fail("promptAssetRevision must be a full lowercase commit SHA"); + } + + let revisionType = git(["cat-file", "-t", revision]); + if (revisionType.status !== 0) { + const fetch = git( + [ + "fetch", + "--no-tags", + "--no-recurse-submodules", + "--no-write-fetch-head", + "--depth=1", + "origin", + revision, + ], + 120_000, + ); + if (fetch.status !== 0) { + fail(`could not fetch immutable prompt asset revision ${revision}`); + } + revisionType = git(["cat-file", "-t", revision]); + } + + if (revisionType.status !== 0) { + fail(`immutable prompt asset revision ${revision} is unavailable after fetch`); + } + const objectType = revisionType.stdout.toString("utf8").trim(); + if (objectType !== "commit") { + fail(`promptAssetRevision must resolve to a commit object, got ${objectType || "no type"}`); + } +} + +function readPinnedPromptAssetBlob( + revision: string, + asset: PromptAsset, + git: GitRunner = runGit, +): Buffer { + const tree = git(["ls-tree", "-z", revision, "--", asset.path]); + if (tree.status !== 0) { + fail(`${revision} prompt asset tree could not be read for ${asset.path}`); + } + const entry = + /^(?100644|100755) blob (?[0-9a-f]{40}|[0-9a-f]{64})\t(?[^\0]+)\0$/u.exec( + tree.stdout.toString("utf8"), + ); + if (!entry?.groups || entry.groups.path !== asset.path) { + fail(`${revision} must contain exactly one regular prompt asset blob at ${asset.path}`); + } + + const blobType = git(["cat-file", "-t", entry.groups.oid]); + if (blobType.status !== 0 || blobType.stdout.toString("utf8").trim() !== "blob") { + fail(`${revision}:${asset.path} does not resolve to a readable Git blob`); + } + const blob = git(["cat-file", "blob", entry.groups.oid]); + if (blob.status !== 0) { + fail(`could not read immutable prompt asset blob ${revision}:${asset.path}`); + } + return blob.stdout; +} + const localCredentialFormSource = path.join( repoRoot, "docs", @@ -188,6 +277,42 @@ function urlsIn(content: string): URL[] { return Array.from(content.matchAll(/https?:\/\/[^\s"'<>;]+/g), ([match]) => new URL(match)); } +function promptAssetRoutesIn(content: string): Map { + const heading = "## Platform-Specific Instructions\n"; + const headingIndex = content.indexOf(heading); + if (headingIndex < 0) fail("Missing Platform-Specific Instructions section"); + const bodyStart = headingIndex + heading.length; + const nextHeading = content.indexOf("\n## ", bodyStart); + const section = content.slice(bodyStart, nextHeading < 0 ? content.length : nextHeading); + const routes = new Map(); + + for (const match of section.matchAll( + /^- (?