release-skill 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.codebuddy-plugin/plugin.json +1 -1
  4. package/.codex-plugin/plugin.json +2 -2
  5. package/.kimi-plugin/plugin.json +1 -1
  6. package/CHANGELOG.md +21 -0
  7. package/INSTALL.md +183 -21
  8. package/INSTALL.zh-CN.md +160 -16
  9. package/README.md +112 -11
  10. package/README.zh-CN.md +73 -10
  11. package/adapters/claude/.claude-plugin/marketplace.json +1 -1
  12. package/adapters/claude/.claude-plugin/plugin.json +1 -1
  13. package/adapters/claude/bin/release-skill.bundle.mjs +1718 -600
  14. package/adapters/claude/schemas/release-plan.schema.json +44 -2
  15. package/adapters/claude/schemas/release-project.schema.json +46 -4
  16. package/adapters/claude/schemas/release-run.schema.json +1 -0
  17. package/adapters/codex/.codex-plugin/plugin.json +2 -2
  18. package/adapters/codex/bin/release-skill.bundle.mjs +1718 -600
  19. package/adapters/codex/schemas/release-plan.schema.json +44 -2
  20. package/adapters/codex/schemas/release-project.schema.json +46 -4
  21. package/adapters/codex/schemas/release-run.schema.json +1 -0
  22. package/adapters/kimi/.kimi-plugin/plugin.json +1 -1
  23. package/adapters/kimi/bin/release-skill.bundle.mjs +1718 -600
  24. package/adapters/kimi/schemas/release-plan.schema.json +44 -2
  25. package/adapters/kimi/schemas/release-project.schema.json +46 -4
  26. package/adapters/kimi/schemas/release-run.schema.json +1 -0
  27. package/adapters/workbuddy/.codebuddy-plugin/plugin.json +4 -2
  28. package/adapters/workbuddy/bin/release-skill.bundle.mjs +1718 -600
  29. package/adapters/workbuddy/schemas/release-plan.schema.json +44 -2
  30. package/adapters/workbuddy/schemas/release-project.schema.json +46 -4
  31. package/adapters/workbuddy/schemas/release-run.schema.json +1 -0
  32. package/bin/release-skill-cli.mjs +46 -4
  33. package/bin/release-skill.bundle.mjs +1718 -600
  34. package/package.json +1 -1
  35. package/references/02-project-config.md +7 -0
  36. package/references/06-adapter-contract.md +21 -2
  37. package/schemas/release-plan.schema.json +44 -2
  38. package/schemas/release-project.schema.json +46 -4
  39. package/schemas/release-run.schema.json +1 -0
  40. package/scripts/sync-public-files.mjs +8 -4
  41. package/src/adapters/contract.mjs +1 -0
  42. package/src/adapters/plugin-marketplace.mjs +536 -23
  43. package/src/commands/assess.mjs +50 -1
  44. package/src/commands/prepare.mjs +273 -9
  45. package/src/commands/publish.mjs +1 -0
  46. package/src/commands/reconcile.mjs +1 -0
  47. package/src/commands/setup.mjs +7 -3
  48. package/src/commands/verify.mjs +2 -0
  49. package/src/core/checkpoints.mjs +7 -2
  50. package/src/core/plan.mjs +97 -4
  51. package/src/core/verification-gates.mjs +1 -1
  52. package/src/platforms/codebuddy.mjs +618 -0
  53. package/src/platforms/registry.mjs +100 -5
  54. package/src/producers/build-adapters.mjs +21 -13
@@ -9,7 +9,7 @@ const __bundlePkgRoot = __bundleResolve(__bundleDirname(__bundleFileURLToPath(im
9
9
  // Provide a real require() for CJS packages bundled into ESM (e.g. yaml, ajv).
10
10
  const __bundleRealRequire = __bundleCreateRequire(import.meta.url);
11
11
  // Package identity injected at build time — closure-independent --version probe.
12
- const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.2.1"});
12
+ const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.2.2"});
13
13
 
14
14
  var __create = Object.create;
15
15
  var __defProp = Object.defineProperty;
@@ -11041,7 +11041,7 @@ var require_compile = __commonJS({
11041
11041
  const schOrFunc = root.refs[ref];
11042
11042
  if (schOrFunc)
11043
11043
  return schOrFunc;
11044
- let _sch = resolve24.call(this, root, ref);
11044
+ let _sch = resolve25.call(this, root, ref);
11045
11045
  if (_sch === void 0) {
11046
11046
  const schema2 = (_a = root.localRefs) === null || _a === void 0 ? void 0 : _a[ref];
11047
11047
  const { schemaId } = this.opts;
@@ -11072,13 +11072,13 @@ var require_compile = __commonJS({
11072
11072
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
11073
11073
  }
11074
11074
  __name(sameSchemaEnv, "sameSchemaEnv");
11075
- function resolve24(root, ref) {
11075
+ function resolve25(root, ref) {
11076
11076
  let sch;
11077
11077
  while (typeof (sch = this.refs[ref]) == "string")
11078
11078
  ref = sch;
11079
11079
  return sch || this.schemas[ref] || resolveSchema.call(this, root, ref);
11080
11080
  }
11081
- __name(resolve24, "resolve");
11081
+ __name(resolve25, "resolve");
11082
11082
  function resolveSchema(root, ref) {
11083
11083
  const p = this.opts.uriResolver.parse(ref);
11084
11084
  const refPath = (0, resolve_1._getFullPath)(this.opts.uriResolver, p);
@@ -11730,56 +11730,56 @@ var require_fast_uri = __commonJS({
11730
11730
  return uri;
11731
11731
  }
11732
11732
  __name(normalize4, "normalize");
11733
- function resolve24(baseURI, relativeURI, options) {
11733
+ function resolve25(baseURI, relativeURI, options) {
11734
11734
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
11735
11735
  const resolved = resolveComponent(parse2(baseURI, schemelessOptions), parse2(relativeURI, schemelessOptions), schemelessOptions, true);
11736
11736
  schemelessOptions.skipEscape = true;
11737
11737
  return serialize(resolved, schemelessOptions);
11738
11738
  }
11739
- __name(resolve24, "resolve");
11740
- function resolveComponent(base, relative21, options, skipNormalization) {
11739
+ __name(resolve25, "resolve");
11740
+ function resolveComponent(base, relative22, options, skipNormalization) {
11741
11741
  const target = {};
11742
11742
  if (!skipNormalization) {
11743
11743
  base = parse2(serialize(base, options), options);
11744
- relative21 = parse2(serialize(relative21, options), options);
11744
+ relative22 = parse2(serialize(relative22, options), options);
11745
11745
  }
11746
11746
  options = options || {};
11747
- if (!options.tolerant && relative21.scheme) {
11748
- target.scheme = relative21.scheme;
11749
- target.userinfo = relative21.userinfo;
11750
- target.host = relative21.host;
11751
- target.port = relative21.port;
11752
- target.path = removeDotSegments(relative21.path || "");
11753
- target.query = relative21.query;
11747
+ if (!options.tolerant && relative22.scheme) {
11748
+ target.scheme = relative22.scheme;
11749
+ target.userinfo = relative22.userinfo;
11750
+ target.host = relative22.host;
11751
+ target.port = relative22.port;
11752
+ target.path = removeDotSegments(relative22.path || "");
11753
+ target.query = relative22.query;
11754
11754
  } else {
11755
- if (relative21.userinfo !== void 0 || relative21.host !== void 0 || relative21.port !== void 0) {
11756
- target.userinfo = relative21.userinfo;
11757
- target.host = relative21.host;
11758
- target.port = relative21.port;
11759
- target.path = removeDotSegments(relative21.path || "");
11760
- target.query = relative21.query;
11755
+ if (relative22.userinfo !== void 0 || relative22.host !== void 0 || relative22.port !== void 0) {
11756
+ target.userinfo = relative22.userinfo;
11757
+ target.host = relative22.host;
11758
+ target.port = relative22.port;
11759
+ target.path = removeDotSegments(relative22.path || "");
11760
+ target.query = relative22.query;
11761
11761
  } else {
11762
- if (!relative21.path) {
11762
+ if (!relative22.path) {
11763
11763
  target.path = base.path;
11764
- if (relative21.query !== void 0) {
11765
- target.query = relative21.query;
11764
+ if (relative22.query !== void 0) {
11765
+ target.query = relative22.query;
11766
11766
  } else {
11767
11767
  target.query = base.query;
11768
11768
  }
11769
11769
  } else {
11770
- if (relative21.path[0] === "/") {
11771
- target.path = removeDotSegments(relative21.path);
11770
+ if (relative22.path[0] === "/") {
11771
+ target.path = removeDotSegments(relative22.path);
11772
11772
  } else {
11773
11773
  if ((base.userinfo !== void 0 || base.host !== void 0 || base.port !== void 0) && !base.path) {
11774
- target.path = "/" + relative21.path;
11774
+ target.path = "/" + relative22.path;
11775
11775
  } else if (!base.path) {
11776
- target.path = relative21.path;
11776
+ target.path = relative22.path;
11777
11777
  } else {
11778
- target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative21.path;
11778
+ target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative22.path;
11779
11779
  }
11780
11780
  target.path = removeDotSegments(target.path);
11781
11781
  }
11782
- target.query = relative21.query;
11782
+ target.query = relative22.query;
11783
11783
  }
11784
11784
  target.userinfo = base.userinfo;
11785
11785
  target.host = base.host;
@@ -11787,7 +11787,7 @@ var require_fast_uri = __commonJS({
11787
11787
  }
11788
11788
  target.scheme = base.scheme;
11789
11789
  }
11790
- target.fragment = relative21.fragment;
11790
+ target.fragment = relative22.fragment;
11791
11791
  return target;
11792
11792
  }
11793
11793
  __name(resolveComponent, "resolveComponent");
@@ -11998,7 +11998,7 @@ var require_fast_uri = __commonJS({
11998
11998
  var fastUri = {
11999
11999
  SCHEMES,
12000
12000
  normalize: normalize4,
12001
- resolve: resolve24,
12001
+ resolve: resolve25,
12002
12002
  resolveComponent,
12003
12003
  equal,
12004
12004
  serialize,
@@ -16344,7 +16344,7 @@ async function walkDiscoveryFiles(root, maxDepth = 8) {
16344
16344
  const absolute = join2(directory, child.name);
16345
16345
  if (child.isDirectory()) {
16346
16346
  if (!SKIP_DIRS.has(child.name)) await walk(absolute, depth + 1);
16347
- } else if (child.isFile() && (child.name === "package.json" || child.name === "public-release.json" || child.name === "SKILL.md" || /^README(?:\.|$)/i.test(child.name) || /^LICENSE(?:\.|$)/i.test(child.name) || /^CHANGELOG(?:\.|$)/i.test(child.name) || absolute.endsWith("/.claude-plugin/plugin.json") || absolute.endsWith("/.codex-plugin/plugin.json") || absolute.endsWith("/.kimi-plugin/plugin.json") || absolute.endsWith("/.claude-plugin/marketplace.json") || absolute.endsWith("/.codex-plugin/marketplace.json"))) {
16347
+ } else if (child.isFile() && (child.name === "package.json" || child.name === "public-release.json" || child.name === "SKILL.md" || /^README(?:\.|$)/i.test(child.name) || /^LICENSE(?:\.|$)/i.test(child.name) || /^CHANGELOG(?:\.|$)/i.test(child.name) || absolute.endsWith("/.claude-plugin/plugin.json") || absolute.endsWith("/.codex-plugin/plugin.json") || absolute.endsWith("/.kimi-plugin/plugin.json") || absolute.endsWith("/.codebuddy-plugin/plugin.json") || absolute.endsWith("/.claude-plugin/marketplace.json") || absolute.endsWith("/.codex-plugin/marketplace.json"))) {
16348
16348
  found.push(absolute);
16349
16349
  }
16350
16350
  }
@@ -16601,7 +16601,7 @@ async function discoverFacts(root) {
16601
16601
  const value = await readJsonBounded(path3, "discovered plugin manifest");
16602
16602
  manifests.push({
16603
16603
  path: safeRelative(root, path3),
16604
- host: path3.includes("/.claude-plugin/") ? "claude" : path3.includes("/.kimi-plugin/") ? "kimi" : "codex",
16604
+ host: path3.includes("/.claude-plugin/") ? "claude" : path3.includes("/.kimi-plugin/") ? "kimi" : path3.includes("/.codebuddy-plugin/") ? "codebuddy" : "codex",
16605
16605
  kind: path3.endsWith("/marketplace.json") ? "marketplace" : "plugin",
16606
16606
  name: typeof value.name === "string" ? value.name : null,
16607
16607
  version: typeof value.version === "string" ? value.version : null
@@ -16620,7 +16620,7 @@ async function discoverFacts(root) {
16620
16620
  return {
16621
16621
  path: relPath,
16622
16622
  name: skillIndex >= 0 ? segments[skillIndex + 1] ?? null : null,
16623
- host: relPath.includes("/adapters/claude/") ? "claude" : relPath.includes("/adapters/codex/") ? "codex" : relPath.includes("/adapters/kimi/") ? "kimi" : "shared"
16623
+ host: relPath.includes("/adapters/claude/") ? "claude" : relPath.includes("/adapters/codex/") ? "codex" : relPath.includes("/adapters/kimi/") ? "kimi" : relPath.includes("/adapters/workbuddy/") ? "codebuddy" : "shared"
16624
16624
  };
16625
16625
  }).filter((item) => item.name).sort((a, b) => canonicalJson(a).localeCompare(canonicalJson(b)));
16626
16626
  const unitGit = {};
@@ -16764,7 +16764,7 @@ function buildCandidates(facts) {
16764
16764
  const ids = /* @__PURE__ */ new Set();
16765
16765
  const knownFiles = new Set(facts.fileDigests.map((file) => file.path));
16766
16766
  const manifestRoots = facts.manifests.map((manifest) => {
16767
- const match = manifest.path.match(/^(.*?)(?:\/)?(?:\.claude-plugin|\.codex-plugin|\.kimi-plugin)\/(?:plugin|marketplace)\.json$/);
16767
+ const match = manifest.path.match(/^(.*?)(?:\/)?(?:\.claude-plugin|\.codex-plugin|\.kimi-plugin|\.codebuddy-plugin)\/(?:plugin|marketplace)\.json$/);
16768
16768
  return { ...manifest, root: match?.[1] || "." };
16769
16769
  });
16770
16770
  const manifestOwners = /* @__PURE__ */ new Map();
@@ -16791,6 +16791,7 @@ function buildCandidates(facts) {
16791
16791
  if (pluginHosts.includes("claude")) distributions.push("claude-plugin");
16792
16792
  if (pluginHosts.includes("codex")) distributions.push("codex-plugin");
16793
16793
  if (pluginHosts.includes("kimi")) distributions.push("kimi-plugin");
16794
+ if (pluginHosts.includes("codebuddy")) distributions.push("codebuddy-plugin");
16794
16795
  if (pkg.private && matchingLegacyUnits.length === 0 && facts.legacyReleaseConfigs.length > 0) continue;
16795
16796
  if (pkg.private && distributions.length === 0) continue;
16796
16797
  const unitGitEntry = unitGit[pkg.directory];
@@ -18196,7 +18197,7 @@ function identifyTopology(config) {
18196
18197
  const uniqueDistTypes = [...new Set(allDistTypes)];
18197
18198
  let type = "unknown";
18198
18199
  const hasNpm = uniqueDistTypes.includes("npm");
18199
- const hasPlugin = uniqueDistTypes.includes("claude-plugin") || uniqueDistTypes.includes("codex-plugin") || uniqueDistTypes.includes("kimi-plugin");
18200
+ const hasPlugin = uniqueDistTypes.includes("claude-plugin") || uniqueDistTypes.includes("codex-plugin") || uniqueDistTypes.includes("kimi-plugin") || uniqueDistTypes.includes("codebuddy-plugin");
18200
18201
  if (units.length === 0) {
18201
18202
  type = "no-release-units";
18202
18203
  } else if (units.length === 1) {
@@ -18453,6 +18454,53 @@ async function checkPluginManifests(root, config) {
18453
18454
  }
18454
18455
  }
18455
18456
  }
18457
+ if (distributionTypes.has("codebuddy-plugin")) {
18458
+ const manifestPath = resolve7(unitRoot, ".codebuddy-plugin", "plugin.json");
18459
+ const displayPath = unitFile(unit, ".codebuddy-plugin/plugin.json");
18460
+ const exists = await fileExists(manifestPath);
18461
+ if (!exists) {
18462
+ gaps.push(
18463
+ createGap({
18464
+ scope: GapScope.PROFILE,
18465
+ category: GapCategory.MANIFEST,
18466
+ severity: Severity.ERROR,
18467
+ code: "CODEBUDDY_MANIFEST_MISSING",
18468
+ message: `\u53D1\u5E03\u5355\u5143 "${unit.id}" \u7F3A\u5C11 .codebuddy-plugin/plugin.json \u63D2\u4EF6\u6E05\u5355`,
18469
+ file: displayPath
18470
+ })
18471
+ );
18472
+ } else {
18473
+ try {
18474
+ const content = await readFile5(manifestPath, "utf8");
18475
+ const manifest = JSON.parse(content);
18476
+ const requiredFields = ["name", "version", "description"];
18477
+ const missingFields = requiredFields.filter((f) => !(f in manifest));
18478
+ if (missingFields.length > 0) {
18479
+ gaps.push(
18480
+ createGap({
18481
+ scope: GapScope.PROFILE,
18482
+ category: GapCategory.MANIFEST,
18483
+ severity: Severity.ERROR,
18484
+ code: "CODEBUDDY_MANIFEST_INCOMPLETE",
18485
+ message: `CodeBuddy \u63D2\u4EF6\u6E05\u5355\u7F3A\u5C11\u5FC5\u586B\u5B57\u6BB5: ${missingFields.join(", ")}`,
18486
+ file: displayPath
18487
+ })
18488
+ );
18489
+ }
18490
+ } catch {
18491
+ gaps.push(
18492
+ createGap({
18493
+ scope: GapScope.PROFILE,
18494
+ category: GapCategory.MANIFEST,
18495
+ severity: Severity.ERROR,
18496
+ code: "CODEBUDDY_MANIFEST_INVALID",
18497
+ message: ".codebuddy-plugin/plugin.json \u89E3\u6790\u5931\u8D25",
18498
+ file: displayPath
18499
+ })
18500
+ );
18501
+ }
18502
+ }
18503
+ }
18456
18504
  }
18457
18505
  return gaps;
18458
18506
  }
@@ -19717,7 +19765,7 @@ function validateGate(gate) {
19717
19765
  if (!gate.scope || typeof gate.scope.unit !== "string") {
19718
19766
  throw gateError(gate, "must declare scope.unit");
19719
19767
  }
19720
- if (gate.phase === "consumer-verify" && !["npm", "claude-plugin", "codex-plugin", "kimi-plugin"].includes(gate.scope.distribution)) {
19768
+ if (gate.phase === "consumer-verify" && !["npm", "claude-plugin", "codex-plugin", "kimi-plugin", "codebuddy-plugin"].includes(gate.scope.distribution)) {
19721
19769
  throw gateError(gate, "consumer-verify must declare a supported scope.distribution");
19722
19770
  }
19723
19771
  if (!Array.isArray(gate.command) || gate.command.length === 0 || gate.command.some((value) => typeof value !== "string")) {
@@ -20376,6 +20424,7 @@ var init_contract = __esm({
20376
20424
  CLAUDE_MARKETPLACE_INSTALL: "claude-marketplace-install",
20377
20425
  CODEX_MARKETPLACE_INSTALL: "codex-marketplace-install",
20378
20426
  KIMI_MARKETPLACE_INSTALL: "kimi-marketplace-install",
20427
+ CODEBUDDY_MARKETPLACE_INSTALL: "codebuddy-marketplace-install",
20379
20428
  // default branch management
20380
20429
  SET_DEFAULT_BRANCH: "set-default-branch"
20381
20430
  });
@@ -20707,8 +20756,356 @@ var init_kimi = __esm({
20707
20756
  }
20708
20757
  });
20709
20758
 
20759
+ // src/platforms/codebuddy.mjs
20760
+ import { readFile as readFile8, mkdir as mkdir8 } from "node:fs/promises";
20761
+ import { join as join7, resolve as resolve12, relative as relative10, isAbsolute as isAbsolute9 } from "node:path";
20762
+ function normalizePlanForDigest2(plan) {
20763
+ const normalized = { ...plan, status: "PREPARED" };
20764
+ if (Array.isArray(plan.externalActions)) {
20765
+ normalized.externalActions = plan.externalActions.map((action) => action && typeof action === "object" && !Array.isArray(action) ? { ...action, status: "PENDING" } : action);
20766
+ }
20767
+ return normalized;
20768
+ }
20769
+ async function resolveCodeBuddyBoundPlanDigest(context) {
20770
+ const plan = context?.plan;
20771
+ if (!plan || typeof plan !== "object" || Array.isArray(plan)) {
20772
+ throw new Error("context.plan is required to bind the codebuddy plan digest");
20773
+ }
20774
+ const carried = plan.digest;
20775
+ if (typeof carried !== "string" || !HEX_DIGEST_RE2.test(carried)) {
20776
+ throw new Error("context.plan.digest must be a 64-char lowercase hex frozen plan digest");
20777
+ }
20778
+ const { computePlanDigest: computePlanDigest2 } = await init_plan().then(() => plan_exports);
20779
+ const normalized = normalizePlanForDigest2(plan);
20780
+ if (computePlanDigest2(normalized) !== carried) {
20781
+ throw new Error("context.plan.digest does not match the normalized frozen plan (a non-lifecycle field was tampered)");
20782
+ }
20783
+ return carried;
20784
+ }
20785
+ function codebuddyAuthorityDir(context, planDigest, plugin) {
20786
+ if (!context?.root) {
20787
+ throw new Error("context.root is required for the codebuddy attestation authority");
20788
+ }
20789
+ if (!HEX_DIGEST_RE2.test(planDigest)) {
20790
+ throw new Error("codebuddy attestation authority requires a 64-hex plan digest");
20791
+ }
20792
+ if (!SAFE_ID_RE.test(plugin)) {
20793
+ throw new Error(`codebuddy attestation authority requires a safe plugin id: "${plugin}"`);
20794
+ }
20795
+ const base = resolve12(context.root, ".release-skill", "codebuddy-attestations");
20796
+ const dir = resolve12(base, planDigest, plugin);
20797
+ const rel = relative10(base, dir);
20798
+ const sep4 = process.platform === "win32" ? "\\" : "/";
20799
+ if (rel === "" || rel === ".." || isAbsolute9(rel) || rel.startsWith(`..${sep4}`) || rel.split(sep4).some((segment) => segment === ".." || segment === "")) {
20800
+ throw new Error("codebuddy attestation authority path escapes its base");
20801
+ }
20802
+ return dir;
20803
+ }
20804
+ function codebuddyCliHome(attestationDir) {
20805
+ return resolve12(attestationDir, "codebuddy-home");
20806
+ }
20807
+ function codebuddyCliInstallRoot(cliHome, marketplace, plugin) {
20808
+ return resolve12(cliHome, CODEBUDDY_CLI_STATE_DIR, "plugins", "marketplaces", marketplace, "plugins", plugin);
20809
+ }
20810
+ function codebuddyDesktopTailSegments(marketplace, plugin) {
20811
+ return [CODEBUDDY_DESKTOP_HOME_DIR, "plugins", "marketplaces", marketplace, "plugins", plugin];
20812
+ }
20813
+ function matchesDesktopLayout(installPath, marketplace, plugin) {
20814
+ const segments = installPath.split(/[\\/]+/).filter((s) => s !== "" && s !== ".");
20815
+ const tail = codebuddyDesktopTailSegments(marketplace, plugin);
20816
+ if (segments.length < tail.length) return false;
20817
+ const offset = segments.length - tail.length;
20818
+ return tail.every((segment, index) => segments[offset + index] === segment);
20819
+ }
20820
+ function buildCodeBuddyManualInstructions({ plugin, version, ref, cliHome, attestationDir }) {
20821
+ const cliInstallRoot = codebuddyCliInstallRoot(cliHome, CODEBUDDY_MARKETPLACE_NAME, plugin);
20822
+ const desktopInstallRoot = `~/${CODEBUDDY_DESKTOP_HOME_DIR}/plugins/marketplaces/${CODEBUDDY_MARKETPLACE_NAME}/plugins/${plugin}`;
20823
+ return [
20824
+ `CodeBuddy/WorkBuddy plugin install cannot pin a frozen ref (the codebuddy CLI marketplace add/install have no ref option and track the default branch), so installation is a manual step proven by a human attestation.`,
20825
+ `1) publish fails closed at this codebuddy checkpoint and leaves the run PARTIAL (the automated Git branch/tag, npm, and GitHub Release writes still complete first).`,
20826
+ `2) PRIMARY PATH (WorkBuddy desktop): install release-skill from the unified marketplace "${CODEBUDDY_MARKETPLACE_NAME}" (${CODEBUDDY_MARKETPLACE_SOURCE}). Confirm "~/.workbuddy/settings.json" enabledPlugins contains "${plugin}@${CODEBUDDY_MARKETPLACE_NAME}": true. The plugin lands at "${desktopInstallRoot}/".`,
20827
+ `3) ALTERNATE PATH (bundled codebuddy CLI, isolatable): run the CLI with the ISOLATED home from this requirement so the clone lands inside it: HOME="${cliHome}" <codebuddy binary> plugin marketplace add ${CODEBUDDY_MARKETPLACE_SOURCE} ; then HOME="${cliHome}" <codebuddy binary> plugin install ${plugin}@${CODEBUDDY_MARKETPLACE_NAME}. The CLI ships with WorkBuddy.app (macOS known path /Applications/WorkBuddy.app/Contents/Resources/app.asar.unpacked/cli/bin/codebuddy). The plugin lands at "${cliInstallRoot}/".`,
20828
+ `4) REF LIMITATION WARNING: a codebuddy install tracks the marketplace default branch and CANNOT be pinned to frozen ref "${ref}". Before writing the attestation you MUST confirm the installed plugin manifest version equals the frozen version ${version}; otherwise do NOT issue an attestation.`,
20829
+ `5) Write the attestation JSON to: ${attestationDir}/${CODEBUDDY_ATTESTATION_FILE}. planDigest MUST be the frozen plan digest; payloadDigest MUST be the frozen snapshot payload digest; installChannel MUST be "desktop" or "cli"; marketplace MUST be "${CODEBUDDY_MARKETPLACE_NAME}"; installPath MUST be the actual installed plugin directory for the chosen channel. attestedAt must not be in the future and expiresAt must be within 24 hours of attestedAt.`,
20830
+ ` Required fields: consumer="codebuddy", plugin, version, entrySkill, repo, ref, marketplace, installChannel, installPath, planDigest, payloadDigest, attestedBy, attestedAt, expiresAt.`,
20831
+ `6) Re-run release-skill reconcile (promotes PARTIAL -> PUBLISHED) and then verify (-> VERIFIED). Both read the attestation from this same plan-digest-keyed authority directory, so a fresh run directory does not lose the proof.`
20832
+ ];
20833
+ }
20834
+ async function readCodeBuddyManifest(pluginRootReal) {
20835
+ const manifestRelative = CODEBUDDY_PLUGIN_MANIFEST_RELATIVE;
20836
+ const manifestPath = resolve12(pluginRootReal, manifestRelative);
20837
+ let content;
20838
+ try {
20839
+ content = await readFile8(manifestPath, "utf8");
20840
+ } catch {
20841
+ throw new Error(`no codebuddy plugin manifest found (expected ${manifestRelative})`);
20842
+ }
20843
+ let manifest;
20844
+ try {
20845
+ manifest = JSON.parse(content);
20846
+ } catch {
20847
+ throw new Error(`codebuddy plugin manifest ${manifestRelative} is not valid JSON`);
20848
+ }
20849
+ if (!manifest || typeof manifest !== "object" || Array.isArray(manifest)) {
20850
+ throw new Error(`codebuddy plugin manifest ${manifestRelative} is not an object`);
20851
+ }
20852
+ return { manifest, manifestRelative };
20853
+ }
20854
+ function validateCodeBuddyAttestation(attestation, action, isoNow, boundPlanDigest) {
20855
+ if (!attestation || typeof attestation !== "object" || Array.isArray(attestation)) {
20856
+ return { valid: false, error: "codebuddy attestation is not an object" };
20857
+ }
20858
+ const requiredStrings = ["plugin", "version", "entrySkill", "repo", "ref", "installPath", "payloadDigest", "planDigest", "attestedBy", "attestedAt", "expiresAt", "marketplace", "installChannel"];
20859
+ for (const field of requiredStrings) {
20860
+ if (typeof attestation[field] !== "string" || attestation[field].length === 0) {
20861
+ return { valid: false, error: `codebuddy attestation missing required field "${field}"` };
20862
+ }
20863
+ }
20864
+ if (attestation.consumer !== "codebuddy") {
20865
+ return { valid: false, error: `codebuddy attestation consumer "${attestation.consumer}" must be "codebuddy"` };
20866
+ }
20867
+ if (!CODEBUDDY_INSTALL_CHANNELS.has(attestation.installChannel)) {
20868
+ return { valid: false, error: `codebuddy attestation installChannel "${attestation.installChannel}" must be "desktop" or "cli"` };
20869
+ }
20870
+ if (attestation.marketplace !== CODEBUDDY_MARKETPLACE_NAME) {
20871
+ return { valid: false, error: `codebuddy attestation marketplace "${attestation.marketplace}" must be "${CODEBUDDY_MARKETPLACE_NAME}"` };
20872
+ }
20873
+ if (!HEX_DIGEST_RE2.test(attestation.planDigest)) {
20874
+ return { valid: false, error: "codebuddy attestation planDigest must be a 64-char lowercase hex digest" };
20875
+ }
20876
+ if (attestation.planDigest !== boundPlanDigest) {
20877
+ return { valid: false, error: "codebuddy attestation planDigest does not match the frozen plan digest" };
20878
+ }
20879
+ if (attestation.plugin !== action.plugin) {
20880
+ return { valid: false, error: `codebuddy attestation plugin "${attestation.plugin}" does not match action plugin "${action.plugin}"` };
20881
+ }
20882
+ if (attestation.version !== action.version) {
20883
+ return { valid: false, error: `codebuddy attestation version "${attestation.version}" does not match action version "${action.version}"` };
20884
+ }
20885
+ if (attestation.entrySkill !== action.entrySkill) {
20886
+ return { valid: false, error: `codebuddy attestation entrySkill "${attestation.entrySkill}" does not match action entrySkill "${action.entrySkill}"` };
20887
+ }
20888
+ if (attestation.repo !== action.repo) {
20889
+ return { valid: false, error: `codebuddy attestation repo "${attestation.repo}" does not match action repo "${action.repo}"` };
20890
+ }
20891
+ const expectedRef = action.ref ?? `v${action.version}`;
20892
+ if (attestation.ref !== expectedRef) {
20893
+ return { valid: false, error: `codebuddy attestation ref "${attestation.ref}" does not match frozen ref "${expectedRef}"` };
20894
+ }
20895
+ if (attestation.payloadDigest !== action.manifestDigest) {
20896
+ return { valid: false, error: "codebuddy attestation payloadDigest does not match the frozen payload digest" };
20897
+ }
20898
+ const attestedMs = Date.parse(attestation.attestedAt);
20899
+ const expiresMs = Date.parse(attestation.expiresAt);
20900
+ const nowMs = Date.parse(isoNow);
20901
+ if (!Number.isFinite(attestedMs) || !Number.isFinite(expiresMs) || !Number.isFinite(nowMs)) {
20902
+ return { valid: false, error: "codebuddy attestation attestedAt/expiresAt must be valid ISO timestamps" };
20903
+ }
20904
+ if (attestedMs > nowMs) {
20905
+ return { valid: false, error: "codebuddy attestation attestedAt is in the future" };
20906
+ }
20907
+ if (expiresMs <= attestedMs) {
20908
+ return { valid: false, error: "codebuddy attestation expiresAt must be after attestedAt" };
20909
+ }
20910
+ if (expiresMs - attestedMs > CODEBUDDY_MAX_ATTESTATION_VALIDITY_MS) {
20911
+ return { valid: false, error: "codebuddy attestation validity must not exceed 24 hours" };
20912
+ }
20913
+ if (nowMs > expiresMs) {
20914
+ return { valid: false, error: "codebuddy attestation has expired" };
20915
+ }
20916
+ if (attestation.installChannel === "desktop" && !matchesDesktopLayout(attestation.installPath, attestation.marketplace, attestation.plugin)) {
20917
+ return { valid: false, error: `codebuddy attestation installPath does not match the WorkBuddy desktop marketplace layout (.workbuddy/plugins/marketplaces/${attestation.marketplace}/plugins/${attestation.plugin})` };
20918
+ }
20919
+ return { valid: true, error: null };
20920
+ }
20921
+ async function executeCodeBuddyManualRequirement(action, context) {
20922
+ const actionType = ActionType.CODEBUDDY_MARKETPLACE_INSTALL;
20923
+ let planDigest;
20924
+ try {
20925
+ planDigest = await resolveCodeBuddyBoundPlanDigest(context);
20926
+ } catch (planErr) {
20927
+ return createResult({
20928
+ actionType,
20929
+ status: ActionStatus.EXECUTE_FAILED,
20930
+ error: `cannot bind codebuddy requirement to the frozen plan: ${planErr.message}`
20931
+ });
20932
+ }
20933
+ try {
20934
+ resolveTimeoutMs(action);
20935
+ } catch (timeoutErr) {
20936
+ return createResult({
20937
+ actionType,
20938
+ status: ActionStatus.EXECUTE_FAILED,
20939
+ error: timeoutErr.message
20940
+ });
20941
+ }
20942
+ const ref = action.ref ?? `v${action.version}`;
20943
+ let attestationDir;
20944
+ try {
20945
+ attestationDir = codebuddyAuthorityDir(context, planDigest, action.plugin);
20946
+ } catch (dirErr) {
20947
+ return createResult({
20948
+ actionType,
20949
+ status: ActionStatus.EXECUTE_FAILED,
20950
+ error: dirErr.message
20951
+ });
20952
+ }
20953
+ const cliHome = codebuddyCliHome(attestationDir);
20954
+ const cliInstallRoot = codebuddyCliInstallRoot(cliHome, CODEBUDDY_MARKETPLACE_NAME, action.plugin);
20955
+ const desktopInstallRoot = `~/${CODEBUDDY_DESKTOP_HOME_DIR}/plugins/marketplaces/${CODEBUDDY_MARKETPLACE_NAME}/plugins/${action.plugin}`;
20956
+ const instructions = buildCodeBuddyManualInstructions({
20957
+ plugin: action.plugin,
20958
+ version: action.version,
20959
+ ref,
20960
+ cliHome,
20961
+ attestationDir
20962
+ });
20963
+ const requirement = {
20964
+ kind: "codebuddy-manual-install-requirement",
20965
+ consumer: "codebuddy",
20966
+ plugin: action.plugin,
20967
+ version: action.version,
20968
+ entrySkill: action.entrySkill,
20969
+ repo: action.repo,
20970
+ ref,
20971
+ marketplace: CODEBUDDY_MARKETPLACE_NAME,
20972
+ marketplaceSource: CODEBUDDY_MARKETPLACE_SOURCE,
20973
+ installChannels: ["desktop", "cli"],
20974
+ // (A) planDigest binds to the real frozen plan digest;
20975
+ // expectedPayloadDigest binds separately to the snapshot payload digest.
20976
+ planDigest,
20977
+ expectedPayloadDigest: action.manifestDigest,
20978
+ isolatedHome: cliHome,
20979
+ codebuddyHome: cliHome,
20980
+ cliInstallRoot,
20981
+ desktopInstallRoot,
20982
+ attestationDir,
20983
+ attestationFile: CODEBUDDY_ATTESTATION_FILE,
20984
+ attestationTemplate: {
20985
+ consumer: "codebuddy",
20986
+ plugin: action.plugin,
20987
+ version: action.version,
20988
+ entrySkill: action.entrySkill,
20989
+ repo: action.repo,
20990
+ ref,
20991
+ marketplace: CODEBUDDY_MARKETPLACE_NAME,
20992
+ installChannel: '<"desktop" or "cli">',
20993
+ installPath: "<actual installed plugin directory for the chosen channel>",
20994
+ planDigest,
20995
+ payloadDigest: action.manifestDigest,
20996
+ attestedBy: "<person responsible for the manual install>",
20997
+ attestedAt: "<ISO 8601 now; must not be in the future>",
20998
+ expiresAt: "<ISO 8601; within 24h of attestedAt>"
20999
+ },
21000
+ instructions
21001
+ };
21002
+ try {
21003
+ await mkdir8(cliHome, { recursive: true, mode: 448 });
21004
+ } catch (mkdirErr) {
21005
+ return createResult({
21006
+ actionType,
21007
+ status: ActionStatus.EXECUTE_FAILED,
21008
+ error: `cannot create codebuddy isolated home directory: ${mkdirErr.message}`
21009
+ });
21010
+ }
21011
+ const requirementPath = resolve12(attestationDir, CODEBUDDY_REQUIREMENT_FILE);
21012
+ let existing = null;
21013
+ let requirementMissing = false;
21014
+ try {
21015
+ const existingRaw = await readFile8(requirementPath, "utf8");
21016
+ try {
21017
+ existing = JSON.parse(existingRaw);
21018
+ } catch (parseErr) {
21019
+ return createResult({
21020
+ actionType,
21021
+ status: ActionStatus.EXECUTE_FAILED,
21022
+ error: `existing codebuddy manual-install requirement is invalid JSON; refusing to overwrite: ${parseErr.message}`
21023
+ });
21024
+ }
21025
+ } catch (readErr) {
21026
+ if (readErr?.code === "ENOENT") {
21027
+ requirementMissing = true;
21028
+ } else {
21029
+ return createResult({
21030
+ actionType,
21031
+ status: ActionStatus.EXECUTE_FAILED,
21032
+ error: `existing codebuddy manual-install requirement cannot be read; refusing to overwrite: ${readErr.message}`
21033
+ });
21034
+ }
21035
+ }
21036
+ if (!requirementMissing) {
21037
+ if (!existing || typeof existing !== "object" || Array.isArray(existing)) {
21038
+ return createResult({
21039
+ actionType,
21040
+ status: ActionStatus.EXECUTE_FAILED,
21041
+ error: "existing codebuddy manual-install requirement is not an object; refusing to overwrite"
21042
+ });
21043
+ }
21044
+ const { createdAt: _existingCreatedAt, ...existingBody } = existing;
21045
+ if (canonicalJson(existingBody) !== canonicalJson(requirement)) {
21046
+ return createResult({
21047
+ actionType,
21048
+ status: ActionStatus.EXECUTE_FAILED,
21049
+ error: "existing codebuddy manual-install requirement conflicts with the current frozen action; refusing to overwrite"
21050
+ });
21051
+ }
21052
+ } else {
21053
+ await writeEvidenceAtomic(requirementPath, { ...requirement, createdAt: (/* @__PURE__ */ new Date()).toISOString() });
21054
+ }
21055
+ return createResult({
21056
+ actionType,
21057
+ status: ActionStatus.EXECUTED,
21058
+ observation: {
21059
+ installed: false,
21060
+ manualInstallRequired: true,
21061
+ consumer: "codebuddy",
21062
+ plugin: action.plugin,
21063
+ version: action.version,
21064
+ entrySkill: action.entrySkill,
21065
+ repo: action.repo,
21066
+ ref,
21067
+ marketplace: CODEBUDDY_MARKETPLACE_NAME,
21068
+ installChannels: ["desktop", "cli"],
21069
+ planDigest,
21070
+ attestationDir,
21071
+ codebuddyHome: cliHome,
21072
+ cliInstallRoot,
21073
+ desktopInstallRoot,
21074
+ instructions
21075
+ }
21076
+ });
21077
+ }
21078
+ var HEX_DIGEST_RE2, CODEBUDDY_REQUIREMENT_FILE, CODEBUDDY_ATTESTATION_FILE, CODEBUDDY_MAX_ATTESTATION_VALIDITY_MS, CODEBUDDY_MARKETPLACE_NAME, CODEBUDDY_MARKETPLACE_SOURCE, CODEBUDDY_PLUGIN_MANIFEST_RELATIVE, CODEBUDDY_INSTALL_CHANNELS, CODEBUDDY_DESKTOP_HOME_DIR, CODEBUDDY_CLI_STATE_DIR;
21079
+ var init_codebuddy = __esm({
21080
+ "src/platforms/codebuddy.mjs"() {
21081
+ init_contract();
21082
+ init_digest();
21083
+ HEX_DIGEST_RE2 = /^[a-f0-9]{64}$/;
21084
+ __name(normalizePlanForDigest2, "normalizePlanForDigest");
21085
+ CODEBUDDY_REQUIREMENT_FILE = "release-skill-codebuddy-manual-install.json";
21086
+ CODEBUDDY_ATTESTATION_FILE = "release-skill-codebuddy-attestation.json";
21087
+ CODEBUDDY_MAX_ATTESTATION_VALIDITY_MS = 24 * 60 * 60 * 1e3;
21088
+ CODEBUDDY_MARKETPLACE_NAME = "artifact-skill-set";
21089
+ CODEBUDDY_MARKETPLACE_SOURCE = "https://github.com/ifoohoo/artifact-skill-set";
21090
+ CODEBUDDY_PLUGIN_MANIFEST_RELATIVE = join7(".codebuddy-plugin", "plugin.json");
21091
+ CODEBUDDY_INSTALL_CHANNELS = /* @__PURE__ */ new Set(["desktop", "cli"]);
21092
+ CODEBUDDY_DESKTOP_HOME_DIR = ".workbuddy";
21093
+ CODEBUDDY_CLI_STATE_DIR = ".codebuddy";
21094
+ __name(resolveCodeBuddyBoundPlanDigest, "resolveCodeBuddyBoundPlanDigest");
21095
+ __name(codebuddyAuthorityDir, "codebuddyAuthorityDir");
21096
+ __name(codebuddyCliHome, "codebuddyCliHome");
21097
+ __name(codebuddyCliInstallRoot, "codebuddyCliInstallRoot");
21098
+ __name(codebuddyDesktopTailSegments, "codebuddyDesktopTailSegments");
21099
+ __name(matchesDesktopLayout, "matchesDesktopLayout");
21100
+ __name(buildCodeBuddyManualInstructions, "buildCodeBuddyManualInstructions");
21101
+ __name(readCodeBuddyManifest, "readCodeBuddyManifest");
21102
+ __name(validateCodeBuddyAttestation, "validateCodeBuddyAttestation");
21103
+ __name(executeCodeBuddyManualRequirement, "executeCodeBuddyManualRequirement");
21104
+ }
21105
+ });
21106
+
20710
21107
  // src/platforms/registry.mjs
20711
- import { join as join7 } from "node:path";
21108
+ import { join as join8 } from "node:path";
20712
21109
  function claudeParseListOutput(listOutput, pluginId) {
20713
21110
  if (!Array.isArray(listOutput)) {
20714
21111
  return { ok: false, error: "Claude plugin list did not return an array" };
@@ -20805,6 +21202,9 @@ function assertRegistry(registry = PLATFORMS) {
20805
21202
  if (!VALID_SOURCE_FORMS.has(platform.marketplaceSourceForm)) {
20806
21203
  throw new Error(`platform registry: ${label} has illegal marketplaceSourceForm "${platform.marketplaceSourceForm}"`);
20807
21204
  }
21205
+ if (!VALID_MARKETPLACE_REF_FORMS.has(platform.marketplaceRefForm)) {
21206
+ throw new Error(`platform registry: ${label} has illegal marketplaceRefForm "${platform.marketplaceRefForm}"`);
21207
+ }
20808
21208
  if (!Array.isArray(platform.knownHostArtifacts)) {
20809
21209
  throw new Error(`platform registry: ${label} knownHostArtifacts must be an array`);
20810
21210
  }
@@ -20855,10 +21255,11 @@ function assertRegistry(registry = PLATFORMS) {
20855
21255
  }
20856
21256
  }
20857
21257
  }
20858
- var CLAUDE, CODEX, KIMI, PLATFORMS, VALID_DISTRIBUTION_TYPES, VALID_ACTION_TYPES, VALID_SOURCE_FORMS, VALID_LIST_OUTPUTS, VALID_CLI_OUTPUTS, VALID_ENTRY_VERSION_BINDING;
21258
+ var CLAUDE, CODEX, KIMI, CODEBUDDY, PLATFORMS, VALID_DISTRIBUTION_TYPES, VALID_ACTION_TYPES, VALID_SOURCE_FORMS, VALID_MARKETPLACE_REF_FORMS, VALID_LIST_OUTPUTS, VALID_CLI_OUTPUTS, VALID_ENTRY_VERSION_BINDING;
20859
21259
  var init_registry = __esm({
20860
21260
  async "src/platforms/registry.mjs"() {
20861
21261
  await init_kimi();
21262
+ init_codebuddy();
20862
21263
  __name(claudeParseListOutput, "claudeParseListOutput");
20863
21264
  __name(claudeExtractInstallPath, "claudeExtractInstallPath");
20864
21265
  __name(claudeExtractListIdentity, "claudeExtractListIdentity");
@@ -20888,7 +21289,7 @@ var init_registry = __esm({
20888
21289
  marketplaceAddOutput: null,
20889
21290
  pluginInstallOutput: null
20890
21291
  }),
20891
- isolationEnv: /* @__PURE__ */ __name((home) => ({ HOME: home, CLAUDE_CONFIG_DIR: join7(home, ".claude") }), "isolationEnv"),
21292
+ isolationEnv: /* @__PURE__ */ __name((home) => ({ HOME: home, CLAUDE_CONFIG_DIR: join8(home, ".claude") }), "isolationEnv"),
20892
21293
  // execute pre-creates the claude config dir under the isolated HOME.
20893
21294
  isolationSubdirs: Object.freeze([".claude"]),
20894
21295
  manifestPaths: Object.freeze({
@@ -20899,6 +21300,10 @@ var init_registry = __esm({
20899
21300
  // Claude carries the authoritative version in the marketplace entry: the
20900
21301
  // preflight binds entry.version to the action version.
20901
21302
  marketplaceEntryCarriesVersion: true,
21303
+ // External marketplace form: `claude plugin marketplace add repo@<ref>` can
21304
+ // only pin a branch/tag NAME (a bare commit sha fails to clone and the
21305
+ // resolved sha is not recorded locally) — name-form weak freeze.
21306
+ marketplaceRefForm: "name",
20902
21307
  knownHostArtifacts: Object.freeze([".in_use"]),
20903
21308
  schemaRequiredFields: Object.freeze(["plugin", "marketplace", "entrySkill"]),
20904
21309
  skillRendering: Object.freeze({ mode: "verbatim", preamble: null, placeholder: "${CLAUDE_PLUGIN_ROOT}" }),
@@ -20947,6 +21352,9 @@ var init_registry = __esm({
20947
21352
  // Codex keeps the authoritative version in .codex-plugin/plugin.json; the
20948
21353
  // marketplace entry version is not bound to the action version.
20949
21354
  marketplaceEntryCarriesVersion: false,
21355
+ // External marketplace form: `codex plugin marketplace add repo --ref <ref>`
21356
+ // accepts a bare commit sha — sha-form strong freeze.
21357
+ marketplaceRefForm: "sha",
20950
21358
  knownHostArtifacts: Object.freeze([".git", ".codex-plugin/migrated-command-skills"]),
20951
21359
  schemaRequiredFields: Object.freeze(["plugin", "marketplace", "entrySkill"]),
20952
21360
  skillRendering: Object.freeze({ mode: "substitute", preamble: "codex", placeholder: "${CLAUDE_PLUGIN_ROOT}" }),
@@ -20993,6 +21401,9 @@ var init_registry = __esm({
20993
21401
  // apply (null = N/A, never consulted: kimi preflight reads its manifest via
20994
21402
  // strategy.readManifest).
20995
21403
  marketplaceEntryCarriesVersion: null,
21404
+ // kimi has no marketplace add at all, so the marketplace ref form does not
21405
+ // apply (null = N/A, never consulted).
21406
+ marketplaceRefForm: null,
20996
21407
  knownHostArtifacts: Object.freeze([".git"]),
20997
21408
  schemaRequiredFields: Object.freeze(["plugin", "entrySkill"]),
20998
21409
  skillRendering: Object.freeze({ mode: "substitute", preamble: "kimi", placeholder: "${CLAUDE_PLUGIN_ROOT}" }),
@@ -21013,10 +21424,72 @@ var init_registry = __esm({
21013
21424
  readManifest: readKimiManifest
21014
21425
  })
21015
21426
  });
21016
- PLATFORMS = Object.freeze([CLAUDE, CODEX, KIMI]);
21017
- VALID_DISTRIBUTION_TYPES = /* @__PURE__ */ new Set(["claude-plugin", "codex-plugin", "kimi-plugin"]);
21018
- VALID_ACTION_TYPES = /* @__PURE__ */ new Set(["claude-marketplace-install", "codex-marketplace-install", "kimi-marketplace-install"]);
21427
+ CODEBUDDY = Object.freeze({
21428
+ id: "codebuddy",
21429
+ distributionType: "codebuddy-plugin",
21430
+ actionType: "codebuddy-marketplace-install",
21431
+ adapter: "plugin-marketplace",
21432
+ automatable: false,
21433
+ cli: null,
21434
+ jsonProtocol: Object.freeze({
21435
+ listOutput: null,
21436
+ installPathSource: null,
21437
+ marketplaceAddOutput: null,
21438
+ pluginInstallOutput: null
21439
+ }),
21440
+ // The closed loop never execs the codebuddy CLI; HOME is the only isolation
21441
+ // input and exists solely so the attestation's isolated cli-channel home has
21442
+ // a base. No unverified host env vars are fabricated.
21443
+ isolationEnv: /* @__PURE__ */ __name((home) => ({ HOME: home }), "isolationEnv"),
21444
+ // codebuddy never execs a CLI; its isolated cli home is created by the
21445
+ // manual-requirement strategy under the attestation authority.
21446
+ isolationSubdirs: Object.freeze([]),
21447
+ manifestPaths: Object.freeze({
21448
+ // Single authoritative manifest (no precedence chain, unlike kimi).
21449
+ plugin: ".codebuddy-plugin/plugin.json",
21450
+ marketplace: null
21451
+ }),
21452
+ marketplaceSourceForm: null,
21453
+ // codebuddy installs from a unified marketplace but carries no marketplace
21454
+ // identity in the action (the marketplace is a fixed constant in
21455
+ // ./codebuddy.mjs); the entry-version binding does not apply (null = N/A).
21456
+ marketplaceEntryCarriesVersion: null,
21457
+ // codebuddy has no marketplace add that can pin a frozen ref (attestation
21458
+ // loop instead), so the marketplace ref form does not apply (null = N/A).
21459
+ marketplaceRefForm: null,
21460
+ knownHostArtifacts: Object.freeze([".git"]),
21461
+ schemaRequiredFields: Object.freeze(["plugin", "entrySkill"]),
21462
+ // Declarative rendering intent (the build-adapters producer keys on
21463
+ // buildAdapter.name = 'workbuddy'): pure ${CLAUDE_PLUGIN_ROOT} ->
21464
+ // ${CODEBUDDY_PLUGIN_ROOT} substitution, no entry-resolution preamble
21465
+ // (CodeBuddy expands the variable inline in skill content).
21466
+ skillRendering: Object.freeze({ mode: "substitute", preamble: null, placeholder: "${CODEBUDDY_PLUGIN_ROOT}" }),
21467
+ buildAdapter: Object.freeze({
21468
+ // Build adapter keeps the historical `workbuddy` directory name; the fields
21469
+ // are byte-for-byte the legacy BUILD_ONLY workbuddy entry so the generated
21470
+ // adapters/workbuddy/ tree is unchanged.
21471
+ name: "workbuddy",
21472
+ pluginDirName: ".codebuddy-plugin",
21473
+ templateFileName: "plugin.json",
21474
+ marketplaceFileName: null,
21475
+ hasMarketplace: false
21476
+ }),
21477
+ strategy: Object.freeze({
21478
+ parseListOutput: null,
21479
+ extractInstallPath: null,
21480
+ extractListIdentity: null,
21481
+ crossValidateListEntry: null,
21482
+ // codebuddy's side-effecting manual-requirement builder and manifest reader
21483
+ // live in ./codebuddy.mjs (per-platform-module option, mirroring kimi).
21484
+ buildManualRequirement: executeCodeBuddyManualRequirement,
21485
+ readManifest: readCodeBuddyManifest
21486
+ })
21487
+ });
21488
+ PLATFORMS = Object.freeze([CLAUDE, CODEX, KIMI, CODEBUDDY]);
21489
+ VALID_DISTRIBUTION_TYPES = /* @__PURE__ */ new Set(["claude-plugin", "codex-plugin", "kimi-plugin", "codebuddy-plugin"]);
21490
+ VALID_ACTION_TYPES = /* @__PURE__ */ new Set(["claude-marketplace-install", "codex-marketplace-install", "kimi-marketplace-install", "codebuddy-marketplace-install"]);
21019
21491
  VALID_SOURCE_FORMS = /* @__PURE__ */ new Set(["string", "local-path-object", null]);
21492
+ VALID_MARKETPLACE_REF_FORMS = /* @__PURE__ */ new Set(["sha", "name", null]);
21020
21493
  VALID_LIST_OUTPUTS = /* @__PURE__ */ new Set(["array", "installed-object", null]);
21021
21494
  VALID_CLI_OUTPUTS = /* @__PURE__ */ new Set(["json", null]);
21022
21495
  VALID_ENTRY_VERSION_BINDING = /* @__PURE__ */ new Set([true, false, null]);
@@ -21027,17 +21500,28 @@ var init_registry = __esm({
21027
21500
  });
21028
21501
 
21029
21502
  // src/core/plan.mjs
21030
- import { readFile as readFile8, writeFile as writeFile6, rename as rename2, mkdir as mkdir8, open as open5, link, unlink as unlink2, lstat as lstat7 } from "node:fs/promises";
21031
- import { basename as basename3, dirname as dirname5, join as join8, resolve as resolve12, parse, sep as sep2 } from "node:path";
21503
+ var plan_exports = {};
21504
+ __export(plan_exports, {
21505
+ assertAuthorityFileTarget: () => assertAuthorityFileTarget,
21506
+ assertImmutablePlanAuthority: () => assertImmutablePlanAuthority,
21507
+ computePlanDigest: () => computePlanDigest,
21508
+ prepareAuthorityDirectory: () => prepareAuthorityDirectory,
21509
+ validatePlan: () => validatePlan,
21510
+ validatePlanActionCompleteness: () => validatePlanActionCompleteness,
21511
+ writePlanAtomic: () => writePlanAtomic,
21512
+ writePlanImmutable: () => writePlanImmutable
21513
+ });
21514
+ import { readFile as readFile9, writeFile as writeFile6, rename as rename2, mkdir as mkdir9, open as open5, link, unlink as unlink2, lstat as lstat7 } from "node:fs/promises";
21515
+ import { basename as basename3, dirname as dirname5, join as join9, resolve as resolve13, parse, sep as sep2 } from "node:path";
21032
21516
  async function assertNoSymlinkAncestors(directory) {
21033
- const absolute = resolve12(directory);
21517
+ const absolute = resolve13(directory);
21034
21518
  const parsed = parse(absolute);
21035
21519
  const segments = absolute.slice(parsed.root.length).split(sep2).filter(Boolean);
21036
21520
  const releaseIndex = segments.lastIndexOf(".release-skill");
21037
21521
  const firstChecked = releaseIndex >= 0 ? releaseIndex : Math.max(0, segments.length - 1);
21038
- let current = join8(parsed.root, ...segments.slice(0, firstChecked));
21522
+ let current = join9(parsed.root, ...segments.slice(0, firstChecked));
21039
21523
  for (const segment of segments.slice(firstChecked)) {
21040
- current = join8(current, segment);
21524
+ current = join9(current, segment);
21041
21525
  let stat9;
21042
21526
  try {
21043
21527
  stat9 = await lstat7(current);
@@ -21055,14 +21539,14 @@ async function assertNoSymlinkAncestors(directory) {
21055
21539
  }
21056
21540
  }
21057
21541
  async function prepareAuthorityDirectory(directory) {
21058
- const absolute = resolve12(directory);
21542
+ const absolute = resolve13(directory);
21059
21543
  await assertNoSymlinkAncestors(absolute);
21060
- await mkdir8(absolute, { recursive: true });
21544
+ await mkdir9(absolute, { recursive: true });
21061
21545
  await assertNoSymlinkAncestors(absolute);
21062
21546
  return absolute;
21063
21547
  }
21064
21548
  async function assertAuthorityFileTarget(filePath) {
21065
- const absolute = resolve12(filePath);
21549
+ const absolute = resolve13(filePath);
21066
21550
  await prepareAuthorityDirectory(dirname5(absolute));
21067
21551
  try {
21068
21552
  const stat9 = await lstat7(absolute);
@@ -21081,7 +21565,7 @@ async function assertAuthorityFileTarget(filePath) {
21081
21565
  function assertImmutablePlanAuthority(planPath, plan) {
21082
21566
  if (!plan?.production) return;
21083
21567
  const digest = computePlanDigest(plan);
21084
- const absolute = resolve12(planPath);
21568
+ const absolute = resolve13(planPath);
21085
21569
  if (basename3(dirname5(absolute)) !== "plans" || basename3(absolute) !== `${digest}.json`) {
21086
21570
  throw new ReleaseError(
21087
21571
  GATE_FAILED,
@@ -21173,7 +21657,7 @@ async function writePlanImmutable(planPath, plan) {
21173
21657
  const dir = dirname5(planPath);
21174
21658
  await prepareAuthorityDirectory(dir);
21175
21659
  await assertAuthorityFileTarget(planPath);
21176
- const tmpPath = join8(dir, `.release-plan-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`);
21660
+ const tmpPath = join9(dir, `.release-plan-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`);
21177
21661
  const handle = await open5(tmpPath, "wx", 384);
21178
21662
  try {
21179
21663
  await handle.writeFile(json, "utf8");
@@ -21185,7 +21669,7 @@ async function writePlanImmutable(planPath, plan) {
21185
21669
  await link(tmpPath, planPath);
21186
21670
  } catch (error) {
21187
21671
  if (error.code !== "EEXIST") throw error;
21188
- const existing = await readFile8(planPath, "utf8");
21672
+ const existing = await readFile9(planPath, "utf8");
21189
21673
  if (existing !== json) {
21190
21674
  if (plan.planVersion === 2) {
21191
21675
  let existingPlan = null;
@@ -21527,6 +22011,12 @@ function validatePlanActionCompleteness(plan, options = {}) {
21527
22011
  `unit "${unitId}", action "${action.id}": status is "${action.status ?? "(missing)"}", expected "PENDING"`
21528
22012
  );
21529
22013
  }
22014
+ const externalMarketplace = dist.marketplaceRepo !== void 0 && dist.marketplaceRepo !== null;
22015
+ if (externalMarketplace && platform.marketplaceRefForm === null) {
22016
+ failures.push(
22017
+ `unit "${unitId}", action "${action.id}": ${platform.distributionType} distribution declares marketplaceRepo but the platform has no marketplace add capability`
22018
+ );
22019
+ }
21530
22020
  _checkRequired(action, "parameters.consumer", action.parameters?.consumer, platform.id, unitId, failures);
21531
22021
  _checkRequired(action, "parameters.plugin", action.parameters?.plugin, plugin, unitId, failures);
21532
22022
  if (requiresMarketplace) {
@@ -21536,12 +22026,44 @@ function validatePlanActionCompleteness(plan, options = {}) {
21536
22026
  `unit "${unitId}", action "${action.id}": parameters.marketplace is "${action.parameters.marketplace}", expected optional legacy value "${marketplace}"`
21537
22027
  );
21538
22028
  }
21539
- _checkRequired(action, "parameters.repo", action.parameters?.repo, publicRepo, unitId, failures);
22029
+ if (externalMarketplace) {
22030
+ _checkRequired(action, "parameters.repo", action.parameters?.repo, dist.marketplaceRepo, unitId, failures);
22031
+ _checkRequired(action, "parameters.marketplaceLocation", action.parameters?.marketplaceLocation, "external", unitId, failures);
22032
+ } else {
22033
+ _checkRequired(action, "parameters.repo", action.parameters?.repo, publicRepo, unitId, failures);
22034
+ }
21540
22035
  _checkRequired(action, "parameters.version", action.parameters?.version, targetVersion, unitId, failures);
21541
22036
  _checkRequired(action, "parameters.entrySkill", action.parameters?.entrySkill, entrySkill, unitId, failures);
21542
22037
  if (production) {
21543
22038
  _checkRequired(action, "parameters.snapshotPath", action.parameters?.snapshotPath, frozen?.path, unitId, failures);
21544
- _checkRequired(action, "parameters.ref", action.parameters?.ref, expectedTag, unitId, failures);
22039
+ if (externalMarketplace) {
22040
+ const ref = action.parameters?.ref;
22041
+ if (ref === void 0 || ref === null) {
22042
+ failures.push(
22043
+ `unit "${unitId}", action "${action.id}": parameters.ref is missing, expected the frozen external marketplace add-ref`
22044
+ );
22045
+ } else if (!_isStructurallySafeExternalRef(ref)) {
22046
+ failures.push(
22047
+ `unit "${unitId}", action "${action.id}": parameters.ref is not a structurally safe ref: ${JSON.stringify(ref)}`
22048
+ );
22049
+ } else if (ref !== action.expected?.ref) {
22050
+ failures.push(
22051
+ `unit "${unitId}", action "${action.id}": parameters.ref is "${ref}", expected self-consistent expected.ref "${action.expected?.ref}"`
22052
+ );
22053
+ }
22054
+ const sha = action.parameters?.marketplaceCommitSha;
22055
+ if (sha === void 0 || sha === null) {
22056
+ failures.push(
22057
+ `unit "${unitId}", action "${action.id}": parameters.marketplaceCommitSha is missing, expected a frozen 40-hex commit sha`
22058
+ );
22059
+ } else if (typeof sha !== "string" || !EXTERNAL_MARKETPLACE_SHA_RE.test(sha)) {
22060
+ failures.push(
22061
+ `unit "${unitId}", action "${action.id}": parameters.marketplaceCommitSha must be a 40-hex commit sha, got: ${JSON.stringify(sha)}`
22062
+ );
22063
+ }
22064
+ } else {
22065
+ _checkRequired(action, "parameters.ref", action.parameters?.ref, expectedTag, unitId, failures);
22066
+ }
21545
22067
  _checkRequired(action, "parameters.manifestDigest", action.parameters?.manifestDigest, frozen?.manifestDigest, unitId, failures);
21546
22068
  }
21547
22069
  {
@@ -21573,8 +22095,15 @@ function validatePlanActionCompleteness(plan, options = {}) {
21573
22095
  _checkRequired(action, "expected.entrySkill", action.expected?.entrySkill, entrySkill, unitId, failures);
21574
22096
  if (production) {
21575
22097
  _checkRequired(action, "expected.consumer", action.expected?.consumer, platform.id, unitId, failures);
21576
- _checkRequired(action, "expected.repo", action.expected?.repo, publicRepo, unitId, failures);
21577
- _checkRequired(action, "expected.ref", action.expected?.ref, expectedTag, unitId, failures);
22098
+ if (externalMarketplace) {
22099
+ _checkRequired(action, "expected.repo", action.expected?.repo, dist.marketplaceRepo, unitId, failures);
22100
+ _checkRequired(action, "expected.ref", action.expected?.ref, action.parameters?.ref, unitId, failures);
22101
+ _checkRequired(action, "expected.marketplaceLocation", action.expected?.marketplaceLocation, "external", unitId, failures);
22102
+ _checkRequired(action, "expected.marketplaceCommitSha", action.expected?.marketplaceCommitSha, action.parameters?.marketplaceCommitSha, unitId, failures);
22103
+ } else {
22104
+ _checkRequired(action, "expected.repo", action.expected?.repo, publicRepo, unitId, failures);
22105
+ _checkRequired(action, "expected.ref", action.expected?.ref, expectedTag, unitId, failures);
22106
+ }
21578
22107
  _checkRequired(action, "expected.entrySkillFound", action.expected?.entrySkillFound, true, unitId, failures);
21579
22108
  _checkRequired(action, "expected.manifestDigest", action.expected?.manifestDigest, frozen?.manifestDigest, unitId, failures);
21580
22109
  }
@@ -21654,7 +22183,22 @@ function _checkRequired(action, fieldPath, actual, expected, unitId, failures) {
21654
22183
  );
21655
22184
  }
21656
22185
  }
21657
- var import_ajv3, import_ajv_formats3, RELEASE_PLAN_SCHEMA, ajv3, validatePlanSchema, CANONICAL_COMMIT_TIMESTAMP_RE, REQUIRED_ACTION_TYPES;
22186
+ function _isStructurallySafeExternalRef(ref) {
22187
+ if (typeof ref !== "string" || ref.length === 0) return false;
22188
+ if (/[\x00-\x1f]/.test(ref)) return false;
22189
+ if (ref.startsWith("-")) return false;
22190
+ if (ref.includes("\\")) return false;
22191
+ if (ref.includes("//")) return false;
22192
+ if (ref.startsWith("/") || ref.endsWith("/")) return false;
22193
+ if (ref.endsWith(".")) return false;
22194
+ if (ref.endsWith(".lock")) return false;
22195
+ if (ref.includes("@{")) return false;
22196
+ if (ref === "@") return false;
22197
+ if (ref.includes("..")) return false;
22198
+ if (/[;|&`$(){}]/.test(ref)) return false;
22199
+ return /^[a-zA-Z0-9][a-zA-Z0-9._/-]*$/.test(ref);
22200
+ }
22201
+ var import_ajv3, import_ajv_formats3, RELEASE_PLAN_SCHEMA, ajv3, validatePlanSchema, CANONICAL_COMMIT_TIMESTAMP_RE, REQUIRED_ACTION_TYPES, EXTERNAL_MARKETPLACE_SHA_RE;
21658
22202
  var init_plan = __esm({
21659
22203
  async "src/core/plan.mjs"() {
21660
22204
  import_ajv3 = __toESM(require_ajv(), 1);
@@ -21683,13 +22227,15 @@ var init_plan = __esm({
21683
22227
  REQUIRED_ACTION_TYPES = ["push-snapshot", "create-tag", "github-release"];
21684
22228
  __name(validatePlanActionCompleteness, "validatePlanActionCompleteness");
21685
22229
  __name(_checkRequired, "_checkRequired");
22230
+ EXTERNAL_MARKETPLACE_SHA_RE = /^[0-9a-f]{40}$/;
22231
+ __name(_isStructurallySafeExternalRef, "_isStructurallySafeExternalRef");
21686
22232
  }
21687
22233
  });
21688
22234
 
21689
22235
  // src/snapshot/public-map.mjs
21690
- import { lstat as lstat8, readFile as readFile9, mkdir as mkdir9, readdir as readdir6, realpath as realpath8, chmod as fsChmod } from "node:fs/promises";
22236
+ import { lstat as lstat8, readFile as readFile10, mkdir as mkdir10, readdir as readdir6, realpath as realpath8, chmod as fsChmod } from "node:fs/promises";
21691
22237
  import { open as fsOpen } from "node:fs/promises";
21692
- import { relative as relative10, resolve as resolve13, dirname as dirname6, sep as pathSep, isAbsolute as isAbsolute9 } from "node:path";
22238
+ import { relative as relative11, resolve as resolve14, dirname as dirname6, sep as pathSep, isAbsolute as isAbsolute10 } from "node:path";
21693
22239
  import { posix } from "node:path";
21694
22240
  import { constants as fsConstants3 } from "node:fs";
21695
22241
  import { createHash as createHash7 } from "node:crypto";
@@ -21698,14 +22244,14 @@ function _isContainedWith(relativeFn, isAbsoluteFn, root, candidate, relPathSep
21698
22244
  return rel !== "" && rel !== ".." && !rel.startsWith(`..${relPathSep}`) && !isAbsoluteFn(rel);
21699
22245
  }
21700
22246
  function isContained(root, candidate) {
21701
- return _isContainedWith(relative10, isAbsolute9, root, candidate);
22247
+ return _isContainedWith(relative11, isAbsolute10, root, candidate);
21702
22248
  }
21703
22249
  async function assertNoAncestorSymlinks(root, filePath, fs = { lstat: lstat8 }) {
21704
- const rel = relative10(root, filePath);
22250
+ const rel = relative11(root, filePath);
21705
22251
  const segments = rel.split(/[/\\]/);
21706
22252
  let current = root;
21707
22253
  for (const segment of segments) {
21708
- current = resolve13(current, segment);
22254
+ current = resolve14(current, segment);
21709
22255
  try {
21710
22256
  const st = await fs.lstat(current, { stage: "source-ancestor" });
21711
22257
  if (st.isSymbolicLink()) {
@@ -21762,11 +22308,11 @@ async function assertOutputAncestorsNoFollow(effectiveOutputDir, fs = { lstat: l
21762
22308
  }
21763
22309
  }
21764
22310
  async function assertDestAncestorsNoFollow(realOutputRoot, destPath, fs = { lstat: lstat8 }) {
21765
- const relDest = relative10(realOutputRoot, destPath);
22311
+ const relDest = relative11(realOutputRoot, destPath);
21766
22312
  const segments = relDest.split(pathSep).filter(Boolean);
21767
22313
  let current = realOutputRoot;
21768
22314
  for (const segment of segments) {
21769
- current = resolve13(current, segment);
22315
+ current = resolve14(current, segment);
21770
22316
  try {
21771
22317
  const st = await fs.lstat(current, { stage: "dest-ancestor" });
21772
22318
  if (st.isSymbolicLink()) {
@@ -21922,9 +22468,9 @@ async function buildPublicStaging({
21922
22468
  const fs = {
21923
22469
  lstat: _fsOps.lstat ? (p, ctx) => _fsOps.lstat({ operation: "lstat", path: p, ...ctx }) : lstat8,
21924
22470
  realpath: _fsOps.realpath ? (p, ctx) => _fsOps.realpath({ operation: "realpath", path: p, ...ctx }) : realpath8,
21925
- readFile: _fsOps.readFile ? (p, ctx) => _fsOps.readFile({ operation: "readFile", path: p, ...ctx }) : readFile9,
22471
+ readFile: _fsOps.readFile ? (p, ctx) => _fsOps.readFile({ operation: "readFile", path: p, ...ctx }) : readFile10,
21926
22472
  open: _fsOps.open ? (p, flags, mode, ctx) => _fsOps.open({ operation: "open", path: p, flags, mode, ...ctx }) : fsOpen,
21927
- mkdir: _fsOps.mkdir ? (p, opts, ctx) => _fsOps.mkdir({ operation: "mkdir", path: p, opts, ...ctx }) : mkdir9,
22473
+ mkdir: _fsOps.mkdir ? (p, opts, ctx) => _fsOps.mkdir({ operation: "mkdir", path: p, opts, ...ctx }) : mkdir10,
21928
22474
  readdir: _fsOps.readdir ? (p, ctx) => _fsOps.readdir({ operation: "readdir", path: p, ...ctx }) : readdir6,
21929
22475
  chmod: _fsOps.chmod ? (p, mode, ctx) => _fsOps.chmod({ operation: "chmod", path: p, mode, ...ctx }) : fsChmod
21930
22476
  };
@@ -21957,7 +22503,7 @@ async function buildPublicStaging({
21957
22503
  { count: mappings.length, limit: MAX_MAPPINGS }
21958
22504
  );
21959
22505
  }
21960
- const unitRootLexical = resolve13(sourceRoot, unit.source);
22506
+ const unitRootLexical = resolve14(sourceRoot, unit.source);
21961
22507
  let realUnitRoot;
21962
22508
  try {
21963
22509
  realUnitRoot = await fs.realpath(unitRootLexical, { stage: "unit-root-realpath" });
@@ -21970,14 +22516,14 @@ async function buildPublicStaging({
21970
22516
  { sourceRoot, unitSource: unit.source, cause: code }
21971
22517
  );
21972
22518
  }
21973
- const effectiveOutputDir = resolve13(
21974
- outputDir ?? resolve13(sourceRoot, ".release-skill", "staging")
22519
+ const effectiveOutputDir = resolve14(
22520
+ outputDir ?? resolve14(sourceRoot, ".release-skill", "staging")
21975
22521
  );
21976
22522
  const preflightRecords = [];
21977
22523
  const requiredTargetSet = new Set(unit.requiredPublicFiles ?? []);
21978
22524
  for (const mapping of mappings) {
21979
- const srcPath = resolve13(sourceRoot, mapping.from);
21980
- const destPath = resolve13(effectiveOutputDir, mapping.to);
22525
+ const srcPath = resolve14(sourceRoot, mapping.from);
22526
+ const destPath = resolve14(effectiveOutputDir, mapping.to);
21981
22527
  if (srcPath.length > MAX_PATH_LENGTH || destPath.length > MAX_PATH_LENGTH) {
21982
22528
  preflightRecords.push({
21983
22529
  ok: false,
@@ -22464,11 +23010,11 @@ async function buildPublicStaging({
22464
23010
  );
22465
23011
  }
22466
23012
  const destDir = dirname6(destPath);
22467
- const relDest = relative10(realOutputRoot, destDir);
23013
+ const relDest = relative11(realOutputRoot, destDir);
22468
23014
  const destSegments = relDest.split(pathSep).filter(Boolean);
22469
23015
  let accumulatedPath = realOutputRoot;
22470
23016
  for (const seg of destSegments) {
22471
- accumulatedPath = resolve13(accumulatedPath, seg);
23017
+ accumulatedPath = resolve14(accumulatedPath, seg);
22472
23018
  try {
22473
23019
  const segStat = await fs.lstat(accumulatedPath, { stage: "dest-ancestor-pre-mkdir" });
22474
23020
  if (segStat.isSymbolicLink()) {
@@ -22767,8 +23313,8 @@ var init_public_map = __esm({
22767
23313
  });
22768
23314
 
22769
23315
  // src/snapshot/scan.mjs
22770
- import { readFile as readFile10, readdir as readdir7, stat as stat3 } from "node:fs/promises";
22771
- import { join as join9, relative as relative11, extname, posix as posix2, win32 } from "node:path";
23316
+ import { readFile as readFile11, readdir as readdir7, stat as stat3 } from "node:fs/promises";
23317
+ import { join as join10, relative as relative12, extname, posix as posix2, win32 } from "node:path";
22772
23318
  import { createHash as createHash8 } from "node:crypto";
22773
23319
  async function collectFiles(dir, base = dir) {
22774
23320
  const results = [];
@@ -22780,12 +23326,12 @@ async function collectFiles(dir, base = dir) {
22780
23326
  }
22781
23327
  for (const entry of entries) {
22782
23328
  if (entry.name === ".git") continue;
22783
- const abs = join9(dir, entry.name);
23329
+ const abs = join10(dir, entry.name);
22784
23330
  if (entry.isDirectory()) {
22785
23331
  const sub = await collectFiles(abs, base);
22786
23332
  results.push(...sub);
22787
23333
  } else if (entry.isFile()) {
22788
- results.push(relative11(base, abs));
23334
+ results.push(relative12(base, abs));
22789
23335
  }
22790
23336
  }
22791
23337
  return results;
@@ -22836,7 +23382,7 @@ async function scanFile(relPath, absPath, forbiddenPaths, forbiddenContentPatter
22836
23382
  }
22837
23383
  let content;
22838
23384
  try {
22839
- content = await readFile10(absPath, "utf8");
23385
+ content = await readFile11(absPath, "utf8");
22840
23386
  } catch {
22841
23387
  return findings;
22842
23388
  }
@@ -22905,10 +23451,10 @@ async function scanFile(relPath, absPath, forbiddenPaths, forbiddenContentPatter
22905
23451
  }
22906
23452
  async function scanForStaleDist(snapshotDir) {
22907
23453
  const findings = [];
22908
- const manifestPath = join9(snapshotDir, "dist", "manifest.json");
23454
+ const manifestPath = join10(snapshotDir, "dist", "manifest.json");
22909
23455
  let manifest;
22910
23456
  try {
22911
- const raw = await readFile10(manifestPath, "utf8");
23457
+ const raw = await readFile11(manifestPath, "utf8");
22912
23458
  manifest = JSON.parse(raw);
22913
23459
  } catch {
22914
23460
  return findings;
@@ -22916,13 +23462,13 @@ async function scanForStaleDist(snapshotDir) {
22916
23462
  if (!manifest.files || typeof manifest.files !== "object") {
22917
23463
  return findings;
22918
23464
  }
22919
- const distDir = join9(snapshotDir, "dist");
23465
+ const distDir = join10(snapshotDir, "dist");
22920
23466
  for (const [fileRel, expectedHash] of Object.entries(manifest.files)) {
22921
23467
  if (typeof expectedHash !== "string") continue;
22922
- const fileAbs = join9(distDir, fileRel);
23468
+ const fileAbs = join10(distDir, fileRel);
22923
23469
  let actualContent;
22924
23470
  try {
22925
- actualContent = await readFile10(fileAbs);
23471
+ actualContent = await readFile11(fileAbs);
22926
23472
  } catch {
22927
23473
  findings.push({
22928
23474
  kind: STALE_BUILD_ARTIFACT,
@@ -22963,7 +23509,7 @@ async function scanSnapshot({ snapshotDir, policy = {} } = {}) {
22963
23509
  const relFiles = await collectFiles(snapshotDir);
22964
23510
  const seenKinds = /* @__PURE__ */ new Set();
22965
23511
  for (const relPath of relFiles) {
22966
- const absPath = join9(snapshotDir, relPath);
23512
+ const absPath = join10(snapshotDir, relPath);
22967
23513
  const normRel = relPath.replaceAll(win32.sep, posix2.sep);
22968
23514
  if (await isBinaryFile(relPath, absPath)) continue;
22969
23515
  const fileFindings = await scanFile(normRel, absPath, forbiddenPaths, forbiddenContentPatterns, seenKinds);
@@ -23054,7 +23600,7 @@ var init_scan = __esm({
23054
23600
  });
23055
23601
 
23056
23602
  // src/readme/contract.mjs
23057
- import { readFile as readFile11 } from "node:fs/promises";
23603
+ import { readFile as readFile12 } from "node:fs/promises";
23058
23604
  import path2 from "node:path";
23059
23605
  function extractMarkers(content) {
23060
23606
  const regex = /<!--\s*release-skill:((?:[\w-]+:)*[\w-]+)\s*-->/g;
@@ -23084,7 +23630,7 @@ function extractExecBlocks(content) {
23084
23630
  }
23085
23631
  async function safeRead(filePath) {
23086
23632
  try {
23087
- return await readFile11(filePath, "utf8");
23633
+ return await readFile12(filePath, "utf8");
23088
23634
  } catch {
23089
23635
  return null;
23090
23636
  }
@@ -24173,10 +24719,10 @@ var require_commonjs = __commonJS({
24173
24719
  * Return a void Promise that resolves once the stream ends.
24174
24720
  */
24175
24721
  async promise() {
24176
- return new Promise((resolve24, reject) => {
24722
+ return new Promise((resolve25, reject) => {
24177
24723
  this.on(DESTROYED, () => reject(new Error("stream destroyed")));
24178
24724
  this.on("error", (er) => reject(er));
24179
- this.on("end", () => resolve24());
24725
+ this.on("end", () => resolve25());
24180
24726
  });
24181
24727
  }
24182
24728
  /**
@@ -24200,7 +24746,7 @@ var require_commonjs = __commonJS({
24200
24746
  return Promise.resolve({ done: false, value: res });
24201
24747
  if (this[EOF])
24202
24748
  return stop();
24203
- let resolve24;
24749
+ let resolve25;
24204
24750
  let reject;
24205
24751
  const onerr = /* @__PURE__ */ __name((er) => {
24206
24752
  this.off("data", ondata);
@@ -24214,19 +24760,19 @@ var require_commonjs = __commonJS({
24214
24760
  this.off("end", onend);
24215
24761
  this.off(DESTROYED, ondestroy);
24216
24762
  this.pause();
24217
- resolve24({ value, done: !!this[EOF] });
24763
+ resolve25({ value, done: !!this[EOF] });
24218
24764
  }, "ondata");
24219
24765
  const onend = /* @__PURE__ */ __name(() => {
24220
24766
  this.off("error", onerr);
24221
24767
  this.off("data", ondata);
24222
24768
  this.off(DESTROYED, ondestroy);
24223
24769
  stop();
24224
- resolve24({ done: true, value: void 0 });
24770
+ resolve25({ done: true, value: void 0 });
24225
24771
  }, "onend");
24226
24772
  const ondestroy = /* @__PURE__ */ __name(() => onerr(new Error("stream destroyed")), "ondestroy");
24227
24773
  return new Promise((res2, rej) => {
24228
24774
  reject = rej;
24229
- resolve24 = res2;
24775
+ resolve25 = res2;
24230
24776
  this.once(DESTROYED, ondestroy);
24231
24777
  this.once("error", onerr);
24232
24778
  this.once("end", onend);
@@ -25317,10 +25863,10 @@ var require_minipass = __commonJS({
25317
25863
  }
25318
25864
  // stream.promise().then(() => done, er => emitted error)
25319
25865
  promise() {
25320
- return new Promise((resolve24, reject) => {
25866
+ return new Promise((resolve25, reject) => {
25321
25867
  this.on(DESTROYED, () => reject(new Error("stream destroyed")));
25322
25868
  this.on("error", (er) => reject(er));
25323
- this.on("end", () => resolve24());
25869
+ this.on("end", () => resolve25());
25324
25870
  });
25325
25871
  }
25326
25872
  // for await (let chunk of stream)
@@ -25331,7 +25877,7 @@ var require_minipass = __commonJS({
25331
25877
  return Promise.resolve({ done: false, value: res });
25332
25878
  if (this[EOF])
25333
25879
  return Promise.resolve({ done: true });
25334
- let resolve24 = null;
25880
+ let resolve25 = null;
25335
25881
  let reject = null;
25336
25882
  const onerr = /* @__PURE__ */ __name((er) => {
25337
25883
  this.removeListener("data", ondata);
@@ -25342,17 +25888,17 @@ var require_minipass = __commonJS({
25342
25888
  this.removeListener("error", onerr);
25343
25889
  this.removeListener("end", onend);
25344
25890
  this.pause();
25345
- resolve24({ value, done: !!this[EOF] });
25891
+ resolve25({ value, done: !!this[EOF] });
25346
25892
  }, "ondata");
25347
25893
  const onend = /* @__PURE__ */ __name(() => {
25348
25894
  this.removeListener("error", onerr);
25349
25895
  this.removeListener("data", ondata);
25350
- resolve24({ done: true });
25896
+ resolve25({ done: true });
25351
25897
  }, "onend");
25352
25898
  const ondestroy = /* @__PURE__ */ __name(() => onerr(new Error("stream destroyed")), "ondestroy");
25353
25899
  return new Promise((res2, rej) => {
25354
25900
  reject = rej;
25355
- resolve24 = res2;
25901
+ resolve25 = res2;
25356
25902
  this.once(DESTROYED, ondestroy);
25357
25903
  this.once("error", onerr);
25358
25904
  this.once("end", onend);
@@ -29391,12 +29937,12 @@ var require_body = __commonJS({
29391
29937
  if (resTimeout && resTimeout.unref) {
29392
29938
  resTimeout.unref();
29393
29939
  }
29394
- return new Promise((resolve24) => {
29940
+ return new Promise((resolve25) => {
29395
29941
  if (stream !== upstream) {
29396
29942
  upstream.on("error", (er) => stream.emit("error", er));
29397
29943
  upstream.pipe(stream);
29398
29944
  }
29399
- resolve24();
29945
+ resolve25();
29400
29946
  }).then(() => stream.concat()).then((buf) => {
29401
29947
  clearTimeout(resTimeout);
29402
29948
  return buf;
@@ -30161,7 +30707,7 @@ var require_lib2 = __commonJS({
30161
30707
  var fetch = /* @__PURE__ */ __name(async (url, opts) => {
30162
30708
  if (/^data:/.test(url)) {
30163
30709
  const request = new Request(url, opts);
30164
- return Promise.resolve().then(() => new Promise((resolve24, reject) => {
30710
+ return Promise.resolve().then(() => new Promise((resolve25, reject) => {
30165
30711
  let type, data;
30166
30712
  try {
30167
30713
  const { pathname, search } = new URL2(url);
@@ -30185,10 +30731,10 @@ var require_lib2 = __commonJS({
30185
30731
  if (type) {
30186
30732
  headers["Content-Type"] = type;
30187
30733
  }
30188
- return resolve24(new Response(data, { headers }));
30734
+ return resolve25(new Response(data, { headers }));
30189
30735
  }));
30190
30736
  }
30191
- return new Promise((resolve24, reject) => {
30737
+ return new Promise((resolve25, reject) => {
30192
30738
  const request = new Request(url, opts);
30193
30739
  let options;
30194
30740
  try {
@@ -30307,7 +30853,7 @@ var require_lib2 = __commonJS({
30307
30853
  requestOpts.body = void 0;
30308
30854
  requestOpts.headers.delete("content-length");
30309
30855
  }
30310
- resolve24(fetch(new Request(locationURL, requestOpts)));
30856
+ resolve25(fetch(new Request(locationURL, requestOpts)));
30311
30857
  finalize();
30312
30858
  return;
30313
30859
  }
@@ -30335,7 +30881,7 @@ var require_lib2 = __commonJS({
30335
30881
  const codings = headers.get("Content-Encoding");
30336
30882
  if (!request.compress || request.method === "HEAD" || codings === null || res.statusCode === 204 || res.statusCode === 304) {
30337
30883
  response = new Response(body, responseOptions);
30338
- resolve24(response);
30884
+ resolve25(response);
30339
30885
  return;
30340
30886
  }
30341
30887
  const zlibOptions = {
@@ -30354,7 +30900,7 @@ var require_lib2 = __commonJS({
30354
30900
  ).pipe(unzip),
30355
30901
  responseOptions
30356
30902
  );
30357
- resolve24(response);
30903
+ resolve25(response);
30358
30904
  return;
30359
30905
  }
30360
30906
  if (codings === "deflate" || codings === "x-deflate") {
@@ -30366,7 +30912,7 @@ var require_lib2 = __commonJS({
30366
30912
  (er) => decoder2.emit("error", er)
30367
30913
  ).pipe(decoder2);
30368
30914
  response = new Response(decoder2, responseOptions);
30369
- resolve24(response);
30915
+ resolve25(response);
30370
30916
  });
30371
30917
  return;
30372
30918
  }
@@ -30384,11 +30930,11 @@ var require_lib2 = __commonJS({
30384
30930
  (er) => decoder.emit("error", er)
30385
30931
  ).pipe(decoder);
30386
30932
  response = new Response(decoder, responseOptions);
30387
- resolve24(response);
30933
+ resolve25(response);
30388
30934
  return;
30389
30935
  }
30390
30936
  response = new Response(body, responseOptions);
30391
- resolve24(response);
30937
+ resolve25(response);
30392
30938
  });
30393
30939
  writeToStream(req, request);
30394
30940
  });
@@ -30642,12 +31188,12 @@ var require_lib3 = __commonJS({
30642
31188
  return process.emit("input", "end");
30643
31189
  }, "end"),
30644
31190
  read: /* @__PURE__ */ __name(function(...args2) {
30645
- let resolve24, reject;
31191
+ let resolve25, reject;
30646
31192
  const promise = new Promise((_resolve, _reject) => {
30647
- resolve24 = _resolve;
31193
+ resolve25 = _resolve;
30648
31194
  reject = _reject;
30649
31195
  });
30650
- process.emit("input", "read", resolve24, reject, ...args2);
31196
+ process.emit("input", "read", resolve25, reject, ...args2);
30651
31197
  return promise;
30652
31198
  }, "read")
30653
31199
  }
@@ -35062,7 +35608,7 @@ var require_npa = __commonJS({
35062
35608
  spec = arg;
35063
35609
  }
35064
35610
  }
35065
- return resolve24(name, spec, where, arg);
35611
+ return resolve25(name, spec, where, arg);
35066
35612
  }
35067
35613
  __name(npa, "npa");
35068
35614
  function isFileSpec(spec) {
@@ -35085,7 +35631,7 @@ var require_npa = __commonJS({
35085
35631
  return spec.toLowerCase().startsWith("npm:");
35086
35632
  }
35087
35633
  __name(isAliasSpec, "isAliasSpec");
35088
- function resolve24(name, spec, where, arg) {
35634
+ function resolve25(name, spec, where, arg) {
35089
35635
  const res = new Result({
35090
35636
  raw: arg,
35091
35637
  name,
@@ -35117,7 +35663,7 @@ var require_npa = __commonJS({
35117
35663
  return fromRegistry(res);
35118
35664
  }
35119
35665
  }
35120
- __name(resolve24, "resolve");
35666
+ __name(resolve25, "resolve");
35121
35667
  function toPurl(arg, reg = defaultRegistry) {
35122
35668
  const res = npa(arg);
35123
35669
  if (res.type !== "version") {
@@ -35418,7 +35964,7 @@ var require_npa = __commonJS({
35418
35964
  }
35419
35965
  __name(fromRegistry, "fromRegistry");
35420
35966
  module.exports = npa;
35421
- module.exports.resolve = resolve24;
35967
+ module.exports.resolve = resolve25;
35422
35968
  module.exports.toPurl = toPurl;
35423
35969
  module.exports.Result = Result;
35424
35970
  }
@@ -37191,7 +37737,7 @@ var require_lib7 = __commonJS({
37191
37737
  module.exports.fromStream = fromStream;
37192
37738
  function fromStream(stream, opts) {
37193
37739
  const istream = integrityStream(opts);
37194
- return new Promise((resolve24, reject) => {
37740
+ return new Promise((resolve25, reject) => {
37195
37741
  stream.pipe(istream);
37196
37742
  stream.on("error", reject);
37197
37743
  istream.on("error", reject);
@@ -37199,7 +37745,7 @@ var require_lib7 = __commonJS({
37199
37745
  istream.on("integrity", (s) => {
37200
37746
  sri = s;
37201
37747
  });
37202
- istream.on("end", () => resolve24(sri));
37748
+ istream.on("end", () => resolve25(sri));
37203
37749
  istream.resume();
37204
37750
  });
37205
37751
  }
@@ -37260,7 +37806,7 @@ var require_lib7 = __commonJS({
37260
37806
  ));
37261
37807
  }
37262
37808
  const checker = integrityStream(opts);
37263
- return new Promise((resolve24, reject) => {
37809
+ return new Promise((resolve25, reject) => {
37264
37810
  stream.pipe(checker);
37265
37811
  stream.on("error", reject);
37266
37812
  checker.on("error", reject);
@@ -37268,7 +37814,7 @@ var require_lib7 = __commonJS({
37268
37814
  checker.on("verified", (s) => {
37269
37815
  verified = s;
37270
37816
  });
37271
- checker.on("end", () => resolve24(verified));
37817
+ checker.on("end", () => resolve25(verified));
37272
37818
  checker.resume();
37273
37819
  });
37274
37820
  }
@@ -38150,7 +38696,7 @@ var require_polyfill = __commonJS({
38150
38696
  chmod: chmod5,
38151
38697
  copyFile,
38152
38698
  lstat: lstat15,
38153
- mkdir: mkdir19,
38699
+ mkdir: mkdir20,
38154
38700
  readdir: readdir13,
38155
38701
  readlink: readlink2,
38156
38702
  stat: stat9,
@@ -38160,10 +38706,10 @@ var require_polyfill = __commonJS({
38160
38706
  } = __require("fs/promises");
38161
38707
  var {
38162
38708
  dirname: dirname15,
38163
- isAbsolute: isAbsolute18,
38164
- join: join25,
38709
+ isAbsolute: isAbsolute19,
38710
+ join: join26,
38165
38711
  parse: parse2,
38166
- resolve: resolve24,
38712
+ resolve: resolve25,
38167
38713
  sep: sep4,
38168
38714
  toNamespacedPath
38169
38715
  } = __require("path");
@@ -38268,7 +38814,7 @@ var require_polyfill = __commonJS({
38268
38814
  if (dirExists) {
38269
38815
  return getStatsForCopy(destStat, src, dest, opts);
38270
38816
  }
38271
- await mkdir19(destParent, { recursive: true });
38817
+ await mkdir20(destParent, { recursive: true });
38272
38818
  return getStatsForCopy(destStat, src, dest, opts);
38273
38819
  }
38274
38820
  __name(checkParentDir, "checkParentDir");
@@ -38281,8 +38827,8 @@ var require_polyfill = __commonJS({
38281
38827
  }
38282
38828
  __name(pathExists2, "pathExists");
38283
38829
  async function checkParentPaths(src, srcStat, dest) {
38284
- const srcParent = resolve24(dirname15(src));
38285
- const destParent = resolve24(dirname15(dest));
38830
+ const srcParent = resolve25(dirname15(src));
38831
+ const destParent = resolve25(dirname15(dest));
38286
38832
  if (destParent === srcParent || destParent === parse2(destParent).root) {
38287
38833
  return;
38288
38834
  }
@@ -38306,7 +38852,7 @@ var require_polyfill = __commonJS({
38306
38852
  return checkParentPaths(src, srcStat, destParent);
38307
38853
  }
38308
38854
  __name(checkParentPaths, "checkParentPaths");
38309
- var normalizePathToArray = /* @__PURE__ */ __name((path3) => resolve24(path3).split(sep4).filter(Boolean), "normalizePathToArray");
38855
+ var normalizePathToArray = /* @__PURE__ */ __name((path3) => resolve25(path3).split(sep4).filter(Boolean), "normalizePathToArray");
38310
38856
  function isSrcSubdir(src, dest) {
38311
38857
  const srcArr = normalizePathToArray(src);
38312
38858
  const destArr = normalizePathToArray(dest);
@@ -38433,7 +38979,7 @@ var require_polyfill = __commonJS({
38433
38979
  }
38434
38980
  __name(onDir, "onDir");
38435
38981
  async function mkDirAndCopy(srcMode, src, dest, opts) {
38436
- await mkdir19(dest);
38982
+ await mkdir20(dest);
38437
38983
  await copyDir(src, dest, opts);
38438
38984
  return setDestMode(dest, srcMode);
38439
38985
  }
@@ -38442,8 +38988,8 @@ var require_polyfill = __commonJS({
38442
38988
  const dir = await readdir13(src);
38443
38989
  for (let i = 0; i < dir.length; i++) {
38444
38990
  const item = dir[i];
38445
- const srcItem = join25(src, item);
38446
- const destItem = join25(dest, item);
38991
+ const srcItem = join26(src, item);
38992
+ const destItem = join26(dest, item);
38447
38993
  const { destStat } = await checkPaths(srcItem, destItem, opts);
38448
38994
  await startCopy(destStat, srcItem, destItem, opts);
38449
38995
  }
@@ -38451,8 +38997,8 @@ var require_polyfill = __commonJS({
38451
38997
  __name(copyDir, "copyDir");
38452
38998
  async function onLink(destStat, src, dest) {
38453
38999
  let resolvedSrc = await readlink2(src);
38454
- if (!isAbsolute18(resolvedSrc)) {
38455
- resolvedSrc = resolve24(dirname15(src), resolvedSrc);
39000
+ if (!isAbsolute19(resolvedSrc)) {
39001
+ resolvedSrc = resolve25(dirname15(src), resolvedSrc);
38456
39002
  }
38457
39003
  if (!destStat) {
38458
39004
  return symlink(resolvedSrc, dest);
@@ -38466,8 +39012,8 @@ var require_polyfill = __commonJS({
38466
39012
  }
38467
39013
  throw err;
38468
39014
  }
38469
- if (!isAbsolute18(resolvedDest)) {
38470
- resolvedDest = resolve24(dirname15(dest), resolvedDest);
39015
+ if (!isAbsolute19(resolvedDest)) {
39016
+ resolvedDest = resolve25(dirname15(dest), resolvedDest);
38471
39017
  }
38472
39018
  if (isSrcSubdir(resolvedSrc, resolvedDest)) {
38473
39019
  throw new ERR_FS_CP_EINVAL({
@@ -38519,15 +39065,15 @@ var require_cp = __commonJS({
38519
39065
  // ../../node_modules/.pnpm/@npmcli+fs@4.0.0/node_modules/@npmcli/fs/lib/with-temp-dir.js
38520
39066
  var require_with_temp_dir = __commonJS({
38521
39067
  "../../node_modules/.pnpm/@npmcli+fs@4.0.0/node_modules/@npmcli/fs/lib/with-temp-dir.js"(exports, module) {
38522
- var { join: join25, sep: sep4 } = __require("path");
39068
+ var { join: join26, sep: sep4 } = __require("path");
38523
39069
  var getOptions = require_get_options();
38524
- var { mkdir: mkdir19, mkdtemp: mkdtemp5, rm: rm9 } = __require("fs/promises");
39070
+ var { mkdir: mkdir20, mkdtemp: mkdtemp5, rm: rm9 } = __require("fs/promises");
38525
39071
  var withTempDir = /* @__PURE__ */ __name(async (root, fn, opts) => {
38526
39072
  const options = getOptions(opts, {
38527
39073
  copy: ["tmpPrefix"]
38528
39074
  });
38529
- await mkdir19(root, { recursive: true });
38530
- const target = await mkdtemp5(join25(`${root}${sep4}`, options.tmpPrefix || ""));
39075
+ await mkdir20(root, { recursive: true });
39076
+ const target = await mkdtemp5(join26(`${root}${sep4}`, options.tmpPrefix || ""));
38531
39077
  let err;
38532
39078
  let result;
38533
39079
  try {
@@ -38552,13 +39098,13 @@ var require_with_temp_dir = __commonJS({
38552
39098
  var require_readdir_scoped = __commonJS({
38553
39099
  "../../node_modules/.pnpm/@npmcli+fs@4.0.0/node_modules/@npmcli/fs/lib/readdir-scoped.js"(exports, module) {
38554
39100
  var { readdir: readdir13 } = __require("fs/promises");
38555
- var { join: join25 } = __require("path");
39101
+ var { join: join26 } = __require("path");
38556
39102
  var readdirScoped = /* @__PURE__ */ __name(async (dir) => {
38557
39103
  const results = [];
38558
39104
  for (const item of await readdir13(dir)) {
38559
39105
  if (item.startsWith("@")) {
38560
- for (const scopedItem of await readdir13(join25(dir, item))) {
38561
- results.push(join25(item, scopedItem));
39106
+ for (const scopedItem of await readdir13(join26(dir, item))) {
39107
+ results.push(join26(item, scopedItem));
38562
39108
  }
38563
39109
  } else {
38564
39110
  results.push(item);
@@ -38573,7 +39119,7 @@ var require_readdir_scoped = __commonJS({
38573
39119
  // ../../node_modules/.pnpm/@npmcli+fs@4.0.0/node_modules/@npmcli/fs/lib/move-file.js
38574
39120
  var require_move_file = __commonJS({
38575
39121
  "../../node_modules/.pnpm/@npmcli+fs@4.0.0/node_modules/@npmcli/fs/lib/move-file.js"(exports, module) {
38576
- var { dirname: dirname15, join: join25, resolve: resolve24, relative: relative21, isAbsolute: isAbsolute18 } = __require("path");
39122
+ var { dirname: dirname15, join: join26, resolve: resolve25, relative: relative22, isAbsolute: isAbsolute19 } = __require("path");
38577
39123
  var fs = __require("fs/promises");
38578
39124
  var pathExists2 = /* @__PURE__ */ __name(async (path3) => {
38579
39125
  try {
@@ -38603,7 +39149,7 @@ var require_move_file = __commonJS({
38603
39149
  if (sourceStat.isDirectory()) {
38604
39150
  const files = await fs.readdir(source);
38605
39151
  await Promise.all(files.map(
38606
- (file) => moveFile(join25(source, file), join25(destination, file), options, false, symlinks)
39152
+ (file) => moveFile(join26(source, file), join26(destination, file), options, false, symlinks)
38607
39153
  ));
38608
39154
  } else if (sourceStat.isSymbolicLink()) {
38609
39155
  symlinks.push({ source, destination });
@@ -38617,12 +39163,12 @@ var require_move_file = __commonJS({
38617
39163
  if (root) {
38618
39164
  await Promise.all(symlinks.map(async ({ source: symSource, destination: symDestination }) => {
38619
39165
  let target = await fs.readlink(symSource);
38620
- if (isAbsolute18(target)) {
38621
- target = resolve24(symDestination, relative21(symSource, target));
39166
+ if (isAbsolute19(target)) {
39167
+ target = resolve25(symDestination, relative22(symSource, target));
38622
39168
  }
38623
39169
  let targetStat = "file";
38624
39170
  try {
38625
- targetStat = await fs.stat(resolve24(dirname15(symSource), target));
39171
+ targetStat = await fs.stat(resolve25(dirname15(symSource), target));
38626
39172
  if (targetStat.isDirectory()) {
38627
39173
  targetStat = "junction";
38628
39174
  }
@@ -38695,7 +39241,7 @@ async function pMap(iterable, mapper, {
38695
39241
  const cleanup = /* @__PURE__ */ __name(() => {
38696
39242
  signal?.removeEventListener("abort", signalListener);
38697
39243
  }, "cleanup");
38698
- const resolve24 = /* @__PURE__ */ __name((value) => {
39244
+ const resolve25 = /* @__PURE__ */ __name((value) => {
38699
39245
  resolve_(value);
38700
39246
  cleanup();
38701
39247
  }, "resolve");
@@ -38727,7 +39273,7 @@ async function pMap(iterable, mapper, {
38727
39273
  }
38728
39274
  isResolved = true;
38729
39275
  if (skippedIndexesMap.size === 0) {
38730
- resolve24(result);
39276
+ resolve25(result);
38731
39277
  return;
38732
39278
  }
38733
39279
  const pureResult = [];
@@ -38737,7 +39283,7 @@ async function pMap(iterable, mapper, {
38737
39283
  }
38738
39284
  pureResult.push(value);
38739
39285
  }
38740
- resolve24(pureResult);
39286
+ resolve25(pureResult);
38741
39287
  }
38742
39288
  return;
38743
39289
  }
@@ -38876,8 +39422,8 @@ var require_entry_index = __commonJS({
38876
39422
  var crypto = __require("crypto");
38877
39423
  var {
38878
39424
  appendFile,
38879
- mkdir: mkdir19,
38880
- readFile: readFile29,
39425
+ mkdir: mkdir20,
39426
+ readFile: readFile30,
38881
39427
  readdir: readdir13,
38882
39428
  rm: rm9,
38883
39429
  writeFile: writeFile11
@@ -38923,7 +39469,7 @@ var require_entry_index = __commonJS({
38923
39469
  }).join("\n");
38924
39470
  const setup = /* @__PURE__ */ __name(async () => {
38925
39471
  const target = uniqueFilename(path3.join(cache, "tmp"), opts.tmpPrefix);
38926
- await mkdir19(path3.dirname(target), { recursive: true });
39472
+ await mkdir20(path3.dirname(target), { recursive: true });
38927
39473
  return {
38928
39474
  target,
38929
39475
  moved: false
@@ -38936,7 +39482,7 @@ var require_entry_index = __commonJS({
38936
39482
  }, "teardown");
38937
39483
  const write = /* @__PURE__ */ __name(async (tmp2) => {
38938
39484
  await writeFile11(tmp2.target, newIndex, { flag: "wx" });
38939
- await mkdir19(path3.dirname(bucket), { recursive: true });
39485
+ await mkdir20(path3.dirname(bucket), { recursive: true });
38940
39486
  await moveFile(tmp2.target, bucket);
38941
39487
  tmp2.moved = true;
38942
39488
  }, "write");
@@ -38961,7 +39507,7 @@ var require_entry_index = __commonJS({
38961
39507
  metadata
38962
39508
  };
38963
39509
  try {
38964
- await mkdir19(path3.dirname(bucket), { recursive: true });
39510
+ await mkdir20(path3.dirname(bucket), { recursive: true });
38965
39511
  const stringified = JSON.stringify(entry);
38966
39512
  await appendFile(bucket, `
38967
39513
  ${hashEntry(stringified)} ${stringified}`);
@@ -39069,7 +39615,7 @@ ${hashEntry(stringified)} ${stringified}`);
39069
39615
  __name(ls, "ls");
39070
39616
  module.exports.bucketEntries = bucketEntries;
39071
39617
  async function bucketEntries(bucket, filter) {
39072
- const data = await readFile29(bucket, "utf8");
39618
+ const data = await readFile30(bucket, "utf8");
39073
39619
  return _bucketEntries(data, filter);
39074
39620
  }
39075
39621
  __name(bucketEntries, "bucketEntries");
@@ -42943,9 +43489,9 @@ var require_commonjs5 = __commonJS({
42943
43489
  if (this.#asyncReaddirInFlight) {
42944
43490
  await this.#asyncReaddirInFlight;
42945
43491
  } else {
42946
- let resolve24 = /* @__PURE__ */ __name(() => {
43492
+ let resolve25 = /* @__PURE__ */ __name(() => {
42947
43493
  }, "resolve");
42948
- this.#asyncReaddirInFlight = new Promise((res) => resolve24 = res);
43494
+ this.#asyncReaddirInFlight = new Promise((res) => resolve25 = res);
42949
43495
  try {
42950
43496
  for (const e of await this.#fs.promises.readdir(fullpath, {
42951
43497
  withFileTypes: true
@@ -42958,7 +43504,7 @@ var require_commonjs5 = __commonJS({
42958
43504
  children.provisional = 0;
42959
43505
  }
42960
43506
  this.#asyncReaddirInFlight = void 0;
42961
- resolve24();
43507
+ resolve25();
42962
43508
  }
42963
43509
  return children.slice(0, children.provisional);
42964
43510
  }
@@ -44069,10 +44615,10 @@ var require_ignore = __commonJS({
44069
44615
  ignored(p) {
44070
44616
  const fullpath = p.fullpath();
44071
44617
  const fullpaths = `${fullpath}/`;
44072
- const relative21 = p.relative() || ".";
44073
- const relatives = `${relative21}/`;
44618
+ const relative22 = p.relative() || ".";
44619
+ const relatives = `${relative22}/`;
44074
44620
  for (const m of this.relative) {
44075
- if (m.match(relative21) || m.match(relatives))
44621
+ if (m.match(relative22) || m.match(relatives))
44076
44622
  return true;
44077
44623
  }
44078
44624
  for (const m of this.absolute) {
@@ -44083,9 +44629,9 @@ var require_ignore = __commonJS({
44083
44629
  }
44084
44630
  childrenIgnored(p) {
44085
44631
  const fullpath = p.fullpath() + "/";
44086
- const relative21 = (p.relative() || ".") + "/";
44632
+ const relative22 = (p.relative() || ".") + "/";
44087
44633
  for (const m of this.relativeChildren) {
44088
- if (m.match(relative21))
44634
+ if (m.match(relative22))
44089
44635
  return true;
44090
44636
  }
44091
44637
  for (const m of this.absoluteChildren) {
@@ -45088,8 +45634,8 @@ var require_verify = __commonJS({
45088
45634
  "../../node_modules/.pnpm/cacache@19.0.1/node_modules/cacache/lib/verify.js"(exports, module) {
45089
45635
  "use strict";
45090
45636
  var {
45091
- mkdir: mkdir19,
45092
- readFile: readFile29,
45637
+ mkdir: mkdir20,
45638
+ readFile: readFile30,
45093
45639
  rm: rm9,
45094
45640
  stat: stat9,
45095
45641
  truncate,
@@ -45158,7 +45704,7 @@ var require_verify = __commonJS({
45158
45704
  __name(markEndTime, "markEndTime");
45159
45705
  async function fixPerms(cache, opts) {
45160
45706
  opts.log.silly("verify", "fixing cache permissions");
45161
- await mkdir19(cache, { recursive: true });
45707
+ await mkdir20(cache, { recursive: true });
45162
45708
  return null;
45163
45709
  }
45164
45710
  __name(fixPerms, "fixPerms");
@@ -45176,8 +45722,8 @@ var require_verify = __commonJS({
45176
45722
  liveContent.add(integrity[algo].toString());
45177
45723
  }
45178
45724
  });
45179
- await new Promise((resolve24, reject) => {
45180
- indexStream.on("end", resolve24).on("error", reject);
45725
+ await new Promise((resolve25, reject) => {
45726
+ indexStream.on("end", resolve25).on("error", reject);
45181
45727
  });
45182
45728
  const contentDir = contentPath.contentDir(cache);
45183
45729
  const files = await glob(path3.join(contentDir, "**"), {
@@ -45316,7 +45862,7 @@ var require_verify = __commonJS({
45316
45862
  __name(writeVerifile, "writeVerifile");
45317
45863
  module.exports.lastRun = lastRun;
45318
45864
  async function lastRun(cache) {
45319
- const data = await readFile29(path3.join(cache, "_lastverified"), { encoding: "utf8" });
45865
+ const data = await readFile30(path3.join(cache, "_lastverified"), { encoding: "utf8" });
45320
45866
  return /* @__PURE__ */ new Date(+data);
45321
45867
  }
45322
45868
  __name(lastRun, "lastRun");
@@ -45733,7 +46279,7 @@ var require_promise_retry = __commonJS({
45733
46279
  fn = temp;
45734
46280
  }
45735
46281
  operation = retry.operation(options);
45736
- return new Promise(function(resolve24, reject) {
46282
+ return new Promise(function(resolve25, reject) {
45737
46283
  operation.attempt(function(number) {
45738
46284
  Promise.resolve().then(function() {
45739
46285
  return fn(function(err) {
@@ -45742,7 +46288,7 @@ var require_promise_retry = __commonJS({
45742
46288
  }
45743
46289
  throw errcode(new Error("Retrying"), "EPROMISERETRY", { retried: err });
45744
46290
  }, number);
45745
- }).then(resolve24, function(err) {
46291
+ }).then(resolve25, function(err) {
45746
46292
  if (isRetryError(err)) {
45747
46293
  err = err.retried;
45748
46294
  if (operation.retry(err || new Error())) {
@@ -46627,8 +47173,8 @@ var require_helpers = __commonJS({
46627
47173
  function req(url, opts = {}) {
46628
47174
  const href = typeof url === "string" ? url : url.href;
46629
47175
  const req2 = (href.startsWith("https:") ? https : http).request(url, opts);
46630
- const promise = new Promise((resolve24, reject) => {
46631
- req2.once("response", resolve24).once("error", reject).end();
47176
+ const promise = new Promise((resolve25, reject) => {
47177
+ req2.once("response", resolve25).once("error", reject).end();
46632
47178
  });
46633
47179
  req2.then = promise.then.bind(promise);
46634
47180
  return req2;
@@ -46943,7 +47489,7 @@ var require_parse_proxy_response = __commonJS({
46943
47489
  var debug_1 = __importDefault(require_src());
46944
47490
  var debug = (0, debug_1.default)("https-proxy-agent:parse-proxy-response");
46945
47491
  function parseProxyResponse(socket) {
46946
- return new Promise((resolve24, reject) => {
47492
+ return new Promise((resolve25, reject) => {
46947
47493
  let buffersLength = 0;
46948
47494
  const buffers = [];
46949
47495
  function read() {
@@ -47013,7 +47559,7 @@ var require_parse_proxy_response = __commonJS({
47013
47559
  }
47014
47560
  debug("got proxy server response: %o %o", firstLine, headers);
47015
47561
  cleanup();
47016
- resolve24({
47562
+ resolve25({
47017
47563
  connect: {
47018
47564
  statusCode,
47019
47565
  statusText,
@@ -50692,12 +51238,12 @@ var require_socksclient = __commonJS({
50692
51238
  "use strict";
50693
51239
  var __awaiter = exports && exports.__awaiter || function(thisArg, _arguments, P, generator) {
50694
51240
  function adopt(value) {
50695
- return value instanceof P ? value : new P(function(resolve24) {
50696
- resolve24(value);
51241
+ return value instanceof P ? value : new P(function(resolve25) {
51242
+ resolve25(value);
50697
51243
  });
50698
51244
  }
50699
51245
  __name(adopt, "adopt");
50700
- return new (P || (P = Promise))(function(resolve24, reject) {
51246
+ return new (P || (P = Promise))(function(resolve25, reject) {
50701
51247
  function fulfilled(value) {
50702
51248
  try {
50703
51249
  step(generator.next(value));
@@ -50715,7 +51261,7 @@ var require_socksclient = __commonJS({
50715
51261
  }
50716
51262
  __name(rejected, "rejected");
50717
51263
  function step(result) {
50718
- result.done ? resolve24(result.value) : adopt(result.value).then(fulfilled, rejected);
51264
+ result.done ? resolve25(result.value) : adopt(result.value).then(fulfilled, rejected);
50719
51265
  }
50720
51266
  __name(step, "step");
50721
51267
  step((generator = generator.apply(thisArg, _arguments || [])).next());
@@ -50753,13 +51299,13 @@ var require_socksclient = __commonJS({
50753
51299
  * @returns { Promise }
50754
51300
  */
50755
51301
  static createConnection(options, callback) {
50756
- return new Promise((resolve24, reject) => {
51302
+ return new Promise((resolve25, reject) => {
50757
51303
  try {
50758
51304
  (0, helpers_1.validateSocksClientOptions)(options, ["connect"]);
50759
51305
  } catch (err) {
50760
51306
  if (typeof callback === "function") {
50761
51307
  callback(err);
50762
- return resolve24(err);
51308
+ return resolve25(err);
50763
51309
  } else {
50764
51310
  return reject(err);
50765
51311
  }
@@ -50770,16 +51316,16 @@ var require_socksclient = __commonJS({
50770
51316
  client.removeAllListeners();
50771
51317
  if (typeof callback === "function") {
50772
51318
  callback(null, info);
50773
- resolve24(info);
51319
+ resolve25(info);
50774
51320
  } else {
50775
- resolve24(info);
51321
+ resolve25(info);
50776
51322
  }
50777
51323
  });
50778
51324
  client.once("error", (err) => {
50779
51325
  client.removeAllListeners();
50780
51326
  if (typeof callback === "function") {
50781
51327
  callback(err);
50782
- resolve24(err);
51328
+ resolve25(err);
50783
51329
  } else {
50784
51330
  reject(err);
50785
51331
  }
@@ -50796,13 +51342,13 @@ var require_socksclient = __commonJS({
50796
51342
  * @returns { Promise }
50797
51343
  */
50798
51344
  static createConnectionChain(options, callback) {
50799
- return new Promise((resolve24, reject) => __awaiter(this, void 0, void 0, function* () {
51345
+ return new Promise((resolve25, reject) => __awaiter(this, void 0, void 0, function* () {
50800
51346
  try {
50801
51347
  (0, helpers_1.validateSocksClientChainOptions)(options);
50802
51348
  } catch (err) {
50803
51349
  if (typeof callback === "function") {
50804
51350
  callback(err);
50805
- return resolve24(err);
51351
+ return resolve25(err);
50806
51352
  } else {
50807
51353
  return reject(err);
50808
51354
  }
@@ -50828,14 +51374,14 @@ var require_socksclient = __commonJS({
50828
51374
  }
50829
51375
  if (typeof callback === "function") {
50830
51376
  callback(null, { socket: sock });
50831
- resolve24({ socket: sock });
51377
+ resolve25({ socket: sock });
50832
51378
  } else {
50833
- resolve24({ socket: sock });
51379
+ resolve25({ socket: sock });
50834
51380
  }
50835
51381
  } catch (err) {
50836
51382
  if (typeof callback === "function") {
50837
51383
  callback(err);
50838
- resolve24(err);
51384
+ resolve25(err);
50839
51385
  } else {
50840
51386
  reject(err);
50841
51387
  }
@@ -51523,12 +52069,12 @@ var require_dist6 = __commonJS({
51523
52069
  let { host } = opts;
51524
52070
  const { port, lookup: lookupFn = dns.lookup } = opts;
51525
52071
  if (shouldLookup) {
51526
- host = await new Promise((resolve24, reject) => {
52072
+ host = await new Promise((resolve25, reject) => {
51527
52073
  lookupFn(host, {}, (err, res) => {
51528
52074
  if (err) {
51529
52075
  reject(err);
51530
52076
  } else {
51531
- resolve24(res);
52077
+ resolve25(res);
51532
52078
  }
51533
52079
  });
51534
52080
  });
@@ -52340,8 +52886,8 @@ var require_entry = __commonJS({
52340
52886
  let body = null;
52341
52887
  if (this.response.status === 200) {
52342
52888
  let cacheWriteResolve, cacheWriteReject;
52343
- const cacheWritePromise = new Promise((resolve24, reject) => {
52344
- cacheWriteResolve = resolve24;
52889
+ const cacheWritePromise = new Promise((resolve25, reject) => {
52890
+ cacheWriteResolve = resolve25;
52345
52891
  cacheWriteReject = reject;
52346
52892
  }).catch((err) => {
52347
52893
  body.emit("error", err);
@@ -53856,7 +54402,7 @@ var require_index_min = __commonJS({
53856
54402
  var require_lib17 = __commonJS({
53857
54403
  "../../node_modules/.pnpm/which@5.0.0/node_modules/which/lib/index.js"(exports, module) {
53858
54404
  var { isexe, sync: isexeSync } = require_index_min();
53859
- var { join: join25, delimiter, sep: sep4, posix: posix3 } = __require("path");
54405
+ var { join: join26, delimiter, sep: sep4, posix: posix3 } = __require("path");
53860
54406
  var isWindows = process.platform === "win32";
53861
54407
  var rSlash = new RegExp(`[${posix3.sep}${sep4 === posix3.sep ? "" : sep4}]`.replace(/(\\)/g, "\\$1"));
53862
54408
  var rRel = new RegExp(`^\\.${rSlash.source}`);
@@ -53885,7 +54431,7 @@ var require_lib17 = __commonJS({
53885
54431
  var getPathPart = /* @__PURE__ */ __name((raw, cmd) => {
53886
54432
  const pathPart = /^".*"$/.test(raw) ? raw.slice(1, -1) : raw;
53887
54433
  const prefix = !pathPart && rRel.test(cmd) ? cmd.slice(0, 2) : "";
53888
- return prefix + join25(pathPart, cmd);
54434
+ return prefix + join26(pathPart, cmd);
53889
54435
  }, "getPathPart");
53890
54436
  var which = /* @__PURE__ */ __name(async (cmd, opt = {}) => {
53891
54437
  const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
@@ -54008,9 +54554,9 @@ var require_lib18 = __commonJS({
54008
54554
  if (opts.shell) {
54009
54555
  return spawnWithShell(cmd, args2, opts, extra);
54010
54556
  }
54011
- let resolve24, reject;
54557
+ let resolve25, reject;
54012
54558
  const promise = new Promise((_resolve, _reject) => {
54013
- resolve24 = _resolve;
54559
+ resolve25 = _resolve;
54014
54560
  reject = _reject;
54015
54561
  });
54016
54562
  const closeError = new Error("command failed");
@@ -54043,7 +54589,7 @@ var require_lib18 = __commonJS({
54043
54589
  if (code || signal) {
54044
54590
  rejectWithOpts(closeError, { code, signal });
54045
54591
  } else {
54046
- resolve24(getResult({ code, signal }));
54592
+ resolve25(getResult({ code, signal }));
54047
54593
  }
54048
54594
  });
54049
54595
  return promise;
@@ -55024,7 +55570,7 @@ var require_lib19 = __commonJS({
55024
55570
  // ../../node_modules/.pnpm/npm-normalize-package-bin@4.0.0/node_modules/npm-normalize-package-bin/lib/index.js
55025
55571
  var require_lib20 = __commonJS({
55026
55572
  "../../node_modules/.pnpm/npm-normalize-package-bin@4.0.0/node_modules/npm-normalize-package-bin/lib/index.js"(exports, module) {
55027
- var { join: join25, basename: basename10 } = __require("path");
55573
+ var { join: join26, basename: basename10 } = __require("path");
55028
55574
  var normalize4 = /* @__PURE__ */ __name((pkg) => !pkg.bin ? removeBin(pkg) : typeof pkg.bin === "string" ? normalizeString(pkg) : Array.isArray(pkg.bin) ? normalizeArray(pkg) : typeof pkg.bin === "object" ? normalizeObject(pkg) : removeBin(pkg), "normalize");
55029
55575
  var normalizeString = /* @__PURE__ */ __name((pkg) => {
55030
55576
  if (!pkg.name) {
@@ -55049,11 +55595,11 @@ var require_lib20 = __commonJS({
55049
55595
  const clean = {};
55050
55596
  let hasBins = false;
55051
55597
  Object.keys(orig).forEach((binKey) => {
55052
- const base = join25("/", basename10(binKey.replace(/\\|:/g, "/"))).slice(1);
55598
+ const base = join26("/", basename10(binKey.replace(/\\|:/g, "/"))).slice(1);
55053
55599
  if (typeof orig[binKey] !== "string" || !base) {
55054
55600
  return;
55055
55601
  }
55056
- const binTarget = join25("/", orig[binKey].replace(/\\/g, "/")).replace(/\\/g, "/").slice(1);
55602
+ const binTarget = join26("/", orig[binKey].replace(/\\/g, "/")).replace(/\\/g, "/").slice(1);
55057
55603
  if (!binTarget) {
55058
55604
  return;
55059
55605
  }
@@ -57594,11 +58140,11 @@ var require_normalize = __commonJS({
57594
58140
  // ../../node_modules/.pnpm/@npmcli+package-json@6.2.0/node_modules/@npmcli/package-json/lib/read-package.js
57595
58141
  var require_read_package = __commonJS({
57596
58142
  "../../node_modules/.pnpm/@npmcli+package-json@6.2.0/node_modules/@npmcli/package-json/lib/read-package.js"(exports, module) {
57597
- var { readFile: readFile29 } = __require("fs/promises");
58143
+ var { readFile: readFile30 } = __require("fs/promises");
57598
58144
  var parseJSON = require_lib16();
57599
58145
  async function read(filename) {
57600
58146
  try {
57601
- const data = await readFile29(filename, "utf8");
58147
+ const data = await readFile30(filename, "utf8");
57602
58148
  return data;
57603
58149
  } catch (err) {
57604
58150
  err.message = `Could not read package.json: ${err}`;
@@ -57731,8 +58277,8 @@ var require_sort2 = __commonJS({
57731
58277
  // ../../node_modules/.pnpm/@npmcli+package-json@6.2.0/node_modules/@npmcli/package-json/lib/index.js
57732
58278
  var require_lib23 = __commonJS({
57733
58279
  "../../node_modules/.pnpm/@npmcli+package-json@6.2.0/node_modules/@npmcli/package-json/lib/index.js"(exports, module) {
57734
- var { readFile: readFile29, writeFile: writeFile11 } = __require("node:fs/promises");
57735
- var { resolve: resolve24 } = __require("node:path");
58280
+ var { readFile: readFile30, writeFile: writeFile11 } = __require("node:fs/promises");
58281
+ var { resolve: resolve25 } = __require("node:path");
57736
58282
  var parseJSON = require_lib16();
57737
58283
  var updateDeps = require_update_dependencies();
57738
58284
  var updateScripts = require_update_scripts();
@@ -57855,10 +58401,10 @@ var require_lib23 = __commonJS({
57855
58401
  parseErr = err;
57856
58402
  }
57857
58403
  if (parseErr) {
57858
- const indexFile = resolve24(this.path, "index.js");
58404
+ const indexFile = resolve25(this.path, "index.js");
57859
58405
  let indexFileContent;
57860
58406
  try {
57861
- indexFileContent = await readFile29(indexFile, "utf8");
58407
+ indexFileContent = await readFile30(indexFile, "utf8");
57862
58408
  } catch (err) {
57863
58409
  throw parseErr;
57864
58410
  }
@@ -57907,7 +58453,7 @@ var require_lib23 = __commonJS({
57907
58453
  }
57908
58454
  get filename() {
57909
58455
  if (this.path) {
57910
- return resolve24(this.path, "package.json");
58456
+ return resolve25(this.path, "package.json");
57911
58457
  }
57912
58458
  return void 0;
57913
58459
  }
@@ -64833,12 +65379,12 @@ var require_fetcher = __commonJS({
64833
65379
  };
64834
65380
  exports.DefaultFetcher = DefaultFetcher;
64835
65381
  var writeBufferToStream = /* @__PURE__ */ __name(async (stream, buffer) => {
64836
- return new Promise((resolve24, reject) => {
65382
+ return new Promise((resolve25, reject) => {
64837
65383
  stream.write(buffer, (err) => {
64838
65384
  if (err) {
64839
65385
  reject(err);
64840
65386
  }
64841
- resolve24(true);
65387
+ resolve25(true);
64842
65388
  });
64843
65389
  });
64844
65390
  }, "writeBufferToStream");
@@ -65057,12 +65603,12 @@ var require_url = __commonJS({
65057
65603
  "../../node_modules/.pnpm/tuf-js@3.1.0/node_modules/tuf-js/dist/utils/url.js"(exports) {
65058
65604
  "use strict";
65059
65605
  Object.defineProperty(exports, "__esModule", { value: true });
65060
- exports.join = join25;
65606
+ exports.join = join26;
65061
65607
  var url_1 = __require("url");
65062
- function join25(base, path3) {
65608
+ function join26(base, path3) {
65063
65609
  return new url_1.URL(ensureTrailingSlash(base) + removeLeadingSlash(path3)).toString();
65064
65610
  }
65065
- __name(join25, "join");
65611
+ __name(join26, "join");
65066
65612
  function ensureTrailingSlash(path3) {
65067
65613
  return path3.endsWith("/") ? path3 : path3 + "/";
65068
65614
  }
@@ -65441,7 +65987,7 @@ var require_target = __commonJS({
65441
65987
  var error_1 = require_error8();
65442
65988
  async function readTarget(tuf, targetPath) {
65443
65989
  const path3 = await getTargetPath(tuf, targetPath);
65444
- return new Promise((resolve24, reject) => {
65990
+ return new Promise((resolve25, reject) => {
65445
65991
  fs_1.default.readFile(path3, "utf-8", (err, data) => {
65446
65992
  if (err) {
65447
65993
  reject(new error_1.TUFError({
@@ -65450,7 +65996,7 @@ var require_target = __commonJS({
65450
65996
  cause: err
65451
65997
  }));
65452
65998
  } else {
65453
- resolve24(data);
65999
+ resolve25(data);
65454
66000
  }
65455
66001
  });
65456
66002
  });
@@ -67167,7 +67713,7 @@ var require_dist15 = __commonJS({
67167
67713
  var require_provenance = __commonJS({
67168
67714
  "../../node_modules/.pnpm/libnpmpublish@11.1.0/node_modules/libnpmpublish/lib/provenance.js"(exports, module) {
67169
67715
  var sigstore = require_dist15();
67170
- var { readFile: readFile29 } = __require("node:fs/promises");
67716
+ var { readFile: readFile30 } = __require("node:fs/promises");
67171
67717
  var ci = require_ci_info();
67172
67718
  var { env } = process;
67173
67719
  var INTOTO_PAYLOAD_TYPE = "application/vnd.in-toto+json";
@@ -67359,7 +67905,7 @@ var require_provenance = __commonJS({
67359
67905
  var verifyProvenance = /* @__PURE__ */ __name(async (subject, provenancePath) => {
67360
67906
  let provenanceBundle;
67361
67907
  try {
67362
- provenanceBundle = JSON.parse(await readFile29(provenancePath));
67908
+ provenanceBundle = JSON.parse(await readFile30(provenancePath));
67363
67909
  } catch (err) {
67364
67910
  err.message = `Invalid provenance provided: ${err.message}`;
67365
67911
  throw err;
@@ -67698,9 +68244,9 @@ import { createHash as createHash9, randomUUID } from "node:crypto";
67698
68244
  import { execFile as execFileCb6, spawn as spawn3 } from "node:child_process";
67699
68245
  import { gunzipSync } from "node:zlib";
67700
68246
  import { promisify as promisify6 } from "node:util";
67701
- import { dirname as dirname7, isAbsolute as isAbsolute10, join as join10, relative as relative12, resolve as resolve14 } from "node:path";
68247
+ import { dirname as dirname7, isAbsolute as isAbsolute11, join as join11, relative as relative13, resolve as resolve15 } from "node:path";
67702
68248
  import { constants as fsConstants4 } from "node:fs";
67703
- import { chmod as chmod3, lstat as lstat9, mkdtemp as mkdtemp2, open as open6, readFile as readFile12, realpath as realpath9, rm as rm5 } from "node:fs/promises";
68249
+ import { chmod as chmod3, lstat as lstat9, mkdtemp as mkdtemp2, open as open6, readFile as readFile13, realpath as realpath9, rm as rm5 } from "node:fs/promises";
67704
68250
  function validatePackageName(value) {
67705
68251
  if (typeof value !== "string" || value.length > 214 || !SAFE_PACKAGE_NAME.test(value)) {
67706
68252
  throw new Error("npm package must be a safe lowercase package name or @scope/name");
@@ -67754,7 +68300,7 @@ function expandNpmrcValue(raw, env) {
67754
68300
  async function tokensFromNpmrc(path3, key, env) {
67755
68301
  let contents;
67756
68302
  try {
67757
- contents = await readFile12(path3, "utf8");
68303
+ contents = await readFile13(path3, "utf8");
67758
68304
  } catch (err) {
67759
68305
  if (err?.code === "ENOENT") return [];
67760
68306
  throw new Error("cannot read npm authentication config");
@@ -67777,7 +68323,7 @@ async function defaultResolveAuthToken({ registry, cwd, exec, env = process.env
67777
68323
  if (env[name]) candidates.push(env[name]);
67778
68324
  }
67779
68325
  const key = registryTokenKey(registry);
67780
- candidates.push(...await tokensFromNpmrc(join10(cwd, ".npmrc"), key, env));
68326
+ candidates.push(...await tokensFromNpmrc(join11(cwd, ".npmrc"), key, env));
67781
68327
  const npmUserConfigKey = ["npm", "config", "userconfig"].join("_");
67782
68328
  const userConfig = env[npmUserConfigKey] ?? (await exec("npm", ["config", "get", "userconfig"], { cwd, shell: false })).stdout.trim();
67783
68329
  if (userConfig) candidates.push(...await tokensFromNpmrc(userConfig, key, env));
@@ -67806,10 +68352,10 @@ async function defaultWhoamiWithToken({ registry, token, cwd, exec }) {
67806
68352
  }
67807
68353
  function resolvePackageCwd(cwd, root) {
67808
68354
  if (!cwd || typeof cwd !== "string") throw new Error("NPM_PUBLISH requires a non-empty action.cwd (package directory)");
67809
- const rootPath = resolve14(root);
67810
- const packagePath = resolve14(root, cwd);
67811
- const rel = relative12(rootPath, packagePath);
67812
- if (isAbsolute10(rel) || rel === ".." || rel.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`)) {
68355
+ const rootPath = resolve15(root);
68356
+ const packagePath = resolve15(root, cwd);
68357
+ const rel = relative13(rootPath, packagePath);
68358
+ if (isAbsolute11(rel) || rel === ".." || rel.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`)) {
67813
68359
  throw new Error(`cwd "${cwd}" is outside project root "${root}"`);
67814
68360
  }
67815
68361
  return packagePath;
@@ -67822,12 +68368,12 @@ ${error?.message ?? ""}`;
67822
68368
  return /\bE404\b|\b404\b.*not found|not found.*\b404\b/i.test(text);
67823
68369
  }
67824
68370
  async function readVerifiedTarballBytes(action, root) {
67825
- if (!action.tarballPath || isAbsolute10(action.tarballPath)) throw new Error("tarballPath must be project-relative");
68371
+ if (!action.tarballPath || isAbsolute11(action.tarballPath)) throw new Error("tarballPath must be project-relative");
67826
68372
  if (!/^[a-f0-9]{64}$/.test(action.tarballSha256 ?? "")) throw new Error("tarballSha256 must be a lowercase SHA-256 digest");
67827
68373
  const rootReal = await realpath9(root);
67828
- const lexical = resolve14(rootReal, action.tarballPath);
67829
- const rel = relative12(rootReal, lexical);
67830
- if (isAbsolute10(rel) || rel === ".." || rel.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`)) {
68374
+ const lexical = resolve15(rootReal, action.tarballPath);
68375
+ const rel = relative13(rootReal, lexical);
68376
+ if (isAbsolute11(rel) || rel === ".." || rel.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`)) {
67831
68377
  throw new Error("tarballPath escapes project root");
67832
68378
  }
67833
68379
  const before = await lstat9(lexical);
@@ -68096,7 +68642,7 @@ function createNpmAdapter(deps = {}) {
68096
68642
  throw new Error("npm bearer authentication does not match the frozen registry and publisher");
68097
68643
  }
68098
68644
  if (typeof beforeBufferPublishHook === "function") {
68099
- await beforeBufferPublishHook(resolve14(context.root, action.tarballPath));
68645
+ await beforeBufferPublishHook(resolve15(context.root, action.tarballPath));
68100
68646
  }
68101
68647
  try {
68102
68648
  await publishTarballBuffer({
@@ -68258,11 +68804,11 @@ var init_npm = __esm({
68258
68804
  });
68259
68805
 
68260
68806
  // src/core/run.mjs
68261
- import { link as link2, lstat as lstat10, mkdir as mkdir10, open as open7, readFile as readFile13, unlink as unlink3 } from "node:fs/promises";
68807
+ import { link as link2, lstat as lstat10, mkdir as mkdir11, open as open7, readFile as readFile14, unlink as unlink3 } from "node:fs/promises";
68262
68808
  import { realpathSync as realpathSync3 } from "node:fs";
68263
- import { dirname as dirname8, join as join11, resolve as resolve15, basename as basename4, relative as relative13, isAbsolute as isAbsolute11 } from "node:path";
68809
+ import { dirname as dirname8, join as join12, resolve as resolve16, basename as basename4, relative as relative14, isAbsolute as isAbsolute12 } from "node:path";
68264
68810
  function resolveDefaultRunDir(planPath, command2, runId = `${command2}-${Date.now()}`) {
68265
- const absolute = resolve15(planPath);
68811
+ const absolute = resolve16(planPath);
68266
68812
  const fileName = basename4(absolute);
68267
68813
  const parentDir = dirname8(absolute);
68268
68814
  if (fileName === "release-plan.json") {
@@ -68270,7 +68816,7 @@ function resolveDefaultRunDir(planPath, command2, runId = `${command2}-${Date.no
68270
68816
  }
68271
68817
  if (basename4(parentDir) === "plans") {
68272
68818
  const releaseDir = dirname8(parentDir);
68273
- return join11(releaseDir, "runs", runId);
68819
+ return join12(releaseDir, "runs", runId);
68274
68820
  }
68275
68821
  return `${parentDir}/runs/${runId}`;
68276
68822
  }
@@ -68310,7 +68856,7 @@ function validateRun(run5, options = {}) {
68310
68856
  async function loadRun(runPath, options = {}) {
68311
68857
  let raw;
68312
68858
  try {
68313
- raw = await readFile13(runPath, "utf8");
68859
+ raw = await readFile14(runPath, "utf8");
68314
68860
  } catch (err) {
68315
68861
  throw new ReleaseError(
68316
68862
  GATE_FAILED,
@@ -68335,7 +68881,7 @@ async function loadRun(runPath, options = {}) {
68335
68881
  return run5;
68336
68882
  }
68337
68883
  function assertImmutableRunAuthority(runPath, planPath, run5) {
68338
- const absolutePlan = realpathSync3(resolve15(planPath));
68884
+ const absolutePlan = realpathSync3(resolve16(planPath));
68339
68885
  const planDir = dirname8(absolutePlan);
68340
68886
  if (basename4(planDir) !== "plans") {
68341
68887
  throw new ReleaseError(GATE_FAILED, "run authority requires an immutable plans/<digest>.json plan path");
@@ -68349,10 +68895,10 @@ function assertImmutableRunAuthority(runPath, planPath, run5) {
68349
68895
  }
68350
68896
  cursor = dirname8(cursor);
68351
68897
  }
68352
- const runsDir = join11(authorityRoot, "runs");
68353
- const absoluteRun = realpathSync3(resolve15(runPath));
68354
- const rel = relative13(runsDir, absoluteRun);
68355
- if (isAbsolute11(rel) || rel === ".." || rel.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`)) {
68898
+ const runsDir = join12(authorityRoot, "runs");
68899
+ const absoluteRun = realpathSync3(resolve16(runPath));
68900
+ const rel = relative14(runsDir, absoluteRun);
68901
+ if (isAbsolute12(rel) || rel === ".." || rel.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`)) {
68356
68902
  throw new ReleaseError(GATE_FAILED, "production run authority must be inside the plan sibling runs/ directory");
68357
68903
  }
68358
68904
  const fileName = basename4(absoluteRun);
@@ -68367,7 +68913,7 @@ function assertImmutableRunAuthority(runPath, planPath, run5) {
68367
68913
  }
68368
68914
  }
68369
68915
  async function createProductionRunDir(runDir, planPath) {
68370
- const absolutePlan = realpathSync3(resolve15(planPath));
68916
+ const absolutePlan = realpathSync3(resolve16(planPath));
68371
68917
  const planDir = dirname8(absolutePlan);
68372
68918
  if (basename4(planDir) !== "plans") {
68373
68919
  throw new ReleaseError(GATE_FAILED, "production run directory requires an immutable plans/<digest>.json authority");
@@ -68376,7 +68922,7 @@ async function createProductionRunDir(runDir, planPath) {
68376
68922
  return createProductionRunDirWithinAuthority(runDir, authorityRoot);
68377
68923
  }
68378
68924
  async function createProductionPrepareRunDir(runDir, releaseDir) {
68379
- const authorityRoot = resolve15(releaseDir);
68925
+ const authorityRoot = resolve16(releaseDir);
68380
68926
  let authorityStat;
68381
68927
  try {
68382
68928
  authorityStat = await lstat10(authorityRoot);
@@ -68404,7 +68950,7 @@ async function createProductionPrepareRunDir(runDir, releaseDir) {
68404
68950
  return createProductionRunDirWithinAuthority(runDir, physicalAuthorityRoot);
68405
68951
  }
68406
68952
  async function createProductionRunDirWithinAuthority(runDir, authorityRoot) {
68407
- const runsDir = join11(authorityRoot, "runs");
68953
+ const runsDir = join12(authorityRoot, "runs");
68408
68954
  let runsStat;
68409
68955
  try {
68410
68956
  runsStat = await lstat10(runsDir);
@@ -68416,7 +68962,7 @@ async function createProductionRunDirWithinAuthority(runDir, authorityRoot) {
68416
68962
  });
68417
68963
  }
68418
68964
  try {
68419
- await mkdir10(runsDir, { mode: 448 });
68965
+ await mkdir11(runsDir, { mode: 448 });
68420
68966
  } catch (mkdirError) {
68421
68967
  if (mkdirError.code !== "EEXIST") {
68422
68968
  throw new ReleaseError(GATE_FAILED, "cannot create production runs authority root", {
@@ -68442,7 +68988,7 @@ async function createProductionRunDirWithinAuthority(runDir, authorityRoot) {
68442
68988
  { runsDir, physicalRunsDir }
68443
68989
  );
68444
68990
  }
68445
- const requested = resolve15(runDir);
68991
+ const requested = resolve16(runDir);
68446
68992
  let physicalParent;
68447
68993
  try {
68448
68994
  physicalParent = realpathSync3(dirname8(requested));
@@ -68472,7 +69018,7 @@ async function createProductionRunDirWithinAuthority(runDir, authorityRoot) {
68472
69018
  }
68473
69019
  }
68474
69020
  try {
68475
- await mkdir10(requested, { mode: 448 });
69021
+ await mkdir11(requested, { mode: 448 });
68476
69022
  } catch (error) {
68477
69023
  throw new ReleaseError(GATE_FAILED, "cannot exclusively create production run directory", {
68478
69024
  runDir,
@@ -68493,7 +69039,7 @@ async function validateStatePredecessorChain(run5, runPath, options = {}) {
68493
69039
  return;
68494
69040
  }
68495
69041
  let current = run5;
68496
- let currentPath = realpathSync3(resolve15(runPath));
69042
+ let currentPath = realpathSync3(resolve16(runPath));
68497
69043
  let traversed = 0;
68498
69044
  while (true) {
68499
69045
  const sequence = current.stateSequence;
@@ -68514,7 +69060,7 @@ async function validateStatePredecessorChain(run5, runPath, options = {}) {
68514
69060
  if (traversed > 1e5) {
68515
69061
  throw new ReleaseError(GATE_FAILED, "run state predecessor chain exceeds maximum depth");
68516
69062
  }
68517
- const previousPath = join11(dirname8(currentPath), `${String(sequence - 1).padStart(6, "0")}.json`);
69063
+ const previousPath = join12(dirname8(currentPath), `${String(sequence - 1).padStart(6, "0")}.json`);
68518
69064
  const previous = await loadRun(previousPath, {
68519
69065
  requireDigest: true,
68520
69066
  ...options.production ? { authorityPlanPath: options.planPath } : {}
@@ -68607,7 +69153,7 @@ function validateRunPlanDigest(run5, plan, options = {}) {
68607
69153
  { runDigest: run5.planDigest, planDigest: expectedDigest }
68608
69154
  );
68609
69155
  }
68610
- if (plan.production && run5.planPath && options.planPath && resolve15(run5.planPath) !== resolve15(options.planPath)) {
69156
+ if (plan.production && run5.planPath && options.planPath && resolve16(run5.planPath) !== resolve16(options.planPath)) {
68611
69157
  throw new ReleaseError(
68612
69158
  GATE_FAILED,
68613
69159
  "source run immutable plan path does not match the supplied plan authority",
@@ -68691,7 +69237,7 @@ async function writeRunAtomic(runPath, run5) {
68691
69237
  const json = JSON.stringify(sealed, null, 2);
68692
69238
  const dir = dirname8(runPath);
68693
69239
  const tmpPath = `${dir}/.release-run-${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`;
68694
- await mkdir10(dir, { recursive: true });
69240
+ await mkdir11(dir, { recursive: true });
68695
69241
  const handle = await open7(tmpPath, "wx", 384);
68696
69242
  try {
68697
69243
  await handle.writeFile(json, "utf8");
@@ -68705,7 +69251,7 @@ async function writeRunAtomic(runPath, run5) {
68705
69251
  await syncDirectory(dir);
68706
69252
  } catch (error) {
68707
69253
  if (error.code !== "EEXIST") throw error;
68708
- const existing = await readFile13(runPath, "utf8");
69254
+ const existing = await readFile14(runPath, "utf8");
68709
69255
  if (existing !== json) {
68710
69256
  throw new ReleaseError(
68711
69257
  GATE_FAILED,
@@ -68724,10 +69270,10 @@ async function appendRunState(runDir, sequence, run5) {
68724
69270
  if (!Number.isSafeInteger(sequence) || sequence < 0) {
68725
69271
  throw new ReleaseError(GATE_FAILED, "run state sequence must be a non-negative integer");
68726
69272
  }
68727
- const statesDir = join11(runDir, "states");
69273
+ const statesDir = join12(runDir, "states");
68728
69274
  let previousStateDigest;
68729
69275
  if (sequence > 0) {
68730
- const previousPath = join11(statesDir, `${String(sequence - 1).padStart(6, "0")}.json`);
69276
+ const previousPath = join12(statesDir, `${String(sequence - 1).padStart(6, "0")}.json`);
68731
69277
  const previous = await loadRun(previousPath, { requireDigest: true });
68732
69278
  if (previous.stateSequence !== sequence - 1 || previous.runId !== run5.runId || previous.command !== run5.command || previous.planDigest !== run5.planDigest) {
68733
69279
  throw new ReleaseError(
@@ -68744,7 +69290,7 @@ async function appendRunState(runDir, sequence, run5) {
68744
69290
  stateSequence: sequence,
68745
69291
  ...previousStateDigest ? { previousStateDigest } : {}
68746
69292
  });
68747
- const statePath = join11(statesDir, `${String(sequence).padStart(6, "0")}.json`);
69293
+ const statePath = join12(statesDir, `${String(sequence).padStart(6, "0")}.json`);
68748
69294
  await writeRunAtomic(statePath, state);
68749
69295
  return Object.freeze({ state, statePath });
68750
69296
  }
@@ -68784,8 +69330,8 @@ var init_run = __esm({
68784
69330
  });
68785
69331
 
68786
69332
  // src/artifacts/transaction-journal.mjs
68787
- import { readdir as readdir8, readFile as readFile14, rm as rm6, stat as stat4 } from "node:fs/promises";
68788
- import { join as join12 } from "node:path";
69333
+ import { readdir as readdir8, readFile as readFile15, rm as rm6, stat as stat4 } from "node:fs/promises";
69334
+ import { join as join13 } from "node:path";
68789
69335
  function failSchema(message, details) {
68790
69336
  throw new ReleaseError(TRANSACTION_INCOMPLETE, message, details);
68791
69337
  }
@@ -69792,11 +70338,11 @@ async function pruneTerminalTransactionRecords(transactionsRoot, {
69792
70338
  if (txnDirs.length <= retentionMax) return summary;
69793
70339
  const terminal = [];
69794
70340
  for (const entry of txnDirs) {
69795
- const recordDir = join12(transactionsRoot, entry.name);
70341
+ const recordDir = join13(transactionsRoot, entry.name);
69796
70342
  let state = null;
69797
70343
  let createdAt = null;
69798
70344
  try {
69799
- const raw = await readFile14(join12(recordDir, "journal.json"), "utf8");
70345
+ const raw = await readFile15(join13(recordDir, "journal.json"), "utf8");
69800
70346
  const journal = JSON.parse(raw);
69801
70347
  if (journal && typeof journal === "object") {
69802
70348
  state = typeof journal.state === "string" ? journal.state : null;
@@ -69860,7 +70406,7 @@ async function createTransactionJournal({
69860
70406
  );
69861
70407
  if (typeof root === "string" && root.length > 0) {
69862
70408
  await pruneTerminalTransactionRecords(
69863
- join12(root, ".release-skill", "transactions"),
70409
+ join13(root, ".release-skill", "transactions"),
69864
70410
  { retentionMax }
69865
70411
  );
69866
70412
  }
@@ -70224,7 +70770,7 @@ __export(transaction_exports, {
70224
70770
  applyWriteSetUnderLock: () => applyWriteSetUnderLock
70225
70771
  });
70226
70772
  import { randomBytes as randomBytes2 } from "node:crypto";
70227
- import { relative as relative14 } from "node:path";
70773
+ import { relative as relative15 } from "node:path";
70228
70774
  function computeCanonicalPlanDigest(plan) {
70229
70775
  const { planDigest: _ignored, ...content } = plan;
70230
70776
  return `sha256:${sha256Hex(canonicalJson(content))}`;
@@ -71137,7 +71683,7 @@ async function applyArtifactPlanUnderLock({
71137
71683
  }
71138
71684
  const handle = await safeFs.openRoot(root);
71139
71685
  try {
71140
- const relPlanPath = canonicalArtifactPath(relative14(root, planPath)).path;
71686
+ const relPlanPath = canonicalArtifactPath(relative15(root, planPath)).path;
71141
71687
  const planFileData = await withParentHandle(handle, relPlanPath, async (parent, leaf) => {
71142
71688
  const planEntry = await parent.readEntry(leaf);
71143
71689
  if (!planEntry || planEntry.kind === "absent") {
@@ -73552,7 +74098,7 @@ __export(refresh_service_exports, {
73552
74098
  planReleaseDocsRefreshForUnit: () => planReleaseDocsRefreshForUnit,
73553
74099
  runReleaseDocsRefresh: () => runReleaseDocsRefresh
73554
74100
  });
73555
- import { isAbsolute as isAbsolute12, relative as relative15, resolve as resolve16, sep as sep3 } from "node:path";
74101
+ import { isAbsolute as isAbsolute13, relative as relative16, resolve as resolve17, sep as sep3 } from "node:path";
73556
74102
  function deepFreeze6(value) {
73557
74103
  if (Array.isArray(value)) {
73558
74104
  for (const item of value) deepFreeze6(item);
@@ -73635,7 +74181,7 @@ async function planReleaseDocsRefreshForUnit({
73635
74181
  field: "unit.source"
73636
74182
  });
73637
74183
  }
73638
- const unitRoot = resolve16(root, unit.source);
74184
+ const unitRoot = resolve17(root, unit.source);
73639
74185
  const backend = await (backendFactory ?? loadSafeFs)();
73640
74186
  const sharedFactory = /* @__PURE__ */ __name(async () => backend, "sharedFactory");
73641
74187
  const notesSource = await loadReleaseNotesSource({
@@ -73845,9 +74391,9 @@ async function runReleaseDocsRefresh({
73845
74391
  });
73846
74392
  }
73847
74393
  const changedFiles = plan.files.filter((file) => file.changed);
73848
- const unitRoot = resolve16(root, unit.source);
73849
- const unitLocation = relative15(root, unitRoot);
73850
- if (unitLocation === ".." || unitLocation.startsWith(`..${sep3}`) || isAbsolute12(unitLocation)) {
74394
+ const unitRoot = resolve17(root, unit.source);
74395
+ const unitLocation = relative16(root, unitRoot);
74396
+ if (unitLocation === ".." || unitLocation.startsWith(`..${sep3}`) || isAbsolute13(unitLocation)) {
73851
74397
  throw new ReleaseError(
73852
74398
  PATH_UNSAFE,
73853
74399
  "release unit source escapes the project root",
@@ -73905,7 +74451,7 @@ async function runReleaseDocsRefresh({
73905
74451
  if (err instanceof ReleaseError && err.code === TRANSACTION_INCOMPLETE && typeof err.details?.recover === "string") {
73906
74452
  const restored = await tryRestoreOldBytes(
73907
74453
  backend,
73908
- resolve16(root, unit.source),
74454
+ resolve17(root, unit.source),
73909
74455
  changedFiles,
73910
74456
  modes
73911
74457
  );
@@ -73995,14 +74541,18 @@ var init_refresh_service = __esm({
73995
74541
  // src/commands/prepare.mjs
73996
74542
  var prepare_exports = {};
73997
74543
  __export(prepare_exports, {
74544
+ buildExternalActions: () => buildExternalActions,
74545
+ decodeExternalMarketplaceIndex: () => decodeExternalMarketplaceIndex,
74546
+ parseExternalMarketplaceLsRemote: () => parseExternalMarketplaceLsRemote,
73998
74547
  prepareRelease: () => prepareRelease,
73999
74548
  readHeadCommitTimestamp: () => readHeadCommitTimestamp,
74000
74549
  resolveAllUnitVersions: () => resolveAllUnitVersions,
74550
+ resolveExternalMarketplaceFreezes: () => resolveExternalMarketplaceFreezes,
74001
74551
  resolveUnitVersion: () => resolveUnitVersion,
74002
74552
  runDeclaredHooks: () => runDeclaredHooks
74003
74553
  });
74004
- import { resolve as resolve17, relative as relative16, isAbsolute as isAbsolute13, normalize as normalize3, dirname as dirname9 } from "node:path";
74005
- import { readFile as readFile15, mkdir as mkdir11, realpath as realpath10 } from "node:fs/promises";
74554
+ import { resolve as resolve18, relative as relative17, isAbsolute as isAbsolute14, normalize as normalize3, dirname as dirname9 } from "node:path";
74555
+ import { readFile as readFile16, mkdir as mkdir12, realpath as realpath10 } from "node:fs/promises";
74006
74556
  import { execFile as execFileCb7 } from "node:child_process";
74007
74557
  import { promisify as promisify7 } from "node:util";
74008
74558
  async function resolveUnitVersion(unit, root, explicitVersion) {
@@ -74014,18 +74564,18 @@ async function resolveUnitVersion(unit, root, explicitVersion) {
74014
74564
  { unitId: unit.id }
74015
74565
  );
74016
74566
  }
74017
- if (isAbsolute13(versionSource)) {
74567
+ if (isAbsolute14(versionSource)) {
74018
74568
  throw new ReleaseError(
74019
74569
  CONFIG_INVALID,
74020
74570
  `unit "${unit.id}" version.source must be a relative path, got absolute: "${versionSource}"`,
74021
74571
  { unitId: unit.id, versionSource }
74022
74572
  );
74023
74573
  }
74024
- const unitRoot = resolve17(root, unit.source);
74025
- const resolvedPath = resolve17(unitRoot, versionSource);
74574
+ const unitRoot = resolve18(root, unit.source);
74575
+ const resolvedPath = resolve18(unitRoot, versionSource);
74026
74576
  const normalizedPath = normalize3(resolvedPath);
74027
- const rel = relative16(unitRoot, normalizedPath);
74028
- if (rel.startsWith("..") || rel === ".." || isAbsolute13(rel)) {
74577
+ const rel = relative17(unitRoot, normalizedPath);
74578
+ if (rel.startsWith("..") || rel === ".." || isAbsolute14(rel)) {
74029
74579
  throw new ReleaseError(
74030
74580
  CONFIG_INVALID,
74031
74581
  `unit "${unit.id}" version.source escapes unit root: "${versionSource}"`,
@@ -74034,7 +74584,7 @@ async function resolveUnitVersion(unit, root, explicitVersion) {
74034
74584
  }
74035
74585
  let content;
74036
74586
  try {
74037
- content = await readFile15(normalizedPath, "utf8");
74587
+ content = await readFile16(normalizedPath, "utf8");
74038
74588
  } catch (err) {
74039
74589
  throw new ReleaseError(
74040
74590
  CONFIG_INVALID,
@@ -74324,7 +74874,7 @@ async function processSnapshots(config, root, evidence, runDir, production = fal
74324
74874
  const unitResults = [];
74325
74875
  const snapshotDigests = [];
74326
74876
  for (const unit of units) {
74327
- const outputDir = resolveUnitScopedPath(resolve17(runDir, "snapshots"), unit.id);
74877
+ const outputDir = resolveUnitScopedPath(resolve18(runDir, "snapshots"), unit.id);
74328
74878
  await evidence.append({
74329
74879
  phase: "snapshot",
74330
74880
  status: "started",
@@ -74552,7 +75102,7 @@ async function buildProductionAssets(unitResults, resolvedVersions, root, runDir
74552
75102
  const { unit, manifest } = unitResults[index];
74553
75103
  const version = resolvedVersions[index];
74554
75104
  const { tag, branch, branchStrategy } = resolveProductionBranch(unit, version);
74555
- const snapshotPath = relative16(root, manifest.outputDir);
75105
+ const snapshotPath = relative17(root, manifest.outputDir);
74556
75106
  const observed = await computeFrozenSnapshot(manifest.outputDir);
74557
75107
  if (observed.digest !== manifest.snapshotDigest) {
74558
75108
  throw new ReleaseError(
@@ -74563,7 +75113,7 @@ async function buildProductionAssets(unitResults, resolvedVersions, root, runDir
74563
75113
  }
74564
75114
  await sealFrozenSnapshot(manifest.outputDir);
74565
75115
  const sealed = await computeFrozenSnapshot(manifest.outputDir);
74566
- const repositoryDir = resolveUnitScopedPath(resolve17(runDir, "git"), unit.id, { suffix: ".git" });
75116
+ const repositoryDir = resolveUnitScopedPath(resolve18(runDir, "git"), unit.id, { suffix: ".git" });
74567
75117
  const unitBaseline = unitBaselineResults.get(unit.id);
74568
75118
  const parent = branchStrategy === "create-release-branch" ? void 0 : {
74569
75119
  githubHost: unitBaseline.githubHost,
@@ -74584,13 +75134,13 @@ async function buildProductionAssets(unitResults, resolvedVersions, root, runDir
74584
75134
  if (npmDistribution) {
74585
75135
  npm = await buildFrozenNpmTarball({
74586
75136
  snapshotDir: manifest.outputDir,
74587
- tarballDir: resolveUnitScopedPath(resolve17(runDir, "tarballs"), unit.id),
75137
+ tarballDir: resolveUnitScopedPath(resolve18(runDir, "tarballs"), unit.id),
74588
75138
  expectedSnapshotDigest: sealed.digest
74589
75139
  });
74590
75140
  await verifyFrozenNpmTarballIdentity({
74591
75141
  package: npmDistribution.package,
74592
75142
  version,
74593
- tarballPath: relative16(root, npm.tarballPath),
75143
+ tarballPath: relative17(root, npm.tarballPath),
74594
75144
  tarballSha256: npm.sha256,
74595
75145
  integrity: npm.integrity
74596
75146
  }, root);
@@ -74598,7 +75148,7 @@ async function buildProductionAssets(unitResults, resolvedVersions, root, runDir
74598
75148
  assets.push({
74599
75149
  snapshotPath,
74600
75150
  manifestDigest: sealed.digest,
74601
- gitObjectDir: relative16(root, repositoryDir),
75151
+ gitObjectDir: relative17(root, repositoryDir),
74602
75152
  commit: git2.commit,
74603
75153
  tree: git2.tree,
74604
75154
  commitTimestamp: canonicalFreezeTimestamp,
@@ -74607,7 +75157,7 @@ async function buildProductionAssets(unitResults, resolvedVersions, root, runDir
74607
75157
  branch,
74608
75158
  tag,
74609
75159
  npm: npm ? {
74610
- tarballPath: relative16(root, npm.tarballPath),
75160
+ tarballPath: relative17(root, npm.tarballPath),
74611
75161
  tarballSha256: npm.sha256,
74612
75162
  integrity: npm.integrity,
74613
75163
  size: npm.size
@@ -74616,7 +75166,167 @@ async function buildProductionAssets(unitResults, resolvedVersions, root, runDir
74616
75166
  }
74617
75167
  return assets;
74618
75168
  }
74619
- function buildExternalActions(unitResults, resolvedVersions, productionAssets) {
75169
+ function parseExternalMarketplaceLsRemote(stdout) {
75170
+ if (typeof stdout !== "string") return null;
75171
+ const lines = stdout.trim().split("\n").filter((line) => line.length > 0);
75172
+ let defaultBranch = null;
75173
+ let sha = null;
75174
+ for (const line of lines) {
75175
+ const tabIndex = line.indexOf(" ");
75176
+ if (tabIndex < 0) continue;
75177
+ const left = line.slice(0, tabIndex);
75178
+ const right = line.slice(tabIndex + 1);
75179
+ if (right !== "HEAD") continue;
75180
+ if (left.startsWith("ref: refs/heads/")) {
75181
+ defaultBranch = left.slice("ref: refs/heads/".length);
75182
+ } else if (EXTERNAL_MARKETPLACE_SHA_RE2.test(left)) {
75183
+ sha = left;
75184
+ }
75185
+ }
75186
+ if (!sha || !defaultBranch) return null;
75187
+ return { sha, defaultBranch };
75188
+ }
75189
+ function decodeExternalMarketplaceIndex(base64Content) {
75190
+ if (typeof base64Content !== "string") return null;
75191
+ try {
75192
+ const base64 = base64Content.replace(/\s/g, "");
75193
+ const content = Buffer.from(base64, "base64").toString("utf8");
75194
+ const parsed = JSON.parse(content);
75195
+ return parsed && typeof parsed === "object" ? parsed : null;
75196
+ } catch {
75197
+ return null;
75198
+ }
75199
+ }
75200
+ async function defaultObserveExternalMarketplaceHead(repo, { githubHost = "github.com" } = {}) {
75201
+ try {
75202
+ const { stdout } = await execFile6(
75203
+ "git",
75204
+ ["ls-remote", "--symref", `https://${githubHost}/${repo}.git`, "HEAD"],
75205
+ { shell: false, encoding: "utf8", timeout: 3e4 }
75206
+ );
75207
+ const parsed = parseExternalMarketplaceLsRemote(stdout);
75208
+ if (!parsed) {
75209
+ return { status: "unknown", error: "could not resolve HEAD commit sha and default branch from ls-remote --symref output" };
75210
+ }
75211
+ return { status: "observed", sha: parsed.sha, defaultBranch: parsed.defaultBranch };
75212
+ } catch (error) {
75213
+ return { status: "unknown", error: error.message };
75214
+ }
75215
+ }
75216
+ async function defaultFetchExternalMarketplaceIndex(repo, manifestPath, ref, { githubHost = "github.com" } = {}) {
75217
+ try {
75218
+ const { stdout } = await execFile6(
75219
+ "gh",
75220
+ ["api", `repos/${repo}/contents/${manifestPath}?ref=${ref}`, "--jq", ".content"],
75221
+ {
75222
+ shell: false,
75223
+ encoding: "utf8",
75224
+ timeout: 3e4,
75225
+ env: { ...process.env, GH_HOST: githubHost }
75226
+ }
75227
+ );
75228
+ const index = decodeExternalMarketplaceIndex(stdout);
75229
+ if (!index) {
75230
+ return { status: "unknown", error: "could not decode external marketplace index content" };
75231
+ }
75232
+ return { status: "fetched", index };
75233
+ } catch (error) {
75234
+ return { status: "unknown", error: error.message };
75235
+ }
75236
+ }
75237
+ async function resolveExternalMarketplaceFreezes({
75238
+ unitResults,
75239
+ resolvedVersions,
75240
+ offline,
75241
+ evidence,
75242
+ observeHeadFn,
75243
+ fetchIndexFn
75244
+ }) {
75245
+ const freezes = /* @__PURE__ */ new Map();
75246
+ for (let index = 0; index < unitResults.length; index += 1) {
75247
+ const { unit } = unitResults[index];
75248
+ const version = resolvedVersions[index];
75249
+ const githubHost = unit.production?.githubHost ?? "github.com";
75250
+ for (const dist of unit.distributions ?? []) {
75251
+ if (dist.marketplaceRepo === void 0 || dist.marketplaceRepo === null) continue;
75252
+ const platform = PLATFORMS.find((p) => p.distributionType === dist.type);
75253
+ if (!platform || platform.marketplaceRefForm === null) {
75254
+ throw new ReleaseError(
75255
+ GATE_FAILED,
75256
+ `unit "${unit.id}" ${dist.type} distribution declares marketplaceRepo but the platform has no marketplace add capability`,
75257
+ { unitId: unit.id, distributionType: dist.type }
75258
+ );
75259
+ }
75260
+ if (offline) {
75261
+ throw new ReleaseError(
75262
+ GATE_FAILED,
75263
+ `unit "${unit.id}" ${dist.type} external marketplace form requires online production prepare to freeze the marketplace commit sha`,
75264
+ { unitId: unit.id, marketplaceRepo: dist.marketplaceRepo }
75265
+ );
75266
+ }
75267
+ const observed = await observeHeadFn(dist.marketplaceRepo, { githubHost });
75268
+ if (observed.status !== "observed" || !EXTERNAL_MARKETPLACE_SHA_RE2.test(observed.sha ?? "") || !observed.defaultBranch) {
75269
+ throw new ReleaseError(
75270
+ GATE_FAILED,
75271
+ `unit "${unit.id}" could not freeze external marketplace "${dist.marketplaceRepo}" HEAD: ${observed.error ?? "unknown"}`,
75272
+ { unitId: unit.id, marketplaceRepo: dist.marketplaceRepo }
75273
+ );
75274
+ }
75275
+ const sha = observed.sha;
75276
+ const manifestPath = platform.manifestPaths.marketplace;
75277
+ const fetched = await fetchIndexFn(dist.marketplaceRepo, manifestPath, sha, { githubHost });
75278
+ if (fetched.status !== "fetched" || !fetched.index || typeof fetched.index !== "object") {
75279
+ throw new ReleaseError(
75280
+ GATE_FAILED,
75281
+ `unit "${unit.id}" could not read external marketplace index for "${dist.marketplaceRepo}" at ${sha}: ${fetched.error ?? "unknown"}`,
75282
+ { unitId: unit.id, marketplaceRepo: dist.marketplaceRepo }
75283
+ );
75284
+ }
75285
+ const marketplaceIndex = fetched.index;
75286
+ if (marketplaceIndex.name !== dist.marketplace) {
75287
+ throw new ReleaseError(
75288
+ GATE_FAILED,
75289
+ `unit "${unit.id}" external marketplace index name "${marketplaceIndex.name}" does not match distribution marketplace "${dist.marketplace}"`,
75290
+ { unitId: unit.id, marketplaceRepo: dist.marketplaceRepo }
75291
+ );
75292
+ }
75293
+ const pluginEntries = Array.isArray(marketplaceIndex.plugins) ? marketplaceIndex.plugins.filter((entry) => entry && entry.name === dist.plugin) : [];
75294
+ if (pluginEntries.length !== 1) {
75295
+ throw new ReleaseError(
75296
+ GATE_FAILED,
75297
+ `unit "${unit.id}" external marketplace index must contain exactly one plugin entry named "${dist.plugin}", found ${pluginEntries.length}`,
75298
+ { unitId: unit.id, marketplaceRepo: dist.marketplaceRepo }
75299
+ );
75300
+ }
75301
+ if (platform.marketplaceEntryCarriesVersion && pluginEntries[0].version !== version) {
75302
+ throw new ReleaseError(
75303
+ GATE_FAILED,
75304
+ `unit "${unit.id}" external marketplace index entry version "${pluginEntries[0].version}" does not match target version "${version}"`,
75305
+ { unitId: unit.id, marketplaceRepo: dist.marketplaceRepo }
75306
+ );
75307
+ }
75308
+ const ref = platform.marketplaceRefForm === "sha" ? sha : observed.defaultBranch;
75309
+ freezes.set(`${unit.id} ${dist.type}`, {
75310
+ repo: dist.marketplaceRepo,
75311
+ ref,
75312
+ marketplaceCommitSha: sha,
75313
+ marketplace: dist.marketplace
75314
+ });
75315
+ await evidence.append({
75316
+ phase: "external-marketplace-freeze",
75317
+ unitId: unit.id,
75318
+ distributionType: dist.type,
75319
+ status: "completed",
75320
+ marketplaceRepo: dist.marketplaceRepo,
75321
+ marketplaceCommitSha: sha,
75322
+ defaultBranch: observed.defaultBranch,
75323
+ addRef: ref
75324
+ });
75325
+ }
75326
+ }
75327
+ return freezes;
75328
+ }
75329
+ function buildExternalActions(unitResults, resolvedVersions, productionAssets, externalFreezes = /* @__PURE__ */ new Map()) {
74620
75330
  const actions = [];
74621
75331
  if (!productionAssets) {
74622
75332
  for (let index = 0; index < unitResults.length; index += 1) {
@@ -74677,6 +75387,7 @@ function buildExternalActions(unitResults, resolvedVersions, productionAssets) {
74677
75387
  if (!dist) continue;
74678
75388
  const requiresMarketplace = platform.schemaRequiredFields.includes("marketplace");
74679
75389
  const timeoutMs = Number.isInteger(dist.timeoutMs) ? dist.timeoutMs : 3e5;
75390
+ const externalMarketplace = dist.marketplaceRepo !== void 0 && dist.marketplaceRepo !== null;
74680
75391
  actions.push({
74681
75392
  id: `${platform.actionType}-${unit.id}`,
74682
75393
  type: platform.actionType,
@@ -74686,7 +75397,7 @@ function buildExternalActions(unitResults, resolvedVersions, productionAssets) {
74686
75397
  consumer: platform.id,
74687
75398
  plugin: dist.plugin,
74688
75399
  ...requiresMarketplace ? { marketplace: dist.marketplace } : {},
74689
- repo: unit.publicRepo,
75400
+ repo: externalMarketplace ? dist.marketplaceRepo : unit.publicRepo,
74690
75401
  version,
74691
75402
  entrySkill: dist.entrySkill,
74692
75403
  timeoutMs,
@@ -74694,14 +75405,18 @@ function buildExternalActions(unitResults, resolvedVersions, productionAssets) {
74694
75405
  // payload is verified by declared-manifest containment; host-added
74695
75406
  // files are recorded, not failed. Frozen plans without this marker
74696
75407
  // keep the legacy full-tree equality semantics byte-for-byte.
74697
- payloadContract: "declared-manifest-v1"
75408
+ // External marketplace form uses the external-marketplace-v1
75409
+ // contract (whole-tree '.' containment; see plugin-marketplace).
75410
+ payloadContract: externalMarketplace ? "external-marketplace-v1" : "declared-manifest-v1",
75411
+ ...externalMarketplace ? { marketplaceLocation: "external" } : {}
74698
75412
  },
74699
75413
  expected: {
74700
75414
  installed: true,
74701
75415
  plugin: dist.plugin,
74702
75416
  ...requiresMarketplace ? { marketplace: dist.marketplace } : {},
74703
75417
  version,
74704
- entrySkill: dist.entrySkill
75418
+ entrySkill: dist.entrySkill,
75419
+ ...externalMarketplace ? { marketplaceLocation: "external", repo: dist.marketplaceRepo } : {}
74705
75420
  },
74706
75421
  status: "PENDING"
74707
75422
  });
@@ -74836,6 +75551,8 @@ function buildExternalActions(unitResults, resolvedVersions, productionAssets) {
74836
75551
  if (!dist) continue;
74837
75552
  const requiresMarketplace = platform.schemaRequiredFields.includes("marketplace");
74838
75553
  const timeoutMs = Number.isInteger(dist.timeoutMs) ? dist.timeoutMs : 3e5;
75554
+ const externalMarketplace = dist.marketplaceRepo !== void 0 && dist.marketplaceRepo !== null;
75555
+ const freeze = externalMarketplace ? externalFreezes.get(`${unit.id} ${dist.type}`) : null;
74839
75556
  actions.push({
74840
75557
  id: `${platform.actionType}-${unit.id}`,
74841
75558
  type: platform.actionType,
@@ -74845,8 +75562,8 @@ function buildExternalActions(unitResults, resolvedVersions, productionAssets) {
74845
75562
  consumer: platform.id,
74846
75563
  plugin: dist.plugin,
74847
75564
  ...requiresMarketplace ? { marketplace: dist.marketplace } : {},
74848
- repo: unit.publicRepo,
74849
- ref: resolvedTag,
75565
+ repo: externalMarketplace ? dist.marketplaceRepo : unit.publicRepo,
75566
+ ref: externalMarketplace ? freeze.ref : resolvedTag,
74850
75567
  version: unitVersion,
74851
75568
  entrySkill: dist.entrySkill,
74852
75569
  snapshotPath: asset.snapshotPath,
@@ -74856,19 +75573,23 @@ function buildExternalActions(unitResults, resolvedVersions, productionAssets) {
74856
75573
  // payload is verified by declared-manifest containment; host-added
74857
75574
  // files are recorded, not failed. Frozen plans without this marker
74858
75575
  // keep the legacy full-tree equality semantics byte-for-byte.
74859
- payloadContract: "declared-manifest-v1"
75576
+ // External marketplace form uses the external-marketplace-v1
75577
+ // contract (whole-tree '.' containment; see plugin-marketplace).
75578
+ payloadContract: externalMarketplace ? "external-marketplace-v1" : "declared-manifest-v1",
75579
+ ...externalMarketplace ? { marketplaceLocation: "external", marketplaceCommitSha: freeze.marketplaceCommitSha } : {}
74860
75580
  },
74861
75581
  expected: {
74862
75582
  installed: true,
74863
75583
  consumer: platform.id,
74864
75584
  plugin: dist.plugin,
74865
75585
  ...requiresMarketplace ? { marketplace: dist.marketplace } : {},
74866
- repo: unit.publicRepo,
75586
+ repo: externalMarketplace ? dist.marketplaceRepo : unit.publicRepo,
74867
75587
  version: unitVersion,
74868
- ref: resolvedTag,
75588
+ ref: externalMarketplace ? freeze.ref : resolvedTag,
74869
75589
  entrySkill: dist.entrySkill,
74870
75590
  entrySkillFound: true,
74871
- manifestDigest: asset.manifestDigest
75591
+ manifestDigest: asset.manifestDigest,
75592
+ ...externalMarketplace ? { marketplaceLocation: "external", marketplaceCommitSha: freeze.marketplaceCommitSha } : {}
74872
75593
  },
74873
75594
  status: "PENDING"
74874
75595
  });
@@ -74903,25 +75624,25 @@ async function prepareRelease(options) {
74903
75624
  );
74904
75625
  }
74905
75626
  if (production) {
74906
- const canonicalOutput = resolve17(realRoot, ".release-skill", "release-plan.json");
74907
- if (output && resolve17(output) !== canonicalOutput) {
75627
+ const canonicalOutput = resolve18(realRoot, ".release-skill", "release-plan.json");
75628
+ if (output && resolve18(output) !== canonicalOutput) {
74908
75629
  throw new ReleaseError(
74909
75630
  GATE_FAILED,
74910
75631
  "production prepare requires the canonical .release-skill/release-plan.json output; custom --output is supported only outside production",
74911
- { output: resolve17(output), expected: canonicalOutput }
75632
+ { output: resolve18(output), expected: canonicalOutput }
74912
75633
  );
74913
75634
  }
74914
75635
  }
74915
75636
  const lock = await acquireProjectLock({ root: realRoot, command: "prepare", mode: "exclusive" });
74916
- const releaseDir = resolve17(realRoot, ".release-skill");
75637
+ const releaseDir = resolve18(realRoot, ".release-skill");
74917
75638
  const runId = `prepare-${Date.now()}`;
74918
- const rawRunDir = runDirOpt ?? resolve17(releaseDir, "runs", runId);
75639
+ const rawRunDir = runDirOpt ?? resolve18(releaseDir, "runs", runId);
74919
75640
  let runDir;
74920
75641
  try {
74921
75642
  if (production) {
74922
75643
  runDir = await createProductionPrepareRunDir(rawRunDir, releaseDir);
74923
75644
  } else {
74924
- await mkdir11(rawRunDir, { recursive: true });
75645
+ await mkdir12(rawRunDir, { recursive: true });
74925
75646
  runDir = await realpath10(rawRunDir);
74926
75647
  }
74927
75648
  } catch (error) {
@@ -74936,7 +75657,7 @@ async function prepareRelease(options) {
74936
75657
  await evidence.append({
74937
75658
  phase: "config",
74938
75659
  status: "completed",
74939
- configPath: relative16(realRoot, configPath),
75660
+ configPath: relative17(realRoot, configPath),
74940
75661
  configDigest
74941
75662
  });
74942
75663
  const configUnits = config.releaseUnits ?? [];
@@ -75353,7 +76074,15 @@ To proceed, pass --acknowledge-hook-side-effects (CLI) or hooksAuthorized=true (
75353
76074
  ...unitBaseline ? { previousPublicBaseline: unitBaseline } : {}
75354
76075
  };
75355
76076
  });
75356
- const externalActions = buildExternalActions(unitResults, resolvedVersions, productionAssets);
76077
+ const externalMarketplaceFreezes = production ? await resolveExternalMarketplaceFreezes({
76078
+ unitResults,
76079
+ resolvedVersions,
76080
+ offline,
76081
+ evidence,
76082
+ observeHeadFn: options.observeExternalMarketplaceHeadFn ?? defaultObserveExternalMarketplaceHead,
76083
+ fetchIndexFn: options.fetchExternalMarketplaceIndexFn ?? defaultFetchExternalMarketplaceIndex
76084
+ }) : /* @__PURE__ */ new Map();
76085
+ const externalActions = buildExternalActions(unitResults, resolvedVersions, productionAssets, externalMarketplaceFreezes);
75357
76086
  const overallSnapshotDigest = sha256Hex(snapshotDigests.join(":"));
75358
76087
  const plan = {
75359
76088
  planVersion: 2,
@@ -75372,7 +76101,7 @@ To proceed, pass --acknowledge-hook-side-effects (CLI) or hooksAuthorized=true (
75372
76101
  ...production ? {
75373
76102
  production: {
75374
76103
  mode: "github-npm-v1",
75375
- assetRoot: relative16(realRoot, runDir)
76104
+ assetRoot: relative17(realRoot, runDir)
75376
76105
  }
75377
76106
  } : {},
75378
76107
  units,
@@ -75386,9 +76115,9 @@ To proceed, pass --acknowledge-hook-side-effects (CLI) or hooksAuthorized=true (
75386
76115
  actionCount: externalActions.length
75387
76116
  });
75388
76117
  await evidence.append({ phase: "plan-write", status: "started" });
75389
- const latestPlanPath = output ?? resolve17(releaseDir, "release-plan.json");
76118
+ const latestPlanPath = output ?? resolve18(releaseDir, "release-plan.json");
75390
76119
  const plannedDigest = computePlanDigest(plan);
75391
- const immutablePlanPath = resolve17(dirname9(latestPlanPath), "plans", `${plannedDigest}.json`);
76120
+ const immutablePlanPath = resolve18(dirname9(latestPlanPath), "plans", `${plannedDigest}.json`);
75392
76121
  const { planPath: writtenPath, planDigest } = await writePlanImmutable(immutablePlanPath, plan);
75393
76122
  await writePlanAtomic(latestPlanPath, plan);
75394
76123
  await evidence.append({
@@ -75429,7 +76158,7 @@ To proceed, pass --acknowledge-hook-side-effects (CLI) or hooksAuthorized=true (
75429
76158
  await lock.release();
75430
76159
  }
75431
76160
  }
75432
- var execFile6;
76161
+ var execFile6, EXTERNAL_MARKETPLACE_SHA_RE2;
75433
76162
  var init_prepare = __esm({
75434
76163
  async "src/commands/prepare.mjs"() {
75435
76164
  await init_config();
@@ -75462,14 +76191,20 @@ var init_prepare = __esm({
75462
76191
  __name(normalizedProductionConfig, "normalizedProductionConfig");
75463
76192
  __name(readHeadCommitTimestamp, "readHeadCommitTimestamp");
75464
76193
  __name(buildProductionAssets, "buildProductionAssets");
76194
+ EXTERNAL_MARKETPLACE_SHA_RE2 = /^[0-9a-f]{40}$/;
76195
+ __name(parseExternalMarketplaceLsRemote, "parseExternalMarketplaceLsRemote");
76196
+ __name(decodeExternalMarketplaceIndex, "decodeExternalMarketplaceIndex");
76197
+ __name(defaultObserveExternalMarketplaceHead, "defaultObserveExternalMarketplaceHead");
76198
+ __name(defaultFetchExternalMarketplaceIndex, "defaultFetchExternalMarketplaceIndex");
76199
+ __name(resolveExternalMarketplaceFreezes, "resolveExternalMarketplaceFreezes");
75465
76200
  __name(buildExternalActions, "buildExternalActions");
75466
76201
  __name(prepareRelease, "prepareRelease");
75467
76202
  }
75468
76203
  });
75469
76204
 
75470
76205
  // src/core/approval.mjs
75471
- import { readFile as readFile16 } from "node:fs/promises";
75472
- import { basename as basename5, dirname as dirname10, join as join13, resolve as resolve18 } from "node:path";
76206
+ import { readFile as readFile17 } from "node:fs/promises";
76207
+ import { basename as basename5, dirname as dirname10, join as join14, resolve as resolve19 } from "node:path";
75473
76208
  function validateApprovalRecordSchema(approval) {
75474
76209
  if (validateApprovalSchema(approval)) return;
75475
76210
  const errors = validateApprovalSchema.errors ?? [];
@@ -75486,7 +76221,7 @@ function assertImmutableApprovalAuthority(approvalPath, plan, rawApproval) {
75486
76221
  if (!plan?.production) return;
75487
76222
  const planDigest = computePlanDigest(plan);
75488
76223
  const approvalDigest = computeApprovalDigest(rawApproval);
75489
- const absolute = resolve18(approvalPath);
76224
+ const absolute = resolve19(approvalPath);
75490
76225
  const planDirectory = dirname10(absolute);
75491
76226
  if (basename5(absolute) !== `${approvalDigest}.json` || basename5(planDirectory) !== planDigest || basename5(dirname10(planDirectory)) !== "approvals") {
75492
76227
  throw new ReleaseError(
@@ -75755,8 +76490,8 @@ var approve_exports = {};
75755
76490
  __export(approve_exports, {
75756
76491
  approvePlan: () => approvePlan
75757
76492
  });
75758
- import { readFile as readFile17, writeFile as writeFile7 } from "node:fs/promises";
75759
- import { resolve as resolve19, dirname as dirname11, basename as basename6 } from "node:path";
76493
+ import { readFile as readFile18, writeFile as writeFile7 } from "node:fs/promises";
76494
+ import { resolve as resolve20, dirname as dirname11, basename as basename6 } from "node:path";
75760
76495
  function defaultClock() {
75761
76496
  return (/* @__PURE__ */ new Date()).toISOString();
75762
76497
  }
@@ -75782,7 +76517,7 @@ async function approvePlan(options) {
75782
76517
  }
75783
76518
  let planRaw;
75784
76519
  try {
75785
- planRaw = await readFile17(planPath, "utf8");
76520
+ planRaw = await readFile18(planPath, "utf8");
75786
76521
  } catch (err) {
75787
76522
  throw new ReleaseError(
75788
76523
  GATE_FAILED,
@@ -75886,18 +76621,18 @@ async function approvePlan(options) {
75886
76621
  expiresAt
75887
76622
  };
75888
76623
  validateApprovalRecordSchema(approvalRecord);
75889
- const planDir = dirname11(resolve19(planPath));
76624
+ const planDir = dirname11(resolve20(planPath));
75890
76625
  const releaseDir = basename6(planDir) === "plans" && basename6(planPath) === `${actualDigest}.json` ? dirname11(planDir) : planDir;
75891
- if (plan.production?.mode === "github-npm-v1" && outputPath && resolve19(outputPath) !== resolve19(releaseDir, "approval-record.json")) {
76626
+ if (plan.production?.mode === "github-npm-v1" && outputPath && resolve20(outputPath) !== resolve20(releaseDir, "approval-record.json")) {
75892
76627
  throw new ReleaseError(
75893
76628
  GATE_FAILED,
75894
76629
  "production approve requires the canonical approval-record.json alias next to the immutable plan authority; custom --output is supported only outside production",
75895
- { outputPath: resolve19(outputPath), expected: resolve19(releaseDir, "approval-record.json") }
76630
+ { outputPath: resolve20(outputPath), expected: resolve20(releaseDir, "approval-record.json") }
75896
76631
  );
75897
76632
  }
75898
76633
  const json = JSON.stringify(approvalRecord, null, 2);
75899
76634
  const approvalDigest = computeApprovalDigest(json);
75900
- const immutableApprovalPath = resolve19(
76635
+ const immutableApprovalPath = resolve20(
75901
76636
  releaseDir,
75902
76637
  "approvals",
75903
76638
  actualDigest,
@@ -75909,7 +76644,7 @@ async function approvePlan(options) {
75909
76644
  await writeFile7(immutableApprovalPath, json, { encoding: "utf8", flag: "wx", mode: 384 });
75910
76645
  } catch (error) {
75911
76646
  if (error.code !== "EEXIST") throw error;
75912
- const existing = await readFile17(immutableApprovalPath, "utf8");
76647
+ const existing = await readFile18(immutableApprovalPath, "utf8");
75913
76648
  if (existing !== json) {
75914
76649
  throw new ReleaseError(
75915
76650
  GATE_FAILED,
@@ -75918,7 +76653,7 @@ async function approvePlan(options) {
75918
76653
  );
75919
76654
  }
75920
76655
  }
75921
- const writePath = outputPath ?? resolve19(releaseDir, "approval-record.json");
76656
+ const writePath = outputPath ?? resolve20(releaseDir, "approval-record.json");
75922
76657
  await prepareAuthorityDirectory(dirname11(writePath));
75923
76658
  await assertAuthorityFileTarget(writePath);
75924
76659
  await writeFile7(writePath, json, "utf8");
@@ -75976,7 +76711,8 @@ var init_checkpoints = __esm({
75976
76711
  "github-release",
75977
76712
  "claude-marketplace-install",
75978
76713
  "codex-marketplace-install",
75979
- "kimi-marketplace-install"
76714
+ "kimi-marketplace-install",
76715
+ "codebuddy-marketplace-install"
75980
76716
  ];
75981
76717
  ADAPTER_ACTION_TYPE_MAP = {
75982
76718
  "push-commit": "git-push",
@@ -75987,7 +76723,8 @@ var init_checkpoints = __esm({
75987
76723
  "github-release": "github-release",
75988
76724
  "claude-marketplace-install": "claude-marketplace-install",
75989
76725
  "codex-marketplace-install": "codex-marketplace-install",
75990
- "kimi-marketplace-install": "kimi-marketplace-install"
76726
+ "kimi-marketplace-install": "kimi-marketplace-install",
76727
+ "codebuddy-marketplace-install": "codebuddy-marketplace-install"
75991
76728
  };
75992
76729
  TIER_TABLE = [
75993
76730
  ["push-commit", "push-snapshot"],
@@ -75996,7 +76733,7 @@ var init_checkpoints = __esm({
75996
76733
  // Tier 1
75997
76734
  ["github-release", "claude-marketplace-install", "codex-marketplace-install"],
75998
76735
  // Tier 2
75999
- ["kimi-marketplace-install"]
76736
+ ["kimi-marketplace-install", "codebuddy-marketplace-install"]
76000
76737
  // Tier 3
76001
76738
  ];
76002
76739
  TIER_OF = /* @__PURE__ */ new Map();
@@ -76096,7 +76833,7 @@ function defaultSleep(ms) {
76096
76833
  if (process.env.RELEASE_SKILL_OBSERVE_RETRY_NO_WAIT === "1") {
76097
76834
  return Promise.resolve();
76098
76835
  }
76099
- return new Promise((resolve24) => setTimeout(resolve24, ms));
76836
+ return new Promise((resolve25) => setTimeout(resolve25, ms));
76100
76837
  }
76101
76838
  function isPropagatingMissing(result) {
76102
76839
  if (result == null) return true;
@@ -76185,8 +76922,8 @@ var reconcile_exports = {};
76185
76922
  __export(reconcile_exports, {
76186
76923
  reconcileRelease: () => reconcileRelease
76187
76924
  });
76188
- import { readFile as readFile18, mkdir as mkdir12 } from "node:fs/promises";
76189
- import { join as join14 } from "node:path";
76925
+ import { readFile as readFile19, mkdir as mkdir13 } from "node:fs/promises";
76926
+ import { join as join15 } from "node:path";
76190
76927
  function defaultClock3() {
76191
76928
  return (/* @__PURE__ */ new Date()).toISOString();
76192
76929
  }
@@ -76215,7 +76952,7 @@ async function reconcileRelease(options) {
76215
76952
  }
76216
76953
  let planRaw;
76217
76954
  try {
76218
- planRaw = await readFile18(planPath, "utf8");
76955
+ planRaw = await readFile19(planPath, "utf8");
76219
76956
  } catch (err) {
76220
76957
  throw new ReleaseError(GATE_FAILED, `cannot read release plan: ${err.message}`, { planPath, cause: err.code });
76221
76958
  }
@@ -76233,7 +76970,7 @@ async function reconcileRelease(options) {
76233
76970
  if (isProductionPlan) {
76234
76971
  runDir = await createProductionRunDir(runDir, planPath);
76235
76972
  } else {
76236
- await mkdir12(runDir, { recursive: true });
76973
+ await mkdir13(runDir, { recursive: true });
76237
76974
  }
76238
76975
  const evidence = createEvidenceWriter({ runDir, command: "reconcile", clock: clockFn });
76239
76976
  try {
@@ -76294,7 +77031,7 @@ async function reconcileRelease(options) {
76294
77031
  { sourceRunId: sourceRun.runId }
76295
77032
  );
76296
77033
  }
76297
- const sourceApprovalRaw = await readFile18(consumedApprovalPath, "utf8").catch((error) => {
77034
+ const sourceApprovalRaw = await readFile19(consumedApprovalPath, "utf8").catch((error) => {
76298
77035
  throw new ReleaseError(GATE_FAILED, "source run approval authority is unavailable", {
76299
77036
  sourceRunId: sourceRun.runId,
76300
77037
  cause: error.code
@@ -76472,7 +77209,7 @@ async function reconcileRelease(options) {
76472
77209
  if (approvalPath) {
76473
77210
  let approvalRaw;
76474
77211
  try {
76475
- approvalRaw = await readFile18(approvalPath, "utf8");
77212
+ approvalRaw = await readFile19(approvalPath, "utf8");
76476
77213
  } catch (err) {
76477
77214
  throw new ReleaseError(
76478
77215
  GATE_FAILED,
@@ -77273,7 +78010,7 @@ async function reconcileRelease(options) {
77273
78010
  status: status === "succeeded" ? "succeeded" : status === "failed" ? "failed" : status === "skipped" ? "skipped" : status === "uncertain" ? "uncertain" : "pending"
77274
78011
  };
77275
78012
  });
77276
- const runPath = join14(runDir, "release-run.json");
78013
+ const runPath = join15(runDir, "release-run.json");
77277
78014
  const sourceRunDigest = sourceAuthorityDigest;
77278
78015
  const runState = {
77279
78016
  runId,
@@ -77346,7 +78083,8 @@ var init_reconcile = __esm({
77346
78083
  MARKETPLACE_TYPES = /* @__PURE__ */ new Set([
77347
78084
  "claude-marketplace-install",
77348
78085
  "codex-marketplace-install",
77349
- "kimi-marketplace-install"
78086
+ "kimi-marketplace-install",
78087
+ "codebuddy-marketplace-install"
77350
78088
  ]);
77351
78089
  __name(defaultClock3, "defaultClock");
77352
78090
  __name(reconcileRelease, "reconcileRelease");
@@ -77943,8 +78681,8 @@ __export(plugin_marketplace_exports, {
77943
78681
  });
77944
78682
  import { execFile as execFileCb10 } from "node:child_process";
77945
78683
  import { promisify as promisify10 } from "node:util";
77946
- import { readFile as readFile19, stat as stat5, mkdir as mkdir13, readdir as readdir9, realpath as realpath11, lstat as lstat11 } from "node:fs/promises";
77947
- import { join as join15, resolve as resolve20, relative as relative17, isAbsolute as isAbsolute14, basename as basename7 } from "node:path";
78684
+ import { readFile as readFile20, stat as stat5, mkdir as mkdir14, readdir as readdir9, realpath as realpath11, lstat as lstat11 } from "node:fs/promises";
78685
+ import { join as join16, resolve as resolve21, relative as relative18, isAbsolute as isAbsolute15, basename as basename7 } from "node:path";
77948
78686
  import { createHash as createHash10 } from "node:crypto";
77949
78687
  function transportPayload(entries) {
77950
78688
  return entries.map(({ path: path3, type, mode, size, contentDigest }) => ({
@@ -77974,13 +78712,16 @@ function extractDeclaredPluginSource(consumer, entry) {
77974
78712
  return segments.length === 0 ? "." : segments.join("/");
77975
78713
  }
77976
78714
  async function resolveInstalledPayloadSubpath(snapshotDir, sourceEntries, action, consumer) {
78715
+ if (action.payloadContract === PAYLOAD_CONTRACT_EXTERNAL_MARKETPLACE || action.marketplaceLocation === "external") {
78716
+ return ".";
78717
+ }
77977
78718
  const marketplaceRelative = getPlatform(consumer).manifestPaths.marketplace;
77978
78719
  if (marketplaceRelative === null) return ".";
77979
78720
  const anchored = sourceEntries.some((entry) => entry.type === "file" && entry.path === marketplaceRelative);
77980
78721
  if (!anchored) {
77981
78722
  throw new Error(`frozen snapshot is missing the marketplace manifest ${marketplaceRelative}`);
77982
78723
  }
77983
- const result = await validateManifestFile(resolve20(snapshotDir, marketplaceRelative), ["name", "plugins"]);
78724
+ const result = await validateManifestFile(resolve21(snapshotDir, marketplaceRelative), ["name", "plugins"]);
77984
78725
  if (!result.valid) {
77985
78726
  throw new Error(`frozen snapshot ${marketplaceRelative} invalid: ${result.error}`);
77986
78727
  }
@@ -78019,10 +78760,10 @@ async function verifyInstalledMarketplacePayload(action, context, installPath, c
78019
78760
  throw new Error("frozen snapshot contains no payload under the declared marketplace source");
78020
78761
  }
78021
78762
  const payloadContract = action.payloadContract;
78022
- if (payloadContract !== void 0 && payloadContract !== PAYLOAD_CONTRACT_DECLARED_MANIFEST) {
78763
+ if (payloadContract !== void 0 && payloadContract !== PAYLOAD_CONTRACT_DECLARED_MANIFEST && payloadContract !== PAYLOAD_CONTRACT_EXTERNAL_MARKETPLACE) {
78023
78764
  throw new Error(`unsupported marketplace payload contract: ${JSON.stringify(payloadContract)}`);
78024
78765
  }
78025
- if (payloadContract === PAYLOAD_CONTRACT_DECLARED_MANIFEST) {
78766
+ if (payloadContract === PAYLOAD_CONTRACT_DECLARED_MANIFEST || payloadContract === PAYLOAD_CONTRACT_EXTERNAL_MARKETPLACE) {
78026
78767
  const installedSnapshot2 = await computeFrozenSnapshot(installPath);
78027
78768
  const authorityPayload = transportPayload(authorityEntries);
78028
78769
  const installedByPath = new Map(
@@ -78047,7 +78788,7 @@ async function verifyInstalledMarketplacePayload(action, context, installPath, c
78047
78788
  const listed = conflicts.slice(0, PAYLOAD_CONFLICT_REPORT_CAP).join("; ");
78048
78789
  const overflow = conflicts.length > PAYLOAD_CONFLICT_REPORT_CAP ? `; and ${conflicts.length - PAYLOAD_CONFLICT_REPORT_CAP} more conflicting path(s)` : "";
78049
78790
  throw new Error(
78050
- `installed marketplace payload differs in path, bytes, size, or non-write mode bits (${PAYLOAD_CONTRACT_DECLARED_MANIFEST}): ${listed}${overflow}`
78791
+ `installed marketplace payload differs in path, bytes, size, or non-write mode bits (${payloadContract}): ${listed}${overflow}`
78051
78792
  );
78052
78793
  }
78053
78794
  const authorityPaths = new Set(authorityPayload.map((entry) => entry.path));
@@ -78094,26 +78835,26 @@ async function resolveKimiEntrySkillFile(pluginRootReal, manifest, entrySkill) {
78094
78835
  }
78095
78836
  let entryAbs;
78096
78837
  if (manifest.skills === void 0 || manifest.skills === null) {
78097
- entryAbs = resolve20(pluginRootReal, "SKILL.md");
78838
+ entryAbs = resolve21(pluginRootReal, "SKILL.md");
78098
78839
  } else {
78099
78840
  const skillsRel = normalizeKimiSkillsRel(manifest.skills);
78100
- const skillsRootAbs = skillsRel === "" ? pluginRootReal : resolve20(pluginRootReal, skillsRel);
78841
+ const skillsRootAbs = skillsRel === "" ? pluginRootReal : resolve21(pluginRootReal, skillsRel);
78101
78842
  const skillsRootReal = await realpath11(skillsRootAbs).catch(() => null);
78102
78843
  if (!skillsRootReal) {
78103
78844
  throw new Error(`kimi manifest skills root does not exist: ${manifest.skills}`);
78104
78845
  }
78105
- const skillsContainment = relative17(pluginRootReal, skillsRootReal);
78846
+ const skillsContainment = relative18(pluginRootReal, skillsRootReal);
78106
78847
  const sepK = process.platform === "win32" ? "\\" : "/";
78107
- if (skillsContainment !== "" && (isAbsolute14(skillsContainment) || skillsContainment === ".." || skillsContainment.startsWith(`..${sepK}`))) {
78848
+ if (skillsContainment !== "" && (isAbsolute15(skillsContainment) || skillsContainment === ".." || skillsContainment.startsWith(`..${sepK}`))) {
78108
78849
  throw new Error(`kimi manifest skills "${manifest.skills}" escapes the plugin root after symlink resolution`);
78109
78850
  }
78110
- entryAbs = resolve20(skillsRootReal, entrySkill, "SKILL.md");
78851
+ entryAbs = resolve21(skillsRootReal, entrySkill, "SKILL.md");
78111
78852
  }
78112
78853
  let entryLexicalStat;
78113
78854
  try {
78114
78855
  entryLexicalStat = await lstat11(entryAbs);
78115
78856
  } catch {
78116
- throw new Error(`kimi entry skill not found: ${relative17(pluginRootReal, entryAbs) || "SKILL.md"}`);
78857
+ throw new Error(`kimi entry skill not found: ${relative18(pluginRootReal, entryAbs) || "SKILL.md"}`);
78117
78858
  }
78118
78859
  if (entryLexicalStat.isSymbolicLink()) {
78119
78860
  throw new Error("kimi entry skill must not be a symlink");
@@ -78123,15 +78864,73 @@ async function resolveKimiEntrySkillFile(pluginRootReal, manifest, entrySkill) {
78123
78864
  }
78124
78865
  const entryReal = await realpath11(entryAbs).catch(() => null);
78125
78866
  if (!entryReal) {
78126
- throw new Error(`kimi entry skill not found: ${relative17(pluginRootReal, entryAbs) || "SKILL.md"}`);
78867
+ throw new Error(`kimi entry skill not found: ${relative18(pluginRootReal, entryAbs) || "SKILL.md"}`);
78127
78868
  }
78128
- const entryContainment = relative17(pluginRootReal, entryReal);
78869
+ const entryContainment = relative18(pluginRootReal, entryReal);
78129
78870
  const sepE = process.platform === "win32" ? "\\" : "/";
78130
- if (entryContainment !== "" && (isAbsolute14(entryContainment) || entryContainment === ".." || entryContainment.startsWith(`..${sepE}`))) {
78871
+ if (entryContainment !== "" && (isAbsolute15(entryContainment) || entryContainment === ".." || entryContainment.startsWith(`..${sepE}`))) {
78131
78872
  throw new Error("kimi entry skill escapes the plugin root after symlink resolution");
78132
78873
  }
78133
78874
  return entryReal;
78134
78875
  }
78876
+ function normalizeCodeBuddySkillsRel(skillsRaw) {
78877
+ if (typeof skillsRaw !== "string" || skillsRaw.length === 0) {
78878
+ throw new Error("codebuddy manifest skills must be a non-empty relative path when present");
78879
+ }
78880
+ if (skillsRaw.startsWith("/") || skillsRaw.includes("..") || skillsRaw.includes("\\") || /^https?:\/\//i.test(skillsRaw)) {
78881
+ throw new Error(`codebuddy manifest skills "${skillsRaw}" is not a safe relative path`);
78882
+ }
78883
+ let rel = skillsRaw.replace(/^\.\//, "");
78884
+ rel = rel.replace(/\/+$/, "");
78885
+ if (rel.split("/").some((segment) => segment === "" || segment === "." || segment === "..")) {
78886
+ throw new Error(`codebuddy manifest skills "${skillsRaw}" is not a safe relative path`);
78887
+ }
78888
+ return rel;
78889
+ }
78890
+ async function resolveCodeBuddyEntrySkillFile(pluginRootReal, manifest, entrySkill) {
78891
+ if (!entrySkill || typeof entrySkill !== "string" || !SAFE_ID_RE.test(entrySkill)) {
78892
+ throw new Error(`unsafe entrySkill: "${entrySkill}"`);
78893
+ }
78894
+ let entryAbs;
78895
+ if (manifest.skills === void 0 || manifest.skills === null) {
78896
+ entryAbs = resolve21(pluginRootReal, "SKILL.md");
78897
+ } else {
78898
+ const skillsRel = normalizeCodeBuddySkillsRel(manifest.skills);
78899
+ const skillsRootAbs = skillsRel === "" ? pluginRootReal : resolve21(pluginRootReal, skillsRel);
78900
+ const skillsRootReal = await realpath11(skillsRootAbs).catch(() => null);
78901
+ if (!skillsRootReal) {
78902
+ throw new Error(`codebuddy manifest skills root does not exist: ${manifest.skills}`);
78903
+ }
78904
+ const skillsContainment = relative18(pluginRootReal, skillsRootReal);
78905
+ const sepK = process.platform === "win32" ? "\\" : "/";
78906
+ if (skillsContainment !== "" && (isAbsolute15(skillsContainment) || skillsContainment === ".." || skillsContainment.startsWith(`..${sepK}`))) {
78907
+ throw new Error(`codebuddy manifest skills "${manifest.skills}" escapes the plugin root after symlink resolution`);
78908
+ }
78909
+ entryAbs = resolve21(skillsRootReal, entrySkill, "SKILL.md");
78910
+ }
78911
+ let entryLexicalStat;
78912
+ try {
78913
+ entryLexicalStat = await lstat11(entryAbs);
78914
+ } catch {
78915
+ throw new Error(`codebuddy entry skill not found: ${relative18(pluginRootReal, entryAbs) || "SKILL.md"}`);
78916
+ }
78917
+ if (entryLexicalStat.isSymbolicLink()) {
78918
+ throw new Error("codebuddy entry skill must not be a symlink");
78919
+ }
78920
+ if (!entryLexicalStat.isFile()) {
78921
+ throw new Error("codebuddy entry skill is not a regular file");
78922
+ }
78923
+ const entryReal = await realpath11(entryAbs).catch(() => null);
78924
+ if (!entryReal) {
78925
+ throw new Error(`codebuddy entry skill not found: ${relative18(pluginRootReal, entryAbs) || "SKILL.md"}`);
78926
+ }
78927
+ const entryContainment = relative18(pluginRootReal, entryReal);
78928
+ const sepE = process.platform === "win32" ? "\\" : "/";
78929
+ if (entryContainment !== "" && (isAbsolute15(entryContainment) || entryContainment === ".." || entryContainment.startsWith(`..${sepE}`))) {
78930
+ throw new Error("codebuddy entry skill escapes the plugin root after symlink resolution");
78931
+ }
78932
+ return entryReal;
78933
+ }
78135
78934
  function validateSafeRef(ref) {
78136
78935
  if (!ref || typeof ref !== "string") {
78137
78936
  return { valid: false, error: "ref is required" };
@@ -78213,7 +79012,7 @@ async function run4(cmd, args2, options = {}) {
78213
79012
  }
78214
79013
  async function validateManifestFile(manifestPath, requiredFields) {
78215
79014
  try {
78216
- const content = await readFile19(manifestPath, "utf8");
79015
+ const content = await readFile20(manifestPath, "utf8");
78217
79016
  const manifest = JSON.parse(content);
78218
79017
  const missing = requiredFields.filter((f) => !(f in manifest));
78219
79018
  return {
@@ -78235,7 +79034,7 @@ async function checkRequiredFiles(dir, requiredFiles) {
78235
79034
  const missing = [];
78236
79035
  for (const file of requiredFiles) {
78237
79036
  try {
78238
- await stat5(resolve20(dir, file));
79037
+ await stat5(resolve21(dir, file));
78239
79038
  } catch {
78240
79039
  missing.push(file);
78241
79040
  }
@@ -78311,7 +79110,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
78311
79110
  status: ActionStatus.PREFLIGHT_PASSED
78312
79111
  });
78313
79112
  }
78314
- if (actionType === ActionType.CLAUDE_MARKETPLACE_INSTALL || actionType === ActionType.CODEX_MARKETPLACE_INSTALL || actionType === ActionType.KIMI_MARKETPLACE_INSTALL) {
79113
+ if (actionType === ActionType.CLAUDE_MARKETPLACE_INSTALL || actionType === ActionType.CODEX_MARKETPLACE_INSTALL || actionType === ActionType.KIMI_MARKETPLACE_INSTALL || actionType === ActionType.CODEBUDDY_MARKETPLACE_INSTALL) {
78315
79114
  const validation = validateMarketplaceParams(action);
78316
79115
  if (!validation.valid) {
78317
79116
  return createResult({
@@ -78387,6 +79186,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
78387
79186
  });
78388
79187
  }
78389
79188
  if (!platform.automatable) {
79189
+ const manifestLabel = consumer === "codebuddy" ? "codebuddy" : "kimi";
78390
79190
  let kimiManifestResult;
78391
79191
  try {
78392
79192
  kimiManifestResult = await platform.strategy.readManifest(snapshotDirReal);
@@ -78394,7 +79194,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
78394
79194
  return createResult({
78395
79195
  actionType,
78396
79196
  status: ActionStatus.PREFLIGHT_FAILED,
78397
- error: `frozen snapshot kimi manifest invalid: ${manifestErr.message}`
79197
+ error: `frozen snapshot ${manifestLabel} manifest invalid: ${manifestErr.message}`
78398
79198
  });
78399
79199
  }
78400
79200
  const kimiManifest = kimiManifestResult.manifest;
@@ -78415,110 +79215,152 @@ function createPluginMarketplaceAdapter(deps = {}) {
78415
79215
  kimiSnapshotManifest = kimiManifest;
78416
79216
  }
78417
79217
  if (platform.automatable) {
78418
- const marketplaceRelative = platform.manifestPaths.marketplace;
78419
- const marketplacePath = resolve20(snapshotDirReal, marketplaceRelative);
78420
- const marketplaceResult = await validateManifestFile(marketplacePath, ["name"]);
78421
- if (!marketplaceResult.valid) {
78422
- return createResult({
78423
- actionType,
78424
- status: ActionStatus.PREFLIGHT_FAILED,
78425
- error: `frozen snapshot ${marketplaceRelative} invalid: ${marketplaceResult.error}`
78426
- });
78427
- }
78428
- if (marketplaceResult.manifest.name !== action.marketplace) {
78429
- return createResult({
78430
- actionType,
78431
- status: ActionStatus.PREFLIGHT_FAILED,
78432
- error: `marketplace.json name "${marketplaceResult.manifest.name}" does not match action marketplace "${action.marketplace}"`
78433
- });
78434
- }
78435
- const plugins = marketplaceResult.manifest.plugins;
78436
- if (!Array.isArray(plugins)) {
78437
- return createResult({
78438
- actionType,
78439
- status: ActionStatus.PREFLIGHT_FAILED,
78440
- error: `${marketplaceRelative} must have a plugins[] array`
78441
- });
78442
- }
78443
- const pluginEntry = plugins.filter((p) => p.name === action.plugin);
78444
- if (pluginEntry.length !== 1) {
78445
- return createResult({
78446
- actionType,
78447
- status: ActionStatus.PREFLIGHT_FAILED,
78448
- error: `expected exactly one plugins[] entry with name "${action.plugin}", found ${pluginEntry.length}`
78449
- });
78450
- }
78451
- const entry = pluginEntry[0];
78452
- let sourcePath;
78453
- try {
78454
- sourcePath = extractDeclaredPluginSource(consumer, entry);
78455
- } catch (sourceErr) {
78456
- return createResult({
78457
- actionType,
78458
- status: ActionStatus.PREFLIGHT_FAILED,
78459
- error: sourceErr.message
78460
- });
78461
- }
78462
- const sourceDirAbs = resolve20(snapshotDirReal, sourcePath);
78463
- const sourceDirReal = await realpath11(sourceDirAbs).catch(() => null);
78464
- if (!sourceDirReal) {
78465
- return createResult({
78466
- actionType,
78467
- status: ActionStatus.PREFLIGHT_FAILED,
78468
- error: `marketplace plugin entry source directory does not exist: ${sourcePath}`
78469
- });
78470
- }
78471
- const sourceRelCheck = relative17(snapshotDirReal, sourceDirReal);
78472
- if (sourceRelCheck.startsWith("..") || isAbsolute14(sourceRelCheck)) {
78473
- return createResult({
78474
- actionType,
78475
- status: ActionStatus.PREFLIGHT_FAILED,
78476
- error: `marketplace plugin entry source "${sourcePath}" escapes the frozen snapshot`
78477
- });
78478
- }
78479
- const manifestRelative = join15(sourcePath, platform.manifestPaths.plugin);
78480
- const manifestPath = resolve20(snapshotDirReal, manifestRelative);
78481
- const manifestResult = await validateManifestFile(manifestPath, ["name", "version"]);
78482
- if (!manifestResult.valid) {
78483
- return createResult({
78484
- actionType,
78485
- status: ActionStatus.PREFLIGHT_FAILED,
78486
- error: `frozen snapshot ${manifestRelative} invalid: ${manifestResult.error}`
78487
- });
78488
- }
78489
- if (platform.marketplaceEntryCarriesVersion && entry.version !== action.version) {
78490
- return createResult({
78491
- actionType,
78492
- status: ActionStatus.PREFLIGHT_FAILED,
78493
- error: `marketplace plugin entry version "${entry.version}" does not match action version "${action.version}"`
78494
- });
78495
- }
78496
- const pluginManifestResult = await validateManifestFile(manifestPath, ["name", "version"]);
78497
- if (!pluginManifestResult.valid) {
78498
- return createResult({
78499
- actionType,
78500
- status: ActionStatus.PREFLIGHT_FAILED,
78501
- error: `frozen snapshot ${manifestRelative} invalid: ${pluginManifestResult.error}`
78502
- });
78503
- }
78504
- if (pluginManifestResult.manifest.name !== entry.name) {
78505
- return createResult({
78506
- actionType,
78507
- status: ActionStatus.PREFLIGHT_FAILED,
78508
- error: `plugin manifest name "${pluginManifestResult.manifest.name}" does not match marketplace entry name "${entry.name}"`
78509
- });
78510
- }
78511
- if (pluginManifestResult.manifest.version !== action.version) {
78512
- return createResult({
78513
- actionType,
78514
- status: ActionStatus.PREFLIGHT_FAILED,
78515
- error: `plugin manifest version "${pluginManifestResult.manifest.version}" does not match action version "${action.version}"`
78516
- });
79218
+ if (action.marketplaceLocation === "external") {
79219
+ if (typeof action.marketplaceCommitSha !== "string" || !/^[0-9a-f]{40}$/.test(action.marketplaceCommitSha)) {
79220
+ return createResult({
79221
+ actionType,
79222
+ status: ActionStatus.PREFLIGHT_FAILED,
79223
+ error: `external marketplace marketplaceCommitSha must be a 40-hex commit sha, got ${JSON.stringify(action.marketplaceCommitSha)}`
79224
+ });
79225
+ }
79226
+ if (typeof action.repo !== "string" || !/^[a-z0-9][a-z0-9._-]*\/[a-z0-9][a-z0-9._-]*$/.test(action.repo)) {
79227
+ return createResult({
79228
+ actionType,
79229
+ status: ActionStatus.PREFLIGHT_FAILED,
79230
+ error: `external marketplace repo must be an owner/name repository, got ${JSON.stringify(action.repo)}`
79231
+ });
79232
+ }
79233
+ const externalManifestRelative = platform.manifestPaths.plugin;
79234
+ const externalManifestPath = resolve21(snapshotDirReal, externalManifestRelative);
79235
+ const externalManifestResult = await validateManifestFile(externalManifestPath, ["name", "version"]);
79236
+ if (!externalManifestResult.valid) {
79237
+ return createResult({
79238
+ actionType,
79239
+ status: ActionStatus.PREFLIGHT_FAILED,
79240
+ error: `frozen snapshot ${externalManifestRelative} invalid: ${externalManifestResult.error}`
79241
+ });
79242
+ }
79243
+ if (externalManifestResult.manifest.name !== action.plugin) {
79244
+ return createResult({
79245
+ actionType,
79246
+ status: ActionStatus.PREFLIGHT_FAILED,
79247
+ error: `plugin manifest name "${externalManifestResult.manifest.name}" does not match action plugin "${action.plugin}"`
79248
+ });
79249
+ }
79250
+ if (externalManifestResult.manifest.version !== action.version) {
79251
+ return createResult({
79252
+ actionType,
79253
+ status: ActionStatus.PREFLIGHT_FAILED,
79254
+ error: `plugin manifest version "${externalManifestResult.manifest.version}" does not match action version "${action.version}"`
79255
+ });
79256
+ }
79257
+ } else {
79258
+ const marketplaceRelative = platform.manifestPaths.marketplace;
79259
+ const marketplacePath = resolve21(snapshotDirReal, marketplaceRelative);
79260
+ const marketplaceResult = await validateManifestFile(marketplacePath, ["name"]);
79261
+ if (!marketplaceResult.valid) {
79262
+ return createResult({
79263
+ actionType,
79264
+ status: ActionStatus.PREFLIGHT_FAILED,
79265
+ error: `frozen snapshot ${marketplaceRelative} invalid: ${marketplaceResult.error}`
79266
+ });
79267
+ }
79268
+ if (marketplaceResult.manifest.name !== action.marketplace) {
79269
+ return createResult({
79270
+ actionType,
79271
+ status: ActionStatus.PREFLIGHT_FAILED,
79272
+ error: `marketplace.json name "${marketplaceResult.manifest.name}" does not match action marketplace "${action.marketplace}"`
79273
+ });
79274
+ }
79275
+ const plugins = marketplaceResult.manifest.plugins;
79276
+ if (!Array.isArray(plugins)) {
79277
+ return createResult({
79278
+ actionType,
79279
+ status: ActionStatus.PREFLIGHT_FAILED,
79280
+ error: `${marketplaceRelative} must have a plugins[] array`
79281
+ });
79282
+ }
79283
+ const pluginEntry = plugins.filter((p) => p.name === action.plugin);
79284
+ if (pluginEntry.length !== 1) {
79285
+ return createResult({
79286
+ actionType,
79287
+ status: ActionStatus.PREFLIGHT_FAILED,
79288
+ error: `expected exactly one plugins[] entry with name "${action.plugin}", found ${pluginEntry.length}`
79289
+ });
79290
+ }
79291
+ const entry = pluginEntry[0];
79292
+ let sourcePath;
79293
+ try {
79294
+ sourcePath = extractDeclaredPluginSource(consumer, entry);
79295
+ } catch (sourceErr) {
79296
+ return createResult({
79297
+ actionType,
79298
+ status: ActionStatus.PREFLIGHT_FAILED,
79299
+ error: sourceErr.message
79300
+ });
79301
+ }
79302
+ const sourceDirAbs = resolve21(snapshotDirReal, sourcePath);
79303
+ const sourceDirReal = await realpath11(sourceDirAbs).catch(() => null);
79304
+ if (!sourceDirReal) {
79305
+ return createResult({
79306
+ actionType,
79307
+ status: ActionStatus.PREFLIGHT_FAILED,
79308
+ error: `marketplace plugin entry source directory does not exist: ${sourcePath}`
79309
+ });
79310
+ }
79311
+ const sourceRelCheck = relative18(snapshotDirReal, sourceDirReal);
79312
+ if (sourceRelCheck.startsWith("..") || isAbsolute15(sourceRelCheck)) {
79313
+ return createResult({
79314
+ actionType,
79315
+ status: ActionStatus.PREFLIGHT_FAILED,
79316
+ error: `marketplace plugin entry source "${sourcePath}" escapes the frozen snapshot`
79317
+ });
79318
+ }
79319
+ const manifestRelative = join16(sourcePath, platform.manifestPaths.plugin);
79320
+ const manifestPath = resolve21(snapshotDirReal, manifestRelative);
79321
+ const manifestResult = await validateManifestFile(manifestPath, ["name", "version"]);
79322
+ if (!manifestResult.valid) {
79323
+ return createResult({
79324
+ actionType,
79325
+ status: ActionStatus.PREFLIGHT_FAILED,
79326
+ error: `frozen snapshot ${manifestRelative} invalid: ${manifestResult.error}`
79327
+ });
79328
+ }
79329
+ if (platform.marketplaceEntryCarriesVersion && entry.version !== action.version) {
79330
+ return createResult({
79331
+ actionType,
79332
+ status: ActionStatus.PREFLIGHT_FAILED,
79333
+ error: `marketplace plugin entry version "${entry.version}" does not match action version "${action.version}"`
79334
+ });
79335
+ }
79336
+ const pluginManifestResult = await validateManifestFile(manifestPath, ["name", "version"]);
79337
+ if (!pluginManifestResult.valid) {
79338
+ return createResult({
79339
+ actionType,
79340
+ status: ActionStatus.PREFLIGHT_FAILED,
79341
+ error: `frozen snapshot ${manifestRelative} invalid: ${pluginManifestResult.error}`
79342
+ });
79343
+ }
79344
+ if (pluginManifestResult.manifest.name !== entry.name) {
79345
+ return createResult({
79346
+ actionType,
79347
+ status: ActionStatus.PREFLIGHT_FAILED,
79348
+ error: `plugin manifest name "${pluginManifestResult.manifest.name}" does not match marketplace entry name "${entry.name}"`
79349
+ });
79350
+ }
79351
+ if (pluginManifestResult.manifest.version !== action.version) {
79352
+ return createResult({
79353
+ actionType,
79354
+ status: ActionStatus.PREFLIGHT_FAILED,
79355
+ error: `plugin manifest version "${pluginManifestResult.manifest.version}" does not match action version "${action.version}"`
79356
+ });
79357
+ }
78517
79358
  }
78518
79359
  }
78519
79360
  if (!platform.automatable) {
79361
+ const resolveEntrySkillFile = consumer === "codebuddy" ? resolveCodeBuddyEntrySkillFile : resolveKimiEntrySkillFile;
78520
79362
  try {
78521
- await resolveKimiEntrySkillFile(snapshotDirReal, kimiSnapshotManifest, action.entrySkill);
79363
+ await resolveEntrySkillFile(snapshotDirReal, kimiSnapshotManifest, action.entrySkill);
78522
79364
  } catch (entryErr) {
78523
79365
  return createResult({
78524
79366
  actionType,
@@ -78527,7 +79369,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
78527
79369
  });
78528
79370
  }
78529
79371
  } else {
78530
- const entrySkillFile = resolve20(snapshotDirReal, "skills", action.entrySkill, "SKILL.md");
79372
+ const entrySkillFile = resolve21(snapshotDirReal, "skills", action.entrySkill, "SKILL.md");
78531
79373
  try {
78532
79374
  await stat5(entrySkillFile);
78533
79375
  } catch {
@@ -78634,7 +79476,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
78634
79476
  }
78635
79477
  if (action.entryPoint) {
78636
79478
  try {
78637
- await exec(process.execPath, ["--check", resolve20(pluginDir, action.entryPoint)]);
79479
+ await exec(process.execPath, ["--check", resolve21(pluginDir, action.entryPoint)]);
78638
79480
  } catch (checkErr) {
78639
79481
  return createResult({
78640
79482
  actionType,
@@ -78660,7 +79502,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
78660
79502
  });
78661
79503
  }
78662
79504
  }
78663
- if (actionType === ActionType.CLAUDE_MARKETPLACE_INSTALL || actionType === ActionType.CODEX_MARKETPLACE_INSTALL || actionType === ActionType.KIMI_MARKETPLACE_INSTALL) {
79505
+ if (actionType === ActionType.CLAUDE_MARKETPLACE_INSTALL || actionType === ActionType.CODEX_MARKETPLACE_INSTALL || actionType === ActionType.KIMI_MARKETPLACE_INSTALL || actionType === ActionType.CODEBUDDY_MARKETPLACE_INSTALL) {
78664
79506
  try {
78665
79507
  assertIsolatedConsumerWritesAuthorized(context, actionType);
78666
79508
  const validation = validateMarketplaceParams(action);
@@ -78691,21 +79533,21 @@ function createPluginMarketplaceAdapter(deps = {}) {
78691
79533
  }
78692
79534
  const consumer = action.consumer;
78693
79535
  const runDir = context.runDir;
78694
- const isolatedHome = resolve20(runDir, "consumers", `${consumer}-${action.plugin}`);
79536
+ const isolatedHome = resolve21(runDir, "consumers", `${consumer}-${action.plugin}`);
78695
79537
  const runDirReal = await realpath11(runDir).catch(() => runDir);
78696
79538
  const isolatedHomePreReal = await realpath11(isolatedHome).catch(() => isolatedHome);
78697
- const relToRun = relative17(runDirReal, isolatedHomePreReal);
79539
+ const relToRun = relative18(runDirReal, isolatedHomePreReal);
78698
79540
  const sepE = process.platform === "win32" ? "\\" : "/";
78699
- if (relToRun !== "" && (isAbsolute14(relToRun) || relToRun === ".." || relToRun.startsWith(`..${sepE}`))) {
79541
+ if (relToRun !== "" && (isAbsolute15(relToRun) || relToRun === ".." || relToRun.startsWith(`..${sepE}`))) {
78700
79542
  return createResult({
78701
79543
  actionType,
78702
79544
  status: ActionStatus.EXECUTE_FAILED,
78703
79545
  error: `consumer directory escapes runDir: ${isolatedHome}`
78704
79546
  });
78705
79547
  }
78706
- await mkdir13(isolatedHome, { recursive: true, mode: 448 });
79548
+ await mkdir14(isolatedHome, { recursive: true, mode: 448 });
78707
79549
  for (const subdir of platform.isolationSubdirs) {
78708
- await mkdir13(resolve20(isolatedHome, subdir), { recursive: true, mode: 448 });
79550
+ await mkdir14(resolve21(isolatedHome, subdir), { recursive: true, mode: 448 });
78709
79551
  }
78710
79552
  const cliCmd = platform.cli.binary;
78711
79553
  const baseEnv = { ...process.env, ...context.env };
@@ -78799,9 +79641,9 @@ function createPluginMarketplaceAdapter(deps = {}) {
78799
79641
  error: `plugin install JSON missing installedPath`
78800
79642
  });
78801
79643
  }
78802
- const installPathAbs = resolve20(installFields.installedPath);
78803
- const installPathRel = relative17(isolatedHome, installPathAbs);
78804
- if (isAbsolute14(installPathRel) || installPathRel === ".." || installPathRel.startsWith(`..${sepE}`)) {
79644
+ const installPathAbs = resolve21(installFields.installedPath);
79645
+ const installPathRel = relative18(isolatedHome, installPathAbs);
79646
+ if (isAbsolute15(installPathRel) || installPathRel === ".." || installPathRel.startsWith(`..${sepE}`)) {
78805
79647
  return createResult({
78806
79648
  actionType,
78807
79649
  status: ActionStatus.EXECUTE_FAILED,
@@ -78859,9 +79701,9 @@ function createPluginMarketplaceAdapter(deps = {}) {
78859
79701
  executedAt: (/* @__PURE__ */ new Date()).toISOString(),
78860
79702
  ...extraInstalledPathsAudit(executeBinding)
78861
79703
  };
78862
- const evidenceDir = resolve20(runDir, "evidence", `${consumer}-${action.plugin}`);
78863
- await mkdir13(evidenceDir, { recursive: true, mode: 448 });
78864
- const evidencePath = resolve20(evidenceDir, "release-skill-install-evidence.json");
79704
+ const evidenceDir = resolve21(runDir, "evidence", `${consumer}-${action.plugin}`);
79705
+ await mkdir14(evidenceDir, { recursive: true, mode: 448 });
79706
+ const evidencePath = resolve21(evidenceDir, "release-skill-install-evidence.json");
78865
79707
  await writeEvidenceAtomic(evidencePath, evidence);
78866
79708
  const executeObservation = {
78867
79709
  ...evidence,
@@ -78910,7 +79752,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
78910
79752
  if (actionType === ActionType.PLUGIN_MANIFEST_VALIDATE) {
78911
79753
  const manifestPath = action.manifestPath;
78912
79754
  try {
78913
- const content = await readFile19(manifestPath, "utf8");
79755
+ const content = await readFile20(manifestPath, "utf8");
78914
79756
  const manifest = JSON.parse(content);
78915
79757
  return createResult({
78916
79758
  actionType,
@@ -78943,7 +79785,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
78943
79785
  }
78944
79786
  });
78945
79787
  }
78946
- if (actionType === ActionType.CLAUDE_MARKETPLACE_INSTALL || actionType === ActionType.CODEX_MARKETPLACE_INSTALL || actionType === ActionType.KIMI_MARKETPLACE_INSTALL) {
79788
+ if (actionType === ActionType.CLAUDE_MARKETPLACE_INSTALL || actionType === ActionType.CODEX_MARKETPLACE_INSTALL || actionType === ActionType.KIMI_MARKETPLACE_INSTALL || actionType === ActionType.CODEBUDDY_MARKETPLACE_INSTALL) {
78947
79789
  const consumer = action.consumer;
78948
79790
  const runDir = context.runDir;
78949
79791
  if (!runDir) {
@@ -78953,7 +79795,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
78953
79795
  observation: { installed: false, error: "context.runDir is required" }
78954
79796
  });
78955
79797
  }
78956
- const isolatedHome = resolve20(runDir, "consumers", `${consumer}-${action.plugin}`);
79798
+ const isolatedHome = resolve21(runDir, "consumers", `${consumer}-${action.plugin}`);
78957
79799
  const platform = PLATFORMS.find((p) => p.id === consumer) ?? null;
78958
79800
  const cliCmd = platform ? platform.cli ? platform.cli.binary : null : "kimi";
78959
79801
  const baseEnv = { ...process.env, ...context.env ?? {} };
@@ -78972,7 +79814,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
78972
79814
  error: timeoutErr.message
78973
79815
  });
78974
79816
  }
78975
- if (platform && !platform.automatable) {
79817
+ if (platform && !platform.automatable && actionType === ActionType.KIMI_MARKETPLACE_INSTALL) {
78976
79818
  const expectedRef = action.ref ?? `v${action.version}`;
78977
79819
  let boundPlanDigest;
78978
79820
  try {
@@ -78999,7 +79841,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
78999
79841
  }
79000
79842
  let requirement = null;
79001
79843
  try {
79002
- requirement = JSON.parse(await readFile19(resolve20(attestationDir, KIMI_REQUIREMENT_FILE), "utf8"));
79844
+ requirement = JSON.parse(await readFile20(resolve21(attestationDir, KIMI_REQUIREMENT_FILE), "utf8"));
79003
79845
  } catch {
79004
79846
  return createResult({
79005
79847
  actionType,
@@ -79023,7 +79865,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
79023
79865
  }
79024
79866
  let attestation = null;
79025
79867
  try {
79026
- attestation = JSON.parse(await readFile19(resolve20(attestationDir, KIMI_ATTESTATION_FILE), "utf8"));
79868
+ attestation = JSON.parse(await readFile20(resolve21(attestationDir, KIMI_ATTESTATION_FILE), "utf8"));
79027
79869
  } catch {
79028
79870
  return createResult({
79029
79871
  actionType,
@@ -79033,7 +79875,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
79033
79875
  manualInstallRequired: true,
79034
79876
  installUrl: requirement.installUrl,
79035
79877
  attestationDir,
79036
- error: `kimi attestation is missing; write ${resolve20(attestationDir, KIMI_ATTESTATION_FILE)} after the interactive install (${requirement.installUrl})`
79878
+ error: `kimi attestation is missing; write ${resolve21(attestationDir, KIMI_ATTESTATION_FILE)} after the interactive install (${requirement.installUrl})`
79037
79879
  }
79038
79880
  });
79039
79881
  }
@@ -79045,7 +79887,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
79045
79887
  observation: { installed: false, error: attestationCheck.error }
79046
79888
  });
79047
79889
  }
79048
- const kimiCodeHome = resolve20(attestationDir, "kimi-home");
79890
+ const kimiCodeHome = resolve21(attestationDir, "kimi-home");
79049
79891
  const kimiCodeHomeReal = await realpath11(kimiCodeHome).catch(() => null);
79050
79892
  if (!kimiCodeHomeReal) {
79051
79893
  return createResult({
@@ -79057,18 +79899,18 @@ function createPluginMarketplaceAdapter(deps = {}) {
79057
79899
  }
79058
79900
  });
79059
79901
  }
79060
- const managedRootReal = await realpath11(resolve20(kimiCodeHomeReal, KIMI_MANAGED_SUBPATH, action.plugin)).catch(() => null);
79902
+ const managedRootReal = await realpath11(resolve21(kimiCodeHomeReal, KIMI_MANAGED_SUBPATH, action.plugin)).catch(() => null);
79061
79903
  if (!managedRootReal) {
79062
79904
  return createResult({
79063
79905
  actionType,
79064
79906
  status: ActionStatus.OBSERVED,
79065
79907
  observation: {
79066
79908
  installed: false,
79067
- error: `kimi managed plugin root does not exist: ${resolve20(kimiCodeHomeReal, KIMI_MANAGED_SUBPATH, action.plugin)}`
79909
+ error: `kimi managed plugin root does not exist: ${resolve21(kimiCodeHomeReal, KIMI_MANAGED_SUBPATH, action.plugin)}`
79068
79910
  }
79069
79911
  });
79070
79912
  }
79071
- const installPath2 = resolve20(attestation.installPath);
79913
+ const installPath2 = resolve21(attestation.installPath);
79072
79914
  let installPathStat;
79073
79915
  try {
79074
79916
  installPathStat = await lstat11(installPath2);
@@ -79102,8 +79944,8 @@ function createPluginMarketplaceAdapter(deps = {}) {
79102
79944
  });
79103
79945
  }
79104
79946
  const sepK = process.platform === "win32" ? "\\" : "/";
79105
- const relToManaged = relative17(managedRootReal, installPathReal2);
79106
- if (relToManaged !== "" && (isAbsolute14(relToManaged) || relToManaged === ".." || relToManaged.startsWith(`..${sepK}`))) {
79947
+ const relToManaged = relative18(managedRootReal, installPathReal2);
79948
+ if (relToManaged !== "" && (isAbsolute15(relToManaged) || relToManaged === ".." || relToManaged.startsWith(`..${sepK}`))) {
79107
79949
  return createResult({
79108
79950
  actionType,
79109
79951
  status: ActionStatus.OBSERVED,
@@ -79205,9 +80047,245 @@ function createPluginMarketplaceAdapter(deps = {}) {
79205
80047
  observation: observation2
79206
80048
  });
79207
80049
  }
80050
+ if (platform && !platform.automatable && actionType === ActionType.CODEBUDDY_MARKETPLACE_INSTALL) {
80051
+ const expectedRef = action.ref ?? `v${action.version}`;
80052
+ let boundPlanDigest;
80053
+ try {
80054
+ boundPlanDigest = await resolveCodeBuddyBoundPlanDigest(context);
80055
+ } catch (planErr) {
80056
+ return createResult({
80057
+ actionType,
80058
+ status: ActionStatus.OBSERVED,
80059
+ observation: {
80060
+ installed: false,
80061
+ error: `cannot bind codebuddy observation to the frozen plan: ${planErr.message}`
80062
+ }
80063
+ });
80064
+ }
80065
+ let attestationDir;
80066
+ try {
80067
+ attestationDir = codebuddyAuthorityDir(context, boundPlanDigest, action.plugin);
80068
+ } catch (dirErr) {
80069
+ return createResult({
80070
+ actionType,
80071
+ status: ActionStatus.OBSERVED,
80072
+ observation: { installed: false, error: dirErr.message }
80073
+ });
80074
+ }
80075
+ let requirement = null;
80076
+ try {
80077
+ requirement = JSON.parse(await readFile20(resolve21(attestationDir, CODEBUDDY_REQUIREMENT_FILE), "utf8"));
80078
+ } catch {
80079
+ return createResult({
80080
+ actionType,
80081
+ status: ActionStatus.OBSERVED,
80082
+ observation: {
80083
+ installed: false,
80084
+ manualInstallRequired: true,
80085
+ error: "codebuddy manual-install requirement is missing; run execute first"
80086
+ }
80087
+ });
80088
+ }
80089
+ if (requirement.planDigest !== boundPlanDigest || requirement.plugin !== action.plugin || requirement.version !== action.version || requirement.entrySkill !== action.entrySkill || requirement.repo !== action.repo || requirement.ref !== expectedRef) {
80090
+ return createResult({
80091
+ actionType,
80092
+ status: ActionStatus.OBSERVED,
80093
+ observation: {
80094
+ installed: false,
80095
+ error: "codebuddy manual-install requirement does not match the frozen plan/action"
80096
+ }
80097
+ });
80098
+ }
80099
+ let attestation = null;
80100
+ try {
80101
+ attestation = JSON.parse(await readFile20(resolve21(attestationDir, CODEBUDDY_ATTESTATION_FILE), "utf8"));
80102
+ } catch {
80103
+ return createResult({
80104
+ actionType,
80105
+ status: ActionStatus.OBSERVED,
80106
+ observation: {
80107
+ installed: false,
80108
+ manualInstallRequired: true,
80109
+ marketplaceSource: CODEBUDDY_MARKETPLACE_SOURCE,
80110
+ attestationDir,
80111
+ error: `codebuddy attestation is missing; write ${resolve21(attestationDir, CODEBUDDY_ATTESTATION_FILE)} after the manual install (marketplace ${CODEBUDDY_MARKETPLACE_SOURCE})`
80112
+ }
80113
+ });
80114
+ }
80115
+ const attestationCheck = validateCodeBuddyAttestation(attestation, action, (/* @__PURE__ */ new Date()).toISOString(), boundPlanDigest);
80116
+ if (!attestationCheck.valid) {
80117
+ return createResult({
80118
+ actionType,
80119
+ status: ActionStatus.OBSERVED,
80120
+ observation: { installed: false, error: attestationCheck.error }
80121
+ });
80122
+ }
80123
+ const installPath2 = resolve21(attestation.installPath);
80124
+ let installPathStat;
80125
+ try {
80126
+ installPathStat = await lstat11(installPath2);
80127
+ } catch {
80128
+ return createResult({
80129
+ actionType,
80130
+ status: ActionStatus.OBSERVED,
80131
+ observation: { installed: false, error: `codebuddy install path does not exist: ${attestation.installPath}` }
80132
+ });
80133
+ }
80134
+ if (installPathStat.isSymbolicLink()) {
80135
+ return createResult({
80136
+ actionType,
80137
+ status: ActionStatus.OBSERVED,
80138
+ observation: { installed: false, error: `codebuddy install path must not be a symlink: ${attestation.installPath}` }
80139
+ });
80140
+ }
80141
+ if (!installPathStat.isDirectory()) {
80142
+ return createResult({
80143
+ actionType,
80144
+ status: ActionStatus.OBSERVED,
80145
+ observation: { installed: false, error: `codebuddy install path must be a directory: ${attestation.installPath}` }
80146
+ });
80147
+ }
80148
+ const installPathReal2 = await realpath11(installPath2).catch(() => null);
80149
+ if (!installPathReal2) {
80150
+ return createResult({
80151
+ actionType,
80152
+ status: ActionStatus.OBSERVED,
80153
+ observation: { installed: false, error: `codebuddy install path cannot be resolved: ${attestation.installPath}` }
80154
+ });
80155
+ }
80156
+ if (attestation.installChannel === "cli") {
80157
+ const cliHome = codebuddyCliHome(attestationDir);
80158
+ const cliHomeReal = await realpath11(cliHome).catch(() => null);
80159
+ if (!cliHomeReal) {
80160
+ return createResult({
80161
+ actionType,
80162
+ status: ActionStatus.OBSERVED,
80163
+ observation: {
80164
+ installed: false,
80165
+ error: `codebuddy isolated CLI home does not exist or cannot be resolved: ${cliHome}`
80166
+ }
80167
+ });
80168
+ }
80169
+ const cliRootAbs = codebuddyCliInstallRoot(cliHomeReal, attestation.marketplace, action.plugin);
80170
+ const cliRootReal = await realpath11(cliRootAbs).catch(() => null);
80171
+ if (!cliRootReal) {
80172
+ return createResult({
80173
+ actionType,
80174
+ status: ActionStatus.OBSERVED,
80175
+ observation: {
80176
+ installed: false,
80177
+ error: `codebuddy CLI marketplace plugin root does not exist: ${cliRootAbs}`
80178
+ }
80179
+ });
80180
+ }
80181
+ const sepC = process.platform === "win32" ? "\\" : "/";
80182
+ const relToRoot = relative18(cliRootReal, installPathReal2);
80183
+ if (relToRoot !== "" && (isAbsolute15(relToRoot) || relToRoot === ".." || relToRoot.startsWith(`..${sepC}`))) {
80184
+ return createResult({
80185
+ actionType,
80186
+ status: ActionStatus.OBSERVED,
80187
+ observation: {
80188
+ installed: false,
80189
+ error: `codebuddy install path escapes the isolated CLI marketplace root (${cliRootReal}): ${attestation.installPath}`
80190
+ }
80191
+ });
80192
+ }
80193
+ }
80194
+ let manifestDigest2;
80195
+ let payloadBinding2 = null;
80196
+ try {
80197
+ payloadBinding2 = await verifyInstalledMarketplacePayload(action, context, installPathReal2, consumer);
80198
+ manifestDigest2 = payloadBinding2.manifestDigest;
80199
+ } catch (digestErr) {
80200
+ return createResult({
80201
+ actionType,
80202
+ status: ActionStatus.OBSERVED,
80203
+ observation: {
80204
+ installed: true,
80205
+ installPath: installPathReal2,
80206
+ error: `failed to bind installed codebuddy payload to frozen authority: ${digestErr.message}`
80207
+ }
80208
+ });
80209
+ }
80210
+ if (manifestDigest2 !== action.manifestDigest) {
80211
+ return createResult({
80212
+ actionType,
80213
+ status: ActionStatus.OBSERVED,
80214
+ observation: {
80215
+ installed: true,
80216
+ installPath: installPathReal2,
80217
+ error: "installed codebuddy payload digest does not match the frozen plan digest"
80218
+ }
80219
+ });
80220
+ }
80221
+ let installedManifest;
80222
+ try {
80223
+ const readManifest = await platform.strategy.readManifest(installPathReal2);
80224
+ installedManifest = readManifest.manifest;
80225
+ await resolveCodeBuddyEntrySkillFile(installPathReal2, installedManifest, action.entrySkill);
80226
+ } catch (entryErr) {
80227
+ return createResult({
80228
+ actionType,
80229
+ status: ActionStatus.OBSERVED,
80230
+ observation: {
80231
+ installed: true,
80232
+ installPath: installPathReal2,
80233
+ manifestDigest: manifestDigest2,
80234
+ entrySkillFound: false,
80235
+ error: `codebuddy entry skill not resolvable in installed copy: ${entryErr.message}`
80236
+ }
80237
+ });
80238
+ }
80239
+ if (installedManifest.name !== action.plugin) {
80240
+ return createResult({
80241
+ actionType,
80242
+ status: ActionStatus.OBSERVED,
80243
+ observation: {
80244
+ installed: true,
80245
+ installPath: installPathReal2,
80246
+ manifestDigest: manifestDigest2,
80247
+ entrySkillFound: true,
80248
+ error: `installed codebuddy manifest name "${installedManifest.name}" does not match action plugin "${action.plugin}"`
80249
+ }
80250
+ });
80251
+ }
80252
+ if (installedManifest.version !== action.version) {
80253
+ return createResult({
80254
+ actionType,
80255
+ status: ActionStatus.OBSERVED,
80256
+ observation: {
80257
+ installed: true,
80258
+ installPath: installPathReal2,
80259
+ manifestDigest: manifestDigest2,
80260
+ entrySkillFound: true,
80261
+ error: `installed codebuddy manifest version "${installedManifest.version}" does not match action version "${action.version}"`
80262
+ }
80263
+ });
80264
+ }
80265
+ const observation2 = {
80266
+ installed: true,
80267
+ installPath: installPathReal2,
80268
+ entrySkillFound: true,
80269
+ entrySkill: action.entrySkill,
80270
+ manifestDigest: manifestDigest2,
80271
+ consumer,
80272
+ plugin: installedManifest.name,
80273
+ version: installedManifest.version,
80274
+ repo: action.repo,
80275
+ ref: expectedRef,
80276
+ marketplace: attestation.marketplace,
80277
+ installChannel: attestation.installChannel,
80278
+ ...extraInstalledPathsAudit(payloadBinding2)
80279
+ };
80280
+ return createResult({
80281
+ actionType,
80282
+ status: ActionStatus.OBSERVED,
80283
+ observation: observation2
80284
+ });
80285
+ }
79208
80286
  let evidence = null;
79209
80287
  try {
79210
- const evidenceRaw = await readFile19(resolve20(runDir, "evidence", `${consumer}-${action.plugin}`, "release-skill-install-evidence.json"), "utf8");
80288
+ const evidenceRaw = await readFile20(resolve21(runDir, "evidence", `${consumer}-${action.plugin}`, "release-skill-install-evidence.json"), "utf8");
79211
80289
  evidence = JSON.parse(evidenceRaw);
79212
80290
  } catch {
79213
80291
  return createResult({
@@ -79292,9 +80370,9 @@ function createPluginMarketplaceAdapter(deps = {}) {
79292
80370
  }
79293
80371
  const isolatedHomeReal = await realpath11(isolatedHome).catch(() => isolatedHome);
79294
80372
  const installPathReal = await realpath11(installPath).catch(() => installPath);
79295
- const relToHome = relative17(isolatedHomeReal, installPathReal);
80373
+ const relToHome = relative18(isolatedHomeReal, installPathReal);
79296
80374
  const sep4 = process.platform === "win32" ? "\\" : "/";
79297
- if (relToHome !== "" && (isAbsolute14(relToHome) || relToHome === ".." || relToHome.startsWith(`..${sep4}`))) {
80375
+ if (relToHome !== "" && (isAbsolute15(relToHome) || relToHome === ".." || relToHome.startsWith(`..${sep4}`))) {
79298
80376
  return createResult({
79299
80377
  actionType,
79300
80378
  status: ActionStatus.OBSERVED,
@@ -79304,7 +80382,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
79304
80382
  }
79305
80383
  });
79306
80384
  }
79307
- const entrySkillPath = resolve20(installPath, "skills", action.entrySkill, "SKILL.md");
80385
+ const entrySkillPath = resolve21(installPath, "skills", action.entrySkill, "SKILL.md");
79308
80386
  let entrySkillFound = false;
79309
80387
  try {
79310
80388
  const skillStat = await lstat11(entrySkillPath);
@@ -79373,8 +80451,8 @@ function createPluginMarketplaceAdapter(deps = {}) {
79373
80451
  });
79374
80452
  }
79375
80453
  try {
79376
- const installedManifestPath = resolve20(installPath, platform.manifestPaths.plugin);
79377
- const installedManifestContent = await readFile19(installedManifestPath, "utf8");
80454
+ const installedManifestPath = resolve21(installPath, platform.manifestPaths.plugin);
80455
+ const installedManifestContent = await readFile20(installedManifestPath, "utf8");
79378
80456
  const installedManifest = JSON.parse(installedManifestContent);
79379
80457
  const expectedName = observation.plugin;
79380
80458
  if (expectedName && installedManifest.name !== expectedName) {
@@ -79444,6 +80522,10 @@ function createPluginMarketplaceAdapter(deps = {}) {
79444
80522
  }
79445
80523
  if (evidence.repo) observation.repo = evidence.repo;
79446
80524
  if (evidence.ref) observation.ref = evidence.ref;
80525
+ if (action.marketplaceLocation === "external") {
80526
+ observation.marketplaceLocation = action.marketplaceLocation;
80527
+ observation.marketplaceCommitSha = action.marketplaceCommitSha;
80528
+ }
79447
80529
  return createResult({
79448
80530
  actionType,
79449
80531
  status: ActionStatus.OBSERVED,
@@ -79489,17 +80571,19 @@ function createPluginMarketplaceAdapter(deps = {}) {
79489
80571
  }
79490
80572
  });
79491
80573
  }
79492
- var execFile9, NAME4, PAYLOAD_CONTRACT_DECLARED_MANIFEST, EXTRA_INSTALLED_PATHS_CAP, PAYLOAD_CONFLICT_REPORT_CAP, SUPPORTED_TYPES, SAFE_REPO_RE, CONSUMER_IDS, STRICT_SEMVER_RE;
80574
+ var execFile9, NAME4, PAYLOAD_CONTRACT_DECLARED_MANIFEST, PAYLOAD_CONTRACT_EXTERNAL_MARKETPLACE, EXTRA_INSTALLED_PATHS_CAP, PAYLOAD_CONFLICT_REPORT_CAP, SUPPORTED_TYPES, SAFE_REPO_RE, CONSUMER_IDS, STRICT_SEMVER_RE;
79493
80575
  var init_plugin_marketplace = __esm({
79494
80576
  async "src/adapters/plugin-marketplace.mjs"() {
79495
80577
  init_contract();
79496
80578
  init_frozen();
79497
80579
  await init_registry();
79498
80580
  await init_kimi();
80581
+ init_codebuddy();
79499
80582
  execFile9 = promisify10(execFileCb10);
79500
80583
  NAME4 = "plugin-marketplace";
79501
80584
  __name(transportPayload, "transportPayload");
79502
80585
  PAYLOAD_CONTRACT_DECLARED_MANIFEST = "declared-manifest-v1";
80586
+ PAYLOAD_CONTRACT_EXTERNAL_MARKETPLACE = "external-marketplace-v1";
79503
80587
  EXTRA_INSTALLED_PATHS_CAP = 200;
79504
80588
  PAYLOAD_CONFLICT_REPORT_CAP = 10;
79505
80589
  __name(extractDeclaredPluginSource, "extractDeclaredPluginSource");
@@ -79508,12 +80592,15 @@ var init_plugin_marketplace = __esm({
79508
80592
  __name(extraInstalledPathsAudit, "extraInstalledPathsAudit");
79509
80593
  __name(normalizeKimiSkillsRel, "normalizeKimiSkillsRel");
79510
80594
  __name(resolveKimiEntrySkillFile, "resolveKimiEntrySkillFile");
80595
+ __name(normalizeCodeBuddySkillsRel, "normalizeCodeBuddySkillsRel");
80596
+ __name(resolveCodeBuddyEntrySkillFile, "resolveCodeBuddyEntrySkillFile");
79511
80597
  SUPPORTED_TYPES = [
79512
80598
  ActionType.PLUGIN_MANIFEST_VALIDATE,
79513
80599
  ActionType.PLUGIN_INSTALL_CHECK,
79514
80600
  ActionType.CLAUDE_MARKETPLACE_INSTALL,
79515
80601
  ActionType.CODEX_MARKETPLACE_INSTALL,
79516
- ActionType.KIMI_MARKETPLACE_INSTALL
80602
+ ActionType.KIMI_MARKETPLACE_INSTALL,
80603
+ ActionType.CODEBUDDY_MARKETPLACE_INSTALL
79517
80604
  ];
79518
80605
  SAFE_REPO_RE = /^[a-zA-Z0-9][a-zA-Z0-9._-]*\/[a-zA-Z0-9][a-zA-Z0-9._-]*$/;
79519
80606
  CONSUMER_IDS = new Set(PLATFORMS.map((p) => p.id));
@@ -79533,8 +80620,8 @@ __export(verify_exports, {
79533
80620
  runSmokeTest: () => runSmokeTest,
79534
80621
  verifyRelease: () => verifyRelease
79535
80622
  });
79536
- import { readFile as readFile20, writeFile as writeFile8, mkdtemp as mkdtemp3, rm as rm7, mkdir as mkdir14, lstat as lstat12, realpath as realpath12 } from "node:fs/promises";
79537
- import { dirname as dirname12, join as join16, relative as relative18, isAbsolute as isAbsolute15, resolve as resolve21 } from "node:path";
80623
+ import { readFile as readFile21, writeFile as writeFile8, mkdtemp as mkdtemp3, rm as rm7, mkdir as mkdir15, lstat as lstat12, realpath as realpath12 } from "node:fs/promises";
80624
+ import { dirname as dirname12, join as join17, relative as relative19, isAbsolute as isAbsolute16, resolve as resolve22 } from "node:path";
79538
80625
  import { tmpdir as tmpdir2 } from "node:os";
79539
80626
  import { execFile as execFileCb11 } from "node:child_process";
79540
80627
  import { promisify as promisify11 } from "node:util";
@@ -79560,8 +80647,8 @@ function matchesSubset2(actual, expected) {
79560
80647
  }
79561
80648
  async function runSmokeTest(plan, root, options = {}) {
79562
80649
  const baseDir = options.baseDir ?? tmpdir2();
79563
- await mkdir14(baseDir, { recursive: true });
79564
- const tmpDir = await mkdtemp3(join16(baseDir, "verify-smoke-"));
80650
+ await mkdir15(baseDir, { recursive: true });
80651
+ const tmpDir = await mkdtemp3(join17(baseDir, "verify-smoke-"));
79565
80652
  const npmExec = options.npmExecutor ?? defaultNpmExecutor;
79566
80653
  const installFlags = [
79567
80654
  "--ignore-scripts",
@@ -79607,7 +80694,7 @@ async function runSmokeTest(plan, root, options = {}) {
79607
80694
  for (const { package: pkgName, registry, targetVersion, unitId, smokeBin, smokeArgs, smokeExpectedJson } of npmDistributions) {
79608
80695
  const packageAtVersion = `${pkgName}@${targetVersion}`;
79609
80696
  const installDir = resolveUnitScopedPath(tmpDir, unitId);
79610
- await mkdir14(join16(installDir, "node_modules"), { recursive: true });
80697
+ await mkdir15(join17(installDir, "node_modules"), { recursive: true });
79611
80698
  const registryFlags = [...installFlags, "--registry", registry];
79612
80699
  const installResult = await npmExec.install(
79613
80700
  packageAtVersion,
@@ -79625,10 +80712,10 @@ async function runSmokeTest(plan, root, options = {}) {
79625
80712
  }
79626
80713
  };
79627
80714
  }
79628
- const installedPkgPath = join16(installDir, "node_modules", pkgName, "package.json");
80715
+ const installedPkgPath = join17(installDir, "node_modules", pkgName, "package.json");
79629
80716
  let installedPkg;
79630
80717
  try {
79631
- installedPkg = JSON.parse(await readFile20(installedPkgPath, "utf8"));
80718
+ installedPkg = JSON.parse(await readFile21(installedPkgPath, "utf8"));
79632
80719
  } catch {
79633
80720
  return {
79634
80721
  passed: false,
@@ -79659,7 +80746,7 @@ async function runSmokeTest(plan, root, options = {}) {
79659
80746
  }
79660
80747
  };
79661
80748
  }
79662
- const pkgRoot = join16(installDir, "node_modules", pkgName);
80749
+ const pkgRoot = join17(installDir, "node_modules", pkgName);
79663
80750
  gateResults.push(...await runConsumerVerificationGates({
79664
80751
  plan,
79665
80752
  unitId,
@@ -79701,10 +80788,10 @@ async function runSmokeTest(plan, root, options = {}) {
79701
80788
  }
79702
80789
  };
79703
80790
  }
79704
- const binPath = resolve21(pkgRoot, binRelative);
79705
- const relBin = relative18(pkgRoot, binPath);
80791
+ const binPath = resolve22(pkgRoot, binRelative);
80792
+ const relBin = relative19(pkgRoot, binPath);
79706
80793
  const sep4 = process.platform === "win32" ? "\\" : "/";
79707
- if (isAbsolute15(relBin) || relBin === ".." || relBin.startsWith(`..${sep4}`)) {
80794
+ if (isAbsolute16(relBin) || relBin === ".." || relBin.startsWith(`..${sep4}`)) {
79708
80795
  return {
79709
80796
  passed: false,
79710
80797
  details: {
@@ -79718,8 +80805,8 @@ async function runSmokeTest(plan, root, options = {}) {
79718
80805
  try {
79719
80806
  binStat = await lstat12(binPath);
79720
80807
  const [pkgRootReal, binPathReal] = await Promise.all([realpath12(pkgRoot), realpath12(binPath)]);
79721
- const relReal = relative18(pkgRootReal, binPathReal);
79722
- if (!binStat.isFile() || binStat.isSymbolicLink() || isAbsolute15(relReal) || relReal === ".." || relReal.startsWith(`..${sep4}`)) {
80808
+ const relReal = relative19(pkgRootReal, binPathReal);
80809
+ if (!binStat.isFile() || binStat.isSymbolicLink() || isAbsolute16(relReal) || relReal === ".." || relReal.startsWith(`..${sep4}`)) {
79723
80810
  throw new Error("bin is not a regular file inside the installed package");
79724
80811
  }
79725
80812
  } catch (err) {
@@ -79849,7 +80936,7 @@ async function verifyRelease(options) {
79849
80936
  }
79850
80937
  let planRaw;
79851
80938
  try {
79852
- planRaw = await readFile20(planPath, "utf8");
80939
+ planRaw = await readFile21(planPath, "utf8");
79853
80940
  } catch (err) {
79854
80941
  throw new ReleaseError(
79855
80942
  GATE_FAILED,
@@ -79871,7 +80958,7 @@ async function verifyRelease(options) {
79871
80958
  const runId = `verify-${Date.now()}`;
79872
80959
  const requestedRunDir = runDirOpt ?? resolveDefaultRunDir(planPath, "verify", runId);
79873
80960
  const runDir = plan.production ? await createProductionRunDir(requestedRunDir, planPath) : requestedRunDir;
79874
- if (!plan.production) await mkdir14(runDir, { recursive: true });
80961
+ if (!plan.production) await mkdir15(runDir, { recursive: true });
79875
80962
  const evidence = createEvidenceWriter({ runDir, command: "verify", clock: clockFn });
79876
80963
  try {
79877
80964
  await evidence.append({ phase: "verify", step: "plan-load", status: "started" });
@@ -79919,7 +81006,7 @@ async function verifyRelease(options) {
79919
81006
  }
79920
81007
  let approvalRaw;
79921
81008
  try {
79922
- approvalRaw = await readFile20(sourceRun.approvalPath, "utf8");
81009
+ approvalRaw = await readFile21(sourceRun.approvalPath, "utf8");
79923
81010
  } catch (error) {
79924
81011
  throw new ReleaseError(
79925
81012
  GATE_FAILED,
@@ -79978,7 +81065,8 @@ async function verifyRelease(options) {
79978
81065
  const MARKETPLACE_TYPES3 = /* @__PURE__ */ new Set([
79979
81066
  "claude-marketplace-install",
79980
81067
  "codex-marketplace-install",
79981
- "kimi-marketplace-install"
81068
+ "kimi-marketplace-install",
81069
+ "codebuddy-marketplace-install"
79982
81070
  ]);
79983
81071
  for (const action of actions) {
79984
81072
  const adapterActionType = ADAPTER_ACTION_TYPE_MAP2[action.type];
@@ -80077,14 +81165,14 @@ async function verifyRelease(options) {
80077
81165
  evidence,
80078
81166
  env: gateEnv ?? process.env,
80079
81167
  fixedEnv: action.type === "claude-marketplace-install" ? {
80080
- HOME: resolve21(runDir, "consumers", `claude-${action.parameters.plugin}`),
80081
- CLAUDE_CONFIG_DIR: resolve21(runDir, "consumers", `claude-${action.parameters.plugin}`, ".claude")
81168
+ HOME: resolve22(runDir, "consumers", `claude-${action.parameters.plugin}`),
81169
+ CLAUDE_CONFIG_DIR: resolve22(runDir, "consumers", `claude-${action.parameters.plugin}`, ".claude")
80082
81170
  } : action.type === "codex-marketplace-install" ? {
80083
- HOME: resolve21(runDir, "consumers", `codex-${action.parameters.plugin}`),
80084
- CODEX_HOME: resolve21(runDir, "consumers", `codex-${action.parameters.plugin}`)
81171
+ HOME: resolve22(runDir, "consumers", `codex-${action.parameters.plugin}`),
81172
+ CODEX_HOME: resolve22(runDir, "consumers", `codex-${action.parameters.plugin}`)
80085
81173
  } : {
80086
- HOME: resolve21(runDir, "consumers", `kimi-${action.parameters.plugin}`),
80087
- KIMI_CODE_HOME: resolve21(runDir, "consumers", `kimi-${action.parameters.plugin}`)
81174
+ HOME: resolve22(runDir, "consumers", `kimi-${action.parameters.plugin}`),
81175
+ KIMI_CODE_HOME: resolve22(runDir, "consumers", `kimi-${action.parameters.plugin}`)
80088
81176
  }
80089
81177
  }));
80090
81178
  } else {
@@ -80165,7 +81253,7 @@ async function verifyRelease(options) {
80165
81253
  assertTransition(PUBLISHED, VERIFIED);
80166
81254
  await evidence.append({ phase: "verify", status: "completed", overallStatus: VERIFIED });
80167
81255
  const sourceRunDigest = sourceRun.runDigest ?? computeRunDigest(sourceRun);
80168
- const verifyRunPath = join16(runDir, "release-run.json");
81256
+ const verifyRunPath = join17(runDir, "release-run.json");
80169
81257
  const verifyRunState = {
80170
81258
  runId,
80171
81259
  command: "verify",
@@ -80246,7 +81334,8 @@ var init_verify = __esm({
80246
81334
  "github-release": "github-release",
80247
81335
  "claude-marketplace-install": "claude-marketplace-install",
80248
81336
  "codex-marketplace-install": "codex-marketplace-install",
80249
- "kimi-marketplace-install": "kimi-marketplace-install"
81337
+ "kimi-marketplace-install": "kimi-marketplace-install",
81338
+ "codebuddy-marketplace-install": "codebuddy-marketplace-install"
80250
81339
  };
80251
81340
  __name(defaultClock4, "defaultClock");
80252
81341
  __name(matchesSubset2, "matchesSubset");
@@ -80260,7 +81349,7 @@ var init_verify = __esm({
80260
81349
  exec: execFile10,
80261
81350
  env: process.env
80262
81351
  });
80263
- const userConfig = join16(cwd, ".release-skill-npmrc");
81352
+ const userConfig = join17(cwd, ".release-skill-npmrc");
80264
81353
  await writeFile8(
80265
81354
  userConfig,
80266
81355
  `registry=${normalizedRegistry}/
@@ -80320,11 +81409,11 @@ __export(publish_exports, {
80320
81409
  classifyPreObservation: () => classifyPreObservation,
80321
81410
  publishRelease: () => publishRelease
80322
81411
  });
80323
- import { readFile as readFile21, mkdir as mkdir15 } from "node:fs/promises";
80324
- import { isAbsolute as isAbsolute16, join as join17, relative as relative19 } from "node:path";
81412
+ import { readFile as readFile22, mkdir as mkdir16 } from "node:fs/promises";
81413
+ import { isAbsolute as isAbsolute17, join as join18, relative as relative20 } from "node:path";
80325
81414
  function assertInsideAssetRoot(assetRoot, candidate, label) {
80326
- const rel = relative19(assetRoot, candidate);
80327
- if (rel === "" || isAbsolute16(rel) || rel === ".." || rel.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`)) {
81415
+ const rel = relative20(assetRoot, candidate);
81416
+ if (rel === "" || isAbsolute17(rel) || rel === ".." || rel.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`)) {
80328
81417
  throw new ReleaseError(GATE_FAILED, `${label} must be a child of the production asset root`);
80329
81418
  }
80330
81419
  }
@@ -80554,7 +81643,7 @@ async function publishRelease(options) {
80554
81643
  const captureBaselineActual = typeof captureBaselineFn === "function" ? captureBaselineFn : captureBaseline;
80555
81644
  let planRaw;
80556
81645
  try {
80557
- planRaw = await readFile21(planPath, "utf8");
81646
+ planRaw = await readFile22(planPath, "utf8");
80558
81647
  } catch (err) {
80559
81648
  throw new ReleaseError(GATE_FAILED, `cannot read release plan: ${err.message}`, { planPath, cause: err.code });
80560
81649
  }
@@ -80572,7 +81661,7 @@ async function publishRelease(options) {
80572
81661
  if (isProductionPlan) {
80573
81662
  runDir = await createProductionRunDir(runDir, planPath);
80574
81663
  } else {
80575
- await mkdir15(runDir, { recursive: true });
81664
+ await mkdir16(runDir, { recursive: true });
80576
81665
  }
80577
81666
  const evidence = createEvidenceWriter({ runDir, command: "publish", clock: clockFn });
80578
81667
  try {
@@ -80664,7 +81753,7 @@ async function publishRelease(options) {
80664
81753
  await evidence.append({ phase: "safety-gate", gate: "approval-load", status: "started" });
80665
81754
  let approvalRaw;
80666
81755
  try {
80667
- approvalRaw = await readFile21(approvalPath, "utf8");
81756
+ approvalRaw = await readFile22(approvalPath, "utf8");
80668
81757
  } catch (err) {
80669
81758
  throw new ReleaseError(
80670
81759
  GATE_FAILED,
@@ -80936,7 +82025,7 @@ async function publishRelease(options) {
80936
82025
  }
80937
82026
  }
80938
82027
  await evidence.append({ phase: "safety-gate", gate: "global-preflight", status: "passed" });
80939
- const runPath = join17(runDir, "release-run.json");
82028
+ const runPath = join18(runDir, "release-run.json");
80940
82029
  const checkpoints = orderedActions.map((action) => ({
80941
82030
  actionId: action.id,
80942
82031
  actionType: action.type,
@@ -81165,7 +82254,8 @@ var init_publish = __esm({
81165
82254
  MARKETPLACE_TYPES2 = /* @__PURE__ */ new Set([
81166
82255
  "claude-marketplace-install",
81167
82256
  "codex-marketplace-install",
81168
- "kimi-marketplace-install"
82257
+ "kimi-marketplace-install",
82258
+ "codebuddy-marketplace-install"
81169
82259
  ]);
81170
82260
  __name(defaultClock5, "defaultClock");
81171
82261
  __name(deepClone, "deepClone");
@@ -81183,8 +82273,8 @@ var init_publish = __esm({
81183
82273
  });
81184
82274
 
81185
82275
  // src/artifacts/policy.mjs
81186
- import { readFile as readFile22 } from "node:fs/promises";
81187
- import { join as join18 } from "node:path";
82276
+ import { readFile as readFile23 } from "node:fs/promises";
82277
+ import { join as join19 } from "node:path";
81188
82278
  import { createHash as createHash11 } from "node:crypto";
81189
82279
  function validateArtifactPolicy(policy) {
81190
82280
  const ok = _validate(policy);
@@ -81280,10 +82370,10 @@ async function parseSafeYamlWithinRoot(root, policyPath) {
81280
82370
  }
81281
82371
  throw err;
81282
82372
  }
81283
- const fullPath = join18(root, policyPath);
82373
+ const fullPath = join19(root, policyPath);
81284
82374
  let content;
81285
82375
  try {
81286
- content = await readFile22(fullPath, "utf8");
82376
+ content = await readFile23(fullPath, "utf8");
81287
82377
  } catch (err) {
81288
82378
  throw new ReleaseError(
81289
82379
  ARTIFACT_POLICY_INVALID,
@@ -81394,8 +82484,8 @@ var init_policy = __esm({
81394
82484
  });
81395
82485
 
81396
82486
  // src/artifacts/entry.mjs
81397
- import { lstat as lstat13, readdir as readdir10, readFile as readFile23 } from "node:fs/promises";
81398
- import { join as join19 } from "node:path";
82487
+ import { lstat as lstat13, readdir as readdir10, readFile as readFile24 } from "node:fs/promises";
82488
+ import { join as join20 } from "node:path";
81399
82489
  import { promisify as promisify12 } from "node:util";
81400
82490
  import { execFile as execFile11 } from "node:child_process";
81401
82491
  function statToGitMode(stat9) {
@@ -81418,7 +82508,7 @@ async function enumerateTreeEntries(root, dirPath, relBase) {
81418
82508
  const items = await readdir10(dirPath, { withFileTypes: true });
81419
82509
  for (const item of items) {
81420
82510
  if (SKIP_DIRS2.has(item.name)) continue;
81421
- const absPath = join19(dirPath, item.name);
82511
+ const absPath = join20(dirPath, item.name);
81422
82512
  const relPath = relBase ? `${relBase}/${item.name}` : item.name;
81423
82513
  const st = await lstat13(absPath);
81424
82514
  if (st.isSymbolicLink()) {
@@ -81439,7 +82529,7 @@ async function enumerateTreeEntries(root, dirPath, relBase) {
81439
82529
  const subEntries = await enumerateTreeEntries(root, absPath, relPath);
81440
82530
  entries.push(...subEntries);
81441
82531
  } else {
81442
- const content = await readFile23(absPath);
82532
+ const content = await readFile24(absPath);
81443
82533
  entries.push(
81444
82534
  Object.freeze({
81445
82535
  path: relPath,
@@ -81469,7 +82559,7 @@ async function readEntry({ root, path: path3, source = "worktree" } = {}) {
81469
82559
  if (source !== "worktree") {
81470
82560
  throw new ReleaseError(PATH_UNSAFE, `unsupported readEntry source: ${source}`, { source });
81471
82561
  }
81472
- const absPath = join19(root, path3);
82562
+ const absPath = join20(root, path3);
81473
82563
  let st;
81474
82564
  try {
81475
82565
  st = await lstat13(absPath);
@@ -81502,7 +82592,7 @@ async function readEntry({ root, path: path3, source = "worktree" } = {}) {
81502
82592
  { path: path3, nlink: st.nlink }
81503
82593
  );
81504
82594
  }
81505
- const content = await readFile23(absPath);
82595
+ const content = await readFile24(absPath);
81506
82596
  return Object.freeze({
81507
82597
  kind: "regular",
81508
82598
  path: path3,
@@ -81765,8 +82855,8 @@ var init_graph = __esm({
81765
82855
  });
81766
82856
 
81767
82857
  // src/artifacts/producer-registry.mjs
81768
- import { readFile as readFile24, readdir as readdir11, stat as stat6, mkdir as mkdir16, writeFile as writeFile9, rm as rm8 } from "node:fs/promises";
81769
- import { join as join20 } from "node:path";
82858
+ import { readFile as readFile25, readdir as readdir11, stat as stat6, mkdir as mkdir17, writeFile as writeFile9, rm as rm8 } from "node:fs/promises";
82859
+ import { join as join21 } from "node:path";
81770
82860
  import { mkdtemp as mkdtemp4 } from "node:fs/promises";
81771
82861
  import { tmpdir as tmpdir3 } from "node:os";
81772
82862
  import { createHash as createHash12 } from "node:crypto";
@@ -81787,7 +82877,7 @@ function collectStaticImports(filePath, visited = /* @__PURE__ */ new Set()) {
81787
82877
  const dir = abs.replace(/\/[^/]*$/, "");
81788
82878
  while ((match = importRe.exec(source)) !== null) {
81789
82879
  const spec = match[1];
81790
- let resolved = join20(dir, spec);
82880
+ let resolved = join21(dir, spec);
81791
82881
  if (!resolved.endsWith(".mjs")) resolved += ".mjs";
81792
82882
  results.push(...collectStaticImports(resolved, visited));
81793
82883
  }
@@ -81795,10 +82885,10 @@ function collectStaticImports(filePath, visited = /* @__PURE__ */ new Set()) {
81795
82885
  }
81796
82886
  async function createBuiltInProducerRegistry() {
81797
82887
  const producers = /* @__PURE__ */ new Map();
81798
- const lockfilePath = join20(new URL("../../..", import.meta.url).pathname, "pnpm-lock.yaml");
82888
+ const lockfilePath = join21(new URL("../../..", import.meta.url).pathname, "pnpm-lock.yaml");
81799
82889
  let lockfileBytes;
81800
82890
  try {
81801
- lockfileBytes = await readFile24(lockfilePath);
82891
+ lockfileBytes = await readFile25(lockfilePath);
81802
82892
  } catch {
81803
82893
  lockfileBytes = Buffer.from("");
81804
82894
  }
@@ -81815,7 +82905,7 @@ async function createBuiltInProducerRegistry() {
81815
82905
  const allModuleBytes = await Promise.all(
81816
82906
  allModulePaths.map(async (p) => {
81817
82907
  try {
81818
- return await readFile24(p);
82908
+ return await readFile25(p);
81819
82909
  } catch {
81820
82910
  return Buffer.from("");
81821
82911
  }
@@ -81835,13 +82925,13 @@ async function readDirEntries(dirPath, relBase = "") {
81835
82925
  const items = await readdir11(dirPath, { withFileTypes: true });
81836
82926
  for (const item of items) {
81837
82927
  if (item.name === ".git") continue;
81838
- const absPath = join20(dirPath, item.name);
82928
+ const absPath = join21(dirPath, item.name);
81839
82929
  const relPath = relBase ? `${relBase}/${item.name}` : item.name;
81840
82930
  const st = await stat6(absPath);
81841
82931
  if (st.isDirectory()) {
81842
82932
  entries.push(...await readDirEntries(absPath, relPath));
81843
82933
  } else {
81844
- const content = await readFile24(absPath);
82934
+ const content = await readFile25(absPath);
81845
82935
  entries.push(Object.freeze({
81846
82936
  path: relPath,
81847
82937
  type: "blob",
@@ -81858,11 +82948,11 @@ async function readDirEntries(dirPath, relBase = "") {
81858
82948
  async function materializeEntries(entries, dirPath) {
81859
82949
  for (const entry of entries) {
81860
82950
  if (!entry.path) continue;
81861
- const targetPath = join20(dirPath, entry.path);
82951
+ const targetPath = join21(dirPath, entry.path);
81862
82952
  if (entry.type === "tree" || entry.kind === "tree") {
81863
- await mkdir16(targetPath, { recursive: true });
82953
+ await mkdir17(targetPath, { recursive: true });
81864
82954
  } else {
81865
- await mkdir16(join20(targetPath, ".."), { recursive: true });
82955
+ await mkdir17(join21(targetPath, ".."), { recursive: true });
81866
82956
  if (entry.content) {
81867
82957
  await writeFile9(targetPath, entry.content);
81868
82958
  }
@@ -81906,7 +82996,7 @@ async function runProducerClosure({
81906
82996
  graph,
81907
82997
  inputSnapshot,
81908
82998
  artifactIds,
81909
- tempRootFactory = /* @__PURE__ */ __name(async () => mkdtemp4(join20(tmpdir3(), "producer-")), "tempRootFactory")
82999
+ tempRootFactory = /* @__PURE__ */ __name(async () => mkdtemp4(join21(tmpdir3(), "producer-")), "tempRootFactory")
81910
83000
  } = {}) {
81911
83001
  const generatedSet = new Set(graph.topologicalOrder);
81912
83002
  for (const id of artifactIds) {
@@ -81943,7 +83033,7 @@ async function runProducerClosure({
81943
83033
  if (inputEntries) {
81944
83034
  const first = inputEntries[0];
81945
83035
  if (first && first.path) {
81946
- const absPath = first.path.startsWith("/") ? first.path : join20(process.cwd(), first.path);
83036
+ const absPath = first.path.startsWith("/") ? first.path : join21(process.cwd(), first.path);
81947
83037
  try {
81948
83038
  const st = await stat6(absPath);
81949
83039
  if (st.isDirectory()) {
@@ -82367,7 +83457,7 @@ var init_state = __esm({
82367
83457
  });
82368
83458
 
82369
83459
  // src/artifacts/artifact-plan.mjs
82370
- import { writeFile as writeFile10, mkdir as mkdir17, readFile as readFile25, rename as rename3, open as open8 } from "node:fs/promises";
83460
+ import { writeFile as writeFile10, mkdir as mkdir18, readFile as readFile26, rename as rename3, open as open8 } from "node:fs/promises";
82371
83461
  import { dirname as dirname13 } from "node:path";
82372
83462
  function assemblePlan({
82373
83463
  operation,
@@ -82392,7 +83482,7 @@ function assemblePlan({
82392
83482
  }
82393
83483
  async function writePlan(plan, outputPath) {
82394
83484
  const dir = dirname13(outputPath);
82395
- await mkdir17(dir, { recursive: true });
83485
+ await mkdir18(dir, { recursive: true });
82396
83486
  const tmpPath = `${outputPath}.tmp`;
82397
83487
  const content = JSON.stringify(plan, null, 2);
82398
83488
  const fh = await open8(tmpPath, "w");
@@ -83056,8 +84146,8 @@ var init_adoption = __esm({
83056
84146
  // src/artifacts/inspect.mjs
83057
84147
  import { promisify as promisify15 } from "node:util";
83058
84148
  import { execFile as execFile14 } from "node:child_process";
83059
- import { readdir as readdir12, stat as stat7, readFile as readFile26 } from "node:fs/promises";
83060
- import { join as join21 } from "node:path";
84149
+ import { readdir as readdir12, stat as stat7, readFile as readFile27 } from "node:fs/promises";
84150
+ import { join as join22 } from "node:path";
83061
84151
  async function hasNestedGitRoots(root) {
83062
84152
  try {
83063
84153
  const { stdout } = await execFileAsync5(
@@ -83067,9 +84157,9 @@ async function hasNestedGitRoots(root) {
83067
84157
  );
83068
84158
  const dirs = stdout.split("\n").filter((s) => s.length > 0);
83069
84159
  for (const dir of dirs) {
83070
- const absDir = join21(root, dir);
84160
+ const absDir = join22(root, dir);
83071
84161
  try {
83072
- const nestedGit = join21(absDir, ".git");
84162
+ const nestedGit = join22(absDir, ".git");
83073
84163
  await stat7(nestedGit);
83074
84164
  return true;
83075
84165
  } catch {
@@ -83328,8 +84418,8 @@ var init_inspect = __esm({
83328
84418
  });
83329
84419
 
83330
84420
  // src/artifacts/resolution.mjs
83331
- import { mkdir as mkdir18, open as open9, readFile as readFile27, stat as stat8, lstat as lstat14, chmod as chmod4 } from "node:fs/promises";
83332
- import { join as join22, resolve as resolve22, relative as relative20, isAbsolute as isAbsolute17, basename as basename8 } from "node:path";
84421
+ import { mkdir as mkdir19, open as open9, readFile as readFile28, stat as stat8, lstat as lstat14, chmod as chmod4 } from "node:fs/promises";
84422
+ import { join as join23, resolve as resolve23, relative as relative21, isAbsolute as isAbsolute18, basename as basename8 } from "node:path";
83333
84423
  function decodeBuffer(value, label) {
83334
84424
  if (value == null) return null;
83335
84425
  if (Buffer.isBuffer(value)) return value;
@@ -83431,9 +84521,9 @@ function assertSafeArtifactId(id) {
83431
84521
  }
83432
84522
  async function assertNoSymlinksInPath(root, artifactId) {
83433
84523
  const levels = [
83434
- join22(root, ".release-skill"),
83435
- join22(root, ".release-skill", "resolution"),
83436
- join22(root, ".release-skill", "resolution", artifactId)
84524
+ join23(root, ".release-skill"),
84525
+ join23(root, ".release-skill", "resolution"),
84526
+ join23(root, ".release-skill", "resolution", artifactId)
83437
84527
  ];
83438
84528
  for (const dir of levels) {
83439
84529
  try {
@@ -83449,11 +84539,11 @@ async function assertNoSymlinksInPath(root, artifactId) {
83449
84539
  }
83450
84540
  }
83451
84541
  async function assertSafeResolvedPath(root, artifactId, resolvedPath) {
83452
- const resolutionDir = resolve22(root, ".release-skill", "resolution", artifactId);
83453
- const resolved = resolve22(resolvedPath);
84542
+ const resolutionDir = resolve23(root, ".release-skill", "resolution", artifactId);
84543
+ const resolved = resolve23(resolvedPath);
83454
84544
  await assertNoSymlinksInPath(root, artifactId);
83455
- const rel = relative20(resolutionDir, resolved);
83456
- if (rel.startsWith("..") || isAbsolute17(rel)) {
84545
+ const rel = relative21(resolutionDir, resolved);
84546
+ if (rel.startsWith("..") || isAbsolute18(rel)) {
83457
84547
  throw new ReleaseError(
83458
84548
  PATH_UNSAFE,
83459
84549
  `resolvedPath must be inside resolution directory ${resolutionDir}`,
@@ -83468,7 +84558,7 @@ async function assertSafeResolvedPath(root, artifactId, resolvedPath) {
83468
84558
  { resolvedPath, expected: `${artifactId}.resolved`, actual: filename }
83469
84559
  );
83470
84560
  }
83471
- if (resolved !== resolve22(resolutionDir, `${artifactId}.resolved`)) {
84561
+ if (resolved !== resolve23(resolutionDir, `${artifactId}.resolved`)) {
83472
84562
  throw new ReleaseError(
83473
84563
  PATH_UNSAFE,
83474
84564
  "resolvedPath must be the exact materialized resolution file",
@@ -83612,13 +84702,13 @@ async function materializeResolution({
83612
84702
  const template = buildConflictTemplate(artifact.conflict ?? {}, decodedBuffers);
83613
84703
  const templateDigest = sha256Hex(template);
83614
84704
  await assertNoSymlinksInPath(root, artifactId);
83615
- const resolutionDir = join22(root, ".release-skill", "resolution", artifactId);
83616
- await mkdir18(resolutionDir, { recursive: true, mode: 448 });
84705
+ const resolutionDir = join23(root, ".release-skill", "resolution", artifactId);
84706
+ await mkdir19(resolutionDir, { recursive: true, mode: 448 });
83617
84707
  const dirStat = await stat8(resolutionDir);
83618
84708
  if ((dirStat.mode & 511) !== 448) {
83619
84709
  await chmod4(resolutionDir, 448);
83620
84710
  }
83621
- const resolvedPath = join22(resolutionDir, `${artifactId}.resolved`);
84711
+ const resolvedPath = join23(resolutionDir, `${artifactId}.resolved`);
83622
84712
  const fh = await open9(resolvedPath, "wx", 384);
83623
84713
  try {
83624
84714
  await fh.write(template, 0, template.length);
@@ -83660,7 +84750,7 @@ async function submitResolution({
83660
84750
  async function readAndValidateResolvedFile(resolvedPath) {
83661
84751
  let content;
83662
84752
  try {
83663
- content = await readFile27(resolvedPath);
84753
+ content = await readFile28(resolvedPath);
83664
84754
  } catch (err) {
83665
84755
  throw new ReleaseError(MISSING_PARAMETERS, `cannot read resolved file: ${err.message}`, { resolvedPath, cause: err.code });
83666
84756
  }
@@ -83828,8 +84918,8 @@ var artifacts_exports = {};
83828
84918
  __export(artifacts_exports, {
83829
84919
  runArtifactsCommand: () => runArtifactsCommand
83830
84920
  });
83831
- import { readFile as readFile28 } from "node:fs/promises";
83832
- import { join as join23 } from "node:path";
84921
+ import { readFile as readFile29 } from "node:fs/promises";
84922
+ import { join as join24 } from "node:path";
83833
84923
  async function runArtifactsCommand({ subcommand, args: args2, root } = {}) {
83834
84924
  if (!VALID_SUBCOMMANDS.has(subcommand)) {
83835
84925
  throw new ReleaseError(
@@ -83957,7 +85047,7 @@ async function handleAdopt({ args: args2, root }) {
83957
85047
  { subcommand: "adopt" }
83958
85048
  );
83959
85049
  }
83960
- const planRaw = await readFile28(planPath, "utf8");
85050
+ const planRaw = await readFile29(planPath, "utf8");
83961
85051
  const plan = JSON.parse(planRaw);
83962
85052
  if (expectedDigest && plan.planDigest !== expectedDigest) {
83963
85053
  throw new ReleaseError(
@@ -83972,7 +85062,7 @@ async function handleAdopt({ args: args2, root }) {
83972
85062
  if (artifact.path) {
83973
85063
  const entry = await readEntry({ root, path: artifact.path, source: "worktree" });
83974
85064
  if (entry.kind === "regular") {
83975
- const bytes = await readFile28(join23(root, artifact.path));
85065
+ const bytes = await readFile29(join24(root, artifact.path));
83976
85066
  currentEntries.set(artifact.id, Object.freeze({ ...entry, bytes, content: bytes }));
83977
85067
  } else {
83978
85068
  currentEntries.set(artifact.id, entry);
@@ -84037,7 +85127,7 @@ async function handleBootstrap({ args: args2, root }) {
84037
85127
  { subcommand: "bootstrap" }
84038
85128
  );
84039
85129
  }
84040
- const planRaw = await readFile28(planPath, "utf8");
85130
+ const planRaw = await readFile29(planPath, "utf8");
84041
85131
  const adoptionPlan = JSON.parse(planRaw);
84042
85132
  const currentEntries = /* @__PURE__ */ new Map();
84043
85133
  for (const id of new Set((adoptionPlan.protectedHunks ?? []).map((h) => h.artifactId))) {
@@ -84049,12 +85139,12 @@ async function handleBootstrap({ args: args2, root }) {
84049
85139
  if (entry.kind !== "regular") {
84050
85140
  throw new ReleaseError("PLAN_STALE", `artifact is no longer a regular file: ${id}`, { id });
84051
85141
  }
84052
- const bytes = await readFile28(join23(root, artifactPath));
85142
+ const bytes = await readFile29(join24(root, artifactPath));
84053
85143
  currentEntries.set(id, Object.freeze({ ...entry, bytes, content: bytes }));
84054
85144
  }
84055
85145
  let replacementBytes;
84056
85146
  if (action === "replace" && replacementPath) {
84057
- replacementBytes = await readFile28(replacementPath);
85147
+ replacementBytes = await readFile29(replacementPath);
84058
85148
  }
84059
85149
  const updated = await discardBootstrapHunk({
84060
85150
  adoptionPlan,
@@ -84092,7 +85182,7 @@ async function handleResolve({ args: args2, root }) {
84092
85182
  { subcommand: "resolve" }
84093
85183
  );
84094
85184
  }
84095
- const planRaw = await readFile28(planPath, "utf8");
85185
+ const planRaw = await readFile29(planPath, "utf8");
84096
85186
  const plan = JSON.parse(planRaw);
84097
85187
  if (plan.planDigest !== expectedDigest) {
84098
85188
  throw new ReleaseError(
@@ -84460,7 +85550,7 @@ var init_docs = __esm({
84460
85550
  });
84461
85551
 
84462
85552
  // bin/release-skill-cli.mjs
84463
- import { basename as basename9, dirname as dirname14, join as join24, resolve as resolve23 } from "node:path";
85553
+ import { basename as basename9, dirname as dirname14, join as join25, resolve as resolve24 } from "node:path";
84464
85554
  import { execFile as execFileCb12 } from "node:child_process";
84465
85555
  import { promisify as promisify16 } from "node:util";
84466
85556
 
@@ -84525,6 +85615,24 @@ async function checkDependency(command2, versionArgs = ["--version"]) {
84525
85615
  }
84526
85616
  }
84527
85617
  __name(checkDependency, "checkDependency");
85618
+ var CODEBUDDY_MACOS_ABS_PATH = "/Applications/WorkBuddy.app/Contents/Resources/app.asar.unpacked/cli/bin/codebuddy";
85619
+ async function checkCodeBuddyDependency() {
85620
+ const candidates = [
85621
+ { source: "PATH:codebuddy", command: "codebuddy" },
85622
+ { source: "PATH:cbc", command: "cbc" },
85623
+ { source: "macOS-bundle", command: CODEBUDDY_MACOS_ABS_PATH }
85624
+ ];
85625
+ const diagnostics = [];
85626
+ for (const { source, command: command2 } of candidates) {
85627
+ const result = await checkDependency(command2, ["--version"]);
85628
+ if (result.available) {
85629
+ return { available: true, version: result.version, diagnostic: "ok", source };
85630
+ }
85631
+ diagnostics.push(`${source}: ${result.diagnostic}`);
85632
+ }
85633
+ return { available: false, version: null, diagnostic: diagnostics.join("; "), source: null };
85634
+ }
85635
+ __name(checkCodeBuddyDependency, "checkCodeBuddyDependency");
84528
85636
  async function performEnvironmentChecks() {
84529
85637
  const checks = {};
84530
85638
  const nodeCheck = await checkDependency("node", ["--version"]);
@@ -84576,6 +85684,12 @@ async function performEnvironmentChecks() {
84576
85684
  required: false,
84577
85685
  usage: "\u4EC5\u5F53\u8BA1\u5212\u58F0\u660E kimi-plugin distribution \u65F6\u7528\u4E8E\u6D88\u8D39\u8005\u5B89\u88C5\u9A8C\u8BC1"
84578
85686
  };
85687
+ const codebuddyCheck = await checkCodeBuddyDependency();
85688
+ checks.codebuddy = {
85689
+ ...codebuddyCheck,
85690
+ required: false,
85691
+ usage: "\u4EC5\u5F53\u8BA1\u5212\u58F0\u660E codebuddy-plugin distribution \u65F6\u7528\u4E8E\u6D88\u8D39\u8005\u5B89\u88C5\u9A8C\u8BC1\uFF08\u4EBA\u5DE5 attestation \u95ED\u73AF\uFF1BCLI \u65E0\u6CD5\u9489\u6B7B\u51BB\u7ED3 ref\uFF0C\u5B89\u88C5\u7531\u4EBA\u5DE5\u5B8C\u6210\u5E76\u51FA\u5177 attestation\uFF09"
85692
+ };
84579
85693
  return checks;
84580
85694
  }
84581
85695
  __name(performEnvironmentChecks, "performEnvironmentChecks");
@@ -84604,7 +85718,7 @@ function getCapabilityMaturity() {
84604
85718
  publish: {
84605
85719
  available: true,
84606
85720
  mode: "controlled production (protocol-tested; no OS/network sandbox)",
84607
- description: "Publishes frozen GitHub/npm artifacts and runs configured Claude/Codex/Kimi consumer checkpoints with approval and exact digest confirmation"
85721
+ description: "Publishes frozen GitHub/npm artifacts and runs configured Claude/Codex/Kimi/CodeBuddy consumer checkpoints (CodeBuddy via human attestation closed loop) with approval and exact digest confirmation"
84608
85722
  },
84609
85723
  reconcile: {
84610
85724
  available: true,
@@ -84614,7 +85728,7 @@ function getCapabilityMaturity() {
84614
85728
  verify: {
84615
85729
  available: true,
84616
85730
  mode: "fresh consumer verification (protocol-tested; no OS/network sandbox)",
84617
- description: "Recheck remote state, exact npm installation, CLI help, and configured Claude/Codex/Kimi installs before VERIFIED"
85731
+ description: "Recheck remote state, exact npm installation, CLI help, and configured Claude/Codex/Kimi/CodeBuddy installs (CodeBuddy via human attestation) before VERIFIED"
84618
85732
  }
84619
85733
  };
84620
85734
  }
@@ -84690,7 +85804,7 @@ if (!command && (args.includes("--version") || args.includes("-v"))) {
84690
85804
  } else {
84691
85805
  const { readFileSync: readFileSync5 } = await import("node:fs");
84692
85806
  const { fileURLToPath: fileURLToPath3 } = await import("node:url");
84693
- const pkgPath = join24(dirname14(fileURLToPath3(import.meta.url)), "..", "package.json");
85807
+ const pkgPath = join25(dirname14(fileURLToPath3(import.meta.url)), "..", "package.json");
84694
85808
  pkg = JSON.parse(readFileSync5(pkgPath, "utf8"));
84695
85809
  }
84696
85810
  if (hasJson) {
@@ -84739,7 +85853,8 @@ if (!command || command === "help") {
84739
85853
  conditionalConsumers: {
84740
85854
  claude: "\u58F0\u660E claude-plugin distribution \u65F6\u5FC5\u987B\u53EF\u7528",
84741
85855
  codex: "\u58F0\u660E codex-plugin distribution \u65F6\u5FC5\u987B\u53EF\u7528",
84742
- kimi: "\u58F0\u660E kimi-plugin distribution \u65F6\u5FC5\u987B\u53EF\u7528"
85856
+ kimi: "\u58F0\u660E kimi-plugin distribution \u65F6\u5FC5\u987B\u53EF\u7528",
85857
+ codebuddy: "\u58F0\u660E codebuddy-plugin distribution \u65F6\u7528\u4E8E\u4EBA\u5DE5 attestation \u95ED\u73AF\uFF08CLI \u65E0\u6CD5\u9489\u6B7B\u51BB\u7ED3 ref\uFF0C\u5B89\u88C5\u7531\u4EBA\u5DE5\u5B8C\u6210\u5E76\u51FA\u5177 attestation\uFF09"
84743
85858
  }
84744
85859
  }
84745
85860
  },
@@ -84751,9 +85866,9 @@ if (!command || command === "help") {
84751
85866
  prepare: "offline local writes; configured hooks/gates require their explicit side-effect acknowledgements",
84752
85867
  docs: "read-only dry-run by default; write requires --write, exact --confirm-refresh, and --ack-local-document-write; never commits, pushes, or publishes",
84753
85868
  onlinePrepare: "previous-public-baseline observation available; production mode freezes publish artifacts and fails closed on drift or unknown state",
84754
- publish: "GitHub/npm plus configured Claude/Codex/Kimi consumer checkpoints are protocol-tested without an OS/network sandbox; approval and exact digest confirmation required",
85869
+ publish: "GitHub/npm plus configured Claude/Codex/Kimi/CodeBuddy consumer checkpoints are protocol-tested without an OS/network sandbox (CodeBuddy via human attestation closed loop); approval and exact digest confirmation required",
84755
85870
  reconcile: "PARTIAL recovery is protocol-tested without an OS/network sandbox; remote conflicts require human intervention",
84756
- verify: "fresh exact npm and Claude/Codex/Kimi consumer installation checks are protocol-tested without an OS/network sandbox; configured consumer processes require explicit acknowledgement; success reaches VERIFIED"
85871
+ verify: "fresh exact npm and Claude/Codex/Kimi/CodeBuddy consumer installation checks are protocol-tested without an OS/network sandbox (CodeBuddy via human attestation); configured consumer processes require explicit acknowledgement; success reaches VERIFIED"
84757
85872
  },
84758
85873
  recommendations: []
84759
85874
  };
@@ -84783,6 +85898,9 @@ if (!command || command === "help") {
84783
85898
  if (!checks.kimi.available) {
84784
85899
  output.recommendations.push("Install Kimi Code CLI before releasing a configured kimi-plugin distribution");
84785
85900
  }
85901
+ if (!checks.codebuddy.available) {
85902
+ output.recommendations.push("Install WorkBuddy (bundled codebuddy CLI) before releasing a configured codebuddy-plugin distribution; the install is a manual attestation closed loop because the CLI cannot pin a frozen ref");
85903
+ }
84786
85904
  console.log(JSON.stringify(output, null, 2));
84787
85905
  process.exit(readiness.status === "READY" ? 0 : 1);
84788
85906
  } else {
@@ -84807,7 +85925,7 @@ if (!COMMANDS.has(command)) {
84807
85925
  if (command === "setup") {
84808
85926
  const rootIdx = args.indexOf("--root");
84809
85927
  const rawRoot = rootIdx !== -1 && args[rootIdx + 1] ? args[rootIdx + 1] : process.cwd();
84810
- const root = resolve23(rawRoot);
85928
+ const root = resolve24(rawRoot);
84811
85929
  const answersIdx = args.indexOf("--answers");
84812
85930
  const answersPath = answersIdx !== -1 && args[answersIdx + 1] ? args[answersIdx + 1] : void 0;
84813
85931
  const confirmationIdx = args.indexOf("--confirm-setup");
@@ -84842,7 +85960,7 @@ if (command === "setup") {
84842
85960
  if (command === "assess") {
84843
85961
  const rootIdx = args.indexOf("--root");
84844
85962
  const rawRoot = rootIdx !== -1 && args[rootIdx + 1] ? args[rootIdx + 1] : process.cwd();
84845
- const root = resolve23(rawRoot);
85963
+ const root = resolve24(rawRoot);
84846
85964
  const offline = args.includes("--offline") || !args.includes("--online");
84847
85965
  const outputIdx = args.indexOf("--output");
84848
85966
  const output = outputIdx !== -1 && args[outputIdx + 1] ? args[outputIdx + 1] : void 0;
@@ -84873,7 +85991,7 @@ if (command === "assess") {
84873
85991
  if (command === "prepare") {
84874
85992
  const rootIdx = args.indexOf("--root");
84875
85993
  const rawRoot = rootIdx !== -1 && args[rootIdx + 1] ? args[rootIdx + 1] : process.cwd();
84876
- const root = resolve23(rawRoot);
85994
+ const root = resolve24(rawRoot);
84877
85995
  const offline = args.includes("--offline") || !args.includes("--online");
84878
85996
  let targetVersion;
84879
85997
  for (const flag of ["--target-version", "--version"]) {
@@ -84888,9 +86006,9 @@ if (command === "prepare") {
84888
86006
  const hookCache = !args.includes("--no-hook-cache");
84889
86007
  const production = args.includes("--production");
84890
86008
  const outputIdx = args.indexOf("--output");
84891
- const output = outputIdx !== -1 && args[outputIdx + 1] ? resolve23(args[outputIdx + 1]) : void 0;
86009
+ const output = outputIdx !== -1 && args[outputIdx + 1] ? resolve24(args[outputIdx + 1]) : void 0;
84892
86010
  const runDirIdx = args.indexOf("--run-dir");
84893
- const runDir = runDirIdx !== -1 && args[runDirIdx + 1] ? resolve23(args[runDirIdx + 1]) : void 0;
86011
+ const runDir = runDirIdx !== -1 && args[runDirIdx + 1] ? resolve24(args[runDirIdx + 1]) : void 0;
84894
86012
  try {
84895
86013
  const { prepareRelease: prepareRelease2 } = await init_prepare().then(() => prepare_exports);
84896
86014
  const { readFile: readFileFs } = await import("node:fs/promises");
@@ -84943,7 +86061,7 @@ if (command === "approve") {
84943
86061
  const actorIdx = args.indexOf("--actor");
84944
86062
  const actor = actorIdx !== -1 && args[actorIdx + 1] ? args[actorIdx + 1] : void 0;
84945
86063
  const outputIdx = args.indexOf("--output");
84946
- const outputPath = outputIdx !== -1 && args[outputIdx + 1] ? resolve23(args[outputIdx + 1]) : void 0;
86064
+ const outputPath = outputIdx !== -1 && args[outputIdx + 1] ? resolve24(args[outputIdx + 1]) : void 0;
84947
86065
  if (!planPath || !expectedDigest || !actor) {
84948
86066
  const msg = "approve requires --plan <path>, --digest <sha256>, and --actor <name>";
84949
86067
  if (hasJson) {
@@ -84955,10 +86073,10 @@ if (command === "approve") {
84955
86073
  }
84956
86074
  try {
84957
86075
  const { approvePlan: approvePlan2 } = await init_approve().then(() => approve_exports);
84958
- const resolvedPlanPath = resolve23(planPath);
86076
+ const resolvedPlanPath = resolve24(planPath);
84959
86077
  const planDir = dirname14(resolvedPlanPath);
84960
86078
  const releaseDir = basename9(planDir) === "plans" && basename9(resolvedPlanPath) === `${expectedDigest}.json` ? dirname14(planDir) : planDir;
84961
- const approvalPath = outputPath ?? join24(releaseDir, "approval-record.json");
86079
+ const approvalPath = outputPath ?? join25(releaseDir, "approval-record.json");
84962
86080
  const record = await approvePlan2({ planPath, expectedDigest, actor, outputPath: approvalPath });
84963
86081
  if (hasJson) {
84964
86082
  console.log(JSON.stringify(record, null, 2));
@@ -84985,13 +86103,13 @@ if (command === "approve") {
84985
86103
  if (command === "reconcile") {
84986
86104
  const rootIdx = args.indexOf("--root");
84987
86105
  const rawRoot = rootIdx !== -1 && args[rootIdx + 1] ? args[rootIdx + 1] : process.cwd();
84988
- const root = resolve23(rawRoot);
86106
+ const root = resolve24(rawRoot);
84989
86107
  const planIdx = args.indexOf("--plan");
84990
- const planPath = planIdx !== -1 && args[planIdx + 1] ? resolve23(args[planIdx + 1]) : void 0;
86108
+ const planPath = planIdx !== -1 && args[planIdx + 1] ? resolve24(args[planIdx + 1]) : void 0;
84991
86109
  const runIdx = args.indexOf("--run");
84992
- const runPath = runIdx !== -1 && args[runIdx + 1] ? resolve23(args[runIdx + 1]) : void 0;
86110
+ const runPath = runIdx !== -1 && args[runIdx + 1] ? resolve24(args[runIdx + 1]) : void 0;
84993
86111
  const approvalIdx = args.indexOf("--approval");
84994
- const approvalPath = approvalIdx !== -1 && args[approvalIdx + 1] ? resolve23(args[approvalIdx + 1]) : void 0;
86112
+ const approvalPath = approvalIdx !== -1 && args[approvalIdx + 1] ? resolve24(args[approvalIdx + 1]) : void 0;
84995
86113
  const confirmationIdx = args.indexOf("--confirm-production");
84996
86114
  const productionConfirmation = confirmationIdx !== -1 && args[confirmationIdx + 1] ? args[confirmationIdx + 1] : void 0;
84997
86115
  if (!planPath || !runPath) {
@@ -85050,11 +86168,11 @@ if (command === "reconcile") {
85050
86168
  if (command === "verify") {
85051
86169
  const rootIdx = args.indexOf("--root");
85052
86170
  const rawRoot = rootIdx !== -1 && args[rootIdx + 1] ? args[rootIdx + 1] : process.cwd();
85053
- const root = resolve23(rawRoot);
86171
+ const root = resolve24(rawRoot);
85054
86172
  const planIdx = args.indexOf("--plan");
85055
- const planPath = planIdx !== -1 && args[planIdx + 1] ? resolve23(args[planIdx + 1]) : void 0;
86173
+ const planPath = planIdx !== -1 && args[planIdx + 1] ? resolve24(args[planIdx + 1]) : void 0;
85056
86174
  const runIdx = args.indexOf("--run");
85057
- const runPath = runIdx !== -1 && args[runIdx + 1] ? resolve23(args[runIdx + 1]) : void 0;
86175
+ const runPath = runIdx !== -1 && args[runIdx + 1] ? resolve24(args[runIdx + 1]) : void 0;
85058
86176
  const verificationGatesAuthorized = args.includes("--acknowledge-gate-side-effects");
85059
86177
  if (!planPath || !runPath) {
85060
86178
  const msg = "verify requires --plan <path> and --run <path>";
@@ -85110,11 +86228,11 @@ if (command === "verify") {
85110
86228
  if (command === "publish") {
85111
86229
  const rootIdx = args.indexOf("--root");
85112
86230
  const rawRoot = rootIdx !== -1 && args[rootIdx + 1] ? args[rootIdx + 1] : process.cwd();
85113
- const root = resolve23(rawRoot);
86231
+ const root = resolve24(rawRoot);
85114
86232
  const planIdx = args.indexOf("--plan");
85115
- const planPath = planIdx !== -1 && args[planIdx + 1] ? resolve23(args[planIdx + 1]) : void 0;
86233
+ const planPath = planIdx !== -1 && args[planIdx + 1] ? resolve24(args[planIdx + 1]) : void 0;
85116
86234
  const approvalIdx = args.indexOf("--approval");
85117
- const approvalPath = approvalIdx !== -1 && args[approvalIdx + 1] ? resolve23(args[approvalIdx + 1]) : void 0;
86235
+ const approvalPath = approvalIdx !== -1 && args[approvalIdx + 1] ? resolve24(args[approvalIdx + 1]) : void 0;
85118
86236
  const confirmationIdx = args.indexOf("--confirm-production");
85119
86237
  const productionConfirmation = confirmationIdx !== -1 && args[confirmationIdx + 1] ? args[confirmationIdx + 1] : void 0;
85120
86238
  if (!planPath || !approvalPath || !productionConfirmation) {
@@ -85173,9 +86291,9 @@ if (command === "publish") {
85173
86291
  if (command === "artifacts") {
85174
86292
  const rootIdx = args.indexOf("--root");
85175
86293
  const rawRoot = rootIdx !== -1 && args[rootIdx + 1] ? args[rootIdx + 1] : process.cwd();
85176
- const root = resolve23(rawRoot);
86294
+ const root = resolve24(rawRoot);
85177
86295
  const outputIdx = args.indexOf("--output");
85178
- const output = outputIdx !== -1 && args[outputIdx + 1] ? resolve23(args[outputIdx + 1]) : void 0;
86296
+ const output = outputIdx !== -1 && args[outputIdx + 1] ? resolve24(args[outputIdx + 1]) : void 0;
85179
86297
  const subcommand = positional[1] ?? "status";
85180
86298
  try {
85181
86299
  const { runArtifactsCommand: runArtifactsCommand2 } = await Promise.resolve().then(() => (init_artifacts(), artifacts_exports));
@@ -85242,7 +86360,7 @@ if (command === "docs") {
85242
86360
  );
85243
86361
  }
85244
86362
  }
85245
- const root = resolve23(rawRoot);
86363
+ const root = resolve24(rawRoot);
85246
86364
  const valuedDocsFlags = /* @__PURE__ */ new Set(["--root", "--unit", "--confirm-refresh"]);
85247
86365
  const booleanDocsFlags = /* @__PURE__ */ new Set(["--json", "--write", "--ack-local-document-write"]);
85248
86366
  let docsSubcommand;