Files
open-design/tools/pack/tests/resources.test.ts
T
3447f60a34 fix packaged payload desktop handoff (#5678)
* fix packaged payload desktop handoff

* fix beta mac full smoke fixture wiring

* fix tools-pack mac payload cold start

* test payload desktop update restart

* fix Nix daemon launcher protocol build

* fix(pack): harden Windows long-jump updates

* fix(pack): harden mac long-jump acceptance

* fix(handoff): defer armed journal writes until spawn and shutdown succeed

Previously executeLegacyPayloadDesktopHandoff wrote the armed handoff
journal, attempt, and runtime state before spawning the payload desktop
and before the old desktop accepted shutdown. When spawn() threw or the
shutdown request failed, the armed journal was stranded on disk, so the
next cold start bailed out of prepareLegacyPayloadDesktopHandoff() with
reason "already-armed" and the install stayed pinned to the old desktop
generation indefinitely.

Move the three writes to after both the payload child has spawned and the
shutdown has been accepted. The old desktop is still alive while it acks
the shutdown, and the payload waits for the old pid to exit before
resuming, so the state still lands before the payload reads it. Add
regression coverage for both the spawn-failed and shutdown-failed paths,
asserting the journal stays "prepared" and a later cold start can retry.

Generated-By: looper 0.10.3 (runner=fixer, agent=claude-code)

* fix(updater): await payload spawn acceptance

* fix(packaged): advance confirmed handoff recovery

---------

Co-authored-by: Looper <looper@noreply.github.com>
2026-07-20 02:21:49 +00:00

420 lines
15 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
access,
chmod,
constants,
mkdir,
mkdtemp,
readFile,
rm,
stat,
writeFile,
} from "node:fs/promises";
import { tmpdir } from "node:os";
import { dirname, join } from "node:path";
import process from "node:process";
import { domToPptxBundleResource } from "../src/dom-to-pptx-resource.js";
import { copyBundledResourceTrees } from "../src/resources.js";
import { copyOptionalVelaCliBinary, resolveOptionalVelaCliBinary } from "../src/vela-cli.js";
async function writeFakeOpenCodeCompanion(
source: string,
content = "#!/bin/sh\nexit 0\n",
): Promise<string> {
const companion = join(dirname(source), "libexec", "opencode", "opencode");
await mkdir(dirname(companion), { recursive: true });
await writeFile(companion, content, "utf8");
await chmod(companion, 0o755);
return companion;
}
describe("domToPptxBundleResource", () => {
it("derives the vendored bundle path from the workspace root, not the caller cwd", async () => {
const root = await mkdtemp(join(tmpdir(), "open-design-tools-pack-resource-"));
const workspaceRoot = join(root, "workspace");
const callerCwd = join(root, "caller");
const previousCwd = process.cwd();
try {
await mkdir(workspaceRoot, { recursive: true });
await mkdir(callerCwd, { recursive: true });
process.chdir(callerCwd);
expect(domToPptxBundleResource({ workspaceRoot })).toEqual({
from: join(workspaceRoot, "apps", "desktop", "vendor", "dom-to-pptx", "dom-to-pptx.bundle.js.gz"),
to: "dom-to-pptx.bundle.js.gz",
});
} finally {
process.chdir(previousCwd);
await rm(root, { force: true, recursive: true });
}
});
});
describe("copyBundledResourceTrees", () => {
it("includes daemon resource trees", async () => {
const root = await mkdtemp(join(tmpdir(), "open-design-tools-pack-"));
const workspaceRoot = join(root, "workspace");
const resourceRoot = join(root, "resources");
try {
const promptTemplatePath = join(
workspaceRoot,
"prompt-templates",
"image",
"sample.json",
);
const designTemplatePath = join(
workspaceRoot,
"design-templates",
"orbit-general",
"SKILL.md",
);
const communityPetPath = join(
workspaceRoot,
"assets",
"community-pets",
"sample",
"pet.json",
);
const communityRegistryPath = join(
workspaceRoot,
"plugins",
"registry",
"community",
"open-design-marketplace.json",
);
await mkdir(join(workspaceRoot, "skills", "sample"), { recursive: true });
// The skills/design-templates split (see specs/current/
// skills-and-design-templates.md) added a separate top-level
// `design-templates/` tree that copyBundledResourceTrees now also
// bundles. Create it in the fixture so the recursive copy does not
// fail with ENOENT before reaching the prompt-templates assertion.
await mkdir(join(workspaceRoot, "design-templates", "orbit-general"), {
recursive: true,
});
await mkdir(join(workspaceRoot, "design-systems", "sample"), {
recursive: true,
});
await mkdir(join(workspaceRoot, "craft", "sample"), { recursive: true });
await mkdir(join(workspaceRoot, "plugins", "_official", "sample"), {
recursive: true,
});
await mkdir(join(workspaceRoot, "plugins", "registry", "community"), {
recursive: true,
});
await mkdir(join(workspaceRoot, "assets", "frames"), { recursive: true });
await mkdir(join(workspaceRoot, "assets", "community-pets", "sample"), {
recursive: true,
});
await mkdir(join(workspaceRoot, "prompt-templates", "image"), {
recursive: true,
});
await mkdir(join(workspaceRoot, "data", "plugin-previews"), {
recursive: true,
});
await writeFile(promptTemplatePath, "{\"id\":\"sample\"}\n", "utf8");
await writeFile(
join(workspaceRoot, "data", "plugin-previews", "manifest.json"),
"{\"previews\":{}}\n",
"utf8",
);
await writeFile(designTemplatePath, "# Orbit General\n", "utf8");
await writeFile(communityPetPath, "{\"name\":\"sample\"}\n", "utf8");
await writeFile(
join(workspaceRoot, "plugins", "_official", "sample", "open-design.json"),
"{\"id\":\"sample\"}\n",
"utf8",
);
await writeFile(communityRegistryPath, "{\"plugins\":[]}\n", "utf8");
await copyBundledResourceTrees({ workspaceRoot, resourceRoot });
await expect(
readFile(
join(resourceRoot, "prompt-templates", "image", "sample.json"),
"utf8",
),
).resolves.toBe("{\"id\":\"sample\"}\n");
// The baked plugin-preview manifest must land under data/plugin-previews so
// the packaged daemon can map plugins to their R2 clips; without it the
// gallery silently falls back to live iframes.
await expect(
readFile(
join(resourceRoot, "data", "plugin-previews", "manifest.json"),
"utf8",
),
).resolves.toBe("{\"previews\":{}}\n");
await expect(
readFile(
join(resourceRoot, "design-templates", "orbit-general", "SKILL.md"),
"utf8",
),
).resolves.toBe("# Orbit General\n");
await expect(
readFile(
join(resourceRoot, "community-pets", "sample", "pet.json"),
"utf8",
),
).resolves.toBe("{\"name\":\"sample\"}\n");
await expect(
readFile(
join(resourceRoot, "plugins", "_official", "sample", "open-design.json"),
"utf8",
),
).resolves.toBe("{\"id\":\"sample\"}\n");
await expect(
readFile(
join(
resourceRoot,
"plugins",
"registry",
"community",
"open-design-marketplace.json",
),
"utf8",
),
).resolves.toBe("{\"plugins\":[]}\n");
} finally {
await rm(root, { force: true, recursive: true });
}
});
});
describe("copyOptionalVelaCliBinary", () => {
it("copies the installed Vela CLI through the default npm resolver", async () => {
const root = await mkdtemp(join(tmpdir(), "open-design-tools-pack-vela-installed-"));
const resourceRoot = join(root, "resources", "open-design");
const platform = process.platform === "win32" ? "win" : process.platform === "darwin" ? "mac" : "linux";
try {
const copied = await copyOptionalVelaCliBinary({
env: {},
platform,
requireBundled: true,
resourceRoot,
});
const target = join(resourceRoot, "bin", process.platform === "win32" ? "vela.exe" : "vela");
expect(copied?.target).toBe(target);
await expect(access(target)).resolves.toBeUndefined();
const openCodeName = process.platform === "win32" ? "opencode.exe" : "opencode";
await expect(access(join(resourceRoot, "bin", "libexec", "opencode", openCodeName))).resolves.toBeUndefined();
} finally {
await rm(root, { force: true, recursive: true });
}
});
it("copies a configured Vela CLI binary into the POSIX resource bin", async () => {
const root = await mkdtemp(join(tmpdir(), "open-design-tools-pack-vela-"));
const source = join(root, "source", "vela");
const resourceRoot = join(root, "resources", "open-design");
try {
await mkdir(join(root, "source"), { recursive: true });
await writeFile(source, "#!/bin/sh\nexit 0\n", "utf8");
await writeFakeOpenCodeCompanion(source, "#!/bin/sh\necho opencode\n");
const copied = await copyOptionalVelaCliBinary({
env: { OPEN_DESIGN_VELA_CLI_BIN: source },
platform: "mac",
requireBundled: true,
resourceRoot,
});
const target = join(resourceRoot, "bin", "vela");
const companionTarget = join(resourceRoot, "bin", "libexec", "opencode", "opencode");
await expect(readFile(target, "utf8")).resolves.toBe("#!/bin/sh\nexit 0\n");
await expect(readFile(companionTarget, "utf8")).resolves.toBe(
"#!/bin/sh\necho opencode\n",
);
await expect(access(target, constants.X_OK)).resolves.toBeUndefined();
await expect(access(companionTarget, constants.X_OK)).resolves.toBeUndefined();
expect(copied).toEqual({ source, target });
if (process.platform !== "win32") {
expect((await stat(target)).mode & 0o111).not.toBe(0);
expect((await stat(companionTarget)).mode & 0o111).not.toBe(0);
}
} finally {
await rm(root, { force: true, recursive: true });
}
});
it("fails strict mode when the OpenCode companion tree is missing", async () => {
const root = await mkdtemp(join(tmpdir(), "open-design-tools-pack-vela-strict-"));
const source = join(root, "source", "vela");
const resourceRoot = join(root, "resources", "open-design");
try {
await mkdir(join(root, "source"), { recursive: true });
await writeFile(source, "#!/bin/sh\nexit 0\n", "utf8");
await expect(
copyOptionalVelaCliBinary({
env: { OPEN_DESIGN_VELA_CLI_BIN: source },
platform: "mac",
requireBundled: true,
resourceRoot,
}),
).rejects.toThrow(/OpenCode companion directory is missing.*OPEN_DESIGN_VELA_CLI_BIN/);
} finally {
await rm(root, { force: true, recursive: true });
}
});
it("copies the Vela CLI binary without a companion tree in non-strict mode", async () => {
const root = await mkdtemp(join(tmpdir(), "open-design-tools-pack-vela-nonstrict-"));
const source = join(root, "source", "vela");
const resourceRoot = join(root, "resources", "open-design");
try {
await mkdir(join(root, "source"), { recursive: true });
await writeFile(source, "#!/bin/sh\nexit 0\n", "utf8");
const copied = await copyOptionalVelaCliBinary({
env: { OPEN_DESIGN_VELA_CLI_BIN: source },
platform: "mac",
requireBundled: false,
resourceRoot,
});
const target = join(resourceRoot, "bin", "vela");
const companionTarget = join(resourceRoot, "bin", "libexec", "opencode", "opencode");
await expect(readFile(target, "utf8")).resolves.toBe("#!/bin/sh\nexit 0\n");
await expect(access(companionTarget)).rejects.toThrow();
expect(copied).toEqual({ source, target });
} finally {
await rm(root, { force: true, recursive: true });
}
});
it("copies a configured Vela CLI binary into the Windows resource bin", async () => {
const root = await mkdtemp(join(tmpdir(), "open-design-tools-pack-vela-win-"));
const source = join(root, "source", "vela.exe");
const resourceRoot = join(root, "resources", "open-design");
try {
await mkdir(join(root, "source"), { recursive: true });
await writeFile(source, "fake exe\n", "utf8");
await writeFakeOpenCodeCompanion(source, "fake opencode\n");
const copied = await copyOptionalVelaCliBinary({
env: { OPEN_DESIGN_VELA_CLI_BIN: source },
platform: "win",
resourceRoot,
});
const target = join(resourceRoot, "bin", "vela.exe");
const companionTarget = join(resourceRoot, "bin", "libexec", "opencode", "opencode");
await expect(readFile(target, "utf8")).resolves.toBe("fake exe\n");
await expect(readFile(companionTarget, "utf8")).resolves.toBe("fake opencode\n");
expect(copied).toEqual({ source, target });
} finally {
await rm(root, { force: true, recursive: true });
}
});
it("copies a Vela CLI binary resolved from the npm package", async () => {
const root = await mkdtemp(join(tmpdir(), "open-design-tools-pack-vela-npm-"));
const source = join(root, "source", "vela");
const resourceRoot = join(root, "resources", "open-design");
try {
await mkdir(join(root, "source"), { recursive: true });
await writeFile(source, "#!/bin/sh\nexit 0\n", "utf8");
await writeFakeOpenCodeCompanion(source, "#!/bin/sh\necho opencode\n");
const copied = await copyOptionalVelaCliBinary({
env: {},
importPackage: async () => ({
resolveVelaCliBin: () => source,
}),
platform: "mac",
requireBundled: true,
resourceRoot,
});
const target = join(resourceRoot, "bin", "vela");
const companionTarget = join(resourceRoot, "bin", "libexec", "opencode", "opencode");
await expect(readFile(target, "utf8")).resolves.toBe("#!/bin/sh\nexit 0\n");
await expect(readFile(companionTarget, "utf8")).resolves.toBe(
"#!/bin/sh\necho opencode\n",
);
await expect(access(target, constants.X_OK)).resolves.toBeUndefined();
expect(copied).toEqual({ source, target });
} finally {
await rm(root, { force: true, recursive: true });
}
});
it("skips copying when the npm resolver reports an unsupported non-strict platform", async () => {
const root = await mkdtemp(join(tmpdir(), "open-design-tools-pack-vela-skip-"));
const resourceRoot = join(root, "resources", "open-design");
try {
const copied = await copyOptionalVelaCliBinary({
env: {},
importPackage: async () => ({
resolveVelaCliBin: () => null,
}),
platform: "linux",
resourceRoot,
});
expect(copied).toBeNull();
await expect(access(join(resourceRoot, "bin", "vela"))).rejects.toThrow();
} finally {
await rm(root, { force: true, recursive: true });
}
});
});
describe("resolveOptionalVelaCliBinary", () => {
it("prefers OPEN_DESIGN_VELA_CLI_BIN over the npm resolver", async () => {
await expect(
resolveOptionalVelaCliBinary({
env: { OPEN_DESIGN_VELA_CLI_BIN: "/tmp/local-vela" },
importPackage: async () => ({
resolveVelaCliBin: () => "/tmp/npm-vela",
}),
}),
).resolves.toBe("/tmp/local-vela");
});
it("fails strict mode when the resolver package is missing", async () => {
await expect(
resolveOptionalVelaCliBinary({
env: {},
importPackage: async () => {
throw new Error("not installed");
},
requireBundled: true,
}),
).rejects.toThrow(/@powerformer\/vela-cli.*OPEN_DESIGN_VELA_CLI_BIN/);
});
it("fails strict mode when the resolver returns no binary", async () => {
await expect(
resolveOptionalVelaCliBinary({
env: {},
importPackage: async () => ({
resolveVelaCliBin: () => ({ supported: false }),
}),
requireBundled: true,
}),
).rejects.toThrow(/@powerformer\/vela-cli.*OPEN_DESIGN_VELA_CLI_BIN/);
});
it("returns null in non-strict mode when the resolver package is missing", async () => {
await expect(
resolveOptionalVelaCliBinary({
env: {},
importPackage: async () => {
throw new Error("not installed");
},
}),
).resolves.toBeNull();
});
});