Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
135 commits
Select commit Hold shift + click to select a range
ca3edf4
refactor(mcp): make lifecycle source-backed
ericksoa Sep 7, 2026
ba2580a
merge: resolve conflicts with main
github-actions[bot] Sep 7, 2026
fd5f600
fix(mcp): harden stateless lifecycle cutover
ericksoa Sep 7, 2026
a98afee
fix(rebuild): freeze pre-delete policy bytes
ericksoa Sep 7, 2026
4ec373b
fix(mcp): preserve source handoff across rebuild retry
ericksoa Sep 7, 2026
1ac94bf
fix(mcp): complete stateless recovery boundaries
ericksoa Sep 7, 2026
33d2764
fix(mcp): defer rebuild runtime authority
ericksoa Sep 7, 2026
4df2f94
fix(e2e): exercise OpenClaw MCP tool catalog
ericksoa Sep 7, 2026
948fc63
fix(e2e): parse OpenClaw tool result envelopes
ericksoa Sep 7, 2026
79fc3e5
fix(e2e): drive OpenClaw catalog by tool identity
ericksoa Sep 7, 2026
cebca34
fix(e2e): accept OpenClaw rewritten tool call ids
ericksoa Sep 7, 2026
007b7b2
merge(main): integrate source-backed denied tool policies
ericksoa Sep 7, 2026
2986508
merge(main): integrate provider lifecycle changes
ericksoa Sep 7, 2026
4e1955f
test(e2e): register MCP rewrite probe parity
ericksoa Sep 7, 2026
4e23e5e
fix(e2e): match native OpenClaw MCP tool names
ericksoa Sep 7, 2026
72237df
fix(mcp): activate native OpenClaw config changes
ericksoa Sep 7, 2026
8deb1c2
fix(mcp): preserve OpenClaw config integrity
ericksoa Sep 7, 2026
db91bc7
fix(e2e): use native OpenClaw tool catalog contract
ericksoa Sep 7, 2026
fb92063
fix(mcp): enable native OpenClaw MCP tools
ericksoa Sep 8, 2026
1d153a1
merge(main): integrate native skill lifecycle
ericksoa Sep 8, 2026
be07fda
fix(e2e): isolate MCP policy denial traffic
ericksoa Sep 8, 2026
1865167
fix(mcp): admit native OpenClaw MCP tools
ericksoa Sep 8, 2026
694dd71
fix(mcp): select OpenClaw streamable HTTP transport
ericksoa Sep 8, 2026
a92a14f
test(e2e): isolate OpenClaw MCP lifecycle sessions
ericksoa Sep 8, 2026
33ffbd7
merge: resolve conflicts with main
github-actions[bot] Sep 8, 2026
8abc158
fix(mcp): make recovery source-derived
ericksoa Sep 8, 2026
ffff6f7
Merge remote-tracking branch 'origin/refactor/stateless-mcp-11134' in…
ericksoa Sep 8, 2026
2c3d238
test(destroy): isolate host inference fixtures from MCP
ericksoa Sep 8, 2026
4ea535b
fix(destroy): tolerate unavailable MCP source inventory
ericksoa Sep 8, 2026
5ac6c49
test(destroy): assert explicit MCP source handoff
ericksoa Sep 8, 2026
f87cd78
fix(destroy): avoid empty MCP runtime pinning
ericksoa Sep 8, 2026
b5d0ea7
test(e2e): accept source-derived MCP add retries
ericksoa Sep 8, 2026
a0963db
fix(mcp): replay committed pins during add recovery
ericksoa Sep 8, 2026
35aca90
test(mcp): qualify conservative credential rotation
ericksoa Sep 8, 2026
1bacf21
fix(policy): admit OpenShell read-only endpoint access
ericksoa Sep 8, 2026
7f76676
fix(mcp): preserve fresh rebuild source handoff
ericksoa Sep 8, 2026
2775bce
merge: resolve conflicts with main
github-actions[bot] Sep 8, 2026
884a489
fix(mcp): close source-backed E2E gaps
ericksoa Sep 8, 2026
431f4e1
Merge remote-tracking branch 'origin/main' into refactor/stateless-mc…
ericksoa Sep 8, 2026
0e82550
fix(mcp): synchronize retired hash helper consumers
ericksoa Sep 8, 2026
1084070
fix(openclaw): settle empty MCP tool catalog
ericksoa Sep 8, 2026
36c84e3
Merge remote-tracking branch 'origin/main' into refactor/stateless-mc…
ericksoa Sep 8, 2026
e81ecbd
fix(mcp): reuse destroy source snapshot
ericksoa Sep 8, 2026
4a9f32d
Merge remote-tracking branch 'refs/remotes/origin/main' into refactor…
ericksoa Sep 8, 2026
efa2d82
fix(mcp): stabilize source-backed lifecycle retries
ericksoa Sep 8, 2026
59336d2
Merge remote-tracking branch 'origin/main' into refactor/stateless-mc…
ericksoa Sep 8, 2026
bdb0c24
test(mcp): align snapshot mocks with source inspection
ericksoa Sep 9, 2026
1a33361
merge(main): resolve stateless MCP lifecycle test conflict
ericksoa Sep 9, 2026
36fcc0d
fix(deps): update js-yaml to 4.3.2
ericksoa Sep 9, 2026
17ce50a
merge: resolve conflicts with main
github-actions[bot] Sep 9, 2026
22ca6eb
merge(main): preserve MCP and Hermes rebuild recovery
ericksoa Sep 9, 2026
16b6f09
merge: reconcile automated branch conflict resolution
ericksoa Sep 9, 2026
c50534e
merge: resolve conflicts with main
github-actions[bot] Sep 9, 2026
58785e6
fix(mcp): retain rebuild recovery after restore failure
ericksoa Sep 9, 2026
f0c1342
merge: preserve concurrent Hermes recovery update
ericksoa Sep 9, 2026
961b21c
merge(main): preserve source-backed MCP discovery failures
ericksoa Sep 9, 2026
4905a1b
docs(mcp): resume incomplete restoration with rebuild
ericksoa Sep 9, 2026
f870127
ci(e2e): consume verified PR branch base images
ericksoa Sep 9, 2026
3957ed6
fix(mcp): correct native source and supervisor inspection
ericksoa Sep 9, 2026
8f6acbb
test(mcp): retain bounded failure diagnostics
ericksoa Sep 9, 2026
019098a
merge(main): resolve assertion census conflict for PR CI
ericksoa Sep 9, 2026
6675588
test(mcp): register credential-window helper coverage
ericksoa Sep 9, 2026
8893534
merge(main): reconcile live assertion counts for CI
ericksoa Sep 9, 2026
8c04ab9
test(mcp): assert same-provider credential fallback
ericksoa Sep 9, 2026
774eeb6
fix(mcp): pace Hermes reloads and clean retained test providers
ericksoa Sep 9, 2026
251e52a
fix(mcp): preserve live authority through recovery and migration
ericksoa Sep 9, 2026
f4a633b
merge: resolve main conflicts for MCP validation
ericksoa Sep 9, 2026
206111b
fix(mcp): reuse the sandbox gateway authority resolver
ericksoa Sep 9, 2026
1bf1010
fix(mcp): bind source operations to verified live targets
ericksoa Sep 9, 2026
5664047
fix(mcp): preserve registered gateway authority boundaries
ericksoa Sep 9, 2026
832cfa0
merge: resolve current main conflicts for MCP validation
ericksoa Sep 9, 2026
14879a2
fix(mcp): qualify current images and isolate operation fixtures
ericksoa Sep 9, 2026
d508d0d
fix(mcp): remove policy bindings before exact provider detach
ericksoa Sep 9, 2026
920faf6
fix(build): refresh the locked CLI cache
ericksoa Sep 9, 2026
5b8858e
merge: align with upstream plugin cache constraints
ericksoa Sep 9, 2026
a6a34ba
merge: preserve MCP runtime changes through Node cleanup
ericksoa Sep 9, 2026
36a1859
fix: qualify images and align inherited CI fixtures
ericksoa Sep 9, 2026
ae6c64c
merge: resolve upstream CI contract conflicts
ericksoa Sep 9, 2026
e38b97e
test: preserve MCP fixture permissions and export diagnostics
ericksoa Sep 9, 2026
a74048f
fix: preserve DeepAgents migration recovery and qualify network exports
ericksoa Sep 10, 2026
c7c103f
merge: resolve sandbox command adapter conflicts with main
ericksoa Sep 10, 2026
b741aa7
refactor: isolate MCP rebuild handoff validation
ericksoa Sep 10, 2026
0e9f4b3
test: share rebuild harness module dependencies
ericksoa Sep 10, 2026
b7e8de0
ci: give CLI typechecking sufficient heap
ericksoa Sep 10, 2026
698521a
fix: reject malformed legacy MCP inventories
ericksoa Sep 10, 2026
57f28dd
test: capture failed rebuild HTTP status
ericksoa Sep 10, 2026
10ee815
fix(mcp): repair compact native source inspection
ericksoa Sep 10, 2026
cef3583
merge: reconcile compact MCP removal with current main
ericksoa Sep 10, 2026
593bc2c
style(mcp): apply canonical formatting to compact source
ericksoa Sep 10, 2026
d7501b5
test(rebuild): preserve canonical gateway readiness observation
ericksoa Sep 10, 2026
43a8b44
test(mcp): preserve source contracts within existing limits
ericksoa Sep 10, 2026
392202c
refactor(mcp): restore the compact source-backed lifecycle
ericksoa Sep 10, 2026
f185d1a
test(mcp): align source fixtures and refresh image evidence
ericksoa Sep 10, 2026
947b9cd
test(mcp): retain Hermes runtime evidence before restart failure
ericksoa Sep 10, 2026
762522c
merge: reconcile current main without restoring the MCP ledger
ericksoa Sep 10, 2026
db670ef
merge: resolve current conflicts and qualify compact Pi images
ericksoa Sep 10, 2026
91077d8
merge: reconcile compact MCP with asynchronous SSH
ericksoa Sep 10, 2026
2dd9620
merge: reconcile current validation budget conflicts
ericksoa Sep 11, 2026
b3ffbf9
merge: integrate upstream MCP qualification fix
ericksoa Sep 11, 2026
84c4346
merge: consume upstream provider fixture fixes
ericksoa Sep 11, 2026
2a27393
merge: incorporate qualified main base for E2E
ericksoa Sep 11, 2026
572c8c0
test(e2e): launch the rebuilt Hermes ACP helper directly
ericksoa Sep 11, 2026
68d4938
merge: integrate canonical Hermes rebuild and image fixes
ericksoa Sep 11, 2026
16132a9
merge(mcp): retain compact sources through OpenShell cutover
ericksoa Sep 11, 2026
0b1b16c
merge(mcp): resolve native fixture conflict with main
ericksoa Sep 11, 2026
b30b6ea
chore(images): record compact source Pi qualification
ericksoa Sep 11, 2026
e525729
test(mcp): probe the supported Deep Agents connect shell
ericksoa Sep 11, 2026
72f76ae
merge: reconcile canonical asynchronous policy adapters
ericksoa Sep 11, 2026
490db57
chore(mcp): format asynchronous policy restoration
ericksoa Sep 11, 2026
416cd35
test(mcp): map the approved connect probe to its coverage
ericksoa Sep 11, 2026
c7b4054
merge: reconcile canonical agent input budget counts
ericksoa Sep 11, 2026
35712b8
test(e2e): restore protected startup and retain restart failure evidence
ericksoa Sep 12, 2026
f30466a
test(onboard): isolate ambient-provider reuse from concurrent fixtures
ericksoa Sep 12, 2026
400a838
merge: integrate required managed-image qualification dependency
ericksoa Sep 12, 2026
cbb20bb
fix(mcp): finish forced cleanup and remove unused mutation builders
ericksoa Sep 12, 2026
8a453af
merge: reconcile current main and preserve Pi qualification lineage
ericksoa Sep 12, 2026
5817a27
chore(agent): refresh Pi image qualification
ericksoa Sep 12, 2026
73a4590
test(e2e): restart sandbox through OpenShell lifecycle
ericksoa Sep 12, 2026
cf3f562
fix(images): refresh shared curl package pin
ericksoa Sep 12, 2026
3cdf190
fix(images): refresh unavailable base package pins
ericksoa Sep 12, 2026
ad2f74b
fix(images): align Python security package with Debian update
ericksoa Sep 12, 2026
b97a829
fix(images): synchronize Python dependency consumers
ericksoa Sep 12, 2026
1dd7694
test(mcp): retain unexpected request details in count failures
ericksoa Sep 12, 2026
67bc56b
chore(agent): refresh Pi qualification from validated images
ericksoa Sep 12, 2026
27343f7
merge: resolve conflicts with main
github-actions[bot] Sep 12, 2026
719771e
merge: resolve conflicts with main
github-actions[bot] Sep 13, 2026
51f9a4e
chore(agent): refresh Pi qualification from validated images
ericksoa Sep 13, 2026
0cffdb5
merge: integrate current main for CI
ericksoa Sep 13, 2026
6f16a34
chore(lint): remove declarations orphaned by merge
ericksoa Sep 13, 2026
37a8edc
fix(mcp): preserve source ownership on recovery
ericksoa Sep 13, 2026
8f330f5
fix(hermes): authorize unchanged MCP restarts
ericksoa Sep 13, 2026
887ba3c
Merge current main into refactor/stateless-mcp-11134
ericksoa Sep 13, 2026
668bff1
test(snapshot): keep restore fixture branchless
ericksoa Sep 13, 2026
bffadc4
Merge current main into refactor/stateless-mcp-11134
ericksoa Sep 13, 2026
b83f0a3
fix(hermes): admit expected-exit lease reads
ericksoa Sep 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4471,6 +4471,7 @@ jobs:
--revision "$CHECKOUT_SHA" \
--cohort "$NEMOCLAW_PROTECTED_MANAGED_IMAGE_COHORT" \
--platform "$NEMOCLAW_PROTECTED_MANAGED_IMAGE_PLATFORM" \
--runtime-user sandbox \
--openclaw-base "$BASE_OPENCLAW" \
--hermes-base "$BASE_HERMES" \
--dcode-base "$BASE_DCODE" \
Expand Down
15 changes: 4 additions & 11 deletions agents/hermes/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# Layers PR-specific code (plugin, config, startup script) on top of the
# pre-built Hermes base image. Mirrors the OpenClaw Dockerfile structure.

ARG BASE_IMAGE=ghcr.io/nvidia/nemoclaw/hermes-sandbox-base@sha256:c588bf76ba1c280f8a366bdfd672193e852de4f509a280662c7070a9b6e2fa48
ARG BASE_IMAGE=ghcr.io/nvidia/nemoclaw/hermes-sandbox-base@sha256:0faf0abc8c62a284ba7dfecfc9afcd52524c0f5710ea9b2523be7c47b2a76582
ARG NEMOCLAW_CORPORATE_CA_B64=
ARG NEMOCLAW_MANAGED_IMAGE_CAPABILITY_UNION=0
# BuildKit supplies this automatic platform argument. The Portable staged
Expand Down Expand Up @@ -131,7 +131,6 @@
COPY agents/hermes/seed-dashboard-config.py /usr/local/lib/nemoclaw/seed-hermes-dashboard-config.py
COPY agents/hermes/runtime-config-guard.py /usr/local/lib/nemoclaw/hermes-runtime-config-guard.py
COPY agents/hermes/finalize-tirith-marker.py /usr/local/lib/nemoclaw/finalize-tirith-marker.py
COPY agents/hermes/build-mcp-digest.py /usr/local/lib/nemoclaw/build-hermes-mcp-digest.py
COPY agents/hermes/mcp-config-transaction.py /usr/local/lib/nemoclaw/hermes-mcp-config-transaction.py
COPY agents/hermes/cron-restore-control.py /usr/local/lib/nemoclaw/hermes-cron-restore-control.py
COPY src/lib/actions/sandbox/openshell-child-visible-credentials.v0.0.116.json /usr/local/lib/nemoclaw/openshell-child-visible-credentials.v0.0.116.json
Expand Down Expand Up @@ -569,10 +568,10 @@
# minimum supported Hermes sandbox base tag guarantees those artifacts and
# test/runtime/sandbox/sandbox-rlimit-hooks.test.ts covers that base.
RUN chmod 755 /usr/local/bin/nemoclaw-start /usr/local/bin/nemoclaw-managed-startup-hold /usr/local/bin/nemoclaw-managed-bootstrap /usr/local/lib/nemoclaw/sandbox-init.sh /usr/local/lib/nemoclaw/validate-hermes-env-secret-boundary.py /usr/local/lib/nemoclaw/patch-hermes-sqlite-temp-store.py /usr/local/lib/nemoclaw/patch-hermes-discord-recovery-permissions.py /usr/local/lib/nemoclaw/seed-hermes-dashboard-config.py /usr/local/lib/nemoclaw/hermes-runtime-config-guard.py /usr/local/lib/nemoclaw/finalize-tirith-marker.py /usr/local/lib/nemoclaw/hermes-mcp-config-transaction.py \
&& chown root:root /usr/local/bin/nemoclaw-gateway-control /usr/local/lib/nemoclaw/gateway-supervisor.sh /usr/local/lib/nemoclaw/managed-gateway-control.py /usr/local/lib/nemoclaw/build-hermes-mcp-digest.py /usr/local/lib/nemoclaw/hermes-cron-restore-control.py /usr/local/lib/nemoclaw/openshell-child-visible-credentials.v0.0.116.json \
&& chown root:root /usr/local/bin/nemoclaw-gateway-control /usr/local/lib/nemoclaw/gateway-supervisor.sh /usr/local/lib/nemoclaw/managed-gateway-control.py /usr/local/lib/nemoclaw/hermes-cron-restore-control.py /usr/local/lib/nemoclaw/openshell-child-visible-credentials.v0.0.116.json \
&& chmod 700 /usr/local/bin/nemoclaw-gateway-control /usr/local/lib/nemoclaw/hermes-cron-restore-control.py \
&& chmod 500 /usr/local/lib/nemoclaw/managed-gateway-control.py \
&& chmod 444 /usr/local/lib/nemoclaw/corporate-ca-runtime.sh /usr/local/lib/nemoclaw/entrypoint-env-wrapper.sh /usr/local/lib/nemoclaw/gateway-supervisor.sh /usr/local/lib/nemoclaw/build-hermes-mcp-digest.py /usr/local/lib/nemoclaw/managed_policy.py \
&& chmod 444 /usr/local/lib/nemoclaw/corporate-ca-runtime.sh /usr/local/lib/nemoclaw/entrypoint-env-wrapper.sh /usr/local/lib/nemoclaw/gateway-supervisor.sh /usr/local/lib/nemoclaw/managed_policy.py \
&& chmod 444 /usr/local/lib/nemoclaw/patch-hermes-langfuse-credentials.mts \
&& chmod 444 /usr/local/lib/nemoclaw/openshell-child-visible-credentials.v0.0.116.json \
&& /opt/hermes/.venv/bin/python3 -I -c 'import runpy, yaml; assert yaml.safe_load("ready: true")["ready"] is True; runpy.run_path("/usr/local/lib/nemoclaw/hermes-runtime-config-guard.py", run_name="nemoclaw_runtime_config_guard_probe")' \
Expand Down Expand Up @@ -686,7 +685,7 @@
# Hermes v0.20.6 drops explicit auxiliary output limits on custom endpoints.
# Preserve those limits on NemoClaw's managed inference route so session-title
# generation cannot occupy Ollama's only inference slot until the context fills.
ARG NEMOCLAW_HERMES_AUXILIARY_TOKEN_LIMIT_PATCHER_SHA256=d04ffc133e115caddd6a1243979e317a512a4ffd8b259ec2b053a5057c26ba93

Check warning on line 688 in agents/hermes/Dockerfile

View workflow job for this annotation

GitHub Actions / PR build and direct managed startup (Hermes)

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ARG "NEMOCLAW_HERMES_AUXILIARY_TOKEN_LIMIT_PATCHER_SHA256") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/

Check warning on line 688 in agents/hermes/Dockerfile

View workflow job for this annotation

GitHub Actions / PR build and direct managed startup (Hermes)

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ARG "NEMOCLAW_HERMES_AUXILIARY_TOKEN_LIMIT_PATCHER_SHA256") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/
# hadolint ignore=DL4006
RUN printf '%s %s\n' \
"$NEMOCLAW_HERMES_CRON_RUNTIME_PATCHER_SHA256" /opt/nemoclaw-hermes-config/patch-cron-execution-runtime.py \
Expand Down Expand Up @@ -1571,16 +1570,10 @@
/sandbox/.hermes/audio_cache \
/sandbox/.hermes/skills

# Pin config hash at build time for integrity verification at startup. Invoke
# the installed runtime guard's `_canonical_mcp_servers_digest` directly so
# image sealing and runtime verification cannot drift onto different JSON
# canonicalization contracts.
# Pin config hash at build time for config and environment integrity verification at startup.
RUN mkdir -p /etc/nemoclaw \
&& sha256sum /sandbox/.hermes/config.yaml /sandbox/.hermes/.env \
> /etc/nemoclaw/hermes.config-hash \
&& mcp_digest="$(/opt/hermes/.venv/bin/python -I /usr/local/lib/nemoclaw/build-hermes-mcp-digest.py --guard /usr/local/lib/nemoclaw/hermes-runtime-config-guard.py --config /sandbox/.hermes/config.yaml)" \
&& printf '# nemoclaw-hermes-mcp-state-v1 intended=%s applied=%s\n' "$mcp_digest" "$mcp_digest" \
>> /etc/nemoclaw/hermes.config-hash \
&& chown root:root /etc/nemoclaw/hermes.config-hash \
&& chmod 444 /etc/nemoclaw/hermes.config-hash

Expand Down
39 changes: 0 additions & 39 deletions agents/hermes/build-mcp-digest.py

This file was deleted.

27 changes: 13 additions & 14 deletions agents/hermes/mcp-config-transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,7 @@ def inspect_managed_config(payload: dict[str, object]) -> dict[str, object]:
)
# TOCTOU contract: this call reads config, env, and every hash anchor into
# one authenticated snapshot. After comparing the returned config bytes to
# host intent, `assert_mcp_integrity_snapshot_current` reopens every path and
# the command's requested entry, `assert_mcp_integrity_snapshot_current` reopens every path and
# requires the same inode/content metadata before any match is reported.
integrity = guard.inspect_mcp_integrity_snapshot(
HERMES_DIR, hash_path, compatibility_hash_path
Expand All @@ -636,23 +636,23 @@ def inspect_managed_config(payload: dict[str, object]) -> dict[str, object]:
if parsed is None:
parsed = {}
if not isinstance(parsed, dict):
raise RuntimeError("Hermes MCP config does not match persisted managed intent")
raise RuntimeError("Hermes MCP config does not match the requested native entry")
servers = parsed.get("mcp_servers", {})
if servers is None:
servers = {}
if not isinstance(servers, dict):
raise RuntimeError("Hermes MCP config does not match persisted managed intent")
raise RuntimeError("Hermes MCP config does not match the requested native entry")
present = payload["present"]
absent = payload["absent"]
if not isinstance(present, dict) or not isinstance(absent, list):
raise RuntimeError("Hermes MCP config does not match persisted managed intent")
raise RuntimeError("Hermes MCP config does not match the requested native entry")
matches = all(
_managed_candidate_matches(servers.get(name), expected, True)
for name, expected in present.items()
)
matches = matches and all(name not in servers for name in absent)
if not matches:
raise RuntimeError("Hermes MCP config does not match persisted managed intent")
raise RuntimeError("Hermes MCP config does not match the requested native entry")
guard.assert_mcp_integrity_snapshot_current(integrity)
return {"ok": True, "state": "matched"}

Expand Down Expand Up @@ -747,12 +747,8 @@ def _refresh_and_verify_hashes(
HERMES_DIR,
STRICT_HASH_PATH if privileged else os.path.join(HERMES_DIR, ".config-hash"),
)
expected_state = {
"apply": "current",
"rollback": "pending",
}.get(mcp_transition)
if expected_state is not None and state != expected_state:
raise RuntimeError("Hermes MCP applied hash state is stale")
if state != "current":
raise RuntimeError("Hermes config hash is stale")


def _restore_hash_snapshots(
Expand Down Expand Up @@ -809,12 +805,15 @@ def apply_transaction(action: str, payload: dict[str, object]) -> bool:
guard = _load_guard()
original_text, original_snapshot = guard._read_text(CONFIG_PATH)
_assert_mutable_snapshot(original_snapshot)
hash_originals = {
path: guard._read_text(path) for path in _managed_hash_paths(privileged)
}
integrity_path = (
STRICT_HASH_PATH if privileged else os.path.join(HERMES_DIR, ".config-hash")
)
# Direct Hermes configuration changes are authoritative. Adopt the current
# source bytes into the file-integrity seal before this scoped mutation.
_refresh_and_verify_hashes(guard, privileged, "adopt")
hash_originals = {
path: guard._read_text(path) for path in _managed_hash_paths(privileged)
}
guard.inspect_mcp_integrity(HERMES_DIR, integrity_path)
parsed = yaml.safe_load(original_text)
if parsed is None:
Expand Down
1 change: 1 addition & 0 deletions agents/hermes/policy-additions.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ filesystem_policy:
- /app
- /run/nemoclaw/managed-startup-ca-bundle.pem
- /run/nemoclaw/managed-startup-runtime.env
- /run/nemoclaw/managed-gateway-expected-exit
- /etc
- /var/log
- /var/lib/dpkg # Allow package-version inspection without package mutation.
Expand Down
Loading
Loading