diff --git a/src/lib/commands/sandbox/logs.ts b/src/lib/commands/sandbox/logs.ts index fb3c179e91..dfdf1053cd 100644 --- a/src/lib/commands/sandbox/logs.ts +++ b/src/lib/commands/sandbox/logs.ts @@ -4,8 +4,8 @@ import { Args, Command, Flags } from "@oclif/core"; import { logsSinceDurationFlag } from "../../duration-flags"; -import type { SandboxLogsOptions } from "../../sandbox-logs-options"; -import { DEFAULT_SANDBOX_LOG_LINES } from "../../sandbox-logs-options"; +import type { SandboxLogsOptions } from "../../domain/sandbox/log-options"; +import { DEFAULT_SANDBOX_LOG_LINES } from "../../domain/sandbox/log-options"; import { showSandboxLogs } from "../../sandbox-runtime-actions"; type SandboxLogsRuntimeBridge = { diff --git a/src/lib/coverage-hotspots.test.ts b/src/lib/coverage-hotspots.test.ts index 26e4af0448..d33029e2a0 100644 --- a/src/lib/coverage-hotspots.test.ts +++ b/src/lib/coverage-hotspots.test.ts @@ -6,7 +6,7 @@ import os from "node:os"; import path from "node:path"; import { describe, expect, it } from "vitest"; -import { parseDuration } from "./duration"; +import { parseDuration } from "./domain/duration"; import { parseGatewayTokenArgs, runGatewayTokenCommand } from "./gateway-token-command"; import { resolveDefaultSandboxName, runStartCommand, runStopCommand } from "./services-command"; import { getVersion } from "./version"; diff --git a/test/duration.test.ts b/src/lib/domain/duration.test.ts similarity index 96% rename from test/duration.test.ts rename to src/lib/domain/duration.test.ts index ccb2b9720c..a83452ee0a 100644 --- a/test/duration.test.ts +++ b/src/lib/domain/duration.test.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { describe, it, expect } from "vitest"; -import { parseDuration, MAX_SECONDS, DEFAULT_SECONDS } from "../src/lib/duration.js"; +import { parseDuration, MAX_SECONDS, DEFAULT_SECONDS } from "./duration"; describe("parseDuration", () => { it("parses minutes", () => { diff --git a/src/lib/duration.ts b/src/lib/domain/duration.ts similarity index 100% rename from src/lib/duration.ts rename to src/lib/domain/duration.ts diff --git a/src/lib/lifecycle-options.test.ts b/src/lib/domain/lifecycle/options.test.ts similarity index 98% rename from src/lib/lifecycle-options.test.ts rename to src/lib/domain/lifecycle/options.test.ts index 52e9cb63ff..36b2f69974 100644 --- a/src/lib/lifecycle-options.test.ts +++ b/src/lib/domain/lifecycle/options.test.ts @@ -8,7 +8,7 @@ import { normalizeGarbageCollectImagesOptions, normalizeRebuildSandboxOptions, normalizeUpgradeSandboxesOptions, -} from "./lifecycle-options"; +} from "./options"; describe("lifecycle option normalization", () => { it("preserves typed destroy options and still accepts compatibility argv", () => { diff --git a/src/lib/lifecycle-options.ts b/src/lib/domain/lifecycle/options.ts similarity index 100% rename from src/lib/lifecycle-options.ts rename to src/lib/domain/lifecycle/options.ts diff --git a/src/lib/maintenance-image-helpers.test.ts b/src/lib/domain/maintenance/images.test.ts similarity index 97% rename from src/lib/maintenance-image-helpers.test.ts rename to src/lib/domain/maintenance/images.test.ts index f79a5dd9ba..b4fd599465 100644 --- a/src/lib/maintenance-image-helpers.test.ts +++ b/src/lib/domain/maintenance/images.test.ts @@ -7,7 +7,7 @@ import { findOrphanedSandboxImages, getRegisteredImageTags, parseSandboxImageRows, -} from "./maintenance-image-helpers"; +} from "./images"; describe("maintenance image helpers", () => { it("parses Docker image rows and fills missing sizes", () => { diff --git a/src/lib/maintenance-image-helpers.ts b/src/lib/domain/maintenance/images.ts similarity index 100% rename from src/lib/maintenance-image-helpers.ts rename to src/lib/domain/maintenance/images.ts diff --git a/src/lib/upgrade-sandboxes-helpers.test.ts b/src/lib/domain/maintenance/upgrade.test.ts similarity index 98% rename from src/lib/upgrade-sandboxes-helpers.test.ts rename to src/lib/domain/maintenance/upgrade.test.ts index 649d8a6b3c..51b68a46f6 100644 --- a/src/lib/upgrade-sandboxes-helpers.test.ts +++ b/src/lib/domain/maintenance/upgrade.test.ts @@ -8,7 +8,7 @@ import { shouldSkipUpgradeConfirmation, splitRebuildableSandboxes, type SandboxVersionCheck, -} from "./upgrade-sandboxes-helpers"; +} from "./upgrade"; describe("upgrade sandboxes helpers", () => { it("detects upgrade confirmation bypass modes", () => { diff --git a/src/lib/upgrade-sandboxes-helpers.ts b/src/lib/domain/maintenance/upgrade.ts similarity index 96% rename from src/lib/upgrade-sandboxes-helpers.ts rename to src/lib/domain/maintenance/upgrade.ts index 07b8d93c78..a8d962a8da 100644 --- a/src/lib/upgrade-sandboxes-helpers.ts +++ b/src/lib/domain/maintenance/upgrade.ts @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 -import type { UpgradeSandboxesOptions } from "./lifecycle-options"; +import type { UpgradeSandboxesOptions } from "../lifecycle/options"; export type SandboxVersionCheck = { isStale: boolean; diff --git a/src/lib/policy-channel-helpers.test.ts b/src/lib/domain/policy-channel.test.ts similarity index 98% rename from src/lib/policy-channel-helpers.test.ts rename to src/lib/domain/policy-channel.test.ts index 74297d0da3..dab7b9c397 100644 --- a/src/lib/policy-channel-helpers.test.ts +++ b/src/lib/domain/policy-channel.test.ts @@ -7,7 +7,7 @@ import { parseCustomPolicySource, parsePolicyAddArgs, shouldSkipPolicyConfirmation, -} from "./policy-channel-helpers"; +} from "./policy-channel"; describe("policy channel helpers", () => { it("parses custom policy source flags", () => { diff --git a/src/lib/policy-channel-helpers.ts b/src/lib/domain/policy-channel.ts similarity index 100% rename from src/lib/policy-channel-helpers.ts rename to src/lib/domain/policy-channel.ts diff --git a/src/lib/sandbox-destroy-helpers.test.ts b/src/lib/domain/sandbox/destroy.test.ts similarity index 98% rename from src/lib/sandbox-destroy-helpers.test.ts rename to src/lib/domain/sandbox/destroy.test.ts index b3c7577968..14bf40f38a 100644 --- a/src/lib/sandbox-destroy-helpers.test.ts +++ b/src/lib/domain/sandbox/destroy.test.ts @@ -8,7 +8,7 @@ import { isMissingSandboxDeleteOutput, shouldCleanupGatewayAfterDestroy, shouldStopHostServicesAfterDestroy, -} from "./sandbox-destroy-helpers"; +} from "./destroy"; describe("sandbox destroy helpers", () => { it("detects missing sandbox delete output", () => { diff --git a/src/lib/sandbox-destroy-helpers.ts b/src/lib/domain/sandbox/destroy.ts similarity index 92% rename from src/lib/sandbox-destroy-helpers.ts rename to src/lib/domain/sandbox/destroy.ts index 64c5aea75d..acdc5011a3 100644 --- a/src/lib/sandbox-destroy-helpers.ts +++ b/src/lib/domain/sandbox/destroy.ts @@ -3,7 +3,11 @@ /* v8 ignore start -- pure helper tests exercise this module; orchestration coverage still runs through dist. */ -import { stripAnsi } from "./openshell"; +const ANSI_RE = /\x1b\[[0-9;]*m/g; + +function stripAnsi(value = ""): string { + return String(value).replace(ANSI_RE, ""); +} export type SpawnLikeResult = { status: number | null; diff --git a/src/lib/sandbox-logs-options.ts b/src/lib/domain/sandbox/log-options.ts similarity index 100% rename from src/lib/sandbox-logs-options.ts rename to src/lib/domain/sandbox/log-options.ts diff --git a/src/lib/sandbox-logs-helpers.test.ts b/src/lib/domain/sandbox/logs.test.ts similarity index 98% rename from src/lib/sandbox-logs-helpers.test.ts rename to src/lib/domain/sandbox/logs.test.ts index 723c49e4c4..e2dce25870 100644 --- a/src/lib/sandbox-logs-helpers.test.ts +++ b/src/lib/domain/sandbox/logs.test.ts @@ -11,7 +11,7 @@ import { exitCodeFromSignal, getLogsProbeTimeoutMs, normalizeSandboxLogsOptions, -} from "./sandbox-logs-helpers"; +} from "./logs"; describe("sandbox logs helpers", () => { it("normalizes boolean and partial logs options", () => { diff --git a/src/lib/sandbox-logs-helpers.ts b/src/lib/domain/sandbox/logs.ts similarity index 95% rename from src/lib/sandbox-logs-helpers.ts rename to src/lib/domain/sandbox/logs.ts index 0b998e29cc..c7dad18e44 100644 --- a/src/lib/sandbox-logs-helpers.ts +++ b/src/lib/domain/sandbox/logs.ts @@ -5,8 +5,8 @@ import os from "node:os"; -import type { SandboxLogsOptions } from "./sandbox-logs-options"; -import { DEFAULT_SANDBOX_LOG_LINES } from "./sandbox-logs-options"; +import type { SandboxLogsOptions } from "./log-options"; +import { DEFAULT_SANDBOX_LOG_LINES } from "./log-options"; export const DEFAULT_LOGS_PROBE_TIMEOUT_MS = 5000; export const LOGS_PROBE_TIMEOUT_ENV = "NEMOCLAW_LOGS_PROBE_TIMEOUT_MS"; diff --git a/src/lib/duration-flags.ts b/src/lib/duration-flags.ts index d5a391313e..b82542223d 100644 --- a/src/lib/duration-flags.ts +++ b/src/lib/duration-flags.ts @@ -3,7 +3,7 @@ import { Errors, Flags } from "@oclif/core"; -import { parseDuration } from "./duration"; +import { parseDuration } from "./domain/duration"; const LOGS_SINCE_DURATION_RE = /^[1-9]\d*(?:ms|s|m|h|d)$/i; diff --git a/src/lib/global-cli-actions.ts b/src/lib/global-cli-actions.ts index 5e7ee4ff4c..9d5692327d 100644 --- a/src/lib/global-cli-actions.ts +++ b/src/lib/global-cli-actions.ts @@ -5,7 +5,7 @@ import { runDeployAction as executeDeployAction } from "./deploy-action"; import { type GarbageCollectImagesOptions, type UpgradeSandboxesOptions, -} from "./lifecycle-options"; +} from "./domain/lifecycle/options"; import { backupAll as executeBackupAllAction, garbageCollectImages as executeGarbageCollectImagesAction, diff --git a/src/lib/maintenance-actions.ts b/src/lib/maintenance-actions.ts index e1dee12cd0..dd4bcdb760 100644 --- a/src/lib/maintenance-actions.ts +++ b/src/lib/maintenance-actions.ts @@ -7,9 +7,9 @@ import { prompt as askPrompt } from "./credentials"; import { type GarbageCollectImagesOptions, normalizeGarbageCollectImagesOptions, -} from "./lifecycle-options"; +} from "./domain/lifecycle/options"; import { dockerListImagesFormat, dockerRmi } from "./docker"; -import { findOrphanedSandboxImages, parseSandboxImageRows } from "./maintenance-image-helpers"; +import { findOrphanedSandboxImages, parseSandboxImageRows } from "./domain/maintenance/images"; import { captureOpenshell } from "./openshell-runtime"; import * as registry from "./registry"; import { parseLiveSandboxNames } from "./runtime-recovery"; diff --git a/src/lib/policy-channel-actions.ts b/src/lib/policy-channel-actions.ts index d2cacdd429..4b85e8bab3 100644 --- a/src/lib/policy-channel-actions.ts +++ b/src/lib/policy-channel-actions.ts @@ -13,7 +13,7 @@ import { recoverNamedGatewayRuntime } from "./gateway-runtime-action"; const { isNonInteractive } = require("./onboard") as { isNonInteractive: () => boolean }; const onboardProviders = require("./onboard-providers"); import * as policies from "./policies"; -import { parsePolicyAddArgs } from "./policy-channel-helpers"; +import { parsePolicyAddArgs } from "./domain/policy-channel"; import * as registry from "./registry"; import { runOpenshell } from "./openshell-runtime"; import { rebuildSandbox } from "./sandbox-runtime-actions"; diff --git a/src/lib/sandbox-destroy-action.ts b/src/lib/sandbox-destroy-action.ts index 39af24c07a..32f7eab212 100644 --- a/src/lib/sandbox-destroy-action.ts +++ b/src/lib/sandbox-destroy-action.ts @@ -10,7 +10,7 @@ import { prompt as askPrompt } from "./credentials"; import { type DestroySandboxOptions, normalizeDestroySandboxOptions, -} from "./lifecycle-options"; +} from "./domain/lifecycle/options"; import * as onboardSession from "./onboard-session"; import type { Session } from "./onboard-session"; import { OPENSHELL_PROBE_TIMEOUT_MS } from "./openshell-timeouts"; @@ -26,7 +26,7 @@ import { getSandboxDeleteOutcome, shouldCleanupGatewayAfterDestroy, shouldStopHostServicesAfterDestroy, -} from "./sandbox-destroy-helpers"; +} from "./domain/sandbox/destroy"; import { G, R, YW } from "./terminal-style"; type DockerRmi = (tag: string, opts?: { ignoreError?: boolean }) => { status: number | null }; diff --git a/src/lib/sandbox-logs-action.ts b/src/lib/sandbox-logs-action.ts index 89d97cd05c..0c81c4a728 100644 --- a/src/lib/sandbox-logs-action.ts +++ b/src/lib/sandbox-logs-action.ts @@ -14,8 +14,8 @@ import { getLogsProbeTimeoutMs, normalizeSandboxLogsOptions, type LogProbeResult, -} from "./sandbox-logs-helpers"; -import type { SandboxLogsOptions } from "./sandbox-logs-options"; +} from "./domain/sandbox/logs"; +import type { SandboxLogsOptions } from "./domain/sandbox/log-options"; /* v8 ignore next -- process exit mapping is covered through CLI subprocess log tests. */ function exitWithSpawnResult(result: LogProbeResult) { diff --git a/src/lib/sandbox-rebuild-action.ts b/src/lib/sandbox-rebuild-action.ts index 56ae7fef3a..56a19c5418 100644 --- a/src/lib/sandbox-rebuild-action.ts +++ b/src/lib/sandbox-rebuild-action.ts @@ -8,7 +8,7 @@ import { prompt as askPrompt } from "./credentials"; import { normalizeRebuildSandboxOptions, type RebuildSandboxOptions, -} from "./lifecycle-options"; +} from "./domain/lifecycle/options"; const { hydrateCredentialEnv } = require("./onboard") as { hydrateCredentialEnv: (name: string) => string | null; @@ -26,7 +26,7 @@ import * as policies from "./policies"; import * as registry from "./registry"; import { resolveOpenshell } from "./resolve-openshell"; import { parseLiveSandboxNames } from "./runtime-recovery"; -import { getSandboxDeleteOutcome } from "./sandbox-destroy-helpers"; +import { getSandboxDeleteOutcome } from "./domain/sandbox/destroy"; import { removeSandboxRegistryEntry } from "./sandbox-destroy-action"; import { executeSandboxCommand } from "./sandbox-process-recovery-action"; import { diff --git a/src/lib/sandbox-runtime-actions.ts b/src/lib/sandbox-runtime-actions.ts index 7e39c7f182..ab3b6f4c88 100644 --- a/src/lib/sandbox-runtime-actions.ts +++ b/src/lib/sandbox-runtime-actions.ts @@ -3,9 +3,9 @@ /* v8 ignore start -- transitional action facade until implementations leave src/nemoclaw.ts. */ -import type { DestroySandboxOptions, RebuildSandboxOptions } from "./lifecycle-options"; +import type { DestroySandboxOptions, RebuildSandboxOptions } from "./domain/lifecycle/options"; import type { SandboxConnectOptions } from "./sandbox-connect-action"; -import type { SandboxLogsOptions } from "./sandbox-logs-options"; +import type { SandboxLogsOptions } from "./domain/sandbox/log-options"; export async function connectSandbox( sandboxName: string, diff --git a/src/lib/shields.ts b/src/lib/shields.ts index f06ae4fc0d..d1d518a7d3 100644 --- a/src/lib/shields.ts +++ b/src/lib/shields.ts @@ -21,7 +21,7 @@ const { parseCurrentPolicy, PERMISSIVE_POLICY_PATH, } = require("./policies"); -const { parseDuration, MAX_SECONDS, DEFAULT_SECONDS } = require("./duration"); +const { parseDuration, MAX_SECONDS, DEFAULT_SECONDS } = require("./domain/duration"); const { appendAuditEntry } = require("./shields-audit"); const { resolveAgentConfig } = require("./sandbox-config"); diff --git a/src/lib/upgrade-sandboxes-action.ts b/src/lib/upgrade-sandboxes-action.ts index 9db9fb4782..e347cc9e80 100644 --- a/src/lib/upgrade-sandboxes-action.ts +++ b/src/lib/upgrade-sandboxes-action.ts @@ -8,7 +8,7 @@ import { prompt as askPrompt } from "./credentials"; import { normalizeUpgradeSandboxesOptions, type UpgradeSandboxesOptions, -} from "./lifecycle-options"; +} from "./domain/lifecycle/options"; import { captureOpenshell } from "./openshell-runtime"; import * as registry from "./registry"; import { parseLiveSandboxNames } from "./runtime-recovery"; @@ -19,7 +19,7 @@ import { classifyUpgradeableSandboxes, shouldSkipUpgradeConfirmation, splitRebuildableSandboxes, -} from "./upgrade-sandboxes-helpers"; +} from "./domain/maintenance/upgrade"; // ── Upgrade sandboxes (#1904) ──────────────────────────────────── // Detect sandboxes running stale agent versions and offer to rebuild them. diff --git a/test/image-cleanup.test.ts b/test/image-cleanup.test.ts index e441b652b8..8707e190a4 100644 --- a/test/image-cleanup.test.ts +++ b/test/image-cleanup.test.ts @@ -12,8 +12,8 @@ import { removeSandboxImage, removeSandboxRegistryEntry, } from "../src/lib/sandbox-destroy-action"; -import { getSandboxDeleteOutcome } from "../src/lib/sandbox-destroy-helpers"; -import { normalizeGarbageCollectImagesOptions } from "../src/lib/lifecycle-options"; +import { getSandboxDeleteOutcome } from "../src/lib/domain/sandbox/destroy"; +import { normalizeGarbageCollectImagesOptions } from "../src/lib/domain/lifecycle/options"; import { help as renderRootHelp } from "../src/lib/root-help-action"; const ROOT = path.resolve(import.meta.dirname, ".."); diff --git a/test/shields.test.ts b/test/shields.test.ts index 0af5ca0baa..36b982cec1 100644 --- a/test/shields.test.ts +++ b/test/shields.test.ts @@ -76,29 +76,29 @@ describe("shields — unit logic", () => { // Since the CJS require resolution issue makes direct import flaky, // test the TypeScript duration module instead. it("parses minutes", async () => { - const { parseDuration } = await import("../src/lib/duration.js"); + const { parseDuration } = await import("../src/lib/domain/duration.js"); expect(parseDuration("5m")).toBe(300); expect(parseDuration("30m")).toBe(1800); }); it("parses seconds", async () => { - const { parseDuration } = await import("../src/lib/duration.js"); + const { parseDuration } = await import("../src/lib/domain/duration.js"); expect(parseDuration("90s")).toBe(90); }); it("treats bare numbers as seconds", async () => { - const { parseDuration } = await import("../src/lib/duration.js"); + const { parseDuration } = await import("../src/lib/domain/duration.js"); expect(parseDuration("300")).toBe(300); }); it("rejects durations exceeding 30 minutes", async () => { - const { parseDuration } = await import("../src/lib/duration.js"); + const { parseDuration } = await import("../src/lib/domain/duration.js"); expect(() => parseDuration("31m")).toThrow("exceeds maximum"); expect(() => parseDuration("1h")).toThrow("exceeds maximum"); }); it("rejects invalid input", async () => { - const { parseDuration } = await import("../src/lib/duration.js"); + const { parseDuration } = await import("../src/lib/domain/duration.js"); expect(() => parseDuration("abc")).toThrow("Invalid duration"); }); });