Skip to content

refactor(e2e): complete cleanup resource tracking - #6724

Merged
cv merged 6 commits into
mainfrom
codex/issue-6352-cleanup-migrations
Jul 12, 2026
Merged

refactor(e2e): complete cleanup resource tracking#6724
cv merged 6 commits into
mainfrom
codex/issue-6352-cleanup-migrations

Conversation

@cv

@cv cv commented Jul 12, 2026

Copy link
Copy Markdown
Collaborator

Summary

Complete the remaining live-E2E cleanup resource migration so ordinary teardown is strict, idempotent, ordered, and visible in cleanup.json. Standard sandbox, gateway, forward, server, process, image, and temporary-state cleanup now uses typed trackers or strict disposables; destructive pre-clean and negative-path verification remain explicit. This changes test infrastructure only, not NemoClaw product behavior.

Related Issue

Closes #6352
Closes #6346

Changes

  • Extend SandboxClient with strict already-absent-aware OpenShell sandbox cleanup, add a tested command-availability probe for partial installer setup, and narrow each tracker to the client method it consumes.
  • Migrate ordinary final teardown across the live suite to trackSandbox, trackGateway, trackForward, and trackDisposable while preserving LIFO dependencies, artifact names, redactions, timeouts, keep policies, and owned gateway-runtime cleanup.
  • Keep pre-clean, recovery, and negative-proof cleanup explicit; unexpected final cleanup failures now reach the registry instead of disappearing inside catch-all wrappers.
  • Preserve partial-install behavior by treating a missing managing CLI as non-acquisition, while surfacing every cleanup failure once that CLI exists.
  • Add focused support coverage for option forwarding, reverse ordering, partial setup, canonical absence, failure continuation, redaction, and unexpected failures.
  • Add mock/live parity mappings for all 56 changed live specs and directly test the shared cleanup guards, overlayfs preserve/LIFO behavior, and verified Hermes teardown skip.
  • Cleanup census from the refactor(e2e): track sandbox and gateway cleanup as resources #6352 baseline: raw cleanup.add calls 123 -> 53; exact generic bestEffort helpers 28 -> 0; current typed adoption is 41 sandbox, 39 gateway, 8 forward, and 124 disposable registrations. The remaining raw callbacks are bespoke lifecycle, recovery, diagnostic, or negative-proof work rather than repeated standard sandbox/gateway/forward teardown.
  • Cumulative Epic: Deduplicate and harden the Vitest E2E test infrastructure #6346 closing census includes local result helpers 36 -> 0, local exit-zero helpers 10 -> 0, manual target.json writers 61 -> 0, manual target-result.json writers 34 -> 0, and redundant per-file live gates 66 -> 0.

The new command-availability client method is required by installer-fidelity live tests that register cleanup before install.sh may acquire the CLI. Registering only after a successful install would miss partially-created resources; test/e2e/support/e2e-clients.test.ts protects available, missing, failure, and exact-option behavior.

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: internal E2E fixture and teardown behavior only; no CLI, configuration, workflow, or operator contract changed.
  • 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

  • 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, or npm run check:diff passed when hooks were skipped or unavailable
  • Targeted behavior tests pass for the current change set, or tests are marked not applicable above — npx vitest run --project e2e-support (115 files, 978 tests); exact mock/live parity for all 56 changed live specs; conditional count 375 -> 373 with zero per-file increases; npm run typecheck:cli; exact 8-project membership; all live specs transform/list
  • Applicable broad gate passed — npm test (1,450 files; 16,396 tests; 3 files / 40 tests skipped)
  • Quality Gates section completed with required justifications or waivers
  • No secrets, API keys, or credentials committed
  • npm run docs builds without warnings (doc changes only)
  • Doc pages follow the style guide (doc changes only)
  • New doc pages include SPDX header and frontmatter (new pages only)

Signed-off-by: Carlos Villela cvillela@nvidia.com

Summary by CodeRabbit

  • Bug Fixes

    • Improved end-to-end teardown robustness by tracking gateways, forwards, sandboxes, and temporary artifacts separately.
    • Teardown now treats expected “already absent/missing” outcomes as success, while failing on unexpected non-zero results.
    • Added command-availability checks and stricter “succeeded or absent” verification during cleanup.
  • Tests

    • Expanded and refactored many live end-to-end suites to use standardized lifecycle cleanup helpers and clearer cleanup ordering.
    • Added new coverage for cleanup resource utilities and client probing behavior.
  • Refactor

    • Standardized “best-effort/secondary/pre-clean” helper naming and wiring.
    • Added configurable OpenShell binary-path support for host-side checks/cleanup.

cv added 2 commits July 12, 2026 12:24
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
@cv cv self-assigned this Jul 12, 2026
@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR adds typed E2E cleanup resource tracking, command availability probing, idempotent sandbox deletion, stricter cleanup result handling, and migrates live tests from monolithic cleanup callbacks to tracked gateway, forward, sandbox, and disposable resources.

Changes

E2E cleanup lifecycle

Layer / File(s) Summary
Cleanup primitives and fixture clients
test/e2e/fixtures/*, test/e2e/support/*
Adds typed cleanup tracking, command availability probing, idempotent sandbox deletion, conditional cleanup helpers, process termination handling, and focused support coverage.
Shared live cleanup helpers
test/e2e/live/*helpers.ts
Separates preclean and secondary cleanup behavior, adds reusable sandbox tracking, and introduces strict cleanup helpers for gateway runtimes and scenario resources.
Live test migration
test/e2e/live/*.test.ts
Replaces monolithic cleanup callbacks with granular tracked gateway, forward, sandbox, disposable, provider, process, and temporary-state cleanup registrations across the live E2E suite.
Overlayfs and parity coverage
test/e2e/live/overlayfs-autofix-cleanup.ts, test/e2e/support/overlayfs-autofix-outcome.test.ts, test/e2e/mock-parity.json
Adds overlayfs cleanup orchestration and tests, and includes shared cleanup support tests in fast mock-parity entries.

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

Suggested labels: refactor, area: e2e

Suggested reviewers: ericksoa, jyaunches

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR adds typed cleanup tracking, absence-aware cleanup, removes local bestEffort wrappers, and adds support tests, matching #6352/#6346.
Out of Scope Changes check ✅ Passed The changes stay within E2E teardown infrastructure and support coverage; no unrelated product behavior or scenario rewrites are evident.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: completing E2E cleanup resource tracking.
✨ 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 codex/issue-6352-cleanup-migrations

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

Signed-off-by: Carlos Villela <cvillela@nvidia.com>
@github-code-quality

github-code-quality Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

The overall coverage remains at 96%, unchanged from the main branch.

TypeScript / code-coverage/cli

The overall coverage in the codex/issue-6352-cle... branch remains at 79%, unchanged from the main branch.

Show a code coverage summary of the most impacted files.
File main 457311c codex/issue-6352-cle... 0bfd95d +/-
src/lib/messagi...ridge-health.ts 79% 68% -11%
src/lib/messagi...ate-resolver.ts 89% 78% -11%
src/lib/messagi.../token-paste.ts 92% 82% -10%
src/lib/messagi...onfig-prompt.ts 97% 91% -6%
src/lib/platform.ts 86% 80% -6%
src/lib/messagi...ridge-health.ts 96% 91% -5%
src/lib/messagi...l-validation.ts 74% 70% -4%
src/lib/state/config-io.ts 93% 90% -3%
src/lib/messagi...reachability.ts 78% 76% -2%
src/lib/messagi...annel-config.ts 96% 99% +3%

Updated July 12, 2026 20:35 UTC
Code Coverage is in Public Preview. Learn more and provide us with your feedback.

@github-actions

github-actions Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

E2E Advisor Recommendation

Required E2E: cloud-onboard
Optional E2E: onboard-resume, onboard-repair, full-e2e

Dispatch hint: cloud-onboard,onboard-resume,onboard-repair,full-e2e

Workflow run

Full advisor summary

E2E Recommendation Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E

  • cloud-onboard: Required by the deterministic risk plan: validate the clean-host public installer and hosted onboarding flow after the cloud onboarding E2E target cleanup changes.

Optional E2E

  • onboard-resume: Exercises the changed cleanup-resource helpers alongside real interrupted-onboarding resume and gateway/session credential recovery.
  • onboard-repair: Exercises the changed cleanup-resource helpers in the real onboarding repair flow, including cleanup verification after recovery.
  • full-e2e: Useful broad lifecycle confidence for the shared HostCliClient/SandboxClient cleanup refactor across onboarding, sandbox creation, and teardown.

New E2E recommendations

  • None.

Dispatch hint

  • Workflow: E2E
  • jobs input: cloud-onboard,onboard-resume,onboard-repair,full-e2e

@github-actions

github-actions Bot commented Jul 12, 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.

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

Caution

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

⚠️ Outside diff range comments (2)
test/e2e/live/rebuild-hermes.test.ts (1)

147-173: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Export the sandbox name for the pre-clean shell.

Lines 158-159 expand $SANDBOX_NAME, but the environment only provides NEMOCLAW_SANDBOX_NAME. Pre-clean therefore skips the intended sandbox, allowing stale resources to contaminate the run.

Proposed fix
       env: testEnv(apiKey, {
+        SANDBOX_NAME,
         DISCORD_PROVIDER: `${SANDBOX_NAME}-discord-bridge`,
         OLD_BASE_TAG,
       }),
🤖 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/rebuild-hermes.test.ts` around lines 147 - 173, Update
bestEffortPrecleanHermesResources so the pre-clean shell receives SANDBOX_NAME
mapped from the existing NEMOCLAW_SANDBOX_NAME value in testEnv. Preserve the
command references to SANDBOX_NAME and ensure the exported environment variable
targets the intended sandbox.
test/e2e/live/double-onboard.test.ts (1)

220-247: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

New exitCode assertion doesn't exercise a real success/failure claim.

The script uses set +e and every fallible step is guarded with || true, ending in an unconditional exit 0. stop.exitCode will always be 0 regardless of whether any internal step actually succeeded, so expect(stop.exitCode, ...).toBe(0) only verifies that bash itself could be spawned — it never fails on a real teardown problem. This reads as a meaningful assertion but doesn't test what it implies.

Either drop the assertion (it adds no signal), or make the script propagate a real terminal status so the check is meaningful.

As per path instructions for test files, "Flag ... conditionals that make a test pass without exercising its claim."

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

In `@test/e2e/live/double-onboard.test.ts` around lines 220 - 247, Make the
teardown result assertion in stopGatewayRuntime meaningful: either remove the
stop.exitCode expectation, or change the script to preserve and return a real
failure status for teardown operations instead of using unconditional exit 0
with broadly suppressed errors. Keep intentionally best-effort cleanup behavior
only where appropriate, while ensuring the chosen outcome matches what the test
claims to verify.

Source: Path instructions

🧹 Nitpick comments (3)
test/e2e/live/jetson-nvmap-gpu.test.ts (1)

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

Repeated "probe availability, then cleanup" boilerplate across gateway/sandbox/nemoclaw guards.

The same three-line pattern (probe with isCommandAvailable, return early if false, else delegate to the real cleanup) is duplicated three times with only the probed command and delegate call varying. Extracting a small helper (e.g., guardedCleanup(probeCommand, probeOptions, action)) would remove ~30 lines of repetition and reduce the chance of the drift seen with the OPENSHELL_BIN inconsistency above.

🤖 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/jetson-nvmap-gpu.test.ts` around lines 119 - 181, Extract the
repeated availability-check and early-return logic into a small guarded cleanup
helper near the cleanup registrations, accepting the probe command, probe
options, and cleanup action. Update the gateway, OpenShell sandbox, and nemoclaw
sandbox registrations to use this helper while preserving each existing command
source and cleanup delegate, including the current OPENSHELL_BIN behavior.
test/e2e/live/credential-sanitization.test.ts (1)

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

Duplicated sandbox-absence detection logic; regex has already drifted.

This re-implements the same absence-pattern check as HostCliClient.cleanupSandbox (test/e2e/fixtures/clients/host.ts), but uses /iu here versus /i there. Since this test needs a node [CLI_ENTRYPOINT, ...] invocation instead of host.nemoclaw(...), it can't call host.cleanupSandbox directly, but the duplicated regex is exactly the kind of pattern the PR's "distinguishing permitted absence from real failures" objective is meant to centralize.

Consider extracting a shared isSandboxAbsentError(text: string): boolean helper (e.g., alongside resultText/assertExitZero in command.ts) and reusing it from both HostCliClient.cleanupSandbox and this function.

♻️ Proposed shared helper
+// test/e2e/fixtures/clients/command.ts
+const SANDBOX_ABSENT_PATTERN =
+  /Sandbox '.+' does not exist|Run 'nemoclaw onboard' to create one|sandbox .* not found|no such sandbox/i;
+
+export function isSandboxAbsentError(text: string): boolean {
+  return SANDBOX_ABSENT_PATTERN.test(text);
+}
 async function cleanupCredentialSanitizationNemoClawSandbox(
   host: HostCliClient,
   home: string,
 ): Promise<void> {
   const result = await host.command("node", [CLI_ENTRYPOINT, SANDBOX_NAME, "destroy", "--yes"], {
     artifactName: "cleanup-nemoclaw-destroy-credential-sanitization",
     env: testEnv(home),
     timeoutMs: 120_000,
   });
-  if (
-    result.exitCode === 0 ||
-    /Sandbox '.+' does not exist|Run 'nemoclaw onboard' to create one|sandbox .* not found|no such sandbox/iu.test(
-      resultText(result),
-    )
-  ) {
+  if (result.exitCode === 0 || isSandboxAbsentError(resultText(result))) {
     return;
   }
   assertExitZero(result, `cleanup credential sanitization sandbox ${SANDBOX_NAME}`);
 }
🤖 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/credential-sanitization.test.ts` around lines 81 - 99,
Centralize sandbox-absence detection in a shared isSandboxAbsentError(text:
string) helper alongside resultText/assertExitZero in command.ts, preserving the
existing absence patterns and case-insensitive behavior. Update
HostCliClient.cleanupSandbox and cleanupCredentialSanitizationNemoClawSandbox to
call this helper instead of maintaining separate regular expressions, while
keeping their existing command invocation and failure handling unchanged.
test/e2e/live/gpu-e2e-helpers.ts (1)

57-60: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoff

Consider consolidating the repeated preCleanBestEffort helper.

This file's exported preCleanBestEffort(label, run) duplicates near-identical, differently-shaped local helpers reintroduced in several other test/helper files (some take only run, no label). Since the PR's stated goal is reducing duplicated bestEffort helpers, extracting one shared implementation (e.g., in a common fixtures module) would prevent further signature drift.

Also applies to: 118-140

🤖 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/gpu-e2e-helpers.ts` around lines 57 - 60, Consolidate the
exported preCleanBestEffort helper with the duplicated best-effort helpers used
across the test and fixture files by moving one shared implementation into the
common fixtures module. Standardize callers on a single signature, adapting
label handling as needed, and remove the local duplicate definitions while
preserving their existing cleanup behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/e2e/live/bedrock-runtime-compatible-anthropic.test.ts`:
- Around line 1344-1347: Reverse the cleanup registration order around
stopBedrockAdapter and the fake endpoint callback so cleanup LIFO executes
stopBedrockAdapter first and mock.close() afterward. Keep both existing cleanup
actions and their conditions unchanged.

In `@test/e2e/live/common-egress-agent.test.ts`:
- Around line 241-252: Update the cleanup callback around cleanupSandbox to
capture its validated ShellProbeResult instead of discarding the return value.
Populate summary.openshellDelete from that result, preserving the actual
exitCode, missingSandboxTolerated flag, and outputTail so already-absent
sandboxes are recorded as tolerated rather than as successful deletions.

In `@test/e2e/live/concurrent-gateway-ports.test.ts`:
- Around line 332-346: The cleanup trackers around gateway destruction and port
forwarding currently use HostCliClient, which invokes literal openshell instead
of the configured executable. Update these trackers to use a
SandboxClient-backed adapter, or update HostCliClient to resolve OPENSHELL_BIN
consistently with the surrounding setup and pre-clean flow, while preserving the
existing cleanup behavior.

In `@test/e2e/live/diagnostics.test.ts`:
- Around line 152-173: Update the teardown registrations around
cleanup.trackGateway and the OpenShell sandbox-delete cleanup.trackDisposable to
pass redactionValues: [apiKey], matching cleanup.trackSandbox. Ensure all three
cleanup trackers using cleanupEnv consistently redact the API key.

In `@test/e2e/live/gpu-double-onboard.test.ts`:
- Around line 219-235: Update the gateway cleanup flow around
cleanupRegistry.trackGateway and HostCliClient.cleanupGatewayRegistration to use
the configured OPENSHELL_BIN executable for both isCommandAvailable probing and
cleanup invocation, rather than the literal “openshell” command. Thread the
configured executable through gatewayCleanupOptions or the cleanup client so
probing and execution use the same path and cleanup still runs when the binary
is outside PATH.

In `@test/e2e/live/hermes-shields-config.test.ts`:
- Around line 179-182: Update the cleanup callback registered with
cleanupRegistry.trackDisposable to wrap artifacts.writeJson in a try/finally
block, ensuring fake.close() is always awaited even when writing
fake-openai-compatible-requests.json fails.

In `@test/e2e/live/hermes-slack-e2e-helpers.ts`:
- Around line 243-248: Update the pre-install gateway registrations using
cleanup.trackGateway so cleanupGatewayRegistration treats unavailable OpenShell
as an allowed absence rather than a failure. Apply the same availability-aware
cleanup configuration to the Hermes Slack flow and the matching Hermes Discord
and onboard-repair registration paths, while preserving cleanup failures when an
existing gateway cannot be removed.

In `@test/e2e/live/jetson-nvmap-gpu.test.ts`:
- Around line 119-141: Update the gateway cleanup probe inside
cleanupGatewayRegistration to use the same process.env.OPENSHELL_BIN ??
"openshell" command selection as the sandbox-delete guard, while preserving the
existing cleanup flow and options.

In `@test/e2e/live/messaging-compatible-endpoint-helpers.ts`:
- Around line 41-55: Update the PID cleanup logic in the messaging-compatible
endpoint helper to validate that the PID belongs to the OpenShell gateway using
/proc/$pid/cmdline or an equivalent gateway-specific marker before any kill or
kill -9 operation. Perform this ownership check for both termination attempts
and preserve the existing wait and exit behavior for an owned process.

In `@test/e2e/live/messaging-providers-helpers.ts`:
- Around line 618-628: Update the cleanup callback around the Docker removal in
cleanup to wrap the removal attempt and exit-code validation in try/finally, and
move fs.rmSync(dir, { recursive: true, force: true }) into the finally block so
the fake API scratch directory is always removed even when Docker cleanup
validation throws.

In `@test/e2e/live/openshell-gateway-upgrade.test.ts`:
- Around line 392-394: Update preCleanUpgradeGateway to capture and assert the
result returned by upgradeGatewayCleanupScript, matching the validation already
used in the teardown path at Lines 743-747. Ensure a non-zero cleanup result
fails before the upgrade retry proceeds.

In `@test/e2e/live/sandbox-survival.test.ts`:
- Around line 188-210: Update the cleanupSandbox call in the trackSandbox setup
to pass env: buildAvailabilityProbeEnv() alongside sandboxCleanupOptions. Keep
the availability probe and existing cleanup options unchanged so sandbox
deletion uses the same fixture PATH.

In `@test/e2e/live/snapshot-commands.test.ts`:
- Around line 62-68: Update the pre-clean callback in the snapshot command test
to invoke the configured NemoClaw executable through the existing HostCliClient
configuration rather than calling host.command directly. Preserve the current
destroy arguments, environment, artifactName, timeoutMs, and bestEffortPreclean
behavior.

In `@test/e2e/live/upgrade-stale-sandbox.test.ts`:
- Around line 61-74: Register the “remove stale OpenClaw test image” disposable
before the sandbox cleanup registrations so LIFO cleanup runs cleanupOldImage
only after the OpenShell deletion and sandbox destruction complete. Preserve the
existing artifact, environment, timeout, and precleanStaleSandbox behavior.

---

Outside diff comments:
In `@test/e2e/live/double-onboard.test.ts`:
- Around line 220-247: Make the teardown result assertion in stopGatewayRuntime
meaningful: either remove the stop.exitCode expectation, or change the script to
preserve and return a real failure status for teardown operations instead of
using unconditional exit 0 with broadly suppressed errors. Keep intentionally
best-effort cleanup behavior only where appropriate, while ensuring the chosen
outcome matches what the test claims to verify.

In `@test/e2e/live/rebuild-hermes.test.ts`:
- Around line 147-173: Update bestEffortPrecleanHermesResources so the pre-clean
shell receives SANDBOX_NAME mapped from the existing NEMOCLAW_SANDBOX_NAME value
in testEnv. Preserve the command references to SANDBOX_NAME and ensure the
exported environment variable targets the intended sandbox.

---

Nitpick comments:
In `@test/e2e/live/credential-sanitization.test.ts`:
- Around line 81-99: Centralize sandbox-absence detection in a shared
isSandboxAbsentError(text: string) helper alongside resultText/assertExitZero in
command.ts, preserving the existing absence patterns and case-insensitive
behavior. Update HostCliClient.cleanupSandbox and
cleanupCredentialSanitizationNemoClawSandbox to call this helper instead of
maintaining separate regular expressions, while keeping their existing command
invocation and failure handling unchanged.

In `@test/e2e/live/gpu-e2e-helpers.ts`:
- Around line 57-60: Consolidate the exported preCleanBestEffort helper with the
duplicated best-effort helpers used across the test and fixture files by moving
one shared implementation into the common fixtures module. Standardize callers
on a single signature, adapting label handling as needed, and remove the local
duplicate definitions while preserving their existing cleanup behavior.

In `@test/e2e/live/jetson-nvmap-gpu.test.ts`:
- Around line 119-181: Extract the repeated availability-check and early-return
logic into a small guarded cleanup helper near the cleanup registrations,
accepting the probe command, probe options, and cleanup action. Update the
gateway, OpenShell sandbox, and nemoclaw sandbox registrations to use this
helper while preserving each existing command source and cleanup delegate,
including the current OPENSHELL_BIN behavior.
🪄 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: 08b13b04-8445-4162-9f21-2053c6dc05fc

📥 Commits

Reviewing files that changed from the base of the PR and between e7e2ce6 and 6870ecc.

📒 Files selected for processing (76)
  • test/e2e/fixtures/cleanup.ts
  • test/e2e/fixtures/clients/host.ts
  • test/e2e/fixtures/clients/sandbox.ts
  • test/e2e/live/agent-turn-latency-helpers.ts
  • test/e2e/live/agent-turn-latency.test.ts
  • test/e2e/live/bedrock-runtime-compatible-anthropic.test.ts
  • test/e2e/live/brave-search-helpers.ts
  • test/e2e/live/brave-search.test.ts
  • test/e2e/live/channels-add-remove.test.ts
  • test/e2e/live/channels-stop-start-helpers.ts
  • test/e2e/live/cloud-inference.test.ts
  • test/e2e/live/cloud-onboard.test.ts
  • test/e2e/live/common-egress-agent.test.ts
  • test/e2e/live/concurrent-gateway-ports.test.ts
  • test/e2e/live/credential-migration.test.ts
  • test/e2e/live/credential-sanitization.test.ts
  • test/e2e/live/cron-preflight-inference-local.test.ts
  • test/e2e/live/device-auth-health-helpers.ts
  • test/e2e/live/device-auth-health.test.ts
  • test/e2e/live/diagnostics.test.ts
  • test/e2e/live/double-onboard.test.ts
  • test/e2e/live/full-e2e.test.ts
  • test/e2e/live/gateway-health-honest.test.ts
  • test/e2e/live/gpu-double-onboard.test.ts
  • test/e2e/live/gpu-e2e-helpers.ts
  • test/e2e/live/gpu-e2e.test.ts
  • test/e2e/live/hermes-discord.test.ts
  • test/e2e/live/hermes-e2e.test.ts
  • test/e2e/live/hermes-gpu-startup.test.ts
  • test/e2e/live/hermes-inference-switch-helpers.ts
  • test/e2e/live/hermes-inference-switch.test.ts
  • test/e2e/live/hermes-shields-config.test.ts
  • test/e2e/live/hermes-slack-e2e-helpers.ts
  • test/e2e/live/issue-2478-crash-loop-recovery.test.ts
  • test/e2e/live/issue-4462-scope-upgrade-approval.test.ts
  • test/e2e/live/jetson-nvmap-gpu.test.ts
  • test/e2e/live/kimi-inference-compat-helpers.ts
  • test/e2e/live/kimi-inference-compat.test.ts
  • test/e2e/live/mcp-bridge.test.ts
  • test/e2e/live/messaging-compatible-endpoint-helpers.ts
  • test/e2e/live/messaging-compatible-endpoint.test.ts
  • test/e2e/live/messaging-providers-helpers.ts
  • test/e2e/live/messaging-providers.test.ts
  • test/e2e/live/model-router-provider-routed-inference.test.ts
  • test/e2e/live/network-policy.test.ts
  • test/e2e/live/ollama-auth-proxy.test.ts
  • test/e2e/live/onboard-repair.test.ts
  • test/e2e/live/onboard-resume.test.ts
  • test/e2e/live/openclaw-discord-pairing.test.ts
  • test/e2e/live/openclaw-inference-switch.test.ts
  • test/e2e/live/openclaw-pairing-helpers.ts
  • test/e2e/live/openclaw-plugin-runtime-exdev.test.ts
  • test/e2e/live/openclaw-skill-cli.test.ts
  • test/e2e/live/openclaw-slack-pairing.test.ts
  • test/e2e/live/openshell-gateway-upgrade-helpers.ts
  • test/e2e/live/openshell-gateway-upgrade.test.ts
  • test/e2e/live/overlayfs-autofix.test.ts
  • test/e2e/live/phase6-messaging-helpers.ts
  • test/e2e/live/rebuild-hermes.test.ts
  • test/e2e/live/rebuild-openclaw.test.ts
  • test/e2e/live/sandbox-rebuild.test.ts
  • test/e2e/live/sandbox-rlimits-connect.test.ts
  • test/e2e/live/sandbox-survival.test.ts
  • test/e2e/live/sessions-agents-cli.test.ts
  • test/e2e/live/shields-config.test.ts
  • test/e2e/live/skill-agent.test.ts
  • test/e2e/live/snapshot-commands.test.ts
  • test/e2e/live/spark-install.test.ts
  • test/e2e/live/state-backup-restore.test.ts
  • test/e2e/live/telegram-injection.test.ts
  • test/e2e/live/token-rotation.test.ts
  • test/e2e/live/tunnel-lifecycle-helpers.ts
  • test/e2e/live/upgrade-stale-sandbox-helpers.ts
  • test/e2e/live/upgrade-stale-sandbox.test.ts
  • test/e2e/support/e2e-cleanup-resources.test.ts
  • test/e2e/support/e2e-clients.test.ts

Comment thread test/e2e/live/bedrock-runtime-compatible-anthropic.test.ts
Comment thread test/e2e/live/common-egress-agent.test.ts
Comment thread test/e2e/live/concurrent-gateway-ports.test.ts
Comment thread test/e2e/live/diagnostics.test.ts
Comment thread test/e2e/live/gpu-double-onboard.test.ts
Comment thread test/e2e/live/messaging-providers-helpers.ts Outdated
Comment thread test/e2e/live/openshell-gateway-upgrade.test.ts
Comment thread test/e2e/live/sandbox-survival.test.ts
Comment thread test/e2e/live/snapshot-commands.test.ts Outdated
Comment thread test/e2e/live/upgrade-stale-sandbox.test.ts
Signed-off-by: Carlos Villela <cvillela@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: 2

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

Inline comments:
In `@test/e2e/live/overlayfs-autofix-cleanup.ts`:
- Around line 25-71: Split cleanupOverlayArtifacts into independently tracked
disposable steps for gateway container removal, patched-image listing/removal,
and onboard.lock deletion. Update the surrounding trackDisposable registration
so CleanupRegistry.runAll() isolates failures and continues executing later
cleanup steps; preserve the existing absence handling, assertions, command
options, and lock-file removal behavior.

In `@test/e2e/support/overlayfs-autofix-outcome.test.ts`:
- Around line 108-136: Restore the fs.rmSync spy created in the test “tears down
sandbox resources before gateway artifacts in LIFO order (`#6352`)” after
assertions complete, using the repository’s established mock-restoration pattern
so the stub cannot affect later tests.
🪄 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: ed80f5d9-02a9-4e62-ab59-a60d0476ddb1

📥 Commits

Reviewing files that changed from the base of the PR and between 939f59e and 3af19e5.

📒 Files selected for processing (25)
  • test/e2e/fixtures/cleanup-resources.ts
  • test/e2e/live/bedrock-runtime-compatible-anthropic.test.ts
  • test/e2e/live/cloud-inference.test.ts
  • test/e2e/live/common-egress-agent.test.ts
  • test/e2e/live/credential-migration.test.ts
  • test/e2e/live/credential-sanitization.test.ts
  • test/e2e/live/gateway-health-honest.test.ts
  • test/e2e/live/gpu-double-onboard.test.ts
  • test/e2e/live/hermes-gpu-startup.test.ts
  • test/e2e/live/hermes-shields-config.test.ts
  • test/e2e/live/jetson-nvmap-gpu.test.ts
  • test/e2e/live/mcp-bridge.test.ts
  • test/e2e/live/onboard-repair.test.ts
  • test/e2e/live/onboard-resume.test.ts
  • test/e2e/live/overlayfs-autofix-cleanup.ts
  • test/e2e/live/overlayfs-autofix.test.ts
  • test/e2e/live/rebuild-hermes.test.ts
  • test/e2e/live/rebuild-openclaw.test.ts
  • test/e2e/live/sandbox-survival.test.ts
  • test/e2e/live/sessions-agents-cli.test.ts
  • test/e2e/live/shields-config.test.ts
  • test/e2e/live/token-rotation.test.ts
  • test/e2e/mock-parity.json
  • test/e2e/support/e2e-cleanup-resources.test.ts
  • test/e2e/support/overlayfs-autofix-outcome.test.ts
🚧 Files skipped from review as they are similar to previous changes (14)
  • test/e2e/live/onboard-repair.test.ts
  • test/e2e/live/hermes-shields-config.test.ts
  • test/e2e/live/sessions-agents-cli.test.ts
  • test/e2e/live/jetson-nvmap-gpu.test.ts
  • test/e2e/live/token-rotation.test.ts
  • test/e2e/live/common-egress-agent.test.ts
  • test/e2e/live/gpu-double-onboard.test.ts
  • test/e2e/live/cloud-inference.test.ts
  • test/e2e/live/shields-config.test.ts
  • test/e2e/live/rebuild-hermes.test.ts
  • test/e2e/live/rebuild-openclaw.test.ts
  • test/e2e/live/bedrock-runtime-compatible-anthropic.test.ts
  • test/e2e/live/onboard-resume.test.ts
  • test/e2e/live/hermes-gpu-startup.test.ts

Comment thread test/e2e/live/overlayfs-autofix-cleanup.ts Outdated
Comment thread test/e2e/support/overlayfs-autofix-outcome.test.ts
cv added 2 commits July 12, 2026 13:22
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
@cv
cv merged commit 5d0ea55 into main Jul 12, 2026
56 of 59 checks passed
@cv
cv deleted the codex/issue-6352-cleanup-migrations branch July 12, 2026 21:46
cv pushed a commit that referenced this pull request Jul 14, 2026
<!-- markdownlint-disable MD041 -->
## Summary

Addresses the five release/nightly E2E blockers according to the
evidence each failure left behind. The OpenShell version-pin fixture now
supports the installer's archive validation calls, the Shields target
restores lockdown after its intentional failure assertion, MCP patch
failures preserve their real sandbox phase, and the Hermes rebuild
target emits secret-safe phase and host-resource heartbeats.

The Hermes failure was not the fixture's 45-minute rebuild timeout.
GitHub ended the job after about 50 minutes because the hosted runner
lost communication; the rebuild command began later in the scenario and
could not yet have reached its own timeout. No final logs or artifacts
survived, so the underlying memory, disk, CPU, network, or
runner-termination trigger cannot be recovered from that run.

Follow-up to #6744 and #6724.

The source nightly had seven red jobs. A same-SHA rerun cleared the two
accepted flakes, `hermes-shields-config` and `gateway-guard-recovery`,
leaving five release blockers: `openshell-version-pin`,
`shields-config`, `mcp-bridge`, `rebuild-hermes`, and
`channels-stop-start (hermes)`. This PR fixes the two reproducible
fixture defects, repairs the MCP phase evidence, and instruments the
Hermes rebuild runner loss. `mcp-bridge` failed when Docker `stop`
exceeded its 30-second client timeout after a successful image build,
while `channels-stop-start (hermes)` was externally canceled before any
assertion or artifact; neither has evidence for a causal retry or
timeout change, so both still require a fresh green candidate run or a
reproducible product defect.

## Changes

- Model `tar -tzf`, `tar -tvzf`, and extraction in the hermetic
OpenShell version-pin fixture so the installer can validate fake release
archives before extracting them.
- Restore Shields lockdown after the duplicate-down rejection assertion
and register a strict relock cleanup that reports a failed command or
missing lockdown confirmation before continuing destruction.
- Parse modern `NAME CREATED PHASE` OpenShell rows with the shared
sandbox-list parser so MCP Docker-patch diagnostics report
`Provisioning` instead of the creation date, while retaining the
canonical terminal `Evicted` phase.
- Emit a one-minute Hermes rebuild heartbeat from setup through cleanup
with the active phase, child-output age, memory, process RSS, workspace
disk, and load average. The output observer records timestamps only and
never forwards command output or credentials.
- Map the changed OpenShell and Hermes live targets to their fast PR
coverage in the mock/live parity manifest.
- Keep installer recovery behavior, the 30-second destructive
Docker-operation timeout, Shields behavior, sandbox destruction, and
Hermes rebuild behavior unchanged; the 90-minute workflow limit and
45-minute rebuild-command limit are unchanged.
- Keep the underlying `mcp-bridge` Docker timeout and
`channels-stop-start (hermes)` cancellation as explicit green-evidence
blockers instead of masking them with retries.

## 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: all changes are internal E2E
fixture, diagnostic, and parity corrections; no user-facing CLI, policy,
lifecycle, installer, or Hermes contract changes.
- [x] 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: the Shields security
E2E target and secret-safe Hermes diagnostics changed; review is pending
on the current revision and no waiver is requested.
- [ ] Non-success, skipped, or missing CI check accepted by maintainer —
check name, approval link, and follow-up issue: no waiver is requested;
required PR CI is pending.

## 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 — OpenShell version-pin live fixture
(3/3); focused archive-safety installer tests (9/9); MCP Docker-patch
and shared phase parsing (29/29); Hermes progress and cleanup tests
(15/15); mock/live parity guard; Vitest project membership; source-shape
check; CLI typecheck and build; Shields and Hermes live target
collection.
- [ ] Applicable broad gate passed — `npm test` for broad
runtime/test-harness changes; `npm run check` for repo-wide
validation/coverage changes — command/result: not applicable to narrow
live-target fixture and diagnostic changes. An exploratory local
E2E-support run passed 979 tests and hit 15 environment-specific
failures (macOS Bash behavior, Node 26 warning output, and nested-run
timeouts); required Linux CI remains authoritative.
- [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: Charan Jagwani <cjagwani@nvidia.com>


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

## Summary by CodeRabbit

- **Bug Fixes**
- Improved sandbox status detection across modern list output formats,
including evicted sandboxes.
- Improved cleanup behavior so shield restoration failures are reported
while subsequent cleanup continues.
  - Strengthened shield-state handling during test teardown.

- **User Experience**
- Added clearer progress and activity reporting during lengthy Hermes
rebuild operations.

- **Tests**
- Expanded coverage for installer version pinning, sandbox lifecycle
states, cleanup ordering, and rebuild progress reporting.

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

---------

Signed-off-by: Charan Jagwani <cjagwani@nvidia.com>
@wscurran wscurran added area: ci CI workflows, checks, release automation, or GitHub Actions area: e2e End-to-end tests, nightly failures, or validation infrastructure refactor PR restructures code without intended behavior change labels Jul 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: ci CI workflows, checks, release automation, or GitHub Actions area: e2e End-to-end tests, nightly failures, or validation infrastructure refactor PR restructures code without intended behavior change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

refactor(e2e): track sandbox and gateway cleanup as resources Epic: Deduplicate and harden the Vitest E2E test infrastructure

2 participants