Skip to content

test(cli): split oversized CLI suites - #4898

Merged
cv merged 14 commits into
mainfrom
codex/cli-sandbox-mutation-split
Jun 7, 2026
Merged

test(cli): split oversized CLI suites#4898
cv merged 14 commits into
mainfrom
codex/cli-sandbox-mutation-split

Conversation

@cv

@cv cv commented Jun 6, 2026

Copy link
Copy Markdown
Collaborator

Summary

Splits the oversized test/cli.test.ts catch-all into focused test/cli/ suites following the #4892 parallelization plan. The migration keeps the existing assertions mechanical and verifiable, then removes test/cli.test.ts so future CLI tests have to land in a specific destination.

Related Issue

Refs #4892

Changes

  • Move sandbox command mutation and parser-dispatch tests into test/cli/sandbox-mutations.test.ts.
  • Move host-alias mutation, dry-run, retry, and Docker probe classification tests into test/cli/sandbox-host-aliases.test.ts.
  • Move shields and snapshot command dispatch tests into test/cli/snapshot-shields.test.ts.
  • Move start/onboard/setup/setup-spark/deploy/debug parser and stale-default tests into test/cli/onboard-debug.test.ts.
  • Move logs, audit enablement, follow-mode child-process, bridge-status helper, plain-log, and SIGINT tests into test/cli/logs.test.ts.
  • Move tunnel, credentials, maintenance, and skill install/plugin-marker tests into test/cli/tunnel-credentials-maintenance-skills.test.ts.
  • Move status, sandbox status JSON, gateway health, Docker failure-layer, and status validation tests into test/cli/status-health.test.ts.
  • Move connect, probe-only recovery, readiness polling, SSH fallback, registry/list recovery, and sandbox-not-found recovery tests into test/cli/connect-recovery.test.ts.
  • Move gateway lifecycle, status reconciliation, local inference warning, live agent version, and orphan registry tests into test/cli/status-gateway-lifecycle.test.ts.
  • Move list, inference get/set routing, alias branding, and list JSON tests into test/cli/list-inference.test.ts.
  • Move root dispatch, help/version, unknown-command, typo, preflight, and command-order tests into test/cli/dispatch-basics.test.ts.
  • Move gateway-token and doctor health/PID checks into test/cli/doctor-gateway-token.test.ts.
  • Move destroy/gateway cleanup policy tests into test/cli/destroy-gateway-cleanup.test.ts.
  • Remove test/cli.test.ts after the final extraction.

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)

Verification

  • npx prek run --all-files passes
  • npm test passes
  • npx vitest run --project cli test/cli.test.ts test/cli/tunnel-credentials-maintenance-skills.test.ts passes
  • npx vitest run --project cli test/cli.test.ts test/cli/status-health.test.ts passes
  • npx vitest run --project cli test/cli.test.ts test/cli/connect-recovery.test.ts passes
  • npx vitest run --project cli test/cli.test.ts test/cli/status-gateway-lifecycle.test.ts passes
  • npx vitest run --project cli test/cli.test.ts test/cli/list-inference.test.ts passes
  • npx vitest run --project cli test/cli.test.ts test/cli/dispatch-basics.test.ts passes
  • npx vitest run --project cli test/cli.test.ts test/cli/doctor-gateway-token.test.ts passes
  • npx vitest run --project cli test/cli/*.test.ts passes
  • npm run typecheck:cli passes
  • Tests added or updated for new or changed behavior
  • No secrets, API keys, or credentials committed
  • Docs updated for user-facing behavior changes
  • 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

  • Tests
    • Expanded CLI test coverage across many areas (host-aliases, sandbox mutations, snapshot/shields, onboard/debug, logs, status health & gateway lifecycle, connect recovery, destroy gateway cleanup, list/inference, doctor/gateway-token, tunnel/credentials/maintenance, dispatch basics)
    • Added dry-run, retry, validation, recovery, streaming, signal, help/usage, JSON output, and error-case scenarios; reorganized/relocated several tests for clarity
    • Extended test helpers to support configurable gateway-start markers in log setups

@cv cv self-assigned this Jun 6, 2026
@coderabbitai

coderabbitai Bot commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 2fd392eb-2a08-4634-b3c8-2b14781a3a08

📥 Commits

Reviewing files that changed from the base of the PR and between 03bc2b1 and 92b309b.

📒 Files selected for processing (1)
  • test/cli/sandbox-mutations.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/cli/sandbox-mutations.test.ts

📝 Walkthrough

Walkthrough

Splits monolithic CLI tests into focused Vitest suites and adds end-to-end tests for host-aliases, sandbox mutations, snapshot/shields, onboard/debug, logs streaming and lifecycle, status/health, connect recovery, list/inference, destroy/gateway cleanup, and maintenance; also extends logs test helper and reorders a few imports.

Changes

CLI Test Suite Reorganization and Expansion

Layer / File(s) Summary
Host-aliases CLI command test suite
test/cli/sandbox-host-aliases.test.ts
hosts-add, hosts-list, hosts-remove tests covering JSON-patch payloads, resourceVersion guarding & retry, --dry-run previews, driver gating for non-legacy openshellDriver, legacy gateway docker probe ordering, and docker-probe failure classification.
Sandbox mutations and CLI dispatch test suite
test/cli/sandbox-mutations.test.ts
CLI dispatch/help grammar checks, policy/channel mutation dry-run behavior and messaging, regression for missing sandboxes in registry, native sandbox subcommand forms, and parser-owned validation rejecting missing/invalid flags before dispatch.
Shields and snapshot commands test suite
test/cli/snapshot-shields.test.ts
Validates alpha shields and alpha snapshot --help output, usage examples, snapshot list empty-case messaging, and failure behavior for unknown snapshot subcommands.
Onboard and debug CLI test suite
test/cli/onboard-debug.test.ts
Covers start, onboard/setup aliases, deploy, and debug parsing and behaviors: help/errors, --resume non-interactive guards, GPU flag validation, Linux dmesg handling, sandbox targeting, stale-registry warnings, and tarball creation guards.
Logs end-to-end and lifecycle tests
test/cli/logs.test.ts
End-to-end logs behavior: routing to OpenClaw/OpenShell, --tail/--follow/--since semantics, audit enable ordering and timeout handling, streaming start-order guarantees, subprocess lifecycle (SIGTERM/SIGINT), sandbox-exec wiring, and pass-through behavior.
Status & health reporting tests
test/cli/status-health.test.ts
status and sandbox <name> status human and --json tests: schema/credential redaction, gateway-unhealthy path, preflight failure layers (docker_unreachable, sandbox_container_stopped, dashboard port conflict), paused-container hints, rpcIssue handling, and help/dispatch validation.
List / inference tests
test/cli/list-inference.test.ts
inference set/get and list tests including OpenShell redirection, branded help output, JSON inventory shapes when registry is present, and parsing validation for empty provider values.
Connect recovery tests
test/cli/connect-recovery.test.ts
Connect dispatch and recovery flows: duplicate port-forward prevention, --probe-only recovery/no-SSH, SSH fallback scenarios, Hermes/agent SSH recovery, sandbox readiness waits, recovery guidance messaging, and list/onboard-session recovery behaviors.
Destroy / gateway cleanup tests
test/cli/destroy-gateway-cleanup.test.ts
destroy behavior and gateway cleanup: default gateway preservation, --cleanup-gateway and NEMOCLAW_CLEANUP_GATEWAY opt-in teardown, platform-dependent teardown commands, failure-mode behavior, already-missing handling, and provider deletion assertions.
Tunnel / credentials / maintenance / skill install tests
test/cli/tunnel-credentials-maintenance-skills.test.ts
Help/usage and dispatch tests for tunnel, credentials, maintenance commands, and alpha skill install; required-arg validation and plugin-shaped directory rejection.
Doctor & gateway-token tests
test/cli/doctor-gateway-token.test.ts, relocated hunks in test/cli.test.ts
gateway-token --help formatting and doctor JSON/human tests including not-ready sandbox failures, Docker vs Kubernetes driver probe behaviors, shields state messaging, gateway mismatch avoidance, and cloudflared PID stale/acceptance checks.
Test helpers: logs setup change
test/cli/helpers.ts
createLogsTestSetup extended with an options parameter allowing injection of a gatewayStartedMarker to emit gateway-started lines in openshell test stubs.
Test suite reorganization
test/cli.test.ts
Minor import reorder and relocation of contiguous gateway-token/doctor tests in the original monolithic test file; no exported API changes.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

Possibly related PRs

Suggested labels

area: cli, area: ci, chore

Suggested reviewers

  • prekshivyas
  • cjagwani

"A rabbit hops through tests at play,
I nudge the stubs so bugs won't stay,
Host aliases and logs align,
Sandboxes safe, snapshots shine,
Hooray — the CLI's prepared to sway!"

🚥 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'test(cli): split oversized CLI suites' accurately summarizes the main change: splitting a large monolithic test file into focused test suites.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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/cli-sandbox-mutation-split

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

@github-actions

github-actions Bot commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

E2E Advisor Recommendation

Required E2E: None
Optional E2E: None

Workflow run

Full advisor summary

E2E Recommendation Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E

  • None. No E2E is recommended because this PR changes only CLI test files and test helpers. These changes can affect local/CI test organization and assertions, but they do not change NemoClaw runtime behavior or user flows.

Optional E2E

  • None.

New E2E recommendations

  • None.

@github-actions

github-actions Bot commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

E2E Scenario Advisor Recommendation

Required scenario E2E: None
Optional scenario E2E: None

Workflow run

Full scenario advisor summary

E2E Scenario Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required scenario E2E

  • None. Changes are limited to non-scenario CLI tests under test/cli*. No files under test/e2e-scenario/, scenario workflows, or other directly scenario-relevant paths changed, so scenario E2E is not affected.

Optional scenario E2E

  • None.

Relevant changed files

  • None.

@github-actions

github-actions Bot commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor

Findings: 0 needs attention, 0 worth checking, 0 nice ideas
Since last review: 0 prior items resolved, 0 still apply, 0 new items found

Consider writing more tests for

Workflow run details

This is an automated advisory review. A human maintainer must make 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.

🧹 Nitpick comments (1)
test/cli/sandbox-mutations.test.ts (1)

173-181: ⚡ Quick win

Use consistent exit code assertions for parser validation failures.

Lines 176 and 181 both test parser-owned validation failures, but use different assertions:

  • Line 176: expect(missingPolicyFile.code).not.toBe(0)
  • Line 181: expect(missingChannel.code).toBe(PARSER_EXIT_CODE)

For consistency and precision, consider using toBe(PARSER_EXIT_CODE) for both, since PARSER_EXIT_CODE is specifically defined for parser validation failures.

♻️ Suggested change for consistency
       const missingPolicyFile = runWithEnv("alpha policy-add --from-file 2>&1", {
         HOME: home,
       });
-      expect(missingPolicyFile.code).not.toBe(0);
+      expect(missingPolicyFile.code).toBe(PARSER_EXIT_CODE);
       expect(missingPolicyFile.out).toContain("--from-file");
🤖 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/cli/sandbox-mutations.test.ts` around lines 173 - 181, Change the loose
assertion on the parser validation for the policy file to use the explicit
PARSER_EXIT_CODE constant: replace the
`expect(missingPolicyFile.code).not.toBe(0)` check with an equality check
against PARSER_EXIT_CODE so it matches the subsequent loop assertions; locate
the test that calls runWithEnv (variable names missingPolicyFile and
missingChannel) in sandbox-mutations.test.ts and update the assertion to
`expect(missingPolicyFile.code).toBe(PARSER_EXIT_CODE)`.
🤖 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 `@test/cli/sandbox-mutations.test.ts`:
- Around line 173-181: Change the loose assertion on the parser validation for
the policy file to use the explicit PARSER_EXIT_CODE constant: replace the
`expect(missingPolicyFile.code).not.toBe(0)` check with an equality check
against PARSER_EXIT_CODE so it matches the subsequent loop assertions; locate
the test that calls runWithEnv (variable names missingPolicyFile and
missingChannel) in sandbox-mutations.test.ts and update the assertion to
`expect(missingPolicyFile.code).toBe(PARSER_EXIT_CODE)`.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: b2e8ace7-a66b-4e09-ba21-b242b3a18f35

📥 Commits

Reviewing files that changed from the base of the PR and between 8d9c573 and d66709b.

📒 Files selected for processing (4)
  • test/cli.test.ts
  • test/cli/sandbox-host-aliases.test.ts
  • test/cli/sandbox-mutations.test.ts
  • test/cli/snapshot-shields.test.ts
💤 Files with no reviewable changes (1)
  • test/cli.test.ts

@cv cv changed the title test(cli): split sandbox mutation suites test(cli): split oversized CLI suites Jun 6, 2026
@cv cv mentioned this pull request Jun 6, 2026
2 tasks

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

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

Inline comments:
In `@test/cli/logs.test.ts`:
- Around line 216-239: The test "starts OpenClaw logs before enabling audit logs
for logs --follow" currently doesn't assert that the OpenClaw (sandbox exec -n
alpha -- tail -n 200 -f /tmp/gateway.log) start occurs before the audit enable
(settings set alpha --key ocsf_json_enabled --value true); update the test (and
the createLogsTestSetup stub) so the OpenClaw stub emits a deterministic
"gateway-started" marker (e.g., write a known marker string to the simulated
output or a marker file when the sandbox exec stub runs) and then assert that
this marker appears in the recorded calls or outputs before the audit enable
call completes by checking that the index/position of the OpenClaw
"gateway-started" marker is less than the index of the settings set alpha --key
ocsf_json_enabled --value true call, while keeping the existing assertions for
openshell logs ordering.
🪄 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: b2817218-80c4-4ea9-9c0a-57b3f7bb0930

📥 Commits

Reviewing files that changed from the base of the PR and between ab3fc6c and cb4d926.

📒 Files selected for processing (2)
  • test/cli.test.ts
  • test/cli/logs.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/cli.test.ts

Comment thread test/cli/logs.test.ts

@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 (5)
test/cli/list-inference.test.ts (1)

179-253: 💤 Low value

Consider adding try/finally cleanup for consistency.

This test creates a temporary directory but doesn't clean it up. Adding a try/finally block (similar to the pattern in test/cli/dispatch-basics.test.ts lines 215-273) would prevent test artifact accumulation.

♻️ Suggested cleanup pattern

Wrap the test body starting after line 180 in a try block and add:

  } finally {
    fs.rmSync(home, { recursive: true, force: true });
  }
🤖 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/cli/list-inference.test.ts` around lines 179 - 253, The test "list
--json emits structured sandbox details" creates a temporary home dir (variable
home) but doesn't remove it; wrap the test body after creating home in a try {
... } finally { fs.rmSync(home, { recursive: true, force: true }); } block so
the temp directory is always cleaned up (place the existing assertions and
runWithEnv(...) call inside the try); reference the test function name and the
home variable to locate where to add the try/finally.
test/cli/dispatch-basics.test.ts (3)

107-125: 💤 Low value

Consider adding try/finally cleanup for consistency.

This test creates a temporary directory but doesn't clean it up. While the OS typically purges tmp directories periodically, other tests in this file (e.g., lines 166-177, 215-273) use try/finally blocks for immediate cleanup. Adding cleanup here would improve consistency and prevent test artifact accumulation during local development.

♻️ Suggested cleanup pattern
 it("bare unknown name surfaces sandbox-not-found (`#2164`)", testTimeoutOptions(35_000), () => {
   const home = fs.mkdtempSync(path.join(os.tmpdir(), "nemoclaw-cli-unknown-sandbox-"));
-  const localBin = path.join(home, "bin");
-  fs.mkdirSync(localBin, { recursive: true });
-  fs.writeFileSync(path.join(localBin, "openshell"), "#!/usr/bin/env bash\nexit 1\n", {
-    mode: 0o755,
-  });
+  try {
+    const localBin = path.join(home, "bin");
+    fs.mkdirSync(localBin, { recursive: true });
+    fs.writeFileSync(path.join(localBin, "openshell"), "#!/usr/bin/env bash\nexit 1\n", {
+      mode: 0o755,
+    });

-  const r = runWithEnv(
-    "boguscmd",
-    {
-      HOME: home,
-      PATH: `${localBin}:${process.env.PATH || ""}`,
-    },
-    execTimeout(30_000),
-  );
-  expect(r.code).toBe(1);
-  expect(r.out.includes("Sandbox 'boguscmd' does not exist")).toBeTruthy();
+    const r = runWithEnv(
+      "boguscmd",
+      {
+        HOME: home,
+        PATH: `${localBin}:${process.env.PATH || ""}`,
+      },
+      execTimeout(30_000),
+    );
+    expect(r.code).toBe(1);
+    expect(r.out.includes("Sandbox 'boguscmd' does not exist")).toBeTruthy();
+  } finally {
+    fs.rmSync(home, { recursive: true, force: true });
+  }
 });
🤖 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/cli/dispatch-basics.test.ts` around lines 107 - 125, The test "bare
unknown name surfaces sandbox-not-found" creates a temp dir with fs.mkdtempSync
assigned to home and writes localBin/openshell but doesn't remove it; wrap the
test body that uses home/localBin and runWithEnv in a try/finally and in the
finally call fs.rmSync(home, { recursive: true, force: true }) (or the project's
existing cleanup helper) so the temporary directory and created files are
removed after the assertion; update the test function surrounding the uses of
home, localBin, and runWithEnv to ensure cleanup always runs.

276-296: 💤 Low value

Consider adding try/finally cleanup for consistency.

Same cleanup suggestion - adding a try/finally block would prevent test artifact accumulation and match the pattern used in other tests in this file.

🤖 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/cli/dispatch-basics.test.ts` around lines 276 - 296, Wrap the test body
in a try/finally: keep the existing setup (creating home, localBin,
writeSandboxRegistry, writing openshell and calling runWithEnv with "hermes
connect alpha") inside the try block, and in the finally block remove the
temporary directory created (home) to clean up artifacts (e.g., call
fs.rmSync(home, { recursive: true, force: true }) or equivalent). This ensures
the test "explains sandbox connect command order when the sandbox name is last"
cleans up created files after runWithEnv and matches the pattern used by other
tests.

180-212: 💤 Low value

Consider adding try/finally cleanup for consistency.

Same cleanup suggestion as the previous test - adding a try/finally block would match the cleanup pattern used elsewhere in this file.

🤖 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/cli/dispatch-basics.test.ts` around lines 180 - 212, Wrap the test body
that creates the temporary HOME and localBin in a try/finally so the temp
directory is always removed; specifically, after creating home and localBin and
writing the openshell stub, run the existing assertions inside a try block and
in finally call fs.rmSync(home, { recursive: true, force: true }) (or the same
cleanup used elsewhere) to mirror the pattern used in other tests and ensure
cleanup even on assertion failures; keep runWithEnv("liost", {...}), the
openshell file creation, and the expect(...) assertions inside the try so they
execute before cleanup.
test/cli/destroy-gateway-cleanup.test.ts (1)

12-547: ⚡ Quick win

Consider extracting common test setup to reduce duplication.

All 8 tests repeat nearly identical setup patterns (~400+ lines total):

  • Creating temp directories and paths
  • Writing sandboxes.json registry
  • Creating fake openshell and docker executables
  • Running destroy command and reading logs

The variation is limited to:

  • Registry contents (number/names of sandboxes)
  • Stub command responses (list output, delete behavior)
  • Optional stubs (pgrep/lsof in tests 2-3)

Extracting a parameterized helper would improve maintainability and reduce the test file size significantly.

♻️ Example refactor pattern
function setupDestroyTest(opts: {
  tmpPrefix: string;
  sandboxes: Record<string, any>;
  openshellBehavior?: {
    listResponse?: string;
    deleteError?: string;
  };
  includePgrepLsof?: boolean;
}) {
  const home = fs.mkdtempSync(path.join(os.tmpdir(), opts.tmpPrefix));
  const localBin = path.join(home, "bin");
  const registryDir = path.join(home, ".nemoclaw");
  const openshellLog = path.join(home, "openshell.log");
  const bashLog = path.join(home, "docker.log");
  
  fs.mkdirSync(localBin, { recursive: true });
  fs.mkdirSync(registryDir, { recursive: true });
  
  fs.writeFileSync(
    path.join(registryDir, "sandboxes.json"),
    JSON.stringify({ sandboxes: opts.sandboxes, defaultSandbox: Object.keys(opts.sandboxes)[0] }),
    { mode: 0o600 }
  );
  
  // ... create stubs based on opts.openshellBehavior, opts.includePgrepLsof
  
  return { home, localBin, openshellLog, bashLog };
}

Then each test becomes:

it("preserves the gateway runtime by default...", () => {
  const { home, localBin, openshellLog, bashLog } = setupDestroyTest({
    tmpPrefix: "nemoclaw-cli-destroy-last-",
    sandboxes: { alpha: { name: "alpha", model: "test-model", ... } }
  });
  
  const r = runWithEnv("alpha destroy -y", {
    HOME: home,
    PATH: `${localBin}:${process.env.PATH || ""}`,
  });
  
  expect(r.code).toBe(0);
  // ... assertions
});
🤖 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/cli/destroy-gateway-cleanup.test.ts` around lines 12 - 547, Extract the
repeated test setup into a single helper (e.g. setupDestroyTest) and use it from
each it(...) block: factor out creation of temp dirs, localBin, registryDir,
openshellLog, bashLog, writing sandboxes.json, and generating stub executables
(openshell, docker, optional pgrep/lsof), returning {home, localBin,
openshellLog, bashLog}; update tests to call runWithEnv with the returned home
and PATH and only supply per-test variations (sandboxes, openshell behavior,
includePgrepLsof) so tests use runWithEnv, expects, and file reads unchanged
while removing the duplicated setup code.
🤖 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 `@test/cli/destroy-gateway-cleanup.test.ts`:
- Around line 12-547: Extract the repeated test setup into a single helper (e.g.
setupDestroyTest) and use it from each it(...) block: factor out creation of
temp dirs, localBin, registryDir, openshellLog, bashLog, writing sandboxes.json,
and generating stub executables (openshell, docker, optional pgrep/lsof),
returning {home, localBin, openshellLog, bashLog}; update tests to call
runWithEnv with the returned home and PATH and only supply per-test variations
(sandboxes, openshell behavior, includePgrepLsof) so tests use runWithEnv,
expects, and file reads unchanged while removing the duplicated setup code.

In `@test/cli/dispatch-basics.test.ts`:
- Around line 107-125: The test "bare unknown name surfaces sandbox-not-found"
creates a temp dir with fs.mkdtempSync assigned to home and writes
localBin/openshell but doesn't remove it; wrap the test body that uses
home/localBin and runWithEnv in a try/finally and in the finally call
fs.rmSync(home, { recursive: true, force: true }) (or the project's existing
cleanup helper) so the temporary directory and created files are removed after
the assertion; update the test function surrounding the uses of home, localBin,
and runWithEnv to ensure cleanup always runs.
- Around line 276-296: Wrap the test body in a try/finally: keep the existing
setup (creating home, localBin, writeSandboxRegistry, writing openshell and
calling runWithEnv with "hermes connect alpha") inside the try block, and in the
finally block remove the temporary directory created (home) to clean up
artifacts (e.g., call fs.rmSync(home, { recursive: true, force: true }) or
equivalent). This ensures the test "explains sandbox connect command order when
the sandbox name is last" cleans up created files after runWithEnv and matches
the pattern used by other tests.
- Around line 180-212: Wrap the test body that creates the temporary HOME and
localBin in a try/finally so the temp directory is always removed; specifically,
after creating home and localBin and writing the openshell stub, run the
existing assertions inside a try block and in finally call fs.rmSync(home, {
recursive: true, force: true }) (or the same cleanup used elsewhere) to mirror
the pattern used in other tests and ensure cleanup even on assertion failures;
keep runWithEnv("liost", {...}), the openshell file creation, and the
expect(...) assertions inside the try so they execute before cleanup.

In `@test/cli/list-inference.test.ts`:
- Around line 179-253: The test "list --json emits structured sandbox details"
creates a temporary home dir (variable home) but doesn't remove it; wrap the
test body after creating home in a try { ... } finally { fs.rmSync(home, {
recursive: true, force: true }); } block so the temp directory is always cleaned
up (place the existing assertions and runWithEnv(...) call inside the try);
reference the test function name and the home variable to locate where to add
the try/finally.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 2584f777-9818-4330-ad77-0c431c03d915

📥 Commits

Reviewing files that changed from the base of the PR and between 76b1b80 and 03bc2b1.

📒 Files selected for processing (10)
  • test/cli.test.ts
  • test/cli/connect-recovery.test.ts
  • test/cli/destroy-gateway-cleanup.test.ts
  • test/cli/dispatch-basics.test.ts
  • test/cli/doctor-gateway-token.test.ts
  • test/cli/helpers.ts
  • test/cli/list-inference.test.ts
  • test/cli/logs.test.ts
  • test/cli/status-gateway-lifecycle.test.ts
  • test/cli/status-health.test.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • test/cli/logs.test.ts
  • test/cli/status-health.test.ts

@cv
cv merged commit 6b05a85 into main Jun 7, 2026
37 checks passed
@cv
cv deleted the codex/cli-sandbox-mutation-split branch June 7, 2026 02:38
@cv cv added the v0.0.61 label Jun 7, 2026
@wscurran wscurran added the chore Build, CI, dependency, or tooling maintenance label Jun 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

chore Build, CI, dependency, or tooling maintenance

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants