Skip to content

fix(sandbox): give each Hermes sandbox its own OpenAI-compatible API port - #8577

Open
laitingsheng wants to merge 46 commits into
mainfrom
fix/hermes-api-port-per-sandbox
Open

fix(sandbox): give each Hermes sandbox its own OpenAI-compatible API port#8577
laitingsheng wants to merge 46 commits into
mainfrom
fix/hermes-api-port-per-sandbox

Conversation

@laitingsheng

@laitingsheng laitingsheng commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Summary

The Hermes OpenAI-compatible API port was a fixed host-wide 8642, so only one Hermes sandbox per host could own its host forward. A snapshot clone therefore received no inference forward, and gateway restart on the clone exited 1 with a forward recovery failure it could never repair. Each Hermes sandbox now allocates its own API port from 8642 through 8652, and every consumer resolves that port instead of the manifest default.

Related Issue

Fixes #8543

Changes

  • src/lib/core/ports.ts adds HERMES_API_PORT_RANGE_START/END and isHermesApiPort. 8642 becomes the range start rather than a host-wide reservation.
  • src/lib/onboard/hermes-api-port.ts is new: allocation, resolveOnboardHermesApiPort, resolveSandboxHermesApiPort, and retargetHermesApiPortInUrl. The port is published back to NEMOCLAW_HERMES_API_PORT so the sandbox-create environment, the registry row, and the host forward agree on one value without threading an argument through the onboarding entrypoint, matching how ensureAgentDashboardForward already propagates the dashboard port through CHAT_UI_URL. A registered sandbox keeps its recorded port: an explicit environment value is accepted only at the create, recreate, and created-sandbox registration boundaries, and every other consumer rejects a conflicting value before it mutates a host forward. isValidHermesApiPort accepts only the allocation range, so an out-of-range operator value is refused outright.
  • src/lib/onboard/dashboard-port.ts extracts findAvailablePortInRange so the dashboard and API allocators share one forward-list, registry, and host-bind view, and adds getRegistryOccupiedHermesApiPorts for the cross-gateway view.
  • The registry carries hermesApiPort, sanitised in src/lib/state/registry.ts and validated fail-closed in src/lib/state/gateway-registry.ts so a corrupt value cannot drop occupancy and hand out a colliding port.
  • src/lib/actions/sandbox/snapshot.ts allocates the clone's own port before any destructive step, so range exhaustion aborts before deleteSandboxForRestore removes a --force destination, and overrides the value the source-entry spread would otherwise inherit.
  • src/lib/actions/sandbox/forward-recovery.ts resolves manifest-declared forward ports against the sandbox's own ports. This fixes both halves of the reported failure: recovery no longer demands the manifest dashboard port from a sandbox that owns a different one, and it targets the sandbox's own API port.
  • agents/hermes/start.sh reads NEMOCLAW_HERMES_API_PORT and publishes the resolved value as a 0444 marker at /run/nemoclaw/hermes-api-port, on the root-separated path and on the same-uid path that OpenShell-managed and macOS VM startups take. A one-shot openshell sandbox exec does not inherit the supervisor environment, so agents/hermes/mcp-config-transaction.py, agents/hermes/plugin/__init__.py, and scripts/managed-gateway-control.py read that marker instead. Under privilege separation the marker is root-owned and the sandbox user cannot rewrite it; the transaction helper opens it with O_NOFOLLOW and checks ownership, mode, link count, and size before trusting it. In the same-uid topology the gateway already runs as the sandbox user, so the marker carries that same authority, and a sandbox that cannot publish an allocated port there refuses to start rather than leave its helpers probing a default port any process can bind.
  • src/lib/onboard/managed-startup/profile.ts declares the reserved range locally instead of importing core/ports. That module is bundled into the managed image and is also executed directly by node --experimental-strip-types, and neither path resolves a relative value import; src/lib/onboard/managed-startup-profile.test.ts pins the two declarations to the same values.
  • tools/mcp-tool-discovery-runtime/reviewed-runtime-bundle/managed-startup-image-runtime.bundle is regenerated for that change, and its pinned digest in test/mcp-tool-discovery-image-contract.test.ts is updated. bundle:reviewed:check reproduced the other three reviewed artefacts byte-for-byte, so only the managed-startup bundle moved.
  • src/lib/agent/onboard.ts passes sandboxName through the API-kind dashboard branch, which otherwise announced the manifest default for a Hermes sandbox that owns another port.
  • The sandbox agent rejection message, the onboarding ready summary, and scripts/install.sh resolve the sandbox's port instead of naming 8642, and the installer restores a registered Hermes forward rather than the manifest default.
  • The reserved-port guards in src/lib/onboard/preflight-ports.ts, src/lib/onboard/hermes-dashboard.ts, and the managed-startup profile validation cover the whole range rather than the single literal.
  • ci/source-architecture-budget.json raises four limits. Introducing one module adds edges to snapshot.ts fan-out, the src/lib/onboard root-file count, and core/ports.ts/state/registry.ts fan-in. Two other increases were avoidable and were removed instead: getSandboxHealthProbeUrl moved into forward-recovery.ts, which already owned that dependency, and snapshot.ts no longer imports core/ports.
  • The seven Hermes pages now state the condition under which a sandbox receives 8642 instead of calling it the first sandbox's port, document the clone's own API port allocation and the installer's forward-restore failure, and replace the interactive port prompt in the headless procedure with the <api-port> placeholder the credential-rotation page already uses.
  • agents/hermes/start.sh restores the runtime directory's owner and mode from root before it refuses startup. Publishing the API port marker replaced an unconditional install -d -m 0755 -o root -g root /run/nemoclaw with an assertion that the directory was already root-owned with mode 0755, and the managed runtime presents that directory before the root-separated gateway starts, so the assertion crash-looped the container during managed activation. Startup still refuses when the restore is not permitted.
  • test/e2e/live/managed-image-activation-e2e-helpers.ts adds three fixed startup signals for the Hermes refusals, so an activation failure names which refusal ended the container instead of leaving only a restart count. The container log capture moves from a direct synchronous spawn onto the audited shell probe: test/e2e/fixtures/shell-probe.ts accepts a non-persisting run, which keeps the probe's bounded timeout, kill signal, output limit, and redaction while raw output stays out of the artifact sink.
  • docs/reference/troubleshooting.mdx states the range and the occupancy behaviour for a manual NEMOCLAW_HERMES_API_PORT override.
  • src/lib/actions/sandbox/gateway-restart.ts is reformatted, and three launch harnesses under test/ extract launch_openclaw_gateway_process. Both arrived from main: the log-tail command landed in a shape the repository formatter rewrites, which failed static-checks, and the launch path now delegates the background process to a helper the harnesses did not assemble, which failed three cli-test-shards jobs. Both reproduce on a pristine origin/main checkout.
  • Merged origin/main to keep the branch current. The merges were clean.

Large change note: this PR changes 60 files with 2,587 additions and 210 deletions. The scope spans port allocation, registry state, forward recovery, runtime hardening, tests, and documentation, so the large review surface remains explicitly flagged.

Type of Change

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

Quality Gates

  • Tests added or updated for changed behavior
  • Existing tests cover changed behavior — justification:
  • Tests not applicable — justification:
  • Docs updated for user-facing behavior changes
  • Docs not applicable — justification:
  • Sensitive paths changed (security, policy, credentials, preflight, onboarding, inference, runner, sandbox, or messaging)
  • Sensitive-path review completed or maintainer-approved waiver recorded — reviewer/approval link/justification: follow-up security review passed with no new blocker: fix(sandbox): give each Hermes sandbox its own OpenAI-compatible API port #8577 (comment). The fresh hosted checks, managed-runtime activation, and required reviewer approval remain merge gates.
  • Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue:

Documentation Writer Review

  • Documentation writer subagent reviewed the completed changes
  • Result: docs-updated
  • Evidence: docs/get-started/quickstart-hermes.mdx, docs/reference/commands.mdx, docs/reference/troubleshooting.mdx, docs/deployment/deploy-to-headless-server.mdx, docs/deployment/set-up-mcp-bridge.mdx, docs/security/credential-rotation.mdx, docs/manage-sandboxes/run-sandboxes.mdx, and docs/manage-sandboxes/backup-restore.mdx, plus the changed comments, CLI strings, error strings, and test titles across the diff. The subagent reviewed the writing rules and documentation style over eleven passes, eight of them on the merged tree. The early passes closed six blocking items, including a sandbox agent rejection message and an onboarding ready summary that still emitted the manifest default, docs that pointed operators at status, which prints no port, a guard that applied the Hermes port to any agent, and unit tests that had begun reading the real sandbox registry. A later pass returned docs-missing with 14 findings, among them a Hermes credential-rotation procedure that still hardcoded 8642, an agent-neutral port guard described as Hermes-only, an override whose failure result was unstated, and three reader docstrings that claimed a root-owned marker in a topology where the gateway itself owns it. All were applied. Two further passes corrected an override consequence that had been stated in the wrong direction and a guard that would have rejected the very --recreate-sandbox command its own error recommends; both corrections were traced through src/lib/onboard/dashboard.ts, src/lib/onboard/agent-dashboard-forward.ts, and src/lib/onboard/sandbox-lifecycle.ts before they were accepted. The final pass covers the merged tree at this head and applied nine findings across seven pages: the allocation condition stated as first-sandbox ownership on four pages, the missing clone API-port allocation and its pre-delete abort, the missing range-exhaustion and installer forward-restore entries, an off-vocabulary registry term, a hedged port claim, and the headless procedure's interactive prompt and exit 1, which ends the reader's own SSH session when the typed port is rejected. Every finding was verified against source before it was applied, and two requests to add explanatory comments were declined and recorded for maintainer review.
  • Follow-up evidence: Codex Desktop reviewed the readiness fixes after integration with current main, added fail-closed validation for the documented Hermes API port before token retrieval, and confirmed no other documentation changes were needed. The later test-only revision adds non-root marker-owner rejection, dependency stubbing, and fixture cleanup; no user-facing documentation changed. The diagnostic-only revision persists only content-free container state and fixed boolean startup signals when managed onboarding fails. Raw logs remain in memory and never enter the artifact sink; a focused regression proves arbitrary credential-like output is absent from the saved summary. The current head merges origin/main and carries the documentation pass described above. The later commits repair the startup refusal that crash-looped managed activation, name that refusal in the activation diagnostics, and restore two inherited gates; none of them changes a user-facing surface, so no further documentation follows. The final documentation build completed with 0 errors and the 2 previously documented warnings. The internal E2E comment correction accurately describes persisted output as redacted and size-bounded and confirms that disabling persistence writes neither output nor result metadata; no user-facing documentation changed.
  • Agent: Claude Code; Codex Desktop follow-up

Verification

  • PR description includes a Signed-off-by: line and every commit appears as Verified in GitHub
  • Normal pre-commit, commit-msg, and pre-push hooks passed, or npm run validate:pr passed after refreshing origin/main when hooks were skipped or unavailable
  • Targeted behavior tests pass for the current change set, or tests are marked not applicable above — command/result or justification: the current head adds documentation and one formatter-only source change, so the behaviour suites from the preceding head still apply: npx vitest run --project cli src/lib/onboard/hermes-api-port.test.ts — 22 passed. npx vitest run --project integration test/generate-managed-startup-profile-fixture.test.ts test/mcp-tool-discovery-image-contract.test.ts test/source-architecture.test.ts — 31 passed. npx vitest run --project cli src/lib/onboard/managed-startup-profile.test.ts — 105 passed. On this head: npm run typecheck:cli — exit 0. npm run checks:repository — exit 0. npx biome format over the formatter hook's file set — no drift. npm run docs — 0 errors, 2 warnings. npx vitest run --project integration test/nemoclaw-start-gateway-health.test.ts test/nemoclaw-start-gateway-marker.test.ts test/openclaw-2026-7-startup-compat.test.ts — 51 passed, 1 skipped. npx vitest run --project integration test/hermes-api-port-startup.test.ts test/hermes-api-port-marker.test.ts — 10 passed. npx vitest run --project e2e-support — 2481 passed, 10 skipped. CI on the preceding head reported all eight cli-test-shards green and all three PR build and direct managed startup jobs passing, and the PR Review Advisor reported 0 blockers. The later internal-comment correction was validated with 52 focused E2E-support tests and all applicable repository hooks.
  • Applicable broad gate passed — npm test for broad runtime/test-harness changes; npm run check for repo-wide validation/coverage changes — command/result: not run locally; left to CI.
  • 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) — npm run docs exits 0 with 0 errors and 2 warnings. Both warnings are pre-existing learn.microsoft.com language-reference links in docs/reference/troubleshooting.mdx that this change does not touch, so the box stays clear rather than claiming a warning-free build.
  • Doc pages follow the style guide (doc changes only)
  • New doc pages include SPDX header and frontmatter (new pages only)

Signed-off-by: Tinson Lai tinsonl@nvidia.com

Summary by CodeRabbit

  • New Features

    • Hermes sandboxes now receive unique OpenAI-compatible API ports from 8642–8652.
    • Port assignments are automatically preserved across onboarding, forwarding, recovery, and snapshot restores.
    • Dashboard and API port conflicts are detected with clearer guidance.
    • Assigned ports are shown through forwarding and status information.
  • Bug Fixes

    • Health checks, API URLs, and installer forward restoration now target the correct sandbox port.
    • Legacy sandboxes continue using the default port when no assignment exists.
  • Documentation

    • Added guidance for discovering assigned ports, configuring overrides, troubleshooting, and headless deployments.

…port

The API port was a fixed host-wide 8642, so a second Hermes sandbox on one
host could never own an inference forward. A snapshot clone therefore received
no inference forward and its gateway restart could not converge.

Allocate the port per sandbox from 8642-8652, persist it on the registry row,
and publish it to the sandbox through the create environment. The entrypoint
re-publishes it as a root-owned read-only marker because a one-shot sandbox
exec does not inherit the supervisor environment. Forward recovery now resolves
manifest-declared ports against the sandbox's own ports instead of demanding
the agent defaults a sibling sandbox already holds.

Signed-off-by: Tinson Lai <tinsonl@nvidia.com>
The first pass left three host-side surfaces on the manifest default: the
`sandbox agent` rejection message, the onboarding ready summary, and the docs.
Each told an operator to forward a port their sandbox does not use.

Relaunch also reached the allocator through the sandbox-create environment. A
sandbox registered before the port became per-sandbox has no recorded value, so
the allocator saw its own live forward holding the default and moved it, leaving
the sandbox bound to one port while the host forwarded another. A registered
sandbox without a port now keeps the default; only an unregistered sandbox takes
a fresh allocation.

Signed-off-by: Tinson Lai <tinsonl@nvidia.com>
…er-sandbox

Signed-off-by: Tinson Lai <tinsonl@nvidia.com>

# Conflicts:
#	ci/source-architecture-budget.json
@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 0ae3f3f2-1694-4758-9106-4e48a36b83ea

📥 Commits

Reviewing files that changed from the base of the PR and between 6234714 and 9675497.

📒 Files selected for processing (1)
  • test/e2e/fixtures/shell-probe.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/e2e/fixtures/shell-probe.ts

📝 Walkthrough

Walkthrough

Hermes now supports per-sandbox API ports in the 8642–8652 range. The selected port flows through onboarding, registry state, startup, health checks, forwarding, recovery, cloning, installer restoration, tests, and documentation.

Changes

Hermes API port lifecycle

Layer / File(s) Summary
Port allocation and persistence
src/lib/core/ports.ts, src/lib/onboard/*, src/lib/state/*
Hermes API ports now use range-aware allocation, registry persistence, collision checks, environment propagation, and dashboard-port protection.
Runtime publication and discovery
agents/hermes/*, scripts/managed-gateway-control.py, agents/hermes/plugin/__init__.py
Startup publishes a protected port marker. Runtime checks resolve validated ports before health checks, probes, and transactions.
Forwarding, recovery, cloning, and restoration
src/lib/actions/sandbox/*, scripts/install.sh, src/lib/agent/onboard.ts
Forwarding, recovery, snapshot cloning, dashboard output, and installer restoration use each sandbox’s configured API port.
Tests and operator guidance
test/*, docs/*, vitest.config.ts, ci/*
Tests cover allocation, marker security, runtime resolution, recovery, cloning, and diagnostics. Documentation describes allocation, discovery, migration, and troubleshooting.
Managed activation diagnostics
test/e2e/live/managed-image-activation-e2e-helpers.ts, test/e2e/support/managed-image-activation-diagnostics.test.ts, test/e2e/fixtures/shell-probe.ts
Onboarding failures now collect bounded container diagnostics and summarize fixed startup signals. Artifact persistence can be disabled.

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

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 32.84% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: assigning each Hermes sandbox its own OpenAI-compatible API port.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/hermes-api-port-per-sandbox

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

@github-code-quality

github-code-quality Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

The overall coverage in commit 9675497 in the fix/hermes-api-port-... branch remains at 96%, unchanged from commit ac6adac in the main branch.


Updated August 12, 2026 11:08 UTC

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

@laitingsheng laitingsheng added integration: hermes Hermes integration behavior area: sandbox OpenShell sandbox lifecycle, runtime, config, or recovery bug-fix PR fixes a bug or regression feature PR adds or expands user-visible functionality labels Aug 7, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

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

⚠️ Outside diff range comments (1)
src/lib/onboard/dashboard-port.ts (1)

318-344: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Reject explicit Hermes API/dashboard port overlaps before sandbox creation.

assertDashboardPortNotReserved rejects dashboard ports in 8642–8652, but resolveOnboardHermesApiPort accepts any valid NEMOCLAW_HERMES_API_PORT without checking the resolved dashboard port. Thus NEMOCLAW_HERMES_API_PORT=18789 can map both resources to one host port. Reject this equality and add regression tests for both cases.

🤖 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/onboard/dashboard-port.ts` around lines 318 - 344, Update
resolveOnboardHermesApiPort to reject configurations where the resolved Hermes
API port equals the resolved dashboard port, including explicit
NEMOCLAW_HERMES_API_PORT values and automatically selected ports. Ensure the
rejection occurs before sandbox creation and add regression tests covering both
explicit overlap and overlap produced by resolution.
🤖 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 `@agents/hermes/start.sh`:
- Around line 173-196: Use the shared Hermes API-port validity contract of
8642–8652 at all affected sites: update agents/hermes/start.sh lines 173-196,
agents/hermes/mcp-config-transaction.py lines 88-106,
agents/hermes/plugin/__init__.py lines 1035-1051,
scripts/managed-gateway-control.py lines 1125-1151, and scripts/install.sh lines
465-485 to reject values outside that inclusive range while preserving existing
defaults and error handling.

In `@docs/deployment/deploy-to-headless-server.mdx`:
- Line 292: Update all listed documentation examples to reflect dynamic Hermes
API-port allocation: in docs/deployment/deploy-to-headless-server.mdx lines
292-292, qualify 8642 as the first-sandbox default and revise adjacent curl
guidance; in docs/reference/commands.mdx lines 1216-1217, replace fixed-port
wording and update the Hermes agent example to use the port from openshell
forward list; in docs/reference/commands.mdx lines 1918-1919, use the selected
API port for the gateway-token example; and in
docs/reference/troubleshooting.mdx lines 3132-3133, qualify the 8642
troubleshooting path and update its health/client examples accordingly.

In `@docs/reference/troubleshooting.mdx`:
- Around line 3163-3167: Update the troubleshooting guidance around the final
destroy/re-onboard instruction to distinguish new second Hermes sandboxes from
existing pre-change sandboxes. State that new sandboxes receive the next free
API port automatically, while destroy and re-onboard is required only for an
existing sandbox with a registry row lacking hermesApiPort.

In `@src/lib/agent/onboard.ts`:
- Around line 559-577: The API dashboard branch that calls
printAdditionalForwardPorts must pass sandboxName so Hermes resolves its
registered sandbox-specific API port instead of the manifest default. Update
that kind === "api" call site, and add coverage for the Hermes dashboard.kind
=== "api" path verifying the sandbox-specific port is announced.

---

Outside diff comments:
In `@src/lib/onboard/dashboard-port.ts`:
- Around line 318-344: Update resolveOnboardHermesApiPort to reject
configurations where the resolved Hermes API port equals the resolved dashboard
port, including explicit NEMOCLAW_HERMES_API_PORT values and automatically
selected ports. Ensure the rejection occurs before sandbox creation and add
regression tests covering both explicit overlap and overlap produced by
resolution.
🪄 Autofix

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: dc739679-b1ab-436c-a70f-c20c3887833e

📥 Commits

Reviewing files that changed from the base of the PR and between 71a7e7c and 525b49e.

📒 Files selected for processing (37)
  • agents/hermes/mcp-config-transaction.py
  • agents/hermes/plugin/__init__.py
  • agents/hermes/start.sh
  • ci/source-architecture-budget.json
  • docs/deployment/deploy-to-headless-server.mdx
  • docs/deployment/set-up-mcp-bridge.mdx
  • docs/get-started/quickstart-hermes.mdx
  • docs/reference/commands.mdx
  • docs/reference/troubleshooting.mdx
  • scripts/install.sh
  • scripts/managed-gateway-control.py
  • src/commands/sandbox/agent.ts
  • src/lib/actions/sandbox/agent/passthrough-help.ts
  • src/lib/actions/sandbox/agent/passthrough.test.ts
  • src/lib/actions/sandbox/agent/passthrough.ts
  • src/lib/actions/sandbox/forward-recovery-declared-ports.test.ts
  • src/lib/actions/sandbox/forward-recovery.ts
  • src/lib/actions/sandbox/process-recovery.ts
  • src/lib/actions/sandbox/snapshot-restore-clone-ports.test.ts
  • src/lib/actions/sandbox/snapshot.ts
  • src/lib/agent/onboard.test.ts
  • src/lib/agent/onboard.ts
  • src/lib/core/ports.ts
  • src/lib/onboard/agent-dashboard-forward.ts
  • src/lib/onboard/dashboard-port.ts
  • src/lib/onboard/hermes-api-port.test.ts
  • src/lib/onboard/hermes-api-port.ts
  • src/lib/onboard/hermes-dashboard.ts
  • src/lib/onboard/managed-startup-profile.test.ts
  • src/lib/onboard/managed-startup/profile.ts
  • src/lib/onboard/preflight-ports.ts
  • src/lib/onboard/sandbox-create-launch.ts
  • src/lib/onboard/sandbox-registration.ts
  • src/lib/state/gateway-registry.ts
  • src/lib/state/registry.ts
  • src/lib/state/registry/types.ts
  • test/hermes-mcp-reload-convergence.test.ts

Comment thread agents/hermes/start.sh Outdated
Comment thread docs/deployment/deploy-to-headless-server.mdx Outdated
Comment thread docs/reference/troubleshooting.mdx Outdated
Comment thread src/lib/agent/onboard.ts
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor — Informational

Advisor assessment: Informational / low confidence
Next action: No advisor follow-up needed.
Findings: 0 blockers · 0 warnings · 0 suggestions
Status: Same-session synthesis validation failed; the advisor result is incomplete.

Model lanes

  • GPT-5.6 Terra (primary): Completed · low confidence · 0 blockers · 0 warnings · 0 suggestions
  • Nemotron 3 Ultra (second opinion): Failed after a partial review · low confidence · 0 blockers · 0 warnings · 0 suggestions

Second-opinion terminology and E2E selections are advisory. Live E2E does not run automatically for pull requests.

3 semantic terminology decisions

Terminology decisions are advisory. They affect the assessment only when a separate finding identifies concrete semantic impact.

  • established — Hermes API port at src/lib/onboard/hermes-api-port.ts:34: Keep `Hermes API port` for this concept. State the sandbox-specific allocation range when the distinction affects operator action.
  • justified — per-sandbox API port at src/lib/actions/sandbox/snapshot.ts:287: Keep the modifier where the contrast with the former host-wide port affects forwarding, cloning, or recovery.
  • established — root-separated topology at agents/hermes/plugin/init.py:1047: Keep `root-separated topology` and contrast it with the same-UID topology when the identity boundary affects behavior.

E2E guidance

Advisory only. A maintainer can dispatch the default E2E suite for the commit under review.

Recommended E2E: managed-image-protected-runtime

Manual-only E2E: cloud-inference, cloud-onboard, full-e2e, hermes-e2e, hermes-inference-switch, managed-image-multiarch-startup, security-posture, bedrock-runtime-compatible-anthropic, channels-stop-start, dashboard-remote-bind, device-auth-health, hermes-shields-config, issue-4462-scope-upgrade-approval, onboard-repair, onboard-resume, openclaw-inference-switch, rebuild-openclaw, state-backup-restore
The manual PR workflow does not run these selectors for the commit under review. Run them from reviewed code on main.

3 optional E2E recommendations
  • snapshot-commands
  • concurrent-gateway-ports
  • rebuild-hermes

Workflow run details

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

@copy-pr-bot

copy-pr-bot Bot commented Aug 7, 2026

Copy link
Copy Markdown

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

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@cv cv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

agents/hermes/start.sh:3319 publishes the trusted Hermes API-port marker only on the root startup path. The supported managed non-root path exits through lines 3254-3284 without creating it. agents/hermes/mcp-config-transaction.py, agents/hermes/plugin/__init__.py, and scripts/managed-gateway-control.py then silently use port 8642. For a sandbox configured for port 8643, a sandbox user can bind 8642 and cause reload or lifecycle probes to accept the wrong listener. Publish a supervisor-owned, sandbox-user-unwritable binding before non-root helpers can run, or make those helpers fail closed when the binding is absent. Add an integration regression test that starts managed non-root Hermes on 8643, verifies the binding ownership and mode, verifies all helpers probe 8643, and proves a listener on 8642 cannot satisfy readiness.

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

🤖 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 `@agents/hermes/plugin/__init__.py`:
- Around line 1048-1051: Update the port-parsing logic around the raw marker
conversion to catch ValueError from int(raw) and return the existing 8642
fallback, including for non-ASCII digit strings accepted by isdigit(). Add a
negative-path test covering such input.

In `@src/lib/onboard/hermes-api-port.ts`:
- Around line 125-154: Update the missing-or-invalid registry-state path used by
restore_onboard_forward_after_post_checks so it reuses the persisted result from
resolveOnboardHermesApiPort instead of falling back to the fixed 8642 port. If
no valid resolved port is available, fail closed rather than starting a watcher
on the default port, and add coverage for a custom hermesApiPort followed by
invalid registry state.
🪄 Autofix

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: e00f63d3-7c15-4071-a6d8-692b6001f10a

📥 Commits

Reviewing files that changed from the base of the PR and between 7d1c24e and 38d5b86.

📒 Files selected for processing (37)
  • agents/hermes/mcp-config-transaction.py
  • agents/hermes/plugin/__init__.py
  • agents/hermes/start.sh
  • ci/source-architecture-budget.json
  • docs/deployment/deploy-to-headless-server.mdx
  • docs/deployment/set-up-mcp-bridge.mdx
  • docs/get-started/quickstart-hermes.mdx
  • docs/reference/commands.mdx
  • docs/reference/troubleshooting.mdx
  • scripts/install.sh
  • scripts/managed-gateway-control.py
  • src/commands/sandbox/agent.ts
  • src/lib/actions/sandbox/agent/passthrough-help.ts
  • src/lib/actions/sandbox/agent/passthrough.test.ts
  • src/lib/actions/sandbox/agent/passthrough.ts
  • src/lib/actions/sandbox/forward-recovery-declared-ports.test.ts
  • src/lib/actions/sandbox/forward-recovery.ts
  • src/lib/actions/sandbox/process-recovery.ts
  • src/lib/actions/sandbox/snapshot-restore-clone-ports.test.ts
  • src/lib/actions/sandbox/snapshot.ts
  • src/lib/agent/onboard.test.ts
  • src/lib/agent/onboard.ts
  • src/lib/core/ports.ts
  • src/lib/onboard/agent-dashboard-forward.ts
  • src/lib/onboard/dashboard-port.ts
  • src/lib/onboard/hermes-api-port.test.ts
  • src/lib/onboard/hermes-api-port.ts
  • src/lib/onboard/hermes-dashboard.ts
  • src/lib/onboard/managed-startup-profile.test.ts
  • src/lib/onboard/managed-startup/profile.ts
  • src/lib/onboard/preflight-ports.ts
  • src/lib/onboard/sandbox-create-launch.ts
  • src/lib/onboard/sandbox-registration.ts
  • src/lib/state/gateway-registry.ts
  • src/lib/state/registry.ts
  • src/lib/state/registry/types.ts
  • test/hermes-mcp-reload-convergence.test.ts
🚧 Files skipped from review as they are similar to previous changes (35)
  • src/commands/sandbox/agent.ts
  • src/lib/core/ports.ts
  • src/lib/state/registry.ts
  • src/lib/actions/sandbox/forward-recovery-declared-ports.test.ts
  • docs/deployment/set-up-mcp-bridge.mdx
  • docs/deployment/deploy-to-headless-server.mdx
  • ci/source-architecture-budget.json
  • src/lib/agent/onboard.test.ts
  • src/lib/onboard/managed-startup-profile.test.ts
  • src/lib/onboard/sandbox-registration.ts
  • src/lib/onboard/preflight-ports.ts
  • docs/get-started/quickstart-hermes.mdx
  • src/lib/actions/sandbox/snapshot.ts
  • scripts/managed-gateway-control.py
  • src/lib/state/gateway-registry.ts
  • src/lib/state/registry/types.ts
  • src/lib/actions/sandbox/agent/passthrough.test.ts
  • src/lib/actions/sandbox/process-recovery.ts
  • docs/reference/troubleshooting.mdx
  • src/lib/actions/sandbox/agent/passthrough.ts
  • src/lib/actions/sandbox/snapshot-restore-clone-ports.test.ts
  • src/lib/onboard/managed-startup/profile.ts
  • src/lib/onboard/hermes-dashboard.ts
  • src/lib/onboard/hermes-api-port.test.ts
  • scripts/install.sh
  • src/lib/actions/sandbox/forward-recovery.ts
  • src/lib/actions/sandbox/agent/passthrough-help.ts
  • src/lib/onboard/agent-dashboard-forward.ts
  • agents/hermes/mcp-config-transaction.py
  • agents/hermes/start.sh
  • docs/reference/commands.mdx
  • test/hermes-mcp-reload-convergence.test.ts
  • src/lib/onboard/dashboard-port.ts
  • src/lib/agent/onboard.ts
  • src/lib/onboard/sandbox-create-launch.ts

Comment thread agents/hermes/plugin/__init__.py Outdated
Comment thread src/lib/onboard/hermes-api-port.ts
The profile module is bundled into the managed image and executed directly by
node type stripping, so a relative value import broke both consumers. Declare
the Hermes API port range locally and pin it to core/ports through the profile
test.

Signed-off-by: Tinson Lai <tinsonl@nvidia.com>
Signed-off-by: Tinson Lai <tinsonl@nvidia.com>
The non-root startup path returned before the root-only marker write, so the
same-uid helpers that probe the public relay fell back to the default port. It
now publishes the marker with the identity that runs the gateway and refuses to
start when an allocated port cannot be published. Documentation states the
per-sandbox port where a page still named the default.

Signed-off-by: Tinson Lai <tinsonl@nvidia.com>
Rerunning onboarding with NEMOCLAW_HERMES_API_PORT and without
--recreate-sandbox moves the host forward while the relay keeps the recorded
port, which is the opposite of what the reference stated.

Signed-off-by: Tinson Lai <tinsonl@nvidia.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 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 `@agents/hermes/start.sh`:
- Around line 2915-2929: Update both current-user and root API-port marker
publication paths, including publish_hermes_api_port_marker_current_user and the
corresponding root flow, to write the value to a temporary file, apply final
permissions (and root ownership where applicable), then atomically rename it
into place. Remove the successful default-port fallback when cleanup or
replacement fails: if an old marker remains or publication cannot complete, fail
closed with a nonzero result. Add restart coverage for stale markers and
publication failures.
- Around line 3342-3344: Harden the marker publication around
HERMES_API_PORT_MARKER by validating that its parent directory is a real
root-owned, non-writable directory before writing. Replace the direct printf
redirection with a root-created temporary file in that directory, set its
contents and permissions, then atomically rename it to the marker so planted
symlinks cannot be followed; add a negative test covering a pre-existing marker
symlink.

In `@docs/security/credential-rotation.mdx`:
- Around line 219-221: Update the credential-rotation commands to use the
placeholder <api-port> instead of the literal 8642, including forwarding and API
probe commands. Explicitly instruct users to replace <api-port> with the port
shown for their selected <sandbox> by openshell forward list, while preserving
the existing first-sandbox context.

In `@src/lib/onboard/managed-startup-profile.test.ts`:
- Around line 978-986: Update the test around validateManagedStartupProfile to
iterate through every port from HERMES_API_PORT_RANGE_START through
HERMES_API_PORT_RANGE_END inclusively, asserting each reserved port throws.
Preserve or add adjacent-port assertions to confirm ports immediately outside
the declared range remain accepted.

In `@test/hermes-api-port-marker.test.ts`:
- Around line 15-33: Remove both conditionals from
runHermesApiPortMarkerPublication by extracting the runtime-parent and
stale-marker setup variants into named helpers, such as writable, blocked, and
read-only-stale-marker setups. Update the runner to accept and invoke the
selected setup helper so its body remains linear while preserving the existing
test scenarios.
🪄 Autofix

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: 0f741197-7e5c-4cb9-8f95-03fa38a1feb2

📥 Commits

Reviewing files that changed from the base of the PR and between 38d5b86 and 1b819cc.

📒 Files selected for processing (19)
  • agents/hermes/mcp-config-transaction.py
  • agents/hermes/plugin/__init__.py
  • agents/hermes/start.sh
  • ci/source-architecture-budget.json
  • docs/get-started/quickstart-hermes.mdx
  • docs/manage-sandboxes/run-sandboxes.mdx
  • docs/reference/commands.mdx
  • docs/reference/troubleshooting.mdx
  • docs/security/credential-rotation.mdx
  • scripts/managed-gateway-control.py
  • src/lib/actions/sandbox/agent/passthrough-help.ts
  • src/lib/actions/sandbox/forward-recovery-declared-ports.test.ts
  • src/lib/agent/onboard.test.ts
  • src/lib/agent/onboard.ts
  • src/lib/onboard/managed-startup-profile.test.ts
  • src/lib/onboard/managed-startup/profile.ts
  • test/hermes-api-port-marker.test.ts
  • test/mcp-tool-discovery-image-contract.test.ts
  • tools/mcp-tool-discovery-runtime/reviewed-runtime-bundle/managed-startup-image-runtime.bundle
🚧 Files skipped from review as they are similar to previous changes (12)
  • docs/get-started/quickstart-hermes.mdx
  • src/lib/actions/sandbox/agent/passthrough-help.ts
  • scripts/managed-gateway-control.py
  • src/lib/actions/sandbox/forward-recovery-declared-ports.test.ts
  • docs/reference/troubleshooting.mdx
  • agents/hermes/plugin/init.py
  • src/lib/agent/onboard.ts
  • src/lib/agent/onboard.test.ts
  • src/lib/onboard/managed-startup/profile.ts
  • ci/source-architecture-budget.json
  • agents/hermes/mcp-config-transaction.py
  • docs/reference/commands.mdx

Comment thread agents/hermes/start.sh Outdated
Comment thread agents/hermes/start.sh Outdated
Comment thread docs/security/credential-rotation.mdx Outdated
Comment thread src/lib/onboard/managed-startup-profile.test.ts
Comment thread test/hermes-api-port-marker.test.ts Outdated
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
Comment thread scripts/managed-gateway-control.py Fixed
Comment thread scripts/managed-gateway-control.py Fixed
Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
@prekshivyas

Copy link
Copy Markdown
Collaborator

Addressed every current inline review thread in b0ff41f: added the non-root marker-owner rejection, made both probe fixtures independent of host PyYAML, and put all temporary setup under guaranteed cleanup (including the older TemporaryDirectory suggestion). Focused integration and installer suites passed 11/11, repository commit gates passed, and the exact pre-push CLI typecheck passed. The new head starts a clean all-job CI attempt, avoiding the prior attempt-1/attempt-2 managed-contract artifact mismatch. @cv please re-review after the fresh checks complete.

@prekshivyas
prekshivyas requested a review from cv August 11, 2026 18:56
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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/managed-image-activation-e2e-helpers.ts`:
- Around line 363-368: Update the container-log collection in the managed
activation failure helper around host.command to stop persisting raw docker
logs. Replace docker logs --tail 1000 with approved content-free metadata or a
bounded safe diagnostic, while preserving the existing artifact naming,
environment, timeout, and redaction configuration as applicable.
🪄 Autofix

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: 9fc4c8bd-a6f4-46a9-ba7b-3cce9af8423c

📥 Commits

Reviewing files that changed from the base of the PR and between b0ff41f and e839d4a.

📒 Files selected for processing (1)
  • test/e2e/live/managed-image-activation-e2e-helpers.ts

Comment thread test/e2e/live/managed-image-activation-e2e-helpers.ts Outdated
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
@prekshivyas

Copy link
Copy Markdown
Collaborator

Addressed the remaining exact managed-runtime activation request at head 016ab4352f74430c9b19dbda67856898ad37d402.

  • Refreshed this branch onto current main (9ac22da56), bringing in the newly landed transient/narrow forward-readiness retry fixes from fix(onboard): retry transient forward readiness #8826 and fix(onboard): narrow forward readiness retry #8828. The prior branch base (e9dc6ba) predated both fixes; current-main exact activation runs are passing.
  • Re-ran the focused Hermes/port/supervisor/headless coverage: 7 files, 137 tests passed.
  • Rebuilt both the CLI and nested package successfully.
  • Manually ran the pre-push gate successfully.

The pushed head has now triggered the requested exact all-agent managed runtime activation workflow; that remote privileged job is the authoritative E2E proof.

# Conflicts:
#	test/mcp-tool-discovery-image-contract.test.ts
#	tools/mcp-tool-discovery-runtime/reviewed-runtime-bundle/managed-startup-image-runtime.bundle
@github-actions github-actions Bot added v0.0.108 Release target and removed v0.0.107 labels Aug 11, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (1)
agents/hermes/plugin/__init__.py (1)

325-332: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Honor security.allow_private_urls in the runtime URL guard.

_install_broker_url_safety_patch() resolves the flag, but _broker_safe_url() never reads it. Private URLs remain blocked even when the value is true. _load_hermes_config() also parses YAML without schema validation. Add end-to-end tests for missing, non-boolean, False, and explicit True values.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@agents/hermes/plugin/__init__.py` around lines 325 - 332, Update
_broker_safe_url() to read browser_tool._allow_private_urls_resolved and permit
private URLs only when it is explicitly true, while preserving the default
blocking behavior for missing, non-boolean, or false values. Ensure
_load_hermes_config() validates the parsed YAML schema before resolving
security.allow_private_urls, and add end-to-end coverage for missing, invalid
non-boolean, false, and explicit true configurations.

Source: Path instructions

🧹 Nitpick comments (1)
agents/hermes/plugin/__init__.py (1)

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

Use direct assignment for the fixed attribute name.

Ruff B010 flags this setattr call because the attribute name is constant. Replace it with direct assignment. This preserves the resolved boolean value and removes the lint warning.

Proposed fix
-            setattr(browser_tool, "_allow_private_urls_resolved", allow_private_urls)
+            browser_tool._allow_private_urls_resolved = allow_private_urls
🤖 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 `@agents/hermes/plugin/__init__.py` at line 332, Replace the setattr call
assigning _allow_private_urls_resolved with direct attribute assignment on
browser_tool, preserving the existing allow_private_urls value.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/e2e/live/managed-image-activation-e2e-helpers.ts`:
- Around line 410-416: Replace the direct spawnSync call in the docker logs flow
with the project’s audited, progress-aware non-persisting helper for bounded
raw-output capture. Preserve the existing 30-second timeout, SIGKILL behavior,
output limit, environment, and container log arguments, and ensure the result is
not routed through normal artifact capture.

---

Outside diff comments:
In `@agents/hermes/plugin/__init__.py`:
- Around line 325-332: Update _broker_safe_url() to read
browser_tool._allow_private_urls_resolved and permit private URLs only when it
is explicitly true, while preserving the default blocking behavior for missing,
non-boolean, or false values. Ensure _load_hermes_config() validates the parsed
YAML schema before resolving security.allow_private_urls, and add end-to-end
coverage for missing, invalid non-boolean, false, and explicit true
configurations.

---

Nitpick comments:
In `@agents/hermes/plugin/__init__.py`:
- Line 332: Replace the setattr call assigning _allow_private_urls_resolved with
direct attribute assignment on browser_tool, preserving the existing
allow_private_urls value.
🪄 Autofix

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: 36bb9bf8-d173-4754-abc5-163728ac87bb

📥 Commits

Reviewing files that changed from the base of the PR and between b0ff41f and bac2935.

📒 Files selected for processing (12)
  • agents/hermes/plugin/__init__.py
  • docs/get-started/quickstart-hermes.mdx
  • docs/reference/commands.mdx
  • docs/reference/troubleshooting.mdx
  • scripts/install.sh
  • src/commands/sandbox/agent.ts
  • src/lib/actions/sandbox/process-recovery.ts
  • src/lib/onboard/sandbox-registration.ts
  • src/lib/state/registry.ts
  • src/lib/state/registry/types.ts
  • test/e2e/live/managed-image-activation-e2e-helpers.ts
  • test/e2e/support/managed-image-activation-diagnostics.test.ts
🚧 Files skipped from review as they are similar to previous changes (9)
  • src/commands/sandbox/agent.ts
  • docs/get-started/quickstart-hermes.mdx
  • src/lib/actions/sandbox/process-recovery.ts
  • src/lib/onboard/sandbox-registration.ts
  • src/lib/state/registry/types.ts
  • scripts/install.sh
  • src/lib/state/registry.ts
  • docs/reference/troubleshooting.mdx
  • docs/reference/commands.mdx

Comment thread test/e2e/live/managed-image-activation-e2e-helpers.ts Outdated

@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 `@docs/reference/troubleshooting.mdx`:
- Around line 3312-3313: Update the manual migration guidance in the
recreate-sandbox documentation to state that NEMOCLAW_HERMES_API_PORT must be
set to an available port in the inclusive range 8642–8652, preserving the
existing explanation about retaining the recorded port when the variable is
omitted.
🪄 Autofix

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: a5168fc6-9dca-4073-92ab-f8db9794240d

📥 Commits

Reviewing files that changed from the base of the PR and between bac2935 and a5fd737.

📒 Files selected for processing (8)
  • docs/deployment/deploy-to-headless-server.mdx
  • docs/get-started/quickstart-hermes.mdx
  • docs/manage-sandboxes/backup-restore.mdx
  • docs/manage-sandboxes/run-sandboxes.mdx
  • docs/reference/commands.mdx
  • docs/reference/troubleshooting.mdx
  • docs/security/credential-rotation.mdx
  • src/lib/actions/sandbox/gateway-restart.ts
🚧 Files skipped from review as they are similar to previous changes (5)
  • docs/manage-sandboxes/run-sandboxes.mdx
  • docs/get-started/quickstart-hermes.mdx
  • docs/security/credential-rotation.mdx
  • docs/reference/commands.mdx
  • docs/deployment/deploy-to-headless-server.mdx

Comment thread docs/reference/troubleshooting.mdx
The launch harnesses assembled a runnable script from the start script's own
functions, but the launch path now delegates the background process to a
separate helper. Without it the generated script reached the call and exited
127.

Signed-off-by: Tinson Lai <tinsonl@nvidia.com>
Publishing the API port marker asserted that the runtime directory was already
root-owned with mode 0755 and refused startup otherwise, where the previous
code reset both. The managed runtime presents that directory before the
root-separated gateway starts, so the assertion crash-looped the container.
Startup now restores the owner and mode from root and refuses only when the
restore is not permitted, and the activation diagnostics name which Hermes
refusal ended the container.

Signed-off-by: Tinson Lai <tinsonl@nvidia.com>
Container log capture ran through a direct synchronous spawn to keep raw output
out of the artifact sink. The shell probe now accepts a non-persisting run, so
the capture keeps the bounded timeout, kill signal, output limit, and redaction
of every other probe without writing the logs.

Signed-off-by: Tinson Lai <tinsonl@nvidia.com>
Signed-off-by: Tinson Lai <tinsonl@nvidia.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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/fixtures/shell-probe.ts`:
- Around line 31-32: Update the persistArtifacts documentation near
ShellProbe.run to describe the actual behavior: output is redacted and
size-bounded before persistence, and setting it to false also prevents writing
the result JSON artifact; do not describe the retained data as raw output.
🪄 Autofix

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: 36e3261f-57a0-4b54-9705-ac94697b500c

📥 Commits

Reviewing files that changed from the base of the PR and between e7febca and 6234714.

📒 Files selected for processing (3)
  • docs/reference/troubleshooting.mdx
  • test/e2e/fixtures/shell-probe.ts
  • test/e2e/live/managed-image-activation-e2e-helpers.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • docs/reference/troubleshooting.mdx
  • test/e2e/live/managed-image-activation-e2e-helpers.ts

Comment thread test/e2e/fixtures/shell-probe.ts Outdated
@cv
cv dismissed their stale review August 12, 2026 10:07

The latest PR commit uses the selected Hermes API port, has passing managed-startup evidence, and retains the verified marker contract. Dismissing this resolved review before a full current-commit review.

github-actions Bot and others added 2 commits August 12, 2026 10:11
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 bug-fix PR fixes a bug or regression feature PR adds or expands user-visible functionality integration: hermes Hermes integration behavior v0.0.108 Release target

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Ubuntu 24.04][Sandbox] snapshot clone cannot restore its inference host forward

5 participants