Skip to content

fix(install): skip shim when npm prefix equals shim dir#1718

Merged
cv merged 1 commit intoNVIDIA:mainfrom
Dongni-Yang:fix/install-shim-self-reference
Apr 10, 2026
Merged

fix(install): skip shim when npm prefix equals shim dir#1718
cv merged 1 commit intoNVIDIA:mainfrom
Dongni-Yang:fix/install-shim-self-reference

Conversation

@Dongni-Yang
Copy link
Copy Markdown
Contributor

@Dongni-Yang Dongni-Yang commented Apr 10, 2026

Summary

  • `ensure_nemoclaw_shim()` creates a self-referential shell script when `npm_config_prefix=$HOME/.local` (set in the brev E2E environment), because `cli_path` and `shim_path` resolve to the same file (`$HOME/.local/bin/nemoclaw`)
  • The shim overwrites the real npm-linked binary with a wrapper that `exec`s itself → infinite loop on invocation
  • `is_real_nemoclaw_cli()` (added in fix(install): detect and remove broken npm placeholder package #1606) correctly detected the broken binary but misidentified it as the npm placeholder package → `npm uninstall -g nemoclaw` → binary gone → install fails

Fix: Add a `-ef` guard before writing the shim. If `cli_path` and `shim_path` refer to the same file, the binary is already in place — return early.

Why #1606 didn't catch this: All local/unit tests use the default npm prefix, which differs from `NEMOCLAW_SHIM_DIR`. The self-reference only occurs when `npm_config_prefix=$HOME/.local` is explicitly exported — exclusive to the brev E2E runner. Before #1606 the broken shim was silently accepted (no verification step existed).

Fixes regression from #1606, caught by E2E brev run 24216985741.

Test plan

  • Local test suite passes (`npm test`) — 12 pre-existing failures in `runtime-shell.test.js` unchanged
  • E2E brev CI passes Phase 2 (install.sh) on this PR

Signed-off-by: Dongni Yang dongniy@nvidia.com

🤖 Generated with Claude Code

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 10, 2026

📝 Walkthrough

Walkthrough

The scripts/install.sh file's ensure_nemoclaw_shim function now includes an early guard that detects when the npm-installed binary already resolves to the intended shim path. If they match, the function refreshes PATH and updates the shell profile, then exits without creating a redundant shim.

Changes

Cohort / File(s) Summary
Installation Guard Logic
scripts/install.sh
Added early condition check in ensure_nemoclaw_shim to detect when the npm-installed binary ($cli_path) already points to the target shim path ($shim_path). If matched, refreshes PATH via refresh_path and updates shell profile via ensure_local_bin_in_profile, then exits early without creating or modifying the shim.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 A bunny hopped through install.sh with glee,
Found a shim that pointed where it ought to be,
No more redundant copies, just a gentle check—
Refresh the PATH, update the deck,
Efficiency wins, as nature's inspection's blessed! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.09% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding a guard to skip shim creation when npm prefix equals shim directory, which is the core fix addressing the self-referential shim bug.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

When npm_config_prefix=$HOME/.local (as in the brev E2E environment),
npm link places the nemoclaw binary at $HOME/.local/bin/nemoclaw —
the same path that ensure_nemoclaw_shim() targets for the wrapper shim.
Without this guard the function overwrites the real binary with a shell
script that exec's itself, causing an infinite loop.

is_real_nemoclaw_cli() (added in NVIDIA#1606) correctly detected the broken
binary but misidentified it as the npm placeholder package and ran
npm uninstall -g, leaving no binary at all.

Add a -ef guard: if cli_path and shim_path refer to the same file,
the binary is already in the right place — return early without writing
a self-referential wrapper.

Fixes NVIDIA#1606 regression caught by E2E brev (run 24216985741).

Signed-off-by: Dongni Yang <dongniy@nvidia.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@Dongni-Yang Dongni-Yang force-pushed the fix/install-shim-self-reference branch from ce8c666 to bcc9bc2 Compare April 10, 2026 00:26
@github-actions
Copy link
Copy Markdown

Brev E2E (full): FAILED on branch fix/install-shim-self-referenceSee logs

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (3)
test/validate-config-schemas.test.ts (1)

74-97: Add a positive test for protocol: rest + access (without rules).

Current negatives only assert the strict rules requirement. Once the schema condition is fixed, you’ll want a pass-case to lock that intended behavior.

Also applies to: 168-179

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/validate-config-schemas.test.ts` around lines 74 - 97, Add a positive
test case in test/validate-config-schemas.test.ts that verifies a policy
addition with protocol: "rest" can pass when using an "access" property instead
of "rules" (mirror the existing negative test "rejects blueprint policyAddition
endpoint with protocol rest but no rules" but assert validate(...) === true).
Target the same structure used in the bad case
(components.policy.additions.my_service.endpoints) but include an "access"
object (or array) appropriate to the schema (the same shape you expect to allow)
and call validate(better) expecting true; also add a similar positive case
corresponding to the other negative at lines 168-179 so both negative and
positive behaviors are covered for the protocol "rest" condition.
schemas/sandbox-policy.schema.json (1)

14-90: Consider closing nested policy objects to catch config typos earlier.

filesystem_policy, landlock, process, networkPolicyEntry, and endpoint currently allow unknown keys. In practice, this can let misspelled fields pass schema validation silently.

Suggested patch
     "filesystem_policy": {
       "type": "object",
+      "additionalProperties": false,
       "properties": {
@@
     "landlock": {
       "type": "object",
+      "additionalProperties": false,
       "properties": {
@@
     "process": {
       "type": "object",
+      "additionalProperties": false,
       "properties": {
@@
     "networkPolicyEntry": {
       "type": "object",
       "required": ["name", "endpoints"],
+      "additionalProperties": false,
       "properties": {
@@
     "endpoint": {
       "type": "object",
       "required": ["host", "port"],
+      "additionalProperties": false,
       "properties": {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@schemas/sandbox-policy.schema.json` around lines 14 - 90, The listed schema
objects allow unknown keys; update each object definition (filesystem_policy,
landlock, process, networkPolicyEntry, endpoint) to include
"additionalProperties": false so typos are rejected, and ensure any nested
arrays/refs still validate (e.g., network_policies uses networkPolicyEntry,
endpoint is referenced by networkPolicyEntry) so no other constraints are
broken; add the additionalProperties flag inside each object's "properties"
object block to disallow extraneous fields.
scripts/validate-configs.ts (1)

94-114: Reject unexpected CLI args instead of silently running default validation.

At Line [113], any unrecognized args (e.g., typoed flags) currently fall through to discoverTargets(). That can mask invocation mistakes and report misleading success.

Suggested patch
 function main(): void {
   const args = process.argv.slice(2);
@@
   const hasFileFlag = args.indexOf("--file") !== -1;
   const hasSchemaFlag = args.indexOf("--schema") !== -1;
+  if (!hasFileFlag && !hasSchemaFlag && args.length > 0) {
+    console.error("Usage: validate-configs.ts --file <config> --schema <schema>");
+    process.exitCode = 1;
+    return;
+  }
   if (hasFileFlag !== hasSchemaFlag) {
     console.error("Usage: validate-configs.ts --file <config> --schema <schema>");
     process.exitCode = 1;
     return;
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/validate-configs.ts` around lines 94 - 114, The CLI currently accepts
only --file and --schema but silently ignores any other flags and falls back to
discoverTargets(); update the argument handling in validate-configs.ts to reject
unexpected flags: after parsing args and computing hasFileFlag/hasSchemaFlag
(and before falling back to discoverTargets()), scan args for any token starting
with "-" that is not "--file" or "--schema" (and not the values immediately
following those flags), and if any unrecognized flag is found, print the same
usage message and set process.exitCode = 1 then return; ensure this logic
references the existing variables and flow using args, fileIdx/schemaIdx,
hasFileFlag/hasSchemaFlag, targets, and discoverTargets so valid --file/--schema
usage still works but typoed or unknown flags no longer silently run default
validation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.pre-commit-config.yaml:
- Line 173: The hook's files regex (the value after the files: key — currently
^(nemoclaw-blueprint/.*\.yaml$|nemoclaw/openclaw\.plugin\.json$|schemas/.*\.json$))
only matches .yaml and misses .yml files; update that regex to accept both
extensions (for example replace \.yaml$ with \.(?:yml|yaml)$ or use \.ya?ml$) so
changes to .yml presets/configs will trigger the schema validation pre-commit
hook.

In `@schemas/blueprint.schema.json`:
- Around line 137-141: The JSON Schema currently forces protocol "rest" to
always include "rules"; update the conditional so REST endpoints must include
either "rules" or an access policy instead of mandating "rules" unconditionally.
Concretely, replace the "then": { "required": ["rules"] } with a clause that
requires at least one of ["rules","access"] (e.g., "then": { "anyOf": [ {
"required": ["rules"] }, { "required": ["access"] } ] } ), keeping the existing
"if" that checks "protocol": "rest".

In `@schemas/policy-preset.schema.json`:
- Around line 60-64: The current conditional requires "rules" when protocol is
"rest", which disallows REST presets that use "access"; update the schema
conditional block (the "if" that checks properties.protocol === "rest") so its
"then" allows either "rules" OR "access" — replace the existing then: {
"required": ["rules"] } with a then that uses oneOf: [ { "required": ["rules"]
}, { "required": ["access"] } ] (ensure "access" is validated elsewhere or add
its schema if missing).

---

Nitpick comments:
In `@schemas/sandbox-policy.schema.json`:
- Around line 14-90: The listed schema objects allow unknown keys; update each
object definition (filesystem_policy, landlock, process, networkPolicyEntry,
endpoint) to include "additionalProperties": false so typos are rejected, and
ensure any nested arrays/refs still validate (e.g., network_policies uses
networkPolicyEntry, endpoint is referenced by networkPolicyEntry) so no other
constraints are broken; add the additionalProperties flag inside each object's
"properties" object block to disallow extraneous fields.

In `@scripts/validate-configs.ts`:
- Around line 94-114: The CLI currently accepts only --file and --schema but
silently ignores any other flags and falls back to discoverTargets(); update the
argument handling in validate-configs.ts to reject unexpected flags: after
parsing args and computing hasFileFlag/hasSchemaFlag (and before falling back to
discoverTargets()), scan args for any token starting with "-" that is not
"--file" or "--schema" (and not the values immediately following those flags),
and if any unrecognized flag is found, print the same usage message and set
process.exitCode = 1 then return; ensure this logic references the existing
variables and flow using args, fileIdx/schemaIdx, hasFileFlag/hasSchemaFlag,
targets, and discoverTargets so valid --file/--schema usage still works but
typoed or unknown flags no longer silently run default validation.

In `@test/validate-config-schemas.test.ts`:
- Around line 74-97: Add a positive test case in
test/validate-config-schemas.test.ts that verifies a policy addition with
protocol: "rest" can pass when using an "access" property instead of "rules"
(mirror the existing negative test "rejects blueprint policyAddition endpoint
with protocol rest but no rules" but assert validate(...) === true). Target the
same structure used in the bad case
(components.policy.additions.my_service.endpoints) but include an "access"
object (or array) appropriate to the schema (the same shape you expect to allow)
and call validate(better) expecting true; also add a similar positive case
corresponding to the other negative at lines 168-179 so both negative and
positive behaviors are covered for the protocol "rest" condition.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1cb3410a-358f-41c8-80ed-d0daf640ad06

📥 Commits

Reviewing files that changed from the base of the PR and between e2b34fb and ce8c666.

📒 Files selected for processing (12)
  • .github/actions/basic-checks/action.yaml
  • .pre-commit-config.yaml
  • nemoclaw-blueprint/blueprint.yaml
  • package.json
  • schemas/blueprint.schema.json
  • schemas/onboard-config.schema.json
  • schemas/openclaw-plugin.schema.json
  • schemas/policy-preset.schema.json
  • schemas/sandbox-policy.schema.json
  • scripts/install.sh
  • scripts/validate-configs.ts
  • test/validate-config-schemas.test.ts

@NVIDIA NVIDIA deleted a comment from coderabbitai bot Apr 10, 2026
@NVIDIA NVIDIA deleted a comment from coderabbitai bot Apr 10, 2026
@NVIDIA NVIDIA deleted a comment from coderabbitai bot Apr 10, 2026
@cv cv merged commit bde4a53 into NVIDIA:main Apr 10, 2026
12 of 14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants