Skip to content

fix(mcp): reconcile Hermes runtime state - #6261

Merged
cv merged 22 commits into
mainfrom
fix/mcp-v075-followups
Jul 6, 2026
Merged

fix(mcp): reconcile Hermes runtime state#6261
cv merged 22 commits into
mainfrom
fix/mcp-v075-followups

Conversation

@ericksoa

@ericksoa ericksoa commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Summary

Reconcile Hermes MCP intent with the gateway state across transactions and lifecycle recovery, and bind OpenShell credential-boundary validation to the exact host CLI version before provider mutations. This closes the configuration-drift gap from #6257 while implementing the enforceable host-side portion of #6256 without adding a misleading in-image OpenShell stub.

Related Issue

Closes #6257
Addresses #6256

Changes

  • add an exact, uncached openshell --version gate before MCP provider/credential mutations; missing, failed, malformed, and mismatched probes fail closed without exposing command output
  • persist a canonical credential-safe MCP digest as intended and applied, commit applied state only after a healthy gateway reload, and restore both config and integrity snapshots on rollback
  • reconcile Hermes startup, restart, resume, rebuild, status, and recovery against persisted managed intent, including removal tombstones, with actionable fail-closed guidance
  • prevent generic config writes from changing mcp_servers, reject malformed or stale integrity state, and avoid blessing concurrent config drift during applied-state commits
  • preserve the canonical MCP state marker when shields transitions regenerate strict and compatibility hashes, and keep supervisor/API-key test fixtures on the same three-line contract
  • strictly allowlist credential-safe inspection fields and sanitize all sandbox-derived reconciliation diagnostics before connect/restart output
  • add focused regression coverage for version probes, additions/removals, pending and malformed state, root/non-root startup, rollback, registry reconciliation, and destroy recovery
  • extend the live Hermes MCP lane through removal plus a real gateway restart, proving the tombstone persists, effective config stays absent, the retired route remains denied, and credentials do not leak
  • preserve exact supervised API/dashboard relays across managed Hermes gateway replacements, retrying public health without churning structurally proven listeners
  • exclude authenticated Hermes config bytes from dataclass representations and cover the redaction

#6256 runtime-boundary note

OpenShell 0.0.72 intentionally does not expose the supervisor identity mount to workload children, and the Hermes workload image does not contain the host OpenShell CLI. Running openshell --version in the Python helper would therefore either fail every real transaction or attest an unrelated in-image stub rather than the supervisor enforcing credentials. This change verifies the selected host CLI immediately before every provider mutation and retains exact manifest/policy validation in Python. #6256 remains open for an upstream supervisor capability/version attestation that Hermes startup can verify honestly.

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: no new command, option, or operator-managed configuration; failures include inline restart/rebuild recovery guidance
  • 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: reviewed the credential boundary, transactional ordering, rollback, stale-state, redaction, tombstone, and concurrent-drift paths with focused fail-closed regressions; maintainer approval remains required before merge
  • Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue:

Verification

  • PR description includes the DCO sign-off declaration and every commit appears as Verified in GitHub
  • Git hooks passed during commit and push, or npx prek run --from-ref main --to-ref HEAD passes
  • Targeted tests pass for changed behavior
  • Full npm test passes (broad runtime changes only)
  • 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)
  • Doc pages follow the style guide (doc changes only)
  • New doc pages include SPDX header and frontmatter (new pages only)

Local verification on final head 44195b56c096ae3ee50f465de9c983f705eda031 passed 190 focused security/lifecycle tests across 10 files, both TypeScript typechecks, the CLI/plugin builds, Python compile/Ruff, ShellCheck/Biome, source-shape, test-size, title, conditional, diff, secret-scan, and commit/push hooks.

All ordinary required GitHub checks are green on the final head: 39 passed, 2 intentional skips, and 0 pending/failing. The one unrelated package-contract require-cache flake passed on clean rerun attempt 2, with no source change. The exact-head GPT advisor recommends merge_as_is; CodeRabbit is green, and all 8 review threads are resolved. The remaining stale/false-premise Nemotron items are addressed in the final-head disposition.

All advisor-required exact-head runtime proof passed: stable MCP bridge, Hermes E2E, gateway guard recovery, and production sandbox images plus downstream E2E. Stable MCP passed the real OpenClaw, DeepAgents, and Hermes add/restart/rebuild/remove/restart lifecycles, including adjacent Hermes restart and credential rotation; the credential scan passed across 489 artifact files.

All 22 PR commits are GitHub Verified and DCO-signed. The head is mergeable with a clean current-main synthetic merge. The moving OpenShell-dev lane remains optional and is not merge evidence; the supported credential boundary is the exact stable OpenShell 0.0.72 contract.

I certify that this contribution is made under the Developer Certificate of Origin.


Signed-off-by: Aaron Erickson aerickson@nvidia.com

Summary by CodeRabbit

  • New Features

    • Added Hermes MCP integrity tracking with intended/applied state transitions, plus CLI commands to inspect integrity and commit “applied”.
    • Added Hermes MCP runtime reconciliation remediation with fail-closed behavior during sandbox connect and gateway recovery/restart.
    • Persist and reconcile managed MCP server names across add/remove/destroy/restore.
  • Bug Fixes

    • Strengthened startup/restart verification to block drift and pending reconciliation, with improved rollback/reload verification behavior.
    • Improved failure classification/remediation messaging for MCP integrity and reconciliation-refusal scenarios.
  • Tests

    • Expanded coverage for Hermes MCP integrity, drift, reconciliation refusal, lifecycle flows, and config hash sealing.

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@ericksoa ericksoa added integration: hermes Hermes integration behavior area: sandbox OpenShell sandbox lifecycle, runtime, config, or recovery area: security Security controls, permissions, secrets, or hardening v0.0.75 labels Jul 3, 2026
@ericksoa ericksoa self-assigned this Jul 3, 2026
@coderabbitai

coderabbitai Bot commented Jul 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
📝 Walkthrough

Walkthrough

Adds MCP intended/applied integrity tracking across Hermes build, runtime guard, transaction, startup, and sandbox flows, reconciles persisted MCP server intent with the running gateway, persists managedServerNames through lifecycle operations, and adds fail-closed OpenShell runtime version verification with pinned fixtures.

Changes

Hermes MCP intended/applied integrity reconciliation

Layer / File(s) Summary
Build-time MCP digest helper and Dockerfile wiring
agents/hermes/build-mcp-digest.py, agents/hermes/Dockerfile, scripts/update-hermes-agent.sh, test/hermes-doctor-config-hash.test.ts, test/update-hermes-agent-script.test.ts
New digest helper computes canonical MCP digests; Dockerfile copies/hardens it and appends intended/applied markers to the config hash; schema validator and Dockerfile tests now require the new markers and helper wiring.
Runtime config guard MCP state
agents/hermes/runtime-config-guard.py, test/hermes-mcp-integrity-state.test.ts, test/hermes-runtime-config-guard.test.ts
Adds McpHashState/McpIntegritySnapshot, MCP-aware digest hashing, transition-based refresh_hashes, integrity inspection APIs, drift rejection in write_config_transaction, new CLI actions, and readiness/test coverage for the new actions and state transitions.
MCP transaction inspect and reload flow
agents/hermes/mcp-config-transaction.py, test/hermes-mcp-config-transaction.test.ts, test/hermes-nonroot-strict-hash-reconciliation.test.ts
Adds inspect_managed_config/inspect CLI action, transition-aware hash verification in apply_transaction/apply_transaction_and_reload, tightened gateway identity checks, and updated transaction/reconciliation test fixtures.
start.sh MCP reconcile enforcement
agents/hermes/start.sh, scripts/gateway-control.sh, scripts/lib/gateway-supervisor.sh, test/hermes-gateway-supervisor-recovery.test.ts, test/hermes-start-config-integrity.test.ts, test/gateway-supervisor-mcp-failure-contract.test.ts
Startup/restart flow gains MCP integrity inspection, commit-if-pending, and revocation/quarantine behavior on drift; supervisor scripts add new failure codes and the shell tests stub the new startup/commit paths.
Hermes MCP reconciliation helper
src/lib/actions/sandbox/mcp-bridge-hermes-reconciliation.ts, src/lib/actions/sandbox/mcp-bridge-adapter-status.ts, src/lib/actions/sandbox/mcp-bridge-hermes-reconciliation.test.ts, test/e2e/live/mcp-bridge-hermes-lifecycle.ts, test/e2e/live/mcp-bridge.test.ts
New helper inspects/asserts Hermes runtime intent against persisted state via sandbox exec, with sanitized diagnostics and status/e2e coverage.
Connect, restart, and process recovery wiring
src/lib/actions/sandbox/connect.ts, src/lib/actions/sandbox/connect-boundary-refusal.ts, src/lib/actions/sandbox/gateway-restart.ts, src/lib/actions/sandbox/process-recovery.ts, src/lib/actions/sandbox/mcp-bridge-recovery.ts, related tests
MCP reconciliation refusal becomes a distinct fail-closed path across connect probe/full flow, gateway restart, and process recovery.
managedServerNames persistence and MCP bridge status
src/lib/state/registry-mcp.ts, src/lib/actions/sandbox/mcp-bridge-state.ts, src/lib/actions/sandbox/mcp-bridge-destroy.ts, src/lib/actions/sandbox/mcp-bridge-status.ts, src/lib/actions/sandbox/mcp-bridge-add-restart.ts, src/lib/actions/sandbox/mcp-bridge-remove.ts, src/lib/actions/sandbox/mcp-bridge-restart.ts, related tests
Managed server name tombstones persist through bridge removal/destroy/restart, and status reporting consults Hermes reconciliation.
Python/shell MCP integrity regression tests
test/*.test.ts
Regression coverage spans hash state, drift, commit failure, startup trace ordering, and registry persistence behavior.

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

OpenShell credential boundary runtime version enforcement

Layer / File(s) Summary
Runtime version assertion
src/lib/actions/sandbox/mcp-bridge-validation.ts, src/lib/actions/sandbox/mcp-bridge-input-validation.test.ts
New assertMcpCredentialBoundaryRuntimeVersion() probes openshell --version and fails closed on mismatch, missing binary, or unparseable output.
OpenShell fixture and test pinning
test/fixtures/openshell-v0.0.72, test/deepagents-mcp-legacy-lifecycle.test.ts, test/mcp-*.test.ts, test/sandbox-*.test.ts
A pinned OpenShell fixture and subprocess environment updates are applied across MCP lifecycle, policy, restart, and provisioning tests.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Startsh as start.sh
  participant Guard as runtime-config-guard.py
  participant Transaction as mcp-config-transaction.py
  participant Gateway

  Startsh->>Guard: inspect_hermes_mcp_integrity()
  Guard-->>Startsh: pending or current
  alt reconciliation pending
    Startsh->>Transaction: commit_hermes_mcp_applied_if_pending()
    Transaction->>Guard: refresh_hashes(mcp_transition="apply")
    Guard-->>Transaction: applied state committed
  else drift detected / commit fails
    Startsh->>Gateway: stop uncommitted gateway
    Startsh-->>Startsh: fail with mcp-integrity
  end
Loading
sequenceDiagram
  participant Client as connectSandbox
  participant Recon as inspectHermesMcpRuntimeIntent
  participant Openshell as OpenShell CLI
  participant Transaction as hermes-mcp-config-transaction.py

  Client->>Recon: inspectHermesMcpRuntimeIntent(sandboxName)
  Recon->>Openshell: sandbox exec inspect --payload
  Openshell->>Transaction: inspect
  Transaction-->>Openshell: matched or mismatch
  Openshell-->>Recon: stdout/stderr
  Recon-->>Client: ok/state/detail
  alt refused
    Client->>Client: exitOnMcpReconciliationRefusal (exit 1)
  end
Loading

Possibly related issues

Possibly related PRs

  • NVIDIA/NemoClaw#2891: Touches the same CLI sandbox connect flow and its refactoring path.
    Suggested labels: bug-fix

Suggested reviewers: cjagwani

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes implement canonical MCP intent hashing, fail-closed drift checks, transactional apply/rollback behavior, and regression coverage for add/remove and restart/rebuild cases.
Out of Scope Changes check ✅ Passed No clear unrelated code changes stand out; the added helpers, guards, and tests all support Hermes MCP reconciliation and credential-boundary enforcement.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately reflects the main change: aligning Hermes MCP runtime state and reconciliation behavior.
✨ 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/mcp-v075-followups

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

@github-code-quality

github-code-quality Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

The overall coverage in the fix/mcp-v075-followu... branch is 96%. Coverage data for the main branch is not yet available.

Show a code coverage summary of the most covered files.
File main fix/mcp-v075-followu... 44195b5 +/-
nemoclaw/src/se...cret-scanner.ts 100%
nemoclaw/src/commands/slash.ts 100%
nemoclaw/src/li...bprocess-env.ts 100%
nemoclaw/src/bl...eprint/state.ts 98%
nemoclaw/src/onboard/config.ts 98%
nemoclaw/src/bl...int/snapshot.ts 97%
nemoclaw/src/bl...print/runner.ts 95%
nemoclaw/src/co...ration-state.ts 94%
nemoclaw/src/bl...ate-networks.ts 94%
nemoclaw/src/index.ts 94%

TypeScript / code-coverage/cli

The overall coverage in the fix/mcp-v075-followu... branch is 71%. Coverage data for the main branch is not yet available.

Show a code coverage summary of the most covered files.
File main fix/mcp-v075-followu... 44195b5 +/-
src/lib/shields...nsition-lock.ts 87%
src/lib/actions...all/run-plan.ts 81%
src/lib/state/o...oard-session.ts 81%
src/lib/onboard/preflight.ts 71%
src/lib/state/sandbox.ts 71%
src/lib/onboard...er-gpu-patch.ts 69%
src/lib/shields/index.ts 68%
src/lib/policy/index.ts 66%
src/lib/actions...licy-channel.ts 60%
src/lib/onboard.ts 24%

Updated July 06, 2026 04:39 UTC
Code Coverage is in Public Preview. Learn more and provide us with your feedback.

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor (Nemotron Ultra) — Changes requested

Merge posture: Do not merge yet
Primary next action: Fix PRA-2: McpIntegritySnapshot.config_text leaks in default dataclass repr; then add or justify PRA-T1.
Open items: 5 required · 14 warnings · 6 suggestions · 8 test follow-ups
Since last review: 3 prior items resolved · 8 still apply · 4 new items found

Action checklist

  • PRA-2 Fix: McpIntegritySnapshot.config_text leaks in default dataclass repr in agents/hermes/runtime-config-guard.py:245
  • PRA-3 Fix: Missing test for _parse_config_hash usage in non-root reconciliation in test/hermes-mcp-integrity-state.test.ts:1
  • PRA-4 Fix: mcp-bridge-recovery tests lack caller-specific parameterized coverage in src/lib/actions/sandbox/mcp-bridge-recovery.test.ts:1
  • PRA-7 Fix: Credential manifest test missing source-checkout layout fallback and version mismatch coverage in test/hermes-mcp-credential-boundary-manifest.test.ts:1
  • PRA-8 Fix: Missing add→restart→remove→restart cycle test with integrity verification in test/hermes-mcp-integrity-state.test.ts:1
  • PRA-1 Resolve or justify: Source-of-truth review needed: agents/hermes/mcp-config-transaction.py:_load_credential_boundary_manifest (line 39)
  • PRA-5 Resolve or justify: Missing full rollback transition test (rollback → healthy reload → current/current) in test/hermes-mcp-integrity-state.test.ts:1
  • PRA-6 Resolve or justify: Missing McpIntegritySnapshot __repr__ redaction test in test/hermes-mcp-integrity-state.test.ts:1
  • PRA-9 Resolve or justify: Source-of-truth review needed for double-parse TOCTOU in non-root reconciliation in agents/hermes/runtime-config-guard.py:1673
  • PRA-10 Resolve or justify: Source-of-truth review for credential boundary manifest workaround in agents/hermes/mcp-config-transaction.py:39
  • PRA-11 Resolve or justify: Source-of-truth review for non-root lifecycle identity check in agents/hermes/runtime-config-guard.py:579
  • PRA-12 Resolve or justify: Source-of-truth review for rollback 'restored/failed-candidate' state in agents/hermes/runtime-config-guard.py:1312
  • PRA-13 Resolve or justify: Source-of-truth review for os.access best-effort compat hash writability probe in agents/hermes/runtime-config-guard.py:1376
  • PRA-14 Resolve or justify: Source-of-truth review for reload gateway re-kick fallback (socat relay limitation) in agents/hermes/mcp-config-transaction.py:1008
  • PRA-15 Resolve or justify: Coordinate with authors of PRs feat(hermes): bump to v0.16 (calver 2026.6.5) + upgrade follow-ups #5217, feat(sandbox): import host corporate proxy CA into sandbox trust (#6210) #6292, fix(model-router): stop/recover router on uninstall & onboard; extend gateway health wait #5230, fix(hermes): install safety-net + ciao NODE_OPTIONS preloads so recover can relaunch #5416 to determine merge order in agents/hermes/start.sh:1
  • PRA-T1 Add or justify test follow-up: Runtime validation
  • PRA-T2 Add or justify test follow-up: Runtime validation
  • PRA-T3 Add or justify test follow-up: Runtime validation
  • PRA-T4 Add or justify test follow-up: Runtime validation
  • PRA-T5 Add or justify test follow-up: Runtime validation
  • PRA-T6 Add or justify test follow-up: Missing test for _parse_config_hash usage in non-root reconciliation
  • PRA-T7 Add or justify test follow-up: mcp-bridge-recovery tests lack caller-specific parameterized coverage
  • PRA-T8 Add or justify test follow-up: Missing full rollback transition test (rollback → healthy reload → current/current)
  • PRA-16 In-scope improvement: Extract enforceHermesSecretBoundaryOnRunningGateway, recoverMessagingHostForward, recoverDeclaredAgentForwardPorts into separate modules in src/lib/actions/sandbox/process-recovery.ts:1
  • PRA-17 In-scope improvement: build-mcp-digest.py reuses guard's canonical MCP function — good pattern in agents/hermes/build-mcp-digest.py:1
  • PRA-18 In-scope improvement: Compatibility proof for OpenShell 0.0.72 split topology documented in agents/hermes/runtime-config-guard.py:579
  • PRA-19 In-scope improvement: Rollback 'restored/failed-candidate' state documented with removal condition in agents/hermes/runtime-config-guard.py:1312
  • PRA-20 In-scope improvement: os.access best-effort probe correctly acknowledged with atomic write as real authority in agents/hermes/runtime-config-guard.py:1376
  • PRA-24 In-scope improvement: connect.ts net-negative delta (-35 lines) — good simplification in src/lib/actions/sandbox/connect.ts:1

Findings index

ID Severity Category Location Required action
PRA-1 Resolve/justify architecture Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
PRA-2 Required security agents/hermes/runtime-config-guard.py:245 FIXED — field(repr=False) added on config_text. Verify test 'omits authenticated config bytes from integrity snapshot representations' passes.
PRA-3 Required tests test/hermes-mcp-integrity-state.test.ts:1 Add test in hermes-mcp-integrity-state.test.ts that mocks runtime-config-guard.py, calls _reconcile_nonroot_startup_api_key_hash with controlled inputs, and asserts _parse_config_hash was invoked with expected config_path and env_path, returning expected McpHashState.
PRA-4 Required tests src/lib/actions/sandbox/mcp-bridge-recovery.test.ts:1 Add it.each parameterized tests in mcp-bridge-recovery.test.ts exercising both functions with mocked inspect functions matching each caller's contract, verifying correct output structure for recovery vs restart vs add vs remove vs gateway-restart.
PRA-5 Resolve/justify tests test/hermes-mcp-integrity-state.test.ts:1 Add test in hermes-mcp-integrity-state.test.ts exercising complete rollback flow: pending → restore config → rollback transition → verify state='pending' with intended=restored/applied=failed-candidate → simulate healthy reload → call commit-mcp-applied → verify current/current.
PRA-6 Resolve/justify tests test/hermes-mcp-integrity-state.test.ts:1 Verify test passes; no new test needed.
PRA-7 Required tests test/hermes-mcp-credential-boundary-manifest.test.ts:1 Add three tests: (1) manifest only in source-checkout path loads correctly; (2) both paths present with different versions — verify strict version check fails; (3) both paths present with same version — verify first-found precedence.
PRA-8 Required acceptance test/hermes-mcp-integrity-state.test.ts:1 Add test in hermes-mcp-integrity-state.test.ts or hermes-mcp-config-transaction.test.ts: add MCP server → verify integrity state becomes pending → restart gateway → verify integrity state becomes current → remove MCP server → verify integrity state becomes pending → restart gateway → verify integrity state becomes current.
PRA-9 Resolve/justify architecture agents/hermes/runtime-config-guard.py:1673 Verify source-of-truth comment block in _reconcile_nonroot_startup_api_key_hash documents all five elements. Already present in code — confirm completeness.
PRA-10 Resolve/justify architecture agents/hermes/mcp-config-transaction.py:39 Verify comment completeness. Note: test gap in PRA-6 (dual-path tests missing) weakens regression test claim.
PRA-11 Resolve/justify architecture agents/hermes/runtime-config-guard.py:579 Verify source-of-truth comment in _pinned_process_matches_supervised_nonroot_start documents all five elements.
PRA-12 Resolve/justify architecture agents/hermes/runtime-config-guard.py:1312 Verify source-of-truth comment in refresh_hashes rollback branch documents all five elements with #6257 reference.
PRA-13 Resolve/justify architecture agents/hermes/runtime-config-guard.py:1376 Verify source-of-truth comment documents os.access as best-effort only, with atomic write as authority.
PRA-14 Resolve/justify architecture agents/hermes/mcp-config-transaction.py:1008 Verify source-of-truth comment in reload_gateway re-kick logic documents all five elements.
PRA-15 Resolve/justify correctness agents/hermes/start.sh:1 Coordinate with authors of PRs #5217, #6292, #5230, #5416 to determine merge order. Rebase this PR onto the others or vice versa before merge. Run hermes-start.test.ts and hermes-gateway-supervisor-recovery.test.ts after merge resolution.
PRA-16 Improvement architecture src/lib/actions/sandbox/process-recovery.ts:1 Track as technical debt; extract when these functions are reused or modified. Not blocking for this PR.
PRA-17 Improvement architecture agents/hermes/build-mcp-digest.py:1 No change needed. Follow this pattern for other build-time/runtime verification alignments.
PRA-18 Improvement correctness agents/hermes/runtime-config-guard.py:579 Verify comment completeness. No change needed if complete.
PRA-19 Improvement architecture agents/hermes/runtime-config-guard.py:1312 Verify comment references #6257. No change needed if complete.
PRA-20 Improvement architecture agents/hermes/runtime-config-guard.py:1376 Verify comment acknowledges os.access as best-effort. No change needed if complete.

🚨 Required before merge

Address these before merging unless a maintainer explicitly overrides the advisor with rationale.

PRA-2 Required — McpIntegritySnapshot.config_text leaks in default dataclass repr

  • Location: agents/hermes/runtime-config-guard.py:245
  • Category: security
  • Problem: The dataclass field `config_text` was not marked `repr=False`, causing authenticated config bytes (which can include credentials) to appear in `repr(snapshot)` and potentially leak into logs.
  • Impact: Credential leakage if any code logs or prints McpIntegritySnapshot instances during debugging or error handling.
  • Required action: FIXED — field(repr=False) added on config_text. Verify test 'omits authenticated config bytes from integrity snapshot representations' passes.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check agents/hermes/runtime-config-guard.py line 245 for field(repr=False) on config_text; run test/hermes-mcp-integrity-state.test.ts 'omits authenticated config bytes from integrity snapshot representations'
  • Missing regression test: Already covered by hermes-mcp-integrity-state.test.ts test 'omits authenticated config bytes from integrity snapshot representations' which asserts repr does not contain config_text field or secret value
  • Done when: The required change is committed and verification passes: Check agents/hermes/runtime-config-guard.py line 245 for field(repr=False) on config_text; run test/hermes-mcp-integrity-state.test.ts 'omits authenticated config bytes from integrity snapshot representations'.
  • Evidence: agents/hermes/runtime-config-guard.py:245 shows config_text: str = field(repr=False); test verifies JSON output contains contains_config_field: false

PRA-3 Required — Missing test for _parse_config_hash usage in non-root reconciliation

  • Location: test/hermes-mcp-integrity-state.test.ts:1
  • Category: tests
  • Problem: The non-root reconciliation path (_reconcile_nonroot_startup_api_key_hash) calls _parse_config_hash twice (strict + actual) with a re-read between. No test mocks this function to verify it's invoked with correct config_path and env_path arguments returning expected McpHashState.
  • Impact: TOCTOU race between the two _parse_config_hash calls could allow config/env drift to be blessed if the race is not caught by the re-read verification. Without a mock test, the double-parse contract is unverified.
  • Required action: Add test in hermes-mcp-integrity-state.test.ts that mocks runtime-config-guard.py, calls _reconcile_nonroot_startup_api_key_hash with controlled inputs, and asserts _parse_config_hash was invoked with expected config_path and env_path, returning expected McpHashState.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Search test/hermes-nonroot-strict-hash-reconciliation.test.ts for _parse_config_hash mock/verification — currently absent
  • Missing regression test: New test needed: mock _parse_config_hash in non-root reconciliation path and assert it's called with correct arguments
  • Done when: The required change is committed and verification passes: Search test/hermes-nonroot-strict-hash-reconciliation.test.ts for _parse_config_hash mock/verification — currently absent.
  • Evidence: runtime-config-guard.py:1672-1678 shows double _parse_config_hash call with re-read between; no existing test mocks this function

PRA-4 Required — mcp-bridge-recovery tests lack caller-specific parameterized coverage

  • Location: src/lib/actions/sandbox/mcp-bridge-recovery.test.ts:1
  • Category: tests
  • Problem: The module exports inspectHermesMcpReconciliationRefusal and processRecoveryMcpReconciliationRefusal. Tests only cover 3 basic cases (match, sanitize, map). No parameterized tests over caller types (recovery vs restart vs add vs remove vs gateway-restart) with their distinct inspect contracts.
  • Impact: Different callers may pass different reconciliation result shapes; without caller-specific tests, a contract mismatch in one path (e.g., gateway-restart vs recovery) could go undetected.
  • Required action: Add it.each parameterized tests in mcp-bridge-recovery.test.ts exercising both functions with mocked inspect functions matching each caller's contract, verifying correct output structure for recovery vs restart vs add vs remove vs gateway-restart.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Read src/lib/actions/sandbox/mcp-bridge-recovery.test.ts — only 3 basic tests exist, no it.each parameterization over caller types
  • Missing regression test: Parameterized test matrix covering: recovery, restart, add, remove, gateway-restart callers with their distinct inspect contracts
  • Done when: The required change is committed and verification passes: Read src/lib/actions/sandbox/mcp-bridge-recovery.test.ts — only 3 basic tests exist, no it.each parameterization over caller types.
  • Evidence: mcp-bridge-recovery.ts exports two functions used by different callers; test file has only 3 basic tests

PRA-7 Required — Credential manifest test missing source-checkout layout fallback and version mismatch coverage

  • Location: test/hermes-mcp-credential-boundary-manifest.test.ts:1
  • Category: tests
  • Problem: The manifest loader tries two paths: installed location (beside helper) and source-checkout layout (parents[2]/src/lib/actions/sandbox/...). Tests only cover: missing manifest, wrong version (0.0.73), missing keys. No tests for: (1) manifest only in source-checkout path loads correctly; (2) both paths present with different versions — strict version check fails; (3) both paths present with same version — first-found precedence.
  • Impact: If the installed manifest is corrupted/missing but source-checkout is valid, the transaction could fail incorrectly. If both exist with version mismatch, the wrong manifest could be loaded silently.
  • Required action: Add three tests: (1) manifest only in source-checkout path loads correctly; (2) both paths present with different versions — verify strict version check fails; (3) both paths present with same version — verify first-found precedence.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Read test/hermes-mcp-credential-boundary-manifest.test.ts — 107 lines covering missing/wrong-version/missing-keys only; no dual-path tests
  • Missing regression test: Three new tests covering: source-checkout-only, dual-path version mismatch, dual-path same-version precedence
  • Done when: The required change is committed and verification passes: Read test/hermes-mcp-credential-boundary-manifest.test.ts — 107 lines covering missing/wrong-version/missing-keys only; no dual-path tests.
  • Evidence: mcp-config-transaction.py:55-75 shows two candidate paths; test file only exercises single-path failure modes

PRA-8 Required — Missing add→restart→remove→restart cycle test with integrity verification

  • Location: test/hermes-mcp-integrity-state.test.ts:1
  • Category: acceptance
  • Problem: Issue fix(hermes): reconcile mcp_servers configuration drift at startup #6257 requires coverage for 'additions, removals, restart, resume, and rebuild'. The full lifecycle: add MCP server → verify integrity state becomes pending → restart gateway → verify integrity state becomes current → remove MCP server → verify integrity state becomes pending → restart gateway → verify integrity state becomes current. No test exercises this complete cycle.
  • Impact: Integration gap: individual steps tested but not the end-to-end drift reconciliation across multiple transactions and gateway restarts.
  • Required action: Add test in hermes-mcp-integrity-state.test.ts or hermes-mcp-config-transaction.test.ts: add MCP server → verify integrity state becomes pending → restart gateway → verify integrity state becomes current → remove MCP server → verify integrity state becomes pending → restart gateway → verify integrity state becomes current.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Search test files for add/restart/remove cycle with integrity state verification — not found
  • Missing regression test: Full lifecycle test: add → pending → reload → current → remove → pending → reload → current
  • Done when: The required change is committed and verification passes: Search test files for add/restart/remove cycle with integrity state verification — not found.
  • Evidence: Issue fix(hermes): reconcile mcp_servers configuration drift at startup #6257 acceptance criteria requires 'Successful nemoclaw mcp add|remove operations remain correct after restart, resume, and rebuild'
Review findings by urgency: 5 required fixes, 14 items to resolve/justify, 6 in-scope improvements

⚠️ Resolve or justify before merge

Investigate these in the current review; either fix them, explain why they are not applicable, or document the accepted risk.

PRA-1 Resolve/justify — Source-of-truth review needed: agents/hermes/mcp-config-transaction.py:_load_credential_boundary_manifest (line 39)

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as needs_followup.
  • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
  • Recommended action: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Missing regression test: hermes-mcp-credential-boundary-manifest.test.ts covers missing/wrong-version/invalid keys but NOT dual-path precedence or source-checkout-only (PRA-6 gap)
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Evidence: mcp-config-transaction.py lines 39-80 show manifest loading with updated comment including OpenShell 0.0.72 limitation

PRA-5 Resolve/justify — Missing full rollback transition test (rollback → healthy reload → current/current)

  • Location: test/hermes-mcp-integrity-state.test.ts:1
  • Category: tests
  • Problem: The rollback state machine transitions: pending (intended!=applied) → restore config → rollback transition (intended=restored/applied=failed-candidate) → healthy old-config reload → commit-mcp-applied → current/current. No test exercises this full cycle in hermes-mcp-integrity-state.test.ts.
  • Impact: Rollback path could have a gap where the second healthy reload doesn't properly advance applied state, leaving the system stuck in pending.
  • Recommended action: Add test in hermes-mcp-integrity-state.test.ts exercising complete rollback flow: pending → restore config → rollback transition → verify state='pending' with intended=restored/applied=failed-candidate → simulate healthy reload → call commit-mcp-applied → verify current/current.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: test/hermes-mcp-rollback-pending.test.ts covers rollback flow but not the full commit-mcp-applied transition in integrity-state test file
  • Missing regression test: Full lifecycle test in hermes-mcp-integrity-state.test.ts covering rollback → reload → commit-mcp-applied
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: test/hermes-mcp-rollback-pending.test.ts covers rollback flow but not the full commit-mcp-applied transition in integrity-state test file.
  • Evidence: hermes-mcp-rollback-pending.test.ts proves rollback state machine but not the commit-mcp-applied step in integrity-state context

PRA-6 Resolve/justify — Missing McpIntegritySnapshot __repr__ redaction test

  • Location: test/hermes-mcp-integrity-state.test.ts:1
  • Category: tests
  • Problem: Test already exists and passes — 'omits authenticated config bytes from integrity snapshot representations' verifies repr does not contain config_text field or secret value.
  • Impact: None — already covered.
  • Recommended action: Verify test passes; no new test needed.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Run test/hermes-mcp-integrity-state.test.ts and verify the repr test passes
  • Missing regression test: Already covered by existing test in hermes-mcp-integrity-state.test.ts
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Run test/hermes-mcp-integrity-state.test.ts and verify the repr test passes.
  • Evidence: test/hermes-mcp-integrity-state.test.ts lines 40-80: 'omits authenticated config bytes from integrity snapshot representations' test

PRA-9 Resolve/justify — Source-of-truth review needed for double-parse TOCTOU in non-root reconciliation

  • Location: agents/hermes/runtime-config-guard.py:1673
  • Category: architecture
  • Problem: The _reconcile_nonroot_startup_api_key_hash function calls _parse_config_hash twice (strict text + actual text) with a re-read between. Source-of-truth comment must document: (1) Invalid state: config/env race between two _parse_config_hash calls. (2) Source boundary: guard owns parsing and atomic hash advancement. (3) Why not source fix: Hermes/OpenShell exposes no authenticated applied-config digest. (4) Regression test: hermes-nonroot-strict-hash-reconciliation.test.ts covers reconciliation posture. (5) Removal condition: when runtime exposes authenticated applied-config digest (security: verify runtime OpenShell version against credential boundary manifest #6256).
  • Impact: If the source-of-truth comment is incomplete, future maintainers may not understand the TOCTOU boundary or when it can be removed.
  • Recommended action: Verify source-of-truth comment block in _reconcile_nonroot_startup_api_key_hash documents all five elements. Already present in code — confirm completeness.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Check agents/hermes/runtime-config-guard.py lines 1580-1720 for source-of-truth comment block on _reconcile_nonroot_startup_api_key_hash
  • Missing regression test: hermes-nonroot-strict-hash-reconciliation.test.ts covers reconciliation but not the double-parse TOCTOU specifically
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Check agents/hermes/runtime-config-guard.py lines 1580-1720 for source-of-truth comment block on _reconcile_nonroot_startup_api_key_hash.
  • Evidence: runtime-config-guard.py lines 1580-1720 contain the function with source-of-truth comment

PRA-10 Resolve/justify — Source-of-truth review for credential boundary manifest workaround

  • Location: agents/hermes/mcp-config-transaction.py:39
  • Category: architecture
  • Problem: _load_credential_boundary_manifest loads manifest from two deterministic paths. Source-of-truth comment must document: (1) Invalid state: transaction accepts credential against missing/corrupt/wrong-version manifest. (2) Source boundary: NemoClaw owns reviewed manifest at two deterministic paths. (3) Why not source fix: OpenShell v0.0.72 no child-env contract, hides supervisor mount. (4) Regression test: hermes-mcp-credential-boundary-manifest.test.ts covers missing/wrong-version/invalid keys. (5) Removal condition: security: verify runtime OpenShell version against credential boundary manifest #6256 upstream authenticated attestation.
  • Impact: Workaround is documented with removal condition tied to upstream capability.
  • Recommended action: Verify comment completeness. Note: test gap in PRA-6 (dual-path tests missing) weakens regression test claim.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Check agents/hermes/mcp-config-transaction.py lines 39-80 for updated source-of-truth comment block
  • Missing regression test: Test file missing dual-path precedence and source-checkout-only tests (see PRA-6)
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Check agents/hermes/mcp-config-transaction.py lines 39-80 for updated source-of-truth comment block.
  • Evidence: mcp-config-transaction.py lines 39-80 show manifest loading with two candidates

PRA-11 Resolve/justify — Source-of-truth review for non-root lifecycle identity check

  • Location: agents/hermes/runtime-config-guard.py:579
  • Category: architecture
  • Problem: _pinned_process_matches_supervised_nonroot_start prevents legacy topology mutations. Source-of-truth comment must document: (1) Invalid state: sandbox process claims same-UID authority while Hermes runs legacy root-separated topology. (2) Source boundary: OpenShell owns workload topology; NemoClaw owns immutable root-lifecycle marker. (3) Why not source fix: OpenShell 0.0.72 no attested same-UID capability. (4) Regression test: hermes-mcp-config-transaction.test.ts rejects probe/add when root-lifecycle marker identifies legacy topology. (5) Removal condition: security: verify runtime OpenShell version against credential boundary manifest #6256.
  • Impact: Legacy topology mutation prevention is a critical security boundary; documentation must be accurate for future removal.
  • Recommended action: Verify source-of-truth comment in _pinned_process_matches_supervised_nonroot_start documents all five elements.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Check agents/hermes/runtime-config-guard.py lines 579-650 for source-of-truth comment block
  • Missing regression test: hermes-mcp-config-transaction.test.ts should cover legacy topology rejection
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Check agents/hermes/runtime-config-guard.py lines 579-650 for source-of-truth comment block.
  • Evidence: runtime-config-guard.py lines 579-650 contain the function with OpenShell 0.0.72 compatibility comment

PRA-12 Resolve/justify — Source-of-truth review for rollback 'restored/failed-candidate' state

  • Location: agents/hermes/runtime-config-guard.py:1312
  • Category: architecture
  • Problem: refresh_hashes rollback branch sets state to intended=restored/applied=failed-candidate. Source-of-truth comment must document: (1) Invalid state: failed desired-config reload leaves runtime identity uncertain. (2) Source boundary: guard owns hash state machine; transaction helper owns candidate writes/rollback. (3) Why not source fix: Hermes/OpenShell no authenticated applied-config digest. (4) Regression test: hermes-mcp-rollback-pending.test.ts and hermes-mcp-integrity-state.test.ts cover rollback transitions. (5) Removal condition: fix(hermes): reconcile mcp_servers configuration drift at startup #6257 runtime exposes authenticated applied-config digest with transactional rollback.
  • Impact: Rollback state machine correctness depends on this conservative state recording.
  • Recommended action: Verify source-of-truth comment in refresh_hashes rollback branch documents all five elements with fix(hermes): reconcile mcp_servers configuration drift at startup #6257 reference.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Check agents/hermes/runtime-config-guard.py lines 1130-1200 for rollback transition source-of-truth comment
  • Missing regression test: hermes-mcp-rollback-pending.test.ts covers rollback but could use more explicit state verification
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Check agents/hermes/runtime-config-guard.py lines 1130-1200 for rollback transition source-of-truth comment.
  • Evidence: runtime-config-guard.py lines 1130-1200 contain rollback logic with McpHashState

PRA-13 Resolve/justify — Source-of-truth review for os.access best-effort compat hash writability probe

  • Location: agents/hermes/runtime-config-guard.py:1376
  • Category: architecture
  • Problem: refresh_hashes uses os.access for compat hash writability check but acknowledges atomic write as real authority. Source-of-truth comment must document: (1) Invalid state: os.access disagrees with effective write credentials. (2) Source boundary: atomic rename is real authority. (3) Why not source fix: old locked images need best-effort compat anchor. (4) Regression test: hermes-mcp-integrity-state.test.ts 'uses the atomic write outcome for compat applied-state commits'. (5) Removal condition: remove compat fallback when minimum image guarantees strict-only anchor.
  • Impact: Compat hash path could incorrectly allow/deny writes based on os.access false positive/negative; atomic write is the true gate.
  • Recommended action: Verify source-of-truth comment documents os.access as best-effort only, with atomic write as authority.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Check agents/hermes/runtime-config-guard.py lines 1130-1200 for compat_commit_required logic and comment
  • Missing regression test: hermes-mcp-integrity-state.test.ts has 'uses the atomic write outcome for compat applied-state commits' test
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Check agents/hermes/runtime-config-guard.py lines 1130-1200 for compat_commit_required logic and comment.
  • Evidence: runtime-config-guard.py lines 1376-1385 show compat_commit_required logic with comment

PRA-14 Resolve/justify — Source-of-truth review for reload gateway re-kick fallback (socat relay limitation)

  • Location: agents/hermes/mcp-config-transaction.py:1008
  • Category: architecture
  • Problem: reload_gateway re-kicks SIGUSR1 once if gateway doesn't converge, but skips re-kick if observed_phase is 'waiting-for-public-relay-health-on-8642' because managed supervisor owns socat relay. Source-of-truth comment must document: (1) Invalid state: public socat relay not re-established after gateway reload. (2) Source boundary: OpenShell supervisor owns socat relay lifecycle; Hermes gateway cannot repair. (3) Why not source fix: OpenShell v0.0.72 no relay health/repair API to workload. (4) Regression test: hermes-gateway-auxiliary-retry.test.ts covers retry behavior. (5) Removal condition: security: verify runtime OpenShell version against credential boundary manifest #6256 OpenShell exposes authenticated supervisor/runtime attestation with relay health.
  • Impact: Re-kick logic correctly avoids churn but is a workaround for missing upstream capability.
  • Recommended action: Verify source-of-truth comment in reload_gateway re-kick logic documents all five elements.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Check agents/hermes/mcp-config-transaction.py lines 940-1020 for re-kick logic and source-of-truth comment
  • Missing regression test: hermes-gateway-auxiliary-retry.test.ts covers auxiliary retry but not the specific socat relay re-kick limitation
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Check agents/hermes/mcp-config-transaction.py lines 940-1020 for re-kick logic and source-of-truth comment.
  • Evidence: mcp-config-transaction.py lines 940-1020 contain reload_gateway with re_kick_attempted logic

PRA-15 Resolve/justify — Coordinate with authors of PRs #5217, #6292, #5230, #5416 to determine merge order

PRA-21 Resolve/justify — New inspect action in mcp-config-transaction.py lacks test coverage for credential boundary manifest source-checkout path

  • Location: agents/hermes/mcp-config-transaction.py:470
  • Category: security
  • Problem: The new 'inspect' action (added alongside add/remove/probe) loads the credential boundary manifest via _load_credential_boundary_manifest which tries two paths. No test exercises inspect with manifest only in source-checkout layout.
  • Impact: Inspect action could fail silently or load wrong manifest if source-checkout path has different version/content.
  • Recommended action: Add test that exercises the inspect action with a manifest only present in the source-checkout layout (parents[2]/src/lib/actions/sandbox/...).
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Check test/hermes-mcp-config-transaction.test.ts for inspect action tests — none found
  • Missing regression test: New test for inspect action with source-checkout manifest layout
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Check test/hermes-mcp-config-transaction.test.ts for inspect action tests — none found.
  • Evidence: mcp-config-transaction.py:1081 adds 'inspect' to action choices; _load_credential_boundary_manifest uses two candidate paths

PRA-22 Resolve/justify — inspect_hermes_mcp_integrity uses exit-code-only protocol; verify no shell interpolation vulnerabilities

  • Location: agents/hermes/start.sh:300
  • Category: security
  • Problem: The function runs the guard as a direct child (no command substitution) and trusts only kernel-owned exit status (0=current, 10=pending, other=failure). This avoids shell parser truncation and same-UID result file forgery.
  • Impact: Correct design — exit-code-only protocol prevents shell interpolation and result file tampering.
  • Recommended action: VERIFIED — implementation uses direct child process, no command substitution, only trusts exit status. Test 'runs startup-owned MCP inspection as a direct child' covers parent PID verification.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read agents/hermes/start.sh lines 280-340 for inspect_hermes_mcp_integrity function — confirms no command substitution, uses exit status only
  • Missing regression test: test/hermes-mcp-integrity-state.test.ts 'runs startup-owned MCP inspection as a direct child' covers parent PID verification
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read agents/hermes/start.sh lines 280-340 for inspect_hermes_mcp_integrity function — confirms no command substitution, uses exit status only.
  • Evidence: start.sh lines 280-340 show direct execution with exit-code protocol

PRA-23 Resolve/justify — _parse_config_hash called during inspect_managed_config — verify TOCTOU protection

  • Location: agents/hermes/mcp-config-transaction.py:542
  • Category: security
  • Problem: inspect_managed_config calls guard.inspect_mcp_integrity_snapshot (which calls _parse_config_hash internally), then parses config_text, then calls assert_mcp_integrity_snapshot_current which reopens all paths and validates inode/content metadata hasn't changed.
  • Impact: TOCTOU protection is correctly implemented — snapshot authentication → parse → revalidate before reporting match.
  • Recommended action: VERIFIED — assert_mcp_integrity_snapshot_current called after parsing config_text. Test 'refuses diverged root anchors and config races after integrity verification' covers this.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read agents/hermes/mcp-config-transaction.py lines 500-570 — inspect_managed_config calls assert_mcp_integrity_snapshot_current after parsing
  • Missing regression test: test/hermes-mcp-integrity-state.test.ts 'refuses diverged root anchors and config races after integrity verification' covers this
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read agents/hermes/mcp-config-transaction.py lines 500-570 — inspect_managed_config calls assert_mcp_integrity_snapshot_current after parsing.
  • Evidence: mcp-config-transaction.py lines 500-570 show the TOCTOU contract

PRA-25 Resolve/justify — Verify reload convergence tests cover new MCP hash state transitions

  • Location: test/hermes-mcp-reload-convergence.test.ts:1
  • Category: tests
  • Problem: The new mcp_transition modes in refresh_hashes (preserve, intend, rollback, apply) should be exercised by hermes-mcp-reload-convergence.test.ts. Need to confirm all four transitions are covered.
  • Impact: If transitions aren't tested, a regression in one mode (e.g., rollback) could go undetected.
  • Recommended action: Check hermes-mcp-reload-convergence.test.ts for mcp_transition coverage. Add tests for any missing modes.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read test/hermes-mcp-reload-convergence.test.ts for mcp_transition coverage
  • Missing regression test: May need additional tests for new mcp_transition modes if not covered
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read test/hermes-mcp-reload-convergence.test.ts for mcp_transition coverage.
  • Evidence: refresh_hashes signature changed to accept mcp_transition parameter with four modes

💡 In-scope improvements

These are lower-risk, not throwaway. Prefer fixing them in this PR when they are local to changed code; defer only with rationale or a linked follow-up.

PRA-16 Improvement — Extract enforceHermesSecretBoundaryOnRunningGateway, recoverMessagingHostForward, recoverDeclaredAgentForwardPorts into separate modules

  • Location: src/lib/actions/sandbox/process-recovery.ts:1
  • Category: architecture
  • Problem: Three functions in process-recovery.ts (9 lines changed in this PR) could be extracted to separate modules for better separation of concerns. Not blocking since changes are localized to MCP integration.
  • Impact: Technical debt — large monolith file with mixed concerns.
  • Suggested action: Track as technical debt; extract when these functions are reused or modified. Not blocking for this PR.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Read src/lib/actions/sandbox/process-recovery.ts for the three functions — they are 9 lines changed in this PR
  • Missing regression test: No test gap; this is a refactor suggestion
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: process-recovery.ts is 993 lines; PR changes only 9 lines in MCP integration area

PRA-17 Improvement — build-mcp-digest.py reuses guard's canonical MCP function — good pattern

  • Location: agents/hermes/build-mcp-digest.py:1
  • Category: architecture
  • Problem: New build-mcp-digest.py loads the runtime guard module and calls _canonical_mcp_servers_digest directly, ensuring build-time and runtime canonicalization cannot drift. This is the correct pattern for alignment.
  • Impact: Positive — prevents seal drift between image build and runtime verification.
  • Suggested action: No change needed. Follow this pattern for other build-time/runtime verification alignments.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Read agents/hermes/build-mcp-digest.py — loads guard via importlib and calls _canonical_mcp_servers_digest
  • Missing regression test: test/hermes-mcp-integrity-state.test.ts 'uses the runtime canonicalizer for the build-time MCP seal' covers this
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: build-mcp-digest.py:30-35 loads guard and calls canonicalizer

PRA-18 Improvement — Compatibility proof for OpenShell 0.0.72 split topology documented

  • Location: agents/hermes/runtime-config-guard.py:579
  • Category: correctness
  • Problem: The non-root lifecycle check is documented with why OpenShell 0.0.72 supports both topologies but exposes no attested same-UID capability. Removal condition: security: verify runtime OpenShell version against credential boundary manifest #6256.
  • Impact: Documentation ensures future maintainers understand the workaround boundary.
  • Suggested action: Verify comment completeness. No change needed if complete.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Check agents/hermes/runtime-config-guard.py lines 579-650 for OpenShell 0.0.72 compatibility comment
  • Missing regression test: Covered by hermes-mcp-config-transaction.test.ts legacy topology rejection
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: runtime-config-guard.py lines 579-650 contain compatibility proof comment

PRA-19 Improvement — Rollback 'restored/failed-candidate' state documented with removal condition

PRA-20 Improvement — os.access best-effort probe correctly acknowledged with atomic write as real authority

  • Location: agents/hermes/runtime-config-guard.py:1376
  • Category: architecture
  • Problem: The compat_commit_required logic acknowledges os.access as best-effort only, using atomic write outcome as real authority.
  • Impact: Correctly prevents false negatives from os.access while maintaining compatibility with old locked images.
  • Suggested action: Verify comment acknowledges os.access as best-effort. No change needed if complete.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Check agents/hermes/runtime-config-guard.py compat_commit_required logic for comment
  • Missing regression test: Covered by hermes-mcp-integrity-state.test.ts 'uses the atomic write outcome for compat applied-state commits'
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: runtime-config-guard.py lines 1376-1385 show compat_commit_required with comment

PRA-24 Improvement — connect.ts net-negative delta (-35 lines) — good simplification

  • Location: src/lib/actions/sandbox/connect.ts:1
  • Category: correctness
  • Problem: connect.ts reduced from 1137 to 1102 lines. Net reduction suggests dead code removal or consolidation without behavior change.
  • Impact: Positive — smaller attack surface, less maintenance burden.
  • Suggested action: No action needed. Existing connect tests should cover any behavior changes.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Git diff shows connect.ts reduced from 1137 to 1102 lines
  • Missing regression test: Existing connect tests should cover any behavior changes
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: Diff stat shows connect.ts -35 lines net
Test follow-ups to resolve or justify

If these cover changed behavior, prefer adding them in this PR; otherwise state why existing coverage is enough or link the follow-up.

  • PRA-T1 Runtime validation — Mock _parse_config_hash in non-root reconciliation and assert called with expected config_path/env_path (PRA-2). Runtime/sandbox/infrastructure paths need behavioral runtime validation: agents/hermes/Dockerfile, agents/hermes/build-mcp-digest.py, agents/hermes/mcp-config-transaction.py, agents/hermes/runtime-config-guard.py, agents/hermes/start.sh, scripts/gateway-control.sh, scripts/lib/gateway-supervisor.sh, scripts/update-hermes-agent.sh. New test files provide excellent unit coverage for MCP integrity state machine, rollback, auxiliary retry, non-root reconciliation, but 5 blocker test gaps remain.
  • PRA-T2 Runtime validation — it.each over caller types for mcp-bridge-recovery with mocked inspect contracts (recovery/restart/add/remove/gateway-restart) (PRA-3). Runtime/sandbox/infrastructure paths need behavioral runtime validation: agents/hermes/Dockerfile, agents/hermes/build-mcp-digest.py, agents/hermes/mcp-config-transaction.py, agents/hermes/runtime-config-guard.py, agents/hermes/start.sh, scripts/gateway-control.sh, scripts/lib/gateway-supervisor.sh, scripts/update-hermes-agent.sh. New test files provide excellent unit coverage for MCP integrity state machine, rollback, auxiliary retry, non-root reconciliation, but 5 blocker test gaps remain.
  • PRA-T3 Runtime validation — Credential manifest loads from source-checkout only; dual-path version mismatch fails; dual-path same version uses first-found (PRA-6). Runtime/sandbox/infrastructure paths need behavioral runtime validation: agents/hermes/Dockerfile, agents/hermes/build-mcp-digest.py, agents/hermes/mcp-config-transaction.py, agents/hermes/runtime-config-guard.py, agents/hermes/start.sh, scripts/gateway-control.sh, scripts/lib/gateway-supervisor.sh, scripts/update-hermes-agent.sh. New test files provide excellent unit coverage for MCP integrity state machine, rollback, auxiliary retry, non-root reconciliation, but 5 blocker test gaps remain.
  • PRA-T4 Runtime validation — Add MCP server → verify integrity state becomes pending → restart gateway → verify current → remove MCP server → verify pending → restart gateway → verify current (PRA-7). Runtime/sandbox/infrastructure paths need behavioral runtime validation: agents/hermes/Dockerfile, agents/hermes/build-mcp-digest.py, agents/hermes/mcp-config-transaction.py, agents/hermes/runtime-config-guard.py, agents/hermes/start.sh, scripts/gateway-control.sh, scripts/lib/gateway-supervisor.sh, scripts/update-hermes-agent.sh. New test files provide excellent unit coverage for MCP integrity state machine, rollback, auxiliary retry, non-root reconciliation, but 5 blocker test gaps remain.
  • PRA-T5 Runtime validation — Inspect action with manifest only in source-checkout layout (PRA-20). Runtime/sandbox/infrastructure paths need behavioral runtime validation: agents/hermes/Dockerfile, agents/hermes/build-mcp-digest.py, agents/hermes/mcp-config-transaction.py, agents/hermes/runtime-config-guard.py, agents/hermes/start.sh, scripts/gateway-control.sh, scripts/lib/gateway-supervisor.sh, scripts/update-hermes-agent.sh. New test files provide excellent unit coverage for MCP integrity state machine, rollback, auxiliary retry, non-root reconciliation, but 5 blocker test gaps remain.
  • PRA-T6 Missing test for _parse_config_hash usage in non-root reconciliation — Add test in hermes-mcp-integrity-state.test.ts that mocks runtime-config-guard.py, calls _reconcile_nonroot_startup_api_key_hash with controlled inputs, and asserts _parse_config_hash was invoked with expected config_path and env_path, returning expected McpHashState.
  • PRA-T7 mcp-bridge-recovery tests lack caller-specific parameterized coverage — Add it.each parameterized tests in mcp-bridge-recovery.test.ts exercising both functions with mocked inspect functions matching each caller's contract, verifying correct output structure for recovery vs restart vs add vs remove vs gateway-restart.
  • PRA-T8 Missing full rollback transition test (rollback → healthy reload → current/current) — Add test in hermes-mcp-integrity-state.test.ts exercising complete rollback flow: pending → restore config → rollback transition → verify state='pending' with intended=restored/applied=failed-candidate → simulate healthy reload → call commit-mcp-applied → verify current/current.
Since last review details

Current findings, using the urgency labels above:

PRA-1 Resolve/justify — Source-of-truth review needed: agents/hermes/mcp-config-transaction.py:_load_credential_boundary_manifest (line 39)

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as needs_followup.
  • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
  • Recommended action: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Missing regression test: hermes-mcp-credential-boundary-manifest.test.ts covers missing/wrong-version/invalid keys but NOT dual-path precedence or source-checkout-only (PRA-6 gap)
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Evidence: mcp-config-transaction.py lines 39-80 show manifest loading with updated comment including OpenShell 0.0.72 limitation

PRA-2 Required — McpIntegritySnapshot.config_text leaks in default dataclass repr

  • Location: agents/hermes/runtime-config-guard.py:245
  • Category: security
  • Problem: The dataclass field `config_text` was not marked `repr=False`, causing authenticated config bytes (which can include credentials) to appear in `repr(snapshot)` and potentially leak into logs.
  • Impact: Credential leakage if any code logs or prints McpIntegritySnapshot instances during debugging or error handling.
  • Required action: FIXED — field(repr=False) added on config_text. Verify test 'omits authenticated config bytes from integrity snapshot representations' passes.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check agents/hermes/runtime-config-guard.py line 245 for field(repr=False) on config_text; run test/hermes-mcp-integrity-state.test.ts 'omits authenticated config bytes from integrity snapshot representations'
  • Missing regression test: Already covered by hermes-mcp-integrity-state.test.ts test 'omits authenticated config bytes from integrity snapshot representations' which asserts repr does not contain config_text field or secret value
  • Done when: The required change is committed and verification passes: Check agents/hermes/runtime-config-guard.py line 245 for field(repr=False) on config_text; run test/hermes-mcp-integrity-state.test.ts 'omits authenticated config bytes from integrity snapshot representations'.
  • Evidence: agents/hermes/runtime-config-guard.py:245 shows config_text: str = field(repr=False); test verifies JSON output contains contains_config_field: false

PRA-3 Required — Missing test for _parse_config_hash usage in non-root reconciliation

  • Location: test/hermes-mcp-integrity-state.test.ts:1
  • Category: tests
  • Problem: The non-root reconciliation path (_reconcile_nonroot_startup_api_key_hash) calls _parse_config_hash twice (strict + actual) with a re-read between. No test mocks this function to verify it's invoked with correct config_path and env_path arguments returning expected McpHashState.
  • Impact: TOCTOU race between the two _parse_config_hash calls could allow config/env drift to be blessed if the race is not caught by the re-read verification. Without a mock test, the double-parse contract is unverified.
  • Required action: Add test in hermes-mcp-integrity-state.test.ts that mocks runtime-config-guard.py, calls _reconcile_nonroot_startup_api_key_hash with controlled inputs, and asserts _parse_config_hash was invoked with expected config_path and env_path, returning expected McpHashState.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Search test/hermes-nonroot-strict-hash-reconciliation.test.ts for _parse_config_hash mock/verification — currently absent
  • Missing regression test: New test needed: mock _parse_config_hash in non-root reconciliation path and assert it's called with correct arguments
  • Done when: The required change is committed and verification passes: Search test/hermes-nonroot-strict-hash-reconciliation.test.ts for _parse_config_hash mock/verification — currently absent.
  • Evidence: runtime-config-guard.py:1672-1678 shows double _parse_config_hash call with re-read between; no existing test mocks this function

PRA-4 Required — mcp-bridge-recovery tests lack caller-specific parameterized coverage

  • Location: src/lib/actions/sandbox/mcp-bridge-recovery.test.ts:1
  • Category: tests
  • Problem: The module exports inspectHermesMcpReconciliationRefusal and processRecoveryMcpReconciliationRefusal. Tests only cover 3 basic cases (match, sanitize, map). No parameterized tests over caller types (recovery vs restart vs add vs remove vs gateway-restart) with their distinct inspect contracts.
  • Impact: Different callers may pass different reconciliation result shapes; without caller-specific tests, a contract mismatch in one path (e.g., gateway-restart vs recovery) could go undetected.
  • Required action: Add it.each parameterized tests in mcp-bridge-recovery.test.ts exercising both functions with mocked inspect functions matching each caller's contract, verifying correct output structure for recovery vs restart vs add vs remove vs gateway-restart.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Read src/lib/actions/sandbox/mcp-bridge-recovery.test.ts — only 3 basic tests exist, no it.each parameterization over caller types
  • Missing regression test: Parameterized test matrix covering: recovery, restart, add, remove, gateway-restart callers with their distinct inspect contracts
  • Done when: The required change is committed and verification passes: Read src/lib/actions/sandbox/mcp-bridge-recovery.test.ts — only 3 basic tests exist, no it.each parameterization over caller types.
  • Evidence: mcp-bridge-recovery.ts exports two functions used by different callers; test file has only 3 basic tests

PRA-5 Resolve/justify — Missing full rollback transition test (rollback → healthy reload → current/current)

  • Location: test/hermes-mcp-integrity-state.test.ts:1
  • Category: tests
  • Problem: The rollback state machine transitions: pending (intended!=applied) → restore config → rollback transition (intended=restored/applied=failed-candidate) → healthy old-config reload → commit-mcp-applied → current/current. No test exercises this full cycle in hermes-mcp-integrity-state.test.ts.
  • Impact: Rollback path could have a gap where the second healthy reload doesn't properly advance applied state, leaving the system stuck in pending.
  • Recommended action: Add test in hermes-mcp-integrity-state.test.ts exercising complete rollback flow: pending → restore config → rollback transition → verify state='pending' with intended=restored/applied=failed-candidate → simulate healthy reload → call commit-mcp-applied → verify current/current.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: test/hermes-mcp-rollback-pending.test.ts covers rollback flow but not the full commit-mcp-applied transition in integrity-state test file
  • Missing regression test: Full lifecycle test in hermes-mcp-integrity-state.test.ts covering rollback → reload → commit-mcp-applied
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: test/hermes-mcp-rollback-pending.test.ts covers rollback flow but not the full commit-mcp-applied transition in integrity-state test file.
  • Evidence: hermes-mcp-rollback-pending.test.ts proves rollback state machine but not the commit-mcp-applied step in integrity-state context

PRA-6 Resolve/justify — Missing McpIntegritySnapshot __repr__ redaction test

  • Location: test/hermes-mcp-integrity-state.test.ts:1
  • Category: tests
  • Problem: Test already exists and passes — 'omits authenticated config bytes from integrity snapshot representations' verifies repr does not contain config_text field or secret value.
  • Impact: None — already covered.
  • Recommended action: Verify test passes; no new test needed.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Run test/hermes-mcp-integrity-state.test.ts and verify the repr test passes
  • Missing regression test: Already covered by existing test in hermes-mcp-integrity-state.test.ts
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Run test/hermes-mcp-integrity-state.test.ts and verify the repr test passes.
  • Evidence: test/hermes-mcp-integrity-state.test.ts lines 40-80: 'omits authenticated config bytes from integrity snapshot representations' test

PRA-7 Required — Credential manifest test missing source-checkout layout fallback and version mismatch coverage

  • Location: test/hermes-mcp-credential-boundary-manifest.test.ts:1
  • Category: tests
  • Problem: The manifest loader tries two paths: installed location (beside helper) and source-checkout layout (parents[2]/src/lib/actions/sandbox/...). Tests only cover: missing manifest, wrong version (0.0.73), missing keys. No tests for: (1) manifest only in source-checkout path loads correctly; (2) both paths present with different versions — strict version check fails; (3) both paths present with same version — first-found precedence.
  • Impact: If the installed manifest is corrupted/missing but source-checkout is valid, the transaction could fail incorrectly. If both exist with version mismatch, the wrong manifest could be loaded silently.
  • Required action: Add three tests: (1) manifest only in source-checkout path loads correctly; (2) both paths present with different versions — verify strict version check fails; (3) both paths present with same version — verify first-found precedence.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Read test/hermes-mcp-credential-boundary-manifest.test.ts — 107 lines covering missing/wrong-version/missing-keys only; no dual-path tests
  • Missing regression test: Three new tests covering: source-checkout-only, dual-path version mismatch, dual-path same-version precedence
  • Done when: The required change is committed and verification passes: Read test/hermes-mcp-credential-boundary-manifest.test.ts — 107 lines covering missing/wrong-version/missing-keys only; no dual-path tests.
  • Evidence: mcp-config-transaction.py:55-75 shows two candidate paths; test file only exercises single-path failure modes

PRA-8 Required — Missing add→restart→remove→restart cycle test with integrity verification

  • Location: test/hermes-mcp-integrity-state.test.ts:1
  • Category: acceptance
  • Problem: Issue fix(hermes): reconcile mcp_servers configuration drift at startup #6257 requires coverage for 'additions, removals, restart, resume, and rebuild'. The full lifecycle: add MCP server → verify integrity state becomes pending → restart gateway → verify integrity state becomes current → remove MCP server → verify integrity state becomes pending → restart gateway → verify integrity state becomes current. No test exercises this complete cycle.
  • Impact: Integration gap: individual steps tested but not the end-to-end drift reconciliation across multiple transactions and gateway restarts.
  • Required action: Add test in hermes-mcp-integrity-state.test.ts or hermes-mcp-config-transaction.test.ts: add MCP server → verify integrity state becomes pending → restart gateway → verify integrity state becomes current → remove MCP server → verify integrity state becomes pending → restart gateway → verify integrity state becomes current.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Search test files for add/restart/remove cycle with integrity state verification — not found
  • Missing regression test: Full lifecycle test: add → pending → reload → current → remove → pending → reload → current
  • Done when: The required change is committed and verification passes: Search test files for add/restart/remove cycle with integrity state verification — not found.
  • Evidence: Issue fix(hermes): reconcile mcp_servers configuration drift at startup #6257 acceptance criteria requires 'Successful nemoclaw mcp add|remove operations remain correct after restart, resume, and rebuild'

PRA-9 Resolve/justify — Source-of-truth review needed for double-parse TOCTOU in non-root reconciliation

  • Location: agents/hermes/runtime-config-guard.py:1673
  • Category: architecture
  • Problem: The _reconcile_nonroot_startup_api_key_hash function calls _parse_config_hash twice (strict text + actual text) with a re-read between. Source-of-truth comment must document: (1) Invalid state: config/env race between two _parse_config_hash calls. (2) Source boundary: guard owns parsing and atomic hash advancement. (3) Why not source fix: Hermes/OpenShell exposes no authenticated applied-config digest. (4) Regression test: hermes-nonroot-strict-hash-reconciliation.test.ts covers reconciliation posture. (5) Removal condition: when runtime exposes authenticated applied-config digest (security: verify runtime OpenShell version against credential boundary manifest #6256).
  • Impact: If the source-of-truth comment is incomplete, future maintainers may not understand the TOCTOU boundary or when it can be removed.
  • Recommended action: Verify source-of-truth comment block in _reconcile_nonroot_startup_api_key_hash documents all five elements. Already present in code — confirm completeness.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Check agents/hermes/runtime-config-guard.py lines 1580-1720 for source-of-truth comment block on _reconcile_nonroot_startup_api_key_hash
  • Missing regression test: hermes-nonroot-strict-hash-reconciliation.test.ts covers reconciliation but not the double-parse TOCTOU specifically
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Check agents/hermes/runtime-config-guard.py lines 1580-1720 for source-of-truth comment block on _reconcile_nonroot_startup_api_key_hash.
  • Evidence: runtime-config-guard.py lines 1580-1720 contain the function with source-of-truth comment

PRA-10 Resolve/justify — Source-of-truth review for credential boundary manifest workaround

  • Location: agents/hermes/mcp-config-transaction.py:39
  • Category: architecture
  • Problem: _load_credential_boundary_manifest loads manifest from two deterministic paths. Source-of-truth comment must document: (1) Invalid state: transaction accepts credential against missing/corrupt/wrong-version manifest. (2) Source boundary: NemoClaw owns reviewed manifest at two deterministic paths. (3) Why not source fix: OpenShell v0.0.72 no child-env contract, hides supervisor mount. (4) Regression test: hermes-mcp-credential-boundary-manifest.test.ts covers missing/wrong-version/invalid keys. (5) Removal condition: security: verify runtime OpenShell version against credential boundary manifest #6256 upstream authenticated attestation.
  • Impact: Workaround is documented with removal condition tied to upstream capability.
  • Recommended action: Verify comment completeness. Note: test gap in PRA-6 (dual-path tests missing) weakens regression test claim.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Check agents/hermes/mcp-config-transaction.py lines 39-80 for updated source-of-truth comment block
  • Missing regression test: Test file missing dual-path precedence and source-checkout-only tests (see PRA-6)
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Check agents/hermes/mcp-config-transaction.py lines 39-80 for updated source-of-truth comment block.
  • Evidence: mcp-config-transaction.py lines 39-80 show manifest loading with two candidates

PRA-11 Resolve/justify — Source-of-truth review for non-root lifecycle identity check

  • Location: agents/hermes/runtime-config-guard.py:579
  • Category: architecture
  • Problem: _pinned_process_matches_supervised_nonroot_start prevents legacy topology mutations. Source-of-truth comment must document: (1) Invalid state: sandbox process claims same-UID authority while Hermes runs legacy root-separated topology. (2) Source boundary: OpenShell owns workload topology; NemoClaw owns immutable root-lifecycle marker. (3) Why not source fix: OpenShell 0.0.72 no attested same-UID capability. (4) Regression test: hermes-mcp-config-transaction.test.ts rejects probe/add when root-lifecycle marker identifies legacy topology. (5) Removal condition: security: verify runtime OpenShell version against credential boundary manifest #6256.
  • Impact: Legacy topology mutation prevention is a critical security boundary; documentation must be accurate for future removal.
  • Recommended action: Verify source-of-truth comment in _pinned_process_matches_supervised_nonroot_start documents all five elements.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Check agents/hermes/runtime-config-guard.py lines 579-650 for source-of-truth comment block
  • Missing regression test: hermes-mcp-config-transaction.test.ts should cover legacy topology rejection
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Check agents/hermes/runtime-config-guard.py lines 579-650 for source-of-truth comment block.
  • Evidence: runtime-config-guard.py lines 579-650 contain the function with OpenShell 0.0.72 compatibility comment

PRA-12 Resolve/justify — Source-of-truth review for rollback 'restored/failed-candidate' state

  • Location: agents/hermes/runtime-config-guard.py:1312
  • Category: architecture
  • Problem: refresh_hashes rollback branch sets state to intended=restored/applied=failed-candidate. Source-of-truth comment must document: (1) Invalid state: failed desired-config reload leaves runtime identity uncertain. (2) Source boundary: guard owns hash state machine; transaction helper owns candidate writes/rollback. (3) Why not source fix: Hermes/OpenShell no authenticated applied-config digest. (4) Regression test: hermes-mcp-rollback-pending.test.ts and hermes-mcp-integrity-state.test.ts cover rollback transitions. (5) Removal condition: fix(hermes): reconcile mcp_servers configuration drift at startup #6257 runtime exposes authenticated applied-config digest with transactional rollback.
  • Impact: Rollback state machine correctness depends on this conservative state recording.
  • Recommended action: Verify source-of-truth comment in refresh_hashes rollback branch documents all five elements with fix(hermes): reconcile mcp_servers configuration drift at startup #6257 reference.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Check agents/hermes/runtime-config-guard.py lines 1130-1200 for rollback transition source-of-truth comment
  • Missing regression test: hermes-mcp-rollback-pending.test.ts covers rollback but could use more explicit state verification
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Check agents/hermes/runtime-config-guard.py lines 1130-1200 for rollback transition source-of-truth comment.
  • Evidence: runtime-config-guard.py lines 1130-1200 contain rollback logic with McpHashState

PRA-13 Resolve/justify — Source-of-truth review for os.access best-effort compat hash writability probe

  • Location: agents/hermes/runtime-config-guard.py:1376
  • Category: architecture
  • Problem: refresh_hashes uses os.access for compat hash writability check but acknowledges atomic write as real authority. Source-of-truth comment must document: (1) Invalid state: os.access disagrees with effective write credentials. (2) Source boundary: atomic rename is real authority. (3) Why not source fix: old locked images need best-effort compat anchor. (4) Regression test: hermes-mcp-integrity-state.test.ts 'uses the atomic write outcome for compat applied-state commits'. (5) Removal condition: remove compat fallback when minimum image guarantees strict-only anchor.
  • Impact: Compat hash path could incorrectly allow/deny writes based on os.access false positive/negative; atomic write is the true gate.
  • Recommended action: Verify source-of-truth comment documents os.access as best-effort only, with atomic write as authority.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Check agents/hermes/runtime-config-guard.py lines 1130-1200 for compat_commit_required logic and comment
  • Missing regression test: hermes-mcp-integrity-state.test.ts has 'uses the atomic write outcome for compat applied-state commits' test
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Check agents/hermes/runtime-config-guard.py lines 1130-1200 for compat_commit_required logic and comment.
  • Evidence: runtime-config-guard.py lines 1376-1385 show compat_commit_required logic with comment

PRA-14 Resolve/justify — Source-of-truth review for reload gateway re-kick fallback (socat relay limitation)

  • Location: agents/hermes/mcp-config-transaction.py:1008
  • Category: architecture
  • Problem: reload_gateway re-kicks SIGUSR1 once if gateway doesn't converge, but skips re-kick if observed_phase is 'waiting-for-public-relay-health-on-8642' because managed supervisor owns socat relay. Source-of-truth comment must document: (1) Invalid state: public socat relay not re-established after gateway reload. (2) Source boundary: OpenShell supervisor owns socat relay lifecycle; Hermes gateway cannot repair. (3) Why not source fix: OpenShell v0.0.72 no relay health/repair API to workload. (4) Regression test: hermes-gateway-auxiliary-retry.test.ts covers retry behavior. (5) Removal condition: security: verify runtime OpenShell version against credential boundary manifest #6256 OpenShell exposes authenticated supervisor/runtime attestation with relay health.
  • Impact: Re-kick logic correctly avoids churn but is a workaround for missing upstream capability.
  • Recommended action: Verify source-of-truth comment in reload_gateway re-kick logic documents all five elements.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Check agents/hermes/mcp-config-transaction.py lines 940-1020 for re-kick logic and source-of-truth comment
  • Missing regression test: hermes-gateway-auxiliary-retry.test.ts covers auxiliary retry but not the specific socat relay re-kick limitation
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Check agents/hermes/mcp-config-transaction.py lines 940-1020 for re-kick logic and source-of-truth comment.
  • Evidence: mcp-config-transaction.py lines 940-1020 contain reload_gateway with re_kick_attempted logic

PRA-15 Resolve/justify — Coordinate with authors of PRs #5217, #6292, #5230, #5416 to determine merge order

PRA-16 Improvement — Extract enforceHermesSecretBoundaryOnRunningGateway, recoverMessagingHostForward, recoverDeclaredAgentForwardPorts into separate modules

  • Location: src/lib/actions/sandbox/process-recovery.ts:1
  • Category: architecture
  • Problem: Three functions in process-recovery.ts (9 lines changed in this PR) could be extracted to separate modules for better separation of concerns. Not blocking since changes are localized to MCP integration.
  • Impact: Technical debt — large monolith file with mixed concerns.
  • Suggested action: Track as technical debt; extract when these functions are reused or modified. Not blocking for this PR.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Read src/lib/actions/sandbox/process-recovery.ts for the three functions — they are 9 lines changed in this PR
  • Missing regression test: No test gap; this is a refactor suggestion
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: process-recovery.ts is 993 lines; PR changes only 9 lines in MCP integration area

PRA-17 Improvement — build-mcp-digest.py reuses guard's canonical MCP function — good pattern

  • Location: agents/hermes/build-mcp-digest.py:1
  • Category: architecture
  • Problem: New build-mcp-digest.py loads the runtime guard module and calls _canonical_mcp_servers_digest directly, ensuring build-time and runtime canonicalization cannot drift. This is the correct pattern for alignment.
  • Impact: Positive — prevents seal drift between image build and runtime verification.
  • Suggested action: No change needed. Follow this pattern for other build-time/runtime verification alignments.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Read agents/hermes/build-mcp-digest.py — loads guard via importlib and calls _canonical_mcp_servers_digest
  • Missing regression test: test/hermes-mcp-integrity-state.test.ts 'uses the runtime canonicalizer for the build-time MCP seal' covers this
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: build-mcp-digest.py:30-35 loads guard and calls canonicalizer

PRA-18 Improvement — Compatibility proof for OpenShell 0.0.72 split topology documented

  • Location: agents/hermes/runtime-config-guard.py:579
  • Category: correctness
  • Problem: The non-root lifecycle check is documented with why OpenShell 0.0.72 supports both topologies but exposes no attested same-UID capability. Removal condition: security: verify runtime OpenShell version against credential boundary manifest #6256.
  • Impact: Documentation ensures future maintainers understand the workaround boundary.
  • Suggested action: Verify comment completeness. No change needed if complete.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Check agents/hermes/runtime-config-guard.py lines 579-650 for OpenShell 0.0.72 compatibility comment
  • Missing regression test: Covered by hermes-mcp-config-transaction.test.ts legacy topology rejection
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: runtime-config-guard.py lines 579-650 contain compatibility proof comment

PRA-19 Improvement — Rollback 'restored/failed-candidate' state documented with removal condition

PRA-20 Improvement — os.access best-effort probe correctly acknowledged with atomic write as real authority

  • Location: agents/hermes/runtime-config-guard.py:1376
  • Category: architecture
  • Problem: The compat_commit_required logic acknowledges os.access as best-effort only, using atomic write outcome as real authority.
  • Impact: Correctly prevents false negatives from os.access while maintaining compatibility with old locked images.
  • Suggested action: Verify comment acknowledges os.access as best-effort. No change needed if complete.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Check agents/hermes/runtime-config-guard.py compat_commit_required logic for comment
  • Missing regression test: Covered by hermes-mcp-integrity-state.test.ts 'uses the atomic write outcome for compat applied-state commits'
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: runtime-config-guard.py lines 1376-1385 show compat_commit_required with comment

Workflow run details

This is an automated, non-binding review; it still expects maintainers and agents to respond to each required or warning item. Treat suggestions as current-PR improvements when they touch changed code; defer only with maintainer rationale or a linked follow-up. A human maintainer must make the final merge decision.

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

E2E Advisor Recommendation

Required E2E: mcp-bridge, build-hermes-sandbox-image, gateway-guard-recovery, sandbox-operations, shields-config, hermes-e2e, rebuild-hermes
Optional E2E: mcp-bridge-dev, rebuild-hermes-stale-base, gateway-health-honest

Dispatch hint: mcp-bridge,gateway-guard-recovery,sandbox-operations,shields-config,hermes-e2e,rebuild-hermes

Workflow run

Full advisor summary

E2E Recommendation Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E

  • mcp-bridge (high): Required because this PR changes the MCP bridge host actions, Hermes MCP transaction helper, registry MCP state, credential boundary validation, live Hermes MCP inspection, and add/remove/restart recovery. The existing live mcp-bridge job exercises real OpenShell provider setup, credential placeholders, policy boundaries, Hermes config adapter behavior, and the updated Hermes lifecycle assertions.
  • build-hermes-sandbox-image (high): Required because Dockerfile packaging, installed helper permissions, runtime guard sealing, start.sh, and Hermes secret-boundary entrypoint behavior changed. This job builds the production Hermes image and runs the Hermes sandbox secret-boundary and root-entrypoint smoke live checks against the built image.
  • gateway-guard-recovery (medium): Required because the PR changes gateway-control.sh, gateway-supervisor.sh, process recovery, and gateway restart/reload behavior. This live E2E validates recovery under real sandbox gateway guard conditions rather than only mocked process/unit boundaries.
  • sandbox-operations (high): Required because connect.ts, connect boundary refusal, gateway restart, process recovery, and sandbox lifecycle-adjacent behavior changed. This job covers live sandbox operations including process/gateway lifecycle behavior in a real OpenShell sandbox.
  • shields-config (medium): Required because runtime-config-guard.py changed config hash parsing, MCP intended/applied state, sealed hash generation, shields transition behavior, and descriptor-safe write logic. The shields-config live test is the closest existing end-to-end coverage for real locked/unlocked config mutation boundaries.
  • hermes-e2e (high): Required as a full hosted Hermes assistant smoke because the PR changes Hermes startup, runtime guard, gateway supervisor/reload, and image contents that can affect real assistant user flows beyond the MCP-specific path.
  • rebuild-hermes (high): Required because the PR changes Hermes image packaging and scripts/update-hermes-agent.sh, which can affect deployment/rebuild/update flows. The existing rebuild-hermes E2E validates the real install/rebuild path for a Hermes sandbox.

Optional E2E

  • mcp-bridge-dev (high): Optional compatibility confidence for the same MCP bridge flow against moving OpenShell dev artifacts. Useful because this PR tightens OpenShell child-env/manifest and supervisor-boundary assumptions, but the stable mcp-bridge job should remain the merge-blocking lane.
  • rebuild-hermes-stale-base (high): Optional additional deployment confidence for stale-base Hermes rebuild behavior, because runtime guard hash format and packaged helper layout changed. Run if the PR is expected to support older existing Hermes sandboxes during update/rebuild.
  • gateway-health-honest (low): Optional adjacent confidence for gateway health reporting because the PR changes gateway restart/reload and supervisor paths. It is narrower than gateway-guard-recovery and sandbox-operations, so not the primary required lane.

New E2E recommendations

  • Hermes MCP transaction rollback under real supervisor (high): Existing live mcp-bridge coverage exercises successful add/remove/list/inspect and post-removal restart, while unit tests cover many failure contracts. A dedicated live E2E would close the gap for failed Hermes MCP reload rollback and intended/applied digest recovery under the real OpenShell supervisor, public relay, and Hermes gateway process topology.
    • Suggested test: hermes-mcp-reload-rollback-e2e

Dispatch hint

  • Workflow: .github/workflows/e2e.yaml
  • jobs input: mcp-bridge,gateway-guard-recovery,sandbox-operations,shields-config,hermes-e2e,rebuild-hermes

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

E2E Target Recommendation

Required E2E targets: mcp-bridge, mcp-bridge-dev
Optional E2E targets: None

Dispatch required E2E targets:

  • gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=mcp-bridge
  • gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=mcp-bridge-dev

Workflow run

Full E2E target advisor summary

E2E Target Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E targets

  • mcp-bridge: Focused free-standing E2E job wired for changed live test test/e2e/live/mcp-bridge.test.ts.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=mcp-bridge
  • mcp-bridge-dev: Focused free-standing E2E job wired for changed live test test/e2e/live/mcp-bridge.test.ts.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=mcp-bridge-dev

Optional E2E targets

  • None.

Relevant changed files

  • agents/hermes/Dockerfile
  • agents/hermes/build-mcp-digest.py
  • agents/hermes/mcp-config-transaction.py
  • agents/hermes/runtime-config-guard.py
  • agents/hermes/start.sh
  • scripts/gateway-control.sh
  • scripts/lib/gateway-supervisor.sh
  • scripts/update-hermes-agent.sh
  • src/lib/actions/sandbox/gateway-restart.ts
  • src/lib/actions/sandbox/mcp-bridge-adapter-status.ts
  • src/lib/actions/sandbox/mcp-bridge-add-restart.ts
  • src/lib/actions/sandbox/mcp-bridge-destroy.ts
  • src/lib/actions/sandbox/mcp-bridge-hermes-reconciliation.ts
  • src/lib/actions/sandbox/mcp-bridge-recovery.ts
  • src/lib/actions/sandbox/mcp-bridge-remove.ts
  • src/lib/actions/sandbox/mcp-bridge-restart.ts
  • src/lib/actions/sandbox/mcp-bridge-state.ts
  • src/lib/actions/sandbox/mcp-bridge-status.ts
  • src/lib/actions/sandbox/mcp-bridge-validation.ts
  • src/lib/actions/sandbox/process-recovery.ts
  • src/lib/state/registry-mcp.ts
  • test/e2e/live/mcp-bridge-hermes-lifecycle.ts
  • test/e2e/live/mcp-bridge.test.ts

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor — No blocking findings

Merge posture: No blocking advisor findings
Primary next action: Add or justify PRA-T1 and any related test follow-ups.
Open items: 0 required · 0 warnings · 0 suggestions · 3 test follow-ups
Since last review: 0 prior items resolved · 0 still apply · 0 new items found

Action checklist

  • PRA-T1 Add or justify test follow-up: Runtime validation
  • PRA-T2 Add or justify test follow-up: Runtime validation
  • PRA-T3 Add or justify test follow-up: Runtime validation
Test follow-ups to resolve or justify

If these cover changed behavior, prefer adding them in this PR; otherwise state why existing coverage is enough or link the follow-up.

  • PRA-T1 Runtime validation — Real Hermes startup or resume from a registry containing only a managed removal tombstone plus pending intended/applied MCP metadata converges or fails closed while `nemoclaw <sandbox> mcp list --json` stays empty and emits no credential value.. Static, subprocess, shell-harness, and live Hermes MCP coverage is broad and directly exercises add, restart, rotation, rebuild, removal, rollback, redaction, integrity states, supervisor failures, and reconciliation boundaries. Because this PR changes Docker image sealing, PID1 startup ordering, supervisor relay recovery, rollback, and durable intended/applied MCP state, a few uncommon persisted-state combinations still warrant behavior-specific real-runtime validation.
  • PRA-T2 Runtime validation — Real supervisor-mediated `gateway restart` when MCP integrity is pending before applied-state completion emits no `GATEWAY_PID=` completion marker and the CLI prints MCP restart/rebuild remediation instead of generic launch-failure guidance.. Static, subprocess, shell-harness, and live Hermes MCP coverage is broad and directly exercises add, restart, rotation, rebuild, removal, rollback, redaction, integrity states, supervisor failures, and reconciliation boundaries. Because this PR changes Docker image sealing, PID1 startup ordering, supervisor relay recovery, rollback, and durable intended/applied MCP state, a few uncommon persisted-state combinations still warrant behavior-specific real-runtime validation.
  • PRA-T3 Runtime validation — Real Hermes desired-config MCP reload failure followed by rollback reload failure restores the old config, leaves pending integrity state, and a later real recovery commits old-config applied state without logging the host secret.. Static, subprocess, shell-harness, and live Hermes MCP coverage is broad and directly exercises add, restart, rotation, rebuild, removal, rollback, redaction, integrity states, supervisor failures, and reconciliation boundaries. Because this PR changes Docker image sealing, PID1 startup ordering, supervisor relay recovery, rollback, and durable intended/applied MCP state, a few uncommon persisted-state combinations still warrant behavior-specific real-runtime validation.

Workflow run details

This is an automated, non-binding review; it still expects maintainers and agents to respond to each required or warning item. Treat suggestions as current-PR improvements when they touch changed code; defer only with maintainer rationale or a linked follow-up. A human maintainer must make the final merge decision.

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

Caution

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

⚠️ Outside diff range comments (1)
src/lib/actions/sandbox/mcp-bridge-remove.ts (1)

97-330: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Add the OpenShell runtime-version check before the first provider mutation.

removeMcpBridgeUnlocked mutates providers via detachProvider, detachMissingProviderReference, unregisterAgentAdapter, and deleteProvider, but never calls assertMcpCredentialBoundaryRuntimeVersion(). The shared helpers also don’t enforce it, so mcp remove can act on an unverified OpenShell binary while mcp add and mcp restart fail closed.

🤖 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/actions/sandbox/mcp-bridge-remove.ts` around lines 97 - 330, The
remove path is missing the OpenShell runtime-version gate before any provider
mutation, so `removeMcpBridgeUnlocked` can proceed on an unverified binary while
other MCP lifecycle commands fail closed. Add a call to
`assertMcpCredentialBoundaryRuntimeVersion()` in `removeMcpBridgeUnlocked` after
the preflight checks and before the first provider-affecting action, so it runs
ahead of `detachMissingProviderReference`, `detachProvider`,
`unregisterAgentAdapter`, and `deleteProvider`. Keep the check in the same
guardrail position as the add/restart flow, using the existing helper name to
make the protection consistent across MCP lifecycle commands.
🧹 Nitpick comments (5)
test/mcp-policy-key-ownership.test.ts (1)

11-12: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider extracting the repeated --version stub clause into a shared helper.

The identical if [ "$1" = "--version" ]; then printf '%s\n' 'openshell 0.0.72'; exit 0; fi clause is duplicated across 6 inline-generated openshell stubs in this file. A shared constant/helper (e.g. a function returning this snippet, parameterized by version) would reduce the future maintenance cost of an OpenShell version bump across this file (and its siblings using the same literal).

♻️ Example consolidation
+const OPENSHELL_VERSION_STUB_CLAUSE =
+  `if [ "$1" = "--version" ]; then printf '%s\n' 'openshell 0.0.72'; exit 0; fi`;
+
 fs.writeFileSync(
   path.join(binDir, "openshell"),
   `#!/bin/sh
-if [ "$1" = "--version" ]; then printf '%s\n' 'openshell 0.0.72'; exit 0; fi
+${OPENSHELL_VERSION_STUB_CLAUSE}
 printf '%s\n' "$*" >> ${JSON.stringify(callsPath)}
 ...

Also applies to: 30-30, 80-80, 110-110, 175-175, 291-291, 378-378, 554-554

🤖 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/mcp-policy-key-ownership.test.ts` around lines 11 - 12, The inline
OpenShell stub scripts in this test file repeat the same --version clause, so
extract that snippet into a shared helper or constant and reuse it across the
generated stubs. Update the logic around the openshell fixture generation in
this test (and any sibling test helpers using the same literal) so the version
string is parameterized in one place, making OpenShell version bumps easier to
maintain.
src/lib/actions/sandbox/process-recovery.ts (1)

765-775: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate reconciliation-refusal result construction.

Both branches build an almost identical refusal object (only wasRunning differs). Extracting a small helper would reduce duplication and keep the two call sites from drifting if a field is later added/renamed.

♻️ Proposed fix
+function mcpReconciliationRefusalResult(reconciliation: { detail: string }, wasRunning: boolean) {
+  return {
+    checked: true as const,
+    wasRunning,
+    recovered: false,
+    forwardRecovered: false,
+    mcpReconciliationRefused: true as const,
+    mcpReconciliationReason: reconciliation.detail,
+  };
+}

Then at each call site:

-    const reconciliation = inspectHermesMcpRuntimeIntent(sandboxName);
-    if (!reconciliation.ok) {
-      return {
-        checked: true,
-        wasRunning: true,
-        recovered: false,
-        forwardRecovered: false,
-        mcpReconciliationRefused: true,
-        mcpReconciliationReason: reconciliation.detail,
-      };
-    }
+    const reconciliation = inspectHermesMcpRuntimeIntent(sandboxName);
+    if (!reconciliation.ok) {
+      return mcpReconciliationRefusalResult(reconciliation, true);
+    }

(and false for the not-running/recovered branch at line 927)

Also applies to: 927-937

🤖 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/actions/sandbox/process-recovery.ts` around lines 765 - 775, The
reconciliation refusal return object is duplicated in both branches of
process-recovery.ts, with only wasRunning changing between the call sites.
Extract a small helper near inspectHermesMcpRuntimeIntent/reconciliation
handling that builds the refusal result, and have both branches call it with the
appropriate wasRunning value while keeping checked, recovered, forwardRecovered,
mcpReconciliationRefused, and mcpReconciliationReason aligned in one place.
src/lib/actions/sandbox/connect.ts (1)

240-262: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider consolidating duplicated MCP remediation guidance.

This function's remediation text (mcp restart / rebuild --yes guidance) is near-identical to the text emitted by printGatewayRestartFailure in gateway-restart.ts (lines 189-194) for the same "MCP reconciliation refusal" condition. Extracting a shared helper (e.g. mcpReconciliationRemediationLines(sandboxName)) would keep the two messages from silently diverging as one is edited without the other.

🤖 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/actions/sandbox/connect.ts` around lines 240 - 262, The MCP
reconciliation refusal remediation text is duplicated between
exitOnMcpReconciliationRefusal and the matching gateway restart failure output,
so centralize it in a shared helper to avoid drift. Extract the common “mcp
restart” and “rebuild --yes” guidance into a reusable function such as
mcpReconciliationRemediationLines(sandboxName), then have
exitOnMcpReconciliationRefusal and printGatewayRestartFailure call that helper
for their console output.
src/lib/actions/sandbox/gateway-restart.ts (2)

189-194: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicated remediation text vs. connect.ts.

Same duplication concern noted in connect.ts's exitOnMcpReconciliationRefusal (lines 254-259): the mcp restart / rebuild --yes guidance strings are duplicated here with slightly different wording ("restore managed MCP state" vs. "restore the managed MCP configuration, then retry"). Worth a single shared helper for consistency.

🤖 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/actions/sandbox/gateway-restart.ts` around lines 189 - 194, The MCP
refusal remediation text is duplicated between gateway-restart and connect, so
consolidate it into one shared helper for consistency. Move the `mcp restart`
and `rebuild --yes` guidance used in `gateway-restart.ts` and `connect.ts` into
a common function, then have the existing flow in
`exitOnMcpReconciliationRefusal` and the gateway restart path call that helper
so both sites emit the same wording.

81-83: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Import HermesMcpReconciliationResult here instead of re-declaring the union. The inline copy widens state to string, so it can drift from the bridge result without a type error.

🤖 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/actions/sandbox/gateway-restart.ts` around lines 81 - 83, The
inspectHermesMcpRuntimeIntent return type is being re-declared inline and widens
state to string, which can drift from the bridge result. Import and reuse
HermesMcpReconciliationResult in gateway-restart.ts instead of the local union
so the type stays aligned with the source definition and any future changes are
caught automatically.

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 `@src/lib/actions/sandbox/mcp-bridge-validation.ts`:
- Around line 58-100: The fail-closed error in
assertMcpCredentialBoundaryRuntimeVersion is too generic when OpenShell version
validation fails. Update credentialBoundaryVersionError so the message includes
a short remediation hint for users, especially on version mismatch or
unparseable output, and keep the hint actionable (for example, pin/install the
expected OpenShell version) while preserving the existing expected/actual
detail.

In `@test/hermes-mcp-integrity-state.test.ts`:
- Around line 20-27: The startup parsing helper in runHermesRootMcpStartup adds
a new if-statement that trips the guardrail. Refactor it to follow the same
pattern used by extractShellFunctionFromSource in the sibling integrity test:
assert the match result directly with the test framework instead of branching
and throwing, while keeping the existing startupBlock extraction logic and error
message context.

In `@test/hermes-start-config-integrity.test.ts`:
- Line 40: Add a negative test for the MCP-integrity gate in
hermes-start-config-integrity.test.ts: the current root-mode stub for
inspect_hermes_mcp_integrity() always returns 0, so it only verifies the success
path. Introduce a failing stub case for inspect_hermes_mcp_integrity() that
returns a nonzero exit status and assert that the restart logic emits
HERMES_RESTART_FAILURE_CODE=mcp-integrity, alongside the existing happy-path
coverage.

---

Outside diff comments:
In `@src/lib/actions/sandbox/mcp-bridge-remove.ts`:
- Around line 97-330: The remove path is missing the OpenShell runtime-version
gate before any provider mutation, so `removeMcpBridgeUnlocked` can proceed on
an unverified binary while other MCP lifecycle commands fail closed. Add a call
to `assertMcpCredentialBoundaryRuntimeVersion()` in `removeMcpBridgeUnlocked`
after the preflight checks and before the first provider-affecting action, so it
runs ahead of `detachMissingProviderReference`, `detachProvider`,
`unregisterAgentAdapter`, and `deleteProvider`. Keep the check in the same
guardrail position as the add/restart flow, using the existing helper name to
make the protection consistent across MCP lifecycle commands.

---

Nitpick comments:
In `@src/lib/actions/sandbox/connect.ts`:
- Around line 240-262: The MCP reconciliation refusal remediation text is
duplicated between exitOnMcpReconciliationRefusal and the matching gateway
restart failure output, so centralize it in a shared helper to avoid drift.
Extract the common “mcp restart” and “rebuild --yes” guidance into a reusable
function such as mcpReconciliationRemediationLines(sandboxName), then have
exitOnMcpReconciliationRefusal and printGatewayRestartFailure call that helper
for their console output.

In `@src/lib/actions/sandbox/gateway-restart.ts`:
- Around line 189-194: The MCP refusal remediation text is duplicated between
gateway-restart and connect, so consolidate it into one shared helper for
consistency. Move the `mcp restart` and `rebuild --yes` guidance used in
`gateway-restart.ts` and `connect.ts` into a common function, then have the
existing flow in `exitOnMcpReconciliationRefusal` and the gateway restart path
call that helper so both sites emit the same wording.
- Around line 81-83: The inspectHermesMcpRuntimeIntent return type is being
re-declared inline and widens state to string, which can drift from the bridge
result. Import and reuse HermesMcpReconciliationResult in gateway-restart.ts
instead of the local union so the type stays aligned with the source definition
and any future changes are caught automatically.

In `@src/lib/actions/sandbox/process-recovery.ts`:
- Around line 765-775: The reconciliation refusal return object is duplicated in
both branches of process-recovery.ts, with only wasRunning changing between the
call sites. Extract a small helper near
inspectHermesMcpRuntimeIntent/reconciliation handling that builds the refusal
result, and have both branches call it with the appropriate wasRunning value
while keeping checked, recovered, forwardRecovered, mcpReconciliationRefused,
and mcpReconciliationReason aligned in one place.

In `@test/mcp-policy-key-ownership.test.ts`:
- Around line 11-12: The inline OpenShell stub scripts in this test file repeat
the same --version clause, so extract that snippet into a shared helper or
constant and reuse it across the generated stubs. Update the logic around the
openshell fixture generation in this test (and any sibling test helpers using
the same literal) so the version string is parameterized in one place, making
OpenShell version bumps easier to maintain.
🪄 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: dd4c30eb-9393-423a-967d-19180f0233fb

📥 Commits

Reviewing files that changed from the base of the PR and between abc5855 and aa7461e.

📒 Files selected for processing (37)
  • agents/hermes/Dockerfile
  • agents/hermes/mcp-config-transaction.py
  • agents/hermes/runtime-config-guard.py
  • agents/hermes/start.sh
  • src/lib/actions/sandbox/connect-flow-hermes-boundary.test.ts
  • src/lib/actions/sandbox/connect.ts
  • src/lib/actions/sandbox/gateway-restart.test.ts
  • src/lib/actions/sandbox/gateway-restart.ts
  • src/lib/actions/sandbox/mcp-bridge-adapter-status.ts
  • src/lib/actions/sandbox/mcp-bridge-add-restart.ts
  • src/lib/actions/sandbox/mcp-bridge-destroy.ts
  • src/lib/actions/sandbox/mcp-bridge-hermes-reconciliation.test.ts
  • src/lib/actions/sandbox/mcp-bridge-hermes-reconciliation.ts
  • src/lib/actions/sandbox/mcp-bridge-input-validation.test.ts
  • src/lib/actions/sandbox/mcp-bridge-remove.ts
  • src/lib/actions/sandbox/mcp-bridge-restart.ts
  • src/lib/actions/sandbox/mcp-bridge-state.ts
  • src/lib/actions/sandbox/mcp-bridge-status-removal.test.ts
  • src/lib/actions/sandbox/mcp-bridge-status-state.test.ts
  • src/lib/actions/sandbox/mcp-bridge-status.ts
  • src/lib/actions/sandbox/mcp-bridge-validation.ts
  • src/lib/actions/sandbox/process-recovery.ts
  • src/lib/state/registry-mcp.ts
  • test/deepagents-mcp-legacy-lifecycle.test.ts
  • test/fixtures/openshell-v0.0.72
  • test/hermes-doctor-config-hash.test.ts
  • test/hermes-mcp-config-transaction.test.ts
  • test/hermes-mcp-integrity-state.test.ts
  • test/hermes-nonroot-strict-hash-reconciliation.test.ts
  • test/hermes-runtime-config-guard.test.ts
  • test/hermes-start-config-integrity.test.ts
  • test/mcp-add-crash-consistency.test.ts
  • test/mcp-destroy-lifecycle.test.ts
  • test/mcp-policy-key-ownership.test.ts
  • test/mcp-restart-policy-order.test.ts
  • test/registry.test.ts
  • test/support/connect-flow-test-harness.ts

Comment thread src/lib/actions/sandbox/mcp-bridge-validation.ts
Comment thread test/hermes-mcp-integrity-state.test.ts Outdated
Comment thread test/hermes-start-config-integrity.test.ts Outdated
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@ericksoa

ericksoa commented Jul 4, 2026

Copy link
Copy Markdown
Contributor Author

Addressed the advisor findings at 107cef1bd.

Implemented:

  • GPT PRA-1 / T1-T2 / acceptance clauses: extended the existing real Hermes MCP live lane through removal and a supervisor-mediated gateway restart. It now proves the durable removal tombstone, healthy restart, post-restart mcp list reconciliation, current intended/applied integrity, effective server absence, continued route denial, and no old/rotated secret residue. The gated live lane was not run locally; its E2E-support contracts pass 18/18 and CI remains authoritative.
  • GPT PRA-2 / T3: centralized sanitizeHermesMcpReconciliationDetail. Helper stdout/stderr/errors, thrown failures, connect refusal, and gateway-restart refusal now strip ANSI/C0/C1 controls and forged line breaks, redact known bridge values, and apply broad token redaction. Focused consumer and helper tests cover both returned and thrown paths.
  • Nemotron PRA-3/PRA-4/PRA-T1/PRA-T6: added an explicit present[server] allowlist matching the managed Hermes projection and a regression rejecting command, transport, and arbitrary extra fields.
  • Nemotron PRA-5/PRA-6/PRA-T2/PRA-T7/PRA-T8: added a connect-flow regression where gateway health has already normalized to running (HTTP 200/authenticated 401 semantics) but MCP integrity is pending; connect fails closed with sanitized restart/rebuild guidance before opening the session.
  • Nemotron PRA-1/PRA-9/PRA-11: documented the invalid state, source boundary, asynchronous reload constraint, regression evidence, removal condition, and the single-snapshot plus pre/post-write stability checks that prevent apply-time drift from being blessed.
  • Nemotron PRA-2/PRA-10: tightened the manifest removal condition to require authenticated live-supervisor attestation binding both runtime version and the child-environment contract.

Resolved with existing focused evidence:

  • Nemotron PRA-T3: single-snapshot integrity and compare-and-swap regressions cover config mutation races (hermes-mcp-integrity-state, hermes-runtime-config-guard, and non-root strict-hash reconciliation).
  • Nemotron PRA-T4: the OpenShell version suite covers exact match, mismatch, missing binary, non-zero exit, and unparseable output without reflecting command output.
  • Nemotron PRA-T5: non-MCP writes are bound to the persisted intended MCP digest; pending/current, unrelated-drift, malformed-state, and rollback regressions exercise that trust anchor.

Justified without additional refactoring:

  • Nemotron PRA-7/PRA-8: the reconciliation logic and sanitization now live in the dedicated mcp-bridge-hermes-reconciliation module. The remaining connect.ts and process-recovery.ts code is intentionally thin lifecycle orchestration at the exact refusal/recovery ordering points; extracting those calls again would split the trust-boundary ordering without removing duplicated logic.

Latest local proof: 106/106 focused CLI/integration/E2E-support tests, both TypeScript checks, Ruff/Python compile, Biome/lint, shell syntax, source-shape, test-size, conditional scan, diff checks, and secret scanning.

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@ericksoa

ericksoa commented Jul 4, 2026

Copy link
Copy Markdown
Contributor Author

Follow-up for the refreshed advisor findings, addressed at d2b027ef8:

  • GPT PRA-2 / PRA-T1 / PRA-T7: inspect_managed_config() now compares host intent against the exact one-read config text authenticated by the persisted hash and canonical MCP digest. The opaque snapshot token binds config, env, and the selected hash anchors; privileged inspection also requires strict and compatibility anchors to be byte-identical. Every captured pathname is reopened and its snapshot revalidated immediately before success. The regression proves both diverged-anchor refusal and config mutation after authentication refusal.
  • GPT PRA-1: the snapshot token has the requested structured invalid-state, source-boundary, source-fix constraint, regression, and removal-condition documentation.
  • GPT PRA-T2-T6: pending/current transitions, add/remove, restart/rebuild, removal after a real gateway restart, route denial, and secret absence are covered by the focused and live-lane tests described above; the snapshot-race regression closes the false-positive reconciliation path those clauses identified.

Nemotron’s remaining items are improvements rather than blockers; disposition:

  • PRA-T1/PRA-T4: there is no public nemoclaw mcp inspect --payload surface. The payload is an internal host-generated projection, so the direct helper-boundary test is the end-to-end validation for malformed command/transport fields; the live lane exercises the canonical host producer.
  • PRA-T2/PRA-T5: gateway-restart refusal and sanitization are covered at the restart consumer boundary, while the new authenticated-snapshot race test exercises real config drift. Combining those into another config-mutating restart fixture would duplicate both boundaries without increasing the live guarantee.
  • PRA-T3/PRA-T6: test/hermes-mcp-integrity-state.test.ts already executes the root startup block with health passing and commit_hermes_mcp_applied_if_pending returning failure; it asserts fail-closed stop, non-zero exit, and no permission restore/startup continuation.
  • PRA-1/PRA-2: reconciliation/sanitization already reside in the dedicated mcp-bridge-hermes-reconciliation module. Remaining connect/process-recovery calls are thin lifecycle ordering points, so another extraction would split trust-boundary sequencing without deduplicating logic.
  • PRA-3: gateway-restart.test.ts remains below the advisor’s stated 600-line split threshold; the MCP case can move if that file grows past it.

Focused snapshot verification: 57/57 tests plus Ruff, Python compile, Biome, source-shape, test-size, and diff checks. All commits on the PR are GitHub Verified.

@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 current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/e2e/live/mcp-bridge-hermes-lifecycle.ts`:
- Around line 111-125: The inspect payload in the hermes lifecycle test
hardcodes the absent server name instead of using SERVER_NAME, which can make
the assertion drift from the rest of the test. Update the payload built in the
sandbox.execShell call inside the mcp-bridge-hermes-lifecycle test to reference
SERVER_NAME consistently, matching the tombstone check already used earlier in
the same test, so the inspect step always targets the intended server name.
🪄 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: f4c8fb74-9055-466a-a8cd-7d8637a7c53f

📥 Commits

Reviewing files that changed from the base of the PR and between aa7461e and 107cef1.

📒 Files selected for processing (11)
  • agents/hermes/mcp-config-transaction.py
  • agents/hermes/runtime-config-guard.py
  • src/lib/actions/sandbox/connect-flow-hermes-boundary.test.ts
  • src/lib/actions/sandbox/connect.ts
  • src/lib/actions/sandbox/gateway-restart.test.ts
  • src/lib/actions/sandbox/gateway-restart.ts
  • src/lib/actions/sandbox/mcp-bridge-hermes-reconciliation.test.ts
  • src/lib/actions/sandbox/mcp-bridge-hermes-reconciliation.ts
  • test/e2e/live/mcp-bridge-hermes-lifecycle.ts
  • test/e2e/live/mcp-bridge.test.ts
  • test/hermes-mcp-integrity-state.test.ts
🚧 Files skipped from review as they are similar to previous changes (6)
  • src/lib/actions/sandbox/connect.ts
  • src/lib/actions/sandbox/gateway-restart.ts
  • src/lib/actions/sandbox/mcp-bridge-hermes-reconciliation.ts
  • test/hermes-mcp-integrity-state.test.ts
  • agents/hermes/mcp-config-transaction.py
  • agents/hermes/runtime-config-guard.py

Comment thread test/e2e/live/mcp-bridge-hermes-lifecycle.ts
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@ericksoa

ericksoa commented Jul 4, 2026

Copy link
Copy Markdown
Contributor Author

Completed Nemotron’s three explicit proof requests at 2cf484a86:

  • PRA-1 / T1 / T4: the real Hermes live lane now invokes the packaged in-sandbox hermes-mcp-config-transaction.py inspect boundary through SandboxClient with forbidden command and transport fields. It requires non-zero rejection with the exact sanitized error and proves no fixture secret, ANSI sequence, CR, or forged-line marker escapes. There is intentionally no invented public nemoclaw mcp inspect command.
  • PRA-2 / T2 / T5: new focused gateway-restart-hermes-drift.test.ts builds real config/env/strict/compat anchors, mutates the config after hashing, invokes the real Python inspection path, then proves restartSandboxGatewayWithDeps reports sanitized MCP reconciliation refusal, preserves the drifted evidence, and performs no post-reconciliation forward mutation.
  • PRA-3 / T3 / T6: the applied-state commit failure proof is now a separately named test. Its trace explicitly shows gateway health before the failed commit, fail-closed stop, exit 1 plus HERMES_MCP_APPLIED_COMMIT_FAILED, and no permission restore or startup continuation.

Remaining resolve/justify items:

  • PRA-4/PRA-5: core reconciliation and sanitization are already centralized in mcp-bridge-hermes-reconciliation; connect and process recovery retain only the thin, ordering-sensitive orchestration calls.
  • PRA-6: the gateway restart test file remains below the stated 600-line split threshold; the new real-drift case is already isolated in its own focused file.
  • PRA-7: upstream runtime/child-env attestation is tracked by security: verify runtime OpenShell version against credential boundary manifest #6256; the code’s removal condition now requires authenticated live-supervisor attestation before the local manifest boundary can be removed.
  • PRA-8: the existing PID 1 compatibility path is outside this MCP change and remains covered by the runtime guard topology tests; it is removable only when legacy/direct-PID1 image support is retired.
  • PRA-9: the authenticated-config-read gap and removal condition are tracked in fix(hermes): reconcile mcp_servers configuration drift at startup #6257 and directly beside McpIntegritySnapshot; removal requires a Hermes authenticated applied-config digest/API.

Validation: combined new tests 10/10; full E2E-support suite 674/674; both TypeScript checks, Biome, test-size, source-shape, conditional-growth, diff checks, hooks, and secret scan pass. The live cloud/OpenShell lane remains gated and was not run locally. The new commit is GitHub Verified.

@ericksoa

ericksoa commented Jul 4, 2026

Copy link
Copy Markdown
Contributor Author

Final Nemotron disposition on 2cf484a86:

  • PRA-7 is already implemented exactly as requested. test/hermes-mcp-integrity-state.test.ts lines 281-294 is a separately named negative test. Its expected trace is health → auxiliaries → failed applied commit → fail-closed stop; it asserts exit 1, HERMES_MCP_APPLIED_COMMIT_FAILED, and no restore/startup continuation. This is not deferred.
  • PRA-5’s stated threshold is not met. gateway-restart.test.ts is 490 lines, below the advisor’s 600-line threshold, and the new real-drift coverage was deliberately placed in the focused gateway-restart-hermes-drift.test.ts file. Splitting unrelated existing tests now would be churn rather than risk reduction.
  • PRA-4/PRA-6 are intentionally justified, not ignored. Reconciliation payload construction, execution, sanitization, mismatch classification, and assertion live in the dedicated mcp-bridge-hermes-reconciliation module. The remaining additions in connect.ts and process-recovery.ts are thin, ordering-sensitive lifecycle calls. Moving those calls would split the trust-boundary sequence without deduplicating behavior and would broaden this follow-up beyond security: verify runtime OpenShell version against credential boundary manifest #6256/fix(hermes): reconcile mcp_servers configuration drift at startup #6257.
  • PRA-1/PRA-3/PRA-8/PRA-10 have structured invalidState, sourceBoundary, whyNotSourceFix, regressionTest, and removalCondition documentation beside the code. security: verify runtime OpenShell version against credential boundary manifest #6256 tracks authenticated OpenShell runtime/child-env attestation; fix(hermes): reconcile mcp_servers configuration drift at startup #6257 tracks the Hermes applied-config attestation gap.
  • PRA-2/PRA-9 describe an existing PID 1 compatibility boundary outside this MCP change. Its source-boundary rationale and topology regressions remain intact; removal is tied to retirement of legacy/direct-PID1 image support, not to this PR.
  • PRA-T1-T5/T7-T8 are covered by the changed live Hermes lane, the real config-drift restart test, the authenticated-snapshot race test, and the focused connect/restart sanitization tests. CI confirms the new CLI test is discovered; the live helper is called by mcp-bridge.test.ts.

The GPT-5.5 advisor now reports merge_as_is, zero required items, zero warnings, zero suggestions, and zero test follow-ups. I am leaving the remaining Nemotron monolith refactors out of scope; a human maintainer can override that disposition if they want a separate structural follow-up.

@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

♻️ Duplicate comments (1)
test/e2e/live/mcp-bridge-hermes-lifecycle.ts (1)

156-163: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Still hardcodes "fake" instead of SERVER_NAME.

This was flagged in a prior review round and remains unaddressed. The inspect payload should reference SERVER_NAME like the tombstone check at Line 131, so it can't silently drift from the rest of the test if the constant's value changes.

🛠️ Proposed fix
     trustedSandboxShellScript(
       [
         "set -eu",
-        '/usr/local/lib/nemoclaw/hermes-mcp-config-transaction.py inspect --payload \'{"present":{},"absent":["fake"]}\'',
+        `/usr/local/lib/nemoclaw/hermes-mcp-config-transaction.py inspect --payload '${JSON.stringify(
+          { present: {}, absent: [SERVER_NAME] },
+        )}'`,
       ].join("\n"),
     ),
🤖 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/e2e/live/mcp-bridge-hermes-lifecycle.ts` around lines 156 - 163, The
inspect payload in the hermes lifecycle test is still hardcoding the absent
server name as "fake" instead of using SERVER_NAME. Update the payload passed to
hermes-mcp-config-transaction.py inspect in the test around the
sandbox.execShell call so it references SERVER_NAME consistently, matching the
tombstone check logic and keeping the test aligned if the constant changes.
🤖 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 `@src/lib/actions/sandbox/gateway-restart-hermes-drift.test.ts`:
- Around line 116-150: The test is mocking inspectHermesMcpRuntimeIntent, so it
only verifies refusal and sanitization for an arbitrary failed reconciliation
result rather than the real drift-detection path. Update
gateway-restart-hermes-drift.test.ts by either wiring the actual
inspectHermesMcpRuntimeIntent implementation into deps (so the python-backed
detection is exercised end-to-end) or by renaming/refocusing the test to
explicitly cover only restartSandboxGatewayWithDeps refusal/sanitization
behavior; keep the earlier drift-detection assertions separate from this mocked
branch.

---

Duplicate comments:
In `@test/e2e/live/mcp-bridge-hermes-lifecycle.ts`:
- Around line 156-163: The inspect payload in the hermes lifecycle test is still
hardcoding the absent server name as "fake" instead of using SERVER_NAME. Update
the payload passed to hermes-mcp-config-transaction.py inspect in the test
around the sandbox.execShell call so it references SERVER_NAME consistently,
matching the tombstone check logic and keeping the test aligned if the constant
changes.
🪄 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: 10258781-4870-4a69-8944-22dd84248ab0

📥 Commits

Reviewing files that changed from the base of the PR and between d2b027e and 2cf484a.

📒 Files selected for processing (4)
  • src/lib/actions/sandbox/gateway-restart-hermes-drift.test.ts
  • test/e2e/live/mcp-bridge-hermes-lifecycle.ts
  • test/e2e/live/mcp-bridge.test.ts
  • test/hermes-mcp-integrity-state.test.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • test/e2e/live/mcp-bridge.test.ts
  • test/hermes-mcp-integrity-state.test.ts

Comment thread src/lib/actions/sandbox/gateway-restart-hermes-drift.test.ts
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@ericksoa

ericksoa commented Jul 4, 2026

Copy link
Copy Markdown
Contributor Author

Latest-head advisor disposition for 7bd10987c:

GPT runtime follow-ups

  • PRA-T1: the Hermes live lane proves the registered bridge survives a full sandbox rebuild, performs authenticated MCP discovery, remains present in effective Hermes config, and completes a real tool call after rebuild (lines 1310-1331).
  • PRA-T2: the same lane removes the bridge, proves provider/config/policy absence, then performs a real supervisor-mediated gateway restart and re-proves effective absence, route denial, and no credential residue (lines 1332-1359). Pending/cold-start state transitions are covered by the focused start.sh integrity-state integration tests; the live lane covers the real lifecycle boundary without adding a test-only runtime fault hook.
  • PRA-T3: the named negative integration test drives gateway launch -> health -> auxiliaries -> failed applied-state commit and requires the exact gateway to stop fail-closed, exit 1, emit HERMES_MCP_APPLIED_COMMIT_FAILED, and skip startup success (lines 281-294). The real live lane covers the healthy restart/rebuild path; inducing this failure in a packaged sandbox would require a production fault-injection surface, which is not warranted.

The advisor-selected mcp-bridge and mcp-bridge-dev runtime targets were dispatched on this exact head: https://github.com/NVIDIA/NemoClaw/actions/runs/28690073365

Nemotron scope disposition

  • PRA-4 / PRA-T5: already implemented by the explicit negative test linked above. The advisor's requested static search is limited to gateway-restart*.test.ts, while the actual applied-state commit and fail-closed stop execute in agents/hermes/start.sh; the integration test extracts and executes that exact production block.
  • PRA-5 through PRA-7: the static OpenShell manifest, PID 1 exclusion, and authenticated snapshot token each now document the invalid state, source boundary, reason a source fix is unavailable, regression proof, and removal condition. They are accepted compatibility/security boundaries, not untracked workarounds.
  • PRA-1 and PRA-3 justified: the shared inspection and sanitization implementations are already centralized in mcp-bridge-hermes-reconciliation.ts. The remaining connect refusal functions are connect-specific UX/exit handling, and the recovery call sites are orchestration points rather than duplicated reconciliation implementations. Pure extraction now would add release-scope churn without changing or strengthening a boundary.
  • PRA-2 justified: gateway-restart.test.ts is 490 lines, below the advisor's stated 600-line threshold; the new real-boundary drift proof is already isolated in gateway-restart-hermes-drift.test.ts.
  • PRA-8 justified: _parse_two_file_hash is the intentional digest-only compatibility API for its caller while _parse_config_hash still validates the mandatory MCP state line. Removing four lines would not change behavior or reduce risk.
  • PRA-9 justified: HTTP 401 is only process-health evidence; mandatory MCP reconciliation still runs before connect/restart success. The real-drift test proves post-health reconciliation refuses the operation before any forward or messaging mutation (lines 23-156).

All required PR checks are green on this head. GPT recommends merge_as_is; Nemotron is non-binding, and its remaining items are the structural/static-search points justified above rather than uncovered behavioral failures.

@github-actions

github-actions Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

E2E Target Results — ❌ Some jobs failed

Run: 28690073365
Workflow ref: fix/mcp-v075-followups
Requested targets: (default — all supported)
Requested jobs: mcp-bridge,mcp-bridge-dev
Summary: 0 passed, 2 failed, 0 cancelled, 0 skipped

Job Result
mcp-bridge ❌ failure
mcp-bridge-dev ❌ failure

Failed jobs: mcp-bridge, mcp-bridge-dev. Check run artifacts for logs.

@ericksoa

ericksoa commented Jul 4, 2026

Copy link
Copy Markdown
Contributor Author

Runtime dispatch disposition for E2E run 28690073365 on exact head 7bd10987c:

  • Stable mcp-bridge: MCP behavior passed for OpenClaw and Deep Agents on OpenShell 0.0.72. Hermes was infrastructure-blocked during onboarding, before any MCP operation: mutable hermes-sandbox-base:latest resolved to sha256:83e72e6c…, while this checkout trusts sha256:8dad3b989…, so ensureAgentBaseImage correctly refused the untracked image. The release-pinned base-image gap is already tracked by Publish release-pinned sandbox base image refs #4052.
  • Dev mcp-bridge-dev: expected fail-closed version evidence. The moving dev channel installed OpenShell 0.0.77-dev.1+gf852d07b; both OpenClaw and Deep Agents rejected provider mutation with sanitized expected 0.0.72, actual 0.0.77-dev.1+gf852d07b. Hermes independently hit the same pre-MCP base-image drift.
  • Credential artifact scans passed for all 351 stable artifacts and all 122 dev artifacts.

No PR code change or blind rerun is warranted: the stable non-Hermes runtime paths validate the MCP implementation, the dev rejection is the intended #6256 security behavior, and Hermes was prevented from reaching the changed code by the known mutable-base infrastructure issue. All required PR checks remain green; GPT's latest-head posture remains merge_as_is.

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@ericksoa

ericksoa commented Jul 4, 2026

Copy link
Copy Markdown
Contributor Author

CodeRabbit follow-up completed at c76a74181:

  • Added actionable OpenShell 0.0.72 remediation and asserted it in the mismatch regression.
  • Added the missing root-mode MCP-integrity failure case and proved HERMES_RESTART_FAILURE_CODE=mcp-integrity.
  • Split the gateway drift test into an honest real-Python read-only drift proof and a separately named injected restart-refusal/sanitization proof.
  • Centralized connect/restart MCP reconciliation remediation text.
  • Reused HermesMcpReconciliationResult instead of widening a duplicate union.
  • Centralized the duplicated process-recovery refusal result.
  • Centralized the six repeated OpenShell version clauses in the policy ownership fixture.
  • Audited the suggested remove-path runtime-version gate and intentionally did not add it: remove only revokes credential access through detach/delete. Gating teardown on a version mismatch would strand the credential cleanup that operators need to recover. Credential creation and reattachment remain fail-closed; the API comment now states this boundary explicitly.

Validation: 104/104 consolidated focused tests, both TypeScript checks, Biome, source-shape/test-size/conditional guardrails, commit hooks, push hooks, and git diff --check pass. All three live CodeRabbit threads have commit-level replies and are resolved.

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@github-actions

github-actions Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

E2E Target Results — ❌ Some jobs failed

Run: 28714607119
Workflow ref: fix/mcp-v075-followups
Requested targets: (default — all supported)
Requested jobs: mcp-bridge
Summary: 0 passed, 1 failed, 0 cancelled, 0 skipped

Job Result
mcp-bridge ❌ failure

Failed jobs: mcp-bridge. Check run artifacts for logs.

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@github-actions

github-actions Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

E2E Target Results — ❌ Some jobs failed

Run: 28715858064
Workflow ref: fix/mcp-v075-followups
Requested targets: (default — all supported)
Requested jobs: mcp-bridge
Summary: 0 passed, 1 failed, 0 cancelled, 0 skipped

Job Result
mcp-bridge ❌ failure

Failed jobs: mcp-bridge. Check run artifacts for logs.

ericksoa added 2 commits July 5, 2026 21:16
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

E2E Target Results — ✅ All requested jobs passed

Run: 28767576983
Workflow ref: fix/mcp-v075-followups
Requested targets: (default — all supported)
Requested jobs: gateway-guard-recovery
Summary: 1 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
gateway-guard-recovery ✅ success

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

E2E Target Results — ✅ All requested jobs passed

Run: 28767576010
Workflow ref: fix/mcp-v075-followups
Requested targets: (default — all supported)
Requested jobs: hermes-e2e
Summary: 1 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
hermes-e2e ✅ success

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

E2E Target Results — ⚠️ Run cancelled — no signal

Run: 28767440873
Workflow ref: fix/mcp-v075-followups
Requested targets: (default — all supported)
Requested jobs: mcp-bridge
Summary: 0 passed, 0 failed, 1 cancelled, 0 skipped

Job Result
mcp-bridge ⚠️ cancelled

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

E2E Target Results — ✅ All requested jobs passed

Run: 28767850811
Workflow ref: fix/mcp-v075-followups
Requested targets: (default — all supported)
Requested jobs: gateway-guard-recovery
Summary: 1 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
gateway-guard-recovery ✅ success

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

E2E Target Results — ✅ All requested jobs passed

Run: 28767849656
Workflow ref: fix/mcp-v075-followups
Requested targets: (default — all supported)
Requested jobs: hermes-e2e
Summary: 1 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
hermes-e2e ✅ success

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

E2E Target Results — ✅ All requested jobs passed

Run: 28767848673
Workflow ref: fix/mcp-v075-followups
Requested targets: (default — all supported)
Requested jobs: mcp-bridge
Summary: 1 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
mcp-bridge ✅ success

@ericksoa

ericksoa commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

Final-head advisor disposition — 44195b56c096ae3ee50f465de9c983f705eda031

This supersedes the earlier head-specific disposition. The exact-head GPT advisor recommends merge_as_is with no blocking findings. Nemotron completed successfully, but its merge_after_fixes summary mechanically retains items that its own detailed findings mark fixed or that are based on nonexistent/implementation-detail contracts:

Final evidence:

  • Ordinary exact-head checks: 39 passed, 2 intentional skips, 0 pending/failing; the unrelated package-contract require-cache flake passed on clean rerun attempt 2.
  • Required exact-head runtime proof: MCP bridge, Hermes E2E, gateway guard recovery, and production images/downstream E2E all passed. The MCP credential scan passed across 489 artifact files.
  • All 22 commits are GitHub Verified and DCO-signed; all 8 review threads are resolved; the branch has a clean current-main synthetic merge.

@cv, this is ready for independent review and approval. This disposition is not a self-approval and does not authorize an admin merge.

@cv
cv merged commit f0d2549 into main Jul 6, 2026
293 of 295 checks passed
@cv
cv deleted the fix/mcp-v075-followups branch July 6, 2026 05:07
cv pushed a commit that referenced this pull request Jul 7, 2026
## Summary
Add the v0.0.75 release-notes entry for the release train, summarizing
the user-facing fixes merged since v0.0.74. Release-prep docs for the
`nemoclaw-maintainer-cut-release-tag` gate.

## Related Issue
Release prep for v0.0.75. Remove this section if none.

## Changes
- `docs/about/release-notes.mdx`: add the `## v0.0.75` section (themed
intro + grouped bullets with source-page links), matching the existing
v0.0.74 style.

### Source summary (doc-impacting PRs → doc page)
- #6370 -> `docs/about/release-notes.mdx`: prepared-backup recovery
restores gateway state and defers the live route check to onboarding, so
upgrade recovery no longer fails on an unset gateway route.
- #6305 -> `docs/about/release-notes.mdx`: in-place upgrades recover
gateway-orphaned sandboxes.
- #6332 -> `docs/about/release-notes.mdx`: same-name `--fresh`
re-onboard preserves fresh LangChain Deep Agents Code routing.
- #6335 -> `docs/about/release-notes.mdx`: custom Anthropic-compatible
inference uses the OpenAI frontend.
- #6298 -> `docs/about/release-notes.mdx`: OpenAI-only agents keep the
`/v1` base URL on Anthropic-compatible endpoints.
- #6304 -> `docs/about/release-notes.mdx`: local docker-driver gateway
credentials no longer expire.
- #6261 -> `docs/about/release-notes.mdx`: Hermes runtime and managed
MCP state reconcile after a runtime change.
- #6318 -> `docs/about/release-notes.mdx`: Hermes installs accept a
pinned base platform digest.
- #6291 -> `docs/about/release-notes.mdx`: OpenClaw local CLI pairing
restores its previous connection path.

Test-performance, CI, and chore commits since v0.0.74 are excluded as
non-user-facing.

## Type of Change
- [x] Doc only (prose changes, no code sample modifications)

## Quality Gates
- [x] Tests not applicable — justification: documentation-only change
(release notes prose).
- [x] Docs updated for user-facing behavior changes

## Verification
- [x] PR description includes the DCO sign-off declaration and every
commit appears as `Verified` in GitHub
- [x] `npm run docs` builds without warnings introduced by this change —
command/result: "Found 0 errors and 2 warnings" (the 2 warnings
pre-exist this change).
- [x] Doc pages follow the style guide (active voice, no numbered/colon
titles, correct NVIDIA/NemoClaw/OpenShell capitalization; skip-terms
avoided).
- [x] No secrets, API keys, or credentials committed

---
Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>


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

* **Documentation**
* Added a new **v0.0.75** section to the release notes, highlighting
improved sandbox upgrade hardening and prepared-backup recovery, updated
inference routing for Anthropic-compatible endpoints, longer-lasting
local gateway credential handling, and restored CLI pairing reconnection
without re-pairing. Also includes cross-links to related NemoClaw CLI
and documentation pages.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Hadar301 pushed a commit to Hadar301/NemoClaw-OpenShift that referenced this pull request Jul 12, 2026
## Summary

Reconcile Hermes MCP intent with the gateway state across transactions
and lifecycle recovery, and bind OpenShell credential-boundary
validation to the exact host CLI version before provider mutations. This
closes the configuration-drift gap from NVIDIA#6257 while implementing the
enforceable host-side portion of NVIDIA#6256 without adding a misleading
in-image OpenShell stub.

## Related Issue

Closes NVIDIA#6257
Addresses NVIDIA#6256

## Changes

- add an exact, uncached `openshell --version` gate before MCP
provider/credential mutations; missing, failed, malformed, and
mismatched probes fail closed without exposing command output
- persist a canonical credential-safe MCP digest as `intended` and
`applied`, commit applied state only after a healthy gateway reload, and
restore both config and integrity snapshots on rollback
- reconcile Hermes startup, restart, resume, rebuild, status, and
recovery against persisted managed intent, including removal tombstones,
with actionable fail-closed guidance
- prevent generic config writes from changing `mcp_servers`, reject
malformed or stale integrity state, and avoid blessing concurrent config
drift during applied-state commits
- preserve the canonical MCP state marker when shields transitions
regenerate strict and compatibility hashes, and keep supervisor/API-key
test fixtures on the same three-line contract
- strictly allowlist credential-safe inspection fields and sanitize all
sandbox-derived reconciliation diagnostics before connect/restart output
- add focused regression coverage for version probes,
additions/removals, pending and malformed state, root/non-root startup,
rollback, registry reconciliation, and destroy recovery
- extend the live Hermes MCP lane through removal plus a real gateway
restart, proving the tombstone persists, effective config stays absent,
the retired route remains denied, and credentials do not leak
- preserve exact supervised API/dashboard relays across managed Hermes
gateway replacements, retrying public health without churning
structurally proven listeners
- exclude authenticated Hermes config bytes from dataclass
representations and cover the redaction

### NVIDIA#6256 runtime-boundary note

OpenShell 0.0.72 intentionally does not expose the supervisor identity
mount to workload children, and the Hermes workload image does not
contain the host OpenShell CLI. Running `openshell --version` in the
Python helper would therefore either fail every real transaction or
attest an unrelated in-image stub rather than the supervisor enforcing
credentials. This change verifies the selected host CLI immediately
before every provider mutation and retains exact manifest/policy
validation in Python. NVIDIA#6256 remains open for an upstream supervisor
capability/version attestation that Hermes startup can verify honestly.

## Type of Change

- [x] 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

- [x] Tests added or updated for changed behavior
- [ ] Existing tests cover changed behavior — justification:
- [ ] Tests not applicable — justification:
- [ ] Docs updated for user-facing behavior changes
- [x] Docs not applicable — justification: no new command, option, or
operator-managed configuration; failures include inline restart/rebuild
recovery guidance
- [x] Sensitive paths changed (security, policy, credentials, preflight,
onboarding, inference, runner, sandbox, or messaging)
- [x] Sensitive-path review completed or maintainer-approved waiver
recorded — reviewer/approval link/justification: reviewed the credential
boundary, transactional ordering, rollback, stale-state, redaction,
tombstone, and concurrent-drift paths with focused fail-closed
regressions; maintainer approval remains required before merge
- [ ] 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] Git hooks passed during commit and push, or `npx prek run
--from-ref main --to-ref HEAD` passes
- [x] Targeted tests pass for changed behavior
- [ ] Full `npm test` passes (broad runtime changes only)
- [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)
- [ ] 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)

Local verification on final head
`44195b56c096ae3ee50f465de9c983f705eda031` passed 190 focused
security/lifecycle tests across 10 files, both TypeScript typechecks,
the CLI/plugin builds, Python compile/Ruff, ShellCheck/Biome,
source-shape, test-size, title, conditional, diff, secret-scan, and
commit/push hooks.

All ordinary required GitHub checks are green on the final head: 39
passed, 2 intentional skips, and 0 pending/failing. The one unrelated
package-contract require-cache flake passed on [clean rerun attempt
2](https://github.com/NVIDIA/NemoClaw/actions/runs/28767840291/attempts/2),
with no source change. The exact-head [GPT
advisor](NVIDIA#6261 (comment))
recommends `merge_as_is`; CodeRabbit is green, and all 8 review threads
are resolved. The remaining stale/false-premise Nemotron items are
addressed in the [final-head
disposition](NVIDIA#6261 (comment)).

All advisor-required exact-head runtime proof passed: [stable MCP
bridge](https://github.com/NVIDIA/NemoClaw/actions/runs/28767848673),
[Hermes
E2E](https://github.com/NVIDIA/NemoClaw/actions/runs/28767849656),
[gateway guard
recovery](https://github.com/NVIDIA/NemoClaw/actions/runs/28767850811),
and [production sandbox images plus downstream
E2E](https://github.com/NVIDIA/NemoClaw/actions/runs/28767851667).
Stable MCP passed the real OpenClaw, DeepAgents, and Hermes
add/restart/rebuild/remove/restart lifecycles, including adjacent Hermes
restart and credential rotation; the credential scan passed across 489
artifact files.

All 22 PR commits are GitHub `Verified` and DCO-signed. The head is
mergeable with a clean current-`main` synthetic merge. The moving
OpenShell-dev lane remains optional and is not merge evidence; the
supported credential boundary is the exact stable OpenShell 0.0.72
contract.

I certify that this contribution is made under the Developer Certificate
of Origin.

---
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>


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

* **New Features**
* Added Hermes MCP integrity tracking with intended/applied state
transitions, plus CLI commands to inspect integrity and commit
“applied”.
* Added Hermes MCP runtime reconciliation remediation with fail-closed
behavior during sandbox connect and gateway recovery/restart.
* Persist and reconcile managed MCP server names across
add/remove/destroy/restore.

* **Bug Fixes**
* Strengthened startup/restart verification to block drift and pending
reconciliation, with improved rollback/reload verification behavior.
* Improved failure classification/remediation messaging for MCP
integrity and reconciliation-refusal scenarios.

* **Tests**
* Expanded coverage for Hermes MCP integrity, drift, reconciliation
refusal, lifecycle flows, and config hash sealing.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Hadar301 pushed a commit to Hadar301/NemoClaw-OpenShift that referenced this pull request Jul 12, 2026
## Summary
Add the v0.0.75 release-notes entry for the release train, summarizing
the user-facing fixes merged since v0.0.74. Release-prep docs for the
`nemoclaw-maintainer-cut-release-tag` gate.

## Related Issue
Release prep for v0.0.75. Remove this section if none.

## Changes
- `docs/about/release-notes.mdx`: add the `## v0.0.75` section (themed
intro + grouped bullets with source-page links), matching the existing
v0.0.74 style.

### Source summary (doc-impacting PRs → doc page)
- NVIDIA#6370 -> `docs/about/release-notes.mdx`: prepared-backup recovery
restores gateway state and defers the live route check to onboarding, so
upgrade recovery no longer fails on an unset gateway route.
- NVIDIA#6305 -> `docs/about/release-notes.mdx`: in-place upgrades recover
gateway-orphaned sandboxes.
- NVIDIA#6332 -> `docs/about/release-notes.mdx`: same-name `--fresh`
re-onboard preserves fresh LangChain Deep Agents Code routing.
- NVIDIA#6335 -> `docs/about/release-notes.mdx`: custom Anthropic-compatible
inference uses the OpenAI frontend.
- NVIDIA#6298 -> `docs/about/release-notes.mdx`: OpenAI-only agents keep the
`/v1` base URL on Anthropic-compatible endpoints.
- NVIDIA#6304 -> `docs/about/release-notes.mdx`: local docker-driver gateway
credentials no longer expire.
- NVIDIA#6261 -> `docs/about/release-notes.mdx`: Hermes runtime and managed
MCP state reconcile after a runtime change.
- NVIDIA#6318 -> `docs/about/release-notes.mdx`: Hermes installs accept a
pinned base platform digest.
- NVIDIA#6291 -> `docs/about/release-notes.mdx`: OpenClaw local CLI pairing
restores its previous connection path.

Test-performance, CI, and chore commits since v0.0.74 are excluded as
non-user-facing.

## Type of Change
- [x] Doc only (prose changes, no code sample modifications)

## Quality Gates
- [x] Tests not applicable — justification: documentation-only change
(release notes prose).
- [x] Docs updated for user-facing behavior changes

## Verification
- [x] PR description includes the DCO sign-off declaration and every
commit appears as `Verified` in GitHub
- [x] `npm run docs` builds without warnings introduced by this change —
command/result: "Found 0 errors and 2 warnings" (the 2 warnings
pre-exist this change).
- [x] Doc pages follow the style guide (active voice, no numbered/colon
titles, correct NVIDIA/NemoClaw/OpenShell capitalization; skip-terms
avoided).
- [x] No secrets, API keys, or credentials committed

---
Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>


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

* **Documentation**
* Added a new **v0.0.75** section to the release notes, highlighting
improved sandbox upgrade hardening and prepared-backup recovery, updated
inference routing for Anthropic-compatible endpoints, longer-lasting
local gateway credential handling, and restored CLI pairing reconnection
without re-pairing. Also includes cross-links to related NemoClaw CLI
and documentation pages.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: sandbox OpenShell sandbox lifecycle, runtime, config, or recovery area: security Security controls, permissions, secrets, or hardening integration: hermes Hermes integration behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(hermes): reconcile mcp_servers configuration drift at startup

5 participants