smoke-package.mjs 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. #!/usr/bin/env node
  2. import assert from "node:assert/strict";
  3. import { execFile } from "node:child_process";
  4. import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
  5. import { tmpdir } from "node:os";
  6. import { dirname, join, resolve } from "node:path";
  7. import { fileURLToPath } from "node:url";
  8. import { promisify } from "node:util";
  9. import { okResult } from "../mcp/src/core/result-envelope.mjs";
  10. import { sha256, signState, verifyState } from "../mcp/src/core/run-state-integrity.mjs";
  11. import { buildValidPlan } from "./test-plan-fixture.mjs";
  12. const execFileAsync = promisify(execFile);
  13. export async function smokePackage() {
  14. const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
  15. const packageJson = JSON.parse(await readFile(join(root, "package.json"), "utf8"));
  16. const pluginJson = JSON.parse(await readFile(join(root, ".claude-plugin", "plugin.json"), "utf8"));
  17. const manifest = JSON.parse(await readFile(join(root, "skill-package-manifest.json"), "utf8"));
  18. assert.equal(packageJson.version, pluginJson.version);
  19. assert.equal(pluginJson.version, manifest.version);
  20. assert.equal(manifest.entrySkill, "fmode-image-set");
  21. const envelope = okResult({ assistantMessage: "ok" });
  22. assert.equal(envelope.status, "ok");
  23. assert.equal(envelope.assistantMessage, "ok");
  24. const state = { run_id: "run-20260729000000-abcdef", status: "running" };
  25. const secret = "package-smoke-secret";
  26. const signed = signState(state, secret);
  27. assert.equal(verifyState(signed, secret), true);
  28. assert.equal(sha256("image-set").length, 64);
  29. const temp = await mkdtemp(join(tmpdir(), "fmode-image-set-"));
  30. try {
  31. const planPath = join(temp, "prompt-plan.json");
  32. await writeFile(planPath, `${JSON.stringify(buildValidPlan(
  33. "generic consumer product",
  34. "https://images.example.test/product.jpg",
  35. "run-20260729000000-abcdef",
  36. ), null, 2)}\n`, "utf8");
  37. const validator = join(root, "mcp", "src", "features", "image-set", "validate-plan.mjs");
  38. const { stdout } = await execFileAsync(process.execPath, [validator, planPath]);
  39. const validation = JSON.parse(stdout);
  40. assert.equal(validation.valid, true);
  41. assert.equal(validation.images, 7);
  42. } finally {
  43. await rm(temp, { recursive: true, force: true });
  44. }
  45. return {
  46. status: "ok",
  47. version: packageJson.version,
  48. checks: ["version-sync", "result-envelope", "state-integrity", "plan-validation"],
  49. };
  50. }
  51. if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
  52. console.log(JSON.stringify(await smokePackage(), null, 2));
  53. }