Skip to content

fix(status): show live enforced policy instead of stale baseline (#1132) - #1896

Merged
cv merged 8 commits into
mainfrom
fix/policy-add-status-not-showing-1132
Apr 15, 2026
Merged

fix(status): show live enforced policy instead of stale baseline (#1132)#1896
cv merged 8 commits into
mainfrom
fix/policy-add-status-not-showing-1132

Conversation

@yanyunl1991

@yanyunl1991 yanyunl1991 commented Apr 15, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #1132

nemoclaw status displays policy details from openshell sandbox get, which returns the immutable baseline policy from sandbox creation time. Network policies added later via nemoclaw policy-add / openshell policy set are not reflected in this baseline, causing the Policy section to be missing actively enforced
policies.

Root Cause

OpenShell maintains two separate storage locations for policy:

  1. sandbox.spec.policy (baseline) — Written once at sandbox creation. Used by validate_static_fields_unchanged() to ensure static fields (filesystem_policy, landlock, process) cannot be modified after creation, since these are kernel-level restrictions (Landlock, UID/GID) that are irreversible. Returned
    by openshell sandbox get.

  2. sandbox_policies table (runtime revisions) — Updated on every openshell policy set. The sandbox proxy reads the latest revision to enforce network access rules. Returned by openshell policy get --full.

When openshell policy set is called, it validates the new policy against the baseline, writes a new revision to the runtime table, but intentionally does NOT update sandbox.spec.policy — preserving the immutable security baseline. This means openshell sandbox get never reflects post-creation policy changes.

Fix

In getSandboxGatewayState(), after a successful openshell sandbox get, fetch the live policy via openshell policy get --full and replace the Policy section in the output. The Sandbox info and colored "Policy:" header are preserved from the original output.

Reproduction & Verification

Before fixnemoclaw status Policy section missing slack after policy-add:

Check Result
nemoclaw lyy policy-list ● slack (applied)
nemoclaw lyy status header Policies: pypi, npm, slack
openshell policy get --full lyy ✅ Contains slack endpoints
Network access from sandbox via node api.slack.com returns {"ok":true}
nemoclaw lyy status policy detail slack missing from network_policies
openshell sandbox get lyy slack missing from network_policies

nemoclaw status Policy section missing slack after policy-add:

  Policies: pypi, npm, slack    ← header shows slack (from registry)                                                                                                                                                                                                                                                         

  Policy:                                                                                                                                                                                                                                                                                                                    
    network_policies:
      claude_code: ...
      npm_registry: ...
      nvidia: ...
      openclaw_api: ...
      openclaw_docs: ...
                                 ← slack missing from policy detail! 

After fix — Policy detail section now shows all enforced policies including slack, pypi, npm_yarn (all policies added post-creation are visible).
Policy section shows all enforced policies including slack:

  Policies: pypi, npm, slack

  Policy:
    network_policies:
      claude_code: ...
      npm_registry: ...                                                                                                                                                                                                                                                                                                      
      npm_yarn: ...
      nvidia: ...                                                                                                                                                                                                                                                                                                            
      openclaw_api: ...
      openclaw_docs: ...
      pypi: ...
      slack:                     ← now visible
        name: slack
        endpoints:
        - host: slack.com                                                                                                                                                                                                                                                                                                    
        ...                                                                                                                                                              

Test plan

  • Reproduced on Ubuntu 24.04 (NemoClaw v0.1.0, OpenShell 0.0.20)
  • Verified nemoclaw policy-add slack → nemoclaw status now shows slack in Policy detail
  • Verified Sandbox info section preserved with colors
  • Verified OpenClaw/NIM status lines still display correctly
  • Verified fallback: if policy get --full fails, original output shown unchanged
  • Existing test suite passes

Summary by CodeRabbit

  • New Features

    • Automatic gateway recovery: the system can attempt to recover named gateways when their lifecycle isn't healthy and reports whether recovery was attempted and which recovery path was used.
  • Bug Fixes

    • Sandbox details now display the live enforced policy YAML (replacing the previous static policy section) so shown policy matches current enforced configuration.
  • Documentation

    • Added inline documentation for lifecycle hint output.

Signed-off-by: Yanyun Liao yanyunl@nvidia.com

yanyunl1991 and others added 4 commits April 15, 2026 10:06
`nemoclaw status` displays the policy detail from `openshell sandbox get`,
which returns the immutable baseline policy from sandbox creation time.
Network policies added later via `nemoclaw policy-add` (which calls
`openshell policy set`) are not reflected in this baseline — by design,
OpenShell preserves it for static field validation (filesystem_policy,
landlock, process fields are kernel-level and irreversible).

This causes the Policy section in `nemoclaw status` to be missing
policies that were successfully applied and are actively enforced.

Fix: In `getSandboxGatewayState`, after a successful `sandbox get`,
fetch the live policy via `openshell policy get --full` and replace
the Policy section in the output. The Sandbox info and colored
"Policy:" header are preserved from the original output.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Yanyun Liao <yanyunl@nvidia.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Yanyun Liao <yanyunl@nvidia.com>
Use regex with multiline flag to match "---" separator regardless of
line endings (\n, \r\n) or trailing whitespace.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Yanyun Liao <yanyunl@nvidia.com>
…overage

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Yanyun Liao <yanyunl@nvidia.com>
@coderabbitai

coderabbitai Bot commented Apr 15, 2026

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: f7388bd7-b33d-4531-a7b2-fb687f4aae66

📥 Commits

Reviewing files that changed from the base of the PR and between f991115 and 515c634.

📒 Files selected for processing (1)
  • src/nemoclaw.ts
✅ Files skipped from review due to trivial changes (1)
  • src/nemoclaw.ts

📝 Walkthrough

Walkthrough

Added async recoverNamedGatewayRuntime() to attempt recovering a named gateway (select, recheck, optionally start) and enhanced getSandboxGatewayState() to fetch live policy via openshell, extract YAML from the first ---, re-indent it, and replace the Policy section in captured sandbox output. JSDoc added for printGatewayLifecycleHint().

Changes

Cohort / File(s) Summary
Gateway & Sandbox State
src/nemoclaw.ts
Added recoverNamedGatewayRuntime() (select gateway, snapshot lifecycle, re-check, optionally start via guarded startGatewayForRecovery(), set OPENSHELL_GATEWAY on success, return recovery metadata). Modified getSandboxGatewayState() to call openshell policy get --full, extract YAML from first ---, heuristically validate, re-indent (2-space) and replace the Policy: section in the sandbox output. Added JSDoc for printGatewayLifecycleHint().

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant Nemoclaw
  participant Openshell
  participant GatewayRuntime

  Caller->>Nemoclaw: recoverNamedGatewayRuntime(name)
  Nemoclaw->>GatewayRuntime: selectNamedGateway(name)
  Nemoclaw->>GatewayRuntime: getLifecycleState()
  alt lifecycle != "healthy_named"
    Nemoclaw->>Openshell: sandbox get (capture output)
    Openshell-->>Nemoclaw: sandbox output (ANSI colored)
    Nemoclaw->>Openshell: policy get --full sandboxName (ignore errors)
    Openshell-->>Nemoclaw: full policy output (may contain '---' YAML)
    Nemoclaw->>Nemoclaw: extract YAML from first '---', validate, re-indent
    Nemoclaw->>Nemoclaw: replace Policy: section in sandbox output
    alt allowed by lifecycle guards
      Nemoclaw->>GatewayRuntime: startGatewayForRecovery()
      GatewayRuntime-->>Nemoclaw: new lifecycle state
    end
    Nemoclaw->>GatewayRuntime: re-select and re-check lifecycle
    Nemoclaw->>Nemoclaw: set process.env.OPENSHELL_GATEWAY on success
  end
  Nemoclaw-->>Caller: recovery result {attempted, via, state, output}
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

I nibble through YAML, neat and spry,
I hop and paste the policy sky,
I strip the colors, find the dash,
I indent twice with a happy splash,
A rabbit's patch — now policies fly! 🐇✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(status): show live enforced policy instead of stale baseline' directly and accurately describes the main change: replacing stale baseline policy display with live enforced policy in status output.
Linked Issues check ✅ Passed The PR directly addresses issue #1132 by fetching live policy via 'openshell policy get --full' and replacing the stale baseline policy in getSandboxGatewayState(), allowing 'nemoclaw status' to show runtime policy revisions including those added post-creation.
Out of Scope Changes check ✅ Passed All changes remain within scope: recoverNamedGatewayRuntime() addition supports recovery logic, getSandboxGatewayState() enhancement implements the core fix, and JSDoc addition for printGatewayLifecycleHint() is minor documentation without scope creep.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/policy-add-status-not-showing-1132

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

@yanyunl1991 yanyunl1991 changed the title Fix/policy add status not showing 1132 fix(status): show live enforced policy instead of stale baseline 1132 Apr 15, 2026
@yanyunl1991 yanyunl1991 changed the title fix(status): show live enforced policy instead of stale baseline 1132 fix(status): show live enforced policy instead of stale baseline (#1132) Apr 15, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/nemoclaw.ts`:
- Around line 562-578: The code replaces the "Policy:" section whenever
livePolicy.output is non-empty; instead, only replace when the extracted
yamlPart actually looks like a policy YAML. After computing delimIdx and
yamlPart, validate yamlPart with a regex for expected top-level policy keys (for
example /(^|\n)\s*(name|rules|version)\s*:/m) or reuse the existing guard logic
from policies.ts; if the check passes proceed to indent and replace (using
yamlPart), otherwise leave output unchanged so warnings/status text isn't
mistaken for policy YAML (references: livePolicy, policyLineIdx, delimIdx,
yamlPart).
🪄 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 Plus

Run ID: c0e8000e-8cd3-4ec3-b1a3-9047250aff18

📥 Commits

Reviewing files that changed from the base of the PR and between 8fac9d6 and ee2da0f.

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

Comment thread src/nemoclaw.ts Outdated
yanyunl1991 and others added 2 commits April 15, 2026 10:16
Only replace the Policy section when the extracted content looks like
valid policy YAML (starts with a YAML key). Prevents replacing with
warnings or status text from unexpected openshell output.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Yanyun Liao <yanyunl@nvidia.com>
…verage

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Yanyun Liao <yanyunl@nvidia.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/nemoclaw.ts (1)

576-584: Consider adding error/warning prefix check for robustness.

The YAML-key regex guard at line 580 doesn't prevent error messages from being treated as valid policy content. Messages like error: connection refused or warning: timeout match the pattern /^[a-z_][a-z0-9_]*\s*:/m since error: and warning: look like YAML keys.

The existing parseCurrentPolicy() in src/lib/policies.ts (lines 87-89) guards against this with an explicit prefix check before the YAML-key test.

🛡️ Proposed fix to add error prefix guard
         // Guard: only replace if the extracted content looks like policy YAML
         // (starts with a YAML key like "version:" or "network_policies:").
         // Avoids replacing with warnings or status text from unexpected output.
         const trimmedYaml = yamlPart.trim();
-        if (trimmedYaml && /^[a-z_][a-z0-9_]*\s*:/m.test(trimmedYaml)) {
+        const looksLikeError = /^(error|failed|invalid|warning|status)\b/i.test(trimmedYaml);
+        if (trimmedYaml && !looksLikeError && /^[a-z_][a-z0-9_]*\s*:/m.test(trimmedYaml)) {
           // Add 2-space indent to match the original sandbox get output format.
           const indented = trimmedYaml.split("\n").map((l) => (l ? "  " + l : l)).join("\n");
           output = before + "\n\n" + indented + "\n";
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/nemoclaw.ts` around lines 576 - 584, The YAML guard in nemoclaw.ts
currently treats lines like "error: ..." or "warning: ..." as valid YAML keys;
update the validation around trimmedYaml (the block that computes indented and
assigns output) to first reject strings that begin with known non-policy
prefixes (e.g., /^ *(error|warning|status):/i) before applying the
/^[a-z_][a-z0-9_]*\s*:/m test, mirroring the prefix check used in
parseCurrentPolicy() in src/lib/policies.ts; ensure you reference trimmedYaml
and keep the existing indentation and output assignment logic only for content
that passes the new prefix filter.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/nemoclaw.ts`:
- Around line 576-584: The YAML guard in nemoclaw.ts currently treats lines like
"error: ..." or "warning: ..." as valid YAML keys; update the validation around
trimmedYaml (the block that computes indented and assigns output) to first
reject strings that begin with known non-policy prefixes (e.g., /^
*(error|warning|status):/i) before applying the /^[a-z_][a-z0-9_]*\s*:/m test,
mirroring the prefix check used in parseCurrentPolicy() in src/lib/policies.ts;
ensure you reference trimmedYaml and keep the existing indentation and output
assignment logic only for content that passes the new prefix filter.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 26c7bd0f-4516-464e-b450-8af8c89c94b4

📥 Commits

Reviewing files that changed from the base of the PR and between e008d87 and 2b7b904.

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

Add explicit prefix check for error/warning/status text before the
YAML-key regex, mirroring parseCurrentPolicy() in policies.ts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Yanyun Liao <yanyunl@nvidia.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/nemoclaw.ts (1)

559-585: Add regression coverage for the policy-output parser.

This now depends on delimiter detection plus heuristic YAML guards before rewriting the Policy: section. Please add focused tests for at least: valid policy get --full YAML, exit-0 warning/status text, and output with no Policy: header so future CLI output changes don't silently reintroduce stale or malformed status output.

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

In `@src/nemoclaw.ts` around lines 559 - 585, Add regression tests for the
policy-output parser that exercise the new delimiter detection and YAML-guard
heuristics: write focused tests that simulate captureOpenshell returning (1) a
valid `policy get --full` output whose YAML begins at the `---` delimiter and
should be preserved and indented (exercise the delimIdx, yamlPart, trimmedYaml
and indented logic), (2) an exit-0 output that contains only warning/status text
(e.g. lines starting with "warning", "status", "failed", which should trigger
looksLikeError and NOT replace the Policy: section), and (3) output that
contains no "Policy:" header (policyLineIdx === -1) to ensure no rewrite occurs;
implement these by stubbing/mocking the captureOpenshell result
(livePolicy.output and livePolicy.status) and asserting the final output value
produced by the parser code in nemoclaw.ts (the block referencing livePolicy,
policyLineIdx, delimIdx, yamlPart, trimmedYaml and looksLikeError).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/nemoclaw.ts`:
- Around line 559-585: Add regression tests for the policy-output parser that
exercise the new delimiter detection and YAML-guard heuristics: write focused
tests that simulate captureOpenshell returning (1) a valid `policy get --full`
output whose YAML begins at the `---` delimiter and should be preserved and
indented (exercise the delimIdx, yamlPart, trimmedYaml and indented logic), (2)
an exit-0 output that contains only warning/status text (e.g. lines starting
with "warning", "status", "failed", which should trigger looksLikeError and NOT
replace the Policy: section), and (3) output that contains no "Policy:" header
(policyLineIdx === -1) to ensure no rewrite occurs; implement these by
stubbing/mocking the captureOpenshell result (livePolicy.output and
livePolicy.status) and asserting the final output value produced by the parser
code in nemoclaw.ts (the block referencing livePolicy, policyLineIdx, delimIdx,
yamlPart, trimmedYaml and looksLikeError).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 4bbb6d51-bd72-4168-9708-a5b6c264bdcc

📥 Commits

Reviewing files that changed from the base of the PR and between 2b7b904 and f991115.

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

@cv
cv merged commit ef39d7e into main Apr 15, 2026
13 checks passed
cv pushed a commit that referenced this pull request Apr 15, 2026
## Summary
- Document `nemoclaw <name> snapshot create/list/restore` commands (from
#1892)
- Document `nemoclaw <name> policy-remove` command (from #1822)
- Document `nemoclaw <name> rebuild` command with version staleness
detection (from #1870)
- Document `nemoclaw backup-all` command (from #1870)
- Update `status` to mention live enforced policy display (from #1896)
- Update `connect` and `status` to mention version staleness warnings
(from #1870)
- Update `destroy` to reference snapshots and rebuild as alternatives
- Add snapshot commands section to backup-restore page
- Add `policy-remove` to customize-network-policy page
- Add "Sandbox is running an outdated agent version" troubleshooting
entry
- Bump doc version switcher through 0.0.16
- Regenerate agent skills from updated docs

## Test plan
- [x] `make docs` builds without warnings
- [x] All pre-commit hooks pass
- [ ] Verify rendered pages in docs build output

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Documentation**
* Added documentation for policy preset removal command with selection
flow
* Documented new rebuild command for sandbox upgrades while preserving
workspace state
* Introduced snapshot commands for creating, listing, and restoring
workspace backups
  * Added bulk backup capability for multiple sandboxes
* Enhanced agent version warnings in connect and status commands with
remediation guidance
* Expanded troubleshooting guide with outdated agent version resolution
steps

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@wscurran wscurran added the bug-fix PR fixes a bug or regression label Jun 8, 2026
@cv
cv deleted the fix/policy-add-status-not-showing-1132 branch June 28, 2026 00:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug-fix PR fixes a bug or regression

Projects

None yet

Development

Successfully merging this pull request may close these issues.

network policy for slack won't apply

3 participants