Skip to content

feat(gpu): prefer native OpenShell with compatibility fallback#6333

Merged
ericksoa merged 52 commits into
mainfrom
feat/gpu-native-fallback-6110
Jul 12, 2026
Merged

feat(gpu): prefer native OpenShell with compatibility fallback#6333
ericksoa merged 52 commits into
mainfrom
feat/gpu-native-fallback-6110

Conversation

@ericksoa

@ericksoa ericksoa commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Summary

This non-breaking follow-up to PR 6142 preserves automatic GPU onboarding while preferring native OpenShell GPU injection on eligible Linux Docker hosts and retrying exactly once through the compatibility path only after trusted failure classification, complete retry preparation, and proven-safe cleanup. It preserves the existing CLI, environment controls, registry behavior, and OpenShell supervisor/workload boundary.

Related Issue

Related to #6110. This PR intentionally does not close the issue; reporter-class DGX Spark aarch64 or DGX Station GB300 validation remains required.

Follow-up to PR 6142 and its final reviewer feedback.

Changes

  • Add internal none, native-only, compatibility-only, and native-with-fallback GPU route plans while preserving existing environment controls.
  • Preserve NEMOCLAW_DOCKER_GPU_PATCH=0 as native-only, =1 as compatibility-only, and legacy nonzero compatibility routing.
  • Restrict automatic fallback to a complete OpenShell parser-rejection envelope on a verified clean baseline, canonical exact-container Docker CDI errors, or a structured driver proof independently corroborated by host configuration proving GPU attachment is absent.
  • Keep free-form build/list output and sandbox-controlled CUDA proof output from authorizing the broader compatibility envelope; those paths fail closed without trusted host corroboration.
  • Reuse only an immutable image ID captured from the exact causal container (or trusted prebuild) for retry while keeping mutable tag bookkeeping separate for registry and image GC.
  • Render and validate the full compatibility command and rerun local-provider network reachability before deleting native state.
  • Capture redacted diagnostics, delete the incomplete native attempt, prove both gateway and labeled-container absence, and retry compatibility at most once.
  • Preserve the OpenShell supervisor boundary: recreated Docker argv ends at the image and the workload remains only in OPENSHELL_SANDBOX_COMMAND.
  • Add native, real-partial-state fallback, and explicit compatibility-only live GPU scenarios, plus focused routing, trust-boundary, cleanup-refusal, command-envelope, registry, and one-retry tests.
  • Correct Jetson/Tegra compatibility-route documentation and failed-run native diagnostics artifact discovery.
  • Add no flags, prompts, environment variables, registry fields, or migration.

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: Re-review requested on exact head.
  • 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
  • Normal pre-commit, commit-msg, and pre-push hooks passed
  • Targeted behavior tests pass for the current change set — exact head 3e82fd26e1dfab5e7fc9a12081a69f40af5f4ac0: npm run build:cli, npm run typecheck, npm run source-shape:check, git diff --check origin/main...HEAD, and 405 focused GPU/onboarding/rebuild/E2E-support tests passed
  • Documentation validation passed — exact head 3e82fd26e1dfab5e7fc9a12081a69f40af5f4ac0: npm run docs:strict reported 0 errors and 2 existing Fern warnings
  • Applicable broad gate passed — exact-head PR CI, security scanning, review advisors, WSL/macOS, and CodeRabbit completed with 41 pass, 0 pending, and 0 failed
  • GPU runner matrix passed — exact-head E2E run 28964796094 passed the serialized native, real-partial-state fallback, and compatibility-only scenarios with Ready/CUDA, authenticated inference, correct supervisor topology, clean teardown, and trap-verified nvidia → runc → nvidia runner restoration
  • 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) — Fern reports two advisory warnings
  • Doc pages follow the style guide (doc changes only)
  • New doc pages include SPDX header and frontmatter (new pages only)

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

Summary by CodeRabbit

  • New Features
    • Native-first Docker GPU onboarding now uses explicit GPU routing plans and performs a single, safety-guarded compatibility retry; sandbox readiness supports consecutive “stable ready” polling.
    • Hermes GPU startup E2E is scenario-driven (native, fallback, compatibility-only) with scenario-scoped artifacts and a live OpenShell --gpu rejection wrapper.
  • Bug Fixes
    • Tightened Docker GPU rollback/restore fail-closed behavior (no status coercion) and made GPU local inference verification route-aware.
  • Documentation
    • Updated GPU passthrough onboarding + troubleshooting to clarify routing decisions and NEMOCLAW_DOCKER_GPU_PATCH semantics by platform.
  • Tests
    • Expanded route planning/rendering, diagnostics, DNS fallback, Jetson group handling, supervisor reconnect edge cases, readiness stability, and workflow boundary validation.

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@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 replaces boolean GPU-patch handling with route plans, adds bounded native-first compatibility fallback, threads route-aware behavior through sandbox creation and onboarding, expands Hermes GPU E2E coverage, and updates GPU passthrough documentation.

Changes

GPU Routing and Fallback Refactor

Layer / File(s) Summary
Route planning and rendering
src/lib/onboard/docker-gpu-route.ts, src/lib/onboard/docker-gpu-route-patch-adapter.ts, src/lib/onboard/docker-gpu-route*.test.ts
Adds route-plan types, route selection, route-to-patch adaptation, and route-aware sandbox create-argument rendering.
Docker GPU patch support
src/lib/onboard/docker-gpu-patch*.ts, src/lib/onboard/openshell-docker-sandbox-containers*.ts, src/lib/onboard/docker-gpu-jetson-groups*.ts, src/lib/onboard/docker-gpu-dns-fallback*.ts
Splits patch logic into dedicated modules for mode selection, cloning, diagnostics, runtime inspection, DNS fallback, Jetson groups, rollback, and supervisor reconnect.
Sandbox creation and policy materialization
src/lib/onboard/sandbox-create-*.ts, src/lib/onboard/sandbox-gpu-route-policy.ts, src/lib/onboard/initial-policy*.ts, src/lib/onboard/sandbox-prebuild*.ts, src/lib/build-context*.ts
Replaces boolean GPU-patch wiring with gpuRoutePlan, centralizes command rendering, improves temporary-policy cleanup, and tracks immutable image identity.
Native-first fallback orchestration
src/lib/onboard/sandbox-gpu-create-attempt.ts, src/lib/onboard/sandbox-gpu-create-flow.ts, src/lib/onboard/sandbox-gpu-fallback-constants.ts
Implements failure classification, fail-closed cleanup verification, one compatibility retry, readiness stability polling, and compatibility preparation.
Onboarding and verification wiring
src/lib/onboard.ts, src/lib/onboard/docker-gpu-local-inference.ts, src/lib/actions/sandbox/rebuild-target-runtime.ts, src/lib/state/gateway.ts
Threads selected routes through gateway probes, sandbox creation, rebuild preflight, local inference, and post-ready verification.
Hermes E2E scenarios
.github/workflows/e2e.yaml, test/e2e/live/*, test/e2e/support/*, tools/e2e/*
Runs native, fallback, and compatibility-only scenarios with isolated artifacts, Docker runtime restoration, fallback-wrapper assertions, teardown checks, and workflow boundary validation.
GPU passthrough documentation
docs/reference/commands.mdx, docs/reference/troubleshooting.mdx
Documents native-first injection, bounded compatibility fallback, environment-specific routing, and revised NEMOCLAW_DOCKER_GPU_PATCH semantics.

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

Sequence Diagram(s)

sequenceDiagram
  participant onboard.ts
  participant runSandboxGpuCreateFlow
  participant executeSandboxGpuCreatePlan
  participant cleanupNativeGpuAttemptForFallback
  participant dockerGpuLocalInference
  onboard.ts->>runSandboxGpuCreateFlow: create with gpuRoutePlan
  runSandboxGpuCreateFlow->>executeSandboxGpuCreatePlan: run native attempt
  executeSandboxGpuCreatePlan->>cleanupNativeGpuAttemptForFallback: verify native cleanup
  executeSandboxGpuCreatePlan->>executeSandboxGpuCreatePlan: run one compatibility retry
  runSandboxGpuCreateFlow->>dockerGpuLocalInference: verify selected route after Ready
  dockerGpuLocalInference-->>onboard.ts: verification result
Loading

Possibly related PRs

Suggested labels: refactor

Suggested reviewers: jyaunches

🚥 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 summarizes the main change: native OpenShell GPU startup with a compatibility fallback.
✨ 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 feat/gpu-native-fallback-6110

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

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

@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: Monolith growth: new 461-line module exceeds growth threshold; then add or justify PRA-T1.
Open items: 5 required · 6 warnings · 1 suggestion · 5 test follow-ups
Top item: Monolith growth: new 461-line module exceeds growth threshold

Action checklist

  • PRA-1 Fix: Monolith growth: new 461-line module exceeds growth threshold in src/lib/onboard/sandbox-gpu-create-flow.ts:1
  • PRA-2 Fix: Monolith growth: new 808-line test file exceeds growth threshold in src/lib/onboard/sandbox-gpu-create-flow.test.ts:1
  • PRA-3 Fix: Monolith growth: sandbox-gpu-preflight.test.ts grew by 118 lines in src/lib/onboard/sandbox-gpu-preflight.test.ts:1
  • PRA-4 Fix: Monolith growth: docker-gpu-sandbox-create.test.ts grew by 81 lines in src/lib/onboard/docker-gpu-sandbox-create.test.ts:1
  • PRA-8 Fix: shouldSkipGpuBridgeProbe caller passes incomplete options in src/lib/onboard.ts:1893
  • PRA-5 Resolve or justify: E2E fallback scenario mutates host Docker daemon.json in same step as test execution in .github/workflows/e2e.yaml:1800
  • PRA-6 Resolve or justify: Source-of-truth workaround: DNS fallback for systemd-resolved loopback stub in src/lib/onboard/docker-gpu-dns-fallback.ts:20
  • PRA-7 Resolve or justify: Source-of-truth workaround: legacy nonzero NEMOCLAW_DOCKER_GPU_PATCH preserved for automation compatibility in src/lib/onboard/docker-gpu-route.ts:40
  • PRA-9 Resolve or justify: Missing release note for GPU routing behavior change in docs/reference/commands.mdx:723
  • PRA-11 Resolve or justify: DNS fallback workaround missing regression test for misconfigured resolver in src/lib/onboard/docker-gpu-dns-fallback.ts:20
  • PRA-12 Resolve or justify: Legacy nonzero NEMOCLAW_DOCKER_GPU_PATCH missing regression test in src/lib/onboard/docker-gpu-route.ts:40
  • 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-10 In-scope improvement: Simplify E2E_DEFAULT_ENABLED single-use config to constant in .github/workflows/e2e.yaml:1588

Findings index

ID Severity Category Location Required action
PRA-1 Required architecture src/lib/onboard/sandbox-gpu-create-flow.ts:1 Extract the native attempt executor, fallback classification, and cleanup verification into separate focused modules before merge. Keep sandbox-gpu-create-flow.ts as a thin composition layer.
PRA-2 Required architecture src/lib/onboard/sandbox-gpu-create-flow.test.ts:1 Split into focused test files per failure stage and orchestration concern: native create failure classification, readiness failure classification, gpu-proof failure classification, fallback orchestration ordering, cleanup verification isolation.
PRA-3 Required architecture src/lib/onboard/sandbox-gpu-preflight.test.ts:1 Extract new GPU routing and fallback preflight tests into dedicated test modules (e.g., sandbox-gpu-route-preflight.test.ts, sandbox-gpu-fallback-preflight.test.ts).
PRA-4 Required architecture src/lib/onboard/docker-gpu-sandbox-create.test.ts:1 Extract new sandbox create plan and route rendering tests into dedicated test modules.
PRA-5 Resolve/justify scope .github/workflows/e2e.yaml:1800 Move the Docker daemon mutation and its trap-guarded cleanup into a separate dedicated step before the test step, or prove the runner is ephemeral and never reused. At minimum, add a pre-step that snapshots daemon.json and a post-step (always()) that restores it, independent of the test step's traps.
PRA-6 Resolve/justify scope src/lib/onboard/docker-gpu-dns-fallback.ts:20 Add a regression test that simulates a misconfigured host resolver (loopback-only /etc/resolv.conf with bad upstream) and verifies the fallback either fails closed or picks a safe default. Document the removalCondition: when OpenShell can create a provably GPU-unattached partial sandbox without consulting Docker's default runtime.
PRA-7 Resolve/justify scope src/lib/onboard/docker-gpu-route.ts:40 Add a test that verifies unrecognized nonzero values (e.g., '2', 'yes', 'on') still select compatibility-only but emit the deprecation warning. Add a deprecation timeline to the warning message (e.g., 'will be removed after v0.0.90').
PRA-8 Required correctness src/lib/onboard.ts:1893 Fix the caller in onboard.ts:1893 to pass { dockerDriverGateway: true, dockerDesktopWsl: false } explicitly, or add a comment documenting that missing keys default to false safely. Verify resolveDockerDesktopWsl handles undefined correctly.
PRA-9 Resolve/justify docs docs/reference/commands.mdx:723 Add a release note entry documenting the GPU routing behavior change: native OpenShell GPU injection is now default on ordinary native Linux; compatibility patch used only on Docker Desktop WSL and Jetson/Tegra; NEMOCLAW_DOCKER_GPU_PATCH=1 remains as escape hatch for legacy behavior.
PRA-10 Improvement architecture .github/workflows/e2e.yaml:1588 Replace E2E_DEFAULT_ENABLED: "0" with a constant or remove if truly unused. This is a safe simplification within the current PR scope.
PRA-11 Resolve/justify acceptance src/lib/onboard/docker-gpu-dns-fallback.ts:20 Add a regression test that simulates a misconfigured host resolver (loopback-only /etc/resolv.conf with bad upstream) and verifies the fallback either fails closed or selects a documented safe default. Document the removalCondition: when OpenShell can create a provably GPU-unattached partial sandbox without consulting Docker's default runtime.
PRA-12 Resolve/justify acceptance src/lib/onboard/docker-gpu-route.ts:40 Add a test that verifies unrecognized nonzero values (e.g., '2', 'yes', 'on') still select compatibility-only but emit the deprecation warning. Add a deprecation timeline to the warning message (e.g., 'will be removed after v0.0.90').

🚨 Required before merge

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

PRA-1 Required — Monolith growth: new 461-line module exceeds growth threshold

  • Location: src/lib/onboard/sandbox-gpu-create-flow.ts:1
  • Category: architecture
  • Problem: New module sandbox-gpu-create-flow.ts adds 461 lines orchestrating GPU create flow, fallback classification, cleanup verification, and compatibility retry without extraction into focused modules. The module handles security-critical transitions between native GPU create, fallback authorization, cleanup proof, and compatibility retry.
  • Impact: Large concentrated module increases review burden, test complexity, and risk of trust-boundary logic creep. Security-critical GPU routing and fallback logic is bundled in a single file.
  • Required action: Extract the native attempt executor, fallback classification, and cleanup verification into separate focused modules before merge. Keep sandbox-gpu-create-flow.ts as a thin composition layer.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check riskPlan.monolithDeltas for sandbox-gpu-create-flow.ts (delta 461, severity blocker). Count lines: wc -l src/lib/onboard/sandbox-gpu-create-flow.ts
  • Missing regression test: Architecture guardrail test that fails when any single onboard module exceeds 300 lines without explicit justification in the PR.
  • Done when: The required change is committed and verification passes: Check riskPlan.monolithDeltas for sandbox-gpu-create-flow.ts (delta 461, severity blocker). Count lines: wc -l src/lib/onboard/sandbox-gpu-create-flow.ts.
  • Evidence: riskPlan.monolithDeltas entry: baseLines 0, headLines 461, delta 461, severity blocker File created in this PR with 461 lines orchestrating GPU create flow, fallback, cleanup, and retry

PRA-2 Required — Monolith growth: new 808-line test file exceeds growth threshold

  • Location: src/lib/onboard/sandbox-gpu-create-flow.test.ts:1
  • Category: architecture
  • Problem: New test module sandbox-gpu-create-flow.test.ts adds 808 lines covering multiple failure-stage scenarios (create, readiness, gpu-proof) with diagnostics capture, cleanup verification, and compatibility preparation.
  • Impact: Large test file couples multiple failure-stage scenarios making it hard to maintain, verify coverage, and isolate regressions. Test scenarios for security-critical fallback paths are interleaved.
  • Required action: Split into focused test files per failure stage and orchestration concern: native create failure classification, readiness failure classification, gpu-proof failure classification, fallback orchestration ordering, cleanup verification isolation.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check riskPlan.monolithDeltas for sandbox-gpu-create-flow.test.ts (delta 808, severity blocker). Count lines: wc -l src/lib/onboard/sandbox-gpu-create-flow.test.ts
  • Missing regression test: Architecture guardrail test that fails when any single test module exceeds 500 lines.
  • Done when: The required change is committed and verification passes: Check riskPlan.monolithDeltas for sandbox-gpu-create-flow.test.ts (delta 808, severity blocker). Count lines: wc -l src/lib/onboard/sandbox-gpu-create-flow.test.ts.
  • Evidence: riskPlan.monolithDeltas entry: baseLines 0, headLines 808, delta 808, severity blocker File created in this PR with 808 lines covering multiple fallback stages

PRA-3 Required — Monolith growth: sandbox-gpu-preflight.test.ts grew by 118 lines

  • Location: src/lib/onboard/sandbox-gpu-preflight.test.ts:1
  • Category: architecture
  • Problem: Existing test file sandbox-gpu-preflight.test.ts grew from 367 to 485 lines (+118) without extraction of new GPU routing and fallback preflight tests into dedicated modules.
  • Impact: Test file growth without extraction suggests accumulating test cases in a single module rather than splitting by concern, reducing maintainability and coverage clarity for GPU routing preflight logic.
  • Required action: Extract new GPU routing and fallback preflight tests into dedicated test modules (e.g., sandbox-gpu-route-preflight.test.ts, sandbox-gpu-fallback-preflight.test.ts).
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check riskPlan.monolithDeltas for sandbox-gpu-preflight.test.ts (delta 118, severity blocker). Compare baseLines 367 vs headLines 485.
  • Missing regression test: Architecture guardrail test that fails when an existing test module grows by more than 50 lines without extraction.
  • Done when: The required change is committed and verification passes: Check riskPlan.monolithDeltas for sandbox-gpu-preflight.test.ts (delta 118, severity blocker). Compare baseLines 367 vs headLines 485.
  • Evidence: riskPlan.monolithDeltas entry: baseLines 367, headLines 485, delta 118, severity blocker

PRA-4 Required — Monolith growth: docker-gpu-sandbox-create.test.ts grew by 81 lines

  • Location: src/lib/onboard/docker-gpu-sandbox-create.test.ts:1
  • Category: architecture
  • Problem: Existing test file docker-gpu-sandbox-create.test.ts grew from 342 to 423 lines (+81) without extraction of new sandbox create plan and route rendering tests into dedicated modules.
  • Impact: Test file growth without extraction suggests accumulating test cases in a single module rather than splitting by concern, reducing maintainability for sandbox create plan and GPU route rendering logic.
  • Required action: Extract new sandbox create plan and route rendering tests into dedicated test modules.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check riskPlan.monolithDeltas for docker-gpu-sandbox-create.test.ts (delta 81, severity blocker). Compare baseLines 342 vs headLines 423.
  • Missing regression test: Architecture guardrail test that fails when an existing test module grows by more than 50 lines without extraction.
  • Done when: The required change is committed and verification passes: Check riskPlan.monolithDeltas for docker-gpu-sandbox-create.test.ts (delta 81, severity blocker). Compare baseLines 342 vs headLines 423.
  • Evidence: riskPlan.monolithDeltas entry: baseLines 342, headLines 423, delta 81, severity blocker

PRA-8 Required — shouldSkipGpuBridgeProbe caller passes incomplete options

  • Location: src/lib/onboard.ts:1893
  • Category: correctness
  • Problem: shouldSkipGpuBridgeProbe in onboard.ts:1893 is called with only 2 arguments (gpuPassthrough, _gpu?.platform) but the function signature expects an optional third options object with dockerDriverGateway and dockerDesktopWsl fields. When called from Linux Docker-driver gateway context, dockerDriverGateway: true is not passed, so resolveDockerDesktopWsl defaults to isDockerDesktopWslRuntime() which may be incorrect, causing false-positive/negative GPU bridge probe skipping.
  • Impact: Incorrect host-network detection could cause the GPU bridge probe to be skipped when it should run (or vice versa), leading to false-positive inference reachability results on Linux Docker-driver gateways. This is a security-critical inference routing path.
  • Required action: Fix the caller in onboard.ts:1893 to pass { dockerDriverGateway: true, dockerDesktopWsl: false } explicitly, or add a comment documenting that missing keys default to false safely. Verify resolveDockerDesktopWsl handles undefined correctly.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Read src/lib/onboard.ts line 1893 and src/lib/onboard/docker-gpu-local-inference.ts lines 40-55 to verify the default behavior.
  • Missing regression test: Unit test for shouldSkipGpuBridgeProbe with dockerDriverGateway: true and dockerDesktopWsl: false to confirm correct host-network detection on Linux Docker-driver gateway.
  • Done when: The required change is committed and verification passes: Read src/lib/onboard.ts line 1893 and src/lib/onboard/docker-gpu-local-inference.ts lines 40-55 to verify the default behavior.
  • Evidence: onboard.ts:1893 calls shouldSkipGpuBridgeProbe(gpuPassthrough, _gpu?.platform); only 2 args docker-gpu-local-inference.ts:40-55 shows resolveDockerDesktopWsl defaults to isDockerDesktopWslRuntime() when options.dockerDriverGateway undefined Prior review PRA-11 from fix(gpu): prefer native OpenShell injection #6142 identified this; current PR carries the same call pattern
Review findings by urgency: 5 required fixes, 6 items to resolve/justify, 1 in-scope improvement

⚠️ 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-5 Resolve/justify — E2E fallback scenario mutates host Docker daemon.json in same step as test execution

  • Location: .github/workflows/e2e.yaml:1800
  • Category: scope
  • Problem: The hermes-gpu-startup job's fallback matrix scenario mutates /etc/docker/daemon.json (changes default-runtime to runc) within the test step, with trap-guarded restoration. If Vitest crashes hard (SIGKILL, OOM, runner abort), the trap may not execute, leaving the runner-global Docker default runtime changed and contaminating later OpenShell jobs on this self-hosted runner.
  • Impact: Host-state mutation in a shared self-hosted GPU runner can leak into subsequent jobs, breaking test isolation and potentially affecting production-adjacent validation. The trap runs in the same shell process as the test.
  • Recommended action: Move the Docker daemon mutation and its trap-guarded cleanup into a separate dedicated step before the test step, or prove the runner is ephemeral and never reused. At minimum, add a pre-step that snapshots daemon.json and a post-step (always()) that restores it, independent of the test step's traps.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect .github/workflows/e2e.yaml hermes-gpu-startup job fallback scenario: the daemon.json mutation, trap restore_docker_default_runtime, and vitest run are all in the same 'Run Hermes GPU startup live Vitest test' step.
  • Missing regression test: Workflow validation test that verifies daemon.json is restored to original state after the fallback scenario step, even when the test step is killed mid-execution.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect .github/workflows/e2e.yaml hermes-gpu-startup job fallback scenario: the daemon.json mutation, trap restore_docker_default_runtime, and vitest run are all in the same 'Run Hermes GPU startup live Vitest test' step.
  • Evidence: Diff shows fallback scenario: sudo install -m 0644 daemon.json.runc /etc/docker/daemon.json, trap restore_docker_default_runtime EXIT, then npx vitest run in same step Prior review PRA-5 identified this; current diff expands it with matrix strategy but keeps mutation in test step

PRA-6 Resolve/justify — Source-of-truth workaround: DNS fallback for systemd-resolved loopback stub

  • Location: src/lib/onboard/docker-gpu-dns-fallback.ts:20
  • Category: scope
  • Problem: New module docker-gpu-dns-fallback.ts implements a fallback that detects a loopback-only /etc/resolv.conf with bad upstream and substitutes a DNS fallback. This handles an invalid host state (misconfigured systemd-resolved) rather than fixing the source. The workaround has a documented removalCondition but no regression test proving the source cannot regress.
  • Impact: Workaround masks host misconfiguration instead of failing closed or fixing the root cause. If the host DNS configuration changes, the fallback may silently pick an unsafe default or fail closed without detection.
  • Recommended action: Add a regression test that simulates a misconfigured host resolver (loopback-only /etc/resolv.conf with bad upstream) and verifies the fallback either fails closed or picks a safe default. Document the removalCondition: when OpenShell can create a provably GPU-unattached partial sandbox without consulting Docker's default runtime.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read src/lib/onboard/docker-gpu-dns-fallback.ts around line 20 for the loopback detection and fallback logic. Check for a test in docker-gpu-dns-fallback.test.ts that simulates the misconfigured resolver.
  • Missing regression test: Test that creates a loopback-only /etc/resolv.conf with bad upstream, runs the DNS fallback logic, and asserts it either fails closed or selects a documented safe default.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read src/lib/onboard/docker-gpu-dns-fallback.ts around line 20 for the loopback detection and fallback logic. Check for a test in docker-gpu-dns-fallback.test.ts that simulates the misconfigured resolver.
  • Evidence: New file src/lib/onboard/docker-gpu-dns-fallback.ts created in this PR Prior review PRA-6 identified this workaround; removalCondition documented but no regression test for the invalid host state

PRA-7 Resolve/justify — Source-of-truth workaround: legacy nonzero NEMOCLAW_DOCKER_GPU_PATCH preserved for automation compatibility

  • Location: src/lib/onboard/docker-gpu-route.ts:40
  • Category: scope
  • Problem: docker-gpu-route.ts accepts legacy nonzero values (e.g., '2', 'yes', 'on') for NEMOCLAW_DOCKER_GPU_PATCH and treats them as compatibility-only, but only emits a deprecation warning. This preserves a compatibility shim for automation that may pass arbitrary truthy values. No test verifies unrecognized nonzero values still select compatibility-only with the deprecation warning.
  • Impact: Legacy compatibility shim accepts arbitrary nonzero strings, creating a broad compatibility surface that may mask operator errors. The deprecation timeline is not enforced in code.
  • Recommended action: Add a test that verifies unrecognized nonzero values (e.g., '2', 'yes', 'on') still select compatibility-only but emit the deprecation warning. Add a deprecation timeline to the warning message (e.g., 'will be removed after v0.0.90').
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read src/lib/onboard/docker-gpu-route.ts around line 40 for the legacy nonzero handling. Check docker-gpu-route.test.ts for a test covering unrecognized nonzero values.
  • Missing regression test: Test that passes NEMOCLAW_DOCKER_GPU_PATCH='2' (or 'yes', 'on') and asserts: (1) route selected is compatibility-only, (2) deprecation warning is emitted with a timeline.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read src/lib/onboard/docker-gpu-route.ts around line 40 for the legacy nonzero handling. Check docker-gpu-route.test.ts for a test covering unrecognized nonzero values.
  • Evidence: New file src/lib/onboard/docker-gpu-route.ts created in this PR with legacy nonzero handling Prior review PRA-7 identified this; commands.mdx now documents 'legacy nonzero values remain temporarily accepted for compatibility' but no test or timeline enforcement

PRA-9 Resolve/justify — Missing release note for GPU routing behavior change

  • Location: docs/reference/commands.mdx:723
  • Category: docs
  • Problem: The PR changes default GPU routing on ordinary native Linux from compatibility patch (Docker container swap) to native OpenShell GPU injection. Operators upgrading from older versions will experience changed behavior. The docs reference the new NEMOCLAW_DOCKER_GPU_PATCH=fallback and =1 controls but no release note or migration guide entry documents this behavior change.
  • Impact: Operators may be surprised by changed GPU routing behavior; the escape hatch (NEMOCLAW_DOCKER_GPU_PATCH=1) must be clearly documented in release notes for upgrading users.
  • Recommended action: Add a release note entry documenting the GPU routing behavior change: native OpenShell GPU injection is now default on ordinary native Linux; compatibility patch used only on Docker Desktop WSL and Jetson/Tegra; NEMOCLAW_DOCKER_GPU_PATCH=1 remains as escape hatch for legacy behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Check docs/release-notes/ or CHANGELOG for an entry describing the GPU routing default change. Verify commands.mdx documents the new defaults and escape hatches.
  • Missing regression test: Release note entry documenting the GPU routing behavior change for operators.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Check docs/release-notes/ or CHANGELOG for an entry describing the GPU routing default change. Verify commands.mdx documents the new defaults and escape hatches.
  • Evidence: commands.mdx:723 documents NEMOCLAW_DOCKER_GPU_PATCH=fallback as explicit opt-in for bounded retry commands.mdx:747 documents unset/auto/0 as native-only on ordinary native Linux Prior review PRA-17 from fix(gpu): prefer native OpenShell injection #6142 flagged this; current PR docs updated but no release note entry

PRA-11 Resolve/justify — DNS fallback workaround missing regression test for misconfigured resolver

  • Location: src/lib/onboard/docker-gpu-dns-fallback.ts:20
  • Category: acceptance
  • Problem: docker-gpu-dns-fallback.ts implements a fallback for loopback-only /etc/resolv.conf with bad upstream (misconfigured systemd-resolved). This handles an invalid host state rather than fixing the source. The workaround has a documented removalCondition but no regression test simulates the misconfigured resolver and verifies the fallback either fails closed or picks a safe default.
  • Impact: Workaround masks host misconfiguration instead of failing closed or fixing the root cause. If the host DNS configuration changes, the fallback may silently pick an unsafe default or fail closed without detection. No automated coverage proves the source cannot regress.
  • Recommended action: Add a regression test that simulates a misconfigured host resolver (loopback-only /etc/resolv.conf with bad upstream) and verifies the fallback either fails closed or selects a documented safe default. Document the removalCondition: when OpenShell can create a provably GPU-unattached partial sandbox without consulting Docker's default runtime.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read src/lib/onboard/docker-gpu-dns-fallback.ts around line 20 for the loopback detection and fallback logic. Check docker-gpu-dns-fallback.test.ts for a test simulating the misconfigured resolver.
  • Missing regression test: Test that creates a loopback-only /etc/resolv.conf with bad upstream, runs the DNS fallback logic, and asserts it either fails closed or selects a documented safe default.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read src/lib/onboard/docker-gpu-dns-fallback.ts around line 20 for the loopback detection and fallback logic. Check docker-gpu-dns-fallback.test.ts for a test simulating the misconfigured resolver.
  • Evidence: New file src/lib/onboard/docker-gpu-dns-fallback.ts created in this PR with loopback detection at line 20 Prior review PRA-6 / F-006 identified this workaround; removalCondition documented but no regression test for the invalid host state

PRA-12 Resolve/justify — Legacy nonzero NEMOCLAW_DOCKER_GPU_PATCH missing regression test

  • Location: src/lib/onboard/docker-gpu-route.ts:40
  • Category: acceptance
  • Problem: docker-gpu-route.ts accepts legacy nonzero values (e.g., '2', 'yes', 'on') for NEMOCLAW_DOCKER_GPU_PATCH and treats them as compatibility-only with a deprecation warning. This preserves a compatibility shim for automation that may pass arbitrary truthy values. No test verifies unrecognized nonzero values still select compatibility-only with the deprecation warning and timeline.
  • Impact: Legacy compatibility shim accepts arbitrary nonzero strings, creating a broad compatibility surface that may mask operator errors. The deprecation timeline is not enforced in code and no test guards against regression.
  • Recommended action: Add a test that verifies unrecognized nonzero values (e.g., '2', 'yes', 'on') still select compatibility-only but emit the deprecation warning. Add a deprecation timeline to the warning message (e.g., 'will be removed after v0.0.90').
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read src/lib/onboard/docker-gpu-route.ts around line 40 for the legacy nonzero handling. Check docker-gpu-route.test.ts for a test covering unrecognized nonzero values.
  • Missing regression test: Test that passes NEMOCLAW_DOCKER_GPU_PATCH='2' (or 'yes', 'on') and asserts: (1) route selected is compatibility-only, (2) deprecation warning is emitted with a timeline.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read src/lib/onboard/docker-gpu-route.ts around line 40 for the legacy nonzero handling. Check docker-gpu-route.test.ts for a test covering unrecognized nonzero values.
  • Evidence: New file src/lib/onboard/docker-gpu-route.ts created in this PR with legacy nonzero handling at line 40 Prior review PRA-7 / F-007 identified this; commands.mdx documents 'legacy nonzero values remain temporarily accepted for compatibility' but no test or timeline enforcement

💡 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-10 Improvement — Simplify E2E_DEFAULT_ENABLED single-use config to constant

  • Location: .github/workflows/e2e.yaml:1588
  • Category: architecture
  • Problem: E2E_DEFAULT_ENABLED="0" is set only in the hermes-gpu-startup job and never referenced elsewhere in the workflow or tools. This single-use configuration variable adds cognitive overhead without benefit.
  • Impact: Minor: reduces workflow complexity by removing unused configuration variable.
  • Suggested action: Replace E2E_DEFAULT_ENABLED: "0" with a constant or remove if truly unused. This is a safe simplification within the current PR scope.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: grep -r 'E2E_DEFAULT_ENABLED' .github/workflows/ tools/e2e/ confirms single use in hermes-gpu-startup job.
  • Missing regression test: None needed; minor cleanup.
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: e2e.yaml:1588 sets E2E_DEFAULT_ENABLED: "0" only in hermes-gpu-startup job simplificationSignals identifies single_use_config at e2e.yaml:1588 Prior review PRA-22/PRA-23 from fix(gpu): prefer native OpenShell injection #6142 identified this simplification opportunity
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 the `cloud-onboard` E2E job for Installer and platform changes must work on a clean supported host with the pinned runtime dependencies. Matched files: `.github/workflows/e2e.yaml`.. Deterministic regression risks require live validation: lifecycle-state, upgrade-rebuild, inference-policy, platform-install, credentials-security.
  • PRA-T2 Runtime validation — Run the `credential-sanitization` E2E job for Credential and security-boundary changes must preserve secrecy, sanitization, and fail-closed policy behavior. Matched files: `src/lib/onboard/docker-gpu-diagnostic-redaction.ts`.. Deterministic regression risks require live validation: lifecycle-state, upgrade-rebuild, inference-policy, platform-install, credentials-security.
  • PRA-T3 Runtime validation — Run the `security-posture` E2E job for Credential and security-boundary changes must preserve secrecy, sanitization, and fail-closed policy behavior. Matched files: `src/lib/onboard/docker-gpu-diagnostic-redaction.ts`.. Deterministic regression risks require live validation: lifecycle-state, upgrade-rebuild, inference-policy, platform-install, credentials-security.
  • PRA-T4 Runtime validation — Run the `inference-routing` E2E job for Inference selection, reachability, and network policy must agree at the real host-to-sandbox boundary. Matched files: `src/lib/onboard/docker-gpu-local-inference.ts`.. Deterministic regression risks require live validation: lifecycle-state, upgrade-rebuild, inference-policy, platform-install, credentials-security.
  • PRA-T5 Runtime validation — Run the `network-policy` E2E job for Inference selection, reachability, and network policy must agree at the real host-to-sandbox boundary. Matched files: `src/lib/onboard/docker-gpu-local-inference.ts`.. Deterministic regression risks require live validation: lifecycle-state, upgrade-rebuild, inference-policy, platform-install, credentials-security.

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

E2E Advisor Recommendation

Required E2E: cloud-onboard, credential-sanitization, security-posture, inference-routing, network-policy, onboard-repair, onboard-resume, state-backup-restore, upgrade-stale-sandbox
Optional E2E: hermes-gpu-startup

Dispatch hint: cloud-onboard,credential-sanitization,security-posture,inference-routing,network-policy,onboard-repair,onboard-resume,state-backup-restore,upgrade-stale-sandbox

Workflow run

Full advisor summary

E2E Recommendation Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E

  • cloud-onboard: Required floor: workflow/platform changes must still install and onboard a usable hosted-inference sandbox on a clean host.
  • credential-sanitization: Required floor: redacted GPU diagnostics must not expose credentials in live onboarding evidence or artifacts.
  • security-posture: Required floor: compatibility-route and privileged workflow changes must preserve sandbox security posture for both supported agents.
  • inference-routing: Required floor: GPU local-inference route selection and preflight must retain real gateway-to-provider reachability.
  • network-policy: Required floor: route-specific GPU policy materialization must preserve intended access and denied egress boundaries.
  • onboard-repair: Required floor: failed GPU create, cleanup, and recovery paths must converge without stale sandbox or gateway resources.
  • onboard-resume: Required floor: onboarding state and incomplete-create paths must remain resumable after lifecycle changes.
  • state-backup-restore: Required floor: rebuild-related runtime changes must preserve recoverable user state.
  • upgrade-stale-sandbox: Required floor: stale sandbox upgrade and rebuild must replace runtime state without destructive cleanup.

Optional E2E

  • hermes-gpu-startup: Directly exercises the changed native, bounded-fallback, and compatibility-only Hermes GPU startup scenarios, including the trusted Docker runtime fixture. The workflow intentionally limits this privileged persistent-runner job to trusted main workflow dispatch, so run it post-merge rather than as a PR validation job.

New E2E recommendations

  • platform-install (high): The only direct GPU startup E2E lane is deliberately unavailable for PR commits because it mutates Docker daemon state on a persistent privileged GPU runner. Required PR jobs do not execute native GPU attachment, fallback authorization, or daemon restoration against the submitted commit.
    • Suggested test: Create an isolated, ephemeral GPU validation lane that can execute the native, fallback, and compatibility-only Hermes GPU startup scenarios for a PR commit without exposing a persistent runner or allowing PR-controlled privileged fixture code.

Dispatch hint

  • Workflow: e2e.yaml
  • jobs input: cloud-onboard,credential-sanitization,security-posture,inference-routing,network-policy,onboard-repair,onboard-resume,state-backup-restore,upgrade-stale-sandbox

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

E2E Target Recommendation

Required E2E targets: cloud-onboard, credential-sanitization, security-posture, inference-routing, network-policy, onboard-repair, onboard-resume, state-backup-restore, upgrade-stale-sandbox, hermes-gpu-startup
Optional E2E targets: gpu-double-onboard, jetson-nvmap-gpu

Dispatch required E2E targets:

  • gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=cloud-onboard
  • gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=credential-sanitization
  • gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=security-posture
  • gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=inference-routing
  • gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=network-policy
  • gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=onboard-repair
  • gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=onboard-resume
  • gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=state-backup-restore
  • gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=upgrade-stale-sandbox
  • gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=hermes-gpu-startup

Workflow run

Full E2E target advisor summary

E2E Target Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E targets

  • cloud-onboard: Installer and platform changes must work on a clean supported host with the pinned runtime dependencies.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=cloud-onboard
  • credential-sanitization: Credential and security-boundary changes must preserve secrecy, sanitization, and fail-closed policy behavior.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=credential-sanitization
  • security-posture: Credential and security-boundary changes must preserve secrecy, sanitization, and fail-closed policy behavior.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=security-posture
  • inference-routing: Inference selection, reachability, and network policy must agree at the real host-to-sandbox boundary.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=inference-routing
  • network-policy: Inference selection, reachability, and network policy must agree at the real host-to-sandbox boundary.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=network-policy
  • onboard-repair: Onboarding and sandbox state must converge across persisted metadata, reported status, and the live runtime.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=onboard-repair
  • onboard-resume: Onboarding and sandbox state must converge across persisted metadata, reported status, and the live runtime.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=onboard-resume
  • state-backup-restore: Upgrade, rebuild, snapshot, and restore operations must preserve user state while replacing stale runtime state.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=state-backup-restore
  • upgrade-stale-sandbox: Upgrade, rebuild, snapshot, and restore operations must preserve user state while replacing stale runtime state.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=upgrade-stale-sandbox
  • hermes-gpu-startup: Focused free-standing E2E job wired for changed live test test/e2e/live/hermes-gpu-startup.test.ts.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=hermes-gpu-startup

Optional E2E targets

  • gpu-double-onboard: Adjacent special-runner GPU coverage for broad Docker GPU route, fallback, cleanup, and repeated onboarding changes.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=gpu-double-onboard
  • jetson-nvmap-gpu: Adjacent special-runner coverage for changed Jetson/Tegra GPU group propagation and compatibility-route behavior.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=jetson-nvmap-gpu

Relevant changed files

  • .github/workflows/e2e.yaml
  • src/lib/actions/sandbox/rebuild-target-runtime.ts
  • src/lib/build-context.ts
  • src/lib/onboard.ts
  • src/lib/onboard/docker-gpu-diagnostic-redaction.ts
  • src/lib/onboard/docker-gpu-dns-fallback.ts
  • src/lib/onboard/docker-gpu-jetson-groups.ts
  • src/lib/onboard/docker-gpu-local-inference.ts
  • src/lib/onboard/docker-gpu-patch-clone.ts
  • src/lib/onboard/docker-gpu-patch-constants.ts
  • src/lib/onboard/docker-gpu-patch-diagnostics.ts
  • src/lib/onboard/docker-gpu-patch-finalize.ts
  • src/lib/onboard/docker-gpu-patch-mode.ts
  • src/lib/onboard/docker-gpu-patch-recreate.ts
  • src/lib/onboard/docker-gpu-patch-rollback.ts
  • src/lib/onboard/docker-gpu-patch-types.ts
  • src/lib/onboard/docker-gpu-patch.ts
  • src/lib/onboard/docker-gpu-pre-rollback-diagnostics.ts
  • src/lib/onboard/docker-gpu-route-patch-adapter.ts
  • src/lib/onboard/docker-gpu-route.ts
  • src/lib/onboard/docker-gpu-sandbox-create-plan.ts
  • src/lib/onboard/docker-gpu-sandbox-create.ts
  • src/lib/onboard/docker-gpu-supervisor-reconnect.ts
  • src/lib/onboard/initial-policy.ts
  • src/lib/onboard/openshell-docker-sandbox-containers.ts
  • src/lib/onboard/sandbox-create-intent-types.ts
  • src/lib/onboard/sandbox-create-intent.ts
  • src/lib/onboard/sandbox-create-launch.ts
  • src/lib/onboard/sandbox-create-plan-materialization.ts
  • src/lib/onboard/sandbox-create-plan.ts
  • src/lib/onboard/sandbox-create-step.ts
  • src/lib/onboard/sandbox-dockerfile-patch-flow.ts
  • src/lib/onboard/sandbox-gpu-create-attempt.ts
  • src/lib/onboard/sandbox-gpu-create-flow.ts
  • src/lib/onboard/sandbox-gpu-fallback-constants.ts
  • src/lib/onboard/sandbox-gpu-preflight.ts
  • src/lib/onboard/sandbox-gpu-route-policy.ts
  • src/lib/onboard/sandbox-prebuild.ts
  • src/lib/onboard/sandbox-readiness-tracing.ts
  • src/lib/state/gateway.ts
  • test/e2e/live/hermes-gpu-startup-fallback.ts
  • test/e2e/live/hermes-gpu-startup-integrity.ts
  • test/e2e/live/hermes-gpu-startup-proof.ts
  • test/e2e/live/hermes-gpu-startup.test.ts
  • test/e2e/mock-parity.json
  • test/e2e/support/hermes-gpu-startup-fallback.test.ts
  • test/e2e/support/hermes-gpu-startup-integrity.test.ts
  • test/e2e/support/hermes-workflow-boundary.test.ts
  • test/e2e/support/upload-e2e-artifacts-workflow-boundary.test.ts
  • tools/e2e/hermes-gpu-startup-workflow-boundary.mts
  • tools/e2e/upload-e2e-artifacts-workflow-boundary.mts

@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 remains at 96%, unchanged from the branch.

TypeScript / code-coverage/cli

The overall coverage in the branch remains at 79%, unchanged from the branch.

Show a code coverage summary of the most impacted files.
File 6eb7ca7 0abe4c9 +/-
src/lib/state/sandbox.ts 88% 76% -12%
src/lib/sandbox/config.ts 59% 73% +14%
src/lib/onboard...x-containers.ts 0% 84% +84%
src/lib/onboard...u-patch-mode.ts 0% 90% +90%
src/lib/onboard...-patch-clone.ts 0% 92% +92%
src/lib/onboard...tch-recreate.ts 0% 92% +92%
src/lib/onboard...-run-attempt.ts 0% 95% +95%
src/lib/onboard...-diagnostics.ts 0% 96% +96%
src/lib/onboard...er-gpu-route.ts 0% 96% +96%
src/lib/onboard...eate-attempt.ts 0% 100% +100%

Updated July 12, 2026 18:51 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

PR Review Advisor — No blocking findings

Merge posture: No blocking advisor findings
Primary next action: No advisor follow-up required beyond maintainer review.
Findings: 0 required · 0 warnings · 0 optional suggestions
Since last review: 0 prior items resolved · 0 still apply · 0 new items found

Workflow run details

This is an automated review. Required findings need action before merge. Warnings and optional suggestions do not require a response or follow-up. A human maintainer makes the final merge decision.

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

E2E Target Results — ❌ Some jobs failed

Run: 28810685415
Workflow ref: feat/gpu-native-fallback-6110
Requested targets: (default — all supported)
Requested jobs: hermes-gpu-startup
Summary: 0 passed, 1 failed, 0 cancelled, 0 skipped

Job Result
hermes-gpu-startup ❌ failure

Failed jobs: hermes-gpu-startup. Check run artifacts for logs.

@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 (4)
src/lib/onboard/sandbox-gpu-create-attempt.test.ts (1)

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

Split the fallback gating cases.

This test claims both route-plan and failure-classification gates, but disables both at once, so it cannot catch a regression in either gate independently.

Suggested test split
-  it("does not fallback when the route plan or failure classification forbids it", async () => {
+  it("does not fallback when the route plan forbids it", async () => {
+    const routeIneligibleFailure = nativeFailure("create");
+    const routeRunAttempt = vi.fn(async () => routeIneligibleFailure);
+
+    await expect(
+      executeSandboxGpuCreatePlan("native-only", {
+        runAttempt: routeRunAttempt,
+        cleanupNativeFailure: async () => SAFE_CLEANUP,
+      }),
+    ).resolves.toBe(routeIneligibleFailure);
+    expect(routeRunAttempt).toHaveBeenCalledTimes(1);
+  });
+
+  it("does not fallback when the failure classification forbids it", async () => {
     const ineligibleFailure = {
       ...nativeFailure("create"),
       fallbackEligible: false,
     };
     const runAttempt = vi.fn(async () => ineligibleFailure);
     const cleanupNativeFailure = vi.fn(async () => SAFE_CLEANUP);
 
     await expect(
-      executeSandboxGpuCreatePlan("native-only", { runAttempt, cleanupNativeFailure }),
+      executeSandboxGpuCreatePlan("native-with-fallback", { runAttempt, cleanupNativeFailure }),
     ).resolves.toBe(ineligibleFailure);
     expect(runAttempt).toHaveBeenCalledTimes(1);
     expect(cleanupNativeFailure).not.toHaveBeenCalled();
   });

As per path instructions, tests should prove observable behavior and avoid cases that pass without exercising their 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/onboard/sandbox-gpu-create-attempt.test.ts` around lines 194 - 207,
Split the combined fallback-gating assertion in executeSandboxGpuCreatePlan’s
test so each gate is verified independently: one case should cover a route plan
that forbids fallback while the failure remains eligible, and a separate case
should cover an ineligible failure (fallbackEligible false) under a route plan
that would otherwise allow fallback. Keep the existing symbols like
executeSandboxGpuCreatePlan, runAttempt, and cleanupNativeFailure, but
restructure the test names and expectations so each test proves only one gating
condition.

Source: Path instructions

src/lib/onboard/docker-gpu-patch-finalize.test.ts (1)

117-132: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Rename-stage case doesn't prove the rollback stopped early.

For the "rename" case, the test only checks the final outcome, not that dockerStart was skipped after the rename failure. The sibling test in docker-gpu-patch-rollback.test.ts (lines 168-195) does assert the next step (dockerRunDetached) is never called after a failed rename — the same rigor here would make this test prove "fails closed at rename" rather than just "final result happens to be false."

As per path instructions for test files: "Flag copied production algorithms, broad mocks that bypass the behavior under test, and conditionals that make a test pass without exercising its claim."

✅ Suggested strengthening for the rename case
   it.each([
-    ["rename", { dockerRename: vi.fn(() => ({ status: null })) }],
-    ["start", { dockerStart: vi.fn(() => ({ status: null })) }],
-  ])("fails closed when rollback %s has no exit status", (_stage, override) => {
-    const outcome = finalizeDockerGpuPatchBackup(
+    ["rename", { dockerRename: vi.fn(() => ({ status: null })) }, "dockerStart"],
+    ["start", { dockerStart: vi.fn(() => ({ status: null })) }, undefined],
+  ] as const)("fails closed when rollback %s has no exit status", (_stage, override, unreachedKey) => {
+    const deps = {
+      dockerStop: vi.fn(() => ({ status: 0 })),
+      dockerRm: vi.fn(() => ({ status: 0 })),
+      dockerRename: vi.fn(() => ({ status: 0 })),
+      dockerStart: vi.fn(() => ({ status: 0 })),
+      ...override,
+    };
+    const outcome = finalizeDockerGpuPatchBackup(
       { result: deferredCreateResult(), supervisorReady: false },
-      {
-        dockerStop: vi.fn(() => ({ status: 0 })),
-        dockerRm: vi.fn(() => ({ status: 0 })),
-        dockerRename: vi.fn(() => ({ status: 0 })),
-        dockerStart: vi.fn(() => ({ status: 0 })),
-        ...override,
-      },
+      deps,
     );
     expect(outcome).toEqual({ backupRemoved: false, rolledBack: false });
+    if (unreachedKey) expect(deps[unreachedKey]).not.toHaveBeenCalled();
   });
🤖 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/docker-gpu-patch-finalize.test.ts` around lines 117 - 132,
The rename-stage branch in finalizeDockerGpuPatchBackup is too weak because it
only asserts the final outcome and does not verify rollback stops after
dockerRename fails. Strengthen the "rename" case in
docker-gpu-patch-finalize.test.ts by asserting dockerStart is not called when
dockerRename returns no exit status, mirroring the sibling rollback test’s
pattern so the test proves the rollback halts at the failed step instead of
passing via a broad mock.

Source: Path instructions

test/e2e/live/hermes-gpu-startup.test.ts (1)

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

Ternary used purely for side effects.

This ternary discards its result and exists only to run expect(...) in one branch or the other. Many ESLint configs enforce no-unused-expressions, which flags conditional/ternary expressions used as statements; this could fail CI lint even though the runtime behavior is correct.

🧹 Suggested fix
-  sandboxList.exitCode === 0
-    ? expect(outputContainsSandbox(sandboxList, SANDBOX_NAME)).toBe(false)
-    : expect(resultText(sandboxList)).toMatch(GATEWAY_ALREADY_ABSENT);
+  if (sandboxList.exitCode === 0) {
+    expect(outputContainsSandbox(sandboxList, SANDBOX_NAME)).toBe(false);
+  } else {
+    expect(resultText(sandboxList)).toMatch(GATEWAY_ALREADY_ABSENT);
+  }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/e2e/live/hermes-gpu-startup.test.ts` around lines 110 - 112, The
conditional in hermes-gpu-startup.test.ts is being used only to trigger
assertions, which can trip no-unused-expressions lint rules. Update the test
logic around sandboxList.exitCode so the two expect calls are executed through a
normal if/else statement instead of a ternary expression, keeping the same
behavior while avoiding a side-effect-only expression.
.github/workflows/e2e.yaml (1)

1707-1726: 🩺 Stability & Availability | 🔵 Trivial

Verify GPU runner pool capacity for the 2-way matrix.

runs-on: linux-amd64-gpu-rtxpro6000-latest-1 looks like a specific single-runner label. With fail-fast: false and matrix.scenario: [native, fallback], both legs need concurrently idle runners matching that exact label; GitHub Actions queues (not fails) a job if none is idle, so if only one physical runner carries this label, the two legs will simply serialize rather than run in parallel, which could roughly double the wall-clock time within the 75-minute per-job timeout budget.

Please confirm whether more than one runner is registered under this label, or whether serialization is acceptable.

🤖 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 @.github/workflows/e2e.yaml around lines 1707 - 1726, The hermes-gpu-startup
matrix uses a single specific runs-on label with fail-fast disabled, so both
matrix legs may serialize if only one runner matches. Verify that multiple
runners are registered for linux-amd64-gpu-rtxpro6000-latest-1, or adjust the
workflow to use a broader label/pool if parallel execution is required. Check
the e2e job definition and matrix.scenario setup together to ensure the 2-way
matrix fits the available GPU runner capacity.
🤖 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 @.github/workflows/e2e.yaml:
- Around line 1707-1726: The hermes-gpu-startup matrix uses a single specific
runs-on label with fail-fast disabled, so both matrix legs may serialize if only
one runner matches. Verify that multiple runners are registered for
linux-amd64-gpu-rtxpro6000-latest-1, or adjust the workflow to use a broader
label/pool if parallel execution is required. Check the e2e job definition and
matrix.scenario setup together to ensure the 2-way matrix fits the available GPU
runner capacity.

In `@src/lib/onboard/docker-gpu-patch-finalize.test.ts`:
- Around line 117-132: The rename-stage branch in finalizeDockerGpuPatchBackup
is too weak because it only asserts the final outcome and does not verify
rollback stops after dockerRename fails. Strengthen the "rename" case in
docker-gpu-patch-finalize.test.ts by asserting dockerStart is not called when
dockerRename returns no exit status, mirroring the sibling rollback test’s
pattern so the test proves the rollback halts at the failed step instead of
passing via a broad mock.

In `@src/lib/onboard/sandbox-gpu-create-attempt.test.ts`:
- Around line 194-207: Split the combined fallback-gating assertion in
executeSandboxGpuCreatePlan’s test so each gate is verified independently: one
case should cover a route plan that forbids fallback while the failure remains
eligible, and a separate case should cover an ineligible failure
(fallbackEligible false) under a route plan that would otherwise allow fallback.
Keep the existing symbols like executeSandboxGpuCreatePlan, runAttempt, and
cleanupNativeFailure, but restructure the test names and expectations so each
test proves only one gating condition.

In `@test/e2e/live/hermes-gpu-startup.test.ts`:
- Around line 110-112: The conditional in hermes-gpu-startup.test.ts is being
used only to trigger assertions, which can trip no-unused-expressions lint
rules. Update the test logic around sandboxList.exitCode so the two expect calls
are executed through a normal if/else statement instead of a ternary expression,
keeping the same behavior while avoiding a side-effect-only expression.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 9e4bbda1-3a2a-461b-9f0e-0c754977f01f

📥 Commits

Reviewing files that changed from the base of the PR and between 022c394 and 45fdef7.

📒 Files selected for processing (36)
  • .github/workflows/e2e.yaml
  • docs/reference/commands-nemohermes.mdx
  • docs/reference/commands.mdx
  • docs/reference/troubleshooting.mdx
  • src/lib/actions/sandbox/rebuild-target-runtime.ts
  • src/lib/onboard.ts
  • src/lib/onboard/docker-gpu-local-inference.test.ts
  • src/lib/onboard/docker-gpu-local-inference.ts
  • src/lib/onboard/docker-gpu-patch-finalize.test.ts
  • src/lib/onboard/docker-gpu-patch-finalize.ts
  • src/lib/onboard/docker-gpu-patch-rollback.test.ts
  • src/lib/onboard/docker-gpu-patch.test.ts
  • src/lib/onboard/docker-gpu-patch.ts
  • src/lib/onboard/docker-gpu-route.ts
  • src/lib/onboard/docker-gpu-sandbox-create.test.ts
  • src/lib/onboard/docker-gpu-sandbox-create.ts
  • src/lib/onboard/docker-gpu-supervisor-reconnect.test.ts
  • src/lib/onboard/docker-gpu-supervisor-reconnect.ts
  • src/lib/onboard/sandbox-create-intent-types.ts
  • src/lib/onboard/sandbox-create-launch.ts
  • src/lib/onboard/sandbox-create-plan.test.ts
  • src/lib/onboard/sandbox-create-plan.ts
  • src/lib/onboard/sandbox-dockerfile-patch-flow.test.ts
  • src/lib/onboard/sandbox-dockerfile-patch-flow.ts
  • src/lib/onboard/sandbox-gpu-create-attempt.test.ts
  • src/lib/onboard/sandbox-gpu-create-attempt.ts
  • src/lib/onboard/sandbox-gpu-create-flow.ts
  • src/lib/state/gateway.ts
  • test/e2e/live/hermes-gpu-startup-fallback.ts
  • test/e2e/live/hermes-gpu-startup-proof.ts
  • test/e2e/live/hermes-gpu-startup.test.ts
  • test/e2e/support/hermes-gpu-startup-fallback.test.ts
  • test/e2e/support/hermes-workflow-boundary.test.ts
  • test/e2e/support/upload-e2e-artifacts-workflow-boundary.test.ts
  • tools/e2e/hermes-gpu-startup-workflow-boundary.mts
  • tools/e2e/upload-e2e-artifacts-workflow-boundary.mts

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

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

E2E Target Results — ✅ All requested jobs passed

Run: 28812365881
Workflow ref: feat/gpu-native-fallback-6110
Requested targets: (default — all supported)
Requested jobs: hermes-gpu-startup
Summary: 1 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
hermes-gpu-startup ✅ success

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (1)
src/lib/onboard/sandbox-create-plan.ts (1)

56-59: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Remove the legacy GPU sandbox create path or bound its coexistence. src/lib/onboard/docker-gpu-sandbox-create.ts still exports resolveDockerGpuSandboxCreatePlan, and src/lib/onboard/sandbox-gpu-create.ts still accepts suppressGpuFlag; the related tests are still present. If this migration is meant to be complete, delete the old helper/tests in the same PR; otherwise link the retirement issue and state the compatibility window.

🤖 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/sandbox-create-plan.ts` around lines 56 - 59, The sandbox
create plan still exposes the legacy GPU create path through
SandboxCreatePlanDeps while the old resolveDockerGpuSandboxCreatePlan helper and
suppressGpuFlag-based sandbox GPU flow remain in use. Either remove the
deprecated GPU path end-to-end by deleting the legacy helpers and their tests
from the affected onboarding modules, or explicitly bound the coexistence by
wiring in a retirement/compatibility plan and documenting the allowed overlap in
the relevant sandbox create symbols.

Source: Path instructions

🧹 Nitpick comments (1)
src/lib/onboard/sandbox-create-plan.ts (1)

266-278: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Drop the unused dockerGpuPatch placeholder from the intent

materializeSandboxCreatePlan recomputes the real GPU-patch value from gpuRoutePlan, so this hardcoded false only makes SandboxCreateIntent look authoritative when it isn’t. If the shape is needed for tests, document it as an internal placeholder instead.

🤖 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/sandbox-create-plan.ts` around lines 266 - 278, The intent in
materializeSandboxCreatePlan is carrying an unused dockerGpuPatch placeholder
that is not the real source of truth. Remove the hardcoded dockerGpuPatch field
from the policy options in SandboxCreateIntent, or if the shape must remain for
compatibility, clearly mark it as an internal placeholder and keep the real
GPU-patch value derived from gpuRoutePlan. Use the materializeSandboxCreatePlan
and SandboxCreateIntent symbols to locate the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/e2e/support/hermes-gpu-startup-integrity.test.ts`:
- Line 151: The new test title in the test block should follow the local
issue-ref convention for root-level integration tests under test/, so update the
it(...) description in the relevant test function to end with the required
(`#1234`)-style suffix. Keep the title behavior-oriented, and ensure the suffix is
appended to the existing title in the hermes-gpu-startup-integrity test case.

---

Outside diff comments:
In `@src/lib/onboard/sandbox-create-plan.ts`:
- Around line 56-59: The sandbox create plan still exposes the legacy GPU create
path through SandboxCreatePlanDeps while the old
resolveDockerGpuSandboxCreatePlan helper and suppressGpuFlag-based sandbox GPU
flow remain in use. Either remove the deprecated GPU path end-to-end by deleting
the legacy helpers and their tests from the affected onboarding modules, or
explicitly bound the coexistence by wiring in a retirement/compatibility plan
and documenting the allowed overlap in the relevant sandbox create symbols.

---

Nitpick comments:
In `@src/lib/onboard/sandbox-create-plan.ts`:
- Around line 266-278: The intent in materializeSandboxCreatePlan is carrying an
unused dockerGpuPatch placeholder that is not the real source of truth. Remove
the hardcoded dockerGpuPatch field from the policy options in
SandboxCreateIntent, or if the shape must remain for compatibility, clearly mark
it as an internal placeholder and keep the real GPU-patch value derived from
gpuRoutePlan. Use the materializeSandboxCreatePlan and SandboxCreateIntent
symbols to locate the change.
🪄 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: a9c0f369-38f4-4b52-a165-5139dd5436f8

📥 Commits

Reviewing files that changed from the base of the PR and between 45fdef7 and f2f5e6f.

📒 Files selected for processing (28)
  • docs/reference/troubleshooting.mdx
  • src/lib/onboard.ts
  • src/lib/onboard/docker-gpu-local-inference.test.ts
  • src/lib/onboard/docker-gpu-local-inference.ts
  • src/lib/onboard/docker-gpu-patch-finalize.test.ts
  • src/lib/onboard/docker-gpu-patch-mode-selection.test.ts
  • src/lib/onboard/docker-gpu-patch-wsl.test.ts
  • src/lib/onboard/docker-gpu-patch.test.ts
  • src/lib/onboard/docker-gpu-patch.ts
  • src/lib/onboard/docker-gpu-route-patch-adapter.ts
  • src/lib/onboard/docker-gpu-route.test.ts
  • src/lib/onboard/docker-gpu-route.ts
  • src/lib/onboard/docker-gpu-sandbox-create-diagnostics.test.ts
  • src/lib/onboard/docker-gpu-sandbox-create.test.ts
  • src/lib/onboard/docker-gpu-sandbox-create.ts
  • src/lib/onboard/openshell-docker-sandbox-containers.test.ts
  • src/lib/onboard/openshell-docker-sandbox-containers.ts
  • src/lib/onboard/sandbox-create-plan.test.ts
  • src/lib/onboard/sandbox-create-plan.ts
  • src/lib/onboard/sandbox-gpu-create-attempt.test.ts
  • src/lib/onboard/sandbox-gpu-create-attempt.ts
  • src/lib/onboard/sandbox-gpu-create-flow.ts
  • src/lib/onboard/sandbox-gpu-route-policy.ts
  • test/e2e/live/hermes-gpu-startup-fallback.ts
  • test/e2e/live/hermes-gpu-startup-integrity.ts
  • test/e2e/live/hermes-gpu-startup.test.ts
  • test/e2e/support/hermes-gpu-startup-fallback.test.ts
  • test/e2e/support/hermes-gpu-startup-integrity.test.ts
💤 Files with no reviewable changes (2)
  • src/lib/onboard/docker-gpu-local-inference.test.ts
  • src/lib/onboard/docker-gpu-patch.test.ts
✅ Files skipped from review due to trivial changes (1)
  • src/lib/onboard/docker-gpu-patch-wsl.test.ts
🚧 Files skipped from review as they are similar to previous changes (11)
  • src/lib/onboard/sandbox-gpu-create-attempt.test.ts
  • test/e2e/live/hermes-gpu-startup-fallback.ts
  • src/lib/onboard/sandbox-gpu-create-flow.ts
  • docs/reference/troubleshooting.mdx
  • test/e2e/support/hermes-gpu-startup-fallback.test.ts
  • src/lib/onboard/sandbox-gpu-create-attempt.ts
  • src/lib/onboard/docker-gpu-local-inference.ts
  • src/lib/onboard/sandbox-create-plan.test.ts
  • test/e2e/live/hermes-gpu-startup.test.ts
  • src/lib/onboard/docker-gpu-sandbox-create.test.ts
  • src/lib/onboard.ts

Comment thread test/e2e/support/hermes-gpu-startup-integrity.test.ts Outdated
ericksoa added 2 commits July 6, 2026 11:20
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

E2E Target Results — ✅ All requested jobs passed

Run: 28813686639
Workflow ref: feat/gpu-native-fallback-6110
Requested targets: (default — all supported)
Requested jobs: hermes-gpu-startup
Summary: 1 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
hermes-gpu-startup ✅ success

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

E2E Target Results — ✅ All requested jobs passed

Run: 28813822004
Workflow ref: feat/gpu-native-fallback-6110
Requested targets: (default — all supported)
Requested jobs: hermes-gpu-startup
Summary: 1 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
hermes-gpu-startup ✅ success

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/lib/onboard/docker-gpu-patch-mode.ts (1)

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

Duplicate timeout constant across files.

DOCKER_GPU_PATCH_TIMEOUT_MS = 30_000 is duplicated identically in docker-gpu-patch-diagnostics.ts. Consider hoisting to a shared constants module to avoid drift as these files are further modularized.

♻️ Proposed fix
-const DOCKER_GPU_PATCH_TIMEOUT_MS = 30_000;
+import { DOCKER_GPU_PATCH_TIMEOUT_MS } from "./docker-gpu-patch-constants";
🤖 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/docker-gpu-patch-mode.ts` at line 16, The timeout constant is
duplicated in docker-gpu-patch-mode and docker-gpu-patch-diagnostics, so move
DOCKER_GPU_PATCH_TIMEOUT_MS into a shared constants module and import it from
both places. Update the references in the docker GPU patch helpers that use this
value so both modules rely on the same source of truth and stay aligned as the
code is split further.
🤖 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/lib/onboard/docker-gpu-patch-mode.ts`:
- Line 16: The timeout constant is duplicated in docker-gpu-patch-mode and
docker-gpu-patch-diagnostics, so move DOCKER_GPU_PATCH_TIMEOUT_MS into a shared
constants module and import it from both places. Update the references in the
docker GPU patch helpers that use this value so both modules rely on the same
source of truth and stay aligned as the code is split further.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 12d874ad-9f0d-449d-abfb-b0b7ef9eab3d

📥 Commits

Reviewing files that changed from the base of the PR and between f2f5e6f and 3f11600.

📒 Files selected for processing (20)
  • docs/reference/troubleshooting.mdx
  • src/lib/onboard/docker-gpu-patch-diagnostics.ts
  • src/lib/onboard/docker-gpu-patch-mode.ts
  • src/lib/onboard/docker-gpu-patch-recreate-dns.test.ts
  • src/lib/onboard/docker-gpu-patch-recreate.ts
  • src/lib/onboard/docker-gpu-patch.test.ts
  • src/lib/onboard/docker-gpu-patch.ts
  • src/lib/onboard/docker-gpu-route.test.ts
  • src/lib/onboard/docker-gpu-sandbox-create.ts
  • src/lib/onboard/sandbox-create-intent-types.ts
  • src/lib/onboard/sandbox-create-plan-materialization.ts
  • src/lib/onboard/sandbox-create-plan.test.ts
  • src/lib/onboard/sandbox-create-plan.ts
  • src/lib/onboard/sandbox-gpu-create-attempt.test.ts
  • src/lib/onboard/sandbox-gpu-create-attempt.ts
  • src/lib/onboard/sandbox-gpu-create-flow.test.ts
  • src/lib/onboard/sandbox-gpu-create-flow.ts
  • test/e2e/live/hermes-gpu-startup-fallback.ts
  • test/e2e/support/hermes-gpu-startup-fallback.test.ts
  • test/e2e/support/hermes-gpu-startup-integrity.test.ts
💤 Files with no reviewable changes (2)
  • src/lib/onboard/docker-gpu-patch.test.ts
  • src/lib/onboard/sandbox-create-intent-types.ts
🚧 Files skipped from review as they are similar to previous changes (8)
  • test/e2e/support/hermes-gpu-startup-integrity.test.ts
  • src/lib/onboard/sandbox-gpu-create-attempt.test.ts
  • docs/reference/troubleshooting.mdx
  • src/lib/onboard/docker-gpu-route.test.ts
  • test/e2e/live/hermes-gpu-startup-fallback.ts
  • src/lib/onboard/sandbox-gpu-create-flow.ts
  • src/lib/onboard/sandbox-gpu-create-attempt.ts
  • src/lib/onboard/docker-gpu-sandbox-create.ts

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

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

E2E Target Results — ✅ All requested jobs passed

Run: 28815042279
Workflow ref: feat/gpu-native-fallback-6110
Requested targets: (default — all supported)
Requested jobs: hermes-gpu-startup
Summary: 1 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
hermes-gpu-startup ✅ success

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

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

E2E Target Results — ✅ All requested jobs passed

Run: 28815516859
Workflow ref: feat/gpu-native-fallback-6110
Requested targets: (default — all supported)
Requested jobs: hermes-gpu-startup
Summary: 1 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
hermes-gpu-startup ✅ success

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 (2)
src/lib/onboard/docker-gpu-patch-clone.ts (1)

89-97: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Host-network override silently no-ops without a rewritable OPENSHELL_ENDPOINT.

buildDockerGpuCloneRunOptions only switches to networkMode: "host" when the inspected container also has an OPENSHELL_ENDPOINT pointing at host.openshell.internal (line 94-96). If NEMOCLAW_DOCKER_GPU_PATCH_NETWORK=host is set but that env var is absent/different, the recreated clone silently keeps host.NetworkMode (line 174 in buildDockerGpuCloneRunArgs) instead of honoring the operator's override — there's no warning surfaced for this case.

Worth confirming this coupling (host networking is gated on endpoint rewritability) is the intended design, since OpenShell sandboxes normally always carry this env var, making this a narrow edge case.

🤖 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/docker-gpu-patch-clone.ts` around lines 89 - 97, The
host-network override in buildDockerGpuCloneRunOptions is currently gated on
OPENSHELL_ENDPOINT being rewritable, so a requested
NEMOCLAW_DOCKER_GPU_PATCH_NETWORK=host can silently fall back to the original
network mode. Update buildDockerGpuCloneRunOptions and, if needed,
buildDockerGpuCloneRunArgs to either honor the host override unconditionally or
explicitly surface a warning/fallback path when OPENSHELL_ENDPOINT is missing or
cannot be rewritten, using the existing
dockerGpuHostEndpointFromOpenShellEndpoint and networkMode handling.
src/lib/onboard/docker-gpu-patch-finalize.ts (1)

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

isZeroStatus duplicated across multiple modules instead of centralized.

This file redefines isZeroStatus locally, and the same strict-status tightening (result?.status === 0) was independently applied in docker-gpu-supervisor-reconnect.ts and, per the cohort summary, in the patch/rollback modules too. Since DOCKER_GPU_PATCH_TIMEOUT_MS was already centralized into docker-gpu-patch-constants.ts in this same refactor, isZeroStatus is a natural candidate for the same treatment — duplicated status-gating logic can silently drift between modules on future changes.

♻️ Suggested consolidation
+// docker-gpu-patch-constants.ts
+export function isZeroStatus(result?: { status?: number | null } | null): boolean {
+  return result?.status === 0;
+}

Then import isZeroStatus from ./docker-gpu-patch-constants in docker-gpu-patch-finalize.ts, docker-gpu-supervisor-reconnect.ts, and the patch/rollback modules instead of each defining it locally.

🤖 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/docker-gpu-patch-finalize.ts` around lines 26 - 48, The
status-check helper is duplicated across the docker GPU patch modules, so
consolidate the strict exit-status logic into a single shared `isZeroStatus`
helper in `docker-gpu-patch-constants` alongside `DOCKER_GPU_PATCH_TIMEOUT_MS`.
Update `docker-gpu-patch-finalize`, `docker-gpu-supervisor-reconnect`, and the
patch/rollback modules to import and use that shared helper instead of
redefining it locally. Keep the helper’s behavior as the explicit zero-status
check used by `isZeroStatus` so all cleanup and rollback paths stay consistent.
🤖 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/onboard/docker-gpu-patch-diagnostics.test.ts`:
- Around line 299-324: The test name claims to verify the fallback when
dockerCapture is omitted, but the current collectDockerGpuPatchDiagnostics call
still injects a dockerCapture mock, so it never exercises the
defaultDockerCapture path. Update this test in
docker-gpu-patch-diagnostics.test.ts to omit dockerCapture from the deps object
entirely and assert the observable outcome of the default fallback behavior
through collectDockerGpuPatchDiagnostics rather than checking the injected mock.
Keep the existing sandbox/context setup, but make sure the test truly covers the
missing-dependency case.

---

Nitpick comments:
In `@src/lib/onboard/docker-gpu-patch-clone.ts`:
- Around line 89-97: The host-network override in buildDockerGpuCloneRunOptions
is currently gated on OPENSHELL_ENDPOINT being rewritable, so a requested
NEMOCLAW_DOCKER_GPU_PATCH_NETWORK=host can silently fall back to the original
network mode. Update buildDockerGpuCloneRunOptions and, if needed,
buildDockerGpuCloneRunArgs to either honor the host override unconditionally or
explicitly surface a warning/fallback path when OPENSHELL_ENDPOINT is missing or
cannot be rewritten, using the existing
dockerGpuHostEndpointFromOpenShellEndpoint and networkMode handling.

In `@src/lib/onboard/docker-gpu-patch-finalize.ts`:
- Around line 26-48: The status-check helper is duplicated across the docker GPU
patch modules, so consolidate the strict exit-status logic into a single shared
`isZeroStatus` helper in `docker-gpu-patch-constants` alongside
`DOCKER_GPU_PATCH_TIMEOUT_MS`. Update `docker-gpu-patch-finalize`,
`docker-gpu-supervisor-reconnect`, and the patch/rollback modules to import and
use that shared helper instead of redefining it locally. Keep the helper’s
behavior as the explicit zero-status check used by `isZeroStatus` so all cleanup
and rollback paths stay consistent.
🪄 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: 3af4fadb-6c8f-4e9e-9338-7db1e1a89768

📥 Commits

Reviewing files that changed from the base of the PR and between 3f11600 and 10e615b.

📒 Files selected for processing (29)
  • docs/reference/troubleshooting.mdx
  • src/lib/onboard/docker-gpu-dns-fallback.ts
  • src/lib/onboard/docker-gpu-jetson-groups.ts
  • src/lib/onboard/docker-gpu-patch-clone.test.ts
  • src/lib/onboard/docker-gpu-patch-clone.ts
  • src/lib/onboard/docker-gpu-patch-constants.ts
  • src/lib/onboard/docker-gpu-patch-diagnostics.test.ts
  • src/lib/onboard/docker-gpu-patch-diagnostics.ts
  • src/lib/onboard/docker-gpu-patch-finalize.ts
  • src/lib/onboard/docker-gpu-patch-jetson.test.ts
  • src/lib/onboard/docker-gpu-patch-mode-selection.test.ts
  • src/lib/onboard/docker-gpu-patch-mode.ts
  • src/lib/onboard/docker-gpu-patch-recreate-dns.test.ts
  • src/lib/onboard/docker-gpu-patch-recreate.test.ts
  • src/lib/onboard/docker-gpu-patch-recreate.ts
  • src/lib/onboard/docker-gpu-patch-rollback.ts
  • src/lib/onboard/docker-gpu-patch.test.ts
  • src/lib/onboard/docker-gpu-patch.ts
  • src/lib/onboard/docker-gpu-pre-rollback-diagnostics.ts
  • src/lib/onboard/docker-gpu-route.test.ts
  • src/lib/onboard/docker-gpu-supervisor-reconnect.test.ts
  • src/lib/onboard/docker-gpu-supervisor-reconnect.ts
  • src/lib/onboard/sandbox-create-intent.ts
  • src/lib/onboard/sandbox-create-plan.ts
  • src/lib/onboard/sandbox-gpu-cleanup-verification.test.ts
  • src/lib/onboard/sandbox-gpu-create-attempt.ts
  • src/lib/onboard/sandbox-gpu-create-failure-classification.test.ts
  • src/lib/onboard/sandbox-gpu-create-flow.test.ts
  • src/lib/onboard/sandbox-gpu-fallback-orchestration.test.ts
💤 Files with no reviewable changes (2)
  • src/lib/onboard/sandbox-gpu-fallback-orchestration.test.ts
  • src/lib/onboard/docker-gpu-patch.test.ts
✅ Files skipped from review due to trivial changes (2)
  • src/lib/onboard/sandbox-gpu-create-failure-classification.test.ts
  • src/lib/onboard/docker-gpu-jetson-groups.ts
🚧 Files skipped from review as they are similar to previous changes (6)
  • src/lib/onboard/docker-gpu-patch-recreate-dns.test.ts
  • src/lib/onboard/docker-gpu-route.test.ts
  • docs/reference/troubleshooting.mdx
  • src/lib/onboard/docker-gpu-patch-mode.ts
  • src/lib/onboard/docker-gpu-patch-diagnostics.ts
  • src/lib/onboard/sandbox-gpu-create-attempt.ts

Comment thread src/lib/onboard/docker-gpu-patch-diagnostics.test.ts Outdated
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

E2E Target Results — ❌ Some jobs failed

Run: 28816169079
Workflow ref: feat/gpu-native-fallback-6110
Requested targets: (default — all supported)
Requested jobs: hermes-gpu-startup
Summary: 0 passed, 1 failed, 0 cancelled, 0 skipped

Job Result
hermes-gpu-startup ❌ failure

Failed jobs: hermes-gpu-startup. Check run artifacts for logs.

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

E2E Target Results — ❌ Some jobs failed

Run: 28816418199
Workflow ref: feat/gpu-native-fallback-6110
Requested targets: (default — all supported)
Requested jobs: hermes-gpu-startup
Summary: 0 passed, 1 failed, 0 cancelled, 0 skipped

Job Result
hermes-gpu-startup ❌ failure

Failed jobs: hermes-gpu-startup. Check run artifacts for logs.

@cv

cv commented Jul 12, 2026

Copy link
Copy Markdown
Collaborator

Release sweep: deferring this PR from v0.0.81.

The active security change request is still present: the GPU fallback workflow stores Docker daemon state in a predictable permissive directory and restores it with mode 0644, while its boundary test requires that behavior. The branch also conflicts with current main, spans a very large surface, and does not yet have the required live GPU evidence.

Before re-targeting, please use private temporary state, preserve the original metadata on restore, guarantee cleanup/recovery, update the boundary tests, sync with main, and provide the requested live GPU proof.

@cv cv removed the v0.0.81 Release target label Jul 12, 2026
ericksoa added 3 commits July 12, 2026 06:57
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>

# Conflicts:
#	src/lib/onboard.ts
#	src/lib/onboard/docker-gpu-patch-finalize.test.ts
#	src/lib/onboard/docker-gpu-patch-finalize.ts
#	src/lib/onboard/docker-gpu-patch.test.ts
#	src/lib/onboard/docker-gpu-patch.ts
#	src/lib/onboard/sandbox-create-launch.ts
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Comment thread test/e2e/support/hermes-workflow-boundary.test.ts Fixed
ericksoa added 4 commits July 12, 2026 07:47
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Comment thread src/lib/onboard/sandbox-gpu-create-cleanup-provenance.test.ts Fixed
Comment thread test/e2e/support/hermes-workflow-boundary.test.ts Fixed
Comment thread src/lib/onboard/sandbox-gpu-create-cleanup-provenance.test.ts Fixed
ericksoa added 2 commits July 12, 2026 09:22
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@cv cv mentioned this pull request Jul 12, 2026
21 tasks
cv added a commit that referenced this pull request Jul 12, 2026
## Summary
Repairs three deterministic failures found during v0.0.81 release
validation. Hermes restart-safe recreation now preserves OpenShell's
native CDI GPU attachment, the Slack proof finds the reviewed package in
canonical managed npm projects, and the OpenShell auth contract collects
under Vitest's fixture parser.

## Changes
- Preserve inspected `Driver: cdi` device IDs as Docker `--device`
arguments during startup-command recreation, without selecting
compatibility GPU mode or adding broader privileges.
- Discover `@openclaw/slack` one level below OpenClaw's managed npm
projects only when the project manifest declares that dependency.
- Destructure the live auth-contract fixtures so Vitest 4.1.9 can
collect the test while passing the same scenario inputs.
- Add regression coverage for the CDI clone arguments and managed Slack
project discovery.
- Note for #6333: that PR moves the Docker clone code into split files
but does not yet preserve CDI device requests; whichever PR rebases
second must retain this contract.

The two `rebuild-hermes-stale-base` attempts ended with GitHub's hosted
runner losing communication before Vitest exited or uploaded artifacts;
the unchanged ordinary rebuild also lost a runner once and passed on
retry. Jetson had no runner. Neither result has an evidence-backed
repository change in this PR.

## Type of Change

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

## Quality Gates

- [x] Tests added or updated for changed behavior
- [ ] Existing tests cover changed behavior — justification:
- [ ] Tests not applicable — justification:
- [ ] Docs updated for user-facing behavior changes
- [x] Docs not applicable — justification: this restores existing GPU
passthrough and release-proof contracts without changing commands,
flags, configuration, defaults, or required user actions.
- [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: independent diff review
confirmed CDI propagation is startup-command-only, adds no broader GPU
privileges, and Slack discovery is bounded to one manifest-gated
directory level.
- [ ] 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 — 67 Docker clone tests, 24
messaging-proof tests, live auth-contract collection to its intended
availability skip, and 653 changed-scope 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)
- [ ] 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: Carlos Villela <cvillela@nvidia.com>


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

## Summary by CodeRabbit

- **Bug Fixes**
- Preserved native CDI GPU device attachments when recreating Docker
containers, preventing GPU access from being lost during startup-command
persistence.
- Improved Slack integration discovery for installations managed through
project-specific npm environments.

- **Tests**
- Added coverage for CDI GPU preservation and Slack package discovery
across valid, unrelated, and malformed project directories.
- Updated gateway authentication scenarios for more reliable end-to-end
validation.

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

Signed-off-by: Carlos Villela <cvillela@nvidia.com>
ericksoa added 4 commits July 12, 2026 10:55
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>

# Conflicts:
#	src/lib/onboard/docker-gpu-patch.ts
#	test/e2e/support/dockerhub-auth-workflow-boundary.test.ts
#	test/e2e/support/upload-e2e-artifacts-workflow-boundary.test.ts
#	tools/e2e/upload-e2e-artifacts-workflow-boundary.mts
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@cv cv dismissed stale reviews from cjagwani and themself July 12, 2026 18:48

Outdated review

@ericksoa ericksoa merged commit e7e2ce6 into main Jul 12, 2026
59 of 62 checks passed
@ericksoa ericksoa deleted the feat/gpu-native-fallback-6110 branch July 12, 2026 19:26
@github-actions github-actions Bot added the v0.0.81 Release target label Jul 12, 2026
@cv cv mentioned this pull request Jul 12, 2026
21 tasks
cv added a commit that referenced this pull request Jul 12, 2026
<!-- markdownlint-disable MD041 -->
## Summary

Updates the Hermes GPU live proof to assert the canonical `Docker
container mode selected:` message introduced by #6333. The stale `Docker
GPU mode selected:` expectation failed the exact-candidate fallback E2E
after container recreation, Ready state, and CUDA verification had
already succeeded.

## Changes

- Require the canonical container-mode selection message for fallback
and compatibility-only routes.
- Verify that the native route does not emit the compatibility
container-mode message.

## Type of Change

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

## Quality Gates

- [x] Tests added or updated for changed behavior
- [ ] Existing tests cover changed behavior — justification:
- [ ] Tests not applicable — justification:
- [ ] Docs updated for user-facing behavior changes
- [x] Docs not applicable — justification: This changes only an internal
live-test assertion; user-facing GPU routing, configuration, commands,
and documented behavior are unchanged.
- [ ] 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 e2e-support
test/e2e/support/hermes-gpu-startup-fallback.test.ts
test/e2e/support/hermes-gpu-startup-integrity.test.ts
test/e2e/support/hermes-workflow-boundary.test.ts` (38 passed);
live-test collection passed for native, fallback, and compatibility-only
scenarios
- [ ] 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)
- [ ] 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: Carlos Villela <cvillela@nvidia.com>


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

## Summary by CodeRabbit

* **Tests**
* Updated end-to-end validation to reflect revised Docker startup
messaging.
* Added coverage for container-mode logging in compatibility and
fallback scenarios.
  * Confirmed container-mode messaging is absent for other GPU routes.

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

Signed-off-by: Carlos Villela <cvillela@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: local-models Local model providers, downloads, launch, or connectivity area: onboarding Onboarding FSM, provider setup, sandbox launch, or first-run flow area: sandbox OpenShell sandbox lifecycle, runtime, config, or recovery feature PR adds or expands user-visible functionality needs: design Requires product or architecture direction needs: rebase PR needs rebase or conflict resolution platform: dgx-spark Affects DGX Spark hardware or workflows v0.0.81 Release target

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants