Skip to content

fix(inference): contain shared gateway route conflicts#6338

Merged
cv merged 45 commits into
mainfrom
fix/6315-gateway-route-containment
Jul 7, 2026
Merged

fix(inference): contain shared gateway route conflicts#6338
cv merged 45 commits into
mainfrom
fix/6315-gateway-route-containment

Conversation

@ericksoa

@ericksoa ericksoa commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Summary

Contain the current one-route-per-OpenShell-gateway behavior so onboarding, runtime inference switches, and connect-time repair cannot silently change the route used by another registered sandbox. This is a compatibility guard for the current OpenShell contract; true simultaneous per-sandbox routing remains upstream work.

Related Issue

Addresses #6315

Changes

  • Compare the requested provider/model and custom endpoint/API family with every durable registry row on the target gateway, including stopped sandboxes.
  • Allow identical routes and different gateways; fail closed for same-gateway conflicts, missing durable provider/model identity, incomplete legacy custom-route identity, and invalid gateway bindings.
  • Run the guard before onboarding setup, resumed setup, runtime inference set, connect-time route writes, endpoint probes, or repair mutations.
  • Serialize route-sensitive onboarding, runtime switches, connect repair, snapshot restore, and registry recovery per gateway; different gateways remain independent.
  • Persist a full pending route reservation before verification/smoke checks, and revalidate the target reservation under the gateway lock before creating or reusing a sandbox.
  • Resolve inference set -g from the target sandbox's recorded gateway instead of hardcoding the default gateway.
  • Keep missing-flag guidance inside NemoClaw so users do not bypass the shared-route protection with raw OpenShell commands.
  • Document the one-route-per-gateway contract and recovery options: align routes, remove the conflicting sandbox, or use another NEMOCLAW_GATEWAY_PORT.

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: exact head 7df7274c passed an independent nine-category security review with no findings; the maintainer disposition, exact-head E2E evidence, and manual validation procedure are recorded here.
  • 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 — all 45 PR commits are GitHub-verified and signed off at 7df7274c138efe4080993378863a21b4567db842.
  • Normal pre-commit, commit-msg, and pre-push hooks passed, or npm run check:diff passed when hooks were skipped or unavailable — normal pre-commit, commit-msg, and pre-push hooks passed for the merge-resolution and documentation commits at exact head 7df7274c.
  • Targeted behavior tests pass for the current change set, or tests are marked not applicable above — 93 conflict-focused assertions and CLI typecheck passed locally after the merge; an independent exact-head security pass reran 108 focused assertions across route locking, DNS finalization, late peers, incomplete recovered rows, aliases, SSRF no-bypass behavior, connect/onboard containment, and local-provider probes.
  • Applicable broad gate passed — refreshed exact-head CI run 28893800691 passed all five CLI shards, aggregate tests/checks, build/typecheck, installer, plugin, security, docs, macOS/WSL, self-hosted, and growth-guard jobs; all five required contexts pass.
  • 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) — 0 errors; Fern reports two pre-existing hidden warnings.
  • Doc pages follow the style guide (doc changes only)
  • New doc pages include SPDX header and frontmatter (new pages only)

Additional validation: CLI typecheck, formatting, source/test budgets, the Fern docs build, and normal git hooks passed for the final merge and docs changes at 7df7274c. The top-level src/lib/onboard.ts is net-neutral against the PR base (+139/-139). This branch includes main through 376ebe2ed18f71555aca0d139337e7f6a9a76e90. The DCode default-model conflict in setup-nim-flow.ts was resolved additively: DCode retains its Ultra default and logger, while same-gateway discovery constraints, pre-probe checks, exact route checks, and API coercion remain intact; the combined interaction is now regression-tested. The later rebuild loader-seam merge was conflict-free. The race coverage includes same-gateway serialization, independent gateways, DNS-normalized endpoint changes between preliminary and finalized checks, gateway-binding changes while queued, pending-reservation loss, snapshot pre-delete rejection, recovered rows with incomplete durable route identity, and zero-mutation conflict exits. The earlier isolated OpenShell 0.0.72 proof 2026-07-06T23-01-11-471Z-pid-7719 remains applicable to the unchanged live containment path: identical same-gateway onboarding succeeded; a conflicting same-gateway onboard named both peers, made zero conflicting endpoint probes, and left the first route, providers, sandboxes, forwards, configs, containers, images, volumes, registry, credentials, gateway PID, and data plane unchanged; the same conflicting route succeeded on a separate gateway without changing gateway A; all cleanup checks passed. Final exact-head E2E passed every refreshed advisor requirement: run 28893935439 covered resume/repair, cloud onboarding, inference routing, both OpenClaw variants, both Hermes variants, double-onboard, and concurrent gateway ports; run 28893939992 passed the canonical OpenClaw cloud target; and run 28894237287 passed sandbox operations and snapshot commands. Exact-head GPT-5.5 attempt 2 reports zero required findings and one runtime-test warning. The explicit maintainer acceptance of that residual checked-in-target gap, its rationale, exact-head live evidence, and reproducible manual validation procedure are recorded here. Nemotron's only required item applies an unenforced 20-line growth heuristic even though the repository's 1,500-line test budget passes. An independent exact-head audit found no remaining product or security defect.

Advisor scope rationale
  • The two-phase custom-route check is intentional: the synchronous preliminary guard rejects known registry conflicts before endpoint work, then asynchronous DNS validation feeds a fresh-registry final guard before any OpenShell, config, or registry mutation. The removal condition is concrete: collapse the phases only when preparation can consume fully DNS-validated metadata without an earlier endpoint probe or mutation.
  • Registry recovery never invents missing route identity, probes an endpoint, or changes the live gateway route. Complete recovered identities are compatibility-checked; a durable recovered row with missing provider/model is preserved for inventory but makes every later same-gateway route mutation fail closed until the row is removed and re-onboarded. DNS pinning remains at the later endpoint-use/mutation boundary.
  • Snapshot restore compares the recorded route through the shared compatibility guard under the gateway mutation lock. It does not introduce or probe a new custom endpoint, so adding a second DNS-pinning path there would duplicate the endpoint-use boundary without closing a mutation gap.
  • Both the ambient OPENSHELL_GATEWAY_ENDPOINT environment path and the explicit endpoint flag are rejected or validated at their entry boundaries; neither bypasses the compatibility guard.
  • Further splits of connect.ts, provider onboarding, and the focused containment test files would be structural refactors without changing this issue's behavior. All affected files remain within the repository's enforced source/test budgets, so those splits are deferred to avoid widening the containment PR and its regression surface.
  • The OpenShell 0.0.72 proof above covers the same-gateway conflict contract and separate-gateway success path; the refreshed exact-head E2E run covers onboarding, repair, switching, sandbox operations, multi-gateway behavior, and stale rebuild.
  • Overlapping PR merge order requires maintainer coordination: this branch contains main through 376ebe2e; overlapping route-changing work should rebase after this containment change lands. No change inside this PR can safely rewrite those independent branches.
  • Validation failures are intentionally converted to credential-safe InferenceSetError messages. Preserving raw URL/DNS error causes would risk exposing untrusted endpoint detail and is not required for the fail-closed behavior.

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

ericksoa added 4 commits July 6, 2026 11:28
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
…e-containment

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@ericksoa ericksoa added bug area: inference Inference routing, serving, model selection, or outputs area: sandbox OpenShell sandbox lifecycle, runtime, config, or recovery area: docs Documentation, examples, guides, or docs build labels Jul 6, 2026
@ericksoa ericksoa requested a review from cv July 6, 2026 18:37
@ericksoa ericksoa added the needs: review PR is conflict-free and awaiting maintainer review label Jul 6, 2026
@ericksoa ericksoa requested a review from prekshivyas July 6, 2026 18:37
@github-code-quality

github-code-quality Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

The overall coverage in the branch is 96%. Coverage data for the branch is not yet available.

Show a code coverage summary of the most covered files.
File 7df7274 +/-
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 branch is 75%. Coverage data for the branch is not yet available.

Show a code coverage summary of the most covered files.
File 7df7274 +/-
src/lib/onboard/preflight.ts 83%
src/lib/actions...all/run-plan.ts 81%
src/lib/state/o...oard-session.ts 80%
src/lib/actions...licy-channel.ts 79%
src/lib/state/sandbox.ts 75%
src/lib/actions...dbox/connect.ts 72%
src/lib/onboard...er-gpu-patch.ts 69%
src/lib/policy/index.ts 66%
src/lib/shields/index.ts 61%
src/lib/onboard.ts 28%

Updated July 07, 2026 19:53 UTC
Code Coverage is in Public Preview. Learn more and provide us with your feedback.

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

@coderabbitai

coderabbitai Bot commented Jul 6, 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

This PR adds gateway-scoped inference route compatibility checks across inference setup, route switching, and sandbox connect flows. It also updates missing-flag CLI messaging and documents the shared-gateway routing rules, conflict handling, and remediation paths.

Changes

Gateway route compatibility feature

Layer / File(s) Summary
Gateway route compatibility core module
src/lib/inference/gateway-route-compatibility.ts, src/lib/inference/gateway-route-compatibility.test.ts
Defines route/conflict types, compatibility checking, conflict formatting, and error/assertion helpers, with tests for provider/model, custom-route, incomplete-metadata, and invalid-binding cases.
Inference-set route preparation and gateway scoping
src/lib/actions/inference-set.ts, src/lib/actions/inference-set-route-containment.ts, src/lib/actions/inference-set-*.test.ts
Resolves gateway-scoped route metadata, validates custom endpoints and API families, rechecks compatibility before and after endpoint materialization, and updates inference-set command wiring and tests.
Sandbox connect route repair compatibility gate
src/lib/actions/sandbox/connect.ts, src/lib/actions/sandbox/connect-inference-gateway.ts, src/lib/actions/sandbox/connect-route-*.test.ts, test/support/connect-flow-test-harness.ts
Adds gateway-aware inference get/set builders, checks compatibility before repair and route reset, handles compatibility conflicts as exit-1 errors, and extends the connect harness for multiple registry entries.
Onboarding and provider selection compatibility gating
src/lib/onboard.ts, src/lib/onboard/setup-inference.ts, src/lib/onboard/inference-route.ts, src/lib/onboard/gateway-provider-metadata.ts, src/lib/onboard/resume-provider-shim.ts, src/lib/onboard/machine/core-flow-phases.ts, src/lib/onboard/machine/handlers/provider-inference*.ts, src/lib/onboard/provider-host-state.ts, src/lib/onboard/setup-nim-flow.ts, src/lib/onboard/setup-nim-ollama.ts, src/lib/onboard/setup-nim-vllm.ts, test/support/setup-inference-test-harness.ts, related tests
Threads gateway-name and route-compatibility dependencies through onboarding, resume, host probing, and NIM/vLLM/Ollama selection flows, and updates tests/harnesses for conflict handling.
CLI required-flags messaging for inference set
src/commands/inference/set.ts, src/commands/sandbox/inference/set.ts, src/lib/cli/inference-set-help.ts, test/cli/list-inference.test.ts, src/commands/sandbox/inference/oclif-command-adapters.test.ts
Replaces the prior redirect-style missing-flag guidance with shared required-flags messaging for inference set commands.
Documentation updates for shared gateway routes
docs/inference/switch-inference-providers.mdx, docs/reference/commands.mdx, docs/reference/commands-nemohermes.mdx, docs/reference/troubleshooting.mdx, docs/about/release-notes.mdx
Documents the one-route-per-gateway model, connect-time repair checks, inference set validation rules, and troubleshooting/recovery steps.
Model metadata and probe support
src/lib/inference/nim.ts, src/lib/inference/nim-route-identity.test.ts, bin/lib/nim-images.json
Adds served-model identity support for NIM catalog entries and updates the associated route-identity test fixture.
vLLM served-model and install flow
src/lib/inference/vllm.ts, src/lib/inference/vllm.test.ts, src/lib/onboard/setup-nim-vllm.ts, src/lib/onboard/setup-nim-vllm.test.ts
Adds served-model resolution and a vLLM install preflight hook, with tests covering the new served-model and install behavior.

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

Sequence Diagram(s)

sequenceDiagram
  participant runInferenceSet
  participant prepareInferenceSetRoute
  participant finalizeInferenceSetRoute
  participant checkGatewayRouteCompatibility
  participant OpenShell
  runInferenceSet->>prepareInferenceSetRoute: derive route metadata
  prepareInferenceSetRoute->>checkGatewayRouteCompatibility: preliminary compatibility check
  runInferenceSet->>finalizeInferenceSetRoute: materialize custom endpoint identity
  finalizeInferenceSetRoute->>checkGatewayRouteCompatibility: final compatibility check
  runInferenceSet->>OpenShell: run inference set with gatewayName
Loading
sequenceDiagram
  participant runOnboard
  participant setupInferenceWithDeps
  participant handleProviderInferenceState
  participant checkGatewayRouteCompatibility
  runOnboard->>setupInferenceWithDeps: initialize gateway-scoped setup
  setupInferenceWithDeps->>checkGatewayRouteCompatibility: gate setup route
  handleProviderInferenceState->>checkGatewayRouteCompatibility: validate resume route
Loading

Possibly related PRs

  • NVIDIA/NemoClaw#3193: Changes src/lib/actions/sandbox/connect.ts route repair behavior in a nearby area that this PR further constrains with gateway-scoped compatibility checks.
  • NVIDIA/NemoClaw#3354: Touches the same inference set/Hermes routing paths that this PR expands with gateway-wide route enforcement.

Suggested labels: bug-fix

Suggested reviewers: jyaunches, cjagwani

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: containing shared gateway route conflicts in inference flows.
✨ 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/6315-gateway-route-containment

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

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor (Nemotron Ultra) — Changes requested

Merge posture: Do not merge yet
Primary next action: Fix PRA-1: Multiple test files exceed monolith growth threshold by 20+ lines; then add or justify PRA-T1.
Open items: 2 required · 3 warnings · 14 suggestions · 6 test follow-ups
Since last review: 0 prior items resolved · 0 still apply · 20 new items found

Action checklist

  • PRA-1 Fix: Multiple test files exceed monolith growth threshold by 20+ lines in src/lib/actions/inference-set-gateway-route-containment.test.ts:1
  • PRA-2 Fix: Multiple source files exceed monolith growth threshold by 20+ lines in src/lib/onboard/setup-inference.ts:1
  • PRA-3 Resolve or justify: Legacy incomplete route handling is a workaround, not a source fix in src/lib/actions/inference-set-route-containment.ts:180
  • PRA-4 Resolve or justify: Gateway route mutation lock integration tests could be deeper in src/lib/actions/inference-set-gateway-route-containment.test.ts:450
  • PRA-5 Resolve or justify: Test file size budget not updated for new/expanded test files in ci/test-file-size-budget.json: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: Gateway route mutation lock integration tests could be deeper
  • PRA-6 In-scope improvement: NIM Nano model adds servedModel field in bin/lib/nim-images.json:8
  • PRA-7 In-scope improvement: inference-set-route-containment.ts could be split for maintainability in src/lib/actions/inference-set-route-containment.ts:1
  • PRA-8 In-scope improvement: gateway-route-compatibility.ts could extract shared peer iteration logic in src/lib/inference/gateway-route-compatibility.ts:1
  • PRA-9 In-scope improvement: Shared gateway route containment prevents cross-sandbox inference interference in src/lib/inference/gateway-route-compatibility.ts:1
  • PRA-10 In-scope improvement: DNS-pinning SSRF guard validates custom endpoints before gateway mutation in src/lib/actions/inference-set-route-containment.ts:115
  • PRA-11 In-scope improvement: Incomplete legacy custom routes fail closed instead of silently inheriting in src/lib/actions/inference-set-route-containment.ts:180
  • PRA-12 In-scope improvement: Gateway route mutation lock prevents TOCTOU race conditions in src/lib/inference/gateway-route-mutation-lock.ts:1
  • PRA-13 In-scope improvement: Ambient OPENSHELL_GATEWAY_ENDPOINT and --gateway-endpoint rejected before mutation in src/lib/openshell-gateway-endpoint-guard.ts:1
  • PRA-14 In-scope improvement: Hermes compatible-anthropic-endpoint forced to OpenAI frontend in src/lib/actions/inference-set.ts:280
  • PRA-15 In-scope improvement: Installer provider aliases normalized to OpenShell names for inference set in src/lib/actions/inference-set.ts:90

Findings index

ID Severity Category Location Required action
PRA-1 Required correctness src/lib/actions/inference-set-gateway-route-containment.test.ts:1 Update ci/test-file-size-budget.json with legacyMaxLines entries for each new/expanded test file, OR extract cohesive test modules (e.g., separate DNS-pinning tests, mutation-lock tests, legacy-route tests) to stay under defaultMaxLines (1500).
PRA-2 Required correctness src/lib/onboard/setup-inference.ts:1 Extract gateway route containment integration logic into smaller helper modules, or offset growth by deleting/compressing other code in these files. Consider moving the compatibility check calls into the new dedicated modules rather than inline in each handler.
PRA-3 Resolve/justify security src/lib/actions/inference-set-route-containment.ts:180 Add a telemetry or audit log entry when the legacy incomplete-route error is triggered, to track adoption of the re-onboard fix and know when the workaround can be removed. Consider adding a `nemoclaw doctor` check that flags incomplete legacy routes.
PRA-4 Resolve/justify tests src/lib/actions/inference-set-gateway-route-containment.test.ts:450 Add tests for: lock timeout when holder crashes, cross-process contention with multiple CLI invocations, and lock acquisition ordering under load.
PRA-5 Resolve/justify correctness ci/test-file-size-budget.json:1 Add legacyMaxLines entries for each new/expanded test file, or extract test modules to stay under defaultMaxLines (1500).
PRA-6 Improvement correctness bin/lib/nim-images.json:8 Verify the servedModel field is consumed in route identity logic or remove if unused. If for future use, add a comment explaining purpose.
PRA-7 Improvement correctness src/lib/actions/inference-set-route-containment.ts:1 Move normalizeCustomEndpointUrlWithoutDns and normalizeEndpointUrlShape to core/url-utils.ts alongside canonicalEndpoint. Keep DNS-pinning logic in this file.
PRA-8 Improvement correctness src/lib/inference/gateway-route-compatibility.ts:1 Extract common peer filtering (by gatewayName) and gateway name resolution into a private helper function used by both public functions.
PRA-9 Improvement security src/lib/inference/gateway-route-compatibility.ts:1 No action needed - security feature correctly implemented.
PRA-10 Improvement security src/lib/actions/inference-set-route-containment.ts:115 No action needed - SSRF guard correctly implemented.
PRA-11 Improvement security src/lib/actions/inference-set-route-containment.ts:180 No action needed - fail-closed behavior correct.
PRA-12 Improvement security src/lib/inference/gateway-route-mutation-lock.ts:1 No action needed - mutation lock correctly implemented.
PRA-13 Improvement security src/lib/openshell-gateway-endpoint-guard.ts:1 No action needed - guard correctly implemented.
PRA-14 Improvement security src/lib/actions/inference-set.ts:280 No action needed - protocol enforcement correctly implemented.
PRA-15 Improvement correctness src/lib/actions/inference-set.ts:90 No action needed - alias normalization correct.
PRA-16 Improvement correctness src/lib/actions/sandbox/connect.ts:1 No action needed - connect containment correct.
PRA-17 Improvement correctness src/lib/onboard/setup-inference.ts:50 No action needed - onboarding containment correct.
PRA-18 Improvement correctness src/lib/registry-recovery-action.ts:60 No action needed - recovery containment correct.
PRA-19 Improvement acceptance docs/about/release-notes.mdx:52 No action needed - documentation complete.

🚨 Required before merge

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

PRA-1 Required — Multiple test files exceed monolith growth threshold by 20+ lines

  • Location: src/lib/actions/inference-set-gateway-route-containment.test.ts:1
  • Category: correctness
  • Problem: Five new or significantly expanded test files grow by 200-500+ lines each without offsetting extraction: - src/lib/actions/inference-set-gateway-route-containment.test.ts (new, 508 lines) - src/lib/actions/sandbox/connect-route-containment.test.ts (new, 401 lines) - src/lib/onboard/setup-nim-flow.test.ts (+253 lines) - src/lib/onboard/machine/handlers/provider-inference.test.ts (+180 lines) - src/lib/onboard/machine/handlers/sandbox-route-mutation-lock.test.ts (new, 123 lines) - src/lib/registry-recovery-action.test.ts (+52 lines) - src/lib/actions/sandbox/snapshot.test.ts (+49 lines) - src/lib/state/registry-route-reservation.test.ts (new, 88 lines) - src/lib/onboard/gateway-binding.test.ts (+56 lines) - src/lib/onboard/machine/core-flow-phases.test.ts (+53 lines) Per rubric item 7, E2E/test suite simplicity: new test files should favor focused tests and local helpers over new framework layers. These appear to be unit/integration tests for the new gateway containment feature, but the growth is concentrated in few files rather than distributed.
  • Impact: CI test-file-size-budget job will fail unless budget is updated or files are extracted. Large test files reduce maintainability and make targeted test runs harder.
  • Required action: Update ci/test-file-size-budget.json with legacyMaxLines entries for each new/expanded test file, OR extract cohesive test modules (e.g., separate DNS-pinning tests, mutation-lock tests, legacy-route tests) to stay under defaultMaxLines (1500).
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Run `cat ci/test-file-size-budget.json` and compare legacyMaxLines entries against current file line counts. The budget was updated for test/onboard.test.ts (-14 lines) but not for these new/expanded files.
  • Missing regression test: Test file size budget should be updated with new legacyMaxLines entries for each expanded test file, or the test content should be extracted into smaller focused modules. The PR adds 11 test files but only updates budget for one existing file.
  • Done when: The required change is committed and verification passes: Run `cat ci/test-file-size-budget.json` and compare legacyMaxLines entries against current file line counts. The budget was updated for test/onboard.test.ts (-14 lines) but not for these new/expanded files.
  • Evidence: Drift context monolithDeltas shows 10 test files with severity=blocker (delta >= 20 lines). ci/test-file-size-budget.json only updated test/onboard.test.ts.

PRA-2 Required — Multiple source files exceed monolith growth threshold by 20+ lines

  • Location: src/lib/onboard/setup-inference.ts:1
  • Category: correctness
  • Problem: Eight source files grow by 60-138 lines each: - src/lib/onboard/setup-inference.ts (+138 lines) - src/lib/onboard/machine/handlers/provider-inference.ts (+136 lines) - src/lib/onboard/setup-nim-flow.ts (+121 lines) - src/lib/registry-recovery-action.ts (+98 lines) - src/lib/actions/sandbox/connect.ts (+66 lines) - src/lib/onboard/machine/handlers/sandbox.ts (+63 lines) - src/lib/actions/sandbox/snapshot.ts (+59 lines) - src/lib/state/registry.ts (+49 lines) - src/lib/inference/vllm.ts (+27 lines) Several of these are core onboarding/sandbox handlers already at 600-1000+ lines. The growth adds gateway route containment checks, mutation locks, and compatibility validation throughout the flow.
  • Impact: Large source files reduce readability, increase cognitive load, and make future changes riskier. The new gateway-route-compatibility and gateway-route-mutation-lock modules exist but integration points still add significant bulk to callers.
  • Required action: Extract gateway route containment integration logic into smaller helper modules, or offset growth by deleting/compressing other code in these files. Consider moving the compatibility check calls into the new dedicated modules rather than inline in each handler.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check `git diff main...HEAD --stat` for line deltas on these files. The drift context shows each with severity=blocker.
  • Missing regression test: Consider extracting gateway route containment logic into the new dedicated modules (gateway-route-compatibility.ts, gateway-route-mutation-lock.ts) rather than growing existing handlers. The new modules exist but the integration points still add significant bulk.
  • Done when: The required change is committed and verification passes: Check `git diff main...HEAD --stat` for line deltas on these files. The drift context shows each with severity=blocker.
  • Evidence: Drift context monolithDeltas shows 9 source files with severity=blocker (delta >= 20 lines).
Review findings by urgency: 2 required fixes, 3 items to resolve/justify, 14 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-3 Resolve/justify — Legacy incomplete route handling is a workaround, not a source fix

  • Location: src/lib/actions/inference-set-route-containment.ts:180
  • Category: security
  • Problem: The PR handles legacy sandboxes with incomplete custom-route metadata by failing closed and requiring destroy+re-onboard. This is a localized workaround for invalid state created by earlier onboarding that didn't enforce complete metadata. The source-of-truth questions: - What invalid state: sandbox registry entries missing endpointUrl/preferredInferenceApi for custom providers - Where created: onboarding before this PR's validation - Why source can't be fixed in this PR: existing deployed sandboxes can't be retroactively fixed without operator action - Regression test: 'blocks an incomplete legacy custom target even without a peer' proves the guard - When removable: when all legacy sandboxes are re-onboarded or destroyed This is an acceptable workaround with clear removal conditions, but should be tracked for cleanup.
  • Impact: Operators with legacy sandboxes must manually destroy and re-onboard. No automated migration tool provided. The workaround will remain until all legacy sandboxes are migrated.
  • Recommended action: Add a telemetry or audit log entry when the legacy incomplete-route error is triggered, to track adoption of the re-onboard fix and know when the workaround can be removed. Consider adding a `nemoclaw doctor` check that flags incomplete legacy routes.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: The fail-closed behavior is tested and documented. The workaround can be removed when no legacy sandboxes with incomplete metadata exist in production.
  • Missing regression test: Add a test that verifies the fail-closed behavior is the only path (no silent migration). Consider adding a `nemoclaw doctor` check that flags incomplete legacy routes.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: The fail-closed behavior is tested and documented. The workaround can be removed when no legacy sandboxes with incomplete metadata exist in production.
  • Evidence: checkGatewayRouteCompatibility() returns 'incomplete-custom-route' for requested route and 'incomplete-route' for registered peers. No automatic migration path exists - operator must manually destroy and re-onboard.

PRA-4 Resolve/justify — Gateway route mutation lock integration tests could be deeper

  • Location: src/lib/actions/inference-set-gateway-route-containment.test.ts:450
  • Category: tests
  • Problem: The mutation lock test ('serializes same-gateway mutations and rejects a conflicting write') uses a real file-based lock with 1ms poll interval and 5s timeout. It verifies: - Only one inference set succeeds - Registry ends up with the winner's provider/model - Lock acquired twice However, it doesn't test: lock timeout behavior, lock holder crash recovery, cross-process lock contention, or lock starvation. The lock is built on `withMcpLifecycleLock` which has its own tests, but the gateway-route-specific integration could be stronger.
  • Impact: Lock timeout/crash recovery behavior untested. Could leave waiters hanging or allow split-brain if lock file corrupted.
  • Recommended action: Add tests for: lock timeout when holder crashes, cross-process contention with multiple CLI invocations, and lock acquisition ordering under load.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Review the test at line 450+ in inference-set-gateway-route-containment.test.ts and the withGatewayRouteMutationLock implementation in gateway-route-mutation-lock.ts.
  • Missing regression test: Add tests for: lock timeout when holder crashes, cross-process contention with multiple CLI invocations, and lock acquisition ordering under load.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Review the test at line 450+ in inference-set-gateway-route-containment.test.ts and the withGatewayRouteMutationLock implementation in gateway-route-mutation-lock.ts.
  • Evidence: Test uses real file-based lock but only covers happy-path serialization. No tests for timeout, crash recovery, or cross-process scenarios.

PRA-5 Resolve/justify — Test file size budget not updated for new/expanded test files

  • Location: ci/test-file-size-budget.json:1
  • Category: correctness
  • Problem: ci/test-file-size-budget.json only updated test/onboard.test.ts (-14 lines). The 11 new/expanded test files (totaling ~2000+ new lines) are not in legacyMaxLines. This will cause CI budget failures unless the budget is updated or files are extracted.
  • Impact: CI test-file-size-budget job will fail on merge unless budget entries are added.
  • Recommended action: Add legacyMaxLines entries for each new/expanded test file, or extract test modules to stay under defaultMaxLines (1500).
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Compare the list of changed test files against the legacyMaxLines object in the budget file. Only test/onboard.test.ts was updated.
  • Missing regression test: Add legacyMaxLines entries for each new/expanded test file, or extract test modules to stay under defaultMaxLines (1500).
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Compare the list of changed test files against the legacyMaxLines object in the budget file. Only test/onboard.test.ts was updated.
  • Evidence: Budget file diff shows only test/onboard.test.ts changed from 4057 to 4043. No entries for inference-set-gateway-route-containment.test.ts, connect-route-containment.test.ts, etc.

💡 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-6 Improvement — NIM Nano model adds servedModel field

  • Location: bin/lib/nim-images.json:8
  • Category: correctness
  • Problem: bin/lib/nim-images.json adds `"servedModel": "nvidia/nemotron-3-nano"` for the nemotron-3-nano-30b-a3b entry. This appears to be a metadata fix for the model's served identity. No code changes consume this field yet - verify it's used in nim.ts or nim-route-identity tests.
  • Impact: Unused field adds confusion. If meant for route identity, should be consumed in nim.ts.
  • Suggested action: Verify the servedModel field is consumed in route identity logic or remove if unused. If for future use, add a comment explaining purpose.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Check src/lib/inference/nim.ts and nim-route-identity.test.ts for servedModel usage.
  • Missing regression test: Verify the servedModel field is consumed in route identity logic or remove if unused.
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: grep -r "servedModel" src/ shows no current consumers.

PRA-7 Improvement — inference-set-route-containment.ts could be split for maintainability

  • Location: src/lib/actions/inference-set-route-containment.ts:1
  • Category: correctness
  • Problem: The file is 385 lines covering prepareInferenceSetRoute, finalizeInferenceSetRoute, normalizeCustomEndpointUrl, and validation helpers. The normalizeCustomEndpointUrl function duplicates URL parsing logic that could use core/url-utils.ts canonicalEndpoint.
  • Impact: Large single file harder to navigate. URL normalization logic split between core/url-utils and this file.
  • Suggested action: Move normalizeCustomEndpointUrlWithoutDns and normalizeEndpointUrlShape to core/url-utils.ts alongside canonicalEndpoint. Keep DNS-pinning logic in this file.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Compare normalizeEndpointUrlShape in this file with canonicalEndpoint in core/url-utils.ts - they both parse and normalize URLs.
  • Missing regression test: Ensure URL normalization behavior unchanged after extraction.
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: File is 385 lines. core/url-utils.ts already exports canonicalEndpoint for endpoint normalization.

PRA-8 Improvement — gateway-route-compatibility.ts could extract shared peer iteration logic

  • Location: src/lib/inference/gateway-route-compatibility.ts:1
  • Category: correctness
  • Problem: The file is 368 lines. checkGatewayRouteCompatibility and preflightGatewayRouteDiscovery both iterate peers and resolve gateway names. Shared logic could be extracted to reduce duplication.
  • Impact: Duplicated peer iteration increases maintenance burden and risk of divergence.
  • Suggested action: Extract common peer filtering (by gatewayName) and gateway name resolution into a private helper function used by both public functions.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Compare the peer iteration loops in checkGatewayRouteCompatibility (line ~120) and preflightGatewayRouteDiscovery (line ~60).
  • Missing regression test: Ensure compatibility and discovery behavior unchanged after extraction.
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: Both functions iterate request.sandboxes, call resolveSandboxGatewayName, filter by gatewayName.

PRA-9 Improvement — Shared gateway route containment prevents cross-sandbox inference interference

  • Location: src/lib/inference/gateway-route-compatibility.ts:1
  • Category: security
  • Problem: The PR implements a critical security boundary: OpenShell gateways expose one inference route shared by all sandboxes. The new `gateway-route-compatibility.ts` module enforces that: - All same-gateway sandboxes (including stopped) must have compatible provider/model - Custom routes must match normalized endpoint URL and API family - Legacy incomplete custom routes fail closed until re-onboarded with complete metadata - Mutation lock serializes gateway route changes (prevents TOCTOU) - Ambient OPENSHELL_GATEWAY_ENDPOINT and explicit --gateway-endpoint are rejected before any mutation This prevents a compromised or misconfigured sandbox from hijacking the shared inference route of other sandboxes on the same gateway.
  • Impact: Security posture improved - prevents sandbox-to-sandbox inference route hijacking.
  • Suggested action: No action needed - security feature correctly implemented.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Review checkGatewayRouteCompatibility() and preflightGatewayRouteDiscovery() - they compare requested route against ALL same-gateway registry entries including stopped sandboxes. Tests in inference-set-gateway-route-containment.test.ts cover conflict detection, DNS-change detection, and cross-gateway isolation.
  • Missing regression test: The new test file inference-set-gateway-route-containment.test.ts provides 508 lines of coverage including: ambient gateway rejection, pending reservation rejection, same-gateway conflict blocking, cross-gateway isolation, gateway change during lock wait, custom endpoint conflicts, DNS change detection, incomplete legacy route blocking, Hermes provider scoping, stopped legacy Hermes route blocking, and mutation lock serialization.
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: Security review Category 3 PASS - authorization boundary correctly implemented.

PRA-10 Improvement — DNS-pinning SSRF guard validates custom endpoints before gateway mutation

  • Location: src/lib/actions/inference-set-route-containment.ts:115
  • Category: security
  • Problem: The `normalizeCustomEndpointUrl()` function in inference-set-route-containment.ts applies DNS-pinning validation: - Rejects loopback, link-local, RFC1918, and internal addresses - Allows only http://host.openshell.internal:&lt;port> (1024-65535) as explicit sandbox-to-host bridge - For public HTTP URLs, stores validated IP to prevent DNS rebinding - Rejects DNS-backed HTTPS URLs (cannot pin peer across OpenShell boundary) - HTTPS IP-literal URLs accepted The guard runs in `finalizeInferenceSetRoute()` after preliminary checks but BEFORE any gateway/config/registry mutation. A DNS change between preliminary and final check is caught and rejected.
  • Impact: SSRF attack surface eliminated for custom endpoint switches.
  • Suggested action: No action needed - SSRF guard correctly implemented.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Test 'rechecks a DNS-normalized endpoint before route mutation' and 'catches a DNS change between the preliminary and finalized gateway route checks' in inference-set-gateway-route-containment.test.ts verify the DNS-pinning boundary.
  • Missing regression test: Covered by existing tests. The DNS-change regression test specifically protects this boundary.
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: Security review Category 2 PASS - input validation comprehensive.

PRA-11 Improvement — Incomplete legacy custom routes fail closed instead of silently inheriting

  • Location: src/lib/actions/inference-set-route-containment.ts:180
  • Category: security
  • Problem: Custom routes (compatible-endpoint, compatible-anthropic-endpoint) now require durable endpointUrl AND preferredInferenceApi metadata in the registry. Legacy sandboxes with incomplete metadata: - Are detected during `prepareInferenceSetRoute()` and `checkGatewayRouteCompatibility()` - Cause `inference set`, onboarding, and connect-time repair to fail with actionable error - Error message includes recovery command: destroy + re-onboard with NEMOCLAW_ENDPOINT_URL, NEMOCLAW_MODEL, NEMOCLAW_PREFERRED_API - The recorded registry value is NOT trusted to bypass the SSRF guard (explicit equality check would be self-authorizing)
  • Impact: Prevents silent route corruption from legacy incomplete metadata.
  • Suggested action: No action needed - fail-closed behavior correct.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Test 'blocks an incomplete legacy custom target even without a peer' in inference-set-gateway-route-containment.test.ts. Also test 're-supplying the SAME onboard-recorded internal endpoint is rejected with omit-guidance' in inference-set-provider-alias.test.ts.
  • Missing regression test: Covered by tests. The fail-closed behavior is tested for inference set, onboarding (via provider-inference-route-containment.ts), and connect repair.
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: Security review Category 3 PASS - authorization boundary prevents silent inheritance.

PRA-12 Improvement — Gateway route mutation lock prevents TOCTOU race conditions

  • Location: src/lib/inference/gateway-route-mutation-lock.ts:1
  • Category: security
  • Problem: New `withGatewayRouteMutationLock()` in gateway-route-mutation-lock.ts serializes host-side reads/writes of OpenShell's one-route-per-gateway state using the existing MCP lifecycle lock infrastructure (cross-process lease). The lock: - Uses prefix 'gateway-route:' to keep namespace disjoint from sandbox locks - Wraps the entire inference set mutation (prepare → finalize → OpenShell call → registry update) - Also used in onboarding (setup-inference.ts) and registry recovery - Test 'serializes same-gateway mutations and rejects a conflicting write' verifies one mutation wins, the other fails with registry aligned to the winner
  • Impact: Prevents race conditions where concurrent inference set calls could leave gateway route in inconsistent state.
  • Suggested action: No action needed - mutation lock correctly implemented.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: The lock is acquired in runInferenceSet() via deps.withGatewayRouteMutationLock(gatewayName, ...). The test creates two concurrent inference set calls with different providers on same gateway and asserts only one succeeds.
  • Missing regression test: Covered by the serialization test in inference-set-gateway-route-containment.test.ts.
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: Security review Category 9 PASS - no TOCTOU in security-critical paths.

PRA-13 Improvement — Ambient OPENSHELL_GATEWAY_ENDPOINT and --gateway-endpoint rejected before mutation

  • Location: src/lib/openshell-gateway-endpoint-guard.ts:1
  • Category: security
  • Problem: New `openshell-gateway-endpoint-guard.ts` module: - `assertNoOpenShellGatewayEndpointOverride()` rejects if OPENSHELL_GATEWAY_ENDPOINT env var is set - `assertNoExplicitOpenShellGatewayEndpoint()` rejects if --gateway-endpoint flag appears in args - Both checked in `runInferenceSet()` at the very start, before any lock acquisition or OpenShell call - Also used in `createGatewayScopedOpenshellRunner()` for onboarding This prevents an attacker from hijacking the OpenShell CLI to target a different gateway than the sandbox's recorded binding.
  • Impact: Prevents gateway hijacking via environment/flag injection.
  • Suggested action: No action needed - guard correctly implemented.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Test 'rejects an ambient gateway endpoint before OpenShell prep or state mutation' in inference-set-gateway-route-containment.test.ts sets OPENSHELL_GATEWAY_ENDPOINT and verifies rejection with exitCode=2 before any OpenShell calls.
  • Missing regression test: Covered by test. The guard is also integrated into onboarding via createGatewayScopedOpenshellRunner().
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: Security review Category 3 PASS - ambient gateway rejection at entry point.

PRA-14 Improvement — Hermes compatible-anthropic-endpoint forced to OpenAI frontend

  • Location: src/lib/actions/inference-set.ts:280
  • Category: security
  • Problem: For Hermes sandboxes, `compatible-anthropic-endpoint` provider MUST use the managed OpenAI-compatible frontend (type=openai with OPENAI_BASE_URL). The code: - Rejects explicit --inference-api anthropic-messages for Hermes custom endpoints - Deterministically selects openai-completions when --inference-api omitted - Validates gateway provider metadata matches expected OpenAI surface before allowing switch - Legacy Anthropic-frontend registrations fail with rebuild guidance This closes a protocol confusion vector where a Hermes sandbox could claim Anthropic Messages but actually route through OpenAI frontend.
  • Impact: Prevents protocol mismatch attacks on Hermes sandboxes.
  • Suggested action: No action needed - protocol enforcement correctly implemented.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Test 'rejects an explicit Anthropic frontend request for Hermes custom endpoints' in inference-set-hermes-run.test.ts. Also 'blocks a stopped legacy Hermes Anthropic route before gateway inspection' in inference-set-gateway-route-containment.test.ts.
  • Missing regression test: Covered by tests. The Hermes-specific validation is in assertHermesCompatibleAnthropicOpenAiProvider().
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: Security review Category 3 PASS - Hermes protocol enforcement.

PRA-15 Improvement — Installer provider aliases normalized to OpenShell names for inference set

  • Location: src/lib/actions/inference-set.ts:90
  • Category: correctness
  • Problem: PR [All Platforms][CLI&UX] nemoclaw inference set is unusable for Inference Hub and Deep Agents — rejects the onboard provider name, SSRF-blocks the same URL onboard accepts, and refuses dcode sandboxes #6321: `normalizeInferenceSetProvider()` maps installer-style aliases (anthropicCompatible, build, custom, etc.) to OpenShell provider names (compatible-anthropic-endpoint, nvidia-prod, compatible-endpoint). This ensures `inference set` accepts the same vocabulary as `onboard`. The mapping is a local const (not importing @ts-nocheck onboard module) with a sync test verifying parity.
  • Impact: Users can use the same provider names for onboard and inference set.
  • Suggested action: No action needed - alias normalization correct.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Test in inference-set-provider-alias.test.ts verifies the alias map stays in sync with onboard's REMOTE_PROVIDER_CONFIG.
  • Missing regression test: Covered by sync test.
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: Acceptance clause 'Compare requested provider/model...' met with alias normalization.

PRA-16 Improvement — Connect-time route repair checks all same-gateway sandboxes before mutation

  • Location: src/lib/actions/sandbox/connect.ts:1
  • Category: correctness
  • Problem: In `connect-route-containment.test.ts`, the connect flow now: - Calls `assertRouteCompatible` before any endpoint probe or repair mutation - Checks every registered sandbox on the gateway for conflicts - Exits non-zero without changing gateway if conflict detected - Names conflicting sandboxes in error output - Rechecks peers after waiting for gateway route mutation lock This prevents connect from silently realigning a shared gateway route that would break other sandboxes.
  • Impact: Connect repair no longer silently breaks other sandboxes on shared gateway.
  • Suggested action: No action needed - connect containment correct.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Tests in connect-route-containment.test.ts: 'stops before the initial endpoint probe or repair mutation when routes conflict', 'exits before connect-time route writes when another sandbox conflicts', 'rechecks peers after waiting for the shared gateway route lock'.
  • Missing regression test: Covered by new connect-route-containment.test.ts (401 lines).
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: Acceptance clause 'Run the guard before... connect-time route writes, endpoint probes, or repair mutations' met.

PRA-17 Improvement — Onboarding validates gateway route compatibility before sandbox creation

  • Location: src/lib/onboard/setup-inference.ts:50
  • Category: correctness
  • Problem: In `setup-inference.ts` and `provider-inference-route-containment.ts`: - `createSetupInference()` acquires gateway route mutation lock - Calls `checkGatewayRouteCompatibility()` before any provider registration - `guardProviderInferenceRouteSelection()` constrains discovery from durable peers then exact-checks complete route identities - `assertProviderInferenceRouteCompatible()` fails onboarding with formatted conflict message - Resume path revalidates route compatibility and refreshes provider surface when needed This ensures new sandboxes cannot be created with conflicting routes on an existing gateway.
  • Impact: Onboarding cannot create conflicting routes on shared gateway.
  • Suggested action: No action needed - onboarding containment correct.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: The createSetupInference() function wraps the entire inference setup in withGatewayRouteMutationLock and checks compatibility upfront. provider-inference-route-containment.ts provides the guard functions used by the onboarding FSM.
  • Missing regression test: Test coverage in setup-inference-gateway-scope.test.ts (208 lines new) and provider-inference-route-containment.test.ts (296 lines new).
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: Acceptance clause 'Run the guard before onboarding setup, resumed setup' met.

PRA-18 Improvement — Registry recovery validates gateway compatibility before persisting recovered entries

  • Location: src/lib/registry-recovery-action.ts:60
  • Category: correctness
  • Problem: In `registry-recovery-action.ts`, `upsertRecoveredSandbox()` calls `checkGatewayRouteCompatibility()` before registering/updating a recovered sandbox. If the recovered entry would conflict with existing same-gateway routes, it is skipped with a warning. The recovery path also acquires the gateway route mutation lock for the seeded (mutating) recovery path.
  • Impact: Registry recovery cannot silently introduce conflicting routes.
  • Suggested action: No action needed - recovery containment correct.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Search for checkGatewayRouteCompatibility in registry-recovery-action.ts - it's called in upsertRecoveredSandbox() before registry.updateSandbox() or registry.registerSandbox().
  • Missing regression test: Test 'registry recovery skips incompatible routes' would strengthen coverage - verify a recovered sandbox with conflicting route is skipped and warned.
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: Acceptance clause 'Serialize... registry recovery per gateway' met.

PRA-19 Improvement — Documentation fully updated for gateway route containment feature

  • Location: docs/about/release-notes.mdx:52
  • Category: acceptance
  • Problem: All user-facing docs updated: - release-notes.mdx v0.0.75: Migration warning, recovery commands, Hermes openai-completions note - switch-inference-providers.mdx: Warning box, omit --endpoint-url guidance, Hermes --inference-api note - commands.mdx / commands-nemohermes.mdx: connect checks all peers, inference set compares all registry rows, --no-verify doesn't bypass - troubleshooting.mdx: 'Running multiple sandboxes simultaneously' section with 3 recovery paths Acceptance clauses from PR description (release notes, troubleshooting, command refs) are all addressed.
  • Impact: Users have clear migration path and recovery procedures.
  • Suggested action: No action needed - documentation complete.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Search release-notes.mdx for 'Shared OpenShell gateways now enforce a single compatible inference route' and troubleshooting.mdx for 'OpenShell currently exposes one inference route per gateway'.
  • Missing regression test: Documentation is complete. No automated test needed but could add doc-validate check for cross-reference integrity.
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: All 8 acceptance clauses from PR body mapped to doc updates.
Simplification opportunities: 3 possible cuts, net -81 lines possible

These are safe simplification checks only. Do not remove validation, security controls, data-loss prevention, or required tests.

  • PRA-6 delete (bin/lib/nim-images.json:8): servedModel field from nim-images.json if unused
    • Replacement: Remove field or add consumer code
    • Net: -1 lines
    • Safety boundary: Only remove if confirmed unused in route identity resolution
  • PRA-7 shrink (src/lib/actions/inference-set-route-containment.ts:1): normalizeEndpointUrlShape and normalizeCustomEndpointUrlWithoutDns functions (~50 lines)
    • Replacement: Import and use canonicalEndpoint from core/url-utils.ts
    • Net: -50 lines
    • Safety boundary: DNS-pinning validation in normalizeCustomEndpointUrl must remain in this file
  • PRA-8 shrink (src/lib/inference/gateway-route-compatibility.ts:1): Duplicated peer iteration and gateway resolution logic (~30 lines)
    • Replacement: Private helper: getSameGatewayPeers(request) returning filtered peers with resolved gateway names
    • Net: -30 lines
    • Safety boundary: Conflict detection logic (provider-model, custom-endpoint, custom-api, incomplete-route, invalid-gateway-binding) must remain in each function
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 — gateway route mutation lock times out when holder crashes. Runtime/sandbox/infrastructure paths need behavioral runtime validation: bin/lib/nim-images.json, ci/test-file-size-budget.json, docs/about/release-notes.mdx, docs/inference/switch-inference-providers.mdx, docs/reference/commands-nemohermes.mdx, docs/reference/commands.mdx, docs/reference/troubleshooting.mdx, src/commands/inference/set.ts. Static coverage is comprehensive but mutation lock timeout/crash recovery and cross-process contention need runtime-style tests.
  • PRA-T2 Runtime validation — gateway route mutation lock cross-process contention. Runtime/sandbox/infrastructure paths need behavioral runtime validation: bin/lib/nim-images.json, ci/test-file-size-budget.json, docs/about/release-notes.mdx, docs/inference/switch-inference-providers.mdx, docs/reference/commands-nemohermes.mdx, docs/reference/commands.mdx, docs/reference/troubleshooting.mdx, src/commands/inference/set.ts. Static coverage is comprehensive but mutation lock timeout/crash recovery and cross-process contention need runtime-style tests.
  • PRA-T3 Runtime validation — registry recovery skips incompatible recovered route. Runtime/sandbox/infrastructure paths need behavioral runtime validation: bin/lib/nim-images.json, ci/test-file-size-budget.json, docs/about/release-notes.mdx, docs/inference/switch-inference-providers.mdx, docs/reference/commands-nemohermes.mdx, docs/reference/commands.mdx, docs/reference/troubleshooting.mdx, src/commands/inference/set.ts. Static coverage is comprehensive but mutation lock timeout/crash recovery and cross-process contention need runtime-style tests.
  • PRA-T4 Runtime validation — preflightGatewayRouteDiscovery with mixed valid/invalid peers. Runtime/sandbox/infrastructure paths need behavioral runtime validation: bin/lib/nim-images.json, ci/test-file-size-budget.json, docs/about/release-notes.mdx, docs/inference/switch-inference-providers.mdx, docs/reference/commands-nemohermes.mdx, docs/reference/commands.mdx, docs/reference/troubleshooting.mdx, src/commands/inference/set.ts. Static coverage is comprehensive but mutation lock timeout/crash recovery and cross-process contention need runtime-style tests.
  • PRA-T5 Runtime validation — three-agent-type gateway sharing (OpenClaw + Hermes + DCode). Runtime/sandbox/infrastructure paths need behavioral runtime validation: bin/lib/nim-images.json, ci/test-file-size-budget.json, docs/about/release-notes.mdx, docs/inference/switch-inference-providers.mdx, docs/reference/commands-nemohermes.mdx, docs/reference/commands.mdx, docs/reference/troubleshooting.mdx, src/commands/inference/set.ts. Static coverage is comprehensive but mutation lock timeout/crash recovery and cross-process contention need runtime-style tests.
  • PRA-T6 Gateway route mutation lock integration tests could be deeper — Add tests for: lock timeout when holder crashes, cross-process contention with multiple CLI invocations, and lock acquisition ordering under load.
Since last review details

Current findings, using the urgency labels above:

PRA-1 Required — Multiple test files exceed monolith growth threshold by 20+ lines

  • Location: src/lib/actions/inference-set-gateway-route-containment.test.ts:1
  • Category: correctness
  • Problem: Five new or significantly expanded test files grow by 200-500+ lines each without offsetting extraction: - src/lib/actions/inference-set-gateway-route-containment.test.ts (new, 508 lines) - src/lib/actions/sandbox/connect-route-containment.test.ts (new, 401 lines) - src/lib/onboard/setup-nim-flow.test.ts (+253 lines) - src/lib/onboard/machine/handlers/provider-inference.test.ts (+180 lines) - src/lib/onboard/machine/handlers/sandbox-route-mutation-lock.test.ts (new, 123 lines) - src/lib/registry-recovery-action.test.ts (+52 lines) - src/lib/actions/sandbox/snapshot.test.ts (+49 lines) - src/lib/state/registry-route-reservation.test.ts (new, 88 lines) - src/lib/onboard/gateway-binding.test.ts (+56 lines) - src/lib/onboard/machine/core-flow-phases.test.ts (+53 lines) Per rubric item 7, E2E/test suite simplicity: new test files should favor focused tests and local helpers over new framework layers. These appear to be unit/integration tests for the new gateway containment feature, but the growth is concentrated in few files rather than distributed.
  • Impact: CI test-file-size-budget job will fail unless budget is updated or files are extracted. Large test files reduce maintainability and make targeted test runs harder.
  • Required action: Update ci/test-file-size-budget.json with legacyMaxLines entries for each new/expanded test file, OR extract cohesive test modules (e.g., separate DNS-pinning tests, mutation-lock tests, legacy-route tests) to stay under defaultMaxLines (1500).
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Run `cat ci/test-file-size-budget.json` and compare legacyMaxLines entries against current file line counts. The budget was updated for test/onboard.test.ts (-14 lines) but not for these new/expanded files.
  • Missing regression test: Test file size budget should be updated with new legacyMaxLines entries for each expanded test file, or the test content should be extracted into smaller focused modules. The PR adds 11 test files but only updates budget for one existing file.
  • Done when: The required change is committed and verification passes: Run `cat ci/test-file-size-budget.json` and compare legacyMaxLines entries against current file line counts. The budget was updated for test/onboard.test.ts (-14 lines) but not for these new/expanded files.
  • Evidence: Drift context monolithDeltas shows 10 test files with severity=blocker (delta >= 20 lines). ci/test-file-size-budget.json only updated test/onboard.test.ts.

PRA-2 Required — Multiple source files exceed monolith growth threshold by 20+ lines

  • Location: src/lib/onboard/setup-inference.ts:1
  • Category: correctness
  • Problem: Eight source files grow by 60-138 lines each: - src/lib/onboard/setup-inference.ts (+138 lines) - src/lib/onboard/machine/handlers/provider-inference.ts (+136 lines) - src/lib/onboard/setup-nim-flow.ts (+121 lines) - src/lib/registry-recovery-action.ts (+98 lines) - src/lib/actions/sandbox/connect.ts (+66 lines) - src/lib/onboard/machine/handlers/sandbox.ts (+63 lines) - src/lib/actions/sandbox/snapshot.ts (+59 lines) - src/lib/state/registry.ts (+49 lines) - src/lib/inference/vllm.ts (+27 lines) Several of these are core onboarding/sandbox handlers already at 600-1000+ lines. The growth adds gateway route containment checks, mutation locks, and compatibility validation throughout the flow.
  • Impact: Large source files reduce readability, increase cognitive load, and make future changes riskier. The new gateway-route-compatibility and gateway-route-mutation-lock modules exist but integration points still add significant bulk to callers.
  • Required action: Extract gateway route containment integration logic into smaller helper modules, or offset growth by deleting/compressing other code in these files. Consider moving the compatibility check calls into the new dedicated modules rather than inline in each handler.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check `git diff main...HEAD --stat` for line deltas on these files. The drift context shows each with severity=blocker.
  • Missing regression test: Consider extracting gateway route containment logic into the new dedicated modules (gateway-route-compatibility.ts, gateway-route-mutation-lock.ts) rather than growing existing handlers. The new modules exist but the integration points still add significant bulk.
  • Done when: The required change is committed and verification passes: Check `git diff main...HEAD --stat` for line deltas on these files. The drift context shows each with severity=blocker.
  • Evidence: Drift context monolithDeltas shows 9 source files with severity=blocker (delta >= 20 lines).

PRA-3 Resolve/justify — Legacy incomplete route handling is a workaround, not a source fix

  • Location: src/lib/actions/inference-set-route-containment.ts:180
  • Category: security
  • Problem: The PR handles legacy sandboxes with incomplete custom-route metadata by failing closed and requiring destroy+re-onboard. This is a localized workaround for invalid state created by earlier onboarding that didn't enforce complete metadata. The source-of-truth questions: - What invalid state: sandbox registry entries missing endpointUrl/preferredInferenceApi for custom providers - Where created: onboarding before this PR's validation - Why source can't be fixed in this PR: existing deployed sandboxes can't be retroactively fixed without operator action - Regression test: 'blocks an incomplete legacy custom target even without a peer' proves the guard - When removable: when all legacy sandboxes are re-onboarded or destroyed This is an acceptable workaround with clear removal conditions, but should be tracked for cleanup.
  • Impact: Operators with legacy sandboxes must manually destroy and re-onboard. No automated migration tool provided. The workaround will remain until all legacy sandboxes are migrated.
  • Recommended action: Add a telemetry or audit log entry when the legacy incomplete-route error is triggered, to track adoption of the re-onboard fix and know when the workaround can be removed. Consider adding a `nemoclaw doctor` check that flags incomplete legacy routes.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: The fail-closed behavior is tested and documented. The workaround can be removed when no legacy sandboxes with incomplete metadata exist in production.
  • Missing regression test: Add a test that verifies the fail-closed behavior is the only path (no silent migration). Consider adding a `nemoclaw doctor` check that flags incomplete legacy routes.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: The fail-closed behavior is tested and documented. The workaround can be removed when no legacy sandboxes with incomplete metadata exist in production.
  • Evidence: checkGatewayRouteCompatibility() returns 'incomplete-custom-route' for requested route and 'incomplete-route' for registered peers. No automatic migration path exists - operator must manually destroy and re-onboard.

PRA-4 Resolve/justify — Gateway route mutation lock integration tests could be deeper

  • Location: src/lib/actions/inference-set-gateway-route-containment.test.ts:450
  • Category: tests
  • Problem: The mutation lock test ('serializes same-gateway mutations and rejects a conflicting write') uses a real file-based lock with 1ms poll interval and 5s timeout. It verifies: - Only one inference set succeeds - Registry ends up with the winner's provider/model - Lock acquired twice However, it doesn't test: lock timeout behavior, lock holder crash recovery, cross-process lock contention, or lock starvation. The lock is built on `withMcpLifecycleLock` which has its own tests, but the gateway-route-specific integration could be stronger.
  • Impact: Lock timeout/crash recovery behavior untested. Could leave waiters hanging or allow split-brain if lock file corrupted.
  • Recommended action: Add tests for: lock timeout when holder crashes, cross-process contention with multiple CLI invocations, and lock acquisition ordering under load.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Review the test at line 450+ in inference-set-gateway-route-containment.test.ts and the withGatewayRouteMutationLock implementation in gateway-route-mutation-lock.ts.
  • Missing regression test: Add tests for: lock timeout when holder crashes, cross-process contention with multiple CLI invocations, and lock acquisition ordering under load.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Review the test at line 450+ in inference-set-gateway-route-containment.test.ts and the withGatewayRouteMutationLock implementation in gateway-route-mutation-lock.ts.
  • Evidence: Test uses real file-based lock but only covers happy-path serialization. No tests for timeout, crash recovery, or cross-process scenarios.

PRA-5 Resolve/justify — Test file size budget not updated for new/expanded test files

  • Location: ci/test-file-size-budget.json:1
  • Category: correctness
  • Problem: ci/test-file-size-budget.json only updated test/onboard.test.ts (-14 lines). The 11 new/expanded test files (totaling ~2000+ new lines) are not in legacyMaxLines. This will cause CI budget failures unless the budget is updated or files are extracted.
  • Impact: CI test-file-size-budget job will fail on merge unless budget entries are added.
  • Recommended action: Add legacyMaxLines entries for each new/expanded test file, or extract test modules to stay under defaultMaxLines (1500).
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Compare the list of changed test files against the legacyMaxLines object in the budget file. Only test/onboard.test.ts was updated.
  • Missing regression test: Add legacyMaxLines entries for each new/expanded test file, or extract test modules to stay under defaultMaxLines (1500).
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Compare the list of changed test files against the legacyMaxLines object in the budget file. Only test/onboard.test.ts was updated.
  • Evidence: Budget file diff shows only test/onboard.test.ts changed from 4057 to 4043. No entries for inference-set-gateway-route-containment.test.ts, connect-route-containment.test.ts, etc.

PRA-6 Improvement — NIM Nano model adds servedModel field

  • Location: bin/lib/nim-images.json:8
  • Category: correctness
  • Problem: bin/lib/nim-images.json adds `"servedModel": "nvidia/nemotron-3-nano"` for the nemotron-3-nano-30b-a3b entry. This appears to be a metadata fix for the model's served identity. No code changes consume this field yet - verify it's used in nim.ts or nim-route-identity tests.
  • Impact: Unused field adds confusion. If meant for route identity, should be consumed in nim.ts.
  • Suggested action: Verify the servedModel field is consumed in route identity logic or remove if unused. If for future use, add a comment explaining purpose.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Check src/lib/inference/nim.ts and nim-route-identity.test.ts for servedModel usage.
  • Missing regression test: Verify the servedModel field is consumed in route identity logic or remove if unused.
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: grep -r "servedModel" src/ shows no current consumers.

PRA-7 Improvement — inference-set-route-containment.ts could be split for maintainability

  • Location: src/lib/actions/inference-set-route-containment.ts:1
  • Category: correctness
  • Problem: The file is 385 lines covering prepareInferenceSetRoute, finalizeInferenceSetRoute, normalizeCustomEndpointUrl, and validation helpers. The normalizeCustomEndpointUrl function duplicates URL parsing logic that could use core/url-utils.ts canonicalEndpoint.
  • Impact: Large single file harder to navigate. URL normalization logic split between core/url-utils and this file.
  • Suggested action: Move normalizeCustomEndpointUrlWithoutDns and normalizeEndpointUrlShape to core/url-utils.ts alongside canonicalEndpoint. Keep DNS-pinning logic in this file.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Compare normalizeEndpointUrlShape in this file with canonicalEndpoint in core/url-utils.ts - they both parse and normalize URLs.
  • Missing regression test: Ensure URL normalization behavior unchanged after extraction.
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: File is 385 lines. core/url-utils.ts already exports canonicalEndpoint for endpoint normalization.

PRA-8 Improvement — gateway-route-compatibility.ts could extract shared peer iteration logic

  • Location: src/lib/inference/gateway-route-compatibility.ts:1
  • Category: correctness
  • Problem: The file is 368 lines. checkGatewayRouteCompatibility and preflightGatewayRouteDiscovery both iterate peers and resolve gateway names. Shared logic could be extracted to reduce duplication.
  • Impact: Duplicated peer iteration increases maintenance burden and risk of divergence.
  • Suggested action: Extract common peer filtering (by gatewayName) and gateway name resolution into a private helper function used by both public functions.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Compare the peer iteration loops in checkGatewayRouteCompatibility (line ~120) and preflightGatewayRouteDiscovery (line ~60).
  • Missing regression test: Ensure compatibility and discovery behavior unchanged after extraction.
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: Both functions iterate request.sandboxes, call resolveSandboxGatewayName, filter by gatewayName.

PRA-9 Improvement — Shared gateway route containment prevents cross-sandbox inference interference

  • Location: src/lib/inference/gateway-route-compatibility.ts:1
  • Category: security
  • Problem: The PR implements a critical security boundary: OpenShell gateways expose one inference route shared by all sandboxes. The new `gateway-route-compatibility.ts` module enforces that: - All same-gateway sandboxes (including stopped) must have compatible provider/model - Custom routes must match normalized endpoint URL and API family - Legacy incomplete custom routes fail closed until re-onboarded with complete metadata - Mutation lock serializes gateway route changes (prevents TOCTOU) - Ambient OPENSHELL_GATEWAY_ENDPOINT and explicit --gateway-endpoint are rejected before any mutation This prevents a compromised or misconfigured sandbox from hijacking the shared inference route of other sandboxes on the same gateway.
  • Impact: Security posture improved - prevents sandbox-to-sandbox inference route hijacking.
  • Suggested action: No action needed - security feature correctly implemented.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Review checkGatewayRouteCompatibility() and preflightGatewayRouteDiscovery() - they compare requested route against ALL same-gateway registry entries including stopped sandboxes. Tests in inference-set-gateway-route-containment.test.ts cover conflict detection, DNS-change detection, and cross-gateway isolation.
  • Missing regression test: The new test file inference-set-gateway-route-containment.test.ts provides 508 lines of coverage including: ambient gateway rejection, pending reservation rejection, same-gateway conflict blocking, cross-gateway isolation, gateway change during lock wait, custom endpoint conflicts, DNS change detection, incomplete legacy route blocking, Hermes provider scoping, stopped legacy Hermes route blocking, and mutation lock serialization.
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: Security review Category 3 PASS - authorization boundary correctly implemented.

PRA-10 Improvement — DNS-pinning SSRF guard validates custom endpoints before gateway mutation

  • Location: src/lib/actions/inference-set-route-containment.ts:115
  • Category: security
  • Problem: The `normalizeCustomEndpointUrl()` function in inference-set-route-containment.ts applies DNS-pinning validation: - Rejects loopback, link-local, RFC1918, and internal addresses - Allows only http://host.openshell.internal:&lt;port> (1024-65535) as explicit sandbox-to-host bridge - For public HTTP URLs, stores validated IP to prevent DNS rebinding - Rejects DNS-backed HTTPS URLs (cannot pin peer across OpenShell boundary) - HTTPS IP-literal URLs accepted The guard runs in `finalizeInferenceSetRoute()` after preliminary checks but BEFORE any gateway/config/registry mutation. A DNS change between preliminary and final check is caught and rejected.
  • Impact: SSRF attack surface eliminated for custom endpoint switches.
  • Suggested action: No action needed - SSRF guard correctly implemented.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Test 'rechecks a DNS-normalized endpoint before route mutation' and 'catches a DNS change between the preliminary and finalized gateway route checks' in inference-set-gateway-route-containment.test.ts verify the DNS-pinning boundary.
  • Missing regression test: Covered by existing tests. The DNS-change regression test specifically protects this boundary.
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: Security review Category 2 PASS - input validation comprehensive.

PRA-11 Improvement — Incomplete legacy custom routes fail closed instead of silently inheriting

  • Location: src/lib/actions/inference-set-route-containment.ts:180
  • Category: security
  • Problem: Custom routes (compatible-endpoint, compatible-anthropic-endpoint) now require durable endpointUrl AND preferredInferenceApi metadata in the registry. Legacy sandboxes with incomplete metadata: - Are detected during `prepareInferenceSetRoute()` and `checkGatewayRouteCompatibility()` - Cause `inference set`, onboarding, and connect-time repair to fail with actionable error - Error message includes recovery command: destroy + re-onboard with NEMOCLAW_ENDPOINT_URL, NEMOCLAW_MODEL, NEMOCLAW_PREFERRED_API - The recorded registry value is NOT trusted to bypass the SSRF guard (explicit equality check would be self-authorizing)
  • Impact: Prevents silent route corruption from legacy incomplete metadata.
  • Suggested action: No action needed - fail-closed behavior correct.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Test 'blocks an incomplete legacy custom target even without a peer' in inference-set-gateway-route-containment.test.ts. Also test 're-supplying the SAME onboard-recorded internal endpoint is rejected with omit-guidance' in inference-set-provider-alias.test.ts.
  • Missing regression test: Covered by tests. The fail-closed behavior is tested for inference set, onboarding (via provider-inference-route-containment.ts), and connect repair.
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: Security review Category 3 PASS - authorization boundary prevents silent inheritance.

PRA-12 Improvement — Gateway route mutation lock prevents TOCTOU race conditions

  • Location: src/lib/inference/gateway-route-mutation-lock.ts:1
  • Category: security
  • Problem: New `withGatewayRouteMutationLock()` in gateway-route-mutation-lock.ts serializes host-side reads/writes of OpenShell's one-route-per-gateway state using the existing MCP lifecycle lock infrastructure (cross-process lease). The lock: - Uses prefix 'gateway-route:' to keep namespace disjoint from sandbox locks - Wraps the entire inference set mutation (prepare → finalize → OpenShell call → registry update) - Also used in onboarding (setup-inference.ts) and registry recovery - Test 'serializes same-gateway mutations and rejects a conflicting write' verifies one mutation wins, the other fails with registry aligned to the winner
  • Impact: Prevents race conditions where concurrent inference set calls could leave gateway route in inconsistent state.
  • Suggested action: No action needed - mutation lock correctly implemented.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: The lock is acquired in runInferenceSet() via deps.withGatewayRouteMutationLock(gatewayName, ...). The test creates two concurrent inference set calls with different providers on same gateway and asserts only one succeeds.
  • Missing regression test: Covered by the serialization test in inference-set-gateway-route-containment.test.ts.
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: Security review Category 9 PASS - no TOCTOU in security-critical paths.

PRA-13 Improvement — Ambient OPENSHELL_GATEWAY_ENDPOINT and --gateway-endpoint rejected before mutation

  • Location: src/lib/openshell-gateway-endpoint-guard.ts:1
  • Category: security
  • Problem: New `openshell-gateway-endpoint-guard.ts` module: - `assertNoOpenShellGatewayEndpointOverride()` rejects if OPENSHELL_GATEWAY_ENDPOINT env var is set - `assertNoExplicitOpenShellGatewayEndpoint()` rejects if --gateway-endpoint flag appears in args - Both checked in `runInferenceSet()` at the very start, before any lock acquisition or OpenShell call - Also used in `createGatewayScopedOpenshellRunner()` for onboarding This prevents an attacker from hijacking the OpenShell CLI to target a different gateway than the sandbox's recorded binding.
  • Impact: Prevents gateway hijacking via environment/flag injection.
  • Suggested action: No action needed - guard correctly implemented.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Test 'rejects an ambient gateway endpoint before OpenShell prep or state mutation' in inference-set-gateway-route-containment.test.ts sets OPENSHELL_GATEWAY_ENDPOINT and verifies rejection with exitCode=2 before any OpenShell calls.
  • Missing regression test: Covered by test. The guard is also integrated into onboarding via createGatewayScopedOpenshellRunner().
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: Security review Category 3 PASS - ambient gateway rejection at entry point.

PRA-14 Improvement — Hermes compatible-anthropic-endpoint forced to OpenAI frontend

  • Location: src/lib/actions/inference-set.ts:280
  • Category: security
  • Problem: For Hermes sandboxes, `compatible-anthropic-endpoint` provider MUST use the managed OpenAI-compatible frontend (type=openai with OPENAI_BASE_URL). The code: - Rejects explicit --inference-api anthropic-messages for Hermes custom endpoints - Deterministically selects openai-completions when --inference-api omitted - Validates gateway provider metadata matches expected OpenAI surface before allowing switch - Legacy Anthropic-frontend registrations fail with rebuild guidance This closes a protocol confusion vector where a Hermes sandbox could claim Anthropic Messages but actually route through OpenAI frontend.
  • Impact: Prevents protocol mismatch attacks on Hermes sandboxes.
  • Suggested action: No action needed - protocol enforcement correctly implemented.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Test 'rejects an explicit Anthropic frontend request for Hermes custom endpoints' in inference-set-hermes-run.test.ts. Also 'blocks a stopped legacy Hermes Anthropic route before gateway inspection' in inference-set-gateway-route-containment.test.ts.
  • Missing regression test: Covered by tests. The Hermes-specific validation is in assertHermesCompatibleAnthropicOpenAiProvider().
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: Security review Category 3 PASS - Hermes protocol enforcement.

PRA-15 Improvement — Installer provider aliases normalized to OpenShell names for inference set

  • Location: src/lib/actions/inference-set.ts:90
  • Category: correctness
  • Problem: PR [All Platforms][CLI&UX] nemoclaw inference set is unusable for Inference Hub and Deep Agents — rejects the onboard provider name, SSRF-blocks the same URL onboard accepts, and refuses dcode sandboxes #6321: `normalizeInferenceSetProvider()` maps installer-style aliases (anthropicCompatible, build, custom, etc.) to OpenShell provider names (compatible-anthropic-endpoint, nvidia-prod, compatible-endpoint). This ensures `inference set` accepts the same vocabulary as `onboard`. The mapping is a local const (not importing @ts-nocheck onboard module) with a sync test verifying parity.
  • Impact: Users can use the same provider names for onboard and inference set.
  • Suggested action: No action needed - alias normalization correct.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Test in inference-set-provider-alias.test.ts verifies the alias map stays in sync with onboard's REMOTE_PROVIDER_CONFIG.
  • Missing regression test: Covered by sync test.
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: Acceptance clause 'Compare requested provider/model...' met with alias normalization.

PRA-16 Improvement — Connect-time route repair checks all same-gateway sandboxes before mutation

  • Location: src/lib/actions/sandbox/connect.ts:1
  • Category: correctness
  • Problem: In `connect-route-containment.test.ts`, the connect flow now: - Calls `assertRouteCompatible` before any endpoint probe or repair mutation - Checks every registered sandbox on the gateway for conflicts - Exits non-zero without changing gateway if conflict detected - Names conflicting sandboxes in error output - Rechecks peers after waiting for gateway route mutation lock This prevents connect from silently realigning a shared gateway route that would break other sandboxes.
  • Impact: Connect repair no longer silently breaks other sandboxes on shared gateway.
  • Suggested action: No action needed - connect containment correct.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Tests in connect-route-containment.test.ts: 'stops before the initial endpoint probe or repair mutation when routes conflict', 'exits before connect-time route writes when another sandbox conflicts', 'rechecks peers after waiting for the shared gateway route lock'.
  • Missing regression test: Covered by new connect-route-containment.test.ts (401 lines).
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: Acceptance clause 'Run the guard before... connect-time route writes, endpoint probes, or repair mutations' met.

PRA-17 Improvement — Onboarding validates gateway route compatibility before sandbox creation

  • Location: src/lib/onboard/setup-inference.ts:50
  • Category: correctness
  • Problem: In `setup-inference.ts` and `provider-inference-route-containment.ts`: - `createSetupInference()` acquires gateway route mutation lock - Calls `checkGatewayRouteCompatibility()` before any provider registration - `guardProviderInferenceRouteSelection()` constrains discovery from durable peers then exact-checks complete route identities - `assertProviderInferenceRouteCompatible()` fails onboarding with formatted conflict message - Resume path revalidates route compatibility and refreshes provider surface when needed This ensures new sandboxes cannot be created with conflicting routes on an existing gateway.
  • Impact: Onboarding cannot create conflicting routes on shared gateway.
  • Suggested action: No action needed - onboarding containment correct.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: The createSetupInference() function wraps the entire inference setup in withGatewayRouteMutationLock and checks compatibility upfront. provider-inference-route-containment.ts provides the guard functions used by the onboarding FSM.
  • Missing regression test: Test coverage in setup-inference-gateway-scope.test.ts (208 lines new) and provider-inference-route-containment.test.ts (296 lines new).
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: Acceptance clause 'Run the guard before onboarding setup, resumed setup' met.

PRA-18 Improvement — Registry recovery validates gateway compatibility before persisting recovered entries

  • Location: src/lib/registry-recovery-action.ts:60
  • Category: correctness
  • Problem: In `registry-recovery-action.ts`, `upsertRecoveredSandbox()` calls `checkGatewayRouteCompatibility()` before registering/updating a recovered sandbox. If the recovered entry would conflict with existing same-gateway routes, it is skipped with a warning. The recovery path also acquires the gateway route mutation lock for the seeded (mutating) recovery path.
  • Impact: Registry recovery cannot silently introduce conflicting routes.
  • Suggested action: No action needed - recovery containment correct.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Search for checkGatewayRouteCompatibility in registry-recovery-action.ts - it's called in upsertRecoveredSandbox() before registry.updateSandbox() or registry.registerSandbox().
  • Missing regression test: Test 'registry recovery skips incompatible routes' would strengthen coverage - verify a recovered sandbox with conflicting route is skipped and warned.
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: Acceptance clause 'Serialize... registry recovery per gateway' met.

PRA-19 Improvement — Documentation fully updated for gateway route containment feature

  • Location: docs/about/release-notes.mdx:52
  • Category: acceptance
  • Problem: All user-facing docs updated: - release-notes.mdx v0.0.75: Migration warning, recovery commands, Hermes openai-completions note - switch-inference-providers.mdx: Warning box, omit --endpoint-url guidance, Hermes --inference-api note - commands.mdx / commands-nemohermes.mdx: connect checks all peers, inference set compares all registry rows, --no-verify doesn't bypass - troubleshooting.mdx: 'Running multiple sandboxes simultaneously' section with 3 recovery paths Acceptance clauses from PR description (release notes, troubleshooting, command refs) are all addressed.
  • Impact: Users have clear migration path and recovery procedures.
  • Suggested action: No action needed - documentation complete.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Search release-notes.mdx for 'Shared OpenShell gateways now enforce a single compatible inference route' and troubleshooting.mdx for 'OpenShell currently exposes one inference route per gateway'.
  • Missing regression test: Documentation is complete. No automated test needed but could add doc-validate check for cross-reference integrity.
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: All 8 acceptance clauses from PR body mapped to doc updates.

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 6, 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 · 5 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
  • PRA-T4 Add or justify test follow-up: Runtime validation
  • PRA-T5 Add or justify test follow-up: Acceptance clause
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 — Run or add a targeted runtime validation where a same-gateway conflicting onboard exits before endpoint probing and leaves the existing gateway route, registry row, forwards, in-sandbox configs, and data-plane response unchanged.. Unit and mocked integration coverage is extensive for the changed route-containment logic, but the PR touches runtime OpenShell gateway behavior, sandbox lifecycle, route repair, and local-provider data-plane paths. Static tests cannot fully prove real gateway route and data-plane invariants.
  • PRA-T2 Runtime validation — Run or add a targeted runtime validation where the same conflicting route succeeds on a separate NEMOCLAW_GATEWAY_PORT and does not mutate the original gateway's route.. Unit and mocked integration coverage is extensive for the changed route-containment logic, but the PR touches runtime OpenShell gateway behavior, sandbox lifecycle, route repair, and local-provider data-plane paths. Static tests cannot fully prove real gateway route and data-plane invariants.
  • PRA-T3 Runtime validation — Run or add a targeted runtime validation where nemoclaw inference set --sandbox <non-default-gateway-sandbox> sends the route mutation to that sandbox's recorded gateway and an ambient OPENSHELL_GATEWAY_ENDPOINT produces a zero-mutation failure.. Unit and mocked integration coverage is extensive for the changed route-containment logic, but the PR touches runtime OpenShell gateway behavior, sandbox lifecycle, route repair, and local-provider data-plane paths. Static tests cannot fully prove real gateway route and data-plane invariants.
  • PRA-T4 Runtime validation — Run or add a targeted runtime validation where connect-time route repair detects a same-gateway conflict, exits non-zero, and leaves the live gateway route unchanged.. Unit and mocked integration coverage is extensive for the changed route-containment logic, but the PR touches runtime OpenShell gateway behavior, sandbox lifecycle, route repair, and local-provider data-plane paths. Static tests cannot fully prove real gateway route and data-plane invariants.
  • PRA-T5 Acceptance clause — Addresses [All Platforms][Inference] Onboarding one sandbox silently changes the provider/model/route of ALL existing sandboxes — last onboard wins the host-shared managed route #6315 — add test evidence or identify existing coverage. The deterministic validation context did not include the body or comments for issue [All Platforms][Inference] Onboarding one sandbox silently changes the provider/model/route of ALL existing sandboxes — last onboard wins the host-shared managed route #6315, so literal linked-issue clauses could not be extracted. The PR body links [All Platforms][Inference] Onboarding one sandbox silently changes the provider/model/route of ALL existing sandboxes — last onboard wins the host-shared managed route #6315, but PR-provided text is treated as untrusted evidence; reviewed code and tests nevertheless cover the route-containment behavior represented by the changed implementation.

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.

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

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

E2E Advisor Recommendation

Required E2E: onboard-resume, onboard-repair, cloud-onboard, openclaw-inference-switch, hermes-inference-switch, inference-routing, concurrent-gateway-ports, sandbox-operations, snapshot-commands
Optional E2E: model-router-provider-routed-inference, ubuntu-repo-cloud-openclaw-double-provider-switch, ubuntu-repo-cloud-openclaw-double-same-provider

Dispatch hint: onboard-resume,onboard-repair,cloud-onboard,openclaw-inference-switch,hermes-inference-switch,inference-routing,concurrent-gateway-ports,sandbox-operations,snapshot-commands

Workflow run

Full advisor summary

E2E Recommendation Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E

  • onboard-resume (high): Required by the onboarding resume rule because src/lib/onboard/machine and resume-provider/onboarding state transition code changed. This validates interrupted hosted onboarding resume against a real OpenShell/Docker sandbox.
  • onboard-repair (high): Required by the onboarding resume rule and by changes to provider inference route containment, gateway binding, route mutation locks, and repair policy. Validates repair of existing hosted onboarding state with real gateway/sandbox state.
  • cloud-onboard (high): The onboarding machine, provider inference selection, gateway provider metadata, NIM/vLLM setup, and registry route identity changes can affect full hosted onboarding. This is the canonical hosted OpenClaw onboard E2E.
  • openclaw-inference-switch (high): The PR changes inference set, route containment, route mutation locks, custom endpoint/API-family metadata, registry updates, and OpenClaw config synchronization. This validates a live OpenClaw route switch and inference.local/agent behavior.
  • hermes-inference-switch (high): The PR changes Hermes inference set handling, compatible Anthropic/OpenAI frontend metadata, gateway provider metadata, and route compatibility. This validates live Hermes route/config switching and runtime health.
  • inference-routing (medium): The PR changes setup-inference, endpoint guarding, provider route identity, credential/API-family metadata, and inference-routing user-error surfaces. This no-image live E2E gives focused coverage of inference onboarding/routing boundaries.
  • concurrent-gateway-ports (high): The new shared-gateway route compatibility model and docs direct users to distinct NEMOCLAW_GATEWAY_PORT values for independent routes. This validates multiple gateways/ports, dashboard allocation, registry binding, and isolation on a real host.
  • sandbox-operations (high): Changes to sandbox connect, connect-time inference route repair, registry binding, and sandbox lifecycle command support can affect day-two real user flows beyond onboarding. This exercises live sandbox operations against a real OpenShell sandbox.
  • snapshot-commands (medium): src/lib/actions/sandbox/snapshot.ts changed, so run the existing live snapshot command coverage to verify the day-two snapshot user flow still works against a real sandbox.

Optional E2E

  • model-router-provider-routed-inference (medium): Useful adjacent confidence for provider-routed inference through inference.local, especially because NIM route identity and served model metadata changed, but the core hosted and inference-switch coverage above is more directly tied to this PR.
  • ubuntu-repo-cloud-openclaw-double-provider-switch (high): Optional registry-target coverage for multi-sandbox/provider-switch lifecycle behavior. It is relevant to shared-gateway compatibility, but it runs through the registry target matrix rather than a free-standing job selector.
  • ubuntu-repo-cloud-openclaw-double-same-provider (high): Optional registry-target coverage for two same-provider hosted OpenClaw sandboxes sharing a gateway, useful for validating the compatible shared-route case.

New E2E recommendations

  • shared-gateway inference route containment (high): Existing E2Es cover single-sandbox OpenClaw/Hermes inference switching and separate gateway ports, but there does not appear to be a focused live E2E that registers multiple same-gateway sandboxes, leaves one stopped, attempts an incompatible custom route switch or connect-time repair, and asserts fail-closed behavior with no gateway/registry mutation.
    • Suggested test: shared-gateway-route-containment-e2e
  • legacy custom route metadata recovery (medium): The PR introduces fail-closed behavior for incomplete legacy custom endpoint/API-family metadata. Unit coverage exists, but a live E2E would validate the user-visible recovery path from a seeded legacy registry row through onboarding/inference set/connect diagnostics.
    • Suggested test: legacy-custom-route-metadata-fail-closed-e2e

Dispatch hint

  • Workflow: .github/workflows/e2e.yaml
  • jobs input: onboard-resume,onboard-repair,cloud-onboard,openclaw-inference-switch,hermes-inference-switch,inference-routing,concurrent-gateway-ports,sandbox-operations,snapshot-commands

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

E2E Target Recommendation

Required E2E targets: onboard-resume, onboard-repair, openclaw-inference-switch, hermes-inference-switch, inference-routing, double-onboard, concurrent-gateway-ports
Optional E2E targets: gpu-double-onboard

Dispatch required E2E targets:

  • gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=onboard-resume
  • gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=onboard-repair
  • gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=openclaw-inference-switch
  • gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=hermes-inference-switch
  • gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=inference-routing
  • gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=double-onboard
  • gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=concurrent-gateway-ports

Workflow run

Full E2E target advisor summary

E2E Target Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E targets

  • onboard-resume: Changes touch onboarding machine core phases, provider/sandbox handlers, resume-provider shim, setup-inference, and onboarding state transitions; the onboarding resume rule requires the live onboard-resume job.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=onboard-resume
  • onboard-repair: The same onboarding state-machine and persisted-session changes can affect repair/backstop execution from saved sessions, so onboard-repair is mandatory for these resume paths.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=onboard-repair
  • openclaw-inference-switch: Inference-set route containment, gateway route compatibility/mutation locking, registry route metadata, and OpenClaw config sync changed; this job exercises live OpenClaw provider/model/API-family switching and inference.local validation.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=openclaw-inference-switch
  • hermes-inference-switch: Hermes-specific inference route metadata and compatible Anthropic/OpenAI-frontend handling changed; this job exercises live Hermes inference set, durable route metadata, config/hash state, and runtime probes.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=hermes-inference-switch
  • inference-routing: Setup-inference, endpoint guarding, provider metadata, and route containment changes affect onboarding-time inference routing and fail-closed cleanup behavior covered by the inference-routing live job.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=inference-routing
  • double-onboard: Shared-gateway route compatibility, stopped-sandbox registry metadata, connect-time repair, and multi-sandbox gateway reuse changed; double-onboard is the smallest live job covering same-gateway multi-sandbox lifecycle behavior.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=double-onboard
  • concurrent-gateway-ports: Gateway binding and registry route reservation changes affect the separate-gateway escape path for sandboxes with independent inference routes; this job validates non-default gateway-port isolation.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=concurrent-gateway-ports

Optional E2E targets

  • gpu-double-onboard: Optional special-runner coverage for adjacent local/GPU multi-onboard behavior, given changes to local inference metadata and NIM/Ollama/vLLM setup paths; not the primary route-containment proof.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=gpu-double-onboard

Relevant changed files

  • bin/lib/nim-images.json
  • src/commands/inference/set.ts
  • src/commands/sandbox/inference/set.ts
  • src/lib/actions/inference-set-route-containment.ts
  • src/lib/actions/inference-set.ts
  • src/lib/actions/sandbox/connect-inference-gateway.ts
  • src/lib/actions/sandbox/connect.ts
  • src/lib/actions/sandbox/snapshot.ts
  • src/lib/cli/inference-set-help.ts
  • src/lib/inference/gateway-route-compatibility.ts
  • src/lib/inference/gateway-route-mutation-lock.ts
  • src/lib/inference/nim.ts
  • src/lib/inference/vllm.ts
  • src/lib/onboard.ts
  • src/lib/onboard/gateway-binding.ts
  • src/lib/onboard/gateway-provider-metadata.ts
  • src/lib/onboard/inference-route.ts
  • src/lib/onboard/machine/core-flow-phases.ts
  • src/lib/onboard/machine/handlers/provider-inference-route-containment.ts
  • src/lib/onboard/machine/handlers/provider-inference.ts
  • src/lib/onboard/machine/handlers/sandbox.ts
  • src/lib/onboard/resume-provider-shim.ts
  • src/lib/onboard/setup-inference.ts
  • src/lib/onboard/setup-nim-flow.ts
  • src/lib/onboard/setup-nim-ollama.ts
  • src/lib/onboard/setup-nim-selection.ts
  • src/lib/onboard/setup-nim-vllm.ts
  • src/lib/openshell-gateway-endpoint-guard.ts
  • src/lib/registry-recovery-action.ts
  • src/lib/state/registry.ts

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
src/commands/inference/set.ts (1)

74-86: 📐 Maintainability & Code Quality | 🔵 Trivial

Duplicate printRequiredFlags logic across command classes.

This private helper is nearly identical to the one added in src/commands/sandbox/inference/set.ts (Line 78-90), differing only in the command-name prefix and usage string. Per path instructions, src/commands/** should keep command classes focused on grammar/parsing/help while behavior/orchestration lives elsewhere; a shared helper (e.g. in src/lib/cli/**, which is meant for framework/metadata/help infrastructure) would avoid the copy-paste and keep the two messages from drifting apart as this containment feature evolves.

As per path instructions, src/{commands,lib/cli}/**: "Keep src/lib/cli/** limited to framework, metadata, routing, and help infrastructure rather than product behavior."

♻️ Sketch of a shared helper
// src/lib/cli/required-flags.ts
export function requiredFlagsFailureLines(usagePrefix: string): string[] {
  return [
    `  ${usagePrefix} requires --provider and --model.`,
    "",
    `  Run: ${usagePrefix} --provider <provider> --model <model>`,
    "  NemoClaw must perform this operation so it can protect every sandbox sharing the target gateway.",
    "",
    `  Run '${CLI_NAME} help' for NemoClaw commands.`,
  ];
}
🤖 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/commands/inference/set.ts` around lines 74 - 86, The `printRequiredFlags`
helper in `set.ts` duplicates nearly the same required-flags message logic used
by the sandbox inference command, so extract the shared message-building
behavior into a common helper instead of keeping copy-pasted private methods in
each command. Add the reusable helper in the shared CLI support area under
`src/lib/cli/**`, and have both `printRequiredFlags` callers use it with their
command-specific usage prefix so the command classes only handle wiring/help
text. Keep the command-specific `set.ts` method thin and delegate the actual
line generation to the shared utility to prevent the two messages from drifting.

Source: Path instructions

src/lib/inference/gateway-route-compatibility.test.ts (1)

217-224: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Test doesn't exercise the "skip incomplete row" claim.

The requested route's provider ("anthropic-prod") never matches either fixture row's provider ("nvidia-prod" / null), so this assertion would pass even without any special handling for incomplete rows — it's indistinguishable from an ordinary provider mismatch. To actually validate the "skip" behavior, use a row that shares the requested provider but is missing the model (or vice versa), e.g.:

🧪 Proposed fix to exercise the skip path
   it("skips registry rows without a complete provider and model (`#6315`)", () => {
     expect(
-      check(route("anthropic-prod", "claude-new"), [
-        sandbox("empty", { provider: null, model: null }),
-        sandbox("provider-only", { provider: "nvidia-prod", model: null }),
+      check(route("nvidia-prod", "nvidia/model-a"), [
+        sandbox("empty", { provider: null, model: null }),
+        sandbox("provider-only", { model: null }),
       ]),
     ).toEqual({ ok: true });
   });

This way the row shares the requested provider and would conflict if not skipped, so the assertion actually proves the skip behavior. As per path instructions, "Flag ... conditionals that make a test pass without exercising its claim."

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

In `@src/lib/inference/gateway-route-compatibility.test.ts` around lines 217 -
224, The test in check(route(...)) is not proving the “skip incomplete row”
behavior because the requested provider never matches the fixture rows, so it
passes for a normal mismatch. Update the fixture data in the it("skips registry
rows without a complete provider and model (`#6315`)") case so one row shares the
requested provider or model but is missing the other field, and keep using
sandbox(...) with check(...) to verify the incomplete row is actually ignored by
the route-compatibility logic.

Source: Path instructions

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

Nitpick comments:
In `@src/commands/inference/set.ts`:
- Around line 74-86: The `printRequiredFlags` helper in `set.ts` duplicates
nearly the same required-flags message logic used by the sandbox inference
command, so extract the shared message-building behavior into a common helper
instead of keeping copy-pasted private methods in each command. Add the reusable
helper in the shared CLI support area under `src/lib/cli/**`, and have both
`printRequiredFlags` callers use it with their command-specific usage prefix so
the command classes only handle wiring/help text. Keep the command-specific
`set.ts` method thin and delegate the actual line generation to the shared
utility to prevent the two messages from drifting.

In `@src/lib/inference/gateway-route-compatibility.test.ts`:
- Around line 217-224: The test in check(route(...)) is not proving the “skip
incomplete row” behavior because the requested provider never matches the
fixture rows, so it passes for a normal mismatch. Update the fixture data in the
it("skips registry rows without a complete provider and model (`#6315`)") case so
one row shares the requested provider or model but is missing the other field,
and keep using sandbox(...) with check(...) to verify the incomplete row is
actually ignored by the route-compatibility logic.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: b3b17449-4642-4973-952c-7a30cc190098

📥 Commits

Reviewing files that changed from the base of the PR and between 748a788 and fa6991d.

📒 Files selected for processing (28)
  • docs/inference/switch-inference-providers.mdx
  • docs/reference/commands-nemohermes.mdx
  • docs/reference/commands.mdx
  • docs/reference/troubleshooting.mdx
  • src/commands/inference/set.ts
  • src/commands/sandbox/inference/oclif-command-adapters.test.ts
  • src/commands/sandbox/inference/set.ts
  • src/lib/actions/inference-set-compatible-provider.test.ts
  • src/lib/actions/inference-set-gateway-route-containment.test.ts
  • src/lib/actions/inference-set-hermes-run.test.ts
  • src/lib/actions/inference-set-openclaw-run.test.ts
  • src/lib/actions/inference-set.ts
  • src/lib/actions/sandbox/connect-route-lifecycle.test.ts
  • src/lib/actions/sandbox/connect-route-repair.test.ts
  • src/lib/actions/sandbox/connect.ts
  • src/lib/inference/gateway-route-compatibility.test.ts
  • src/lib/inference/gateway-route-compatibility.ts
  • src/lib/onboard.ts
  • src/lib/onboard/machine/core-flow-phases.test.ts
  • src/lib/onboard/machine/handlers/provider-inference.test.ts
  • src/lib/onboard/machine/handlers/provider-inference.ts
  • src/lib/onboard/setup-inference-route-containment.test.ts
  • src/lib/onboard/setup-inference.ts
  • test/cli/list-inference.test.ts
  • test/onboard-inference-smoke.test.ts
  • test/onboard-selection.test.ts
  • test/support/connect-flow-test-harness.ts
  • test/support/setup-inference-test-harness.ts

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
ericksoa added 5 commits July 6, 2026 12:20
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
…e-containment

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

# Conflicts:
#	src/lib/actions/inference-set-hermes-run.test.ts
#	src/lib/actions/inference-set.ts
#	src/lib/onboard.ts
#	src/lib/onboard/machine/handlers/provider-inference.ts
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@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

🧹 Nitpick comments (1)
src/lib/onboard/inference-route.ts (1)

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

Inconsistent dependency injection for the new compatibility gate.

verifyInferenceRoute/isInferenceRouteReady both use the factory's injected runCaptureOpenshell, but checkGatewayRouteCompatibility reaches for a directly-imported listSandboxes() instead of taking it as a parameter. This is a security-relevant guard (contains cross-sandbox route conflicts), so it's worth keeping it consistent and fake-injectable like the rest of the module rather than requiring module-level mocking in tests.

♻️ Suggested DI-consistent refactor
-export function createInferenceRouteHelpers(runCaptureOpenshell: RunCaptureOpenshell) {
+export function createInferenceRouteHelpers(
+  runCaptureOpenshell: RunCaptureOpenshell,
+  listSandboxesFn: typeof listSandboxes = listSandboxes,
+) {
   ...
   const checkGatewayRouteCompatibility: CurrentGatewayRouteCompatibilityCheck = (request) =>
     checkGatewayRouteCompatibilityForRegistry({
       ...request,
-      sandboxes: listSandboxes().sandboxes,
+      sandboxes: listSandboxesFn().sandboxes,
     });

Also applies to: 29-35

🤖 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/inference-route.ts` around lines 5 - 9, The new compatibility
gate is mixing injected dependencies with a direct module import, so update
checkGatewayRouteCompatibility in inference-route to accept listSandboxes as an
injected dependency instead of importing it directly. Thread that dependency
through the existing factory/entry points used by verifyInferenceRoute and
isInferenceRouteReady so the gate stays fake-injectable and consistent with
runCaptureOpenshell. Keep the current compatibility logic intact, but remove the
module-level reliance on listSandboxes from this flow.

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/inference-set-route-containment.ts`:
- Around line 262-342: Refresh the sandbox snapshot before the final
compatibility check in finalizeInferenceSetRoute. The current re-check still
uses the caller-provided sandboxes array, so it can miss a conflicting route
change that happens during normalizeCustomEndpointUrl. Update
finalizeInferenceSetRoute to re-read the latest registry or otherwise obtain a
fresh sandboxes snapshot immediately before calling
assertGatewayRouteCompatibility, using the existing
prepareInferenceSetRoute/finalizeInferenceSetRoute flow and gatewayName metadata
to locate the right guard.

---

Nitpick comments:
In `@src/lib/onboard/inference-route.ts`:
- Around line 5-9: The new compatibility gate is mixing injected dependencies
with a direct module import, so update checkGatewayRouteCompatibility in
inference-route to accept listSandboxes as an injected dependency instead of
importing it directly. Thread that dependency through the existing factory/entry
points used by verifyInferenceRoute and isInferenceRouteReady so the gate stays
fake-injectable and consistent with runCaptureOpenshell. Keep the current
compatibility logic intact, but remove the module-level reliance on
listSandboxes from this flow.
🪄 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: 4a7fd800-e8e2-408f-8184-cfb6159616da

📥 Commits

Reviewing files that changed from the base of the PR and between e9b9658 and 6dd3c1c.

📒 Files selected for processing (30)
  • docs/about/release-notes.mdx
  • docs/inference/switch-inference-providers.mdx
  • docs/reference/commands-nemohermes.mdx
  • docs/reference/commands.mdx
  • docs/reference/troubleshooting.mdx
  • src/lib/actions/inference-set-gateway-route-containment.test.ts
  • src/lib/actions/inference-set-hermes-run.test.ts
  • src/lib/actions/inference-set-route-containment.ts
  • src/lib/actions/inference-set.ts
  • src/lib/actions/sandbox/connect-inference-gateway.ts
  • src/lib/actions/sandbox/connect-route-containment.test.ts
  • src/lib/actions/sandbox/connect-route-lifecycle.test.ts
  • src/lib/actions/sandbox/connect.ts
  • src/lib/inference/gateway-route-compatibility.test.ts
  • src/lib/inference/gateway-route-compatibility.ts
  • src/lib/onboard.ts
  • src/lib/onboard/gateway-provider-metadata.test.ts
  • src/lib/onboard/gateway-provider-metadata.ts
  • src/lib/onboard/inference-route.ts
  • src/lib/onboard/machine/core-flow-phases.test.ts
  • src/lib/onboard/machine/core-flow-phases.ts
  • src/lib/onboard/machine/handlers/provider-inference-route-containment.test.ts
  • src/lib/onboard/machine/handlers/provider-inference-route-containment.ts
  • src/lib/onboard/machine/handlers/provider-inference.test.ts
  • src/lib/onboard/machine/handlers/provider-inference.ts
  • src/lib/onboard/resume-provider-shim.ts
  • src/lib/onboard/setup-inference-route-containment.test.ts
  • src/lib/onboard/setup-inference.ts
  • test/onboard-remote-recreate-credential-reuse.test.ts
  • test/onboard-selection.test.ts
✅ Files skipped from review due to trivial changes (4)
  • docs/about/release-notes.mdx
  • src/lib/onboard/machine/core-flow-phases.test.ts
  • docs/reference/troubleshooting.mdx
  • docs/inference/switch-inference-providers.mdx
🚧 Files skipped from review as they are similar to previous changes (11)
  • src/lib/actions/inference-set-hermes-run.test.ts
  • src/lib/onboard/setup-inference-route-containment.test.ts
  • src/lib/onboard/setup-inference.ts
  • test/onboard-selection.test.ts
  • src/lib/inference/gateway-route-compatibility.test.ts
  • src/lib/onboard.ts
  • src/lib/inference/gateway-route-compatibility.ts
  • docs/reference/commands.mdx
  • docs/reference/commands-nemohermes.mdx
  • src/lib/onboard/machine/handlers/provider-inference.ts
  • src/lib/actions/inference-set.ts

Comment thread src/lib/actions/inference-set-route-containment.ts
ericksoa added 2 commits July 7, 2026 11:40
…e-containment

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

# Conflicts:
#	src/lib/onboard/setup-nim-flow.ts
…e-containment

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

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

E2E Target Results — ✅ All selected jobs passed

Run: 28890883985
Workflow ref: fix/6315-gateway-route-containment
Requested targets: ubuntu-repo-cloud-langchain-deepagents-code
Requested jobs: (default — all default-enabled free-standing jobs; explicit-only jobs openshell-gateway-auth-contract, mcp-bridge-dev, hermes-gpu-startup, sandbox-rlimits-connect, and jetson-nvmap-gpu are skipped unless selected)
Summary: 1 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
live ✅ success

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

E2E Target Results — ✅ All selected jobs passed

Run: 28890884098
Workflow ref: fix/6315-gateway-route-containment
Requested targets: onboard-resume,onboard-repair,cloud-onboard,inference-routing,cloud-inference,openclaw-inference-switch,hermes-inference-switch,snapshot-commands,concurrent-gateway-ports,sandbox-operations,double-onboard,ubuntu-repo-cloud-openclaw-double-same-provider,ubuntu-repo-cloud-openclaw-double-provider-switch
Requested jobs: (default — all default-enabled free-standing jobs; explicit-only jobs openshell-gateway-auth-contract, mcp-bridge-dev, hermes-gpu-startup, sandbox-rlimits-connect, and jetson-nvmap-gpu are skipped unless selected)
Summary: 12 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
cloud-inference ✅ success
cloud-onboard ✅ success
concurrent-gateway-ports ✅ success
double-onboard ✅ success
hermes-inference-switch ✅ success
inference-routing ✅ success
live ✅ success
onboard-repair ✅ success
onboard-resume ✅ success
openclaw-inference-switch ✅ success
sandbox-operations ✅ success
snapshot-commands ✅ success

@ericksoa

ericksoa commented Jul 7, 2026

Copy link
Copy Markdown
Contributor Author

@cv Exact-head follow-up: main advanced after your 9/9 reviewer-owned lanes passed, so this supersedes my 81f9e394 request. The current head is 78774982d423e4e7a63d29f6291280621209eb02, containing main through fa73ac31.

The only production conflict was additive in setup-nim-flow.ts: main introduced DCode's Ultra default while this PR introduced same-gateway discovery constraints. The resolution preserves both and adds a combined regression proving an existing same-gateway route overrides Ultra before any provider probe. Conflict-focused setup/default/route tests pass 114/114; DCode integration passes 75/75; final rebuild/gateway tests pass 29/29; local check:diff, CLI typecheck, budgets, formatting, and strict docs validation pass.

Fresh exact-head evidence:

  • standard CI passed all five shards and final aggregate, with every required context green;
  • 13-selector containment E2E passed 15/15 lanes;
  • DCode cloud E2E passed 1/1 lane;
  • GPT-5.5 again reports zero required findings; neither advisor reproduces the recovered-row defect.

The branch is mergeable, and all 43 commits are verified and signed off. Please rereview 78774982 and approve it, or identify any remaining concrete blocker.

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

E2E Target Results — ✅ All selected jobs passed

Run: 28891651353
Workflow ref: fix/6315-gateway-route-containment
Requested targets: ubuntu-repo-cloud-openclaw
Requested jobs: (default — all default-enabled free-standing jobs; explicit-only jobs openshell-gateway-auth-contract, mcp-bridge-dev, hermes-gpu-startup, sandbox-rlimits-connect, and jetson-nvmap-gpu are skipped unless selected)
Summary: 1 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
live ✅ success

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

E2E Target Results — ✅ All requested jobs passed

Run: 28891670558
Workflow ref: fix/6315-gateway-route-containment
Requested targets: (default — all supported)
Requested jobs: cloud-onboard,inference-routing
Summary: 2 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
cloud-onboard ✅ success
inference-routing ✅ success

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

E2E Target Results — ✅ All requested jobs passed

Run: 28891647223
Workflow ref: fix/6315-gateway-route-containment
Requested targets: (default — all supported)
Requested jobs: onboard-resume,onboard-repair,openclaw-inference-switch,hermes-inference-switch,double-onboard,concurrent-gateway-ports
Summary: 6 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
concurrent-gateway-ports ✅ success
double-onboard ✅ success
hermes-inference-switch ✅ success
onboard-repair ✅ success
onboard-resume ✅ success
openclaw-inference-switch ✅ success

cv added 2 commits July 7, 2026 12:41
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

E2E Target Results — ✅ All selected jobs passed

Run: 28893939992
Workflow ref: fix/6315-gateway-route-containment
Requested targets: ubuntu-repo-cloud-openclaw
Requested jobs: (default — all default-enabled free-standing jobs; explicit-only jobs openshell-gateway-auth-contract, mcp-bridge-dev, hermes-gpu-startup, sandbox-rlimits-connect, and jetson-nvmap-gpu are skipped unless selected)
Summary: 1 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
live ✅ success

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

E2E Target Results — ✅ All requested jobs passed

Run: 28893935439
Workflow ref: fix/6315-gateway-route-containment
Requested targets: (default — all supported)
Requested jobs: onboard-resume,onboard-repair,cloud-onboard,inference-routing,openclaw-inference-switch,hermes-inference-switch,concurrent-gateway-ports,double-onboard
Summary: 8 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
cloud-onboard ✅ success
concurrent-gateway-ports ✅ success
double-onboard ✅ success
hermes-inference-switch ✅ success
inference-routing ✅ success
onboard-repair ✅ success
onboard-resume ✅ success
openclaw-inference-switch ✅ success

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

E2E Target Results — ✅ All requested jobs passed

Run: 28894237287
Workflow ref: fix/6315-gateway-route-containment
Requested targets: (default — all supported)
Requested jobs: sandbox-operations,snapshot-commands
Summary: 2 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
sandbox-operations ✅ success
snapshot-commands ✅ success

@cv

cv commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator

Maintainer disposition for PRA-1 on exact head 7df7274c138efe4080993378863a21b4567db842:

The absence of a dedicated checked-in same-gateway conflict live target is accepted for this PR. Adding that target here would require a broader stateful registry/gateway orchestration fixture beyond the narrow merge salvage. The exact security delta is covered by behavior-specific fail-closed tests, while real OpenShell integration is covered by the complete exact-head live matrix below.

Evidence:

  • src/lib/registry-recovery-seeded-paths.test.ts recovers a live durable row with missing provider/model metadata, then invokes the real inference-set action and proves exit 2 before DNS pinning, OpenShell, config writes, registry/session updates, audit entries, or gateway restart.
  • Route-containment tests cover a peer appearing after DNS validation, final peer snapshot recheck, lock serialization, incomplete custom metadata, and gateway rebinding.
  • The independent nine-category security review found no actionable issue across SSRF/input validation, credentials, gateway scoping, logging, secure defaults, testing, or TOCTOU/concurrency.
  • Exact-head attached CI is fully green with CodeRabbit SUCCESS and zero unresolved threads.
  • Exact-head live runs passed:

Manual validation procedure for the residual dedicated-target gap:

  1. Create or register two sandboxes on one gateway with different durable routes. Record openshell inference get -g <gateway>, attempt the conflicting inference set, and verify it fails before an endpoint probe or mutation and that the recorded live route is unchanged.
  2. Repeat the desired route on a separate NEMOCLAW_GATEWAY_PORT; verify it succeeds there and the default gateway route remains unchanged.
  3. Stop the conflicting same-gateway peer, run connect --probe-only on the other sandbox, and verify no repair write occurs and the live gateway route remains unchanged.

A dedicated checked-in same-gateway conflict target remains desirable future hardening, but the focused no-side-effect regressions plus the successful real OpenShell matrix make that absence non-blocking for this PR.

@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.

Approved exact head 7df7274. The conflict resolution preserves shared-gateway locking, fail-closed incomplete-row handling, and the post-DNS fresh-peer recheck while incorporating the landed provider-alias and no-SSRF-bypass behavior. All 45 commits are Verified with DCO present; attached CI is fully green; CodeRabbit has no unresolved findings; the independent nine-category security review is clean; every refreshed E2E Advisor requirement passed in runs 28893935439, 28893939992, and 28894237287; and primary PR Review Advisor attempt 3 is merge_as_is. The contributor/approver overlap is the merge-gate advisory only and does not change readiness.

@cv cv merged commit fece345 into main Jul 7, 2026
284 checks passed
@cv cv deleted the fix/6315-gateway-route-containment branch July 7, 2026 20:31
apurvvkumaria added a commit that referenced this pull request Jul 8, 2026
<!-- markdownlint-disable MD041 -->
## Summary

Prepares the user-facing documentation for NemoClaw v0.0.76 and closes
the release-prep documentation gate. It adds the release highlights,
documents the arm64 Local NIM warning and expanded image cleanup
behavior, and fixes agent-specific command headings in generated guides.

## Changes

- Add the v0.0.76 release-notes section and move the shared-gateway
route containment entry out of the v0.0.74 history where it was
incorrectly placed.
- Document the advisory Linux arm64 Local NIM manifest warning in the
canonical platform matrix and local-inference guidance.
- Document that `gc` scans both gateway-built and locally prebuilt
sandbox image repositories.
- Keep OpenClaw and Hermes session headings out of the generated Deep
Agents command guide.
- Add a focused variant regression test for the agent-specific session
headings.

### Source summary

| Merged sources | Documentation coverage |
| --- | --- |
| [#6414](#6414),
[#6418](#6418),
[#6416](#6416),
[#6344](#6344) | v0.0.76 release
notes and the Deep Agents quickstart/inference routes |
| [#6340](#6340) | v0.0.76
release notes and existing Deep Agents observability guidance |
| [#6338](#6338),
[#6378](#6378),
[#6297](#6297) | v0.0.76 release
notes and existing inference/troubleshooting guidance |
| [#6362](#6362) | v0.0.76
release notes and existing lifecycle, command, and credential guidance |
| [#6330](#6330),
[#6307](#6307),
[#6008](#6008) | v0.0.76 release
notes and existing security, troubleshooting, and command guidance |
| [#6382](#6382) | v0.0.76
release notes and existing MCP/command guidance |
| [#6326](#6326),
[#5868](#5868),
[#5539](#5539) | v0.0.76 release
notes, platform matrix, inference options, and local-inference guidance
|
| [#6396](#6396),
[#6390](#6390),
[#6007](#6007) | v0.0.76 release
notes and existing messaging guidance |
| [#5388](#5388),
[#6249](#6249),
[#6303](#6303),
[#6306](#6306) | v0.0.76 release
notes and command/lifecycle guidance |

## Type of Change

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

## Quality Gates

- [x] Tests added or updated for changed behavior
- [ ] Existing tests cover changed behavior — justification:
- [ ] Tests not applicable — justification:
- [x] Docs updated for user-facing behavior changes
- [ ] Docs not applicable — justification:
- [ ] Sensitive paths changed (security, policy, credentials, preflight,
onboarding, inference, runner, sandbox, or messaging)
- [ ] Sensitive-path review completed or maintainer-approved waiver
recorded — reviewer/approval link/justification:
- [ ] Non-success, skipped, or missing CI check accepted by maintainer —
check name, approval link, and follow-up issue:

## Verification

- [x] PR description includes the DCO sign-off declaration and every
commit appears as `Verified` in GitHub
- [x] Normal `pre-commit`, `commit-msg`, and `pre-push` hooks passed, or
`npm run check:diff` passed when hooks were skipped or unavailable
- [x] Targeted behavior tests pass for the current change set, or tests
are marked not applicable above — `npx vitest run --project integration
test/generate-platform-docs.test.ts test/agent-variant-docs.test.ts
test/sync-agent-variant-docs.test.ts` (3 files, 29 tests passed)
- [ ] Applicable broad gate passed — `npm test` for broad
runtime/test-harness changes; `npm run check` for repo-wide
validation/coverage changes — command/result:
- [x] Quality Gates section completed with required justifications or
waivers
- [x] No secrets, API keys, or credentials committed
- [ ] `npm run docs` builds without warnings (doc changes only) —
completed with 0 errors and 2 pre-existing Fern warnings
- [x] Doc pages follow the [style
guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md)
(doc changes only)
- [ ] New doc pages include SPDX header and frontmatter (new pages only)

---
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>


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

## Summary by CodeRabbit

* **Documentation**
* Added v0.0.76 release notes content, and removed an older conflicting
bullet from the surrounding release history.
* Expanded Local NVIDIA NIM guidance across inference/provider docs,
including an advisory for Linux arm64 DGX Spark/DGX Station hosts when a
matching `linux/arm64` image manifest is unavailable.
* Updated the command reference for correct session-section rendering
and clarified `gc` image cleanup sources.
* **Tests**
* Added coverage ensuring Deep Agents omits sessions headings while
Hermes includes them.
* **CI**
* Refreshed Local NVIDIA NIM provider notes used in the platform matrix.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
cv pushed a commit that referenced this pull request Jul 9, 2026
…ecorded route (#6465)

<!-- markdownlint-disable MD041 -->
## Summary

`nemoclaw <name> status` previously showed the live host-gateway
inference route as though it were the sandbox's own route. When an
out-of-band operation such as direct `openshell inference set` makes
that route differ from the sandbox's recorded provider/model, this PR
now emits an explicit warning and safe remediation guidance.

## Related Issue

Refs #6315. This complements #6338's fail-closed containment for
supported flows by surfacing residual out-of-band drift in status; it
follows the connect-time divergence behavior from #3726.

## Changes

- Compute `routeDrift` only when a complete, readable live route differs
from a complete recorded route.
- Show the live and recorded routes, explain that `connect` realigns to
the recorded route, and show the supported `inference set --sandbox`
path for adopting the live route.
- Share one control-character-sanitized warning formatter between status
and connect so the messages cannot drift.
- Cover divergent, aligned, unreadable, and missing-record cases plus
rendered status output.
- Document the warning in the existing one-route-per-gateway guidance.

## Original Author Credit

@Hokonoken authored the diagnosis, implementation, tests, live proof,
and documentation. The maintainer synchronization preserves those
commits, and the review-fix commit records Hokonoken as co-author.

## Type of Change

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

## Quality Gates

- [x] Tests added or updated for changed behavior
- [ ] Existing tests cover changed behavior — justification:
- [ ] Tests not applicable — justification:
- [x] Docs updated for user-facing behavior changes
- [ ] Docs not applicable — justification:
- [x] Sensitive paths changed (security, policy, credentials, preflight,
onboarding, inference, runner, sandbox, or messaging)
- [x] Sensitive-path review completed — display-only route comparison;
no route, registry, credential, or sandbox mutation is introduced;
untrusted route values use the shared sanitizer
- [ ] Non-success, skipped, or missing CI check accepted by maintainer —
check name, approval link, and follow-up issue:

## Verification

- [x] PR description includes DCO declarations and every commit is
GitHub Verified
- [x] Normal pre-commit, commit-msg, and pre-push hooks passed on the
current head
- [x] Focused config, connect-route, status-flow, and snapshot tests —
87/87 passed with one local worker
- [x] `npm run build:cli` — passed
- [x] Plugin build — passed
- [x] `npm run docs` — 0 errors and 2 pre-existing Fern warnings
- [x] Documentation-writer review confirmed the existing page update is
accurate and sufficient
- [x] Quality Gates section completed with required justifications
- [x] No secrets, API keys, or credentials committed
- [x] Doc pages follow the style guide
- [ ] New doc pages include SPDX header and frontmatter (new pages only)

---

Signed-off-by: Hokonoken <41166525+Hokonoken@users.noreply.github.com>
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>


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

* **New Features**
* Sandbox status now detects “route drift” between the live gateway
inference route and the sandbox’s recorded route, showing a warning with
commands to realign or adopt the live route.
* **Bug Fixes**
* If the live route can’t be read, route-drift warnings are suppressed
to avoid misleading output.
* **Tests**
* Added/expanded coverage for route-drift metadata,
warning/sanitization, and safe shell-escaping in emitted commands.
* **Documentation**
* Updated “switch inference providers” docs with the new route-drift
warning and resolution steps.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Hokonoken <41166525+Hokonoken@users.noreply.github.com>
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
Signed-off-by: Charan Jagwani <cjagwani@nvidia.com>
Co-authored-by: Apurv Kumaria <akumaria@nvidia.com>
Co-authored-by: Charan Jagwani <cjagwani@nvidia.com>
Hadar301 pushed a commit to Hadar301/NemoClaw-OpenShift that referenced this pull request Jul 12, 2026
<!-- markdownlint-disable MD041 -->
## Summary

Contain the current one-route-per-OpenShell-gateway behavior so
onboarding, runtime inference switches, and connect-time repair cannot
silently change the route used by another registered sandbox. This is a
compatibility guard for the current OpenShell contract; true
simultaneous per-sandbox routing remains upstream work.

## Related Issue

Addresses NVIDIA#6315

## Changes

- Compare the requested provider/model and custom endpoint/API family
with every durable registry row on the target gateway, including stopped
sandboxes.
- Allow identical routes and different gateways; fail closed for
same-gateway conflicts, missing durable provider/model identity,
incomplete legacy custom-route identity, and invalid gateway bindings.
- Run the guard before onboarding setup, resumed setup, runtime
`inference set`, connect-time route writes, endpoint probes, or repair
mutations.
- Serialize route-sensitive onboarding, runtime switches, connect
repair, snapshot restore, and registry recovery per gateway; different
gateways remain independent.
- Persist a full pending route reservation before verification/smoke
checks, and revalidate the target reservation under the gateway lock
before creating or reusing a sandbox.
- Resolve `inference set -g` from the target sandbox's recorded gateway
instead of hardcoding the default gateway.
- Keep missing-flag guidance inside NemoClaw so users do not bypass the
shared-route protection with raw OpenShell commands.
- Document the one-route-per-gateway contract and recovery options:
align routes, remove the conflicting sandbox, or use another
`NEMOCLAW_GATEWAY_PORT`.

## Type of Change

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

## Quality Gates

- [x] Tests added or updated for changed behavior
- [ ] Existing tests cover changed behavior — justification:
- [ ] Tests not applicable — justification:
- [x] Docs updated for user-facing behavior changes
- [ ] Docs not applicable — justification:
- [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: exact head `7df7274c`
passed an independent nine-category security review with no findings;
the maintainer disposition, exact-head E2E evidence, and manual
validation procedure are recorded
[here](NVIDIA#6338 (comment)).
- [ ] 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 — all 45 PR commits are
GitHub-verified and signed off at
`7df7274c138efe4080993378863a21b4567db842`.
- [x] Normal `pre-commit`, `commit-msg`, and `pre-push` hooks passed, or
`npm run check:diff` passed when hooks were skipped or unavailable —
normal pre-commit, commit-msg, and pre-push hooks passed for the
merge-resolution and documentation commits at exact head `7df7274c`.
- [x] Targeted behavior tests pass for the current change set, or tests
are marked not applicable above — 93 conflict-focused assertions and CLI
typecheck passed locally after the merge; an independent exact-head
security pass reran 108 focused assertions across route locking, DNS
finalization, late peers, incomplete recovered rows, aliases, SSRF
no-bypass behavior, connect/onboard containment, and local-provider
probes.
- [x] Applicable broad gate passed — refreshed exact-head CI [run
28893800691](https://github.com/NVIDIA/NemoClaw/actions/runs/28893800691)
passed all five CLI shards, aggregate tests/checks, build/typecheck,
installer, plugin, security, docs, macOS/WSL, self-hosted, and
growth-guard jobs; all five required contexts pass.
- [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) — 0
errors; Fern reports two pre-existing hidden warnings.
- [x] Doc pages follow the [style
guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md)
(doc changes only)
- [ ] New doc pages include SPDX header and frontmatter (new pages only)

Additional validation: CLI typecheck, formatting, source/test budgets,
the Fern docs build, and normal git hooks passed for the final merge and
docs changes at `7df7274c`. The top-level `src/lib/onboard.ts` is
net-neutral against the PR base (`+139/-139`). This branch includes
`main` through `376ebe2ed18f71555aca0d139337e7f6a9a76e90`. The DCode
default-model conflict in `setup-nim-flow.ts` was resolved additively:
DCode retains its Ultra default and logger, while same-gateway discovery
constraints, pre-probe checks, exact route checks, and API coercion
remain intact; the combined interaction is now regression-tested. The
later rebuild loader-seam merge was conflict-free. The race coverage
includes same-gateway serialization, independent gateways,
DNS-normalized endpoint changes between preliminary and finalized
checks, gateway-binding changes while queued, pending-reservation loss,
snapshot pre-delete rejection, recovered rows with incomplete durable
route identity, and zero-mutation conflict exits. The earlier isolated
OpenShell 0.0.72 proof `2026-07-06T23-01-11-471Z-pid-7719` remains
applicable to the unchanged live containment path: identical
same-gateway onboarding succeeded; a conflicting same-gateway onboard
named both peers, made zero conflicting endpoint probes, and left the
first route, providers, sandboxes, forwards, configs, containers,
images, volumes, registry, credentials, gateway PID, and data plane
unchanged; the same conflicting route succeeded on a separate gateway
without changing gateway A; all cleanup checks passed. Final exact-head
E2E passed every refreshed advisor requirement: [run
28893935439](https://github.com/NVIDIA/NemoClaw/actions/runs/28893935439)
covered resume/repair, cloud onboarding, inference routing, both
OpenClaw variants, both Hermes variants, double-onboard, and concurrent
gateway ports; [run
28893939992](https://github.com/NVIDIA/NemoClaw/actions/runs/28893939992)
passed the canonical OpenClaw cloud target; and [run
28894237287](https://github.com/NVIDIA/NemoClaw/actions/runs/28894237287)
passed sandbox operations and snapshot commands. Exact-head GPT-5.5
attempt 2 reports zero required findings and one runtime-test warning.
The explicit maintainer acceptance of that residual checked-in-target
gap, its rationale, exact-head live evidence, and reproducible manual
validation procedure are recorded
[here](NVIDIA#6338 (comment)).
Nemotron's only required item applies an unenforced 20-line growth
heuristic even though the repository's 1,500-line test budget passes. An
independent exact-head audit found no remaining product or security
defect.

<details>
<summary>Advisor scope rationale</summary>

- The two-phase custom-route check is intentional: the synchronous
preliminary guard rejects known registry conflicts before endpoint work,
then asynchronous DNS validation feeds a fresh-registry final guard
before any OpenShell, config, or registry mutation. The removal
condition is concrete: collapse the phases only when preparation can
consume fully DNS-validated metadata without an earlier endpoint probe
or mutation.
- Registry recovery never invents missing route identity, probes an
endpoint, or changes the live gateway route. Complete recovered
identities are compatibility-checked; a durable recovered row with
missing provider/model is preserved for inventory but makes every later
same-gateway route mutation fail closed until the row is removed and
re-onboarded. DNS pinning remains at the later endpoint-use/mutation
boundary.
- Snapshot restore compares the recorded route through the shared
compatibility guard under the gateway mutation lock. It does not
introduce or probe a new custom endpoint, so adding a second DNS-pinning
path there would duplicate the endpoint-use boundary without closing a
mutation gap.
- Both the ambient `OPENSHELL_GATEWAY_ENDPOINT` environment path and the
explicit endpoint flag are rejected or validated at their entry
boundaries; neither bypasses the compatibility guard.
- Further splits of `connect.ts`, provider onboarding, and the focused
containment test files would be structural refactors without changing
this issue's behavior. All affected files remain within the repository's
enforced source/test budgets, so those splits are deferred to avoid
widening the containment PR and its regression surface.
- The OpenShell 0.0.72 proof above covers the same-gateway conflict
contract and separate-gateway success path; the refreshed exact-head E2E
run covers onboarding, repair, switching, sandbox operations,
multi-gateway behavior, and stale rebuild.
- Overlapping PR merge order requires maintainer coordination: this
branch contains `main` through `376ebe2e`; overlapping route-changing
work should rebase after this containment change lands. No change inside
this PR can safely rewrite those independent branches.
- Validation failures are intentionally converted to credential-safe
`InferenceSetError` messages. Preserving raw URL/DNS error causes would
risk exposing untrusted endpoint detail and is not required for the
fail-closed behavior.

</details>

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

---------

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
Co-authored-by: Carlos Villela <cvillela@nvidia.com>
Hadar301 pushed a commit to Hadar301/NemoClaw-OpenShift that referenced this pull request Jul 12, 2026
<!-- markdownlint-disable MD041 -->
## Summary

Prepares the user-facing documentation for NemoClaw v0.0.76 and closes
the release-prep documentation gate. It adds the release highlights,
documents the arm64 Local NIM warning and expanded image cleanup
behavior, and fixes agent-specific command headings in generated guides.

## Changes

- Add the v0.0.76 release-notes section and move the shared-gateway
route containment entry out of the v0.0.74 history where it was
incorrectly placed.
- Document the advisory Linux arm64 Local NIM manifest warning in the
canonical platform matrix and local-inference guidance.
- Document that `gc` scans both gateway-built and locally prebuilt
sandbox image repositories.
- Keep OpenClaw and Hermes session headings out of the generated Deep
Agents command guide.
- Add a focused variant regression test for the agent-specific session
headings.

### Source summary

| Merged sources | Documentation coverage |
| --- | --- |
| [NVIDIA#6414](NVIDIA#6414),
[NVIDIA#6418](NVIDIA#6418),
[NVIDIA#6416](NVIDIA#6416),
[NVIDIA#6344](NVIDIA#6344) | v0.0.76 release
notes and the Deep Agents quickstart/inference routes |
| [NVIDIA#6340](NVIDIA#6340) | v0.0.76
release notes and existing Deep Agents observability guidance |
| [NVIDIA#6338](NVIDIA#6338),
[NVIDIA#6378](NVIDIA#6378),
[NVIDIA#6297](NVIDIA#6297) | v0.0.76 release
notes and existing inference/troubleshooting guidance |
| [NVIDIA#6362](NVIDIA#6362) | v0.0.76
release notes and existing lifecycle, command, and credential guidance |
| [NVIDIA#6330](NVIDIA#6330),
[NVIDIA#6307](NVIDIA#6307),
[NVIDIA#6008](NVIDIA#6008) | v0.0.76 release
notes and existing security, troubleshooting, and command guidance |
| [NVIDIA#6382](NVIDIA#6382) | v0.0.76
release notes and existing MCP/command guidance |
| [NVIDIA#6326](NVIDIA#6326),
[NVIDIA#5868](NVIDIA#5868),
[NVIDIA#5539](NVIDIA#5539) | v0.0.76 release
notes, platform matrix, inference options, and local-inference guidance
|
| [NVIDIA#6396](NVIDIA#6396),
[NVIDIA#6390](NVIDIA#6390),
[NVIDIA#6007](NVIDIA#6007) | v0.0.76 release
notes and existing messaging guidance |
| [NVIDIA#5388](NVIDIA#5388),
[NVIDIA#6249](NVIDIA#6249),
[NVIDIA#6303](NVIDIA#6303),
[NVIDIA#6306](NVIDIA#6306) | v0.0.76 release
notes and command/lifecycle guidance |

## Type of Change

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

## Quality Gates

- [x] Tests added or updated for changed behavior
- [ ] Existing tests cover changed behavior — justification:
- [ ] Tests not applicable — justification:
- [x] Docs updated for user-facing behavior changes
- [ ] Docs not applicable — justification:
- [ ] Sensitive paths changed (security, policy, credentials, preflight,
onboarding, inference, runner, sandbox, or messaging)
- [ ] Sensitive-path review completed or maintainer-approved waiver
recorded — reviewer/approval link/justification:
- [ ] Non-success, skipped, or missing CI check accepted by maintainer —
check name, approval link, and follow-up issue:

## Verification

- [x] PR description includes the DCO sign-off declaration and every
commit appears as `Verified` in GitHub
- [x] Normal `pre-commit`, `commit-msg`, and `pre-push` hooks passed, or
`npm run check:diff` passed when hooks were skipped or unavailable
- [x] Targeted behavior tests pass for the current change set, or tests
are marked not applicable above — `npx vitest run --project integration
test/generate-platform-docs.test.ts test/agent-variant-docs.test.ts
test/sync-agent-variant-docs.test.ts` (3 files, 29 tests passed)
- [ ] Applicable broad gate passed — `npm test` for broad
runtime/test-harness changes; `npm run check` for repo-wide
validation/coverage changes — command/result:
- [x] Quality Gates section completed with required justifications or
waivers
- [x] No secrets, API keys, or credentials committed
- [ ] `npm run docs` builds without warnings (doc changes only) —
completed with 0 errors and 2 pre-existing Fern warnings
- [x] Doc pages follow the [style
guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md)
(doc changes only)
- [ ] New doc pages include SPDX header and frontmatter (new pages only)

---
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>


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

## Summary by CodeRabbit

* **Documentation**
* Added v0.0.76 release notes content, and removed an older conflicting
bullet from the surrounding release history.
* Expanded Local NVIDIA NIM guidance across inference/provider docs,
including an advisory for Linux arm64 DGX Spark/DGX Station hosts when a
matching `linux/arm64` image manifest is unavailable.
* Updated the command reference for correct session-section rendering
and clarified `gc` image cleanup sources.
* **Tests**
* Added coverage ensuring Deep Agents omits sessions headings while
Hermes includes them.
* **CI**
* Refreshed Local NVIDIA NIM provider notes used in the platform matrix.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
Hadar301 pushed a commit to Hadar301/NemoClaw-OpenShift that referenced this pull request Jul 12, 2026
…ecorded route (NVIDIA#6465)

<!-- markdownlint-disable MD041 -->
## Summary

`nemoclaw <name> status` previously showed the live host-gateway
inference route as though it were the sandbox's own route. When an
out-of-band operation such as direct `openshell inference set` makes
that route differ from the sandbox's recorded provider/model, this PR
now emits an explicit warning and safe remediation guidance.

## Related Issue

Refs NVIDIA#6315. This complements NVIDIA#6338's fail-closed containment for
supported flows by surfacing residual out-of-band drift in status; it
follows the connect-time divergence behavior from NVIDIA#3726.

## Changes

- Compute `routeDrift` only when a complete, readable live route differs
from a complete recorded route.
- Show the live and recorded routes, explain that `connect` realigns to
the recorded route, and show the supported `inference set --sandbox`
path for adopting the live route.
- Share one control-character-sanitized warning formatter between status
and connect so the messages cannot drift.
- Cover divergent, aligned, unreadable, and missing-record cases plus
rendered status output.
- Document the warning in the existing one-route-per-gateway guidance.

## Original Author Credit

@Hokonoken authored the diagnosis, implementation, tests, live proof,
and documentation. The maintainer synchronization preserves those
commits, and the review-fix commit records Hokonoken as co-author.

## Type of Change

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

## Quality Gates

- [x] Tests added or updated for changed behavior
- [ ] Existing tests cover changed behavior — justification:
- [ ] Tests not applicable — justification:
- [x] Docs updated for user-facing behavior changes
- [ ] Docs not applicable — justification:
- [x] Sensitive paths changed (security, policy, credentials, preflight,
onboarding, inference, runner, sandbox, or messaging)
- [x] Sensitive-path review completed — display-only route comparison;
no route, registry, credential, or sandbox mutation is introduced;
untrusted route values use the shared sanitizer
- [ ] Non-success, skipped, or missing CI check accepted by maintainer —
check name, approval link, and follow-up issue:

## Verification

- [x] PR description includes DCO declarations and every commit is
GitHub Verified
- [x] Normal pre-commit, commit-msg, and pre-push hooks passed on the
current head
- [x] Focused config, connect-route, status-flow, and snapshot tests —
87/87 passed with one local worker
- [x] `npm run build:cli` — passed
- [x] Plugin build — passed
- [x] `npm run docs` — 0 errors and 2 pre-existing Fern warnings
- [x] Documentation-writer review confirmed the existing page update is
accurate and sufficient
- [x] Quality Gates section completed with required justifications
- [x] No secrets, API keys, or credentials committed
- [x] Doc pages follow the style guide
- [ ] New doc pages include SPDX header and frontmatter (new pages only)

---

Signed-off-by: Hokonoken <41166525+Hokonoken@users.noreply.github.com>
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>


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

* **New Features**
* Sandbox status now detects “route drift” between the live gateway
inference route and the sandbox’s recorded route, showing a warning with
commands to realign or adopt the live route.
* **Bug Fixes**
* If the live route can’t be read, route-drift warnings are suppressed
to avoid misleading output.
* **Tests**
* Added/expanded coverage for route-drift metadata,
warning/sanitization, and safe shell-escaping in emitted commands.
* **Documentation**
* Updated “switch inference providers” docs with the new route-drift
warning and resolution steps.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Hokonoken <41166525+Hokonoken@users.noreply.github.com>
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
Signed-off-by: Charan Jagwani <cjagwani@nvidia.com>
Co-authored-by: Apurv Kumaria <akumaria@nvidia.com>
Co-authored-by: Charan Jagwani <cjagwani@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: docs Documentation, examples, guides, or docs build area: inference Inference routing, serving, model selection, or outputs area: sandbox OpenShell sandbox lifecycle, runtime, config, or recovery bug needs: review PR is conflict-free and awaiting maintainer review v0.0.76 Release target

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants