fix(shields): self-heal root-owned mutable OpenClaw config on boot#6307
Conversation
The boot-time normalize step treated any root-owned /sandbox/.openclaw as an intentional shields-up lock and skipped repair. When the runtime leaves the mutable-default config tree root-owned, the sandbox user can no longer write openclaw.json in the default state. Classify a root-owned tree by its sealed signature (0755 dir plus a 0444 root:root openclaw.json) and reclaim only a confirmed collapse back to the sandbox:sandbox 2770/660 group contract. A genuine shields-up lock, or any ambiguous state, is left untouched so the lock is never weakened. The reclaim is root-only and refuses symlinked config paths. Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: Tinson Lai <tinsonl@nvidia.com>
|
Note Reviews pausedIt 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 Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds seal classification and reclaim logic for root-owned OpenClaw config trees, wires startup to use it, updates shell test harnesses and coverage, and documents the new trusted-helper boundaries. ChangesMutable config seal/reclaim
Estimated code review effort: 4 (Complex) | ~60 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Code Coverage OverviewLanguages: TypeScript TypeScript / code-coverage/pluginThe overall coverage in the branch is 96%. Coverage data for the branch is not yet available. Show a code coverage summary of the most covered files.
TypeScript / code-coverage/cliThe overall coverage in the branch is 75%. Coverage data for the branch is not yet available. Show a code coverage summary of the most covered files.
Updated |
PR Review Advisor (Nemotron Ultra) — Changes requestedMerge posture: Do not merge yet Action checklist
Findings index
🚨 Required before mergeAddress these before merging unless a maintainer explicitly overrides the advisor with rationale.
|
E2E Advisor RecommendationRequired E2E: Dispatch hint: Full advisor summaryE2E Recommendation AdvisorBase: Required E2E
Optional E2E
New E2E recommendations
Dispatch hint
|
E2E Target RecommendationRequired E2E targets: Dispatch required E2E targets:
Full E2E target advisor summaryE2E Target AdvisorBase: Required E2E targets
Optional E2E targets
Relevant changed files
|
PR Review Advisor — Changes requestedMerge posture: Do not merge yet Action checklist
Findings index
Review findings by urgency: 0 required fixes, 2 items to resolve/justify, 0 in-scope improvements
|
There was a problem hiding this comment.
🧹 Nitpick comments (1)
test/nemoclaw-start-perms.test.ts (1)
399-422: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd a negative-path test proving reclaim refuses a symlinked config path.
The reclaim describe block only exercises the non-root guard. The symlink-refusal branch (
reclaim_collapsed_mutable_configreturningrc=1and leaving the tree untouched) is untested, yet it is the core boundary check. Add a root-gated test that symlinksconfig_dir/openclaw.jsonand asserts the reclaim refuses without following the link.As per path instructions, this boundary requires negative-path tests that prove bypasses are rejected.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@test/nemoclaw-start-perms.test.ts` around lines 399 - 422, The current reclaim tests cover only the non-root ownership guard, but the symlink-refusal path in reclaim_collapsed_mutable_config is missing. Add a root-gated negative-path test in the nemoclaw-start mutable config reclaim describe block that creates a symlinked config path (or symlinked openclaw.json), invokes reclaim_collapsed_mutable_config, and verifies it returns rc=1 without changing the tree. Use the existing reclaimFunction helper and the reclaim_collapsed_mutable_config call site to locate the behavior under test, and assert the on-disk ownership/contents remain untouched.Source: Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@test/nemoclaw-start-perms.test.ts`:
- Around line 399-422: The current reclaim tests cover only the non-root
ownership guard, but the symlink-refusal path in
reclaim_collapsed_mutable_config is missing. Add a root-gated negative-path test
in the nemoclaw-start mutable config reclaim describe block that creates a
symlinked config path (or symlinked openclaw.json), invokes
reclaim_collapsed_mutable_config, and verifies it returns rc=1 without changing
the tree. Use the existing reclaimFunction helper and the
reclaim_collapsed_mutable_config call site to locate the behavior under test,
and assert the on-disk ownership/contents remain untouched.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: 20c5f477-5ca5-4a2c-8c5c-ac79423be5ee
📒 Files selected for processing (2)
scripts/nemoclaw-start.shtest/nemoclaw-start-perms.test.ts
Root reclaim previously discovered entries with `find -P` and then mutated them by path with separate `chown`/`chmod` calls, leaving a window between discovery and mutation for a race to swap a pathname. Rewrite the reclaim as a single descriptor-safe pass: open the root directory with O_NOFOLLOW, re-verify it is still exactly root:root before touching anything, and recurse using pinned file descriptors (fchown/fchmod on already-open fds), verifying each entry's inode identity is unchanged after every mutation. A tree found already sealed at this point is left untouched instead of reclaimed. Add a root-mode regression test that drives the real boot path (normalize_mutable_config_perms) against a root-owned collapsed config and asserts the sandbox:sandbox 2770/660 contract and a group-writable touch both succeed, and replace the non-root test's early-return branch with it.skipIf/it.runIf gates to keep the test bodies linear. Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: Tinson Lai <tinsonl@nvidia.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
test/nemoclaw-start-perms.test.ts (1)
442-448: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winAssert the source patches actually applied — silent no-op risk.
String.prototype.replacewith a string pattern replaces only the first match and, critically, returns the original string unchanged if the substring is absent. If the production text ever drifts (e.g. the literallocal config_dir="/sandbox/.openclaw"orid -u sandbox), these patches silently no-op, and the test would then runnormalize_mutable_config_permsagainst the real/sandbox/.openclawand invoke the realid -u sandboxinstead of the test fixture — a dangerous and hard-to-debug failure mode rather than a clear test error.Consider guarding each substitution, e.g. assert the patched string differs from the input (or that the marker exists) before proceeding.
Illustrative guard
+ const applyPatch = (src: string, from: string, to: string) => { + const out = src.replace(from, to); + if (out === src) throw new Error(`Patch target not found: ${from}`); + return out; + }; const normalizeFunction = extractShellFunction("normalize_mutable_config_perms").replace( 'local config_dir="/sandbox/.openclaw"', `local config_dir=${JSON.stringify(configDir)}`, );🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@test/nemoclaw-start-perms.test.ts` around lines 442 - 448, The string replacements in test/nemoclaw-start-perms.test.ts can silently no-op if the expected markers drift, so add explicit guards around the normalize_mutable_config_perms and reclaimFunction patching. After each String.prototype.replace call, verify the target substring existed or assert the patched string actually changed before continuing, so the test fails fast instead of using the unmodified shell functions. Use the existing symbols extractShellFunction, normalize_mutable_config_perms, and reclaimFunction to locate the patch points.Source: Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@test/nemoclaw-start-perms.test.ts`:
- Line 404: Update the root-level integration test title in the
nemoclaw-start-perms suite so it follows the required behavior-oriented naming
convention with a local issue-ref suffix. Locate the test case whose title is
“leaves the tree untouched when it cannot reclaim ownership without root” and
append the appropriate final “(`#1234`)”-style reference, matching the pattern
used by the sibling root-only test title.
---
Nitpick comments:
In `@test/nemoclaw-start-perms.test.ts`:
- Around line 442-448: The string replacements in
test/nemoclaw-start-perms.test.ts can silently no-op if the expected markers
drift, so add explicit guards around the normalize_mutable_config_perms and
reclaimFunction patching. After each String.prototype.replace call, verify the
target substring existed or assert the patched string actually changed before
continuing, so the test fails fast instead of using the unmodified shell
functions. Use the existing symbols extractShellFunction,
normalize_mutable_config_perms, and reclaimFunction to locate the patch points.
🪄 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: Enterprise
Run ID: f24d4878-42f1-4552-89b0-33b4f1735c8f
📒 Files selected for processing (2)
scripts/nemoclaw-start.shtest/nemoclaw-start-perms.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- scripts/nemoclaw-start.sh
Signed-off-by: Tinson Lai <tinsonl@nvidia.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@scripts/lib/normalize_mutable_config_perms.py`:
- Around line 238-249: The permission normalization in reclaim_dir currently
applies the generic writable mode to the top-level recovery baseline file
openclaw.json.nemoclaw-baseline, which should remain read-only as a trust
anchor. Update reclaim_dir to special-case that filename in the top-level
regular-file handling, either by excluding it from the blanket | 0o060
adjustment or by restoring a stricter mode immediately after the generic chmod.
Use the existing FIXED_FILES/top_level logic and the file-name check near
open_pinned, os.fchmod, and verify_still_linked to locate the change.
🪄 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: Enterprise
Run ID: 48ad638f-7ab4-412c-b36c-404286101178
📒 Files selected for processing (4)
ci/test-file-size-budget.jsonscripts/lib/normalize_mutable_config_perms.pyscripts/nemoclaw-start.shtest/e2e-gateway-isolation.sh
💤 Files with no reviewable changes (1)
- test/e2e-gateway-isolation.sh
✅ Files skipped from review due to trivial changes (1)
- ci/test-file-size-budget.json
Signed-off-by: Tinson Lai <tinsonl@nvidia.com>
Signed-off-by: Tinson Lai <tinsonl@nvidia.com>
There was a problem hiding this comment.
🧹 Nitpick comments (1)
test/nemoclaw-start-perms.test.ts (1)
555-601: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winStrengthen assertions to prove reclaim actually ran, not just that the baseline was spared.
The test only asserts
result.status === 0and thatbaselineFileis untouched. It never checks thatconfigDir/configFile/hashFilewere actually reclaimed (e.g., chowned to the patched nobody uid/gid and set to2770/660). Per NVIDIA's documented permission states,0700root-owned without the immutable bit is a distinct "drift" layout, separate from both the2770mutable-default and the immutable host-locked state — so it's not obvious which classifier branch this fixture exercises. As written, the assertions would pass identically whether reclaim executed and skipped the baseline file, or the classifier treated the whole tree as ambiguous/sealed andnormalize_mutable_config_permsno-op'd before ever reaching the baseline-exclusion logic.Add positive assertions that the config directory/files were reclaimed (owner/mode changed) alongside the negative assertion that the baseline stayed put, so the test actually demonstrates "reclaim happened, and the baseline was excluded" rather than "nothing observably changed."
💡 Suggested strengthening
try { const result = runBash(script); expect(result.status).toBe(0); + expect(fs.statSync(configFile).uid).toBe(nobodyUid); + expect(mode(configDir)).toBe(0o2770); expect(mode(baselineFile)).toBe(0o440); expect(fs.statSync(baselineFile).uid).toBe(beforeBaselineUid); expect(fs.statSync(baselineFile).gid).toBe(beforeBaselineGid); } finally {As per path instructions: "Flag copied production algorithms, broad mocks that bypass the behavior under test, and conditionals that make a test pass without exercising its claim."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@test/nemoclaw-start-perms.test.ts` around lines 555 - 601, The test in `leaves a root-owned recovery baseline untouched during reclaim` only proves the baseline was spared, not that reclaim actually ran. Strengthen the assertions around `normalize_mutable_config_perms`/`reclaimFunction` by checking `configDir`, `configFile`, and `hashFile` are actually reclaimed after `runBash` (ownership changed to the patched nobody uid/gid and modes updated to the expected mutable defaults), while keeping the existing negative checks for `baselineFile`. This will ensure the fixture exercises the reclaim path and not a no-op or ambiguous classifier branch.Source: Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@test/nemoclaw-start-perms.test.ts`:
- Around line 555-601: The test in `leaves a root-owned recovery baseline
untouched during reclaim` only proves the baseline was spared, not that reclaim
actually ran. Strengthen the assertions around
`normalize_mutable_config_perms`/`reclaimFunction` by checking `configDir`,
`configFile`, and `hashFile` are actually reclaimed after `runBash` (ownership
changed to the patched nobody uid/gid and modes updated to the expected mutable
defaults), while keeping the existing negative checks for `baselineFile`. This
will ensure the fixture exercises the reclaim path and not a no-op or ambiguous
classifier branch.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: 19d72cd8-5e71-4035-b52b-1876eff053d5
📒 Files selected for processing (2)
scripts/lib/normalize_mutable_config_perms.pytest/nemoclaw-start-perms.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- scripts/lib/normalize_mutable_config_perms.py
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
|
Maintainer hardening update for final head Tinson Lai's original PR branch, six commits, and PR authorship are retained. The follow-up commits harden the privileged recovery path without superseding his work. Addressed review feedback:
Advisor concurrency dispositions:
Validation:
Remaining merge gate: final-head required CI/automated review and the live |
|
@coderabbitai review |
✅ Action performedReview finished.
|
|
🌿 Preview your docs: https://nvidia-preview-pr-6307.docs.buildwithfern.com/nemoclaw |
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
E2E Target Results — ✅ All selected jobs passedRun: 28888542873
|
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
test/nemoclaw-start-perms.test.ts (1)
478-492: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winTest title claims "requires both fixed files" but never exercises the missing-file path.
This test only creates both fixed files in the sealed posture and asserts the positive result, so it never proves that dropping one file (or mismatching one posture) fails to seal. On non-root runners the assertion also collapses to
rc=2, identical to the "non-root mutable directory" case, so the sealed-classification logic isn't exercised at all there. Consider a companion negative case (e.g., onlyopenclaw.jsonsealed,.config-hashmissing/writable) that proves the "both required" contract.As per path instructions: "Flag copied production algorithms, broad mocks that bypass the behavior under test, and conditionals that make a test pass without exercising its claim."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@test/nemoclaw-start-perms.test.ts` around lines 478 - 492, The test currently only covers the positive sealed-state path and can pass without proving that both fixed files are required. Update the nemoclaw-start-perms test around runClassify to add a companion negative case that leaves only one of the two files sealed or omits one entirely, and assert it does not classify as sealed. Make sure the assertions in this block distinguish the exact root-owned sealed posture from the mutable/non-root fallback so the test title matches the behavior being exercised.Source: Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@test/nemoclaw-start-perms.test.ts`:
- Line 466: The new seal-classification test titles in this suite are missing
the required local issue-reference suffix. Update the two affected `it`
descriptions in the test block to match the existing sibling titles by appending
the final `(`#1234`)`-style suffix, keeping the behavior-oriented wording intact.
---
Nitpick comments:
In `@test/nemoclaw-start-perms.test.ts`:
- Around line 478-492: The test currently only covers the positive sealed-state
path and can pass without proving that both fixed files are required. Update the
nemoclaw-start-perms test around runClassify to add a companion negative case
that leaves only one of the two files sealed or omits one entirely, and assert
it does not classify as sealed. Make sure the assertions in this block
distinguish the exact root-owned sealed posture from the mutable/non-root
fallback so the test title matches the behavior being exercised.
🪄 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: Enterprise
Run ID: d61e4f84-9a18-4b04-bb5c-58846eb983ae
📒 Files selected for processing (7)
docs/reference/troubleshooting.mdxdocs/security/tcb-boundary.mdxscripts/lib/normalize_mutable_config_perms.pyscripts/nemoclaw-start.shtest/e2e-gateway-isolation.shtest/nemoclaw-start-perms.test.tstest/repro-2681-group-writable.test.ts
✅ Files skipped from review due to trivial changes (2)
- docs/reference/troubleshooting.mdx
- docs/security/tcb-boundary.mdx
|
@coderabbitai review |
✅ Action performedReview finished.
|
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
E2E Target Results — ✅ All selected jobs passedRun: 28889048789
|
E2E Target Results — ✅ All selected jobs passedRun: 28889481264
|
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
E2E Target Results — ✅ All selected jobs passedRun: 28890370745
|
|
Final-head maintainer disposition for Original-author creditThis remains Tinson Lai's PR: Tinson is the PR author and the author of the first six commits. No superseding PR was created. The repository currently permits squash merges only, so the final squash metadata will explicitly retain Resolved review feedback
Advisor dispositionsThe following are explicit maintainer dispositions for the automated advisor's remaining items: GPT-5.5
Nemotron Ultra
The historical v0.0.73-to-v0.0.74 comparison remains issue evidence; the merge gate is the current contract, which the fresh-onboard live run and production-image suite verify. These dispositions explicitly override the automated recommendations that were not implemented; no unresolved correctness or security finding remains. |
apurvvkumaria
left a comment
There was a problem hiding this comment.
Approved at c73ef23. Tinson Lai remains the PR author with his six original commits retained in the PR; all 13 commits are GitHub Verified and DCO is green. Final-head CI passes (40 pass, 2 expected skips), exact-head live shields-config run 28890370745 passes, all CodeRabbit threads are resolved, and c73ef23 addresses the final missing-fixed-file test gap. The remaining automated-advisor items are explicitly dispositioned with maintainer rationale in issuecomment-4907403981. #6300 is fixed and #6047's repair contract is preserved.
<!-- markdownlint-disable MD041 --> ## Summary Prepares the user-facing documentation for NemoClaw v0.0.76 and closes the release-prep documentation gate. It adds the release highlights, documents the arm64 Local NIM warning and expanded image cleanup behavior, and fixes agent-specific command headings in generated guides. ## Changes - Add the v0.0.76 release-notes section and move the shared-gateway route containment entry out of the v0.0.74 history where it was incorrectly placed. - Document the advisory Linux arm64 Local NIM manifest warning in the canonical platform matrix and local-inference guidance. - Document that `gc` scans both gateway-built and locally prebuilt sandbox image repositories. - Keep OpenClaw and Hermes session headings out of the generated Deep Agents command guide. - Add a focused variant regression test for the agent-specific session headings. ### Source summary | Merged sources | Documentation coverage | | --- | --- | | [#6414](#6414), [#6418](#6418), [#6416](#6416), [#6344](#6344) | v0.0.76 release notes and the Deep Agents quickstart/inference routes | | [#6340](#6340) | v0.0.76 release notes and existing Deep Agents observability guidance | | [#6338](#6338), [#6378](#6378), [#6297](#6297) | v0.0.76 release notes and existing inference/troubleshooting guidance | | [#6362](#6362) | v0.0.76 release notes and existing lifecycle, command, and credential guidance | | [#6330](#6330), [#6307](#6307), [#6008](#6008) | v0.0.76 release notes and existing security, troubleshooting, and command guidance | | [#6382](#6382) | v0.0.76 release notes and existing MCP/command guidance | | [#6326](#6326), [#5868](#5868), [#5539](#5539) | v0.0.76 release notes, platform matrix, inference options, and local-inference guidance | | [#6396](#6396), [#6390](#6390), [#6007](#6007) | v0.0.76 release notes and existing messaging guidance | | [#5388](#5388), [#6249](#6249), [#6303](#6303), [#6306](#6306) | v0.0.76 release notes and command/lifecycle guidance | ## Type of Change - [ ] Code change (feature, bug fix, or refactor) - [x] Code change with doc updates - [ ] Doc only (prose changes, no code sample modifications) - [ ] Doc only (includes code sample changes) ## Quality Gates - [x] Tests added or updated for changed behavior - [ ] Existing tests cover changed behavior — justification: - [ ] Tests not applicable — justification: - [x] Docs updated for user-facing behavior changes - [ ] Docs not applicable — justification: - [ ] Sensitive paths changed (security, policy, credentials, preflight, onboarding, inference, runner, sandbox, or messaging) - [ ] Sensitive-path review completed or maintainer-approved waiver recorded — reviewer/approval link/justification: - [ ] Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue: ## Verification - [x] PR description includes the DCO sign-off declaration and every commit appears as `Verified` in GitHub - [x] Normal `pre-commit`, `commit-msg`, and `pre-push` hooks passed, or `npm run check:diff` passed when hooks were skipped or unavailable - [x] Targeted behavior tests pass for the current change set, or tests are marked not applicable above — `npx vitest run --project integration test/generate-platform-docs.test.ts test/agent-variant-docs.test.ts test/sync-agent-variant-docs.test.ts` (3 files, 29 tests passed) - [ ] Applicable broad gate passed — `npm test` for broad runtime/test-harness changes; `npm run check` for repo-wide validation/coverage changes — command/result: - [x] Quality Gates section completed with required justifications or waivers - [x] No secrets, API keys, or credentials committed - [ ] `npm run docs` builds without warnings (doc changes only) — completed with 0 errors and 2 pre-existing Fern warnings - [x] Doc pages follow the [style guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md) (doc changes only) - [ ] New doc pages include SPDX header and frontmatter (new pages only) --- Signed-off-by: Apurv Kumaria <akumaria@nvidia.com> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Added v0.0.76 release notes content, and removed an older conflicting bullet from the surrounding release history. * Expanded Local NVIDIA NIM guidance across inference/provider docs, including an advisory for Linux arm64 DGX Spark/DGX Station hosts when a matching `linux/arm64` image manifest is unavailable. * Updated the command reference for correct session-section rendering and clarified `gc` image cleanup sources. * **Tests** * Added coverage ensuring Deep Agents omits sessions headings while Hermes includes them. * **CI** * Refreshed Local NVIDIA NIM provider notes used in the platform matrix. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
…VIDIA#6307) Restore the mutable OpenClaw config ownership contract at startup while keeping sealed and ambiguous states fail-closed. Retains Tinson Lai's original contribution and PR authorship. Co-authored-by: Tinson Lai <tinsonl@nvidia.com> Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
<!-- markdownlint-disable MD041 --> ## Summary Prepares the user-facing documentation for NemoClaw v0.0.76 and closes the release-prep documentation gate. It adds the release highlights, documents the arm64 Local NIM warning and expanded image cleanup behavior, and fixes agent-specific command headings in generated guides. ## Changes - Add the v0.0.76 release-notes section and move the shared-gateway route containment entry out of the v0.0.74 history where it was incorrectly placed. - Document the advisory Linux arm64 Local NIM manifest warning in the canonical platform matrix and local-inference guidance. - Document that `gc` scans both gateway-built and locally prebuilt sandbox image repositories. - Keep OpenClaw and Hermes session headings out of the generated Deep Agents command guide. - Add a focused variant regression test for the agent-specific session headings. ### Source summary | Merged sources | Documentation coverage | | --- | --- | | [NVIDIA#6414](NVIDIA#6414), [NVIDIA#6418](NVIDIA#6418), [NVIDIA#6416](NVIDIA#6416), [NVIDIA#6344](NVIDIA#6344) | v0.0.76 release notes and the Deep Agents quickstart/inference routes | | [NVIDIA#6340](NVIDIA#6340) | v0.0.76 release notes and existing Deep Agents observability guidance | | [NVIDIA#6338](NVIDIA#6338), [NVIDIA#6378](NVIDIA#6378), [NVIDIA#6297](NVIDIA#6297) | v0.0.76 release notes and existing inference/troubleshooting guidance | | [NVIDIA#6362](NVIDIA#6362) | v0.0.76 release notes and existing lifecycle, command, and credential guidance | | [NVIDIA#6330](NVIDIA#6330), [NVIDIA#6307](NVIDIA#6307), [NVIDIA#6008](NVIDIA#6008) | v0.0.76 release notes and existing security, troubleshooting, and command guidance | | [NVIDIA#6382](NVIDIA#6382) | v0.0.76 release notes and existing MCP/command guidance | | [NVIDIA#6326](NVIDIA#6326), [NVIDIA#5868](NVIDIA#5868), [NVIDIA#5539](NVIDIA#5539) | v0.0.76 release notes, platform matrix, inference options, and local-inference guidance | | [NVIDIA#6396](NVIDIA#6396), [NVIDIA#6390](NVIDIA#6390), [NVIDIA#6007](NVIDIA#6007) | v0.0.76 release notes and existing messaging guidance | | [NVIDIA#5388](NVIDIA#5388), [NVIDIA#6249](NVIDIA#6249), [NVIDIA#6303](NVIDIA#6303), [NVIDIA#6306](NVIDIA#6306) | v0.0.76 release notes and command/lifecycle guidance | ## Type of Change - [ ] Code change (feature, bug fix, or refactor) - [x] Code change with doc updates - [ ] Doc only (prose changes, no code sample modifications) - [ ] Doc only (includes code sample changes) ## Quality Gates - [x] Tests added or updated for changed behavior - [ ] Existing tests cover changed behavior — justification: - [ ] Tests not applicable — justification: - [x] Docs updated for user-facing behavior changes - [ ] Docs not applicable — justification: - [ ] Sensitive paths changed (security, policy, credentials, preflight, onboarding, inference, runner, sandbox, or messaging) - [ ] Sensitive-path review completed or maintainer-approved waiver recorded — reviewer/approval link/justification: - [ ] Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue: ## Verification - [x] PR description includes the DCO sign-off declaration and every commit appears as `Verified` in GitHub - [x] Normal `pre-commit`, `commit-msg`, and `pre-push` hooks passed, or `npm run check:diff` passed when hooks were skipped or unavailable - [x] Targeted behavior tests pass for the current change set, or tests are marked not applicable above — `npx vitest run --project integration test/generate-platform-docs.test.ts test/agent-variant-docs.test.ts test/sync-agent-variant-docs.test.ts` (3 files, 29 tests passed) - [ ] Applicable broad gate passed — `npm test` for broad runtime/test-harness changes; `npm run check` for repo-wide validation/coverage changes — command/result: - [x] Quality Gates section completed with required justifications or waivers - [x] No secrets, API keys, or credentials committed - [ ] `npm run docs` builds without warnings (doc changes only) — completed with 0 errors and 2 pre-existing Fern warnings - [x] Doc pages follow the [style guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md) (doc changes only) - [ ] New doc pages include SPDX header and frontmatter (new pages only) --- Signed-off-by: Apurv Kumaria <akumaria@nvidia.com> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Added v0.0.76 release notes content, and removed an older conflicting bullet from the surrounding release history. * Expanded Local NVIDIA NIM guidance across inference/provider docs, including an advisory for Linux arm64 DGX Spark/DGX Station hosts when a matching `linux/arm64` image manifest is unavailable. * Updated the command reference for correct session-section rendering and clarified `gc` image cleanup sources. * **Tests** * Added coverage ensuring Deep Agents omits sessions headings while Hermes includes them. * **CI** * Refreshed Local NVIDIA NIM provider notes used in the platform matrix. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
Summary
Self-heal the conservative root-owned OpenClaw mutable-config signature before transaction recovery can mistake it for an interrupted shields transition. The repair restores sandbox writes in the default state while sealed, ambiguous, linked, raced, and mounted trees remain fail-closed.
This remains Tinson Lai's original PR and branch. His six commits and PR authorship are retained; the maintainer follow-up hardens and verifies that implementation.
Related Issue
Fixes #6300
Preserves the repair and hardlink-safety contract from #6047 / #6060.
Changes
sandbox:sandbox 0755parent,root:root 0700config directory, and single-linkroot:root 0600openclaw.jsonand.config-hash.Type of Change
Quality Gates
Verification
Verifiedin GitHubpre-commit,commit-msg, andpre-pushhooks passed, ornpx prek run --from-ref main --to-ref HEADpassed when hooks were skipped or unavailablenpm testfor broad runtime/test-harness changes;npm run checkfor repo-wide validation/coverage changes — command/result:npm run docsbuilds without warnings (doc changes only) — 0 errors; Fern reported 2 pre-existing hidden warningsEvidence
npx vitest run --project integration test/nemoclaw-start-perms.test.ts test/repro-2681-group-writable.test.ts: 24 passed, 3 intentional root-only host skips.NEMOCLAW_TEST_IMAGE=nemoclaw-pr6307-test-v2 bash test/e2e-gateway-isolation.sh: 45 passed, 0 failed.npx prek run --from-ref origin/main --to-ref HEAD: passed.npm run docs: 0 errors; 2 pre-existing hidden Fern warnings.Signed-off-by, and report GitHub verification{ "verified": true, "reason": "valid" }.shields-configrun 28890370745 passed.Signed-off-by: Tinson Lai tinsonl@nvidia.com
Signed-off-by: Apurv Kumaria akumaria@nvidia.com
Summary by CodeRabbit
New Features
Bug Fixes
Tests
Documentation