// Check Openclaw Package Tarball tests cover check openclaw package tarball script behavior. import { spawnSync } from "node:child_process"; import { chmodSync, existsSync, mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync, } from "node:fs"; import { tmpdir } from "node:os"; import { delimiter, dirname, join } from "node:path"; import { gte as semverGte, valid as validSemver } from "semver"; import { describe, expect, it } from "vitest"; import { LOCAL_BUILD_METADATA_DIST_PATHS } from "../../scripts/lib/local-build-metadata-paths.mts"; import { PACKAGE_INSTALL_GUARD_RELATIVE_PATH } from "../../scripts/lib/package-dist-inventory.ts"; import { WORKSPACE_TEMPLATE_PACK_PATHS } from "../../scripts/lib/workspace-bootstrap-smoke.mts"; const CHECK_SCRIPT = "scripts/check-openclaw-package-tarball.mts"; const PUBLIC_CHECK_SCRIPT = "scripts/check-openclaw-package-tarball.mjs"; const NODE_DEFAULT_SPAWN_MAX_BUFFER_BYTES = 1024 * 1024; const CODE_MODE_WORKER_PATH = "dist/agents/code-mode.worker.js"; const FIRST_CODE_MODE_WORKER_VERSION = "2026.5.14-beta.2"; const FLAT_PLUGIN_SDK_DECLARATION = "dist/plugin-sdk/provider-entry.d.ts"; const DEEP_PLUGIN_SDK_DECLARATION = "dist/plugin-sdk/src/plugin-sdk/provider-entry.d.ts"; const AI_RUNTIME_PACKAGE_JSON = JSON.stringify({ name: "@openclaw/ai", version: "2026.6.11", exports: { ".": { import: "./dist/index.mjs" }, "./providers": { import: "./dist/providers.mjs" }, "./transports": { import: "./dist/transports.mjs" }, "./internal/*": { import: "./dist/internal/*.mjs" }, }, }); const LEGACY_AI_RUNTIME_PACKAGE_JSON = JSON.stringify({ name: "@openclaw/ai", version: "2026.7.2-beta.4", exports: { ".": { import: "./dist/index.mjs" }, "./providers": { import: "./dist/providers.mjs" }, "./internal/*": { import: "./dist/internal/*.mjs" }, }, }); function usesLegacyShrinkwrapByDefault(version: string): boolean { const match = /^(\d{4})\.(\d{1,2})\.(\d{1,2})/u.exec(version); if (!match) { return false; } const [year = 0, month = 0, patch = 0] = match.slice(1).map(Number); return year < 2026 || (year === 2026 && (month < 7 || (month === 7 && patch < 2))); } function withTarball( inventory: string[], files: Record, testBody: (tarball: string) => void, version = "2026.7.2", options: { includeCodeModeWorker?: boolean; includeCodeModeWorkerInInventory?: boolean; includeControlUi?: boolean; includeInstallGuard?: boolean; includeShrinkwrap?: boolean; includeWorkspaceTemplates?: boolean; packageJson?: Record; } = {}, ) { const root = mkdtempSync(join(tmpdir(), "openclaw-package-tarball-test-")); try { const validVersion = validSemver(version); const includeCodeModeWorker = options.includeCodeModeWorker ?? (validVersion !== null && semverGte(validVersion, FIRST_CODE_MODE_WORKER_VERSION)); const includeCodeModeWorkerInInventory = options.includeCodeModeWorkerInInventory ?? includeCodeModeWorker; const packageInventory = includeCodeModeWorkerInInventory ? [...new Set([...inventory, CODE_MODE_WORKER_PATH])] : inventory; const packageRoot = join(root, "package"); mkdirSync(join(packageRoot, "dist"), { recursive: true }); writeFileSync( join(packageRoot, "package.json"), JSON.stringify({ name: "openclaw", version, ...options.packageJson }), ); writeFileSync( join(packageRoot, "dist", "postinstall-inventory.json"), JSON.stringify(packageInventory), ); const workspaceTemplates = options.includeWorkspaceTemplates === false ? {} : Object.fromEntries( WORKSPACE_TEMPLATE_PACK_PATHS.map((relativePath) => [ relativePath, `# ${relativePath}\n`, ]), ); const controlUiFiles = options.includeControlUi === false ? {} : { "dist/control-ui/index.html": "", "dist/control-ui/assets/app.js": "console.log('ok');\n", }; const installGuardFile = options.includeInstallGuard === false ? {} : { [PACKAGE_INSTALL_GUARD_RELATIVE_PATH]: "OpenClaw package preinstall has not completed.\n", }; const shrinkwrapFile = (options.includeShrinkwrap ?? usesLegacyShrinkwrapByDefault(version)) ? { "npm-shrinkwrap.json": `${JSON.stringify({ name: "openclaw", version, lockfileVersion: 3, packages: { "": { name: "openclaw", version } }, })}\n`, } : {}; const tarFiles = { ...workspaceTemplates, ...controlUiFiles, ...installGuardFile, ...shrinkwrapFile, ...(includeCodeModeWorker ? { [CODE_MODE_WORKER_PATH]: "export {};\n" } : {}), ...files, }; for (const [relativePath, body] of Object.entries(tarFiles)) { const filePath = join(packageRoot, relativePath); mkdirSync(dirname(filePath), { recursive: true }); writeFileSync(filePath, body); } const tarball = join(root, "openclaw.tgz"); const pack = spawnSync("tar", ["-czf", tarball, "-C", root, "package"], { encoding: "utf8", }); expect(pack.status, pack.stderr).toBe(0); testBody(tarball); } finally { rmSync(root, { recursive: true, force: true }); } } describe("check-openclaw-package-tarball", () => { it("prints help before touching tarball state", () => { const result = spawnSync("node", [PUBLIC_CHECK_SCRIPT, "--help"], { encoding: "utf8" }); expect(result.status, result.stderr).toBe(0); expect(result.stdout).toContain( "Usage: node scripts/check-openclaw-package-tarball.mjs [--require-bundled-workspace-deps] ", ); expect(result.stderr).toBe(""); }); it("rejects option-like and extra arguments before tar inspection", () => { const unknown = spawnSync("node", [CHECK_SCRIPT, "--tag"], { encoding: "utf8" }); expect(unknown.status).not.toBe(0); expect(unknown.stderr).toContain("Unknown OpenClaw package tarball check option: --tag"); expect(unknown.stderr).not.toContain("OpenClaw package tarball does not exist"); const extra = spawnSync("node", [CHECK_SCRIPT, "openclaw.tgz", "extra"], { encoding: "utf8", }); expect(extra.status).not.toBe(0); expect(extra.stderr).toContain("Unexpected OpenClaw package tarball check argument: extra"); expect(extra.stderr).not.toContain("OpenClaw package tarball does not exist"); }); it("accepts tarballs whose entry list exceeds Node's default spawn buffer", () => { const longNameSuffix = "x".repeat(80); const largeEntryList = Object.fromEntries( Array.from({ length: 8_000 }, (_, index) => [ `dist/control-ui/assets/large-entry-list/asset-${String(index).padStart(5, "0")}-${longNameSuffix}.txt`, "", ]), ); withTarball( ["dist/index.js"], { "dist/index.js": "export {};\n", ...largeEntryList }, (tarball) => { const listing = spawnSync("tar", ["-tf", tarball], { encoding: "utf8", maxBuffer: NODE_DEFAULT_SPAWN_MAX_BUFFER_BYTES * 2, }); expect(listing.status, listing.stderr).toBe(0); expect(Buffer.byteLength(listing.stdout)).toBeGreaterThan( NODE_DEFAULT_SPAWN_MAX_BUFFER_BYTES, ); const result = spawnSync("node", [CHECK_SCRIPT, tarball], { encoding: "utf8" }); expect(result.status, result.stderr).toBe(0); expect(result.stdout).toContain("OpenClaw package tarball integrity passed."); }, ); }); it.runIf(process.platform !== "win32")( "removes the extract dir when tar extraction fails", () => { const root = mkdtempSync(join(tmpdir(), "openclaw-package-tarball-extract-fail-")); try { const fakeBin = join(root, "bin"); mkdirSync(fakeBin); const extractDirFile = join(root, "extract-dir.txt"); const fakeTar = join(fakeBin, "tar"); writeFileSync( fakeTar, [ "#!/usr/bin/env node", "const fs = require('node:fs');", "const args = process.argv.slice(2);", "if (args[0] === '-tf') { console.log('package/package.json'); process.exit(0); }", "const outputDir = args[args.indexOf('-C') + 1];", "fs.writeFileSync(process.env.OPENCLAW_TEST_EXTRACT_DIR_FILE, outputDir);", "console.error('extract denied');", "process.exit(7);", ].join("\n"), ); chmodSync(fakeTar, 0o755); const tarball = join(root, "openclaw.tgz"); writeFileSync(tarball, "not used by fake tar"); const result = spawnSync("node", [CHECK_SCRIPT, tarball], { encoding: "utf8", env: { ...process.env, OPENCLAW_TEST_EXTRACT_DIR_FILE: extractDirFile, PATH: `${fakeBin}${delimiter}${process.env.PATH ?? ""}`, }, }); expect(result.status).not.toBe(0); expect(result.stderr).toContain("extract denied"); expect(existsSync(readFileSync(extractDirFile, "utf8"))).toBe(false); } finally { rmSync(root, { recursive: true, force: true }); } }, ); it("allows legacy private QA inventory entries omitted from shipped tarballs through 2026.4.25", () => { withTarball( ["dist/index.js", "dist/extensions/qa-channel/runtime-api.js"], { "dist/index.js": "export {};\n" }, (tarball) => { const result = spawnSync("node", [CHECK_SCRIPT, tarball], { encoding: "utf8" }); expect(result.status, result.stderr).toBe(0); expect(result.stderr).toContain("legacy inventory references omitted private QA"); expect(result.stdout).toContain("OpenClaw package tarball integrity passed."); }, "2026.4.25-beta.10", ); }); it("rejects legacy private QA inventory omissions for newer packages", () => { withTarball( ["dist/index.js", "dist/extensions/qa-channel/runtime-api.js"], { "dist/index.js": "export {};\n" }, (tarball) => { const result = spawnSync("node", [CHECK_SCRIPT, tarball], { encoding: "utf8" }); expect(result.status).not.toBe(0); expect(result.stderr).toContain( "inventory references missing tar entry dist/extensions/qa-channel/runtime-api.js", ); expect(result.stderr).not.toContain("legacy inventory references omitted private QA"); }, "2026.4.26", ); }); it("requires an install guard omitted from the dist inventory", () => { withTarball( ["dist/index.js"], { "dist/index.js": "export {};\n" }, (tarball) => { const result = spawnSync("node", [CHECK_SCRIPT, tarball], { encoding: "utf8" }); expect(result.status).not.toBe(0); expect(result.stderr).toContain( `missing required tar entry ${PACKAGE_INSTALL_GUARD_RELATIVE_PATH}`, ); }, "0.0.0", { includeInstallGuard: false }, ); withTarball( ["dist/index.js", PACKAGE_INSTALL_GUARD_RELATIVE_PATH], { "dist/index.js": "export {};\n" }, (tarball) => { const result = spawnSync("node", [CHECK_SCRIPT, tarball], { encoding: "utf8" }); expect(result.status).not.toBe(0); expect(result.stderr).toContain( `package dist inventory must omit install guard ${PACKAGE_INSTALL_GUARD_RELATIVE_PATH}`, ); }, ); withTarball( ["dist/index.js"], { "dist/index.js": "export {};\n" }, (tarball) => { const result = spawnSync("node", [CHECK_SCRIPT, tarball], { encoding: "utf8" }); expect(result.status, result.stderr).toBe(0); expect(result.stderr).toContain("legacy package omits the preinstall completion guard"); }, "2026.7.1", { includeInstallGuard: false }, ); }); it("rejects stale deep plugin SDK declaration inventory entries", () => { withTarball( [FLAT_PLUGIN_SDK_DECLARATION, DEEP_PLUGIN_SDK_DECLARATION], { [FLAT_PLUGIN_SDK_DECLARATION]: "export {};\n" }, (tarball) => { const result = spawnSync("node", [CHECK_SCRIPT, tarball], { encoding: "utf8" }); expect(result.status).not.toBe(0); expect(result.stderr).toContain( `inventory references missing tar entry ${DEEP_PLUGIN_SDK_DECLARATION}`, ); }, ); }); it("accepts historical packages published before the Code Mode worker existed", () => { withTarball( ["dist/index.js"], { "dist/index.js": "export {};\n" }, (tarball) => { const result = spawnSync("node", [CHECK_SCRIPT, tarball], { encoding: "utf8" }); expect(result.status, result.stderr).toBe(0); expect(result.stdout).toContain("OpenClaw package tarball integrity passed."); }, "2026.5.14-beta.1", ); }); it("rejects Code Mode packages that omit the dynamically loaded worker", () => { withTarball( ["dist/index.js"], { "dist/index.js": "export {};\n" }, (tarball) => { const result = spawnSync("node", [CHECK_SCRIPT, tarball], { encoding: "utf8" }); expect(result.status).not.toBe(0); expect(result.stderr).toContain(`missing required tar entry ${CODE_MODE_WORKER_PATH}`); }, FIRST_CODE_MODE_WORKER_VERSION, { includeCodeModeWorker: false }, ); }); it("rejects Code Mode workers that postinstall would remove", () => { withTarball( ["dist/index.js"], { "dist/index.js": "export {};\n" }, (tarball) => { const result = spawnSync("node", [CHECK_SCRIPT, tarball], { encoding: "utf8" }); expect(result.status).not.toBe(0); expect(result.stderr).toContain(`postinstall inventory omits ${CODE_MODE_WORKER_PATH}`); }, FIRST_CODE_MODE_WORKER_VERSION, { includeCodeModeWorkerInInventory: false }, ); }); it("rejects dist files that import missing relative chunks", () => { withTarball( ["dist/cli/run-main.js"], { "dist/cli/run-main.js": 'await import("../memory-state-old.js");\n' }, (tarball) => { const result = spawnSync("node", [CHECK_SCRIPT, tarball], { encoding: "utf8" }); expect(result.status).not.toBe(0); expect(result.stderr).toContain( "dist/cli/run-main.js imports missing dist/memory-state-old.js", ); }, "2026.4.27", ); }); it("rejects leaked private QA Docker chunks that import an omitted QA runtime", () => { withTarball( ["dist/docker-runtime-BVdgRgxA.js"], { "dist/docker-runtime-BVdgRgxA.js": 'import { createQaDockerRuntime } from "./qa-runtime-Bi1S3plf.js";\n' + "export { createQaDockerRuntime };\n", }, (tarball) => { const result = spawnSync("node", [CHECK_SCRIPT, tarball], { encoding: "utf8" }); expect(result.status).not.toBe(0); expect(result.stderr).toContain( "dist/docker-runtime-BVdgRgxA.js imports missing dist/qa-runtime-Bi1S3plf.js", ); }, ); }); it("accepts dist files whose relative chunks are present", () => { withTarball( ["dist/cli/run-main.js", "dist/memory-state-current.js"], { "dist/cli/run-main.js": 'await import("../memory-state-current.js");\n', "dist/memory-state-current.js": "export {};\n", }, (tarball) => { const result = spawnSync("node", [CHECK_SCRIPT, tarball], { encoding: "utf8" }); expect(result.status, result.stderr).toBe(0); expect(result.stdout).toContain("OpenClaw package tarball integrity passed."); }, "2026.4.27", ); }); it("rejects imported dist chunks omitted from the postinstall inventory", () => { withTarball( ["dist/cli/run-main.js"], { "dist/cli/run-main.js": 'await import("../memory-state-current.js");\n', "dist/memory-state-current.js": "export {};\n", }, (tarball) => { const result = spawnSync("node", [CHECK_SCRIPT, tarball], { encoding: "utf8" }); expect(result.status).not.toBe(0); expect(result.stderr).toContain( "inventory omits imported dist file dist/memory-state-current.js", ); }, "2026.4.27", ); }); it("rejects named imported chunks omitted from the postinstall inventory", () => { withTarball( ["dist/index.js"], { "dist/index.js": 'import { value } from "./chunk.js";\nexport { value };\n', "dist/chunk.js": "export const value = 42;\n", }, (tarball) => { const result = spawnSync("node", [CHECK_SCRIPT, tarball], { encoding: "utf8" }); expect(result.status).not.toBe(0); expect(result.stderr).toContain("inventory omits imported dist file dist/chunk.js"); }, "2026.4.27", ); }); it("rejects CommonJS require chunks omitted from the postinstall inventory", () => { withTarball( ["dist/index.cjs"], { "dist/index.cjs": 'module.exports = require("./chunk.cjs");\n', "dist/chunk.cjs": "module.exports = {};\n", }, (tarball) => { const result = spawnSync("node", [CHECK_SCRIPT, tarball], { encoding: "utf8" }); expect(result.status).not.toBe(0); expect(result.stderr).toContain("inventory omits imported dist file dist/chunk.cjs"); }, "2026.4.27", ); }); it("rejects dist files with missing import.meta.url URL dependencies", () => { withTarball( ["dist/index.js"], { "dist/index.js": 'const worker = new URL("./worker.js", import.meta.url);\n' }, (tarball) => { const result = spawnSync("node", [CHECK_SCRIPT, tarball], { encoding: "utf8" }); expect(result.status).not.toBe(0); expect(result.stderr).toContain("dist/index.js imports missing dist/worker.js"); }, "2026.4.27", ); }); it("rejects formatted import.meta.url URL dependencies", () => { withTarball( ["dist/index.js"], { "dist/index.js": [ "const worker = new URL(", ' "./worker.js",', " import.meta.url,", ");", "", ].join("\n"), }, (tarball) => { const result = spawnSync("node", [CHECK_SCRIPT, tarball], { encoding: "utf8" }); expect(result.status).not.toBe(0); expect(result.stderr).toContain("dist/index.js imports missing dist/worker.js"); }, "2026.4.27", ); }); it("rejects import.meta.url URL dependencies omitted from the postinstall inventory", () => { withTarball( ["dist/index.js"], { "dist/index.js": 'const worker = new URL("./worker.js", import.meta.url);\n', "dist/worker.js": "export {};\n", }, (tarball) => { const result = spawnSync("node", [CHECK_SCRIPT, tarball], { encoding: "utf8" }); expect(result.status).not.toBe(0); expect(result.stderr).toContain("inventory omits imported dist file dist/worker.js"); }, "2026.4.27", ); }); it("allows import.meta.url package-root probes", () => { withTarball( ["dist/index.js"], { "dist/index.js": 'const root = new URL("../..", import.meta.url);\n' }, (tarball) => { const result = spawnSync("node", [CHECK_SCRIPT, tarball], { encoding: "utf8" }); expect(result.status, result.stderr).toBe(0); expect(result.stdout).toContain("OpenClaw package tarball integrity passed."); }, "2026.4.27", ); }); it("rejects missing Control UI assets", () => { withTarball( ["dist/index.js"], { "dist/index.js": "export {};\n" }, (tarball) => { const result = spawnSync("node", [CHECK_SCRIPT, tarball], { encoding: "utf8" }); expect(result.status).not.toBe(0); expect(result.stderr).toContain("missing required tar entry dist/control-ui/index.html"); expect(result.stderr).toContain( "missing required tar entries under dist/control-ui/assets/", ); }, "2026.4.27", { includeControlUi: false }, ); }); it("rejects package tarballs without workspace templates", () => { withTarball( ["dist/index.js"], { "dist/index.js": "export {};\n" }, (tarball) => { const result = spawnSync("node", [CHECK_SCRIPT, tarball], { encoding: "utf8" }); expect(result.status).not.toBe(0); for (const relativePath of WORKSPACE_TEMPLATE_PACK_PATHS) { expect(result.stderr).toContain(`missing required tar entry ${relativePath}`); } }, "2026.6.11", { includeWorkspaceTemplates: false }, ); }); it("allows package tarballs without npm lockfiles", () => { withTarball( ["dist/index.js"], { "dist/index.js": "export {};\n" }, (tarball) => { const result = spawnSync("node", [CHECK_SCRIPT, tarball], { encoding: "utf8" }); expect(result.status, result.stderr).toBe(0); expect(result.stdout).toContain("OpenClaw package tarball integrity passed."); }, "2026.5.20", { includeShrinkwrap: false }, ); }); it("rejects package-lock.json in package tarballs", () => { withTarball( ["dist/index.js"], { "dist/index.js": "export {};\n", "package-lock.json": "{}\n" }, (tarball) => { const result = spawnSync("node", [CHECK_SCRIPT, tarball], { encoding: "utf8" }); expect(result.status).not.toBe(0); expect(result.stderr).toContain("package tarball must not contain package-lock.json"); }, "2026.4.27", ); }); it("rejects workspace protocol dependencies in package manifests", () => { withTarball( ["dist/index.js"], { "dist/index.js": "export {};\n" }, (tarball) => { const result = spawnSync("node", [CHECK_SCRIPT, tarball], { encoding: "utf8" }); expect(result.status).not.toBe(0); expect(result.stderr).toContain( "package.json dependencies.@openclaw/ai must not use workspace protocol workspace:*", ); }, "2026.6.11", { packageJson: { dependencies: { "@openclaw/ai": "workspace:*" } } }, ); }); it("rejects npm-shrinkwrap.json after the 2026.7.2 transition train", () => { withTarball( ["dist/index.js"], { "dist/index.js": "export {};\n", "npm-shrinkwrap.json": "{}\n" }, (tarball) => { const result = spawnSync("node", [CHECK_SCRIPT, tarball], { encoding: "utf8" }); expect(result.status).not.toBe(0); expect(result.stderr).toContain("package tarball must not contain npm-shrinkwrap.json"); }, "2026.7.3", ); }); it.each(["2026.7.2-beta.4", "2026.7.2"])( "tolerates a valid shrinkwrap in the %s transition train", (version) => { withTarball( ["dist/index.js"], { "dist/index.js": "export {};\n", "npm-shrinkwrap.json": `${JSON.stringify({ name: "openclaw", version, lockfileVersion: 3, packages: { "": { name: "openclaw", version } }, })}\n`, }, (tarball) => { const result = spawnSync("node", [CHECK_SCRIPT, tarball], { encoding: "utf8" }); expect(result.status, result.stderr).toBe(0); expect(result.stderr).toContain( "2026.7.2 transition package contains npm-shrinkwrap.json", ); }, version, ); }, ); it("accepts a valid shrinkwrap in an already-published package", () => { const version = "2026.6.11"; withTarball( ["dist/index.js"], { "dist/index.js": "export {};\n", "npm-shrinkwrap.json": `${JSON.stringify({ name: "openclaw", version, lockfileVersion: 3, packages: { "": { name: "openclaw", version } }, })}\n`, }, (tarball) => { const result = spawnSync("node", [CHECK_SCRIPT, tarball], { encoding: "utf8" }); expect(result.status, result.stderr).toBe(0); }, version, ); }); it("accepts separately published private workspace dependencies by default", () => { withTarball( ["dist/index.js"], { "dist/index.js": "export {};\n" }, (tarball) => { const result = spawnSync("node", [CHECK_SCRIPT, tarball], { encoding: "utf8" }); expect(result.status, result.stderr).toBe(0); expect(result.stdout).toContain("OpenClaw package tarball integrity passed."); }, "2026.6.11", { packageJson: { dependencies: { "@openclaw/ai": "2026.6.11" } } }, ); }); it("rejects private workspace dependencies that are not bundled when strict packaging requires it", () => { withTarball( ["dist/index.js"], { "dist/index.js": "export {};\n" }, (tarball) => { const result = spawnSync( "node", [CHECK_SCRIPT, "--require-bundled-workspace-deps", tarball], { encoding: "utf8" }, ); expect(result.status).not.toBe(0); expect(result.stderr).toContain( "package.json dependencies.@openclaw/ai must be listed in bundleDependencies because it is private to the OpenClaw workspace", ); expect(result.stderr).toContain( "package.json dependencies.@openclaw/ai must be bundled in node_modules/@openclaw/ai", ); }, "2026.6.11", { packageJson: { dependencies: { "@openclaw/ai": "2026.6.11" } } }, ); }); it("rejects private workspace dependencies when only metadata is bundled", () => { withTarball( ["dist/index.js"], { "dist/index.js": "export {};\n", "node_modules/@openclaw/ai/package.json": AI_RUNTIME_PACKAGE_JSON, }, (tarball) => { const result = spawnSync( "node", [CHECK_SCRIPT, "--require-bundled-workspace-deps", tarball], { encoding: "utf8" }, ); expect(result.status).not.toBe(0); expect(result.stderr).toContain( "bundled @openclaw/ai is missing required runtime entry dist/index.mjs", ); expect(result.stderr).toContain( "bundled @openclaw/ai is missing required runtime entry dist/providers.mjs", ); expect(result.stderr).toContain( "bundled @openclaw/ai is missing required runtime entry dist/internal/runtime.mjs", ); }, "2026.6.11", { packageJson: { dependencies: { "@openclaw/ai": "2026.6.11" }, bundleDependencies: ["@openclaw/ai"], }, }, ); }); it("accepts private workspace dependencies when their runtime is bundled", () => { withTarball( ["dist/index.js"], { "dist/index.js": "export {};\n", "node_modules/@openclaw/ai/package.json": AI_RUNTIME_PACKAGE_JSON, "node_modules/@openclaw/ai/dist/index.mjs": "export {};\n", "node_modules/@openclaw/ai/dist/providers.mjs": "export {};\n", "node_modules/@openclaw/ai/dist/transports.mjs": "export {};\n", "node_modules/@openclaw/ai/dist/internal/runtime.mjs": "export {};\n", }, (tarball) => { const result = spawnSync( "node", [CHECK_SCRIPT, "--require-bundled-workspace-deps", tarball], { encoding: "utf8" }, ); expect(result.status, result.stderr).toBe(0); expect(result.stdout).toContain("OpenClaw package tarball integrity passed."); }, "2026.6.11", { packageJson: { dependencies: { "@openclaw/ai": "2026.6.11" }, bundleDependencies: ["@openclaw/ai"], }, }, ); }); it("accepts frozen AI runtimes that predate an optional exported subpath", () => { withTarball( ["dist/index.js"], { "dist/index.js": "export {};\n", "node_modules/@openclaw/ai/package.json": LEGACY_AI_RUNTIME_PACKAGE_JSON, "node_modules/@openclaw/ai/dist/index.mjs": "export {};\n", "node_modules/@openclaw/ai/dist/providers.mjs": "export {};\n", "node_modules/@openclaw/ai/dist/internal/runtime.mjs": "export {};\n", }, (tarball) => { const result = spawnSync( "node", [CHECK_SCRIPT, "--require-bundled-workspace-deps", tarball], { encoding: "utf8" }, ); expect(result.status, result.stderr).toBe(0); expect(result.stdout).toContain("OpenClaw package tarball integrity passed."); }, "2026.7.2-beta.4", { packageJson: { dependencies: { "@openclaw/ai": "2026.7.2-beta.4" }, bundleDependencies: ["@openclaw/ai"], }, }, ); }); it("rejects a missing required bundled AI runtime entry", () => { withTarball( ["dist/index.js"], { "dist/index.js": "export {};\n", "node_modules/@openclaw/ai/package.json": AI_RUNTIME_PACKAGE_JSON, "node_modules/@openclaw/ai/dist/index.mjs": "export {};\n", "node_modules/@openclaw/ai/dist/transports.mjs": "export {};\n", "node_modules/@openclaw/ai/dist/internal/runtime.mjs": "export {};\n", }, (tarball) => { const result = spawnSync( "node", [CHECK_SCRIPT, "--require-bundled-workspace-deps", tarball], { encoding: "utf8" }, ); expect(result.status).not.toBe(0); expect(result.stderr).toContain( "bundled @openclaw/ai is missing required runtime entry dist/providers.mjs", ); }, "2026.6.11", { packageJson: { dependencies: { "@openclaw/ai": "2026.6.11" }, bundleDependencies: ["@openclaw/ai"], }, }, ); }); it("rejects bundled AI entries that its manifest does not export", () => { withTarball( ["dist/index.js"], { "dist/index.js": "export {};\n", "node_modules/@openclaw/ai/package.json": JSON.stringify({ name: "@openclaw/ai", version: "2026.6.11", exports: { ".": "./dist/index.mjs", "./providers": null, "./internal/*": "./dist/internal/*.mjs", }, }), "node_modules/@openclaw/ai/dist/index.mjs": "export {};\n", "node_modules/@openclaw/ai/dist/providers.mjs": "export {};\n", "node_modules/@openclaw/ai/dist/transports.mjs": "export {};\n", "node_modules/@openclaw/ai/dist/internal/runtime.mjs": "export {};\n", }, (tarball) => { const result = spawnSync( "node", [CHECK_SCRIPT, "--require-bundled-workspace-deps", tarball], { encoding: "utf8" }, ); expect(result.status).not.toBe(0); expect(result.stderr).toContain( "bundled @openclaw/ai runtime specifier @openclaw/ai/providers is not resolvable", ); }, "2026.6.11", { packageJson: { dependencies: { "@openclaw/ai": "2026.6.11" }, bundleDependencies: ["@openclaw/ai"], }, }, ); }); it("rejects missing relative imports from bundled AI runtime entries", () => { withTarball( ["dist/index.js"], { "dist/index.js": "export {};\n", "node_modules/@openclaw/ai/package.json": AI_RUNTIME_PACKAGE_JSON, "node_modules/@openclaw/ai/dist/index.mjs": "export {};\n", "node_modules/@openclaw/ai/dist/providers.mjs": "export {};\n", "node_modules/@openclaw/ai/dist/internal/runtime.mjs": 'export * from "./missing.mjs";\n', }, (tarball) => { const result = spawnSync( "node", [CHECK_SCRIPT, "--require-bundled-workspace-deps", tarball], { encoding: "utf8" }, ); expect(result.status).not.toBe(0); expect(result.stderr).toContain( "bundled @openclaw/ai dist/internal/runtime.mjs imports missing dist/internal/missing.mjs", ); }, "2026.6.11", { packageJson: { dependencies: { "@openclaw/ai": "2026.6.11" }, bundleDependencies: ["@openclaw/ai"], }, }, ); }); it("rejects local build metadata entries in package tarballs", () => { withTarball( ["dist/index.js", ...LOCAL_BUILD_METADATA_DIST_PATHS], { "dist/index.js": "export {};\n", ...Object.fromEntries(LOCAL_BUILD_METADATA_DIST_PATHS.map((entry) => [entry, "{}\n"])), }, (tarball) => { const result = spawnSync("node", [CHECK_SCRIPT, tarball], { encoding: "utf8" }); expect(result.status).not.toBe(0); expect(result.stderr).toContain( "forbidden local build metadata tar entry dist/.buildstamp", ); expect(result.stderr).toContain( "forbidden local build metadata tar entry dist/.runtime-postbuildstamp", ); }, "2026.4.27", ); }); it("allows local build metadata in already published legacy packages through 2026.4.26", () => { withTarball( ["dist/index.js", ...LOCAL_BUILD_METADATA_DIST_PATHS], { "dist/index.js": "export {};\n", ...Object.fromEntries(LOCAL_BUILD_METADATA_DIST_PATHS.map((entry) => [entry, "{}\n"])), }, (tarball) => { const result = spawnSync("node", [CHECK_SCRIPT, tarball], { encoding: "utf8" }); expect(result.status, result.stderr).toBe(0); expect(result.stderr).toContain( "legacy package includes local build metadata tar entry dist/.buildstamp", ); expect(result.stderr).toContain( "legacy package includes local build metadata tar entry dist/.runtime-postbuildstamp", ); expect(result.stdout).toContain("OpenClaw package tarball integrity passed."); }, "2026.4.26", ); }); });