Skip to content

refactor(agent): derive state handling from definitions - #8143

Open
jyaunches wants to merge 17 commits into
mainfrom
codex/issue-8006-agent-definition-state
Open

refactor(agent): derive state handling from definitions#8143
jyaunches wants to merge 17 commits into
mainfrom
codex/issue-8006-agent-definition-state

Conversation

@jyaunches

@jyaunches jyaunches commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Summary

Reimplements #8006 by making each agent manifest the only state declaration. loadAgent() validates that declaration and derives the AgentDefinition projections used by backup, restore, wipe, and Shields.

This is the contract foundation for the dependent stack: #8010 (provider/root mutation boundary), then #8009 (generic staged restore), then a replacement for #7806 that synthesizes the useful guarantees from #7871 and #7880. The two existing #7806 PRs should remain open until replacement coverage is visible.

This stack does not promise a net source-line reduction. Its purpose is to replace divergent state authorities with one validated contract and make privileged state mutation safe across agent implementations. Current estimates are:

Follow-up Estimated production additions Estimated production lines replaced or deleted from current main
#8010 About 520–790 for the registered-sandbox slice; 600–930 if created/rebuild flows are included Pending the owner-approved provider and durable-receipt boundary; it must replace a named existing mutation path before merge
#8009 About 530 About 100–160
#7806 replacement Pending the shared interfaces above About 0–30

The only presently defensible deletion estimate is therefore about 100–190 production lines. #8010 intersects the provider work in #7744 and durable receipt work in #7702; its scope and deletion estimate remain provisional until those owners approve or narrow the boundary. #7871 and #7880 together add 2,271 lines and delete 34 across production, tests, and documentation, but they are unmerged alternatives and are not counted as future deletions from main.

The current GitHub diff is +3,942/-727 across production, tests, documentation, and tooling.

The production increase establishes and verifies the shared contract before later PRs consume it. The largest additions are the 308-line TypeScript validation and derivation boundary and the descriptor-safe Python state guard extension. The rest replaces separate behavior in backup, restore, wipe, Shields, startup recovery, and image-version handling.

This PR does not add a policy database or handwritten registry. Each agent manifest contains the declaration, and AgentDefinition is the validated runtime authority. The generator calls listAgents() and loadAgent() instead of maintaining an agent list or parsing YAML separately. The generated OpenClaw and Hermes image plans total 51 lines. No code from closed #8084 was transferred.

Related Issue

Fixes #8006

Parent epic: #8004

Stacked follow-ups: #8010, then #8009, then #7806

Changes

  • Extends state_dirs with the independent facts used by current consumers: backup inclusion, Shields mode, declared prefixes, and writable subpaths.
  • Makes AgentDefinition validate those declarations and derive backup, restore, wipe, and Shields projections.
  • Generates each image state-lock plan through listAgents() and loadAgent(). state_lock_plan_in_image declares whether an agent image carries that projection.
  • Removes HIGH_RISK_STATE_DIRS, CONFIDENTIALITY_STATE_DIRS, runtime_auth_state_dirs, the fixed agents/*/sessions carve-out, literal workspace-* handling, and startup relock lists.
  • Rejects drift between the current AgentDefinition and an installed current-image plan before a privileged mutation. Older images retain the bounded rebuild compatibility path.
  • Makes backup discovery and restore authorization fail closed against the target agent definition, including prefix matches and non-backup authentication state.
  • Routes locked OpenClaw migration through the existing configuration and state-directory guards so a failed relock remains retryable.
  • Updates security documentation and adds contract, permission, backup, restore, wipe, image-layout, version-skew, and live E2E coverage.

The existing backup, restore, wipe, and Shields paths are the consumers required by #8006. A direct change to one consumer would leave the others as separate authorities. The state-directory contract tests, snapshot contract tests, focused consumer tests, and live E2E targets protect the shared definition.

Type of Change

  • Code change (feature, bug fix, or refactor)
  • Code change with doc updates
  • Doc only (prose changes, no code sample modifications)
  • Doc only (includes code sample changes)

Quality Gates

  • Tests added or updated for changed behavior
  • Existing tests cover changed behavior — justification:
  • Tests not applicable — justification:
  • 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: local nemoclaw-maintainer-security-code-review completed against refreshed base 3f7097b4eee982bc6b86f61d9aea24643b12bbff and exact head d7bb3cd259cca72545d63c52cc758499cb5d7532 (tree 1fd369f090b0fe3aeabfa7b33414e9e6ed6c83a7). All nine categories PASS with no security findings or blocker; the PR Gate remains responsible for exact-head live E2E.
  • Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue: none accepted; required GitHub checks and live E2E remain required before merge.

Documentation Writer Review

  • Documentation writer subagent reviewed the completed changes
  • Result: docs-updated
  • Evidence: reviewed docs/index.yml, docs/manage-sandboxes/backup-restore.mdx, docs/security/best-practices.mdx, and docs/security/tcb-boundary.mdx; verified OpenClaw, Hermes, and Deep Agents variants against the implementation; exact-head validation passed 1,909 E2E-support tests and 59 state-guard integration tests; npm run validate:pr passed; npm run docs passed with 0 errors and the same 2 unrelated Fern warnings; git diff --check passed.
  • Agent: Codex Desktop

Verification

  • PR description includes a Signed-off-by: line and every commit appears as Verified in GitHub — all 17 PR commits report valid verification.
  • Normal pre-commit, commit-msg, and pre-push hooks passed.
  • Targeted behavior tests pass for the current change set, or tests are marked not applicable above:
    • npm run typecheck:cli passed.
    • npm --prefix nemoclaw run build passed.
    • npm run build:cli passed.
    • npm run source-shape:check passed.
    • Eleven focused CLI files passed: 202 tests passed.
    • Four focused integration files passed: 105 tests passed.
    • npm run validate:pr passed on exact head d7bb3cd25.
    • npm run docs passed with 0 errors and 2 unchanged Fern warnings.
  • Applicable broad gate passed — not claimed; exact-head required CI and live E2E remain required.
  • Quality Gates section completed with required justifications or waivers
  • No secrets, API keys, or credentials committed
  • npm run docs builds without warnings (doc changes only) — completed with zero errors and two Fern warnings.
  • Doc pages follow the style guide (doc changes only)
  • New doc pages include SPDX header and frontmatter (new pages only) — not applicable; no new documentation page was added.

Signed-off-by: Julie Yaunches jyaunches@nvidia.com

Summary by CodeRabbit

  • New Features
    • Added manifest-driven state protection with read-only and confidential policies.
    • Added validated state-lock plans for protected workspace and session handling.
    • Added support for shielded configuration files such as .env.
  • Bug Fixes
    • Improved backup, restore, recovery, and migration validation.
  • Documentation
    • Added Trusted Computing Base guidance and updated security and backup/restore documentation.
  • Tests
    • Expanded coverage for state protection, recovery, snapshots, permissions, and policy validation.

Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
@jyaunches jyaunches self-assigned this Aug 3, 2026
@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

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: Enterprise

Run ID: 0adc1bb4-e836-4b92-ad5c-d00ad08abf0e

📥 Commits

Reviewing files that changed from the base of the PR and between 478243b and d7bb3cd.

📒 Files selected for processing (1)
  • test/e2e/live/gateway-guard-recovery.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/e2e/live/gateway-guard-recovery.test.ts

📝 Walkthrough

Walkthrough

This PR replaces static state-directory inventories with manifest-derived lock plans. AgentDefinition now supplies Shields, guard, backup, restore, wipe, and image-validation consumers. Packaged plans are validated and propagated through runtime recovery paths.

Changes

Manifest-driven state contract and consumers

Layer / File(s) Summary
State contract and plan generation
src/lib/agent/*, agents/*/manifest.yaml, agents/*/state-lock-plan.json, scripts/lib/generate-agent-state-lock-plans.mts
Manifests define structured state directories, shield files, and image-plan support. AgentDefinition validates and derives state projections and versioned lock plans.
Plan-aware locking and recovery
src/lib/shields/*, scripts/state-dir-guard.py, agents/hermes/runtime-config-guard.py, scripts/nemoclaw-start.sh
Lock, unlock, rollback, status, and recovery paths validate and propagate state-lock plans. The guard supports plan files, host-injected plans, prefixes, and writable subpaths.
Backup, restore, wipe, and image validation
src/lib/state/sandbox.ts, src/lib/actions/sandbox/wipe-state.ts, Dockerfile, agents/hermes/Dockerfile, test/e2e/live/*, test/snapshot*.test.ts
Backup and restore authorize declared directories and prefixes. Wipe uses manifest prefixes. Runtime images package plans with root:root:444 metadata.
Agent configuration and validation
src/lib/sandbox/agent-config.ts, src/lib/sandbox/agent-config.test.ts
Configuration paths and shield files are validated, and resolved targets expose the agent state-lock plan.
Documentation, packaging, and supporting tests
docs/*, package.json, ci/*, test/*
Documentation, package contents, CI budgets, fixtures, and contract tests are updated for the manifest-driven state model.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

Suggested labels: area: sandbox, area: security, area: onboarding, platform: container

Suggested reviewers: cv

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.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 clearly summarizes the main change: deriving agent state handling from agent definitions.
Linked Issues check ✅ Passed The changes migrate backup, restore, wipe, and Shields to manifest-derived AgentDefinition projections and add Hermes and non-Hermes coverage.
Out of Scope Changes check ✅ Passed The supporting code, documentation, packaging, migration, and test changes directly support the linked state-ownership and consumer-migration objectives.
✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/issue-8006-agent-definition-state

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

@github-code-quality

github-code-quality Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

The overall coverage in commit d7bb3cd in the codex/issue-8006-age... branch remains at 96%, unchanged from commit 3f7097b in the main branch.

TypeScript / code-coverage/cli

The overall coverage in commit d7bb3cd in the codex/issue-8006-age... branch remains at 81%, unchanged from commit 3f7097b in the main branch.

Show a code coverage summary of the most impacted files.
File main 3f7097b codex/issue-8006-age... d7bb3cd +/-
src/lib/sandbox...uild-context.ts 42% 40% -2%
src/lib/agent/s...store-reader.ts 90% 88% -2%
src/lib/shields...nsition-lock.ts 86% 85% -1%
src/lib/credentials/store.ts 56% 55% -1%
src/lib/shields/index.ts 71% 71% 0%
src/lib/state/sandbox.ts 85% 87% +2%
src/lib/private-networks.ts 90% 93% +3%
src/lib/shields...ate-dir-lock.ts 76% 80% +4%
src/lib/policy/...ne-exclusion.ts 92% 96% +4%
src/lib/agent/s...ory-contract.ts 0% 95% +95%

Updated August 04, 2026 18:56 UTC

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Comment thread scripts/state-dir-guard.py Fixed
@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor — Informational

Advisor assessment: Informational / low confidence
Next action: No advisor follow-up needed.
Findings: 0 blockers · 0 warnings · 0 suggestions
Status: PR review advisor failed: PR review advisor SDK execution failed: session: 400: {"message":"litellm.BadRequestError: AzureException BadRequestError - {\n \"error\": {\n \"message\": \"Invalid 'max_output_tokens': integer below minimum value. Expected a value >= 16, but got 1 instead.\",\n \"type\": \"invalid_request_error\",\n \"param\": \"max_output_tokens\",\n \"code\": \"integer_below_min_value\"\n }\n}. Received Model Group=azure/openai/gpt-5.6-terra\nAvailable Model Group Fallbacks=None","type":null,"param":null,"code":"400"}; turn: scope-risk-map-analysis: 400: {"message":"litellm.BadRequestError: AzureException BadRequestError - {\n \"error\": {\n \"message\": \"Invalid 'max_output_tokens': integer below minimum value. Expected a value >= 16, but got 1 instead.\",\n \"type\": \"invalid_request_error\",\n \"param\": \"max_output_tokens\",\n \"code\": \"integer_below_min_value\"\n }\n}. Received Model Group=azure/openai/gpt-5.6-terra\nAvailable Model Group Fallbacks=None","type":null,"param":null,"code":"400"}

Model lanes

  • GPT-5.6 Terra (primary): Failed
  • Nemotron 3 Ultra (second opinion): Failed

Second-opinion terminology and E2E selections are advisory. They do not change the primary assessment or E2E / PR Gate.

E2E guidance

Advisory only. E2E / PR Gate selects and runs jobs independently.

Recommended E2E: cloud-inference, cloud-onboard, full-e2e, hermes-e2e, hermes-inference-switch, security-posture, channels-add-remove, channels-stop-start, gateway-guard-recovery, hermes-shields-config, inference-routing, network-policy, onboard-repair, onboard-resume, rebuild-hermes, rebuild-hermes-stale-base, sandbox-survival, snapshot-commands, state-backup-restore, ubuntu-repo-cloud-langchain-deepagents-code

Workflow run details

This automated review informs maintainers. Warnings and suggestions do not require a response. A maintainer decides whether to merge.

@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: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/lib/shields/index.ts (1)

3318-3341: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Stale planIssues can select the wrong recovery guidance.

planIssues is assigned before verify(...) runs. If verify(...) throws, the catch block replaces driftIssues with the resolve message but leaves planIssues populated. The recovery block at Lines 3365-3368 then tells the operator to rebuild so the plan matches the manifest, although the reported drift is a resolve failure. Clear planIssues in the catch block.

🐛 Proposed fix
       } catch (err) {
         const msg = err instanceof Error ? err.message : String(err);
+        planIssues = [];
         driftIssues = [`unable to resolve agent config target: ${msg}`];
       }
🤖 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 `@src/lib/shields/index.ts` around lines 3318 - 3341, Clear planIssues in the
catch block handling failures around verify(...) so recovery guidance cannot use
stale state-lock plan issues when target resolution or verification throws. Keep
driftIssues set to the existing resolve-error message and ensure the recovery
logic sees an empty planIssues array for this failure path.
🧹 Nitpick comments (8)
test/repro-2681-group-writable.test.ts (1)

719-728: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

The subprocess copy of stateDirGuardAction can diverge from the host copy.

This inline copy duplicates the helper defined at Lines 62-69 and uses || where the host version uses ??. The two definitions must stay in step for the assertions at Lines 802-804 and 856 to mean the same thing. Serialize the single helper into the subprocess source instead of writing it twice.

♻️ Serialize one definition
-function stateDirGuardAction(command) {
-  const installedIndex = command.indexOf(STATE_DIR_GUARD);
-  if (installedIndex >= 0) return command[installedIndex + 1] || null;
-  const pythonIndex = command.indexOf("python3");
-  return pythonIndex >= 0 && command[pythonIndex + 2] === "-"
-    ? (command[pythonIndex + 3] || null)
-    : null;
-}
+const stateDirGuardAction = ${stateDirGuardAction.toString()};
🤖 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/repro-2681-group-writable.test.ts` around lines 719 - 728, Replace the
duplicated inline stateDirGuardAction definition in the subprocess source with a
serialized copy of the host helper defined by stateDirGuardAction, so both
subprocess and host assertions use identical nullish-value behavior. Keep the
existing subprocess constants and invocation flow unchanged.
src/lib/shields/policy-transition.test.ts (1)

40-47: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use version: 1 as const for consistency and type safety.

The sibling fixture at Lines 114-121 pins the literal type. Here version: 1 widens to number unless the enclosing object has a declared type. If any consumer expects AgentStateLockPlan, the widened type fails tsc. Pin the literal in both fixtures.

🤖 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 `@src/lib/shields/policy-transition.test.ts` around lines 40 - 47, Update the
stateLockPlan fixtures in the relevant test cases to declare version as the
literal type 1 using the existing `as const` pattern, including both sibling
fixtures. Keep all other fixture fields unchanged.
src/lib/shields/state-dir-lock.ts (3)

101-105: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Plan comparison is order-sensitive.

plansMatch compares serialized arrays. A manifest edit that only reorders entries in readOnlyRoots, readOnlyPrefixes, or writableSubpaths produces "installed state lock plan differs from the current agent manifest" and blocks every Shields transition until the operator rebuilds, although the policy is unchanged. Compare sets or sorted copies so only semantic differences fail closed.

♻️ Order-insensitive comparison
 function plansMatch(actual: AgentStateLockPlan, expected: AgentStateLockPlan): boolean {
   return PLAN_ARRAY_FIELDS.every(
-    (field) => JSON.stringify(actual[field]) === JSON.stringify(expected[field]),
+    (field) =>
+      JSON.stringify([...actual[field]].sort()) === JSON.stringify([...expected[field]].sort()),
   );
 }
🤖 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 `@src/lib/shields/state-dir-lock.ts` around lines 101 - 105, Update plansMatch
to compare readOnlyRoots, readOnlyPrefixes, and writableSubpaths without regard
to entry order, using set or sorted-copy semantics while preserving duplicate
handling as appropriate. Keep comparisons order-sensitive only where array order
is semantically meaningful, and continue returning false for actual policy
differences.

113-115: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

hasImageRecoveryPlan reintroduces a hard-coded agent path list.

This function decides plan-aware behavior from two literal config directories. The PR goal is to derive per-agent state authority from the manifest. An agent that later ships a generated plan, or an agent whose config directory changes, silently keeps the host-injection path and skips installed-plan validation.

Consider passing an explicit flag derived from the agent definition, for example whether the resolved target declares a packaged plan, instead of comparing configDir strings.

♻️ Sketch of a manifest-derived signal
-function hasImageRecoveryPlan(configDir: string): boolean {
-  return configDir === "/sandbox/.openclaw" || configDir === "/sandbox/.hermes";
-}
+// Callers pass the agent definition's packaged-plan declaration so no
+// per-agent path inventory lives in the Shields layer.
+function hasImageRecoveryPlan(packagesStateLockPlan: boolean): boolean {
+  return packagesStateLockPlan;
+}
🤖 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 `@src/lib/shields/state-dir-lock.ts` around lines 113 - 115, Replace the
hard-coded directory comparisons in hasImageRecoveryPlan with an explicit
manifest-derived signal from the resolved agent definition, such as whether the
target declares a packaged plan. Pass that flag through the callers and use it
to select plan-aware behavior, so newly generated plans and
configuration-directory changes follow the manifest without updating this
function.

252-279: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

State the exit criteria for the historical-image path.

The historical branch keeps a second lock implementation alive: the older container helper runs with its own built-in path inventory instead of the manifest plan. The comment explains the intent but does not bound the window. Add the retirement issue link and the observable exit criterion, for example the minimum image build that always ships state-lock-plan.json, so the superseded path can be deleted.

As per path instructions: "Retain an old path only for a demonstrated external/persisted-data contract or a bounded confidence/rollback window ... link the retirement issue or PR in GitHub, and state observable exit criteria."

Also applies to: 289-292

🤖 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 `@src/lib/shields/state-dir-lock.ts` around lines 252 - 279, The
historical-image fallback in the runtime guard needs an explicit, bounded
retirement plan. Update the surrounding comment for the historical branch in the
state-dir guard to link the retirement issue or PR and state the observable exit
criterion, such as the minimum image build that always includes
state-lock-plan.json, so the legacy container-helper path can be removed.

Source: Path instructions

src/lib/shields/state-dir-lock.test.ts (1)

205-222: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert the specific rejection reason per case.

The regex /installed state lock plan|differs from the current agent manifest/ matches every message that parseInstalledPlan and plansMatch produce. The three cases therefore cannot distinguish a JSON parse failure from an unknown field or a policy difference, so a regression that reports the wrong reason still passes. Assert a distinct expected message for each case.

As per path instructions: "Flag ... conditionals that make a test pass without exercising its claim."

♻️ Per-case expectations
   it.each([
-    ["malformed JSON", "{"],
-    ["an unknown field", JSON.stringify({ ...PLAN, registry: [] })],
-    ["a different policy", JSON.stringify({ ...PLAN, readOnlyRoots: ["hooks"] })],
-  ])("rejects an installed plan with %s before mutation", (_case, payload) => {
+    ["malformed JSON", "{", /is not valid JSON/],
+    ["an unknown field", JSON.stringify({ ...PLAN, registry: [] }), /unknown fields: registry/],
+    [
+      "a different policy",
+      JSON.stringify({ ...PLAN, readOnlyRoots: ["hooks"] }),
+      /differs from the current agent manifest/,
+    ],
+  ])("rejects an installed plan with %s before mutation", (_case, payload, expected) => {
@@
-    expect(stateLockPlanCompatibilityIssues(privileged, "/sandbox/.openclaw", PLAN)).toEqual([
-      expect.stringMatching(/installed state lock plan|differs from the current agent manifest/),
-    ]);
+    expect(stateLockPlanCompatibilityIssues(privileged, "/sandbox/.openclaw", PLAN)).toEqual([
+      expect.stringMatching(expected),
+    ]);
   });
🤖 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 `@src/lib/shields/state-dir-lock.test.ts` around lines 205 - 222, Update the
parameterized test around stateLockPlanCompatibilityIssues to include the
expected rejection message for each payload case: malformed JSON must assert the
parse-failure reason, the unknown field must assert the unknown-field reason,
and the different policy must assert the manifest-difference reason. Replace the
shared broad regex with the per-case expectation while preserving the existing
pre-mutation setup.

Source: Path instructions

scripts/state-dir-guard.py (2)

303-307: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Set strict=False explicitly in _patterns_overlap and record the prefix semantics.

_patterns_overlap compares only the shared-length prefix on purpose. It mirrors writablePatternsOverlap in src/lib/agent/state-directory-contract.ts (Lines 202-212), so a/b and a/b/c count as overlapping. Ruff reports B905 here. A later contributor who silences B905 with strict=True would convert plan validation into an unhandled ValueError for patterns of different length.

♻️ Proposed change
 def _patterns_overlap(first: tuple[str, ...], second: tuple[str, ...]) -> bool:
+    # Compare only the shared prefix: a shorter pattern that matches the head of
+    # a longer one still overlaps it. Never use strict=True here.
     return all(
         left == "*" or right == "*" or left == right
-        for left, right in zip(first, second)
+        for left, right in zip(first, second, strict=False)
     )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/state-dir-guard.py` around lines 303 - 307, Update _patterns_overlap
to call zip with strict=False explicitly, preserving its intentional
shared-prefix comparison for patterns of different lengths. Add a concise
comment documenting that prefix semantics and the alignment with
writablePatternsOverlap, without changing the overlap behavior.

Source: Linters/SAST tools


2248-2277: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Bind plan on every path in main, and drop the unreachable-result safeguard.

plan is assigned only when _load_plan succeeds. Line 2274 is reachable only when result is None, so the current code is correct at runtime. The binding is not visible to the reader or to analysis: the CodeQL check fails with "Local variable 'plan' may be used before it is initialized".

Return early on each failure. That makes the plan binding explicit and removes the RuntimeError safeguard, which no branch can reach.

♻️ Proposed restructure
+def _report(result: GuardResult) -> int:
+    for issue in result.issues:
+        print(json.dumps(issue.as_json(), sort_keys=True, separators=(",", ":")))
+    print(json.dumps(result.summary_json(), sort_keys=True, separators=(",", ":")))
+    return 0 if result.ok else 1
+
+
 def main(argv: list[str] | None = None) -> int:
     args = _parse_args(sys.argv[1:] if argv is None else argv)
-    result: GuardResult | None = None
     try:
         plan = _load_plan(args)
     except PlanValidationError as exc:
         result = GuardResult(action=args.action)
         result.issues.append(Issue("invalid-plan", args.config_dir, str(exc)))
-    if result is None and os.geteuid() != 0:
+        return _report(result)
+    if os.geteuid() != 0:
         result = GuardResult(action=args.action)
         result.issues.append(
             Issue("root-required", args.config_dir, "state-dir guard must run as root")
         )
-    elif result is None:
-        try:
-            identity = _production_identity()
-        except KeyError as exc:
-            result = GuardResult(action=args.action)
-            result.issues.append(
-                Issue(
-                    "identity-unavailable",
-                    args.config_dir,
-                    f"required sandbox account is unavailable: {exc}",
-                )
-            )
-        else:
-            result = run_guard(args.action, args.config_dir, identity, plan)
-
-    if result is None:  # All branches above assign a result.
-        raise RuntimeError("state-dir guard did not produce a result")
-    for issue in result.issues:
-        print(json.dumps(issue.as_json(), sort_keys=True, separators=(",", ":")))
-    print(json.dumps(result.summary_json(), sort_keys=True, separators=(",", ":")))
-    return 0 if result.ok else 1
+        return _report(result)
+    try:
+        identity = _production_identity()
+    except KeyError as exc:
+        result = GuardResult(action=args.action)
+        result.issues.append(
+            Issue(
+                "identity-unavailable",
+                args.config_dir,
+                f"required sandbox account is unavailable: {exc}",
+            )
+        )
+        return _report(result)
+    return _report(run_guard(args.action, args.config_dir, identity, plan))
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/state-dir-guard.py` around lines 2248 - 2277, Restructure main so
_load_plan and the prerequisite checks return their failure GuardResult
immediately, leaving plan definitely bound before the production-identity and
run_guard path. Remove the final result-is-None RuntimeError safeguard, while
preserving the existing issue types, messages, and successful run_guard
behavior.

Source: Linters/SAST tools

🤖 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 `@docs/security/best-practices.mdx`:
- Around line 369-371: Update the Deep Agents lock-plan description so the first
declaration is named `agent`, not `agent/skills`, while retaining the separate
`skills` declaration and the existing behavior descriptions.

In `@docs/security/tcb-boundary.mdx`:
- Around line 139-142: Update the host wiring test coverage sentence in the
final-image validation section to say that host wiring tests “validate the
selection and plan handoff,” preserving the surrounding shared helper test
coverage wording.

In `@src/lib/agent/state-directory-contract.ts`:
- Around line 59-81: Update readWritableSubpaths to inspect the final path
component and reject any entry whose final component is "*", including the
single-component entry "*". Preserve the existing validation and duplicate
detection, while continuing to reject wildcard suffixes such as "runtime/*".

In `@test/snapshot-state-directory-contract.test.ts`:
- Around line 19-26: Remove both added if statements from
snapshot-state-directory-contract.test.ts: move the loadedSandboxState
type-narrowing guard into a shared test helper and reuse it from this test, then
restructure the it.each cases around the accepted value so each test path
performs a linear assertion without an if (!accepted) branch, using an expected
error value or separate accepted/rejected tables.

---

Outside diff comments:
In `@src/lib/shields/index.ts`:
- Around line 3318-3341: Clear planIssues in the catch block handling failures
around verify(...) so recovery guidance cannot use stale state-lock plan issues
when target resolution or verification throws. Keep driftIssues set to the
existing resolve-error message and ensure the recovery logic sees an empty
planIssues array for this failure path.

---

Nitpick comments:
In `@scripts/state-dir-guard.py`:
- Around line 303-307: Update _patterns_overlap to call zip with strict=False
explicitly, preserving its intentional shared-prefix comparison for patterns of
different lengths. Add a concise comment documenting that prefix semantics and
the alignment with writablePatternsOverlap, without changing the overlap
behavior.
- Around line 2248-2277: Restructure main so _load_plan and the prerequisite
checks return their failure GuardResult immediately, leaving plan definitely
bound before the production-identity and run_guard path. Remove the final
result-is-None RuntimeError safeguard, while preserving the existing issue
types, messages, and successful run_guard behavior.

In `@src/lib/shields/policy-transition.test.ts`:
- Around line 40-47: Update the stateLockPlan fixtures in the relevant test
cases to declare version as the literal type 1 using the existing `as const`
pattern, including both sibling fixtures. Keep all other fixture fields
unchanged.

In `@src/lib/shields/state-dir-lock.test.ts`:
- Around line 205-222: Update the parameterized test around
stateLockPlanCompatibilityIssues to include the expected rejection message for
each payload case: malformed JSON must assert the parse-failure reason, the
unknown field must assert the unknown-field reason, and the different policy
must assert the manifest-difference reason. Replace the shared broad regex with
the per-case expectation while preserving the existing pre-mutation setup.

In `@src/lib/shields/state-dir-lock.ts`:
- Around line 101-105: Update plansMatch to compare readOnlyRoots,
readOnlyPrefixes, and writableSubpaths without regard to entry order, using set
or sorted-copy semantics while preserving duplicate handling as appropriate.
Keep comparisons order-sensitive only where array order is semantically
meaningful, and continue returning false for actual policy differences.
- Around line 113-115: Replace the hard-coded directory comparisons in
hasImageRecoveryPlan with an explicit manifest-derived signal from the resolved
agent definition, such as whether the target declares a packaged plan. Pass that
flag through the callers and use it to select plan-aware behavior, so newly
generated plans and configuration-directory changes follow the manifest without
updating this function.
- Around line 252-279: The historical-image fallback in the runtime guard needs
an explicit, bounded retirement plan. Update the surrounding comment for the
historical branch in the state-dir guard to link the retirement issue or PR and
state the observable exit criterion, such as the minimum image build that always
includes state-lock-plan.json, so the legacy container-helper path can be
removed.

In `@test/repro-2681-group-writable.test.ts`:
- Around line 719-728: Replace the duplicated inline stateDirGuardAction
definition in the subprocess source with a serialized copy of the host helper
defined by stateDirGuardAction, so both subprocess and host assertions use
identical nullish-value behavior. Keep the existing subprocess constants and
invocation flow unchanged.
🪄 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: 67d4fbd1-0b76-4d94-a53e-f4d1e13a2981

📥 Commits

Reviewing files that changed from the base of the PR and between 8c542b2 and 90da1e0.

📒 Files selected for processing (65)
  • Dockerfile
  • agents/hermes/Dockerfile
  • agents/hermes/manifest.yaml
  • agents/hermes/runtime-config-guard.py
  • agents/hermes/state-lock-plan.json
  • agents/langchain-deepagents-code/manifest.yaml
  • agents/openclaw/manifest.yaml
  • agents/openclaw/state-lock-plan.json
  • ci/source-shape-test-budget.json
  • ci/test-file-size-budget.json
  • docs/index.yml
  • docs/manage-sandboxes/backup-restore.mdx
  • docs/security/best-practices.mdx
  • docs/security/tcb-boundary.mdx
  • package.json
  • scripts/lib/generate-agent-state-lock-plans.mts
  • scripts/nemoclaw-start.sh
  • scripts/state-dir-guard.py
  • src/lib/actions/sandbox/channel-status.test-helpers.ts
  • src/lib/actions/sandbox/wipe-state.ts
  • src/lib/agent/definition-types.ts
  • src/lib/agent/defs.test.ts
  • src/lib/agent/defs.ts
  • src/lib/agent/hermes-recovery-boundary-fixtures.ts
  • src/lib/agent/manifest-readers.ts
  • src/lib/agent/onboard.test.ts
  • src/lib/agent/runtime-auth-state-dirs.test.ts
  • src/lib/agent/runtime.test.ts
  • src/lib/agent/state-directory-contract.test.ts
  • src/lib/agent/state-directory-contract.ts
  • src/lib/onboard/verify-channel-runtime.test.ts
  • src/lib/sandbox/agent-config.test.ts
  • src/lib/sandbox/agent-config.ts
  • src/lib/sandbox/build-context.ts
  • src/lib/sandbox/config-get.test.ts
  • src/lib/shields/flow.test.ts
  • src/lib/shields/index.test.ts
  • src/lib/shields/index.ts
  • src/lib/shields/legacy-hermes-compat.test.ts
  • src/lib/shields/openclaw-transition.test.ts
  • src/lib/shields/policy-transition.test.ts
  • src/lib/shields/state-dir-lock.test.ts
  • src/lib/shields/state-dir-lock.ts
  • src/lib/state/sandbox.ts
  • src/lib/state/user-managed-files-probe.test.ts
  • test/destroy-wipe-sandbox-state.test.ts
  • test/e2e/live/state-dir-guard-metadata.test.ts
  • test/helpers/base-image-test-harness.ts
  • test/helpers/shell-source.ts
  • test/hermes-config-transaction-wiring.test.ts
  • test/hermes-final-image-layout.test.ts
  • test/hermes-runtime-config-guard.test.ts
  • test/nemoclaw-start-locked-migration.test.ts
  • test/nemoclaw-start.test.ts
  • test/openclaw-config-transaction-wiring.test.ts
  • test/openclaw-final-image-layout.test.ts
  • test/package-contract/openshell-policy-boundary.test.ts
  • test/rebuild-shields-auto-unlock.test.ts
  • test/repro-2681-group-writable.test.ts
  • test/sandbox-build-context.test.ts
  • test/shields-up-runtime-perms.test.ts
  • test/snapshot-runtime-auth-state.test.ts
  • test/snapshot-state-directory-contract.test.ts
  • test/snapshot.test.ts
  • test/state-dir-guard.test.ts
💤 Files with no reviewable changes (1)
  • src/lib/agent/runtime-auth-state-dirs.test.ts

Comment thread docs/security/best-practices.mdx
Comment thread docs/security/tcb-boundary.mdx Outdated
Comment thread src/lib/agent/state-directory-contract.ts
Comment thread test/snapshot-state-directory-contract.test.ts Outdated
@copy-pr-bot

copy-pr-bot Bot commented Aug 3, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

Signed-off-by: Julie Yaunches <jyaunches@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)
test/hermes-doctor-config-hash.test.ts (1)

16-43: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Use a real YAML parser in the config-hash test.

The hash command calls _canonical_mcp_servers_digest, which calls yaml.safe_load. The stub returns {} for every input, so the test bypasses YAML parsing and validation. The fixture also lacks mcp_servers. Use the Hermes venv's PyYAML or a fixture-specific parser that asserts the expected mapping.

🤖 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/hermes-doctor-config-hash.test.ts` around lines 16 - 43, The
writeYamlStubPython test helper currently makes yaml.safe_load return an empty
object, bypassing parsing and validation, and its fixture lacks mcp_servers.
Update writeYamlStubPython to use the Hermes virtual environment’s real PyYAML,
or a fixture-specific parser that validates and returns the expected mapping,
and ensure the test configuration includes mcp_servers.

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/hermes-doctor-config-hash.test.ts`:
- Around line 16-43: The writeYamlStubPython test helper currently makes
yaml.safe_load return an empty object, bypassing parsing and validation, and its
fixture lacks mcp_servers. Update writeYamlStubPython to use the Hermes virtual
environment’s real PyYAML, or a fixture-specific parser that validates and
returns the expected mapping, and ensure the test configuration includes
mcp_servers.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 25d566b5-4a65-4686-b1c8-51d34adea2e5

📥 Commits

Reviewing files that changed from the base of the PR and between 3d7a4a2 and 622dc27.

📒 Files selected for processing (50)
  • agents/hermes/manifest.yaml
  • agents/langchain-deepagents-code/manifest.yaml
  • agents/openclaw/manifest.yaml
  • docs/security/tcb-boundary.mdx
  • scripts/lib/generate-agent-state-lock-plans.mts
  • scripts/state-dir-guard.py
  • src/lib/actions/inference-set.test-support.ts
  • src/lib/actions/onboard.ts
  • src/lib/actions/sandbox/gateway-restart-hermes-drift.test.ts
  • src/lib/agent/definition-types.ts
  • src/lib/agent/defs.test.ts
  • src/lib/agent/defs.ts
  • src/lib/agent/hermes-recovery-boundary-fixtures.ts
  • src/lib/agent/manifest-readers.ts
  • src/lib/agent/onboard.test.ts
  • src/lib/agent/runtime.test.ts
  • src/lib/agent/state-directory-contract.test.ts
  • src/lib/agent/state-directory-contract.ts
  • src/lib/onboard/command-support.ts
  • src/lib/onboard/dockerfile-remote-dashboard-bind-contract.ts
  • src/lib/sandbox/agent-config.test.ts
  • src/lib/sandbox/agent-config.ts
  • src/lib/sandbox/hermes-dashboard-reseed.test.ts
  • src/lib/shields/flow.test.ts
  • src/lib/shields/index.test.ts
  • src/lib/shields/index.ts
  • src/lib/shields/legacy-hermes-compat.test.ts
  • src/lib/shields/openclaw-transition.test.ts
  • src/lib/shields/policy-transition.test.ts
  • src/lib/shields/state-dir-lock.test.ts
  • src/lib/shields/state-dir-lock.ts
  • src/lib/shields/timer.ts
  • src/lib/state/sandbox.ts
  • src/lib/tunnel/allowed-origins.test.ts
  • test/e2e/live/gateway-guard-recovery.test.ts
  • test/e2e/live/hermes-shields-config.test.ts
  • test/e2e/live/rebuild-hermes.test.ts
  • test/e2e/live/sandbox-survival.test.ts
  • test/e2e/live/snapshot-commands.test.ts
  • test/e2e/live/state-backup-restore.test.ts
  • test/helpers/base-image-test-harness.ts
  • test/hermes-doctor-config-hash.test.ts
  • test/repro-2681-group-writable.test.ts
  • test/sandbox-provisioning-helper-permissions.test.ts
  • test/sandbox-provisioning.test.ts
  • test/sandbox-rlimit-hooks.test.ts
  • test/shields-up-runtime-perms.test.ts
  • test/snapshot-state-directory-contract.test.ts
  • test/state-dir-guard.test.ts
  • test/support/connect-flow-test-harness.ts
🚧 Files skipped from review as they are similar to previous changes (25)
  • src/lib/agent/onboard.test.ts
  • src/lib/shields/openclaw-transition.test.ts
  • agents/langchain-deepagents-code/manifest.yaml
  • src/lib/shields/policy-transition.test.ts
  • scripts/lib/generate-agent-state-lock-plans.mts
  • src/lib/agent/hermes-recovery-boundary-fixtures.ts
  • agents/hermes/manifest.yaml
  • docs/security/tcb-boundary.mdx
  • src/lib/shields/legacy-hermes-compat.test.ts
  • src/lib/sandbox/agent-config.test.ts
  • test/shields-up-runtime-perms.test.ts
  • src/lib/shields/flow.test.ts
  • src/lib/agent/state-directory-contract.test.ts
  • test/helpers/base-image-test-harness.ts
  • src/lib/shields/index.test.ts
  • src/lib/agent/state-directory-contract.ts
  • src/lib/shields/state-dir-lock.ts
  • src/lib/state/sandbox.ts
  • src/lib/agent/runtime.test.ts
  • src/lib/agent/definition-types.ts
  • src/lib/sandbox/agent-config.ts
  • src/lib/shields/index.ts
  • test/repro-2681-group-writable.test.ts
  • scripts/state-dir-guard.py
  • src/lib/shields/state-dir-lock.test.ts

Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>

@apurvvkumaria apurvvkumaria left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed exact head f6f0085. Manifest-derived state handling validates paths and overlaps, fails closed, preserves prior-agent semantics, and safely handles snapshot and image restoration. I found no blocking correctness, security, compatibility, or regression issue. The current automated test-fixture suggestion is non-blocking.

Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>

@apurvvkumaria apurvvkumaria left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Re-reviewed the current revision after the mainline refresh. The previously reviewed functional commits are unchanged; the only new PR-owned change clarifies the state-guard trust boundary and accurately matches the fail-closed helper/plan selection behavior and its tests. Exact-head correctness, platform, and security checks pass. The remaining dependency-audit gate failures are from existing dependency graphs this PR does not modify, so they are not attributable to this change. No blocking correctness, security, compatibility, or regression defect found.

@apurvvkumaria apurvvkumaria left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Blocking on current head 445b9c6: the CLI no longer compiles. npm run build:cli fails with TS2554 at src/lib/shields/index.ts:2444 because the DeepAgents rollback path still calls restoreStateDirLockPosture with three arguments after the merged base changed that API to require five. This same compile error is failing build-typecheck, installer, CLI shards, CLI parity, macOS, and WSL. Please pass requireStateLockPlan(target) and target.stateLockPlanInImage at this call site, matching the other rollback paths, then rerun the build and focused Shields transition tests.

@wscurran wscurran added area: architecture Architecture, design debt, major refactors, or maintainability area: skills Skills, agent behaviors, prompts, or skill packaging integration: hermes Hermes integration behavior labels Aug 4, 2026
@wscurran wscurran added the refactor PR restructures code without intended behavior change label Aug 4, 2026
github-actions Bot and others added 4 commits August 4, 2026 14:43
Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
@jyaunches

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@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)
scripts/state-dir-guard.py (1)

388-391: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Rename the comprehension variable to avoid shadowing value.

The generator expression binds value for each writable-subpath string while the outer value still holds the parsed plan object. The comprehension scope keeps the behavior correct, but the duplicate name makes the block harder to read and invites a mistake if this code later moves to a for loop.

♻️ Proposed rename
     writable_subpaths = tuple(
-        _validate_writable_subpath(value, f"writableSubpaths[{index}]")
-        for index, value in enumerate(writable_values)
+        _validate_writable_subpath(entry, f"writableSubpaths[{index}]")
+        for index, entry in enumerate(writable_values)
     )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/state-dir-guard.py` around lines 388 - 391, Rename the generator
expression’s comprehension variable in the writable_subpaths assignment, and
update its use in _validate_writable_subpath accordingly; preserve the outer
parsed-plan value binding and existing validation behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@scripts/state-dir-guard.py`:
- Around line 388-391: Rename the generator expression’s comprehension variable
in the writable_subpaths assignment, and update its use in
_validate_writable_subpath accordingly; preserve the outer parsed-plan value
binding and existing validation behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: d360b82e-12ad-49ce-983a-edecc847cc81

📥 Commits

Reviewing files that changed from the base of the PR and between f6f0085 and 0a633eb.

📒 Files selected for processing (11)
  • Dockerfile
  • agents/hermes/Dockerfile
  • ci/source-shape-test-budget.json
  • ci/test-file-size-budget.json
  • docs/index.yml
  • docs/manage-sandboxes/backup-restore.mdx
  • docs/security/best-practices.mdx
  • docs/security/tcb-boundary.mdx
  • package.json
  • scripts/nemoclaw-start.sh
  • scripts/state-dir-guard.py
🚧 Files skipped from review as they are similar to previous changes (9)
  • scripts/nemoclaw-start.sh
  • package.json
  • ci/test-file-size-budget.json
  • ci/source-shape-test-budget.json
  • agents/hermes/Dockerfile
  • docs/index.yml
  • docs/manage-sandboxes/backup-restore.mdx
  • docs/security/best-practices.mdx
  • docs/security/tcb-boundary.mdx

Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
@jyaunches

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
@jyaunches

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: architecture Architecture, design debt, major refactors, or maintainability area: skills Skills, agent behaviors, prompts, or skill packaging integration: hermes Hermes integration behavior refactor PR restructures code without intended behavior change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

refactor(hermes): separate configuration, runtime, and durable state ownership

4 participants