release-skill 0.2.4 → 0.2.5

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 (40) 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 +24 -0
  7. package/INSTALL.md +4 -4
  8. package/INSTALL.zh-CN.md +4 -4
  9. package/README.md +16 -14
  10. package/README.zh-CN.md +16 -14
  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 +1375 -607
  14. package/adapters/claude/schemas/release-plan.schema.json +91 -0
  15. package/adapters/claude/schemas/release-run.schema.json +85 -0
  16. package/adapters/codex/.codex-plugin/plugin.json +2 -2
  17. package/adapters/codex/bin/release-skill.bundle.mjs +1375 -607
  18. package/adapters/codex/schemas/release-plan.schema.json +91 -0
  19. package/adapters/codex/schemas/release-run.schema.json +85 -0
  20. package/adapters/kimi/.kimi-plugin/plugin.json +1 -1
  21. package/adapters/kimi/bin/release-skill.bundle.mjs +1375 -607
  22. package/adapters/kimi/schemas/release-plan.schema.json +91 -0
  23. package/adapters/kimi/schemas/release-run.schema.json +85 -0
  24. package/adapters/workbuddy/.codebuddy-plugin/plugin.json +1 -1
  25. package/adapters/workbuddy/bin/release-skill.bundle.mjs +1375 -607
  26. package/adapters/workbuddy/schemas/release-plan.schema.json +91 -0
  27. package/adapters/workbuddy/schemas/release-run.schema.json +85 -0
  28. package/bin/release-skill.bundle.mjs +1375 -607
  29. package/package.json +1 -1
  30. package/schemas/release-plan.schema.json +91 -0
  31. package/schemas/release-run.schema.json +85 -0
  32. package/scripts/sync-public-files.mjs +20 -9
  33. package/src/adapters/plugin-marketplace.mjs +82 -3
  34. package/src/commands/prepare.mjs +74 -0
  35. package/src/commands/publish.mjs +62 -0
  36. package/src/commands/verify.mjs +151 -1
  37. package/src/core/plan.mjs +29 -0
  38. package/src/core/skill-resource-closure.mjs +425 -0
  39. package/src/platforms/codebuddy.mjs +16 -3
  40. package/src/platforms/kimi.mjs +36 -9
@@ -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.4"});
12
+ const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.2.5"});
13
13
 
14
14
  var __create = Object.create;
15
15
  var __defProp = Object.defineProperty;
@@ -4407,10 +4407,10 @@ var require_resolve_block_map = __commonJS({
4407
4407
  let offset = bm.offset;
4408
4408
  let commentEnd = null;
4409
4409
  for (const collItem of bm.items) {
4410
- const { start, key, sep: sep4, value } = collItem;
4410
+ const { start, key, sep: sep5, value } = collItem;
4411
4411
  const keyProps = resolveProps.resolveProps(start, {
4412
4412
  indicator: "explicit-key-ind",
4413
- next: key ?? sep4?.[0],
4413
+ next: key ?? sep5?.[0],
4414
4414
  offset,
4415
4415
  onError,
4416
4416
  parentIndent: bm.indent,
@@ -4424,7 +4424,7 @@ var require_resolve_block_map = __commonJS({
4424
4424
  else if ("indent" in key && key.indent !== bm.indent)
4425
4425
  onError(offset, "BAD_INDENT", startColMsg);
4426
4426
  }
4427
- if (!keyProps.anchor && !keyProps.tag && !sep4) {
4427
+ if (!keyProps.anchor && !keyProps.tag && !sep5) {
4428
4428
  commentEnd = keyProps.end;
4429
4429
  if (keyProps.comment) {
4430
4430
  if (map.comment)
@@ -4448,7 +4448,7 @@ var require_resolve_block_map = __commonJS({
4448
4448
  ctx.atKey = false;
4449
4449
  if (utilMapIncludes.mapIncludes(ctx, map.items, keyNode))
4450
4450
  onError(keyStart, "DUPLICATE_KEY", "Map keys must be unique");
4451
- const valueProps = resolveProps.resolveProps(sep4 ?? [], {
4451
+ const valueProps = resolveProps.resolveProps(sep5 ?? [], {
4452
4452
  indicator: "map-value-ind",
4453
4453
  next: value,
4454
4454
  offset: keyNode.range[2],
@@ -4464,7 +4464,7 @@ var require_resolve_block_map = __commonJS({
4464
4464
  if (ctx.options.strict && keyProps.start < valueProps.found.offset - 1024)
4465
4465
  onError(keyNode.range, "KEY_OVER_1024_CHARS", "The : indicator must be at most 1024 chars after the start of an implicit block mapping key");
4466
4466
  }
4467
- const valueNode = value ? composeNode(ctx, value, valueProps, onError) : composeEmptyNode(ctx, offset, sep4, null, valueProps, onError);
4467
+ const valueNode = value ? composeNode(ctx, value, valueProps, onError) : composeEmptyNode(ctx, offset, sep5, null, valueProps, onError);
4468
4468
  if (ctx.schema.compat)
4469
4469
  utilFlowIndentCheck.flowIndentCheck(bm.indent, value, onError);
4470
4470
  offset = valueNode.range[2];
@@ -4557,7 +4557,7 @@ var require_resolve_end = __commonJS({
4557
4557
  let comment = "";
4558
4558
  if (end) {
4559
4559
  let hasSpace = false;
4560
- let sep4 = "";
4560
+ let sep5 = "";
4561
4561
  for (const token of end) {
4562
4562
  const { source, type } = token;
4563
4563
  switch (type) {
@@ -4571,13 +4571,13 @@ var require_resolve_end = __commonJS({
4571
4571
  if (!comment)
4572
4572
  comment = cb;
4573
4573
  else
4574
- comment += sep4 + cb;
4575
- sep4 = "";
4574
+ comment += sep5 + cb;
4575
+ sep5 = "";
4576
4576
  break;
4577
4577
  }
4578
4578
  case "newline":
4579
4579
  if (comment)
4580
- sep4 += source;
4580
+ sep5 += source;
4581
4581
  hasSpace = true;
4582
4582
  break;
4583
4583
  default:
@@ -4621,18 +4621,18 @@ var require_resolve_flow_collection = __commonJS({
4621
4621
  let offset = fc.offset + fc.start.source.length;
4622
4622
  for (let i = 0; i < fc.items.length; ++i) {
4623
4623
  const collItem = fc.items[i];
4624
- const { start, key, sep: sep4, value } = collItem;
4624
+ const { start, key, sep: sep5, value } = collItem;
4625
4625
  const props = resolveProps.resolveProps(start, {
4626
4626
  flow: fcName,
4627
4627
  indicator: "explicit-key-ind",
4628
- next: key ?? sep4?.[0],
4628
+ next: key ?? sep5?.[0],
4629
4629
  offset,
4630
4630
  onError,
4631
4631
  parentIndent: fc.indent,
4632
4632
  startOnNewline: false
4633
4633
  });
4634
4634
  if (!props.found) {
4635
- if (!props.anchor && !props.tag && !sep4 && !value) {
4635
+ if (!props.anchor && !props.tag && !sep5 && !value) {
4636
4636
  if (i === 0 && props.comma)
4637
4637
  onError(props.comma, "UNEXPECTED_TOKEN", `Unexpected , in ${fcName}`);
4638
4638
  else if (i < fc.items.length - 1)
@@ -4686,8 +4686,8 @@ var require_resolve_flow_collection = __commonJS({
4686
4686
  }
4687
4687
  }
4688
4688
  }
4689
- if (!isMap && !sep4 && !props.found) {
4690
- const valueNode = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end, sep4, null, props, onError);
4689
+ if (!isMap && !sep5 && !props.found) {
4690
+ const valueNode = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end, sep5, null, props, onError);
4691
4691
  coll.items.push(valueNode);
4692
4692
  offset = valueNode.range[2];
4693
4693
  if (isBlock(value))
@@ -4699,7 +4699,7 @@ var require_resolve_flow_collection = __commonJS({
4699
4699
  if (isBlock(key))
4700
4700
  onError(keyNode.range, "BLOCK_IN_FLOW", blockMsg);
4701
4701
  ctx.atKey = false;
4702
- const valueProps = resolveProps.resolveProps(sep4 ?? [], {
4702
+ const valueProps = resolveProps.resolveProps(sep5 ?? [], {
4703
4703
  flow: fcName,
4704
4704
  indicator: "map-value-ind",
4705
4705
  next: value,
@@ -4710,8 +4710,8 @@ var require_resolve_flow_collection = __commonJS({
4710
4710
  });
4711
4711
  if (valueProps.found) {
4712
4712
  if (!isMap && !props.found && ctx.options.strict) {
4713
- if (sep4)
4714
- for (const st of sep4) {
4713
+ if (sep5)
4714
+ for (const st of sep5) {
4715
4715
  if (st === valueProps.found)
4716
4716
  break;
4717
4717
  if (st.type === "newline") {
@@ -4728,7 +4728,7 @@ var require_resolve_flow_collection = __commonJS({
4728
4728
  else
4729
4729
  onError(valueProps.start, "MISSING_CHAR", `Missing , or : between ${fcName} items`);
4730
4730
  }
4731
- const valueNode = value ? composeNode(ctx, value, valueProps, onError) : valueProps.found ? composeEmptyNode(ctx, valueProps.end, sep4, null, valueProps, onError) : null;
4731
+ const valueNode = value ? composeNode(ctx, value, valueProps, onError) : valueProps.found ? composeEmptyNode(ctx, valueProps.end, sep5, null, valueProps, onError) : null;
4732
4732
  if (valueNode) {
4733
4733
  if (isBlock(value))
4734
4734
  onError(valueNode.range, "BLOCK_IN_FLOW", blockMsg);
@@ -4911,7 +4911,7 @@ var require_resolve_block_scalar = __commonJS({
4911
4911
  chompStart = i + 1;
4912
4912
  }
4913
4913
  let value = "";
4914
- let sep4 = "";
4914
+ let sep5 = "";
4915
4915
  let prevMoreIndented = false;
4916
4916
  for (let i = 0; i < contentStart; ++i)
4917
4917
  value += lines[i][0].slice(trimIndent) + "\n";
@@ -4928,24 +4928,24 @@ var require_resolve_block_scalar = __commonJS({
4928
4928
  indent = "";
4929
4929
  }
4930
4930
  if (type === Scalar.Scalar.BLOCK_LITERAL) {
4931
- value += sep4 + indent.slice(trimIndent) + content;
4932
- sep4 = "\n";
4931
+ value += sep5 + indent.slice(trimIndent) + content;
4932
+ sep5 = "\n";
4933
4933
  } else if (indent.length > trimIndent || content[0] === " ") {
4934
- if (sep4 === " ")
4935
- sep4 = "\n";
4936
- else if (!prevMoreIndented && sep4 === "\n")
4937
- sep4 = "\n\n";
4938
- value += sep4 + indent.slice(trimIndent) + content;
4939
- sep4 = "\n";
4934
+ if (sep5 === " ")
4935
+ sep5 = "\n";
4936
+ else if (!prevMoreIndented && sep5 === "\n")
4937
+ sep5 = "\n\n";
4938
+ value += sep5 + indent.slice(trimIndent) + content;
4939
+ sep5 = "\n";
4940
4940
  prevMoreIndented = true;
4941
4941
  } else if (content === "") {
4942
- if (sep4 === "\n")
4942
+ if (sep5 === "\n")
4943
4943
  value += "\n";
4944
4944
  else
4945
- sep4 = "\n";
4945
+ sep5 = "\n";
4946
4946
  } else {
4947
- value += sep4 + content;
4948
- sep4 = " ";
4947
+ value += sep5 + content;
4948
+ sep5 = " ";
4949
4949
  prevMoreIndented = false;
4950
4950
  }
4951
4951
  }
@@ -5133,25 +5133,25 @@ var require_resolve_flow_scalar = __commonJS({
5133
5133
  if (!match)
5134
5134
  return source;
5135
5135
  let res = match[1];
5136
- let sep4 = " ";
5136
+ let sep5 = " ";
5137
5137
  let pos = first.lastIndex;
5138
5138
  line.lastIndex = pos;
5139
5139
  while (match = line.exec(source)) {
5140
5140
  if (match[1] === "") {
5141
- if (sep4 === "\n")
5142
- res += sep4;
5141
+ if (sep5 === "\n")
5142
+ res += sep5;
5143
5143
  else
5144
- sep4 = "\n";
5144
+ sep5 = "\n";
5145
5145
  } else {
5146
- res += sep4 + match[1];
5147
- sep4 = " ";
5146
+ res += sep5 + match[1];
5147
+ sep5 = " ";
5148
5148
  }
5149
5149
  pos = line.lastIndex;
5150
5150
  }
5151
5151
  const last = /[ \t]*(.*)/sy;
5152
5152
  last.lastIndex = pos;
5153
5153
  match = last.exec(source);
5154
- return res + sep4 + (match?.[1] ?? "");
5154
+ return res + sep5 + (match?.[1] ?? "");
5155
5155
  }
5156
5156
  __name(foldLines, "foldLines");
5157
5157
  function doubleQuotedValue(source, onError) {
@@ -5985,14 +5985,14 @@ var require_cst_stringify = __commonJS({
5985
5985
  }
5986
5986
  }
5987
5987
  __name(stringifyToken, "stringifyToken");
5988
- function stringifyItem({ start, key, sep: sep4, value }) {
5988
+ function stringifyItem({ start, key, sep: sep5, value }) {
5989
5989
  let res = "";
5990
5990
  for (const st of start)
5991
5991
  res += st.source;
5992
5992
  if (key)
5993
5993
  res += stringifyToken(key);
5994
- if (sep4)
5995
- for (const st of sep4)
5994
+ if (sep5)
5995
+ for (const st of sep5)
5996
5996
  res += st.source;
5997
5997
  if (value)
5998
5998
  res += stringifyToken(value);
@@ -7181,18 +7181,18 @@ var require_parser = __commonJS({
7181
7181
  if (this.type === "map-value-ind") {
7182
7182
  const prev = getPrevProps(this.peek(2));
7183
7183
  const start = getFirstKeyStartProps(prev);
7184
- let sep4;
7184
+ let sep5;
7185
7185
  if (scalar.end) {
7186
- sep4 = scalar.end;
7187
- sep4.push(this.sourceToken);
7186
+ sep5 = scalar.end;
7187
+ sep5.push(this.sourceToken);
7188
7188
  delete scalar.end;
7189
7189
  } else
7190
- sep4 = [this.sourceToken];
7190
+ sep5 = [this.sourceToken];
7191
7191
  const map = {
7192
7192
  type: "block-map",
7193
7193
  offset: scalar.offset,
7194
7194
  indent: scalar.indent,
7195
- items: [{ start, key: scalar, sep: sep4 }]
7195
+ items: [{ start, key: scalar, sep: sep5 }]
7196
7196
  };
7197
7197
  this.onKeyLine = true;
7198
7198
  this.stack[this.stack.length - 1] = map;
@@ -7345,15 +7345,15 @@ var require_parser = __commonJS({
7345
7345
  } else if (isFlowToken(it.key) && !includesToken(it.sep, "newline")) {
7346
7346
  const start2 = getFirstKeyStartProps(it.start);
7347
7347
  const key = it.key;
7348
- const sep4 = it.sep;
7349
- sep4.push(this.sourceToken);
7348
+ const sep5 = it.sep;
7349
+ sep5.push(this.sourceToken);
7350
7350
  delete it.key;
7351
7351
  delete it.sep;
7352
7352
  this.stack.push({
7353
7353
  type: "block-map",
7354
7354
  offset: this.offset,
7355
7355
  indent: this.indent,
7356
- items: [{ start: start2, key, sep: sep4 }]
7356
+ items: [{ start: start2, key, sep: sep5 }]
7357
7357
  });
7358
7358
  } else if (start.length > 0) {
7359
7359
  it.sep = it.sep.concat(start, this.sourceToken);
@@ -7547,13 +7547,13 @@ var require_parser = __commonJS({
7547
7547
  const prev = getPrevProps(parent);
7548
7548
  const start = getFirstKeyStartProps(prev);
7549
7549
  fixFlowSeqItems(fc);
7550
- const sep4 = fc.end.splice(1, fc.end.length);
7551
- sep4.push(this.sourceToken);
7550
+ const sep5 = fc.end.splice(1, fc.end.length);
7551
+ sep5.push(this.sourceToken);
7552
7552
  const map = {
7553
7553
  type: "block-map",
7554
7554
  offset: fc.offset,
7555
7555
  indent: fc.indent,
7556
- items: [{ start, key: fc, sep: sep4 }]
7556
+ items: [{ start, key: fc, sep: sep5 }]
7557
7557
  };
7558
7558
  this.onKeyLine = true;
7559
7559
  this.stack[this.stack.length - 1] = map;
@@ -11044,7 +11044,7 @@ var require_compile = __commonJS({
11044
11044
  const schOrFunc = root.refs[ref];
11045
11045
  if (schOrFunc)
11046
11046
  return schOrFunc;
11047
- let _sch = resolve26.call(this, root, ref);
11047
+ let _sch = resolve27.call(this, root, ref);
11048
11048
  if (_sch === void 0) {
11049
11049
  const schema2 = (_a = root.localRefs) === null || _a === void 0 ? void 0 : _a[ref];
11050
11050
  const { schemaId } = this.opts;
@@ -11075,13 +11075,13 @@ var require_compile = __commonJS({
11075
11075
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
11076
11076
  }
11077
11077
  __name(sameSchemaEnv, "sameSchemaEnv");
11078
- function resolve26(root, ref) {
11078
+ function resolve27(root, ref) {
11079
11079
  let sch;
11080
11080
  while (typeof (sch = this.refs[ref]) == "string")
11081
11081
  ref = sch;
11082
11082
  return sch || this.schemas[ref] || resolveSchema.call(this, root, ref);
11083
11083
  }
11084
- __name(resolve26, "resolve");
11084
+ __name(resolve27, "resolve");
11085
11085
  function resolveSchema(root, ref) {
11086
11086
  const p = this.opts.uriResolver.parse(ref);
11087
11087
  const refPath = (0, resolve_1._getFullPath)(this.opts.uriResolver, p);
@@ -11733,56 +11733,56 @@ var require_fast_uri = __commonJS({
11733
11733
  return uri;
11734
11734
  }
11735
11735
  __name(normalize4, "normalize");
11736
- function resolve26(baseURI, relativeURI, options) {
11736
+ function resolve27(baseURI, relativeURI, options) {
11737
11737
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
11738
11738
  const resolved = resolveComponent(parse2(baseURI, schemelessOptions), parse2(relativeURI, schemelessOptions), schemelessOptions, true);
11739
11739
  schemelessOptions.skipEscape = true;
11740
11740
  return serialize(resolved, schemelessOptions);
11741
11741
  }
11742
- __name(resolve26, "resolve");
11743
- function resolveComponent(base, relative23, options, skipNormalization) {
11742
+ __name(resolve27, "resolve");
11743
+ function resolveComponent(base, relative24, options, skipNormalization) {
11744
11744
  const target = {};
11745
11745
  if (!skipNormalization) {
11746
11746
  base = parse2(serialize(base, options), options);
11747
- relative23 = parse2(serialize(relative23, options), options);
11747
+ relative24 = parse2(serialize(relative24, options), options);
11748
11748
  }
11749
11749
  options = options || {};
11750
- if (!options.tolerant && relative23.scheme) {
11751
- target.scheme = relative23.scheme;
11752
- target.userinfo = relative23.userinfo;
11753
- target.host = relative23.host;
11754
- target.port = relative23.port;
11755
- target.path = removeDotSegments(relative23.path || "");
11756
- target.query = relative23.query;
11750
+ if (!options.tolerant && relative24.scheme) {
11751
+ target.scheme = relative24.scheme;
11752
+ target.userinfo = relative24.userinfo;
11753
+ target.host = relative24.host;
11754
+ target.port = relative24.port;
11755
+ target.path = removeDotSegments(relative24.path || "");
11756
+ target.query = relative24.query;
11757
11757
  } else {
11758
- if (relative23.userinfo !== void 0 || relative23.host !== void 0 || relative23.port !== void 0) {
11759
- target.userinfo = relative23.userinfo;
11760
- target.host = relative23.host;
11761
- target.port = relative23.port;
11762
- target.path = removeDotSegments(relative23.path || "");
11763
- target.query = relative23.query;
11758
+ if (relative24.userinfo !== void 0 || relative24.host !== void 0 || relative24.port !== void 0) {
11759
+ target.userinfo = relative24.userinfo;
11760
+ target.host = relative24.host;
11761
+ target.port = relative24.port;
11762
+ target.path = removeDotSegments(relative24.path || "");
11763
+ target.query = relative24.query;
11764
11764
  } else {
11765
- if (!relative23.path) {
11765
+ if (!relative24.path) {
11766
11766
  target.path = base.path;
11767
- if (relative23.query !== void 0) {
11768
- target.query = relative23.query;
11767
+ if (relative24.query !== void 0) {
11768
+ target.query = relative24.query;
11769
11769
  } else {
11770
11770
  target.query = base.query;
11771
11771
  }
11772
11772
  } else {
11773
- if (relative23.path[0] === "/") {
11774
- target.path = removeDotSegments(relative23.path);
11773
+ if (relative24.path[0] === "/") {
11774
+ target.path = removeDotSegments(relative24.path);
11775
11775
  } else {
11776
11776
  if ((base.userinfo !== void 0 || base.host !== void 0 || base.port !== void 0) && !base.path) {
11777
- target.path = "/" + relative23.path;
11777
+ target.path = "/" + relative24.path;
11778
11778
  } else if (!base.path) {
11779
- target.path = relative23.path;
11779
+ target.path = relative24.path;
11780
11780
  } else {
11781
- target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative23.path;
11781
+ target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative24.path;
11782
11782
  }
11783
11783
  target.path = removeDotSegments(target.path);
11784
11784
  }
11785
- target.query = relative23.query;
11785
+ target.query = relative24.query;
11786
11786
  }
11787
11787
  target.userinfo = base.userinfo;
11788
11788
  target.host = base.host;
@@ -11790,7 +11790,7 @@ var require_fast_uri = __commonJS({
11790
11790
  }
11791
11791
  target.scheme = base.scheme;
11792
11792
  }
11793
- target.fragment = relative23.fragment;
11793
+ target.fragment = relative24.fragment;
11794
11794
  return target;
11795
11795
  }
11796
11796
  __name(resolveComponent, "resolveComponent");
@@ -12001,7 +12001,7 @@ var require_fast_uri = __commonJS({
12001
12001
  var fastUri = {
12002
12002
  SCHEMES,
12003
12003
  normalize: normalize4,
12004
- resolve: resolve26,
12004
+ resolve: resolve27,
12005
12005
  resolveComponent,
12006
12006
  equal,
12007
12007
  serialize,
@@ -16156,6 +16156,31 @@ function validatePlan(plan) {
16156
16156
  );
16157
16157
  }
16158
16158
  }
16159
+ if (plan.skillResourceClosure) {
16160
+ const receipts = plan.skillResourceClosure.unitReceipts ?? [];
16161
+ const receiptUnitIds = receipts.map((item) => item.unitId);
16162
+ if (new Set(receiptUnitIds).size !== receiptUnitIds.length || JSON.stringify([...receiptUnitIds].sort()) !== JSON.stringify([...unitsById.keys()].sort())) {
16163
+ throw new ReleaseError(
16164
+ GATE_FAILED,
16165
+ "skill resource closure receipts must cover every release unit exactly once"
16166
+ );
16167
+ }
16168
+ const totals = {
16169
+ totalSkillCount: receipts.reduce((sum, item) => sum + item.skillCount, 0),
16170
+ totalReferenceCount: receipts.reduce((sum, item) => sum + item.referenceCount, 0),
16171
+ totalSourceOnlyCount: receipts.reduce((sum, item) => sum + item.sourceOnlyCount, 0),
16172
+ totalFindingCount: receipts.reduce((sum, item) => sum + item.findingCount, 0)
16173
+ };
16174
+ for (const [field, expected] of Object.entries(totals)) {
16175
+ if (plan.skillResourceClosure[field] !== expected) {
16176
+ throw new ReleaseError(
16177
+ GATE_FAILED,
16178
+ `skill resource closure ${field} does not match unit receipts`,
16179
+ { expected, observed: plan.skillResourceClosure[field] }
16180
+ );
16181
+ }
16182
+ }
16183
+ }
16159
16184
  }
16160
16185
  function stripRecordLayerV2(plan) {
16161
16186
  const {
@@ -17046,8 +17071,8 @@ function kimiAuthorityDir(context, planDigest, plugin) {
17046
17071
  const base = resolve4(context.root, ".release-skill", "kimi-attestations");
17047
17072
  const dir = resolve4(base, planDigest, plugin);
17048
17073
  const rel = relative2(base, dir);
17049
- const sep4 = process.platform === "win32" ? "\\" : "/";
17050
- if (rel === "" || rel === ".." || isAbsolute2(rel) || rel.startsWith(`..${sep4}`) || rel.split(sep4).some((segment) => segment === ".." || segment === "")) {
17074
+ const sep5 = process.platform === "win32" ? "\\" : "/";
17075
+ if (rel === "" || rel === ".." || isAbsolute2(rel) || rel.startsWith(`..${sep5}`) || rel.split(sep5).some((segment) => segment === ".." || segment === "")) {
17051
17076
  throw new Error("kimi attestation authority path escapes its base");
17052
17077
  }
17053
17078
  return dir;
@@ -17055,13 +17080,21 @@ function kimiAuthorityDir(context, planDigest, plugin) {
17055
17080
  function buildKimiInstallUrl(repo, ref) {
17056
17081
  return `https://github.com/${repo}/releases/tag/${ref}`;
17057
17082
  }
17058
- function buildKimiManualInstructions({ installUrl, plugin, version, ref, attestationDir }) {
17083
+ function buildKimiManualInstructions({
17084
+ installUrl,
17085
+ plugin,
17086
+ version,
17087
+ ref,
17088
+ attestationDir,
17089
+ requiresInstalledClosure,
17090
+ managedRoot
17091
+ }) {
17059
17092
  return [
17060
17093
  `Kimi Code \u6CA1\u6709\u53EF\u811A\u672C\u5316\u7684\u63D2\u4EF6\u5B89\u88C5\u547D\u4EE4\u884C\u5DE5\u5177\uFF1B\u5B89\u88C5\u662F\u624B\u52A8\u4EA4\u4E92\u6B65\u9AA4\u3002`,
17061
17094
  `1) publish \u5B8C\u6210\u6240\u6709\u8FDC\u7AEF\u5199\u5165\u540E\u8FDB\u5165 PUBLISHED \u72B6\u6001\uFF08\u81EA\u52A8\u5316 Git \u5206\u652F/\u6807\u7B7E\u3001npm \u548C GitHub Release \u5199\u5165\u5DF2\u5B8C\u6210\uFF09\u3002\u6B64 kimi \u68C0\u67E5\u70B9\u6807\u8BB0\u4E3A\u9700\u8981\u4EBA\u5DE5\u5B89\u88C5\u3002`,
17062
- `2) \u5728 Kimi Code \u4E2D\u8FD0\u884C: /plugins install ${installUrl}\uFF08\u9501\u5B9A\u5230\u51BB\u7ED3 ref "${ref}"\uFF0C\u7248\u672C ${version}\uFF09\u3002\u786E\u8BA4\u63D2\u4EF6 "${plugin}" \u7684\u4FE1\u4EFB\u63D0\u793A\uFF0C\u7136\u540E\u8FD0\u884C /plugins reload\uFF08\u6216 /new\uFF09\u3002`,
17095
+ `2) ${requiresInstalledClosure ? `\u4EE5 KIMI_CODE_HOME="${resolve4(managedRoot, "..", "..")}" \u542F\u52A8 Kimi Code\uFF0C\u7136\u540E` : "\u5728 Kimi Code \u4E2D"}\u8FD0\u884C: /plugins install ${installUrl}\uFF08\u9501\u5B9A\u5230\u51BB\u7ED3 ref "${ref}"\uFF0C\u7248\u672C ${version}\uFF09\u3002\u786E\u8BA4\u63D2\u4EF6 "${plugin}" \u7684\u4FE1\u4EFB\u63D0\u793A\uFF0C\u7136\u540E\u8FD0\u884C /plugins reload\uFF08\u6216 /new\uFF09\u3002`,
17063
17096
  `3) \u5C06\u4EBA\u5DE5\u7ED3\u679C JSON \u5199\u5165: ${attestationDir}/${KIMI_ATTESTATION_FILE}`,
17064
- ` \u5FC5\u586B\u5B57\u6BB5: platform="kimi", version, planDigest\uFF08\u51BB\u7ED3\u8BA1\u5212\u6458\u8981\uFF09, result("passed" \u6216 "failed"), actor\uFF08\u786E\u8BA4\u4EBA\uFF09, confirmedAt\uFF08ISO 8601 \u65F6\u95F4\u6233\uFF09`,
17097
+ ` \u5FC5\u586B\u5B57\u6BB5: platform="kimi", version, planDigest\uFF08\u51BB\u7ED3\u8BA1\u5212\u6458\u8981\uFF09, result("passed" \u6216 "failed"), actor\uFF08\u786E\u8BA4\u4EBA\uFF09, confirmedAt\uFF08ISO 8601 \u65F6\u95F4\u6233\uFF09${requiresInstalledClosure ? "\uFF0CinstallPath\uFF08\u5B9E\u9645\u5B89\u88C5\u540E\u7684\u63D2\u4EF6\u76EE\u5F55\uFF0C\u5FC5\u987B\u4F4D\u4E8E\u8BE5\u8BC1\u660E\u76EE\u5F55\u7684 kimi-home/plugins/managed/ \u5185\uFF09" : ""}`,
17065
17098
  ` \u53EF\u9009\u5B57\u6BB5: note\uFF08\u5907\u6CE8\uFF09`,
17066
17099
  `4) \u8FD0\u884C release-skill reconcile\uFF08\u5BF9\u8D26\u8FDC\u7AEF\u72B6\u6001\u5E76\u8DF3\u8FC7\u5DF2\u5B8C\u6210\u6B65\u9AA4\uFF09\uFF0C\u7136\u540E release-skill verify\uFF08\u4ECE\u540C\u4E00\u4E2A\u8BA1\u5212\u6458\u8981\u7D22\u5F15\u7684\u6743\u5A01\u76EE\u5F55\u8BFB\u53D6\u7ED3\u679C\uFF0C\u6210\u529F\u540E -> VERIFIED\uFF09\u3002`
17067
17100
  ];
@@ -17207,12 +17240,16 @@ async function executeKimiManualRequirement(action, context) {
17207
17240
  error: dirErr.message
17208
17241
  });
17209
17242
  }
17243
+ const requiresInstalledClosure = Boolean(context.plan?.skillResourceClosure);
17244
+ const managedRoot = requiresInstalledClosure ? resolve4(attestationDir, "kimi-home", "plugins", "managed") : null;
17210
17245
  const instructions = buildKimiManualInstructions({
17211
17246
  installUrl,
17212
17247
  plugin: action.plugin,
17213
17248
  version: action.version,
17214
17249
  ref,
17215
- attestationDir
17250
+ attestationDir,
17251
+ requiresInstalledClosure,
17252
+ managedRoot
17216
17253
  });
17217
17254
  const requirement = {
17218
17255
  kind: "kimi-manual-install-requirement",
@@ -17233,6 +17270,7 @@ async function executeKimiManualRequirement(action, context) {
17233
17270
  result: '<"passed" or "failed">',
17234
17271
  actor: "<person who confirmed the install>",
17235
17272
  confirmedAt: "<ISO 8601 timestamp>",
17273
+ ...requiresInstalledClosure ? { installPath: resolve4(managedRoot, action.plugin) } : {},
17236
17274
  note: "<optional note>"
17237
17275
  },
17238
17276
  instructions
@@ -17249,6 +17287,17 @@ async function executeKimiManualRequirement(action, context) {
17249
17287
  });
17250
17288
  }
17251
17289
  }
17290
+ if (requiresInstalledClosure) {
17291
+ try {
17292
+ await mkdir18(managedRoot, { recursive: true, mode: 448 });
17293
+ } catch (mkdirErr) {
17294
+ return createResult({
17295
+ actionType,
17296
+ status: ActionStatus.EXECUTE_FAILED,
17297
+ error: `cannot create kimi resource-closure managed root: ${mkdirErr.message}`
17298
+ });
17299
+ }
17300
+ }
17252
17301
  const requirementPath = resolve4(attestationDir, KIMI_REQUIREMENT_FILE);
17253
17302
  let existing = null;
17254
17303
  let requirementMissing = false;
@@ -17373,19 +17422,25 @@ function codebuddyAuthorityDir(context, planDigest, plugin) {
17373
17422
  const base = resolve5(context.root, ".release-skill", "codebuddy-attestations");
17374
17423
  const dir = resolve5(base, planDigest, plugin);
17375
17424
  const rel = relative3(base, dir);
17376
- const sep4 = process.platform === "win32" ? "\\" : "/";
17377
- if (rel === "" || rel === ".." || isAbsolute3(rel) || rel.startsWith(`..${sep4}`) || rel.split(sep4).some((segment) => segment === ".." || segment === "")) {
17425
+ const sep5 = process.platform === "win32" ? "\\" : "/";
17426
+ if (rel === "" || rel === ".." || isAbsolute3(rel) || rel.startsWith(`..${sep5}`) || rel.split(sep5).some((segment) => segment === ".." || segment === "")) {
17378
17427
  throw new Error("codebuddy attestation authority path escapes its base");
17379
17428
  }
17380
17429
  return dir;
17381
17430
  }
17382
- function buildCodeBuddyManualInstructions({ plugin, version, ref, attestationDir }) {
17431
+ function buildCodeBuddyManualInstructions({
17432
+ plugin,
17433
+ version,
17434
+ ref,
17435
+ attestationDir,
17436
+ requiresInstalledClosure
17437
+ }) {
17383
17438
  return [
17384
17439
  `CodeBuddy/WorkBuddy \u63D2\u4EF6\u5B89\u88C5\u65E0\u6CD5\u9501\u5B9A\u51BB\u7ED3 ref\uFF08codebuddy CLI marketplace add/install \u6CA1\u6709 ref \u9009\u9879\uFF0C\u8DDF\u8E2A\u9ED8\u8BA4\u5206\u652F\uFF09\uFF0C\u56E0\u6B64\u5B89\u88C5\u662F\u9700\u8981\u4EBA\u5DE5\u7ED3\u679C\u8BC1\u660E\u7684\u624B\u52A8\u6B65\u9AA4\u3002`,
17385
17440
  `1) publish \u5B8C\u6210\u6240\u6709\u8FDC\u7AEF\u5199\u5165\u540E\u8FDB\u5165 PUBLISHED \u72B6\u6001\uFF08\u81EA\u52A8\u5316 Git \u5206\u652F/\u6807\u7B7E\u3001npm \u548C GitHub Release \u5199\u5165\u5DF2\u5B8C\u6210\uFF09\u3002\u6B64 codebuddy \u68C0\u67E5\u70B9\u6807\u8BB0\u4E3A\u9700\u8981\u4EBA\u5DE5\u5B89\u88C5\u3002`,
17386
17441
  `2) \u4ECE\u7EDF\u4E00\u5E02\u573A "${CODEBUDDY_MARKETPLACE_NAME}" (${CODEBUDDY_MARKETPLACE_SOURCE}) \u5B89\u88C5 release-skill\u3002\u786E\u8BA4\u5B89\u88C5\u7684\u63D2\u4EF6\u7248\u672C\u7B49\u4E8E\u51BB\u7ED3\u7248\u672C ${version}\u3002`,
17387
17442
  `3) \u5C06\u4EBA\u5DE5\u7ED3\u679C JSON \u5199\u5165: ${attestationDir}/${CODEBUDDY_ATTESTATION_FILE}`,
17388
- ` \u5FC5\u586B\u5B57\u6BB5: platform="codebuddy", version, planDigest\uFF08\u51BB\u7ED3\u8BA1\u5212\u6458\u8981\uFF09, result("passed" \u6216 "failed"), actor\uFF08\u786E\u8BA4\u4EBA\uFF09, confirmedAt\uFF08ISO 8601 \u65F6\u95F4\u6233\uFF09`,
17443
+ ` \u5FC5\u586B\u5B57\u6BB5: platform="codebuddy", version, planDigest\uFF08\u51BB\u7ED3\u8BA1\u5212\u6458\u8981\uFF09, result("passed" \u6216 "failed"), actor\uFF08\u786E\u8BA4\u4EBA\uFF09, confirmedAt\uFF08ISO 8601 \u65F6\u95F4\u6233\uFF09${requiresInstalledClosure ? '\uFF0CinstallChannel("desktop" \u6216 "cli")\uFF0CinstallPath\uFF08\u5B9E\u9645\u5B89\u88C5\u540E\u7684\u63D2\u4EF6\u76EE\u5F55\uFF09' : ""}`,
17389
17444
  ` \u53EF\u9009\u5B57\u6BB5: note\uFF08\u5907\u6CE8\uFF09`,
17390
17445
  `4) \u8FD0\u884C release-skill verify\uFF08\u4ECE\u540C\u4E00\u4E2A\u8BA1\u5212\u6458\u8981\u7D22\u5F15\u7684\u6743\u5A01\u76EE\u5F55\u8BFB\u53D6\u7ED3\u679C\uFF0C\u6210\u529F\u540E -> VERIFIED\uFF09\u3002`
17391
17446
  ];
@@ -17559,7 +17614,8 @@ async function executeCodeBuddyManualRequirement(action, context) {
17559
17614
  plugin: action.plugin,
17560
17615
  version: action.version,
17561
17616
  ref,
17562
- attestationDir
17617
+ attestationDir,
17618
+ requiresInstalledClosure: Boolean(context.plan?.skillResourceClosure)
17563
17619
  });
17564
17620
  const requirement = {
17565
17621
  kind: "codebuddy-manual-install-requirement",
@@ -17579,6 +17635,10 @@ async function executeCodeBuddyManualRequirement(action, context) {
17579
17635
  result: '<"passed" or "failed">',
17580
17636
  actor: "<person who confirmed the install>",
17581
17637
  confirmedAt: "<ISO 8601 timestamp>",
17638
+ ...context.plan?.skillResourceClosure ? {
17639
+ installChannel: '<"desktop" or "cli">',
17640
+ installPath: `<actual .workbuddy/plugins/marketplaces/${CODEBUDDY_MARKETPLACE_NAME}/plugins/${action.plugin} directory>`
17641
+ } : {},
17582
17642
  note: "<optional note>"
17583
17643
  },
17584
17644
  instructions
@@ -17716,8 +17776,8 @@ function codexAuthorityDir(context, planDigest, plugin) {
17716
17776
  const base = resolve6(context.root, ".release-skill", "codex-attestations");
17717
17777
  const dir = resolve6(base, planDigest, plugin);
17718
17778
  const rel = relative4(base, dir);
17719
- const sep4 = process.platform === "win32" ? "\\" : "/";
17720
- if (rel === "" || rel === ".." || isAbsolute4(rel) || rel.startsWith(`..${sep4}`) || rel.split(sep4).some((segment) => segment === ".." || segment === "")) {
17779
+ const sep5 = process.platform === "win32" ? "\\" : "/";
17780
+ if (rel === "" || rel === ".." || isAbsolute4(rel) || rel.startsWith(`..${sep5}`) || rel.split(sep5).some((segment) => segment === ".." || segment === "")) {
17721
17781
  throw new Error("codex attestation authority path escapes its base");
17722
17782
  }
17723
17783
  return dir;
@@ -23157,10 +23217,406 @@ var init_evidence = __esm({
23157
23217
  }
23158
23218
  });
23159
23219
 
23220
+ // src/core/skill-resource-closure.mjs
23221
+ import { lstat as lstat8, readFile as readFile11, readdir as readdir6 } from "node:fs/promises";
23222
+ import { dirname as dirname6, isAbsolute as isAbsolute11, join as join11, relative as relative12, resolve as resolve15, sep as sep3 } from "node:path";
23223
+ function toPosix(value) {
23224
+ return value.replaceAll("\\", "/");
23225
+ }
23226
+ function relativeStable(root, target) {
23227
+ const value = toPosix(relative12(root, target));
23228
+ return value === "" ? "." : value;
23229
+ }
23230
+ function isInside3(parent, candidate) {
23231
+ const rel = relative12(parent, candidate);
23232
+ return rel === "" || !isAbsolute11(rel) && rel !== ".." && !rel.startsWith(`..${sep3}`);
23233
+ }
23234
+ async function discoverSkills(root, base = root) {
23235
+ const results = [];
23236
+ let entries;
23237
+ try {
23238
+ entries = await readdir6(root, { withFileTypes: true });
23239
+ } catch (error) {
23240
+ if (error.code === "ENOENT") return results;
23241
+ throw error;
23242
+ }
23243
+ for (const entry of entries) {
23244
+ if (entry.name === ".git" || entry.name === "node_modules") continue;
23245
+ const absolute = join11(root, entry.name);
23246
+ const stableRelative = toPosix(relative12(base, absolute));
23247
+ if (stableRelative === ".codex-plugin/migrated-command-skills") continue;
23248
+ if (entry.isDirectory()) {
23249
+ results.push(...await discoverSkills(absolute, base));
23250
+ } else if (entry.isFile() && entry.name === "SKILL.md") {
23251
+ results.push(stableRelative);
23252
+ }
23253
+ }
23254
+ return results.sort();
23255
+ }
23256
+ function resolvePluginRoot(skillRelativePath, scanRoot) {
23257
+ const parts = toPosix(skillRelativePath).split("/");
23258
+ const skillsIndex = parts.lastIndexOf("skills");
23259
+ if (skillsIndex < 0) return resolve15(scanRoot);
23260
+ return resolve15(scanRoot, ...parts.slice(0, skillsIndex));
23261
+ }
23262
+ function resolveSkillRoot(skillRelativePath, scanRoot) {
23263
+ return resolve15(scanRoot, dirname6(skillRelativePath));
23264
+ }
23265
+ function trimCandidate(value) {
23266
+ return value.trim().replace(/^["']/u, "").replace(/["']$/u, "").replace(/[.,;:]+$/u, "");
23267
+ }
23268
+ function isPathToken(value) {
23269
+ const token = trimCandidate(value);
23270
+ if (!token || GLOB_PATTERN.test(token)) return false;
23271
+ return BARE_PREFIXES.some((prefix) => token.startsWith(prefix)) || EXPLICIT_PREFIXES.some((prefix) => token.startsWith(prefix)) || SOURCE_TREE_PATTERN.test(token) || MACHINE_ABSOLUTE_PATTERN.test(token);
23272
+ }
23273
+ function scanSnippet(snippet, line, sourceOnly, results, seen) {
23274
+ const candidates = snippet.match(/(?:"[^"\n]+"|'[^'\n]+'|[^\s"'`()\[\],;]+)/gu) ?? [];
23275
+ for (const candidate of candidates) {
23276
+ const token = trimCandidate(candidate);
23277
+ if (!isPathToken(token)) continue;
23278
+ const key = `${line}:${token}`;
23279
+ if (seen.has(key)) continue;
23280
+ seen.add(key);
23281
+ results.push({ token, line, sourceOnly });
23282
+ }
23283
+ }
23284
+ function extractPathTokens(content) {
23285
+ const results = [];
23286
+ const seen = /* @__PURE__ */ new Set();
23287
+ const lines = content.split(/\r?\n/u);
23288
+ let inFence = false;
23289
+ for (let index = 0; index < lines.length; index += 1) {
23290
+ const line = lines[index];
23291
+ const lineNumber = index + 1;
23292
+ if (/^\s*```/u.test(line)) {
23293
+ inFence = !inFence;
23294
+ continue;
23295
+ }
23296
+ const sourceOnly = SOURCE_ONLY_MARKER.test(line);
23297
+ if (inFence) scanSnippet(line, lineNumber, sourceOnly, results, seen);
23298
+ for (const match of line.matchAll(/`([^`]+)`/gu)) {
23299
+ scanSnippet(match[1], lineNumber, sourceOnly, results, seen);
23300
+ }
23301
+ for (const match of line.matchAll(/\]\(([^)]+)\)/gu)) {
23302
+ const target = match[1].trim().split(/[?#]/u)[0];
23303
+ if (!/^(?:https?:|#)/iu.test(target)) {
23304
+ scanSnippet(target, lineNumber, sourceOnly, results, seen);
23305
+ }
23306
+ }
23307
+ }
23308
+ return results;
23309
+ }
23310
+ function stripExplicitPrefix(token) {
23311
+ for (const prefix of EXPLICIT_PREFIXES) {
23312
+ if (token.startsWith(prefix)) return token.slice(prefix.length);
23313
+ }
23314
+ return token;
23315
+ }
23316
+ function classifyReference(token, skillRoot, pluginRoot, scanRoot) {
23317
+ if (MACHINE_ABSOLUTE_PATTERN.test(token)) {
23318
+ return {
23319
+ classification: CLASSIFICATION.MACHINE_ABSOLUTE,
23320
+ resolutionRoot: "(machine)",
23321
+ resolvedTarget: token,
23322
+ absoluteTarget: token
23323
+ };
23324
+ }
23325
+ if (SOURCE_TREE_PATTERN.test(token)) {
23326
+ return {
23327
+ classification: CLASSIFICATION.SOURCE_BACKJUMP,
23328
+ resolutionRoot: "(source-tree)",
23329
+ resolvedTarget: token,
23330
+ absoluteTarget: resolve15(scanRoot, token)
23331
+ };
23332
+ }
23333
+ const explicit = EXPLICIT_PREFIXES.some((prefix) => token.startsWith(prefix));
23334
+ const resolutionRootAbsolute = explicit ? pluginRoot : skillRoot;
23335
+ const relativeTarget = explicit ? stripExplicitPrefix(token) : token;
23336
+ const absoluteTarget = resolve15(resolutionRootAbsolute, relativeTarget);
23337
+ const inBounds = isInside3(resolutionRootAbsolute, absoluteTarget);
23338
+ return {
23339
+ classification: inBounds ? explicit ? CLASSIFICATION.PLUGIN_ROOT : CLASSIFICATION.SKILL_LOCAL : CLASSIFICATION.OUT_OF_BOUNDS,
23340
+ resolutionRoot: relativeStable(scanRoot, resolutionRootAbsolute),
23341
+ resolvedTarget: relativeStable(scanRoot, absoluteTarget),
23342
+ absoluteTarget
23343
+ };
23344
+ }
23345
+ async function inspectRegularFile(root, target) {
23346
+ if (!isInside3(root, target)) return { code: FINDING_CODE.OUT_OF_BOUNDS };
23347
+ const parts = relative12(root, target).split(sep3).filter(Boolean);
23348
+ let current = root;
23349
+ const rootStat = await lstat8(root);
23350
+ if (rootStat.isSymbolicLink() || !rootStat.isDirectory()) {
23351
+ return { code: FINDING_CODE.SYMLINK_NOT_ALLOWED };
23352
+ }
23353
+ for (const part of parts) {
23354
+ current = join11(current, part);
23355
+ let stat9;
23356
+ try {
23357
+ stat9 = await lstat8(current);
23358
+ } catch (error) {
23359
+ if (error.code === "ENOENT") return { code: FINDING_CODE.RESOURCE_MISSING };
23360
+ throw error;
23361
+ }
23362
+ if (stat9.isSymbolicLink()) return { code: FINDING_CODE.SYMLINK_NOT_ALLOWED };
23363
+ }
23364
+ const targetStat = await lstat8(target);
23365
+ if (!targetStat.isFile() || targetStat.nlink !== 1) {
23366
+ return { code: FINDING_CODE.RESOURCE_NOT_REGULAR_FILE };
23367
+ }
23368
+ return { code: null };
23369
+ }
23370
+ function inferSurfaceHost(surfaceId, defaultHost) {
23371
+ const match = /^adapters\/([^/]+)$/u.exec(surfaceId);
23372
+ return match?.[1] ?? defaultHost;
23373
+ }
23374
+ function receiptProjection(result) {
23375
+ return {
23376
+ checkerVersion: result.checkerVersion,
23377
+ inputDigest: result.inputDigest,
23378
+ surfaces: result.surfaces,
23379
+ skillCount: result.skillCount,
23380
+ referenceCount: result.referenceCount,
23381
+ sourceOnlyCount: result.sourceOnlyCount,
23382
+ findingCount: result.findings.length
23383
+ };
23384
+ }
23385
+ function createSkillResourceClosureReceipt(result, identity = {}) {
23386
+ return {
23387
+ ...identity,
23388
+ checkerVersion: result.checkerVersion,
23389
+ inputDigest: result.inputDigest,
23390
+ surfaceCount: result.surfaces.length,
23391
+ skillCount: result.skillCount,
23392
+ referenceCount: result.referenceCount,
23393
+ sourceOnlyCount: result.sourceOnlyCount,
23394
+ findingCount: result.findings.length,
23395
+ receiptDigest: result.receiptDigest
23396
+ };
23397
+ }
23398
+ function assertSkillResourceClosureReceipt(expected, observed, label = "release unit") {
23399
+ if (canonicalJson(expected) !== canonicalJson(observed)) {
23400
+ throw new ReleaseError(
23401
+ GATE_FAILED,
23402
+ `skill resource closure receipt changed for ${label}`,
23403
+ { expected, observed }
23404
+ );
23405
+ }
23406
+ }
23407
+ function evaluateConsumerSkillResourceClosureReceipts(plan, receipts) {
23408
+ const supported = /* @__PURE__ */ new Set([
23409
+ "npm",
23410
+ "claude-plugin",
23411
+ "codex-plugin",
23412
+ "kimi-plugin",
23413
+ "codebuddy-plugin"
23414
+ ]);
23415
+ const expectedKeys = [];
23416
+ for (const unit of plan.units ?? []) {
23417
+ for (const distribution of unit.distributions ?? []) {
23418
+ if (supported.has(distribution.type)) {
23419
+ expectedKeys.push(`${unit.id}:${distribution.type}`);
23420
+ }
23421
+ }
23422
+ }
23423
+ const observedKeys = receipts.map((item) => `${item.unitId}:${item.distribution}`);
23424
+ return {
23425
+ passed: new Set(observedKeys).size === observedKeys.length && canonicalJson([...expectedKeys].sort()) === canonicalJson([...observedKeys].sort()),
23426
+ expectedKeys: expectedKeys.sort(),
23427
+ observedKeys: observedKeys.sort()
23428
+ };
23429
+ }
23430
+ async function checkSkillResourceClosure({
23431
+ snapshotDir,
23432
+ host = "root"
23433
+ } = {}) {
23434
+ if (typeof snapshotDir !== "string" || snapshotDir.length === 0) {
23435
+ throw new TypeError("snapshotDir must be a non-empty string");
23436
+ }
23437
+ const scanRoot = resolve15(snapshotDir);
23438
+ const scanStat = await lstat8(scanRoot);
23439
+ if (!scanStat.isDirectory() || scanStat.isSymbolicLink()) {
23440
+ throw new Error("snapshotDir must be a real directory");
23441
+ }
23442
+ let inputDigest;
23443
+ let snapshotError = null;
23444
+ try {
23445
+ inputDigest = (await computeFrozenSnapshot(scanRoot, {
23446
+ excludeRootEntries: TRANSPORT_EXCLUSIONS
23447
+ })).digest;
23448
+ } catch (error) {
23449
+ snapshotError = error;
23450
+ inputDigest = sha256Hex(canonicalJson({
23451
+ invalidTree: error.message
23452
+ }));
23453
+ }
23454
+ const skillPaths = await discoverSkills(scanRoot);
23455
+ const findings = [];
23456
+ const surfaceMap = /* @__PURE__ */ new Map();
23457
+ let referenceCount = 0;
23458
+ let sourceOnlyCount = 0;
23459
+ for (const skill of skillPaths) {
23460
+ const skillRoot = resolveSkillRoot(skill, scanRoot);
23461
+ const pluginRoot = resolvePluginRoot(skill, scanRoot);
23462
+ const surfaceId = relativeStable(scanRoot, pluginRoot);
23463
+ const surfaceHost = inferSurfaceHost(surfaceId, host);
23464
+ const surface = surfaceMap.get(surfaceId) ?? {
23465
+ id: surfaceId,
23466
+ host: surfaceHost,
23467
+ skillCount: 0,
23468
+ referenceCount: 0,
23469
+ sourceOnlyCount: 0
23470
+ };
23471
+ surface.skillCount += 1;
23472
+ surfaceMap.set(surfaceId, surface);
23473
+ const content = await readFile11(resolve15(scanRoot, skill), "utf8");
23474
+ for (const pathToken of extractPathTokens(content)) {
23475
+ referenceCount += 1;
23476
+ surface.referenceCount += 1;
23477
+ const classification = classifyReference(
23478
+ pathToken.token,
23479
+ skillRoot,
23480
+ pluginRoot,
23481
+ scanRoot
23482
+ );
23483
+ const findingBase = {
23484
+ host: surfaceHost,
23485
+ surface: surfaceId,
23486
+ skill,
23487
+ line: pathToken.line,
23488
+ reference: pathToken.token,
23489
+ classification: classification.classification,
23490
+ resolutionRoot: classification.resolutionRoot,
23491
+ resolvedTarget: classification.resolvedTarget
23492
+ };
23493
+ if (classification.classification === CLASSIFICATION.SOURCE_BACKJUMP) {
23494
+ if (pathToken.sourceOnly) {
23495
+ sourceOnlyCount += 1;
23496
+ surface.sourceOnlyCount += 1;
23497
+ } else {
23498
+ findings.push({ ...findingBase, code: FINDING_CODE.SOURCE_BACKJUMP });
23499
+ }
23500
+ continue;
23501
+ }
23502
+ if (classification.classification === CLASSIFICATION.MACHINE_ABSOLUTE) {
23503
+ findings.push({ ...findingBase, code: FINDING_CODE.MACHINE_ABSOLUTE_PATH });
23504
+ continue;
23505
+ }
23506
+ if (classification.classification === CLASSIFICATION.OUT_OF_BOUNDS) {
23507
+ findings.push({ ...findingBase, code: FINDING_CODE.OUT_OF_BOUNDS });
23508
+ continue;
23509
+ }
23510
+ const resolutionRootAbsolute = classification.classification === CLASSIFICATION.PLUGIN_ROOT ? pluginRoot : skillRoot;
23511
+ const inspection = await inspectRegularFile(
23512
+ resolutionRootAbsolute,
23513
+ classification.absoluteTarget
23514
+ );
23515
+ if (inspection.code) {
23516
+ if (pathToken.sourceOnly && inspection.code === FINDING_CODE.RESOURCE_MISSING) {
23517
+ sourceOnlyCount += 1;
23518
+ surface.sourceOnlyCount += 1;
23519
+ } else {
23520
+ findings.push({ ...findingBase, code: inspection.code });
23521
+ }
23522
+ }
23523
+ }
23524
+ }
23525
+ if (snapshotError) {
23526
+ findings.push({
23527
+ host,
23528
+ surface: ".",
23529
+ skill: null,
23530
+ line: null,
23531
+ reference: "(snapshot tree)",
23532
+ classification: CLASSIFICATION.OUT_OF_BOUNDS,
23533
+ resolutionRoot: ".",
23534
+ resolvedTarget: ".",
23535
+ code: FINDING_CODE.SNAPSHOT_UNSAFE,
23536
+ reason: snapshotError.message
23537
+ });
23538
+ }
23539
+ const surfaces = [...surfaceMap.values()].sort((a, b) => a.id.localeCompare(b.id));
23540
+ const result = {
23541
+ checkerVersion: CHECKER_VERSION,
23542
+ inputDigest,
23543
+ surfaces,
23544
+ skillCount: skillPaths.length,
23545
+ referenceCount,
23546
+ sourceOnlyCount,
23547
+ findings
23548
+ };
23549
+ result.receiptDigest = sha256Hex(canonicalJson(receiptProjection(result)));
23550
+ return result;
23551
+ }
23552
+ var CHECKER_VERSION, BARE_PREFIXES, EXPLICIT_PREFIXES, SOURCE_TREE_PATTERN, MACHINE_ABSOLUTE_PATTERN, GLOB_PATTERN, SOURCE_ONLY_MARKER, TRANSPORT_EXCLUSIONS, CLASSIFICATION, FINDING_CODE;
23553
+ var init_skill_resource_closure = __esm({
23554
+ "src/core/skill-resource-closure.mjs"() {
23555
+ init_digest();
23556
+ init_errors();
23557
+ init_frozen();
23558
+ CHECKER_VERSION = "skill-resource-closure-v1";
23559
+ BARE_PREFIXES = ["references/", "assets/", "schemas/", "examples/", "scripts/"];
23560
+ EXPLICIT_PREFIXES = [
23561
+ "<plugin-root>/",
23562
+ "<plugin_dir>/",
23563
+ "$PLUGIN_ROOT/",
23564
+ "${PLUGIN_ROOT}/",
23565
+ "${CLAUDE_PLUGIN_ROOT}/",
23566
+ "PLUGIN_ROOT/"
23567
+ ];
23568
+ SOURCE_TREE_PATTERN = /(?:^|\/)packages\/[A-Za-z0-9._-]+(?:\/|$)/u;
23569
+ MACHINE_ABSOLUTE_PATTERN = /^(?:\/(?:Users|home|root|tmp|var|etc|opt)(?:\/|$)|[A-Za-z]:[\\/])/u;
23570
+ GLOB_PATTERN = /[*?\[]/u;
23571
+ SOURCE_ONLY_MARKER = /(?:\bsource-only\b|仅源码包)/iu;
23572
+ TRANSPORT_EXCLUSIONS = Object.freeze([
23573
+ ".git",
23574
+ "node_modules",
23575
+ ".in_use",
23576
+ ".codex-plugin/migrated-command-skills"
23577
+ ]);
23578
+ CLASSIFICATION = Object.freeze({
23579
+ SKILL_LOCAL: "skill_local",
23580
+ PLUGIN_ROOT: "plugin_root",
23581
+ SOURCE_BACKJUMP: "source_backjump",
23582
+ MACHINE_ABSOLUTE: "machine_absolute",
23583
+ OUT_OF_BOUNDS: "out_of_bounds"
23584
+ });
23585
+ FINDING_CODE = Object.freeze({
23586
+ SNAPSHOT_UNSAFE: "SNAPSHOT_UNSAFE",
23587
+ RESOURCE_MISSING: "RESOURCE_MISSING",
23588
+ RESOURCE_NOT_REGULAR_FILE: "RESOURCE_NOT_REGULAR_FILE",
23589
+ SOURCE_BACKJUMP: "SOURCE_BACKJUMP",
23590
+ MACHINE_ABSOLUTE_PATH: "MACHINE_ABSOLUTE_PATH",
23591
+ OUT_OF_BOUNDS: "OUT_OF_BOUNDS",
23592
+ SYMLINK_NOT_ALLOWED: "SYMLINK_NOT_ALLOWED"
23593
+ });
23594
+ __name(toPosix, "toPosix");
23595
+ __name(relativeStable, "relativeStable");
23596
+ __name(isInside3, "isInside");
23597
+ __name(discoverSkills, "discoverSkills");
23598
+ __name(resolvePluginRoot, "resolvePluginRoot");
23599
+ __name(resolveSkillRoot, "resolveSkillRoot");
23600
+ __name(trimCandidate, "trimCandidate");
23601
+ __name(isPathToken, "isPathToken");
23602
+ __name(scanSnippet, "scanSnippet");
23603
+ __name(extractPathTokens, "extractPathTokens");
23604
+ __name(stripExplicitPrefix, "stripExplicitPrefix");
23605
+ __name(classifyReference, "classifyReference");
23606
+ __name(inspectRegularFile, "inspectRegularFile");
23607
+ __name(inferSurfaceHost, "inferSurfaceHost");
23608
+ __name(receiptProjection, "receiptProjection");
23609
+ __name(createSkillResourceClosureReceipt, "createSkillResourceClosureReceipt");
23610
+ __name(assertSkillResourceClosureReceipt, "assertSkillResourceClosureReceipt");
23611
+ __name(evaluateConsumerSkillResourceClosureReceipts, "evaluateConsumerSkillResourceClosureReceipts");
23612
+ __name(checkSkillResourceClosure, "checkSkillResourceClosure");
23613
+ }
23614
+ });
23615
+
23160
23616
  // src/snapshot/public-map.mjs
23161
- import { lstat as lstat8, readFile as readFile11, mkdir as mkdir8, readdir as readdir6, realpath as realpath8, chmod as fsChmod } from "node:fs/promises";
23617
+ import { lstat as lstat9, readFile as readFile12, mkdir as mkdir8, readdir as readdir7, realpath as realpath8, chmod as fsChmod } from "node:fs/promises";
23162
23618
  import { open as fsOpen } from "node:fs/promises";
23163
- import { relative as relative12, resolve as resolve15, dirname as dirname6, sep as pathSep, isAbsolute as isAbsolute11 } from "node:path";
23619
+ import { relative as relative13, resolve as resolve16, dirname as dirname7, sep as pathSep, isAbsolute as isAbsolute12 } from "node:path";
23164
23620
  import { posix } from "node:path";
23165
23621
  import { constants as fsConstants3 } from "node:fs";
23166
23622
  import { createHash as createHash7 } from "node:crypto";
@@ -23169,14 +23625,14 @@ function _isContainedWith(relativeFn, isAbsoluteFn, root, candidate, relPathSep
23169
23625
  return rel !== "" && rel !== ".." && !rel.startsWith(`..${relPathSep}`) && !isAbsoluteFn(rel);
23170
23626
  }
23171
23627
  function isContained(root, candidate) {
23172
- return _isContainedWith(relative12, isAbsolute11, root, candidate);
23628
+ return _isContainedWith(relative13, isAbsolute12, root, candidate);
23173
23629
  }
23174
- async function assertNoAncestorSymlinks(root, filePath, fs = { lstat: lstat8 }) {
23175
- const rel = relative12(root, filePath);
23630
+ async function assertNoAncestorSymlinks(root, filePath, fs = { lstat: lstat9 }) {
23631
+ const rel = relative13(root, filePath);
23176
23632
  const segments = rel.split(/[/\\]/);
23177
23633
  let current = root;
23178
23634
  for (const segment of segments) {
23179
- current = resolve15(current, segment);
23635
+ current = resolve16(current, segment);
23180
23636
  try {
23181
23637
  const st = await fs.lstat(current, { stage: "source-ancestor" });
23182
23638
  if (st.isSymbolicLink()) {
@@ -23198,7 +23654,7 @@ async function assertNoAncestorSymlinks(root, filePath, fs = { lstat: lstat8 })
23198
23654
  }
23199
23655
  }
23200
23656
  }
23201
- async function assertOutputAncestorsNoFollow(effectiveOutputDir, fs = { lstat: lstat8 }) {
23657
+ async function assertOutputAncestorsNoFollow(effectiveOutputDir, fs = { lstat: lstat9 }) {
23202
23658
  const parts = effectiveOutputDir.split(pathSep).filter(Boolean);
23203
23659
  let accumulated = "";
23204
23660
  for (const part of parts) {
@@ -23232,12 +23688,12 @@ async function assertOutputAncestorsNoFollow(effectiveOutputDir, fs = { lstat: l
23232
23688
  }
23233
23689
  }
23234
23690
  }
23235
- async function assertDestAncestorsNoFollow(realOutputRoot, destPath, fs = { lstat: lstat8 }) {
23236
- const relDest = relative12(realOutputRoot, destPath);
23691
+ async function assertDestAncestorsNoFollow(realOutputRoot, destPath, fs = { lstat: lstat9 }) {
23692
+ const relDest = relative13(realOutputRoot, destPath);
23237
23693
  const segments = relDest.split(pathSep).filter(Boolean);
23238
23694
  let current = realOutputRoot;
23239
23695
  for (const segment of segments) {
23240
- current = resolve15(current, segment);
23696
+ current = resolve16(current, segment);
23241
23697
  try {
23242
23698
  const st = await fs.lstat(current, { stage: "dest-ancestor" });
23243
23699
  if (st.isSymbolicLink()) {
@@ -23391,12 +23847,12 @@ async function buildPublicStaging({
23391
23847
  throw new ReleaseError(CONFIG_INVALID, "unit.publicFiles must be an array");
23392
23848
  }
23393
23849
  const fs = {
23394
- lstat: _fsOps.lstat ? (p, ctx) => _fsOps.lstat({ operation: "lstat", path: p, ...ctx }) : lstat8,
23850
+ lstat: _fsOps.lstat ? (p, ctx) => _fsOps.lstat({ operation: "lstat", path: p, ...ctx }) : lstat9,
23395
23851
  realpath: _fsOps.realpath ? (p, ctx) => _fsOps.realpath({ operation: "realpath", path: p, ...ctx }) : realpath8,
23396
- readFile: _fsOps.readFile ? (p, ctx) => _fsOps.readFile({ operation: "readFile", path: p, ...ctx }) : readFile11,
23852
+ readFile: _fsOps.readFile ? (p, ctx) => _fsOps.readFile({ operation: "readFile", path: p, ...ctx }) : readFile12,
23397
23853
  open: _fsOps.open ? (p, flags, mode, ctx) => _fsOps.open({ operation: "open", path: p, flags, mode, ...ctx }) : fsOpen,
23398
23854
  mkdir: _fsOps.mkdir ? (p, opts, ctx) => _fsOps.mkdir({ operation: "mkdir", path: p, opts, ...ctx }) : mkdir8,
23399
- readdir: _fsOps.readdir ? (p, ctx) => _fsOps.readdir({ operation: "readdir", path: p, ...ctx }) : readdir6,
23855
+ readdir: _fsOps.readdir ? (p, ctx) => _fsOps.readdir({ operation: "readdir", path: p, ...ctx }) : readdir7,
23400
23856
  chmod: _fsOps.chmod ? (p, mode, ctx) => _fsOps.chmod({ operation: "chmod", path: p, mode, ...ctx }) : fsChmod
23401
23857
  };
23402
23858
  let realSourceRoot;
@@ -23428,7 +23884,7 @@ async function buildPublicStaging({
23428
23884
  { count: mappings.length, limit: MAX_MAPPINGS }
23429
23885
  );
23430
23886
  }
23431
- const unitRootLexical = resolve15(sourceRoot, unit.source);
23887
+ const unitRootLexical = resolve16(sourceRoot, unit.source);
23432
23888
  let realUnitRoot;
23433
23889
  try {
23434
23890
  realUnitRoot = await fs.realpath(unitRootLexical, { stage: "unit-root-realpath" });
@@ -23441,14 +23897,14 @@ async function buildPublicStaging({
23441
23897
  { sourceRoot, unitSource: unit.source, cause: code }
23442
23898
  );
23443
23899
  }
23444
- const effectiveOutputDir = resolve15(
23445
- outputDir ?? resolve15(sourceRoot, ".release-skill", "staging")
23900
+ const effectiveOutputDir = resolve16(
23901
+ outputDir ?? resolve16(sourceRoot, ".release-skill", "staging")
23446
23902
  );
23447
23903
  const preflightRecords = [];
23448
23904
  const requiredTargetSet = new Set(unit.requiredPublicFiles ?? []);
23449
23905
  for (const mapping of mappings) {
23450
- const srcPath = resolve15(sourceRoot, mapping.from);
23451
- const destPath = resolve15(effectiveOutputDir, mapping.to);
23906
+ const srcPath = resolve16(sourceRoot, mapping.from);
23907
+ const destPath = resolve16(effectiveOutputDir, mapping.to);
23452
23908
  if (srcPath.length > MAX_PATH_LENGTH || destPath.length > MAX_PATH_LENGTH) {
23453
23909
  preflightRecords.push({
23454
23910
  ok: false,
@@ -23934,12 +24390,12 @@ async function buildPublicStaging({
23934
24390
  { to: mapping.to, outputDir: effectiveOutputDir, cause: err.code }
23935
24391
  );
23936
24392
  }
23937
- const destDir = dirname6(destPath);
23938
- const relDest = relative12(realOutputRoot, destDir);
24393
+ const destDir = dirname7(destPath);
24394
+ const relDest = relative13(realOutputRoot, destDir);
23939
24395
  const destSegments = relDest.split(pathSep).filter(Boolean);
23940
24396
  let accumulatedPath = realOutputRoot;
23941
24397
  for (const seg of destSegments) {
23942
- accumulatedPath = resolve15(accumulatedPath, seg);
24398
+ accumulatedPath = resolve16(accumulatedPath, seg);
23943
24399
  try {
23944
24400
  const segStat = await fs.lstat(accumulatedPath, { stage: "dest-ancestor-pre-mkdir" });
23945
24401
  if (segStat.isSymbolicLink()) {
@@ -24238,25 +24694,25 @@ var init_public_map = __esm({
24238
24694
  });
24239
24695
 
24240
24696
  // src/snapshot/scan.mjs
24241
- import { readFile as readFile12, readdir as readdir7, stat as stat3 } from "node:fs/promises";
24242
- import { join as join11, relative as relative13, extname, posix as posix2, win32 } from "node:path";
24697
+ import { readFile as readFile13, readdir as readdir8, stat as stat3 } from "node:fs/promises";
24698
+ import { join as join12, relative as relative14, extname, posix as posix2, win32 } from "node:path";
24243
24699
  import { createHash as createHash8 } from "node:crypto";
24244
24700
  async function collectFiles(dir, base = dir) {
24245
24701
  const results = [];
24246
24702
  let entries;
24247
24703
  try {
24248
- entries = await readdir7(dir, { withFileTypes: true });
24704
+ entries = await readdir8(dir, { withFileTypes: true });
24249
24705
  } catch {
24250
24706
  return results;
24251
24707
  }
24252
24708
  for (const entry of entries) {
24253
24709
  if (entry.name === ".git") continue;
24254
- const abs = join11(dir, entry.name);
24710
+ const abs = join12(dir, entry.name);
24255
24711
  if (entry.isDirectory()) {
24256
24712
  const sub = await collectFiles(abs, base);
24257
24713
  results.push(...sub);
24258
24714
  } else if (entry.isFile()) {
24259
- results.push(relative13(base, abs));
24715
+ results.push(relative14(base, abs));
24260
24716
  }
24261
24717
  }
24262
24718
  return results;
@@ -24288,9 +24744,9 @@ async function scanFile(relPath, absPath, forbiddenPaths, forbiddenContentPatter
24288
24744
  for (const fp of forbiddenPaths) {
24289
24745
  const normFp = fp.replaceAll(win32.sep, posix2.sep).replace(/\/+$/, "").toLowerCase();
24290
24746
  if (!normFp) continue;
24291
- for (const sep4 of separators) {
24292
- const prefix = normFp.endsWith(sep4.toLowerCase()) ? normFp : normFp + sep4.toLowerCase();
24293
- const checkPath = lowerRel + sep4.toLowerCase();
24747
+ for (const sep5 of separators) {
24748
+ const prefix = normFp.endsWith(sep5.toLowerCase()) ? normFp : normFp + sep5.toLowerCase();
24749
+ const checkPath = lowerRel + sep5.toLowerCase();
24294
24750
  if (lowerRel === normFp || checkPath.startsWith(prefix)) {
24295
24751
  const dedupKey = `FORBIDDEN_PATH:${normFp}:${normRel}`;
24296
24752
  if (!seenKinds.has(dedupKey)) {
@@ -24307,7 +24763,7 @@ async function scanFile(relPath, absPath, forbiddenPaths, forbiddenContentPatter
24307
24763
  }
24308
24764
  let content;
24309
24765
  try {
24310
- content = await readFile12(absPath, "utf8");
24766
+ content = await readFile13(absPath, "utf8");
24311
24767
  } catch {
24312
24768
  return findings;
24313
24769
  }
@@ -24376,10 +24832,10 @@ async function scanFile(relPath, absPath, forbiddenPaths, forbiddenContentPatter
24376
24832
  }
24377
24833
  async function scanForStaleDist(snapshotDir) {
24378
24834
  const findings = [];
24379
- const manifestPath = join11(snapshotDir, "dist", "manifest.json");
24835
+ const manifestPath = join12(snapshotDir, "dist", "manifest.json");
24380
24836
  let manifest;
24381
24837
  try {
24382
- const raw = await readFile12(manifestPath, "utf8");
24838
+ const raw = await readFile13(manifestPath, "utf8");
24383
24839
  manifest = JSON.parse(raw);
24384
24840
  } catch {
24385
24841
  return findings;
@@ -24387,13 +24843,13 @@ async function scanForStaleDist(snapshotDir) {
24387
24843
  if (!manifest.files || typeof manifest.files !== "object") {
24388
24844
  return findings;
24389
24845
  }
24390
- const distDir = join11(snapshotDir, "dist");
24846
+ const distDir = join12(snapshotDir, "dist");
24391
24847
  for (const [fileRel, expectedHash] of Object.entries(manifest.files)) {
24392
24848
  if (typeof expectedHash !== "string") continue;
24393
- const fileAbs = join11(distDir, fileRel);
24849
+ const fileAbs = join12(distDir, fileRel);
24394
24850
  let actualContent;
24395
24851
  try {
24396
- actualContent = await readFile12(fileAbs);
24852
+ actualContent = await readFile13(fileAbs);
24397
24853
  } catch {
24398
24854
  findings.push({
24399
24855
  kind: STALE_BUILD_ARTIFACT,
@@ -24434,7 +24890,7 @@ async function scanSnapshot({ snapshotDir, policy = {} } = {}) {
24434
24890
  const relFiles = await collectFiles(snapshotDir);
24435
24891
  const seenKinds = /* @__PURE__ */ new Set();
24436
24892
  for (const relPath of relFiles) {
24437
- const absPath = join11(snapshotDir, relPath);
24893
+ const absPath = join12(snapshotDir, relPath);
24438
24894
  const normRel = relPath.replaceAll(win32.sep, posix2.sep);
24439
24895
  if (await isBinaryFile(relPath, absPath)) continue;
24440
24896
  const fileFindings = await scanFile(normRel, absPath, forbiddenPaths, forbiddenContentPatterns, seenKinds);
@@ -24525,7 +24981,7 @@ var init_scan = __esm({
24525
24981
  });
24526
24982
 
24527
24983
  // src/readme/contract.mjs
24528
- import { readFile as readFile13 } from "node:fs/promises";
24984
+ import { readFile as readFile14 } from "node:fs/promises";
24529
24985
  import path2 from "node:path";
24530
24986
  function extractMarkers(content) {
24531
24987
  const regex = /<!--\s*release-skill:((?:[\w-]+:)*[\w-]+)\s*-->/g;
@@ -24555,7 +25011,7 @@ function extractExecBlocks(content) {
24555
25011
  }
24556
25012
  async function safeRead(filePath) {
24557
25013
  try {
24558
- return await readFile13(filePath, "utf8");
25014
+ return await readFile14(filePath, "utf8");
24559
25015
  } catch {
24560
25016
  return null;
24561
25017
  }
@@ -25644,10 +26100,10 @@ var require_commonjs = __commonJS({
25644
26100
  * Return a void Promise that resolves once the stream ends.
25645
26101
  */
25646
26102
  async promise() {
25647
- return new Promise((resolve26, reject) => {
26103
+ return new Promise((resolve27, reject) => {
25648
26104
  this.on(DESTROYED, () => reject(new Error("stream destroyed")));
25649
26105
  this.on("error", (er) => reject(er));
25650
- this.on("end", () => resolve26());
26106
+ this.on("end", () => resolve27());
25651
26107
  });
25652
26108
  }
25653
26109
  /**
@@ -25671,7 +26127,7 @@ var require_commonjs = __commonJS({
25671
26127
  return Promise.resolve({ done: false, value: res });
25672
26128
  if (this[EOF])
25673
26129
  return stop();
25674
- let resolve26;
26130
+ let resolve27;
25675
26131
  let reject;
25676
26132
  const onerr = /* @__PURE__ */ __name((er) => {
25677
26133
  this.off("data", ondata);
@@ -25685,19 +26141,19 @@ var require_commonjs = __commonJS({
25685
26141
  this.off("end", onend);
25686
26142
  this.off(DESTROYED, ondestroy);
25687
26143
  this.pause();
25688
- resolve26({ value, done: !!this[EOF] });
26144
+ resolve27({ value, done: !!this[EOF] });
25689
26145
  }, "ondata");
25690
26146
  const onend = /* @__PURE__ */ __name(() => {
25691
26147
  this.off("error", onerr);
25692
26148
  this.off("data", ondata);
25693
26149
  this.off(DESTROYED, ondestroy);
25694
26150
  stop();
25695
- resolve26({ done: true, value: void 0 });
26151
+ resolve27({ done: true, value: void 0 });
25696
26152
  }, "onend");
25697
26153
  const ondestroy = /* @__PURE__ */ __name(() => onerr(new Error("stream destroyed")), "ondestroy");
25698
26154
  return new Promise((res2, rej) => {
25699
26155
  reject = rej;
25700
- resolve26 = res2;
26156
+ resolve27 = res2;
25701
26157
  this.once(DESTROYED, ondestroy);
25702
26158
  this.once("error", onerr);
25703
26159
  this.once("end", onend);
@@ -26788,10 +27244,10 @@ var require_minipass = __commonJS({
26788
27244
  }
26789
27245
  // stream.promise().then(() => done, er => emitted error)
26790
27246
  promise() {
26791
- return new Promise((resolve26, reject) => {
27247
+ return new Promise((resolve27, reject) => {
26792
27248
  this.on(DESTROYED, () => reject(new Error("stream destroyed")));
26793
27249
  this.on("error", (er) => reject(er));
26794
- this.on("end", () => resolve26());
27250
+ this.on("end", () => resolve27());
26795
27251
  });
26796
27252
  }
26797
27253
  // for await (let chunk of stream)
@@ -26802,7 +27258,7 @@ var require_minipass = __commonJS({
26802
27258
  return Promise.resolve({ done: false, value: res });
26803
27259
  if (this[EOF])
26804
27260
  return Promise.resolve({ done: true });
26805
- let resolve26 = null;
27261
+ let resolve27 = null;
26806
27262
  let reject = null;
26807
27263
  const onerr = /* @__PURE__ */ __name((er) => {
26808
27264
  this.removeListener("data", ondata);
@@ -26813,17 +27269,17 @@ var require_minipass = __commonJS({
26813
27269
  this.removeListener("error", onerr);
26814
27270
  this.removeListener("end", onend);
26815
27271
  this.pause();
26816
- resolve26({ value, done: !!this[EOF] });
27272
+ resolve27({ value, done: !!this[EOF] });
26817
27273
  }, "ondata");
26818
27274
  const onend = /* @__PURE__ */ __name(() => {
26819
27275
  this.removeListener("error", onerr);
26820
27276
  this.removeListener("data", ondata);
26821
- resolve26({ done: true });
27277
+ resolve27({ done: true });
26822
27278
  }, "onend");
26823
27279
  const ondestroy = /* @__PURE__ */ __name(() => onerr(new Error("stream destroyed")), "ondestroy");
26824
27280
  return new Promise((res2, rej) => {
26825
27281
  reject = rej;
26826
- resolve26 = res2;
27282
+ resolve27 = res2;
26827
27283
  this.once(DESTROYED, ondestroy);
26828
27284
  this.once("error", onerr);
26829
27285
  this.once("end", onend);
@@ -30862,12 +31318,12 @@ var require_body = __commonJS({
30862
31318
  if (resTimeout && resTimeout.unref) {
30863
31319
  resTimeout.unref();
30864
31320
  }
30865
- return new Promise((resolve26) => {
31321
+ return new Promise((resolve27) => {
30866
31322
  if (stream !== upstream) {
30867
31323
  upstream.on("error", (er) => stream.emit("error", er));
30868
31324
  upstream.pipe(stream);
30869
31325
  }
30870
- resolve26();
31326
+ resolve27();
30871
31327
  }).then(() => stream.concat()).then((buf) => {
30872
31328
  clearTimeout(resTimeout);
30873
31329
  return buf;
@@ -31632,7 +32088,7 @@ var require_lib2 = __commonJS({
31632
32088
  var fetch = /* @__PURE__ */ __name(async (url, opts) => {
31633
32089
  if (/^data:/.test(url)) {
31634
32090
  const request = new Request(url, opts);
31635
- return Promise.resolve().then(() => new Promise((resolve26, reject) => {
32091
+ return Promise.resolve().then(() => new Promise((resolve27, reject) => {
31636
32092
  let type, data;
31637
32093
  try {
31638
32094
  const { pathname, search } = new URL2(url);
@@ -31656,10 +32112,10 @@ var require_lib2 = __commonJS({
31656
32112
  if (type) {
31657
32113
  headers["Content-Type"] = type;
31658
32114
  }
31659
- return resolve26(new Response(data, { headers }));
32115
+ return resolve27(new Response(data, { headers }));
31660
32116
  }));
31661
32117
  }
31662
- return new Promise((resolve26, reject) => {
32118
+ return new Promise((resolve27, reject) => {
31663
32119
  const request = new Request(url, opts);
31664
32120
  let options;
31665
32121
  try {
@@ -31778,7 +32234,7 @@ var require_lib2 = __commonJS({
31778
32234
  requestOpts.body = void 0;
31779
32235
  requestOpts.headers.delete("content-length");
31780
32236
  }
31781
- resolve26(fetch(new Request(locationURL, requestOpts)));
32237
+ resolve27(fetch(new Request(locationURL, requestOpts)));
31782
32238
  finalize();
31783
32239
  return;
31784
32240
  }
@@ -31806,7 +32262,7 @@ var require_lib2 = __commonJS({
31806
32262
  const codings = headers.get("Content-Encoding");
31807
32263
  if (!request.compress || request.method === "HEAD" || codings === null || res.statusCode === 204 || res.statusCode === 304) {
31808
32264
  response = new Response(body, responseOptions);
31809
- resolve26(response);
32265
+ resolve27(response);
31810
32266
  return;
31811
32267
  }
31812
32268
  const zlibOptions = {
@@ -31825,7 +32281,7 @@ var require_lib2 = __commonJS({
31825
32281
  ).pipe(unzip),
31826
32282
  responseOptions
31827
32283
  );
31828
- resolve26(response);
32284
+ resolve27(response);
31829
32285
  return;
31830
32286
  }
31831
32287
  if (codings === "deflate" || codings === "x-deflate") {
@@ -31837,7 +32293,7 @@ var require_lib2 = __commonJS({
31837
32293
  (er) => decoder2.emit("error", er)
31838
32294
  ).pipe(decoder2);
31839
32295
  response = new Response(decoder2, responseOptions);
31840
- resolve26(response);
32296
+ resolve27(response);
31841
32297
  });
31842
32298
  return;
31843
32299
  }
@@ -31855,11 +32311,11 @@ var require_lib2 = __commonJS({
31855
32311
  (er) => decoder.emit("error", er)
31856
32312
  ).pipe(decoder);
31857
32313
  response = new Response(decoder, responseOptions);
31858
- resolve26(response);
32314
+ resolve27(response);
31859
32315
  return;
31860
32316
  }
31861
32317
  response = new Response(body, responseOptions);
31862
- resolve26(response);
32318
+ resolve27(response);
31863
32319
  });
31864
32320
  writeToStream(req, request);
31865
32321
  });
@@ -32113,12 +32569,12 @@ var require_lib3 = __commonJS({
32113
32569
  return process.emit("input", "end");
32114
32570
  }, "end"),
32115
32571
  read: /* @__PURE__ */ __name(function(...args2) {
32116
- let resolve26, reject;
32572
+ let resolve27, reject;
32117
32573
  const promise = new Promise((_resolve, _reject) => {
32118
- resolve26 = _resolve;
32574
+ resolve27 = _resolve;
32119
32575
  reject = _reject;
32120
32576
  });
32121
- process.emit("input", "read", resolve26, reject, ...args2);
32577
+ process.emit("input", "read", resolve27, reject, ...args2);
32122
32578
  return promise;
32123
32579
  }, "read")
32124
32580
  }
@@ -36533,7 +36989,7 @@ var require_npa = __commonJS({
36533
36989
  spec = arg;
36534
36990
  }
36535
36991
  }
36536
- return resolve26(name, spec, where, arg);
36992
+ return resolve27(name, spec, where, arg);
36537
36993
  }
36538
36994
  __name(npa, "npa");
36539
36995
  function isFileSpec(spec) {
@@ -36556,7 +37012,7 @@ var require_npa = __commonJS({
36556
37012
  return spec.toLowerCase().startsWith("npm:");
36557
37013
  }
36558
37014
  __name(isAliasSpec, "isAliasSpec");
36559
- function resolve26(name, spec, where, arg) {
37015
+ function resolve27(name, spec, where, arg) {
36560
37016
  const res = new Result({
36561
37017
  raw: arg,
36562
37018
  name,
@@ -36588,7 +37044,7 @@ var require_npa = __commonJS({
36588
37044
  return fromRegistry(res);
36589
37045
  }
36590
37046
  }
36591
- __name(resolve26, "resolve");
37047
+ __name(resolve27, "resolve");
36592
37048
  function toPurl(arg, reg = defaultRegistry) {
36593
37049
  const res = npa(arg);
36594
37050
  if (res.type !== "version") {
@@ -36889,7 +37345,7 @@ var require_npa = __commonJS({
36889
37345
  }
36890
37346
  __name(fromRegistry, "fromRegistry");
36891
37347
  module.exports = npa;
36892
- module.exports.resolve = resolve26;
37348
+ module.exports.resolve = resolve27;
36893
37349
  module.exports.toPurl = toPurl;
36894
37350
  module.exports.Result = Result;
36895
37351
  }
@@ -38480,7 +38936,7 @@ var require_lib7 = __commonJS({
38480
38936
  return `${this.algorithm}-${this.digest}${getOptString(this.options)}`;
38481
38937
  }
38482
38938
  };
38483
- function integrityHashToString(toString, sep4, opts, hashes) {
38939
+ function integrityHashToString(toString, sep5, opts, hashes) {
38484
38940
  const toStringIsNotEmpty = toString !== "";
38485
38941
  let shouldAddFirstSep = false;
38486
38942
  let complement = "";
@@ -38490,7 +38946,7 @@ var require_lib7 = __commonJS({
38490
38946
  if (hashString) {
38491
38947
  shouldAddFirstSep = true;
38492
38948
  complement += hashString;
38493
- complement += sep4;
38949
+ complement += sep5;
38494
38950
  }
38495
38951
  }
38496
38952
  const finalHashString = Hash.prototype.toString.call(hashes[lastIndex], opts);
@@ -38499,7 +38955,7 @@ var require_lib7 = __commonJS({
38499
38955
  complement += finalHashString;
38500
38956
  }
38501
38957
  if (toStringIsNotEmpty && shouldAddFirstSep) {
38502
- return toString + sep4 + complement;
38958
+ return toString + sep5 + complement;
38503
38959
  }
38504
38960
  return toString + complement;
38505
38961
  }
@@ -38518,18 +38974,18 @@ var require_lib7 = __commonJS({
38518
38974
  return Object.keys(this).length === 0;
38519
38975
  }
38520
38976
  toString(opts) {
38521
- let sep4 = opts?.sep || " ";
38977
+ let sep5 = opts?.sep || " ";
38522
38978
  let toString = "";
38523
38979
  if (opts?.strict) {
38524
- sep4 = sep4.replace(/\S+/g, " ");
38980
+ sep5 = sep5.replace(/\S+/g, " ");
38525
38981
  for (const hash of SPEC_ALGORITHMS) {
38526
38982
  if (this[hash]) {
38527
- toString = integrityHashToString(toString, sep4, opts, this[hash]);
38983
+ toString = integrityHashToString(toString, sep5, opts, this[hash]);
38528
38984
  }
38529
38985
  }
38530
38986
  } else {
38531
38987
  for (const hash of Object.keys(this)) {
38532
- toString = integrityHashToString(toString, sep4, opts, this[hash]);
38988
+ toString = integrityHashToString(toString, sep5, opts, this[hash]);
38533
38989
  }
38534
38990
  }
38535
38991
  return toString;
@@ -38662,7 +39118,7 @@ var require_lib7 = __commonJS({
38662
39118
  module.exports.fromStream = fromStream;
38663
39119
  function fromStream(stream, opts) {
38664
39120
  const istream = integrityStream(opts);
38665
- return new Promise((resolve26, reject) => {
39121
+ return new Promise((resolve27, reject) => {
38666
39122
  stream.pipe(istream);
38667
39123
  stream.on("error", reject);
38668
39124
  istream.on("error", reject);
@@ -38670,7 +39126,7 @@ var require_lib7 = __commonJS({
38670
39126
  istream.on("integrity", (s) => {
38671
39127
  sri = s;
38672
39128
  });
38673
- istream.on("end", () => resolve26(sri));
39129
+ istream.on("end", () => resolve27(sri));
38674
39130
  istream.resume();
38675
39131
  });
38676
39132
  }
@@ -38731,7 +39187,7 @@ var require_lib7 = __commonJS({
38731
39187
  ));
38732
39188
  }
38733
39189
  const checker = integrityStream(opts);
38734
- return new Promise((resolve26, reject) => {
39190
+ return new Promise((resolve27, reject) => {
38735
39191
  stream.pipe(checker);
38736
39192
  stream.on("error", reject);
38737
39193
  checker.on("error", reject);
@@ -38739,7 +39195,7 @@ var require_lib7 = __commonJS({
38739
39195
  checker.on("verified", (s) => {
38740
39196
  verified = s;
38741
39197
  });
38742
- checker.on("end", () => resolve26(verified));
39198
+ checker.on("end", () => resolve27(verified));
38743
39199
  checker.resume();
38744
39200
  });
38745
39201
  }
@@ -39620,9 +40076,9 @@ var require_polyfill = __commonJS({
39620
40076
  var {
39621
40077
  chmod: chmod5,
39622
40078
  copyFile,
39623
- lstat: lstat15,
40079
+ lstat: lstat16,
39624
40080
  mkdir: mkdir18,
39625
- readdir: readdir14,
40081
+ readdir: readdir15,
39626
40082
  readlink: readlink2,
39627
40083
  stat: stat9,
39628
40084
  symlink,
@@ -39630,12 +40086,12 @@ var require_polyfill = __commonJS({
39630
40086
  utimes
39631
40087
  } = __require("fs/promises");
39632
40088
  var {
39633
- dirname: dirname15,
39634
- isAbsolute: isAbsolute20,
39635
- join: join27,
40089
+ dirname: dirname16,
40090
+ isAbsolute: isAbsolute21,
40091
+ join: join28,
39636
40092
  parse: parse2,
39637
- resolve: resolve26,
39638
- sep: sep4,
40093
+ resolve: resolve27,
40094
+ sep: sep5,
39639
40095
  toNamespacedPath
39640
40096
  } = __require("path");
39641
40097
  var { fileURLToPath: fileURLToPath3 } = __require("url");
@@ -39721,7 +40177,7 @@ var require_polyfill = __commonJS({
39721
40177
  }
39722
40178
  __name(areIdentical, "areIdentical");
39723
40179
  function getStats(src, dest, opts) {
39724
- const statFunc = opts.dereference ? (file) => stat9(file, { bigint: true }) : (file) => lstat15(file, { bigint: true });
40180
+ const statFunc = opts.dereference ? (file) => stat9(file, { bigint: true }) : (file) => lstat16(file, { bigint: true });
39725
40181
  return Promise.all([
39726
40182
  statFunc(src),
39727
40183
  statFunc(dest).catch((err) => {
@@ -39734,7 +40190,7 @@ var require_polyfill = __commonJS({
39734
40190
  }
39735
40191
  __name(getStats, "getStats");
39736
40192
  async function checkParentDir(destStat, src, dest, opts) {
39737
- const destParent = dirname15(dest);
40193
+ const destParent = dirname16(dest);
39738
40194
  const dirExists = await pathExists2(destParent);
39739
40195
  if (dirExists) {
39740
40196
  return getStatsForCopy(destStat, src, dest, opts);
@@ -39752,8 +40208,8 @@ var require_polyfill = __commonJS({
39752
40208
  }
39753
40209
  __name(pathExists2, "pathExists");
39754
40210
  async function checkParentPaths(src, srcStat, dest) {
39755
- const srcParent = resolve26(dirname15(src));
39756
- const destParent = resolve26(dirname15(dest));
40211
+ const srcParent = resolve27(dirname16(src));
40212
+ const destParent = resolve27(dirname16(dest));
39757
40213
  if (destParent === srcParent || destParent === parse2(destParent).root) {
39758
40214
  return;
39759
40215
  }
@@ -39777,7 +40233,7 @@ var require_polyfill = __commonJS({
39777
40233
  return checkParentPaths(src, srcStat, destParent);
39778
40234
  }
39779
40235
  __name(checkParentPaths, "checkParentPaths");
39780
- var normalizePathToArray = /* @__PURE__ */ __name((path3) => resolve26(path3).split(sep4).filter(Boolean), "normalizePathToArray");
40236
+ var normalizePathToArray = /* @__PURE__ */ __name((path3) => resolve27(path3).split(sep5).filter(Boolean), "normalizePathToArray");
39781
40237
  function isSrcSubdir(src, dest) {
39782
40238
  const srcArr = normalizePathToArray(src);
39783
40239
  const destArr = normalizePathToArray(dest);
@@ -39799,7 +40255,7 @@ var require_polyfill = __commonJS({
39799
40255
  }
39800
40256
  __name(startCopy, "startCopy");
39801
40257
  async function getStatsForCopy(destStat, src, dest, opts) {
39802
- const statFn = opts.dereference ? stat9 : lstat15;
40258
+ const statFn = opts.dereference ? stat9 : lstat16;
39803
40259
  const srcStat = await statFn(src);
39804
40260
  if (srcStat.isDirectory() && opts.recursive) {
39805
40261
  return onDir(srcStat, destStat, src, dest, opts);
@@ -39910,11 +40366,11 @@ var require_polyfill = __commonJS({
39910
40366
  }
39911
40367
  __name(mkDirAndCopy, "mkDirAndCopy");
39912
40368
  async function copyDir(src, dest, opts) {
39913
- const dir = await readdir14(src);
40369
+ const dir = await readdir15(src);
39914
40370
  for (let i = 0; i < dir.length; i++) {
39915
40371
  const item = dir[i];
39916
- const srcItem = join27(src, item);
39917
- const destItem = join27(dest, item);
40372
+ const srcItem = join28(src, item);
40373
+ const destItem = join28(dest, item);
39918
40374
  const { destStat } = await checkPaths(srcItem, destItem, opts);
39919
40375
  await startCopy(destStat, srcItem, destItem, opts);
39920
40376
  }
@@ -39922,8 +40378,8 @@ var require_polyfill = __commonJS({
39922
40378
  __name(copyDir, "copyDir");
39923
40379
  async function onLink(destStat, src, dest) {
39924
40380
  let resolvedSrc = await readlink2(src);
39925
- if (!isAbsolute20(resolvedSrc)) {
39926
- resolvedSrc = resolve26(dirname15(src), resolvedSrc);
40381
+ if (!isAbsolute21(resolvedSrc)) {
40382
+ resolvedSrc = resolve27(dirname16(src), resolvedSrc);
39927
40383
  }
39928
40384
  if (!destStat) {
39929
40385
  return symlink(resolvedSrc, dest);
@@ -39937,8 +40393,8 @@ var require_polyfill = __commonJS({
39937
40393
  }
39938
40394
  throw err;
39939
40395
  }
39940
- if (!isAbsolute20(resolvedDest)) {
39941
- resolvedDest = resolve26(dirname15(dest), resolvedDest);
40396
+ if (!isAbsolute21(resolvedDest)) {
40397
+ resolvedDest = resolve27(dirname16(dest), resolvedDest);
39942
40398
  }
39943
40399
  if (isSrcSubdir(resolvedSrc, resolvedDest)) {
39944
40400
  throw new ERR_FS_CP_EINVAL({
@@ -39990,7 +40446,7 @@ var require_cp = __commonJS({
39990
40446
  // ../../node_modules/.pnpm/@npmcli+fs@4.0.0/node_modules/@npmcli/fs/lib/with-temp-dir.js
39991
40447
  var require_with_temp_dir = __commonJS({
39992
40448
  "../../node_modules/.pnpm/@npmcli+fs@4.0.0/node_modules/@npmcli/fs/lib/with-temp-dir.js"(exports, module) {
39993
- var { join: join27, sep: sep4 } = __require("path");
40449
+ var { join: join28, sep: sep5 } = __require("path");
39994
40450
  var getOptions = require_get_options();
39995
40451
  var { mkdir: mkdir18, mkdtemp: mkdtemp5, rm: rm9 } = __require("fs/promises");
39996
40452
  var withTempDir = /* @__PURE__ */ __name(async (root, fn, opts) => {
@@ -39998,7 +40454,7 @@ var require_with_temp_dir = __commonJS({
39998
40454
  copy: ["tmpPrefix"]
39999
40455
  });
40000
40456
  await mkdir18(root, { recursive: true });
40001
- const target = await mkdtemp5(join27(`${root}${sep4}`, options.tmpPrefix || ""));
40457
+ const target = await mkdtemp5(join28(`${root}${sep5}`, options.tmpPrefix || ""));
40002
40458
  let err;
40003
40459
  let result;
40004
40460
  try {
@@ -40022,14 +40478,14 @@ var require_with_temp_dir = __commonJS({
40022
40478
  // ../../node_modules/.pnpm/@npmcli+fs@4.0.0/node_modules/@npmcli/fs/lib/readdir-scoped.js
40023
40479
  var require_readdir_scoped = __commonJS({
40024
40480
  "../../node_modules/.pnpm/@npmcli+fs@4.0.0/node_modules/@npmcli/fs/lib/readdir-scoped.js"(exports, module) {
40025
- var { readdir: readdir14 } = __require("fs/promises");
40026
- var { join: join27 } = __require("path");
40481
+ var { readdir: readdir15 } = __require("fs/promises");
40482
+ var { join: join28 } = __require("path");
40027
40483
  var readdirScoped = /* @__PURE__ */ __name(async (dir) => {
40028
40484
  const results = [];
40029
- for (const item of await readdir14(dir)) {
40485
+ for (const item of await readdir15(dir)) {
40030
40486
  if (item.startsWith("@")) {
40031
- for (const scopedItem of await readdir14(join27(dir, item))) {
40032
- results.push(join27(item, scopedItem));
40487
+ for (const scopedItem of await readdir15(join28(dir, item))) {
40488
+ results.push(join28(item, scopedItem));
40033
40489
  }
40034
40490
  } else {
40035
40491
  results.push(item);
@@ -40044,7 +40500,7 @@ var require_readdir_scoped = __commonJS({
40044
40500
  // ../../node_modules/.pnpm/@npmcli+fs@4.0.0/node_modules/@npmcli/fs/lib/move-file.js
40045
40501
  var require_move_file = __commonJS({
40046
40502
  "../../node_modules/.pnpm/@npmcli+fs@4.0.0/node_modules/@npmcli/fs/lib/move-file.js"(exports, module) {
40047
- var { dirname: dirname15, join: join27, resolve: resolve26, relative: relative23, isAbsolute: isAbsolute20 } = __require("path");
40503
+ var { dirname: dirname16, join: join28, resolve: resolve27, relative: relative24, isAbsolute: isAbsolute21 } = __require("path");
40048
40504
  var fs = __require("fs/promises");
40049
40505
  var pathExists2 = /* @__PURE__ */ __name(async (path3) => {
40050
40506
  try {
@@ -40065,7 +40521,7 @@ var require_move_file = __commonJS({
40065
40521
  if (!options.overwrite && await pathExists2(destination)) {
40066
40522
  throw new Error(`The destination file exists: ${destination}`);
40067
40523
  }
40068
- await fs.mkdir(dirname15(destination), { recursive: true });
40524
+ await fs.mkdir(dirname16(destination), { recursive: true });
40069
40525
  try {
40070
40526
  await fs.rename(source, destination);
40071
40527
  } catch (error) {
@@ -40074,7 +40530,7 @@ var require_move_file = __commonJS({
40074
40530
  if (sourceStat.isDirectory()) {
40075
40531
  const files = await fs.readdir(source);
40076
40532
  await Promise.all(files.map(
40077
- (file) => moveFile(join27(source, file), join27(destination, file), options, false, symlinks)
40533
+ (file) => moveFile(join28(source, file), join28(destination, file), options, false, symlinks)
40078
40534
  ));
40079
40535
  } else if (sourceStat.isSymbolicLink()) {
40080
40536
  symlinks.push({ source, destination });
@@ -40088,12 +40544,12 @@ var require_move_file = __commonJS({
40088
40544
  if (root) {
40089
40545
  await Promise.all(symlinks.map(async ({ source: symSource, destination: symDestination }) => {
40090
40546
  let target = await fs.readlink(symSource);
40091
- if (isAbsolute20(target)) {
40092
- target = resolve26(symDestination, relative23(symSource, target));
40547
+ if (isAbsolute21(target)) {
40548
+ target = resolve27(symDestination, relative24(symSource, target));
40093
40549
  }
40094
40550
  let targetStat = "file";
40095
40551
  try {
40096
- targetStat = await fs.stat(resolve26(dirname15(symSource), target));
40552
+ targetStat = await fs.stat(resolve27(dirname16(symSource), target));
40097
40553
  if (targetStat.isDirectory()) {
40098
40554
  targetStat = "junction";
40099
40555
  }
@@ -40166,7 +40622,7 @@ async function pMap(iterable, mapper, {
40166
40622
  const cleanup = /* @__PURE__ */ __name(() => {
40167
40623
  signal?.removeEventListener("abort", signalListener);
40168
40624
  }, "cleanup");
40169
- const resolve26 = /* @__PURE__ */ __name((value) => {
40625
+ const resolve27 = /* @__PURE__ */ __name((value) => {
40170
40626
  resolve_(value);
40171
40627
  cleanup();
40172
40628
  }, "resolve");
@@ -40198,7 +40654,7 @@ async function pMap(iterable, mapper, {
40198
40654
  }
40199
40655
  isResolved = true;
40200
40656
  if (skippedIndexesMap.size === 0) {
40201
- resolve26(result);
40657
+ resolve27(result);
40202
40658
  return;
40203
40659
  }
40204
40660
  const pureResult = [];
@@ -40208,7 +40664,7 @@ async function pMap(iterable, mapper, {
40208
40664
  }
40209
40665
  pureResult.push(value);
40210
40666
  }
40211
- resolve26(pureResult);
40667
+ resolve27(pureResult);
40212
40668
  }
40213
40669
  return;
40214
40670
  }
@@ -40348,8 +40804,8 @@ var require_entry_index = __commonJS({
40348
40804
  var {
40349
40805
  appendFile,
40350
40806
  mkdir: mkdir18,
40351
- readFile: readFile31,
40352
- readdir: readdir14,
40807
+ readFile: readFile32,
40808
+ readdir: readdir15,
40353
40809
  rm: rm9,
40354
40810
  writeFile: writeFile11
40355
40811
  } = __require("fs/promises");
@@ -40540,7 +40996,7 @@ ${hashEntry(stringified)} ${stringified}`);
40540
40996
  __name(ls, "ls");
40541
40997
  module.exports.bucketEntries = bucketEntries;
40542
40998
  async function bucketEntries(bucket, filter) {
40543
- const data = await readFile31(bucket, "utf8");
40999
+ const data = await readFile32(bucket, "utf8");
40544
41000
  return _bucketEntries(data, filter);
40545
41001
  }
40546
41002
  __name(bucketEntries, "bucketEntries");
@@ -40609,7 +41065,7 @@ ${hashEntry(stringified)} ${stringified}`);
40609
41065
  }
40610
41066
  __name(formatEntry, "formatEntry");
40611
41067
  function readdirOrEmpty(dir) {
40612
- return readdir14(dir).catch((err) => {
41068
+ return readdir15(dir).catch((err) => {
40613
41069
  if (err.code === "ENOENT" || err.code === "ENOTDIR") {
40614
41070
  return [];
40615
41071
  }
@@ -44414,9 +44870,9 @@ var require_commonjs5 = __commonJS({
44414
44870
  if (this.#asyncReaddirInFlight) {
44415
44871
  await this.#asyncReaddirInFlight;
44416
44872
  } else {
44417
- let resolve26 = /* @__PURE__ */ __name(() => {
44873
+ let resolve27 = /* @__PURE__ */ __name(() => {
44418
44874
  }, "resolve");
44419
- this.#asyncReaddirInFlight = new Promise((res) => resolve26 = res);
44875
+ this.#asyncReaddirInFlight = new Promise((res) => resolve27 = res);
44420
44876
  try {
44421
44877
  for (const e of await this.#fs.promises.readdir(fullpath, {
44422
44878
  withFileTypes: true
@@ -44429,7 +44885,7 @@ var require_commonjs5 = __commonJS({
44429
44885
  children.provisional = 0;
44430
44886
  }
44431
44887
  this.#asyncReaddirInFlight = void 0;
44432
- resolve26();
44888
+ resolve27();
44433
44889
  }
44434
44890
  return children.slice(0, children.provisional);
44435
44891
  }
@@ -44671,7 +45127,7 @@ var require_commonjs5 = __commonJS({
44671
45127
  *
44672
45128
  * @internal
44673
45129
  */
44674
- constructor(cwd = process.cwd(), pathImpl, sep4, { nocase, childrenCacheSize = 16 * 1024, fs = defaultFS } = {}) {
45130
+ constructor(cwd = process.cwd(), pathImpl, sep5, { nocase, childrenCacheSize = 16 * 1024, fs = defaultFS } = {}) {
44675
45131
  this.#fs = fsFromOption(fs);
44676
45132
  if (cwd instanceof URL || cwd.startsWith("file://")) {
44677
45133
  cwd = (0, node_url_1.fileURLToPath)(cwd);
@@ -44682,7 +45138,7 @@ var require_commonjs5 = __commonJS({
44682
45138
  this.#resolveCache = new ResolveCache();
44683
45139
  this.#resolvePosixCache = new ResolveCache();
44684
45140
  this.#children = new ChildrenCache(childrenCacheSize);
44685
- const split = cwdPath.substring(this.rootPath.length).split(sep4);
45141
+ const split = cwdPath.substring(this.rootPath.length).split(sep5);
44686
45142
  if (split.length === 1 && !split[0]) {
44687
45143
  split.pop();
44688
45144
  }
@@ -45540,10 +45996,10 @@ var require_ignore = __commonJS({
45540
45996
  ignored(p) {
45541
45997
  const fullpath = p.fullpath();
45542
45998
  const fullpaths = `${fullpath}/`;
45543
- const relative23 = p.relative() || ".";
45544
- const relatives = `${relative23}/`;
45999
+ const relative24 = p.relative() || ".";
46000
+ const relatives = `${relative24}/`;
45545
46001
  for (const m of this.relative) {
45546
- if (m.match(relative23) || m.match(relatives))
46002
+ if (m.match(relative24) || m.match(relatives))
45547
46003
  return true;
45548
46004
  }
45549
46005
  for (const m of this.absolute) {
@@ -45554,9 +46010,9 @@ var require_ignore = __commonJS({
45554
46010
  }
45555
46011
  childrenIgnored(p) {
45556
46012
  const fullpath = p.fullpath() + "/";
45557
- const relative23 = (p.relative() || ".") + "/";
46013
+ const relative24 = (p.relative() || ".") + "/";
45558
46014
  for (const m of this.relativeChildren) {
45559
- if (m.match(relative23))
46015
+ if (m.match(relative24))
45560
46016
  return true;
45561
46017
  }
45562
46018
  for (const m of this.absoluteChildren) {
@@ -46560,7 +47016,7 @@ var require_verify = __commonJS({
46560
47016
  "use strict";
46561
47017
  var {
46562
47018
  mkdir: mkdir18,
46563
- readFile: readFile31,
47019
+ readFile: readFile32,
46564
47020
  rm: rm9,
46565
47021
  stat: stat9,
46566
47022
  truncate,
@@ -46647,8 +47103,8 @@ var require_verify = __commonJS({
46647
47103
  liveContent.add(integrity[algo].toString());
46648
47104
  }
46649
47105
  });
46650
- await new Promise((resolve26, reject) => {
46651
- indexStream.on("end", resolve26).on("error", reject);
47106
+ await new Promise((resolve27, reject) => {
47107
+ indexStream.on("end", resolve27).on("error", reject);
46652
47108
  });
46653
47109
  const contentDir = contentPath.contentDir(cache);
46654
47110
  const files = await glob(path3.join(contentDir, "**"), {
@@ -46787,7 +47243,7 @@ var require_verify = __commonJS({
46787
47243
  __name(writeVerifile, "writeVerifile");
46788
47244
  module.exports.lastRun = lastRun;
46789
47245
  async function lastRun(cache) {
46790
- const data = await readFile31(path3.join(cache, "_lastverified"), { encoding: "utf8" });
47246
+ const data = await readFile32(path3.join(cache, "_lastverified"), { encoding: "utf8" });
46791
47247
  return /* @__PURE__ */ new Date(+data);
46792
47248
  }
46793
47249
  __name(lastRun, "lastRun");
@@ -47204,7 +47660,7 @@ var require_promise_retry = __commonJS({
47204
47660
  fn = temp;
47205
47661
  }
47206
47662
  operation = retry.operation(options);
47207
- return new Promise(function(resolve26, reject) {
47663
+ return new Promise(function(resolve27, reject) {
47208
47664
  operation.attempt(function(number) {
47209
47665
  Promise.resolve().then(function() {
47210
47666
  return fn(function(err) {
@@ -47213,7 +47669,7 @@ var require_promise_retry = __commonJS({
47213
47669
  }
47214
47670
  throw errcode(new Error("Retrying"), "EPROMISERETRY", { retried: err });
47215
47671
  }, number);
47216
- }).then(resolve26, function(err) {
47672
+ }).then(resolve27, function(err) {
47217
47673
  if (isRetryError(err)) {
47218
47674
  err = err.retried;
47219
47675
  if (operation.retry(err || new Error())) {
@@ -48098,8 +48554,8 @@ var require_helpers = __commonJS({
48098
48554
  function req(url, opts = {}) {
48099
48555
  const href = typeof url === "string" ? url : url.href;
48100
48556
  const req2 = (href.startsWith("https:") ? https : http).request(url, opts);
48101
- const promise = new Promise((resolve26, reject) => {
48102
- req2.once("response", resolve26).once("error", reject).end();
48557
+ const promise = new Promise((resolve27, reject) => {
48558
+ req2.once("response", resolve27).once("error", reject).end();
48103
48559
  });
48104
48560
  req2.then = promise.then.bind(promise);
48105
48561
  return req2;
@@ -48414,7 +48870,7 @@ var require_parse_proxy_response = __commonJS({
48414
48870
  var debug_1 = __importDefault(require_src());
48415
48871
  var debug = (0, debug_1.default)("https-proxy-agent:parse-proxy-response");
48416
48872
  function parseProxyResponse(socket) {
48417
- return new Promise((resolve26, reject) => {
48873
+ return new Promise((resolve27, reject) => {
48418
48874
  let buffersLength = 0;
48419
48875
  const buffers = [];
48420
48876
  function read() {
@@ -48484,7 +48940,7 @@ var require_parse_proxy_response = __commonJS({
48484
48940
  }
48485
48941
  debug("got proxy server response: %o %o", firstLine, headers);
48486
48942
  cleanup();
48487
- resolve26({
48943
+ resolve27({
48488
48944
  connect: {
48489
48945
  statusCode,
48490
48946
  statusText,
@@ -52163,12 +52619,12 @@ var require_socksclient = __commonJS({
52163
52619
  "use strict";
52164
52620
  var __awaiter = exports && exports.__awaiter || function(thisArg, _arguments, P, generator) {
52165
52621
  function adopt(value) {
52166
- return value instanceof P ? value : new P(function(resolve26) {
52167
- resolve26(value);
52622
+ return value instanceof P ? value : new P(function(resolve27) {
52623
+ resolve27(value);
52168
52624
  });
52169
52625
  }
52170
52626
  __name(adopt, "adopt");
52171
- return new (P || (P = Promise))(function(resolve26, reject) {
52627
+ return new (P || (P = Promise))(function(resolve27, reject) {
52172
52628
  function fulfilled(value) {
52173
52629
  try {
52174
52630
  step(generator.next(value));
@@ -52186,7 +52642,7 @@ var require_socksclient = __commonJS({
52186
52642
  }
52187
52643
  __name(rejected, "rejected");
52188
52644
  function step(result) {
52189
- result.done ? resolve26(result.value) : adopt(result.value).then(fulfilled, rejected);
52645
+ result.done ? resolve27(result.value) : adopt(result.value).then(fulfilled, rejected);
52190
52646
  }
52191
52647
  __name(step, "step");
52192
52648
  step((generator = generator.apply(thisArg, _arguments || [])).next());
@@ -52224,13 +52680,13 @@ var require_socksclient = __commonJS({
52224
52680
  * @returns { Promise }
52225
52681
  */
52226
52682
  static createConnection(options, callback) {
52227
- return new Promise((resolve26, reject) => {
52683
+ return new Promise((resolve27, reject) => {
52228
52684
  try {
52229
52685
  (0, helpers_1.validateSocksClientOptions)(options, ["connect"]);
52230
52686
  } catch (err) {
52231
52687
  if (typeof callback === "function") {
52232
52688
  callback(err);
52233
- return resolve26(err);
52689
+ return resolve27(err);
52234
52690
  } else {
52235
52691
  return reject(err);
52236
52692
  }
@@ -52241,16 +52697,16 @@ var require_socksclient = __commonJS({
52241
52697
  client.removeAllListeners();
52242
52698
  if (typeof callback === "function") {
52243
52699
  callback(null, info);
52244
- resolve26(info);
52700
+ resolve27(info);
52245
52701
  } else {
52246
- resolve26(info);
52702
+ resolve27(info);
52247
52703
  }
52248
52704
  });
52249
52705
  client.once("error", (err) => {
52250
52706
  client.removeAllListeners();
52251
52707
  if (typeof callback === "function") {
52252
52708
  callback(err);
52253
- resolve26(err);
52709
+ resolve27(err);
52254
52710
  } else {
52255
52711
  reject(err);
52256
52712
  }
@@ -52267,13 +52723,13 @@ var require_socksclient = __commonJS({
52267
52723
  * @returns { Promise }
52268
52724
  */
52269
52725
  static createConnectionChain(options, callback) {
52270
- return new Promise((resolve26, reject) => __awaiter(this, void 0, void 0, function* () {
52726
+ return new Promise((resolve27, reject) => __awaiter(this, void 0, void 0, function* () {
52271
52727
  try {
52272
52728
  (0, helpers_1.validateSocksClientChainOptions)(options);
52273
52729
  } catch (err) {
52274
52730
  if (typeof callback === "function") {
52275
52731
  callback(err);
52276
- return resolve26(err);
52732
+ return resolve27(err);
52277
52733
  } else {
52278
52734
  return reject(err);
52279
52735
  }
@@ -52299,14 +52755,14 @@ var require_socksclient = __commonJS({
52299
52755
  }
52300
52756
  if (typeof callback === "function") {
52301
52757
  callback(null, { socket: sock });
52302
- resolve26({ socket: sock });
52758
+ resolve27({ socket: sock });
52303
52759
  } else {
52304
- resolve26({ socket: sock });
52760
+ resolve27({ socket: sock });
52305
52761
  }
52306
52762
  } catch (err) {
52307
52763
  if (typeof callback === "function") {
52308
52764
  callback(err);
52309
- resolve26(err);
52765
+ resolve27(err);
52310
52766
  } else {
52311
52767
  reject(err);
52312
52768
  }
@@ -52994,12 +53450,12 @@ var require_dist6 = __commonJS({
52994
53450
  let { host } = opts;
52995
53451
  const { port, lookup: lookupFn = dns.lookup } = opts;
52996
53452
  if (shouldLookup) {
52997
- host = await new Promise((resolve26, reject) => {
53453
+ host = await new Promise((resolve27, reject) => {
52998
53454
  lookupFn(host, {}, (err, res) => {
52999
53455
  if (err) {
53000
53456
  reject(err);
53001
53457
  } else {
53002
- resolve26(res);
53458
+ resolve27(res);
53003
53459
  }
53004
53460
  });
53005
53461
  });
@@ -53811,8 +54267,8 @@ var require_entry = __commonJS({
53811
54267
  let body = null;
53812
54268
  if (this.response.status === 200) {
53813
54269
  let cacheWriteResolve, cacheWriteReject;
53814
- const cacheWritePromise = new Promise((resolve26, reject) => {
53815
- cacheWriteResolve = resolve26;
54270
+ const cacheWritePromise = new Promise((resolve27, reject) => {
54271
+ cacheWriteResolve = resolve27;
53816
54272
  cacheWriteReject = reject;
53817
54273
  }).catch((err) => {
53818
54274
  body.emit("error", err);
@@ -55327,9 +55783,9 @@ var require_index_min = __commonJS({
55327
55783
  var require_lib17 = __commonJS({
55328
55784
  "../../node_modules/.pnpm/which@5.0.0/node_modules/which/lib/index.js"(exports, module) {
55329
55785
  var { isexe, sync: isexeSync } = require_index_min();
55330
- var { join: join27, delimiter, sep: sep4, posix: posix3 } = __require("path");
55786
+ var { join: join28, delimiter, sep: sep5, posix: posix3 } = __require("path");
55331
55787
  var isWindows = process.platform === "win32";
55332
- var rSlash = new RegExp(`[${posix3.sep}${sep4 === posix3.sep ? "" : sep4}]`.replace(/(\\)/g, "\\$1"));
55788
+ var rSlash = new RegExp(`[${posix3.sep}${sep5 === posix3.sep ? "" : sep5}]`.replace(/(\\)/g, "\\$1"));
55333
55789
  var rRel = new RegExp(`^\\.${rSlash.source}`);
55334
55790
  var getNotFoundError = /* @__PURE__ */ __name((cmd) => Object.assign(new Error(`not found: ${cmd}`), { code: "ENOENT" }), "getNotFoundError");
55335
55791
  var getPathInfo = /* @__PURE__ */ __name((cmd, {
@@ -55356,7 +55812,7 @@ var require_lib17 = __commonJS({
55356
55812
  var getPathPart = /* @__PURE__ */ __name((raw, cmd) => {
55357
55813
  const pathPart = /^".*"$/.test(raw) ? raw.slice(1, -1) : raw;
55358
55814
  const prefix = !pathPart && rRel.test(cmd) ? cmd.slice(0, 2) : "";
55359
- return prefix + join27(pathPart, cmd);
55815
+ return prefix + join28(pathPart, cmd);
55360
55816
  }, "getPathPart");
55361
55817
  var which = /* @__PURE__ */ __name(async (cmd, opt = {}) => {
55362
55818
  const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
@@ -55479,9 +55935,9 @@ var require_lib18 = __commonJS({
55479
55935
  if (opts.shell) {
55480
55936
  return spawnWithShell(cmd, args2, opts, extra);
55481
55937
  }
55482
- let resolve26, reject;
55938
+ let resolve27, reject;
55483
55939
  const promise = new Promise((_resolve, _reject) => {
55484
- resolve26 = _resolve;
55940
+ resolve27 = _resolve;
55485
55941
  reject = _reject;
55486
55942
  });
55487
55943
  const closeError = new Error("command failed");
@@ -55514,7 +55970,7 @@ var require_lib18 = __commonJS({
55514
55970
  if (code || signal) {
55515
55971
  rejectWithOpts(closeError, { code, signal });
55516
55972
  } else {
55517
- resolve26(getResult({ code, signal }));
55973
+ resolve27(getResult({ code, signal }));
55518
55974
  }
55519
55975
  });
55520
55976
  return promise;
@@ -56495,7 +56951,7 @@ var require_lib19 = __commonJS({
56495
56951
  // ../../node_modules/.pnpm/npm-normalize-package-bin@4.0.0/node_modules/npm-normalize-package-bin/lib/index.js
56496
56952
  var require_lib20 = __commonJS({
56497
56953
  "../../node_modules/.pnpm/npm-normalize-package-bin@4.0.0/node_modules/npm-normalize-package-bin/lib/index.js"(exports, module) {
56498
- var { join: join27, basename: basename11 } = __require("path");
56954
+ var { join: join28, basename: basename11 } = __require("path");
56499
56955
  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");
56500
56956
  var normalizeString = /* @__PURE__ */ __name((pkg) => {
56501
56957
  if (!pkg.name) {
@@ -56520,11 +56976,11 @@ var require_lib20 = __commonJS({
56520
56976
  const clean = {};
56521
56977
  let hasBins = false;
56522
56978
  Object.keys(orig).forEach((binKey) => {
56523
- const base = join27("/", basename11(binKey.replace(/\\|:/g, "/"))).slice(1);
56979
+ const base = join28("/", basename11(binKey.replace(/\\|:/g, "/"))).slice(1);
56524
56980
  if (typeof orig[binKey] !== "string" || !base) {
56525
56981
  return;
56526
56982
  }
56527
- const binTarget = join27("/", orig[binKey].replace(/\\/g, "/")).replace(/\\/g, "/").slice(1);
56983
+ const binTarget = join28("/", orig[binKey].replace(/\\/g, "/")).replace(/\\/g, "/").slice(1);
56528
56984
  if (!binTarget) {
56529
56985
  return;
56530
56986
  }
@@ -56834,13 +57290,13 @@ var require_is = __commonJS({
56834
57290
  var require_find = __commonJS({
56835
57291
  "../../node_modules/.pnpm/@npmcli+git@6.0.3/node_modules/@npmcli/git/lib/find.js"(exports, module) {
56836
57292
  var is = require_is();
56837
- var { dirname: dirname15 } = __require("path");
57293
+ var { dirname: dirname16 } = __require("path");
56838
57294
  module.exports = async ({ cwd = process.cwd(), root } = {}) => {
56839
57295
  while (true) {
56840
57296
  if (await is({ cwd })) {
56841
57297
  return cwd;
56842
57298
  }
56843
- const next = dirname15(cwd);
57299
+ const next = dirname16(cwd);
56844
57300
  if (cwd === root || cwd === next) {
56845
57301
  return null;
56846
57302
  }
@@ -59065,11 +59521,11 @@ var require_normalize = __commonJS({
59065
59521
  // ../../node_modules/.pnpm/@npmcli+package-json@6.2.0/node_modules/@npmcli/package-json/lib/read-package.js
59066
59522
  var require_read_package = __commonJS({
59067
59523
  "../../node_modules/.pnpm/@npmcli+package-json@6.2.0/node_modules/@npmcli/package-json/lib/read-package.js"(exports, module) {
59068
- var { readFile: readFile31 } = __require("fs/promises");
59524
+ var { readFile: readFile32 } = __require("fs/promises");
59069
59525
  var parseJSON = require_lib16();
59070
59526
  async function read(filename) {
59071
59527
  try {
59072
- const data = await readFile31(filename, "utf8");
59528
+ const data = await readFile32(filename, "utf8");
59073
59529
  return data;
59074
59530
  } catch (err) {
59075
59531
  err.message = `Could not read package.json: ${err}`;
@@ -59202,8 +59658,8 @@ var require_sort2 = __commonJS({
59202
59658
  // ../../node_modules/.pnpm/@npmcli+package-json@6.2.0/node_modules/@npmcli/package-json/lib/index.js
59203
59659
  var require_lib23 = __commonJS({
59204
59660
  "../../node_modules/.pnpm/@npmcli+package-json@6.2.0/node_modules/@npmcli/package-json/lib/index.js"(exports, module) {
59205
- var { readFile: readFile31, writeFile: writeFile11 } = __require("node:fs/promises");
59206
- var { resolve: resolve26 } = __require("node:path");
59661
+ var { readFile: readFile32, writeFile: writeFile11 } = __require("node:fs/promises");
59662
+ var { resolve: resolve27 } = __require("node:path");
59207
59663
  var parseJSON = require_lib16();
59208
59664
  var updateDeps = require_update_dependencies();
59209
59665
  var updateScripts = require_update_scripts();
@@ -59326,10 +59782,10 @@ var require_lib23 = __commonJS({
59326
59782
  parseErr = err;
59327
59783
  }
59328
59784
  if (parseErr) {
59329
- const indexFile = resolve26(this.path, "index.js");
59785
+ const indexFile = resolve27(this.path, "index.js");
59330
59786
  let indexFileContent;
59331
59787
  try {
59332
- indexFileContent = await readFile31(indexFile, "utf8");
59788
+ indexFileContent = await readFile32(indexFile, "utf8");
59333
59789
  } catch (err) {
59334
59790
  throw parseErr;
59335
59791
  }
@@ -59378,7 +59834,7 @@ var require_lib23 = __commonJS({
59378
59834
  }
59379
59835
  get filename() {
59380
59836
  if (this.path) {
59381
- return resolve26(this.path, "package.json");
59837
+ return resolve27(this.path, "package.json");
59382
59838
  }
59383
59839
  return void 0;
59384
59840
  }
@@ -66304,12 +66760,12 @@ var require_fetcher = __commonJS({
66304
66760
  };
66305
66761
  exports.DefaultFetcher = DefaultFetcher;
66306
66762
  var writeBufferToStream = /* @__PURE__ */ __name(async (stream, buffer) => {
66307
- return new Promise((resolve26, reject) => {
66763
+ return new Promise((resolve27, reject) => {
66308
66764
  stream.write(buffer, (err) => {
66309
66765
  if (err) {
66310
66766
  reject(err);
66311
66767
  }
66312
- resolve26(true);
66768
+ resolve27(true);
66313
66769
  });
66314
66770
  });
66315
66771
  }, "writeBufferToStream");
@@ -66528,12 +66984,12 @@ var require_url = __commonJS({
66528
66984
  "../../node_modules/.pnpm/tuf-js@3.1.0/node_modules/tuf-js/dist/utils/url.js"(exports) {
66529
66985
  "use strict";
66530
66986
  Object.defineProperty(exports, "__esModule", { value: true });
66531
- exports.join = join27;
66987
+ exports.join = join28;
66532
66988
  var url_1 = __require("url");
66533
- function join27(base, path3) {
66989
+ function join28(base, path3) {
66534
66990
  return new url_1.URL(ensureTrailingSlash(base) + removeLeadingSlash(path3)).toString();
66535
66991
  }
66536
- __name(join27, "join");
66992
+ __name(join28, "join");
66537
66993
  function ensureTrailingSlash(path3) {
66538
66994
  return path3.endsWith("/") ? path3 : path3 + "/";
66539
66995
  }
@@ -66912,7 +67368,7 @@ var require_target = __commonJS({
66912
67368
  var error_1 = require_error8();
66913
67369
  async function readTarget(tuf, targetPath) {
66914
67370
  const path3 = await getTargetPath(tuf, targetPath);
66915
- return new Promise((resolve26, reject) => {
67371
+ return new Promise((resolve27, reject) => {
66916
67372
  fs_1.default.readFile(path3, "utf-8", (err, data) => {
66917
67373
  if (err) {
66918
67374
  reject(new error_1.TUFError({
@@ -66921,7 +67377,7 @@ var require_target = __commonJS({
66921
67377
  cause: err
66922
67378
  }));
66923
67379
  } else {
66924
- resolve26(data);
67380
+ resolve27(data);
66925
67381
  }
66926
67382
  });
66927
67383
  });
@@ -68638,7 +69094,7 @@ var require_dist15 = __commonJS({
68638
69094
  var require_provenance = __commonJS({
68639
69095
  "../../node_modules/.pnpm/libnpmpublish@11.1.0/node_modules/libnpmpublish/lib/provenance.js"(exports, module) {
68640
69096
  var sigstore = require_dist15();
68641
- var { readFile: readFile31 } = __require("node:fs/promises");
69097
+ var { readFile: readFile32 } = __require("node:fs/promises");
68642
69098
  var ci = require_ci_info();
68643
69099
  var { env } = process;
68644
69100
  var INTOTO_PAYLOAD_TYPE = "application/vnd.in-toto+json";
@@ -68830,7 +69286,7 @@ var require_provenance = __commonJS({
68830
69286
  var verifyProvenance = /* @__PURE__ */ __name(async (subject, provenancePath) => {
68831
69287
  let provenanceBundle;
68832
69288
  try {
68833
- provenanceBundle = JSON.parse(await readFile31(provenancePath));
69289
+ provenanceBundle = JSON.parse(await readFile32(provenancePath));
68834
69290
  } catch (err) {
68835
69291
  err.message = `Invalid provenance provided: ${err.message}`;
68836
69292
  throw err;
@@ -69169,9 +69625,9 @@ import { createHash as createHash9, randomUUID } from "node:crypto";
69169
69625
  import { execFile as execFileCb6, spawn as spawn3 } from "node:child_process";
69170
69626
  import { gunzipSync } from "node:zlib";
69171
69627
  import { promisify as promisify6 } from "node:util";
69172
- import { dirname as dirname7, isAbsolute as isAbsolute12, join as join12, relative as relative14, resolve as resolve16 } from "node:path";
69628
+ import { dirname as dirname8, isAbsolute as isAbsolute13, join as join13, relative as relative15, resolve as resolve17 } from "node:path";
69173
69629
  import { constants as fsConstants4 } from "node:fs";
69174
- import { chmod as chmod3, lstat as lstat9, mkdtemp as mkdtemp2, open as open6, readFile as readFile14, realpath as realpath9, rm as rm5 } from "node:fs/promises";
69630
+ import { chmod as chmod3, lstat as lstat10, mkdtemp as mkdtemp2, open as open6, readFile as readFile15, realpath as realpath9, rm as rm5 } from "node:fs/promises";
69175
69631
  function validatePackageName(value) {
69176
69632
  if (typeof value !== "string" || value.length > 214 || !SAFE_PACKAGE_NAME.test(value)) {
69177
69633
  throw new Error("npm package must be a safe lowercase package name or @scope/name");
@@ -69225,7 +69681,7 @@ function expandNpmrcValue(raw, env) {
69225
69681
  async function tokensFromNpmrc(path3, key, env) {
69226
69682
  let contents;
69227
69683
  try {
69228
- contents = await readFile14(path3, "utf8");
69684
+ contents = await readFile15(path3, "utf8");
69229
69685
  } catch (err) {
69230
69686
  if (err?.code === "ENOENT") return [];
69231
69687
  throw new Error("cannot read npm authentication config");
@@ -69248,7 +69704,7 @@ async function defaultResolveAuthToken({ registry, cwd, exec, env = process.env
69248
69704
  if (env[name]) candidates.push(env[name]);
69249
69705
  }
69250
69706
  const key = registryTokenKey(registry);
69251
- candidates.push(...await tokensFromNpmrc(join12(cwd, ".npmrc"), key, env));
69707
+ candidates.push(...await tokensFromNpmrc(join13(cwd, ".npmrc"), key, env));
69252
69708
  const npmUserConfigKey = ["npm", "config", "userconfig"].join("_");
69253
69709
  const userConfig = env[npmUserConfigKey] ?? (await exec("npm", ["config", "get", "userconfig"], { cwd, shell: false })).stdout.trim();
69254
69710
  if (userConfig) candidates.push(...await tokensFromNpmrc(userConfig, key, env));
@@ -69277,10 +69733,10 @@ async function defaultWhoamiWithToken({ registry, token, cwd, exec }) {
69277
69733
  }
69278
69734
  function resolvePackageCwd(cwd, root) {
69279
69735
  if (!cwd || typeof cwd !== "string") throw new Error("NPM_PUBLISH requires a non-empty action.cwd (package directory)");
69280
- const rootPath = resolve16(root);
69281
- const packagePath = resolve16(root, cwd);
69282
- const rel = relative14(rootPath, packagePath);
69283
- if (isAbsolute12(rel) || rel === ".." || rel.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`)) {
69736
+ const rootPath = resolve17(root);
69737
+ const packagePath = resolve17(root, cwd);
69738
+ const rel = relative15(rootPath, packagePath);
69739
+ if (isAbsolute13(rel) || rel === ".." || rel.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`)) {
69284
69740
  throw new Error(`cwd "${cwd}" is outside project root "${root}"`);
69285
69741
  }
69286
69742
  return packagePath;
@@ -69293,15 +69749,15 @@ ${error?.message ?? ""}`;
69293
69749
  return /\bE404\b|\b404\b.*not found|not found.*\b404\b/i.test(text);
69294
69750
  }
69295
69751
  async function readVerifiedTarballBytes(action, root) {
69296
- if (!action.tarballPath || isAbsolute12(action.tarballPath)) throw new Error("tarballPath must be project-relative");
69752
+ if (!action.tarballPath || isAbsolute13(action.tarballPath)) throw new Error("tarballPath must be project-relative");
69297
69753
  if (!/^[a-f0-9]{64}$/.test(action.tarballSha256 ?? "")) throw new Error("tarballSha256 must be a lowercase SHA-256 digest");
69298
69754
  const rootReal = await realpath9(root);
69299
- const lexical = resolve16(rootReal, action.tarballPath);
69300
- const rel = relative14(rootReal, lexical);
69301
- if (isAbsolute12(rel) || rel === ".." || rel.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`)) {
69755
+ const lexical = resolve17(rootReal, action.tarballPath);
69756
+ const rel = relative15(rootReal, lexical);
69757
+ if (isAbsolute13(rel) || rel === ".." || rel.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`)) {
69302
69758
  throw new Error("tarballPath escapes project root");
69303
69759
  }
69304
- const before = await lstat9(lexical);
69760
+ const before = await lstat10(lexical);
69305
69761
  if (!before.isFile() || before.isSymbolicLink() || before.nlink !== 1) {
69306
69762
  throw new Error("frozen tarball must be a single-link regular file");
69307
69763
  }
@@ -69567,7 +70023,7 @@ function createNpmAdapter(deps = {}) {
69567
70023
  throw new Error("npm bearer authentication does not match the frozen registry and publisher");
69568
70024
  }
69569
70025
  if (typeof beforeBufferPublishHook === "function") {
69570
- await beforeBufferPublishHook(resolve16(context.root, action.tarballPath));
70026
+ await beforeBufferPublishHook(resolve17(context.root, action.tarballPath));
69571
70027
  }
69572
70028
  try {
69573
70029
  await publishTarballBuffer({
@@ -69729,19 +70185,19 @@ var init_npm = __esm({
69729
70185
  });
69730
70186
 
69731
70187
  // src/core/run.mjs
69732
- import { link as link2, lstat as lstat10, mkdir as mkdir9, open as open7, readFile as readFile15, unlink as unlink3 } from "node:fs/promises";
70188
+ import { link as link2, lstat as lstat11, mkdir as mkdir9, open as open7, readFile as readFile16, unlink as unlink3 } from "node:fs/promises";
69733
70189
  import { realpathSync as realpathSync3 } from "node:fs";
69734
- import { dirname as dirname8, join as join13, resolve as resolve17, basename as basename4, relative as relative15, isAbsolute as isAbsolute13 } from "node:path";
70190
+ import { dirname as dirname9, join as join14, resolve as resolve18, basename as basename4, relative as relative16, isAbsolute as isAbsolute14 } from "node:path";
69735
70191
  function resolveDefaultRunDir(planPath, command2, runId = `${command2}-${Date.now()}`) {
69736
- const absolute = resolve17(planPath);
70192
+ const absolute = resolve18(planPath);
69737
70193
  const fileName = basename4(absolute);
69738
- const parentDir = dirname8(absolute);
70194
+ const parentDir = dirname9(absolute);
69739
70195
  if (fileName === "release-plan.json") {
69740
70196
  return `${parentDir}/runs/${runId}`;
69741
70197
  }
69742
70198
  if (basename4(parentDir) === "plans") {
69743
- const releaseDir = dirname8(parentDir);
69744
- return join13(releaseDir, "runs", runId);
70199
+ const releaseDir = dirname9(parentDir);
70200
+ return join14(releaseDir, "runs", runId);
69745
70201
  }
69746
70202
  return `${parentDir}/runs/${runId}`;
69747
70203
  }
@@ -69781,7 +70237,7 @@ function validateRun(run5, options = {}) {
69781
70237
  async function loadRun(runPath, options = {}) {
69782
70238
  let raw;
69783
70239
  try {
69784
- raw = await readFile15(runPath, "utf8");
70240
+ raw = await readFile16(runPath, "utf8");
69785
70241
  } catch (err) {
69786
70242
  throw new ReleaseError(
69787
70243
  GATE_FAILED,
@@ -69806,29 +70262,29 @@ async function loadRun(runPath, options = {}) {
69806
70262
  return run5;
69807
70263
  }
69808
70264
  function assertImmutableRunAuthority(runPath, planPath, run5) {
69809
- const absolutePlan = realpathSync3(resolve17(planPath));
69810
- const planDir = dirname8(absolutePlan);
70265
+ const absolutePlan = realpathSync3(resolve18(planPath));
70266
+ const planDir = dirname9(absolutePlan);
69811
70267
  if (basename4(planDir) !== "plans") {
69812
70268
  throw new ReleaseError(GATE_FAILED, "run authority requires an immutable plans/<digest>.json plan path");
69813
70269
  }
69814
- let authorityRoot = dirname8(planDir);
70270
+ let authorityRoot = dirname9(planDir);
69815
70271
  let cursor = planDir;
69816
- while (dirname8(cursor) !== cursor) {
70272
+ while (dirname9(cursor) !== cursor) {
69817
70273
  if (basename4(cursor) === ".release-skill") {
69818
70274
  authorityRoot = cursor;
69819
70275
  break;
69820
70276
  }
69821
- cursor = dirname8(cursor);
70277
+ cursor = dirname9(cursor);
69822
70278
  }
69823
- const runsDir = join13(authorityRoot, "runs");
69824
- const absoluteRun = realpathSync3(resolve17(runPath));
69825
- const rel = relative15(runsDir, absoluteRun);
69826
- if (isAbsolute13(rel) || rel === ".." || rel.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`)) {
70279
+ const runsDir = join14(authorityRoot, "runs");
70280
+ const absoluteRun = realpathSync3(resolve18(runPath));
70281
+ const rel = relative16(runsDir, absoluteRun);
70282
+ if (isAbsolute14(rel) || rel === ".." || rel.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`)) {
69827
70283
  throw new ReleaseError(GATE_FAILED, "production run authority must be inside the plan sibling runs/ directory");
69828
70284
  }
69829
70285
  const fileName = basename4(absoluteRun);
69830
70286
  const isFinal = fileName === "release-run.json";
69831
- const isState = /^\d{6}\.json$/.test(fileName) && basename4(dirname8(absoluteRun)) === "states" && run5.stateSequence === Number(fileName.slice(0, 6));
70287
+ const isState = /^\d{6}\.json$/.test(fileName) && basename4(dirname9(absoluteRun)) === "states" && run5.stateSequence === Number(fileName.slice(0, 6));
69832
70288
  if (!isFinal && !isState) {
69833
70289
  throw new ReleaseError(
69834
70290
  GATE_FAILED,
@@ -69838,19 +70294,19 @@ function assertImmutableRunAuthority(runPath, planPath, run5) {
69838
70294
  }
69839
70295
  }
69840
70296
  async function createProductionRunDir(runDir, planPath) {
69841
- const absolutePlan = realpathSync3(resolve17(planPath));
69842
- const planDir = dirname8(absolutePlan);
70297
+ const absolutePlan = realpathSync3(resolve18(planPath));
70298
+ const planDir = dirname9(absolutePlan);
69843
70299
  if (basename4(planDir) !== "plans") {
69844
70300
  throw new ReleaseError(GATE_FAILED, "production run directory requires an immutable plans/<digest>.json authority");
69845
70301
  }
69846
- const authorityRoot = dirname8(planDir);
70302
+ const authorityRoot = dirname9(planDir);
69847
70303
  return createProductionRunDirWithinAuthority(runDir, authorityRoot);
69848
70304
  }
69849
70305
  async function createProductionPrepareRunDir(runDir, releaseDir) {
69850
- const authorityRoot = resolve17(releaseDir);
70306
+ const authorityRoot = resolve18(releaseDir);
69851
70307
  let authorityStat;
69852
70308
  try {
69853
- authorityStat = await lstat10(authorityRoot);
70309
+ authorityStat = await lstat11(authorityRoot);
69854
70310
  } catch (error) {
69855
70311
  throw new ReleaseError(GATE_FAILED, "cannot inspect production .release-skill authority root", {
69856
70312
  releaseDir: authorityRoot,
@@ -69875,10 +70331,10 @@ async function createProductionPrepareRunDir(runDir, releaseDir) {
69875
70331
  return createProductionRunDirWithinAuthority(runDir, physicalAuthorityRoot);
69876
70332
  }
69877
70333
  async function createProductionRunDirWithinAuthority(runDir, authorityRoot) {
69878
- const runsDir = join13(authorityRoot, "runs");
70334
+ const runsDir = join14(authorityRoot, "runs");
69879
70335
  let runsStat;
69880
70336
  try {
69881
- runsStat = await lstat10(runsDir);
70337
+ runsStat = await lstat11(runsDir);
69882
70338
  } catch (error) {
69883
70339
  if (error.code !== "ENOENT") {
69884
70340
  throw new ReleaseError(GATE_FAILED, "cannot inspect production runs authority root", {
@@ -69896,7 +70352,7 @@ async function createProductionRunDirWithinAuthority(runDir, authorityRoot) {
69896
70352
  });
69897
70353
  }
69898
70354
  }
69899
- runsStat = await lstat10(runsDir);
70355
+ runsStat = await lstat11(runsDir);
69900
70356
  }
69901
70357
  if (runsStat.isSymbolicLink() || !runsStat.isDirectory()) {
69902
70358
  throw new ReleaseError(
@@ -69913,10 +70369,10 @@ async function createProductionRunDirWithinAuthority(runDir, authorityRoot) {
69913
70369
  { runsDir, physicalRunsDir }
69914
70370
  );
69915
70371
  }
69916
- const requested = resolve17(runDir);
70372
+ const requested = resolve18(runDir);
69917
70373
  let physicalParent;
69918
70374
  try {
69919
- physicalParent = realpathSync3(dirname8(requested));
70375
+ physicalParent = realpathSync3(dirname9(requested));
69920
70376
  } catch (error) {
69921
70377
  throw new ReleaseError(GATE_FAILED, "production run directory parent is unavailable", {
69922
70378
  runDir,
@@ -69931,7 +70387,7 @@ async function createProductionRunDirWithinAuthority(runDir, authorityRoot) {
69931
70387
  );
69932
70388
  }
69933
70389
  try {
69934
- await lstat10(requested);
70390
+ await lstat11(requested);
69935
70391
  throw new ReleaseError(GATE_FAILED, "production run directory already exists; authority directories cannot be reused", { runDir });
69936
70392
  } catch (error) {
69937
70393
  if (error instanceof ReleaseError) throw error;
@@ -69951,7 +70407,7 @@ async function createProductionRunDirWithinAuthority(runDir, authorityRoot) {
69951
70407
  });
69952
70408
  }
69953
70409
  const physicalRunDir = realpathSync3(requested);
69954
- if (dirname8(physicalRunDir) !== physicalRunsDir) {
70410
+ if (dirname9(physicalRunDir) !== physicalRunsDir) {
69955
70411
  throw new ReleaseError(GATE_FAILED, "production run directory escaped its immutable authority after creation", { runDir });
69956
70412
  }
69957
70413
  return physicalRunDir;
@@ -69964,12 +70420,12 @@ async function validateStatePredecessorChain(run5, runPath, options = {}) {
69964
70420
  return;
69965
70421
  }
69966
70422
  let current = run5;
69967
- let currentPath = realpathSync3(resolve17(runPath));
70423
+ let currentPath = realpathSync3(resolve18(runPath));
69968
70424
  let traversed = 0;
69969
70425
  while (true) {
69970
70426
  const sequence = current.stateSequence;
69971
70427
  const expectedName = `${String(sequence).padStart(6, "0")}.json`;
69972
- if (!Number.isSafeInteger(sequence) || sequence < 0 || basename4(currentPath) !== expectedName || basename4(dirname8(currentPath)) !== "states") {
70428
+ if (!Number.isSafeInteger(sequence) || sequence < 0 || basename4(currentPath) !== expectedName || basename4(dirname9(currentPath)) !== "states") {
69973
70429
  throw new ReleaseError(GATE_FAILED, "run state sequence is not bound to its immutable states/<sequence>.json slot");
69974
70430
  }
69975
70431
  if (sequence === 0) {
@@ -69985,7 +70441,7 @@ async function validateStatePredecessorChain(run5, runPath, options = {}) {
69985
70441
  if (traversed > 1e5) {
69986
70442
  throw new ReleaseError(GATE_FAILED, "run state predecessor chain exceeds maximum depth");
69987
70443
  }
69988
- const previousPath = join13(dirname8(currentPath), `${String(sequence - 1).padStart(6, "0")}.json`);
70444
+ const previousPath = join14(dirname9(currentPath), `${String(sequence - 1).padStart(6, "0")}.json`);
69989
70445
  const previous = await loadRun(previousPath, {
69990
70446
  requireDigest: true,
69991
70447
  ...options.production ? { authorityPlanPath: options.planPath } : {}
@@ -70078,7 +70534,7 @@ function validateRunPlanDigest(run5, plan, options = {}) {
70078
70534
  { runDigest: run5.planDigest, planDigest: expectedDigest }
70079
70535
  );
70080
70536
  }
70081
- if (plan.production && run5.planPath && options.planPath && resolve17(run5.planPath) !== resolve17(options.planPath)) {
70537
+ if (plan.production && run5.planPath && options.planPath && resolve18(run5.planPath) !== resolve18(options.planPath)) {
70082
70538
  throw new ReleaseError(
70083
70539
  GATE_FAILED,
70084
70540
  "source run immutable plan path does not match the supplied plan authority",
@@ -70160,7 +70616,7 @@ async function syncDirectory(dir) {
70160
70616
  async function writeRunAtomic(runPath, run5) {
70161
70617
  const sealed = sealRun(run5);
70162
70618
  const json = JSON.stringify(sealed, null, 2);
70163
- const dir = dirname8(runPath);
70619
+ const dir = dirname9(runPath);
70164
70620
  const tmpPath = `${dir}/.release-run-${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`;
70165
70621
  await mkdir9(dir, { recursive: true });
70166
70622
  const handle = await open7(tmpPath, "wx", 384);
@@ -70176,7 +70632,7 @@ async function writeRunAtomic(runPath, run5) {
70176
70632
  await syncDirectory(dir);
70177
70633
  } catch (error) {
70178
70634
  if (error.code !== "EEXIST") throw error;
70179
- const existing = await readFile15(runPath, "utf8");
70635
+ const existing = await readFile16(runPath, "utf8");
70180
70636
  if (existing !== json) {
70181
70637
  throw new ReleaseError(
70182
70638
  GATE_FAILED,
@@ -70195,10 +70651,10 @@ async function appendRunState(runDir, sequence, run5) {
70195
70651
  if (!Number.isSafeInteger(sequence) || sequence < 0) {
70196
70652
  throw new ReleaseError(GATE_FAILED, "run state sequence must be a non-negative integer");
70197
70653
  }
70198
- const statesDir = join13(runDir, "states");
70654
+ const statesDir = join14(runDir, "states");
70199
70655
  let previousStateDigest;
70200
70656
  if (sequence > 0) {
70201
- const previousPath = join13(statesDir, `${String(sequence - 1).padStart(6, "0")}.json`);
70657
+ const previousPath = join14(statesDir, `${String(sequence - 1).padStart(6, "0")}.json`);
70202
70658
  const previous = await loadRun(previousPath, { requireDigest: true });
70203
70659
  if (previous.stateSequence !== sequence - 1 || previous.runId !== run5.runId || previous.command !== run5.command || previous.planDigest !== run5.planDigest) {
70204
70660
  throw new ReleaseError(
@@ -70215,7 +70671,7 @@ async function appendRunState(runDir, sequence, run5) {
70215
70671
  stateSequence: sequence,
70216
70672
  ...previousStateDigest ? { previousStateDigest } : {}
70217
70673
  });
70218
- const statePath = join13(statesDir, `${String(sequence).padStart(6, "0")}.json`);
70674
+ const statePath = join14(statesDir, `${String(sequence).padStart(6, "0")}.json`);
70219
70675
  await writeRunAtomic(statePath, state);
70220
70676
  return Object.freeze({ state, statePath });
70221
70677
  }
@@ -70267,8 +70723,8 @@ __export(plugin_marketplace_exports, {
70267
70723
  });
70268
70724
  import { execFile as execFileCb7 } from "node:child_process";
70269
70725
  import { promisify as promisify7 } from "node:util";
70270
- import { readFile as readFile16, stat as stat4, mkdir as mkdir10, readdir as readdir8, realpath as realpath10, lstat as lstat11 } from "node:fs/promises";
70271
- import { join as join14, resolve as resolve18, relative as relative16, isAbsolute as isAbsolute14, basename as basename5 } from "node:path";
70726
+ import { readFile as readFile17, stat as stat4, mkdir as mkdir10, readdir as readdir9, realpath as realpath10, lstat as lstat12 } from "node:fs/promises";
70727
+ import { join as join15, resolve as resolve19, relative as relative17, isAbsolute as isAbsolute15, basename as basename5 } from "node:path";
70272
70728
  import { createHash as createHash10 } from "node:crypto";
70273
70729
  function transportPayload(entries) {
70274
70730
  return entries.map(({ path: path3, type, mode, size, contentDigest }) => ({
@@ -70337,24 +70793,24 @@ async function resolvePluginManifestFromMarketplaceEntrySource(marketIndex, plug
70337
70793
  const entry = matches[0];
70338
70794
  const sourcePath = extractDeclaredPluginSource(platform.id, entry);
70339
70795
  const snapshotDirReal = await realpath10(snapshotDir).catch(() => snapshotDir);
70340
- const marketplaceRootAbs = marketplaceRootRel === "." ? snapshotDirReal : resolve18(snapshotDirReal, marketplaceRootRel);
70341
- const pluginRootAbs = resolve18(marketplaceRootAbs, sourcePath);
70796
+ const marketplaceRootAbs = marketplaceRootRel === "." ? snapshotDirReal : resolve19(snapshotDirReal, marketplaceRootRel);
70797
+ const pluginRootAbs = resolve19(marketplaceRootAbs, sourcePath);
70342
70798
  const pluginRootReal = await realpath10(pluginRootAbs).catch(() => null);
70343
70799
  if (!pluginRootReal) {
70344
70800
  throw new Error(`marketplace plugin entry source "${sourcePath}" does not exist in snapshot`);
70345
70801
  }
70346
- const containment = relative16(snapshotDirReal, pluginRootReal);
70347
- const sep4 = process.platform === "win32" ? "\\" : "/";
70348
- if (containment !== "" && (isAbsolute14(containment) || containment === ".." || containment.startsWith(`..${sep4}`))) {
70802
+ const containment = relative17(snapshotDirReal, pluginRootReal);
70803
+ const sep5 = process.platform === "win32" ? "\\" : "/";
70804
+ if (containment !== "" && (isAbsolute15(containment) || containment === ".." || containment.startsWith(`..${sep5}`))) {
70349
70805
  throw new Error(`marketplace plugin entry source "${sourcePath}" escapes the snapshot after symlink resolution`);
70350
70806
  }
70351
70807
  const manifestRelative = platform.manifestPaths.plugin;
70352
- const manifestAbs = resolve18(pluginRootReal, manifestRelative);
70353
- const pluginRootRelToSnapshot = relative16(snapshotDirReal, pluginRootReal);
70808
+ const manifestAbs = resolve19(pluginRootReal, manifestRelative);
70809
+ const pluginRootRelToSnapshot = relative17(snapshotDirReal, pluginRootReal);
70354
70810
  const fullManifestRelative = pluginRootRelToSnapshot === "" ? manifestRelative : `${pluginRootRelToSnapshot}/${manifestRelative}`;
70355
70811
  let raw;
70356
70812
  try {
70357
- raw = await readFile16(manifestAbs, "utf8");
70813
+ raw = await readFile17(manifestAbs, "utf8");
70358
70814
  } catch (err) {
70359
70815
  throw new Error(
70360
70816
  `plugin manifest not found at "${fullManifestRelative}": ${err.message}`
@@ -70385,7 +70841,7 @@ async function validateInstallationContractDigest(action, snapshotDirReal, platf
70385
70841
  includeMarketplaceEntry = hasMarketplacePath;
70386
70842
  if (includeMarketplaceEntry) {
70387
70843
  marketplaceIndexRelative = action.marketplaceIndexPath ?? platform.manifestPaths.marketplace;
70388
- const marketplacePath = resolve18(snapshotDirReal, marketplaceIndexRelative);
70844
+ const marketplacePath = resolve19(snapshotDirReal, marketplaceIndexRelative);
70389
70845
  const mkResult = await validateManifestFile(marketplacePath, ["name", "plugins"]);
70390
70846
  if (!mkResult.valid) {
70391
70847
  return { valid: false, error: `installationContractDigest \u9A8C\u8BC1\u5931\u8D25\uFF1A\u5E02\u573A\u7D22\u5F15\u8BFB\u53D6\u5931\u8D25\uFF1A${mkResult.error}` };
@@ -70431,7 +70887,7 @@ async function validateInstallationContractDigest(action, snapshotDirReal, platf
70431
70887
  pluginManifestRelative = readResult.manifestRelative ?? platform.manifestPaths.plugin;
70432
70888
  } else {
70433
70889
  pluginManifestRelative = platform.manifestPaths.plugin;
70434
- const pluginManifestPath = resolve18(snapshotDirReal, pluginManifestRelative);
70890
+ const pluginManifestPath = resolve19(snapshotDirReal, pluginManifestRelative);
70435
70891
  const manifestResult = await validateManifestFile(pluginManifestPath, ["name", "version"]);
70436
70892
  if (!manifestResult.valid) {
70437
70893
  return { valid: false, error: `installationContractDigest \u9A8C\u8BC1\u5931\u8D25\uFF1A\u63D2\u4EF6 manifest \u8BFB\u53D6\u5931\u8D25\uFF1A${manifestResult.error}` };
@@ -70468,7 +70924,7 @@ async function resolveInstalledPayloadSubpath(snapshotDir, sourceEntries, action
70468
70924
  if (!anchored) {
70469
70925
  throw new Error(`frozen snapshot is missing the marketplace manifest ${marketplaceRelative}`);
70470
70926
  }
70471
- const result = await validateManifestFile(resolve18(snapshotDir, marketplaceRelative), ["name", "plugins"]);
70927
+ const result = await validateManifestFile(resolve19(snapshotDir, marketplaceRelative), ["name", "plugins"]);
70472
70928
  if (!result.valid) {
70473
70929
  throw new Error(`frozen snapshot ${marketplaceRelative} invalid: ${result.error}`);
70474
70930
  }
@@ -70582,26 +71038,26 @@ async function resolveKimiEntrySkillFile(pluginRootReal, manifest, entrySkill) {
70582
71038
  }
70583
71039
  let entryAbs;
70584
71040
  if (manifest.skills === void 0 || manifest.skills === null) {
70585
- entryAbs = resolve18(pluginRootReal, "SKILL.md");
71041
+ entryAbs = resolve19(pluginRootReal, "SKILL.md");
70586
71042
  } else {
70587
71043
  const skillsRel = normalizeKimiSkillsRel(manifest.skills);
70588
- const skillsRootAbs = skillsRel === "" ? pluginRootReal : resolve18(pluginRootReal, skillsRel);
71044
+ const skillsRootAbs = skillsRel === "" ? pluginRootReal : resolve19(pluginRootReal, skillsRel);
70589
71045
  const skillsRootReal = await realpath10(skillsRootAbs).catch(() => null);
70590
71046
  if (!skillsRootReal) {
70591
71047
  throw new Error(`kimi manifest skills root does not exist: ${manifest.skills}`);
70592
71048
  }
70593
- const skillsContainment = relative16(pluginRootReal, skillsRootReal);
71049
+ const skillsContainment = relative17(pluginRootReal, skillsRootReal);
70594
71050
  const sepK = process.platform === "win32" ? "\\" : "/";
70595
- if (skillsContainment !== "" && (isAbsolute14(skillsContainment) || skillsContainment === ".." || skillsContainment.startsWith(`..${sepK}`))) {
71051
+ if (skillsContainment !== "" && (isAbsolute15(skillsContainment) || skillsContainment === ".." || skillsContainment.startsWith(`..${sepK}`))) {
70596
71052
  throw new Error(`kimi manifest skills "${manifest.skills}" escapes the plugin root after symlink resolution`);
70597
71053
  }
70598
- entryAbs = resolve18(skillsRootReal, entrySkill, "SKILL.md");
71054
+ entryAbs = resolve19(skillsRootReal, entrySkill, "SKILL.md");
70599
71055
  }
70600
71056
  let entryLexicalStat;
70601
71057
  try {
70602
- entryLexicalStat = await lstat11(entryAbs);
71058
+ entryLexicalStat = await lstat12(entryAbs);
70603
71059
  } catch {
70604
- throw new Error(`kimi entry skill not found: ${relative16(pluginRootReal, entryAbs) || "SKILL.md"}`);
71060
+ throw new Error(`kimi entry skill not found: ${relative17(pluginRootReal, entryAbs) || "SKILL.md"}`);
70605
71061
  }
70606
71062
  if (entryLexicalStat.isSymbolicLink()) {
70607
71063
  throw new Error("kimi entry skill must not be a symlink");
@@ -70611,11 +71067,11 @@ async function resolveKimiEntrySkillFile(pluginRootReal, manifest, entrySkill) {
70611
71067
  }
70612
71068
  const entryReal = await realpath10(entryAbs).catch(() => null);
70613
71069
  if (!entryReal) {
70614
- throw new Error(`kimi entry skill not found: ${relative16(pluginRootReal, entryAbs) || "SKILL.md"}`);
71070
+ throw new Error(`kimi entry skill not found: ${relative17(pluginRootReal, entryAbs) || "SKILL.md"}`);
70615
71071
  }
70616
- const entryContainment = relative16(pluginRootReal, entryReal);
71072
+ const entryContainment = relative17(pluginRootReal, entryReal);
70617
71073
  const sepE = process.platform === "win32" ? "\\" : "/";
70618
- if (entryContainment !== "" && (isAbsolute14(entryContainment) || entryContainment === ".." || entryContainment.startsWith(`..${sepE}`))) {
71074
+ if (entryContainment !== "" && (isAbsolute15(entryContainment) || entryContainment === ".." || entryContainment.startsWith(`..${sepE}`))) {
70619
71075
  throw new Error("kimi entry skill escapes the plugin root after symlink resolution");
70620
71076
  }
70621
71077
  return entryReal;
@@ -70653,26 +71109,26 @@ async function resolveCodeBuddyEntrySkillFile(pluginRootReal, manifest, entrySki
70653
71109
  }
70654
71110
  let entryAbs;
70655
71111
  if (manifest.skills === void 0 || manifest.skills === null) {
70656
- entryAbs = resolve18(pluginRootReal, "SKILL.md");
71112
+ entryAbs = resolve19(pluginRootReal, "SKILL.md");
70657
71113
  } else {
70658
71114
  const skillsRel = normalizeCodeBuddySkillsRel(manifest.skills);
70659
- const skillsRootAbs = skillsRel === "" ? pluginRootReal : resolve18(pluginRootReal, skillsRel);
71115
+ const skillsRootAbs = skillsRel === "" ? pluginRootReal : resolve19(pluginRootReal, skillsRel);
70660
71116
  const skillsRootReal = await realpath10(skillsRootAbs).catch(() => null);
70661
71117
  if (!skillsRootReal) {
70662
71118
  throw new Error(`codebuddy manifest skills root does not exist: ${manifest.skills}`);
70663
71119
  }
70664
- const skillsContainment = relative16(pluginRootReal, skillsRootReal);
71120
+ const skillsContainment = relative17(pluginRootReal, skillsRootReal);
70665
71121
  const sepK = process.platform === "win32" ? "\\" : "/";
70666
- if (skillsContainment !== "" && (isAbsolute14(skillsContainment) || skillsContainment === ".." || skillsContainment.startsWith(`..${sepK}`))) {
71122
+ if (skillsContainment !== "" && (isAbsolute15(skillsContainment) || skillsContainment === ".." || skillsContainment.startsWith(`..${sepK}`))) {
70667
71123
  throw new Error(`codebuddy manifest skills "${manifest.skills}" escapes the plugin root after symlink resolution`);
70668
71124
  }
70669
- entryAbs = resolve18(skillsRootReal, entrySkill, "SKILL.md");
71125
+ entryAbs = resolve19(skillsRootReal, entrySkill, "SKILL.md");
70670
71126
  }
70671
71127
  let entryLexicalStat;
70672
71128
  try {
70673
- entryLexicalStat = await lstat11(entryAbs);
71129
+ entryLexicalStat = await lstat12(entryAbs);
70674
71130
  } catch {
70675
- throw new Error(`codebuddy entry skill not found: ${relative16(pluginRootReal, entryAbs) || "SKILL.md"}`);
71131
+ throw new Error(`codebuddy entry skill not found: ${relative17(pluginRootReal, entryAbs) || "SKILL.md"}`);
70676
71132
  }
70677
71133
  if (entryLexicalStat.isSymbolicLink()) {
70678
71134
  throw new Error("codebuddy entry skill must not be a symlink");
@@ -70682,11 +71138,11 @@ async function resolveCodeBuddyEntrySkillFile(pluginRootReal, manifest, entrySki
70682
71138
  }
70683
71139
  const entryReal = await realpath10(entryAbs).catch(() => null);
70684
71140
  if (!entryReal) {
70685
- throw new Error(`codebuddy entry skill not found: ${relative16(pluginRootReal, entryAbs) || "SKILL.md"}`);
71141
+ throw new Error(`codebuddy entry skill not found: ${relative17(pluginRootReal, entryAbs) || "SKILL.md"}`);
70686
71142
  }
70687
- const entryContainment = relative16(pluginRootReal, entryReal);
71143
+ const entryContainment = relative17(pluginRootReal, entryReal);
70688
71144
  const sepE = process.platform === "win32" ? "\\" : "/";
70689
- if (entryContainment !== "" && (isAbsolute14(entryContainment) || entryContainment === ".." || entryContainment.startsWith(`..${sepE}`))) {
71145
+ if (entryContainment !== "" && (isAbsolute15(entryContainment) || entryContainment === ".." || entryContainment.startsWith(`..${sepE}`))) {
70690
71146
  throw new Error("codebuddy entry skill escapes the plugin root after symlink resolution");
70691
71147
  }
70692
71148
  return entryReal;
@@ -70803,7 +71259,7 @@ async function run2(cmd, args2, options = {}) {
70803
71259
  }
70804
71260
  async function validateManifestFile(manifestPath, requiredFields) {
70805
71261
  try {
70806
- const content = await readFile16(manifestPath, "utf8");
71262
+ const content = await readFile17(manifestPath, "utf8");
70807
71263
  const manifest = JSON.parse(content);
70808
71264
  const missing = requiredFields.filter((f) => !(f in manifest));
70809
71265
  return {
@@ -70825,7 +71281,7 @@ async function checkRequiredFiles(dir, requiredFiles) {
70825
71281
  const missing = [];
70826
71282
  for (const file of requiredFiles) {
70827
71283
  try {
70828
- await stat4(resolve18(dir, file));
71284
+ await stat4(resolve19(dir, file));
70829
71285
  } catch {
70830
71286
  missing.push(file);
70831
71287
  }
@@ -71552,7 +72008,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
71552
72008
  });
71553
72009
  }
71554
72010
  const externalManifestRelative = platform.manifestPaths.plugin;
71555
- const externalManifestPath = resolve18(snapshotDirReal, externalManifestRelative);
72011
+ const externalManifestPath = resolve19(snapshotDirReal, externalManifestRelative);
71556
72012
  const externalManifestResult = await validateManifestFile(externalManifestPath, ["name", "version"]);
71557
72013
  if (!externalManifestResult.valid) {
71558
72014
  return createResult({
@@ -71587,7 +72043,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
71587
72043
  error: `marketplace root resolution failed: ${mktRootErr.message}`
71588
72044
  });
71589
72045
  }
71590
- const marketplacePath = resolve18(snapshotDirReal, marketplaceRelative);
72046
+ const marketplacePath = resolve19(snapshotDirReal, marketplaceRelative);
71591
72047
  const marketplaceResult = await validateManifestFile(marketplacePath, ["name"]);
71592
72048
  if (!marketplaceResult.valid) {
71593
72049
  return createResult({
@@ -71630,8 +72086,8 @@ function createPluginMarketplaceAdapter(deps = {}) {
71630
72086
  error: sourceErr.message
71631
72087
  });
71632
72088
  }
71633
- const mktRootAbs = mktRoot === "." ? snapshotDirReal : resolve18(snapshotDirReal, mktRoot);
71634
- const sourceDirAbs = resolve18(mktRootAbs, sourcePath);
72089
+ const mktRootAbs = mktRoot === "." ? snapshotDirReal : resolve19(snapshotDirReal, mktRoot);
72090
+ const sourceDirAbs = resolve19(mktRootAbs, sourcePath);
71635
72091
  sourceDirReal = await realpath10(sourceDirAbs).catch(() => null);
71636
72092
  if (!sourceDirReal) {
71637
72093
  return createResult({
@@ -71640,8 +72096,8 @@ function createPluginMarketplaceAdapter(deps = {}) {
71640
72096
  error: `marketplace plugin entry source directory does not exist: ${sourcePath}`
71641
72097
  });
71642
72098
  }
71643
- const sourceRelCheck = relative16(snapshotDirReal, sourceDirReal);
71644
- if (sourceRelCheck.startsWith("..") || isAbsolute14(sourceRelCheck)) {
72099
+ const sourceRelCheck = relative17(snapshotDirReal, sourceDirReal);
72100
+ if (sourceRelCheck.startsWith("..") || isAbsolute15(sourceRelCheck)) {
71645
72101
  return createResult({
71646
72102
  actionType,
71647
72103
  status: ActionStatus.PREFLIGHT_FAILED,
@@ -71649,9 +72105,9 @@ function createPluginMarketplaceAdapter(deps = {}) {
71649
72105
  });
71650
72106
  }
71651
72107
  pluginRootForEntrySkill = sourceDirReal;
71652
- const pluginRootRelToSnapshot = relative16(snapshotDirReal, sourceDirReal) || ".";
72108
+ const pluginRootRelToSnapshot = relative17(snapshotDirReal, sourceDirReal) || ".";
71653
72109
  const manifestRelative = pluginRootRelToSnapshot === "." ? platform.manifestPaths.plugin : `${pluginRootRelToSnapshot}/${platform.manifestPaths.plugin}`;
71654
- const manifestPath = resolve18(snapshotDirReal, manifestRelative);
72110
+ const manifestPath = resolve19(snapshotDirReal, manifestRelative);
71655
72111
  const manifestResult = await validateManifestFile(manifestPath, ["name", "version"]);
71656
72112
  if (!manifestResult.valid) {
71657
72113
  return createResult({
@@ -71704,11 +72160,11 @@ function createPluginMarketplaceAdapter(deps = {}) {
71704
72160
  }
71705
72161
  } else {
71706
72162
  const pluginRootForSkill = pluginRootForEntrySkill || snapshotDirReal;
71707
- const entrySkillFile = resolve18(pluginRootForSkill, "skills", action.entrySkill, "SKILL.md");
72163
+ const entrySkillFile = resolve19(pluginRootForSkill, "skills", action.entrySkill, "SKILL.md");
71708
72164
  try {
71709
72165
  await stat4(entrySkillFile);
71710
72166
  } catch {
71711
- const skillRel = relative16(snapshotDirReal, entrySkillFile) || `skills/${action.entrySkill}/SKILL.md`;
72167
+ const skillRel = relative17(snapshotDirReal, entrySkillFile) || `skills/${action.entrySkill}/SKILL.md`;
71712
72168
  return createResult({
71713
72169
  actionType,
71714
72170
  status: ActionStatus.PREFLIGHT_FAILED,
@@ -71830,7 +72286,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
71830
72286
  }
71831
72287
  if (action.entryPoint) {
71832
72288
  try {
71833
- await exec(process.execPath, ["--check", resolve18(pluginDir, action.entryPoint)]);
72289
+ await exec(process.execPath, ["--check", resolve19(pluginDir, action.entryPoint)]);
71834
72290
  } catch (checkErr) {
71835
72291
  return createResult({
71836
72292
  actionType,
@@ -71888,12 +72344,12 @@ function createPluginMarketplaceAdapter(deps = {}) {
71888
72344
  }
71889
72345
  const consumer = action.consumer;
71890
72346
  const runDir = context.runDir;
71891
- const isolatedHome = resolve18(runDir, "consumers", `${consumer}-${action.plugin}`);
72347
+ const isolatedHome = resolve19(runDir, "consumers", `${consumer}-${action.plugin}`);
71892
72348
  const runDirReal = await realpath10(runDir).catch(() => runDir);
71893
72349
  const isolatedHomePreReal = await realpath10(isolatedHome).catch(() => isolatedHome);
71894
- const relToRun = relative16(runDirReal, isolatedHomePreReal);
72350
+ const relToRun = relative17(runDirReal, isolatedHomePreReal);
71895
72351
  const sepE = process.platform === "win32" ? "\\" : "/";
71896
- if (relToRun !== "" && (isAbsolute14(relToRun) || relToRun === ".." || relToRun.startsWith(`..${sepE}`))) {
72352
+ if (relToRun !== "" && (isAbsolute15(relToRun) || relToRun === ".." || relToRun.startsWith(`..${sepE}`))) {
71897
72353
  return createResult({
71898
72354
  actionType,
71899
72355
  status: ActionStatus.EXECUTE_FAILED,
@@ -71902,7 +72358,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
71902
72358
  }
71903
72359
  await mkdir10(isolatedHome, { recursive: true, mode: 448 });
71904
72360
  for (const subdir of platform.isolationSubdirs) {
71905
- await mkdir10(resolve18(isolatedHome, subdir), { recursive: true, mode: 448 });
72361
+ await mkdir10(resolve19(isolatedHome, subdir), { recursive: true, mode: 448 });
71906
72362
  }
71907
72363
  const cliCmd = platform.cli.binary;
71908
72364
  const baseEnv = { ...process.env, ...context.env };
@@ -71999,9 +72455,9 @@ function createPluginMarketplaceAdapter(deps = {}) {
71999
72455
  error: `plugin install JSON missing installedPath`
72000
72456
  });
72001
72457
  }
72002
- const installPathAbs = resolve18(installFields.installedPath);
72003
- const installPathRel = relative16(isolatedHome, installPathAbs);
72004
- if (isAbsolute14(installPathRel) || installPathRel === ".." || installPathRel.startsWith(`..${sepE}`)) {
72458
+ const installPathAbs = resolve19(installFields.installedPath);
72459
+ const installPathRel = relative17(isolatedHome, installPathAbs);
72460
+ if (isAbsolute15(installPathRel) || installPathRel === ".." || installPathRel.startsWith(`..${sepE}`)) {
72005
72461
  return createResult({
72006
72462
  actionType,
72007
72463
  status: ActionStatus.EXECUTE_FAILED,
@@ -72062,9 +72518,9 @@ function createPluginMarketplaceAdapter(deps = {}) {
72062
72518
  executedAt: (/* @__PURE__ */ new Date()).toISOString(),
72063
72519
  ...extraInstalledPathsAudit(executeBinding)
72064
72520
  };
72065
- const evidenceDir = resolve18(runDir, "evidence", `${consumer}-${action.plugin}`);
72521
+ const evidenceDir = resolve19(runDir, "evidence", `${consumer}-${action.plugin}`);
72066
72522
  await mkdir10(evidenceDir, { recursive: true, mode: 448 });
72067
- const evidencePath = resolve18(evidenceDir, "release-skill-install-evidence.json");
72523
+ const evidencePath = resolve19(evidenceDir, "release-skill-install-evidence.json");
72068
72524
  await writeEvidenceAtomic(evidencePath, evidence);
72069
72525
  const executeObservation = {
72070
72526
  ...evidence,
@@ -72117,7 +72573,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
72117
72573
  if (actionType === ActionType.PLUGIN_MANIFEST_VALIDATE) {
72118
72574
  const manifestPath = action.manifestPath;
72119
72575
  try {
72120
- const content = await readFile16(manifestPath, "utf8");
72576
+ const content = await readFile17(manifestPath, "utf8");
72121
72577
  const manifest = JSON.parse(content);
72122
72578
  return createResult({
72123
72579
  actionType,
@@ -72160,7 +72616,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
72160
72616
  observation: { installed: false, error: "context.runDir is required" }
72161
72617
  });
72162
72618
  }
72163
- const isolatedHome = resolve18(runDir, "consumers", `${consumer}-${action.plugin}`);
72619
+ const isolatedHome = resolve19(runDir, "consumers", `${consumer}-${action.plugin}`);
72164
72620
  const platform = PLATFORMS.find((p) => p.id === consumer) ?? null;
72165
72621
  if (!platform) {
72166
72622
  throw new Error(
@@ -72212,7 +72668,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
72212
72668
  }
72213
72669
  let requirement = null;
72214
72670
  try {
72215
- requirement = JSON.parse(await readFile16(resolve18(attestationDir, KIMI_REQUIREMENT_FILE), "utf8"));
72671
+ requirement = JSON.parse(await readFile17(resolve19(attestationDir, KIMI_REQUIREMENT_FILE), "utf8"));
72216
72672
  } catch {
72217
72673
  return createResult({
72218
72674
  actionType,
@@ -72236,7 +72692,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
72236
72692
  }
72237
72693
  let attestation = null;
72238
72694
  try {
72239
- attestation = JSON.parse(await readFile16(resolve18(attestationDir, KIMI_ATTESTATION_FILE), "utf8"));
72695
+ attestation = JSON.parse(await readFile17(resolve19(attestationDir, KIMI_ATTESTATION_FILE), "utf8"));
72240
72696
  } catch {
72241
72697
  return createResult({
72242
72698
  actionType,
@@ -72246,7 +72702,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
72246
72702
  manualInstallRequired: true,
72247
72703
  installUrl: requirement.installUrl,
72248
72704
  attestationDir,
72249
- error: `kimi attestation is missing; write ${resolve18(attestationDir, KIMI_ATTESTATION_FILE)} after the interactive install (${requirement.installUrl})`
72705
+ error: `kimi attestation is missing; write ${resolve19(attestationDir, KIMI_ATTESTATION_FILE)} after the interactive install (${requirement.installUrl})`
72250
72706
  }
72251
72707
  });
72252
72708
  }
@@ -72259,6 +72715,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
72259
72715
  });
72260
72716
  }
72261
72717
  const normalizedAttestation = attestationCheck.normalized;
72718
+ const requiresInstalledClosure = Boolean(context.plan?.skillResourceClosure);
72262
72719
  if (normalizedAttestation.result === "failed") {
72263
72720
  const errorMsg = `kimi human result: failed${normalizedAttestation.note ? ` (${normalizedAttestation.note})` : ""}`;
72264
72721
  return createResult({
@@ -72275,9 +72732,20 @@ function createPluginMarketplaceAdapter(deps = {}) {
72275
72732
  }
72276
72733
  });
72277
72734
  }
72735
+ if (requiresInstalledClosure && !normalizedAttestation.installPath) {
72736
+ return createResult({
72737
+ actionType,
72738
+ status: ActionStatus.OBSERVED,
72739
+ observation: {
72740
+ installed: false,
72741
+ error: "kimi attestation installPath is required by the skill resource closure gate"
72742
+ }
72743
+ });
72744
+ }
72745
+ let verifiedInstallPath = null;
72278
72746
  if (normalizedAttestation.installPath) {
72279
- const managedRoot = resolve18(attestationDir, "kimi-home", "plugins", "managed");
72280
- const installPathAbs = resolve18(normalizedAttestation.installPath);
72747
+ const managedRoot = resolve19(attestationDir, "kimi-home", "plugins", "managed");
72748
+ const installPathAbs = resolve19(normalizedAttestation.installPath);
72281
72749
  const managedRootReal = await realpath10(managedRoot).catch(() => null);
72282
72750
  if (!managedRootReal) {
72283
72751
  return createResult({
@@ -72291,7 +72759,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
72291
72759
  }
72292
72760
  let lexicalStat;
72293
72761
  try {
72294
- lexicalStat = await lstat11(installPathAbs);
72762
+ lexicalStat = await lstat12(installPathAbs);
72295
72763
  } catch {
72296
72764
  return createResult({
72297
72765
  actionType,
@@ -72323,9 +72791,9 @@ function createPluginMarketplaceAdapter(deps = {}) {
72323
72791
  }
72324
72792
  });
72325
72793
  }
72326
- const rel = relative16(managedRootReal, installPathReal2);
72327
- const sep5 = process.platform === "win32" ? "\\" : "/";
72328
- if (rel === "" || rel === ".." || isAbsolute14(rel) || rel.startsWith(`..${sep5}`)) {
72794
+ const rel = relative17(managedRootReal, installPathReal2);
72795
+ const sep6 = process.platform === "win32" ? "\\" : "/";
72796
+ if (rel === "" || rel === ".." || isAbsolute15(rel) || rel.startsWith(`..${sep6}`)) {
72329
72797
  return createResult({
72330
72798
  actionType,
72331
72799
  status: ActionStatus.OBSERVED,
@@ -72335,15 +72803,16 @@ function createPluginMarketplaceAdapter(deps = {}) {
72335
72803
  }
72336
72804
  });
72337
72805
  }
72806
+ verifiedInstallPath = installPathReal2;
72338
72807
  }
72339
72808
  let manifestDigest2 = action.manifestDigest;
72340
72809
  let payloadBinding2 = null;
72341
- if (normalizedAttestation.installPath) {
72810
+ if (verifiedInstallPath) {
72342
72811
  try {
72343
72812
  payloadBinding2 = await verifyInstalledMarketplacePayload(
72344
72813
  action,
72345
72814
  context,
72346
- normalizedAttestation.installPath,
72815
+ verifiedInstallPath,
72347
72816
  consumer
72348
72817
  );
72349
72818
  manifestDigest2 = payloadBinding2.manifestDigest;
@@ -72381,6 +72850,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
72381
72850
  entrySkillFound: true,
72382
72851
  manifestDigest: manifestDigest2,
72383
72852
  planDigest: boundPlanDigest,
72853
+ ...verifiedInstallPath ? { installPath: verifiedInstallPath } : {},
72384
72854
  ...extraInstalledPathsAudit(payloadBinding2)
72385
72855
  }
72386
72856
  });
@@ -72413,7 +72883,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
72413
72883
  }
72414
72884
  let requirement = null;
72415
72885
  try {
72416
- requirement = JSON.parse(await readFile16(resolve18(attestationDir, CODEBUDDY_REQUIREMENT_FILE), "utf8"));
72886
+ requirement = JSON.parse(await readFile17(resolve19(attestationDir, CODEBUDDY_REQUIREMENT_FILE), "utf8"));
72417
72887
  } catch {
72418
72888
  return createResult({
72419
72889
  actionType,
@@ -72437,7 +72907,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
72437
72907
  }
72438
72908
  let attestation = null;
72439
72909
  try {
72440
- attestation = JSON.parse(await readFile16(resolve18(attestationDir, CODEBUDDY_ATTESTATION_FILE), "utf8"));
72910
+ attestation = JSON.parse(await readFile17(resolve19(attestationDir, CODEBUDDY_ATTESTATION_FILE), "utf8"));
72441
72911
  } catch {
72442
72912
  return createResult({
72443
72913
  actionType,
@@ -72447,7 +72917,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
72447
72917
  manualInstallRequired: true,
72448
72918
  marketplaceSource: CODEBUDDY_MARKETPLACE_SOURCE,
72449
72919
  attestationDir,
72450
- error: `codebuddy attestation is missing; write ${resolve18(attestationDir, CODEBUDDY_ATTESTATION_FILE)} after the manual install (marketplace ${CODEBUDDY_MARKETPLACE_SOURCE})`
72920
+ error: `codebuddy attestation is missing; write ${resolve19(attestationDir, CODEBUDDY_ATTESTATION_FILE)} after the manual install (marketplace ${CODEBUDDY_MARKETPLACE_SOURCE})`
72451
72921
  }
72452
72922
  });
72453
72923
  }
@@ -72460,6 +72930,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
72460
72930
  });
72461
72931
  }
72462
72932
  const normalizedAttestation = attestationCheck.normalized;
72933
+ const requiresInstalledClosure = Boolean(context.plan?.skillResourceClosure);
72463
72934
  if (normalizedAttestation.result === "failed") {
72464
72935
  const errorMsg = `codebuddy human result: failed${normalizedAttestation.note ? ` (${normalizedAttestation.note})` : ""}`;
72465
72936
  return createResult({
@@ -72476,6 +72947,66 @@ function createPluginMarketplaceAdapter(deps = {}) {
72476
72947
  }
72477
72948
  });
72478
72949
  }
72950
+ let verifiedInstallPath = null;
72951
+ if (requiresInstalledClosure) {
72952
+ if (!normalizedAttestation.installPath) {
72953
+ return createResult({
72954
+ actionType,
72955
+ status: ActionStatus.OBSERVED,
72956
+ observation: {
72957
+ installed: false,
72958
+ error: "codebuddy attestation installPath is required by the skill resource closure gate"
72959
+ }
72960
+ });
72961
+ }
72962
+ if (!["desktop", "cli"].includes(normalizedAttestation.installChannel)) {
72963
+ return createResult({
72964
+ actionType,
72965
+ status: ActionStatus.OBSERVED,
72966
+ observation: {
72967
+ installed: false,
72968
+ error: 'codebuddy attestation installChannel must be "desktop" or "cli" when the skill resource closure gate is active'
72969
+ }
72970
+ });
72971
+ }
72972
+ const normalizedPath = normalizedAttestation.installPath.replaceAll("\\", "/");
72973
+ const expectedSuffix = `.workbuddy/plugins/marketplaces/${CODEBUDDY_MARKETPLACE_NAME}/plugins/${action.plugin}`;
72974
+ if (!normalizedPath.endsWith(expectedSuffix)) {
72975
+ return createResult({
72976
+ actionType,
72977
+ status: ActionStatus.OBSERVED,
72978
+ observation: {
72979
+ installed: false,
72980
+ error: `codebuddy attestation installPath must end with "${expectedSuffix}"`
72981
+ }
72982
+ });
72983
+ }
72984
+ const installPathAbs = resolve19(normalizedAttestation.installPath);
72985
+ let lexicalStat;
72986
+ try {
72987
+ lexicalStat = await lstat12(installPathAbs);
72988
+ } catch {
72989
+ return createResult({
72990
+ actionType,
72991
+ status: ActionStatus.OBSERVED,
72992
+ observation: {
72993
+ installed: false,
72994
+ error: `codebuddy attestation installPath does not exist: ${normalizedAttestation.installPath}`
72995
+ }
72996
+ });
72997
+ }
72998
+ if (lexicalStat.isSymbolicLink() || !lexicalStat.isDirectory()) {
72999
+ return createResult({
73000
+ actionType,
73001
+ status: ActionStatus.OBSERVED,
73002
+ observation: {
73003
+ installed: false,
73004
+ error: "codebuddy attestation installPath must be a real directory, not a symlink"
73005
+ }
73006
+ });
73007
+ }
73008
+ verifiedInstallPath = await realpath10(installPathAbs);
73009
+ }
72479
73010
  return createResult({
72480
73011
  actionType,
72481
73012
  status: ActionStatus.OBSERVED,
@@ -72493,7 +73024,8 @@ function createPluginMarketplaceAdapter(deps = {}) {
72493
73024
  entrySkill: action.entrySkill,
72494
73025
  entrySkillFound: true,
72495
73026
  manifestDigest: action.manifestDigest,
72496
- planDigest: boundPlanDigest
73027
+ planDigest: boundPlanDigest,
73028
+ ...verifiedInstallPath ? { installPath: verifiedInstallPath } : {}
72497
73029
  }
72498
73030
  });
72499
73031
  }
@@ -72513,13 +73045,13 @@ function createPluginMarketplaceAdapter(deps = {}) {
72513
73045
  if (codexAttestationDir) {
72514
73046
  let codexRequirement = null;
72515
73047
  try {
72516
- codexRequirement = JSON.parse(await readFile16(resolve18(codexAttestationDir, CODEX_REQUIREMENT_FILE), "utf8"));
73048
+ codexRequirement = JSON.parse(await readFile17(resolve19(codexAttestationDir, CODEX_REQUIREMENT_FILE), "utf8"));
72517
73049
  } catch {
72518
73050
  }
72519
73051
  if (codexRequirement && codexRequirement.planDigest === codexBoundPlanDigest && codexRequirement.plugin === action.plugin && codexRequirement.version === action.version && codexRequirement.repo === action.repo && codexRequirement.ref === (action.ref ?? `v${action.version}`) && (!action.entrySkill || codexRequirement.entrySkill === action.entrySkill)) {
72520
73052
  let codexAttestation = null;
72521
73053
  try {
72522
- codexAttestation = JSON.parse(await readFile16(resolve18(codexAttestationDir, CODEX_ATTESTATION_FILE), "utf8"));
73054
+ codexAttestation = JSON.parse(await readFile17(resolve19(codexAttestationDir, CODEX_ATTESTATION_FILE), "utf8"));
72523
73055
  } catch {
72524
73056
  }
72525
73057
  if (codexAttestation) {
@@ -72574,7 +73106,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
72574
73106
  }
72575
73107
  let evidence = null;
72576
73108
  try {
72577
- const evidenceRaw = await readFile16(resolve18(runDir, "evidence", `${consumer}-${action.plugin}`, "release-skill-install-evidence.json"), "utf8");
73109
+ const evidenceRaw = await readFile17(resolve19(runDir, "evidence", `${consumer}-${action.plugin}`, "release-skill-install-evidence.json"), "utf8");
72578
73110
  evidence = JSON.parse(evidenceRaw);
72579
73111
  } catch {
72580
73112
  return createResult({
@@ -72659,9 +73191,9 @@ function createPluginMarketplaceAdapter(deps = {}) {
72659
73191
  }
72660
73192
  const isolatedHomeReal = await realpath10(isolatedHome).catch(() => isolatedHome);
72661
73193
  const installPathReal = await realpath10(installPath).catch(() => installPath);
72662
- const relToHome = relative16(isolatedHomeReal, installPathReal);
72663
- const sep4 = process.platform === "win32" ? "\\" : "/";
72664
- if (relToHome !== "" && (isAbsolute14(relToHome) || relToHome === ".." || relToHome.startsWith(`..${sep4}`))) {
73194
+ const relToHome = relative17(isolatedHomeReal, installPathReal);
73195
+ const sep5 = process.platform === "win32" ? "\\" : "/";
73196
+ if (relToHome !== "" && (isAbsolute15(relToHome) || relToHome === ".." || relToHome.startsWith(`..${sep5}`))) {
72665
73197
  return createResult({
72666
73198
  actionType,
72667
73199
  status: ActionStatus.OBSERVED,
@@ -72671,10 +73203,10 @@ function createPluginMarketplaceAdapter(deps = {}) {
72671
73203
  }
72672
73204
  });
72673
73205
  }
72674
- const entrySkillPath = resolve18(installPath, "skills", action.entrySkill, "SKILL.md");
73206
+ const entrySkillPath = resolve19(installPath, "skills", action.entrySkill, "SKILL.md");
72675
73207
  let entrySkillFound = false;
72676
73208
  try {
72677
- const skillStat = await lstat11(entrySkillPath);
73209
+ const skillStat = await lstat12(entrySkillPath);
72678
73210
  if (skillStat.isFile() && !skillStat.isSymbolicLink()) {
72679
73211
  entrySkillFound = true;
72680
73212
  }
@@ -72740,8 +73272,8 @@ function createPluginMarketplaceAdapter(deps = {}) {
72740
73272
  });
72741
73273
  }
72742
73274
  try {
72743
- const installedManifestPath = resolve18(installPath, platform.manifestPaths.plugin);
72744
- const installedManifestContent = await readFile16(installedManifestPath, "utf8");
73275
+ const installedManifestPath = resolve19(installPath, platform.manifestPaths.plugin);
73276
+ const installedManifestContent = await readFile17(installedManifestPath, "utf8");
72745
73277
  const installedManifest = JSON.parse(installedManifestContent);
72746
73278
  const expectedName = observation.plugin;
72747
73279
  if (expectedName && installedManifest.name !== expectedName) {
@@ -72923,8 +73455,8 @@ var init_plugin_marketplace = __esm({
72923
73455
  });
72924
73456
 
72925
73457
  // src/artifacts/transaction-journal.mjs
72926
- import { readdir as readdir9, readFile as readFile17, rm as rm6, stat as stat5 } from "node:fs/promises";
72927
- import { join as join15 } from "node:path";
73458
+ import { readdir as readdir10, readFile as readFile18, rm as rm6, stat as stat5 } from "node:fs/promises";
73459
+ import { join as join16 } from "node:path";
72928
73460
  function failSchema(message, details) {
72929
73461
  throw new ReleaseError(TRANSACTION_INCOMPLETE, message, details);
72930
73462
  }
@@ -73921,7 +74453,7 @@ async function pruneTerminalTransactionRecords(transactionsRoot, {
73921
74453
  if (!Number.isInteger(retentionMax) || retentionMax < 0) return summary;
73922
74454
  let entries;
73923
74455
  try {
73924
- entries = await readdir9(transactionsRoot, { withFileTypes: true });
74456
+ entries = await readdir10(transactionsRoot, { withFileTypes: true });
73925
74457
  } catch (scanErr) {
73926
74458
  summary.errors.push(`scan: ${scanErr?.code || scanErr?.message || "readdir-failed"}`);
73927
74459
  return summary;
@@ -73931,11 +74463,11 @@ async function pruneTerminalTransactionRecords(transactionsRoot, {
73931
74463
  if (txnDirs.length <= retentionMax) return summary;
73932
74464
  const terminal = [];
73933
74465
  for (const entry of txnDirs) {
73934
- const recordDir = join15(transactionsRoot, entry.name);
74466
+ const recordDir = join16(transactionsRoot, entry.name);
73935
74467
  let state = null;
73936
74468
  let createdAt = null;
73937
74469
  try {
73938
- const raw = await readFile17(join15(recordDir, "journal.json"), "utf8");
74470
+ const raw = await readFile18(join16(recordDir, "journal.json"), "utf8");
73939
74471
  const journal = JSON.parse(raw);
73940
74472
  if (journal && typeof journal === "object") {
73941
74473
  state = typeof journal.state === "string" ? journal.state : null;
@@ -73999,7 +74531,7 @@ async function createTransactionJournal({
73999
74531
  );
74000
74532
  if (typeof root === "string" && root.length > 0) {
74001
74533
  await pruneTerminalTransactionRecords(
74002
- join15(root, ".release-skill", "transactions"),
74534
+ join16(root, ".release-skill", "transactions"),
74003
74535
  { retentionMax }
74004
74536
  );
74005
74537
  }
@@ -74363,7 +74895,7 @@ __export(transaction_exports, {
74363
74895
  applyWriteSetUnderLock: () => applyWriteSetUnderLock
74364
74896
  });
74365
74897
  import { randomBytes as randomBytes2 } from "node:crypto";
74366
- import { relative as relative17 } from "node:path";
74898
+ import { relative as relative18 } from "node:path";
74367
74899
  function computeCanonicalPlanDigest(plan) {
74368
74900
  const { planDigest: _ignored, ...content } = plan;
74369
74901
  return `sha256:${sha256Hex(canonicalJson(content))}`;
@@ -75276,7 +75808,7 @@ async function applyArtifactPlanUnderLock({
75276
75808
  }
75277
75809
  const handle = await safeFs.openRoot(root);
75278
75810
  try {
75279
- const relPlanPath = canonicalArtifactPath(relative17(root, planPath)).path;
75811
+ const relPlanPath = canonicalArtifactPath(relative18(root, planPath)).path;
75280
75812
  const planFileData = await withParentHandle(handle, relPlanPath, async (parent, leaf) => {
75281
75813
  const planEntry = await parent.readEntry(leaf);
75282
75814
  if (!planEntry || planEntry.kind === "absent") {
@@ -77691,7 +78223,7 @@ __export(refresh_service_exports, {
77691
78223
  planReleaseDocsRefreshForUnit: () => planReleaseDocsRefreshForUnit,
77692
78224
  runReleaseDocsRefresh: () => runReleaseDocsRefresh
77693
78225
  });
77694
- import { isAbsolute as isAbsolute15, relative as relative18, resolve as resolve19, sep as sep3 } from "node:path";
78226
+ import { isAbsolute as isAbsolute16, relative as relative19, resolve as resolve20, sep as sep4 } from "node:path";
77695
78227
  function deepFreeze7(value) {
77696
78228
  if (Array.isArray(value)) {
77697
78229
  for (const item of value) deepFreeze7(item);
@@ -77774,7 +78306,7 @@ async function planReleaseDocsRefreshForUnit({
77774
78306
  field: "unit.source"
77775
78307
  });
77776
78308
  }
77777
- const unitRoot = resolve19(root, unit.source);
78309
+ const unitRoot = resolve20(root, unit.source);
77778
78310
  const backend = await (backendFactory ?? loadSafeFs)();
77779
78311
  const sharedFactory = /* @__PURE__ */ __name(async () => backend, "sharedFactory");
77780
78312
  const notesSource = await loadReleaseNotesSource({
@@ -77984,16 +78516,16 @@ async function runReleaseDocsRefresh({
77984
78516
  });
77985
78517
  }
77986
78518
  const changedFiles = plan.files.filter((file) => file.changed);
77987
- const unitRoot = resolve19(root, unit.source);
77988
- const unitLocation = relative18(root, unitRoot);
77989
- if (unitLocation === ".." || unitLocation.startsWith(`..${sep3}`) || isAbsolute15(unitLocation)) {
78519
+ const unitRoot = resolve20(root, unit.source);
78520
+ const unitLocation = relative19(root, unitRoot);
78521
+ if (unitLocation === ".." || unitLocation.startsWith(`..${sep4}`) || isAbsolute16(unitLocation)) {
77990
78522
  throw new ReleaseError(
77991
78523
  PATH_UNSAFE,
77992
78524
  "release unit source escapes the project root",
77993
78525
  { reason: "UNIT_SOURCE_ESCAPE", unitId }
77994
78526
  );
77995
78527
  }
77996
- const unitPrefix = unitLocation === "" ? "" : `${unitLocation.split(sep3).join("/")}/`;
78528
+ const unitPrefix = unitLocation === "" ? "" : `${unitLocation.split(sep4).join("/")}/`;
77997
78529
  const projectPath = /* @__PURE__ */ __name((targetPath) => `${unitPrefix}${targetPath}`, "projectPath");
77998
78530
  const writeSet = changedFiles.map((file) => ({
77999
78531
  id: `${file.kind}:${projectPath(file.path)}`,
@@ -78044,7 +78576,7 @@ async function runReleaseDocsRefresh({
78044
78576
  if (err instanceof ReleaseError && err.code === TRANSACTION_INCOMPLETE && typeof err.details?.recover === "string") {
78045
78577
  const restored = await tryRestoreOldBytes(
78046
78578
  backend,
78047
- resolve19(root, unit.source),
78579
+ resolve20(root, unit.source),
78048
78580
  changedFiles,
78049
78581
  modes
78050
78582
  );
@@ -78144,8 +78676,8 @@ __export(prepare_exports, {
78144
78676
  resolveUnitVersion: () => resolveUnitVersion,
78145
78677
  runDeclaredHooks: () => runDeclaredHooks
78146
78678
  });
78147
- import { resolve as resolve20, relative as relative19, isAbsolute as isAbsolute16, normalize as normalize3, dirname as dirname9 } from "node:path";
78148
- import { readFile as readFile18, mkdir as mkdir11, realpath as realpath11 } from "node:fs/promises";
78679
+ import { resolve as resolve21, relative as relative20, isAbsolute as isAbsolute17, normalize as normalize3, dirname as dirname10 } from "node:path";
78680
+ import { readFile as readFile19, mkdir as mkdir11, realpath as realpath11 } from "node:fs/promises";
78149
78681
  import { execFile as execFileCb8 } from "node:child_process";
78150
78682
  import { promisify as promisify8 } from "node:util";
78151
78683
  async function resolveUnitVersion(unit, root, explicitVersion) {
@@ -78157,18 +78689,18 @@ async function resolveUnitVersion(unit, root, explicitVersion) {
78157
78689
  { unitId: unit.id }
78158
78690
  );
78159
78691
  }
78160
- if (isAbsolute16(versionSource)) {
78692
+ if (isAbsolute17(versionSource)) {
78161
78693
  throw new ReleaseError(
78162
78694
  CONFIG_INVALID,
78163
78695
  `unit "${unit.id}" version.source must be a relative path, got absolute: "${versionSource}"`,
78164
78696
  { unitId: unit.id, versionSource }
78165
78697
  );
78166
78698
  }
78167
- const unitRoot = resolve20(root, unit.source);
78168
- const resolvedPath = resolve20(unitRoot, versionSource);
78699
+ const unitRoot = resolve21(root, unit.source);
78700
+ const resolvedPath = resolve21(unitRoot, versionSource);
78169
78701
  const normalizedPath = normalize3(resolvedPath);
78170
- const rel = relative19(unitRoot, normalizedPath);
78171
- if (rel.startsWith("..") || rel === ".." || isAbsolute16(rel)) {
78702
+ const rel = relative20(unitRoot, normalizedPath);
78703
+ if (rel.startsWith("..") || rel === ".." || isAbsolute17(rel)) {
78172
78704
  throw new ReleaseError(
78173
78705
  CONFIG_INVALID,
78174
78706
  `unit "${unit.id}" version.source escapes unit root: "${versionSource}"`,
@@ -78177,7 +78709,7 @@ async function resolveUnitVersion(unit, root, explicitVersion) {
78177
78709
  }
78178
78710
  let content;
78179
78711
  try {
78180
- content = await readFile18(normalizedPath, "utf8");
78712
+ content = await readFile19(normalizedPath, "utf8");
78181
78713
  } catch (err) {
78182
78714
  throw new ReleaseError(
78183
78715
  CONFIG_INVALID,
@@ -78467,7 +78999,7 @@ async function processSnapshots(config, root, evidence, runDir, production = fal
78467
78999
  const unitResults = [];
78468
79000
  const snapshotDigests = [];
78469
79001
  for (const unit of units) {
78470
- const outputDir = resolveUnitScopedPath(resolve20(runDir, "snapshots"), unit.id);
79002
+ const outputDir = resolveUnitScopedPath(resolve21(runDir, "snapshots"), unit.id);
78471
79003
  await evidence.append({
78472
79004
  phase: "snapshot",
78473
79005
  status: "started",
@@ -78695,7 +79227,7 @@ async function buildProductionAssets(unitResults, resolvedVersions, root, runDir
78695
79227
  const { unit, manifest } = unitResults[index];
78696
79228
  const version = resolvedVersions[index];
78697
79229
  const { tag, branch, branchStrategy } = resolveProductionBranch(unit, version);
78698
- const snapshotPath = relative19(root, manifest.outputDir);
79230
+ const snapshotPath = relative20(root, manifest.outputDir);
78699
79231
  const observed = await computeFrozenSnapshot(manifest.outputDir);
78700
79232
  if (observed.digest !== manifest.snapshotDigest) {
78701
79233
  throw new ReleaseError(
@@ -78706,7 +79238,7 @@ async function buildProductionAssets(unitResults, resolvedVersions, root, runDir
78706
79238
  }
78707
79239
  await sealFrozenSnapshot(manifest.outputDir);
78708
79240
  const sealed = await computeFrozenSnapshot(manifest.outputDir);
78709
- const repositoryDir = resolveUnitScopedPath(resolve20(runDir, "git"), unit.id, { suffix: ".git" });
79241
+ const repositoryDir = resolveUnitScopedPath(resolve21(runDir, "git"), unit.id, { suffix: ".git" });
78710
79242
  const unitBaseline = unitBaselineResults.get(unit.id);
78711
79243
  const parent = branchStrategy === "create-release-branch" ? void 0 : {
78712
79244
  githubHost: unitBaseline.githubHost,
@@ -78727,13 +79259,13 @@ async function buildProductionAssets(unitResults, resolvedVersions, root, runDir
78727
79259
  if (npmDistribution) {
78728
79260
  npm = await buildFrozenNpmTarball({
78729
79261
  snapshotDir: manifest.outputDir,
78730
- tarballDir: resolveUnitScopedPath(resolve20(runDir, "tarballs"), unit.id),
79262
+ tarballDir: resolveUnitScopedPath(resolve21(runDir, "tarballs"), unit.id),
78731
79263
  expectedSnapshotDigest: sealed.digest
78732
79264
  });
78733
79265
  await verifyFrozenNpmTarballIdentity({
78734
79266
  package: npmDistribution.package,
78735
79267
  version,
78736
- tarballPath: relative19(root, npm.tarballPath),
79268
+ tarballPath: relative20(root, npm.tarballPath),
78737
79269
  tarballSha256: npm.sha256,
78738
79270
  integrity: npm.integrity
78739
79271
  }, root);
@@ -78741,7 +79273,7 @@ async function buildProductionAssets(unitResults, resolvedVersions, root, runDir
78741
79273
  assets.push({
78742
79274
  snapshotPath,
78743
79275
  manifestDigest: sealed.digest,
78744
- gitObjectDir: relative19(root, repositoryDir),
79276
+ gitObjectDir: relative20(root, repositoryDir),
78745
79277
  commit: git2.commit,
78746
79278
  tree: git2.tree,
78747
79279
  commitTimestamp: canonicalFreezeTimestamp,
@@ -78750,7 +79282,7 @@ async function buildProductionAssets(unitResults, resolvedVersions, root, runDir
78750
79282
  branch,
78751
79283
  tag,
78752
79284
  npm: npm ? {
78753
- tarballPath: relative19(root, npm.tarballPath),
79285
+ tarballPath: relative20(root, npm.tarballPath),
78754
79286
  tarballSha256: npm.sha256,
78755
79287
  integrity: npm.integrity,
78756
79288
  size: npm.size
@@ -79310,19 +79842,19 @@ async function prepareRelease(options) {
79310
79842
  );
79311
79843
  }
79312
79844
  if (production) {
79313
- const canonicalOutput = resolve20(realRoot, ".release-skill", "release-plan.json");
79314
- if (output && resolve20(output) !== canonicalOutput) {
79845
+ const canonicalOutput = resolve21(realRoot, ".release-skill", "release-plan.json");
79846
+ if (output && resolve21(output) !== canonicalOutput) {
79315
79847
  throw new ReleaseError(
79316
79848
  GATE_FAILED,
79317
79849
  "production prepare requires the canonical .release-skill/release-plan.json output; custom --output is supported only outside production",
79318
- { output: resolve20(output), expected: canonicalOutput }
79850
+ { output: resolve21(output), expected: canonicalOutput }
79319
79851
  );
79320
79852
  }
79321
79853
  }
79322
79854
  const lock = await acquireProjectLock({ root: realRoot, command: "prepare", mode: "exclusive" });
79323
- const releaseDir = resolve20(realRoot, ".release-skill");
79855
+ const releaseDir = resolve21(realRoot, ".release-skill");
79324
79856
  const runId = `prepare-${Date.now()}`;
79325
- const rawRunDir = runDirOpt ?? resolve20(releaseDir, "runs", runId);
79857
+ const rawRunDir = runDirOpt ?? resolve21(releaseDir, "runs", runId);
79326
79858
  let runDir;
79327
79859
  try {
79328
79860
  if (production) {
@@ -79343,7 +79875,7 @@ async function prepareRelease(options) {
79343
79875
  await evidence.append({
79344
79876
  phase: "config",
79345
79877
  status: "completed",
79346
- configPath: relative19(realRoot, configPath),
79878
+ configPath: relative20(realRoot, configPath),
79347
79879
  configDigest
79348
79880
  });
79349
79881
  const configUnits = config.releaseUnits ?? [];
@@ -79731,6 +80263,56 @@ To proceed, pass --acknowledge-hook-side-effects (CLI) or hooksAuthorized=true (
79731
80263
  options.buildFrozenGitRepositoryFn ?? buildFrozenGitRepository,
79732
80264
  freezeTimestamp
79733
80265
  ) : null;
80266
+ const skillResourceClosureResults = [];
80267
+ for (const { unit, manifest } of unitResults) {
80268
+ await evidence.append({
80269
+ phase: "skill-resource-closure",
80270
+ status: "started",
80271
+ unitId: unit.id
80272
+ });
80273
+ const closureResult = await checkSkillResourceClosure({
80274
+ snapshotDir: manifest.outputDir,
80275
+ host: "root"
80276
+ });
80277
+ const receipt = createSkillResourceClosureReceipt(closureResult, { unitId: unit.id });
80278
+ skillResourceClosureResults.push(receipt);
80279
+ if (closureResult.findings.length > 0) {
80280
+ await evidence.append({
80281
+ phase: "skill-resource-closure",
80282
+ status: "blocking",
80283
+ unitId: unit.id,
80284
+ findingCount: closureResult.findings.length,
80285
+ findings: closureResult.findings.map((f) => ({
80286
+ skill: f.skill,
80287
+ line: f.line,
80288
+ reference: f.reference,
80289
+ classification: f.classification,
80290
+ code: f.code
80291
+ }))
80292
+ });
80293
+ throw new ReleaseError(
80294
+ GATE_FAILED,
80295
+ `skill resource closure gate failed for unit "${unit.id}": ${closureResult.findings.length} finding(s)`,
80296
+ {
80297
+ unitId: unit.id,
80298
+ findingCount: closureResult.findings.length,
80299
+ findings: closureResult.findings
80300
+ }
80301
+ );
80302
+ }
80303
+ await evidence.append({
80304
+ phase: "skill-resource-closure",
80305
+ status: "completed",
80306
+ unitId: unit.id,
80307
+ checkerVersion: closureResult.checkerVersion,
80308
+ surfaceCount: receipt.surfaceCount,
80309
+ skillCount: receipt.skillCount,
80310
+ referenceCount: closureResult.referenceCount,
80311
+ sourceOnlyCount: closureResult.sourceOnlyCount,
80312
+ findingCount: 0,
80313
+ receiptDigest: closureResult.receiptDigest
80314
+ });
80315
+ }
79734
80316
  const externalMarketplaceFreezes = production ? await resolveExternalMarketplaceFreezes({
79735
80317
  unitResults,
79736
80318
  resolvedVersions,
@@ -79814,10 +80396,10 @@ To proceed, pass --acknowledge-hook-side-effects (CLI) or hooksAuthorized=true (
79814
80396
  { unitId: unit.id, distributionType: dist.type }
79815
80397
  );
79816
80398
  }
79817
- const marketplaceIndexPath = resolve20(snapshotDir, marketplaceIndexRelative);
80399
+ const marketplaceIndexPath = resolve21(snapshotDir, marketplaceIndexRelative);
79818
80400
  let marketplaceIndexRaw;
79819
80401
  try {
79820
- marketplaceIndexRaw = await readFile18(marketplaceIndexPath, "utf8");
80402
+ marketplaceIndexRaw = await readFile19(marketplaceIndexPath, "utf8");
79821
80403
  } catch (err) {
79822
80404
  throw new ReleaseError(
79823
80405
  GATE_FAILED,
@@ -79883,10 +80465,10 @@ To proceed, pass --acknowledge-hook-side-effects (CLI) or hooksAuthorized=true (
79883
80465
  pluginManifestRelative = readResult.manifestRelative ?? platform.manifestPaths.plugin;
79884
80466
  } else {
79885
80467
  pluginManifestRelative = platform.manifestPaths.plugin;
79886
- const pluginManifestPath = resolve20(snapshotDir, pluginManifestRelative);
80468
+ const pluginManifestPath = resolve21(snapshotDir, pluginManifestRelative);
79887
80469
  let raw;
79888
80470
  try {
79889
- raw = await readFile18(pluginManifestPath, "utf8");
80471
+ raw = await readFile19(pluginManifestPath, "utf8");
79890
80472
  } catch (err) {
79891
80473
  throw new ReleaseError(
79892
80474
  GATE_FAILED,
@@ -80003,12 +80585,20 @@ To proceed, pass --acknowledge-hook-side-effects (CLI) or hooksAuthorized=true (
80003
80585
  capturedAt: baseline.capturedAt
80004
80586
  },
80005
80587
  configDigest,
80588
+ skillResourceClosure: {
80589
+ checkerVersion: CHECKER_VERSION,
80590
+ unitReceipts: skillResourceClosureResults,
80591
+ totalSkillCount: skillResourceClosureResults.reduce((sum, item) => sum + item.skillCount, 0),
80592
+ totalReferenceCount: skillResourceClosureResults.reduce((sum, item) => sum + item.referenceCount, 0),
80593
+ totalSourceOnlyCount: skillResourceClosureResults.reduce((sum, item) => sum + item.sourceOnlyCount, 0),
80594
+ totalFindingCount: 0
80595
+ },
80006
80596
  verificationGates: config.verificationGates ?? [],
80007
80597
  snapshotDigest: overallSnapshotDigest,
80008
80598
  ...production ? {
80009
80599
  production: {
80010
80600
  mode: "github-npm-v1",
80011
- assetRoot: relative19(realRoot, runDir)
80601
+ assetRoot: relative20(realRoot, runDir)
80012
80602
  }
80013
80603
  } : {},
80014
80604
  units,
@@ -80022,9 +80612,9 @@ To proceed, pass --acknowledge-hook-side-effects (CLI) or hooksAuthorized=true (
80022
80612
  actionCount: externalActions.length
80023
80613
  });
80024
80614
  await evidence.append({ phase: "plan-write", status: "started" });
80025
- const latestPlanPath = output ?? resolve20(releaseDir, "release-plan.json");
80615
+ const latestPlanPath = output ?? resolve21(releaseDir, "release-plan.json");
80026
80616
  const plannedDigest = computePlanDigest(plan);
80027
- const immutablePlanPath = resolve20(dirname9(latestPlanPath), "plans", `${plannedDigest}.json`);
80617
+ const immutablePlanPath = resolve21(dirname10(latestPlanPath), "plans", `${plannedDigest}.json`);
80028
80618
  const { planPath: writtenPath, planDigest } = await writePlanImmutable(immutablePlanPath, plan);
80029
80619
  await writePlanAtomic(latestPlanPath, plan);
80030
80620
  await evidence.append({
@@ -80076,6 +80666,7 @@ var init_prepare = __esm({
80076
80666
  init_evidence();
80077
80667
  await init_plan();
80078
80668
  init_digest();
80669
+ init_skill_resource_closure();
80079
80670
  init_public_map();
80080
80671
  init_public_path();
80081
80672
  init_scan();
@@ -80113,8 +80704,8 @@ var init_prepare = __esm({
80113
80704
  });
80114
80705
 
80115
80706
  // src/core/approval.mjs
80116
- import { readFile as readFile19 } from "node:fs/promises";
80117
- import { basename as basename6, dirname as dirname10, join as join16, resolve as resolve21 } from "node:path";
80707
+ import { readFile as readFile20 } from "node:fs/promises";
80708
+ import { basename as basename6, dirname as dirname11, join as join17, resolve as resolve22 } from "node:path";
80118
80709
  function validateApprovalRecordSchema(approval) {
80119
80710
  if (validateApprovalSchema(approval)) return;
80120
80711
  const errors = validateApprovalSchema.errors ?? [];
@@ -80131,9 +80722,9 @@ function assertImmutableApprovalAuthority(approvalPath, plan, rawApproval) {
80131
80722
  if (!plan?.production) return;
80132
80723
  const planDigest = computePlanDigest(plan);
80133
80724
  const approvalDigest = computeApprovalDigest(rawApproval);
80134
- const absolute = resolve21(approvalPath);
80135
- const planDirectory = dirname10(absolute);
80136
- if (basename6(absolute) !== `${approvalDigest}.json` || basename6(planDirectory) !== planDigest || basename6(dirname10(planDirectory)) !== "approvals") {
80725
+ const absolute = resolve22(approvalPath);
80726
+ const planDirectory = dirname11(absolute);
80727
+ if (basename6(absolute) !== `${approvalDigest}.json` || basename6(planDirectory) !== planDigest || basename6(dirname11(planDirectory)) !== "approvals") {
80137
80728
  throw new ReleaseError(
80138
80729
  GATE_FAILED,
80139
80730
  "production commands require approvals/<planDigest>/<approvalDigest>.json immutable authority",
@@ -80400,8 +80991,8 @@ var approve_exports = {};
80400
80991
  __export(approve_exports, {
80401
80992
  approvePlan: () => approvePlan
80402
80993
  });
80403
- import { readFile as readFile20, writeFile as writeFile7 } from "node:fs/promises";
80404
- import { resolve as resolve22, dirname as dirname11, basename as basename7 } from "node:path";
80994
+ import { readFile as readFile21, writeFile as writeFile7 } from "node:fs/promises";
80995
+ import { resolve as resolve23, dirname as dirname12, basename as basename7 } from "node:path";
80405
80996
  function defaultClock() {
80406
80997
  return (/* @__PURE__ */ new Date()).toISOString();
80407
80998
  }
@@ -80427,7 +81018,7 @@ async function approvePlan(options) {
80427
81018
  }
80428
81019
  let planRaw;
80429
81020
  try {
80430
- planRaw = await readFile20(planPath, "utf8");
81021
+ planRaw = await readFile21(planPath, "utf8");
80431
81022
  } catch (err) {
80432
81023
  throw new ReleaseError(
80433
81024
  GATE_FAILED,
@@ -80531,30 +81122,30 @@ async function approvePlan(options) {
80531
81122
  expiresAt
80532
81123
  };
80533
81124
  validateApprovalRecordSchema(approvalRecord);
80534
- const planDir = dirname11(resolve22(planPath));
80535
- const releaseDir = basename7(planDir) === "plans" && basename7(planPath) === `${actualDigest}.json` ? dirname11(planDir) : planDir;
80536
- if (plan.production?.mode === "github-npm-v1" && outputPath && resolve22(outputPath) !== resolve22(releaseDir, "approval-record.json")) {
81125
+ const planDir = dirname12(resolve23(planPath));
81126
+ const releaseDir = basename7(planDir) === "plans" && basename7(planPath) === `${actualDigest}.json` ? dirname12(planDir) : planDir;
81127
+ if (plan.production?.mode === "github-npm-v1" && outputPath && resolve23(outputPath) !== resolve23(releaseDir, "approval-record.json")) {
80537
81128
  throw new ReleaseError(
80538
81129
  GATE_FAILED,
80539
81130
  "production approve requires the canonical approval-record.json alias next to the immutable plan authority; custom --output is supported only outside production",
80540
- { outputPath: resolve22(outputPath), expected: resolve22(releaseDir, "approval-record.json") }
81131
+ { outputPath: resolve23(outputPath), expected: resolve23(releaseDir, "approval-record.json") }
80541
81132
  );
80542
81133
  }
80543
81134
  const json = JSON.stringify(approvalRecord, null, 2);
80544
81135
  const approvalDigest = computeApprovalDigest(json);
80545
- const immutableApprovalPath = resolve22(
81136
+ const immutableApprovalPath = resolve23(
80546
81137
  releaseDir,
80547
81138
  "approvals",
80548
81139
  actualDigest,
80549
81140
  `${approvalDigest}.json`
80550
81141
  );
80551
- await prepareAuthorityDirectory(dirname11(immutableApprovalPath));
81142
+ await prepareAuthorityDirectory(dirname12(immutableApprovalPath));
80552
81143
  await assertAuthorityFileTarget(immutableApprovalPath);
80553
81144
  try {
80554
81145
  await writeFile7(immutableApprovalPath, json, { encoding: "utf8", flag: "wx", mode: 384 });
80555
81146
  } catch (error) {
80556
81147
  if (error.code !== "EEXIST") throw error;
80557
- const existing = await readFile20(immutableApprovalPath, "utf8");
81148
+ const existing = await readFile21(immutableApprovalPath, "utf8");
80558
81149
  if (existing !== json) {
80559
81150
  throw new ReleaseError(
80560
81151
  GATE_FAILED,
@@ -80563,8 +81154,8 @@ async function approvePlan(options) {
80563
81154
  );
80564
81155
  }
80565
81156
  }
80566
- const writePath = outputPath ?? resolve22(releaseDir, "approval-record.json");
80567
- await prepareAuthorityDirectory(dirname11(writePath));
81157
+ const writePath = outputPath ?? resolve23(releaseDir, "approval-record.json");
81158
+ await prepareAuthorityDirectory(dirname12(writePath));
80568
81159
  await assertAuthorityFileTarget(writePath);
80569
81160
  await writeFile7(writePath, json, "utf8");
80570
81161
  return Object.freeze({
@@ -80765,7 +81356,7 @@ function defaultSleep(ms) {
80765
81356
  if (process.env.RELEASE_SKILL_OBSERVE_RETRY_NO_WAIT === "1") {
80766
81357
  return Promise.resolve();
80767
81358
  }
80768
- return new Promise((resolve26) => setTimeout(resolve26, ms));
81359
+ return new Promise((resolve27) => setTimeout(resolve27, ms));
80769
81360
  }
80770
81361
  function isPropagatingMissing(result) {
80771
81362
  if (result == null) return true;
@@ -80854,8 +81445,8 @@ var reconcile_exports = {};
80854
81445
  __export(reconcile_exports, {
80855
81446
  reconcileRelease: () => reconcileRelease
80856
81447
  });
80857
- import { readFile as readFile21, mkdir as mkdir12 } from "node:fs/promises";
80858
- import { join as join17 } from "node:path";
81448
+ import { readFile as readFile22, mkdir as mkdir12 } from "node:fs/promises";
81449
+ import { join as join18 } from "node:path";
80859
81450
  function defaultClock3() {
80860
81451
  return (/* @__PURE__ */ new Date()).toISOString();
80861
81452
  }
@@ -80884,7 +81475,7 @@ async function reconcileRelease(options) {
80884
81475
  }
80885
81476
  let planRaw;
80886
81477
  try {
80887
- planRaw = await readFile21(planPath, "utf8");
81478
+ planRaw = await readFile22(planPath, "utf8");
80888
81479
  } catch (err) {
80889
81480
  throw new ReleaseError(GATE_FAILED, `cannot read release plan: ${err.message}`, { planPath, cause: err.code });
80890
81481
  }
@@ -80963,7 +81554,7 @@ async function reconcileRelease(options) {
80963
81554
  { sourceRunId: sourceRun.runId }
80964
81555
  );
80965
81556
  }
80966
- const sourceApprovalRaw = await readFile21(consumedApprovalPath, "utf8").catch((error) => {
81557
+ const sourceApprovalRaw = await readFile22(consumedApprovalPath, "utf8").catch((error) => {
80967
81558
  throw new ReleaseError(GATE_FAILED, "source run approval authority is unavailable", {
80968
81559
  sourceRunId: sourceRun.runId,
80969
81560
  cause: error.code
@@ -81140,7 +81731,7 @@ async function reconcileRelease(options) {
81140
81731
  if (approvalPath) {
81141
81732
  let approvalRaw;
81142
81733
  try {
81143
- approvalRaw = await readFile21(approvalPath, "utf8");
81734
+ approvalRaw = await readFile22(approvalPath, "utf8");
81144
81735
  } catch (err) {
81145
81736
  throw new ReleaseError(
81146
81737
  GATE_FAILED,
@@ -81759,7 +82350,7 @@ async function reconcileRelease(options) {
81759
82350
  ...normalized === "deferred" ? { reason: CONSUMER_VERIFICATION_DEFERRED, phase: "post-publish-verification" } : {}
81760
82351
  };
81761
82352
  });
81762
- const runPath = join17(runDir, "release-run.json");
82353
+ const runPath = join18(runDir, "release-run.json");
81763
82354
  const sourceRunDigest = sourceAuthorityDigest;
81764
82355
  const runState = {
81765
82356
  runId,
@@ -82423,9 +83014,9 @@ __export(verify_exports, {
82423
83014
  runSmokeTest: () => runSmokeTest,
82424
83015
  verifyRelease: () => verifyRelease
82425
83016
  });
82426
- import { readFile as readFile22, writeFile as writeFile8, mkdtemp as mkdtemp3, rm as rm7, mkdir as mkdir13, lstat as lstat12, realpath as realpath12, readdir as readdir10 } from "node:fs/promises";
83017
+ import { readFile as readFile23, writeFile as writeFile8, mkdtemp as mkdtemp3, rm as rm7, mkdir as mkdir13, lstat as lstat13, realpath as realpath12, readdir as readdir11 } from "node:fs/promises";
82427
83018
  import { realpathSync as realpathSync4 } from "node:fs";
82428
- import { dirname as dirname12, join as join18, relative as relative20, isAbsolute as isAbsolute17, resolve as resolve23, basename as basename8 } from "node:path";
83019
+ import { dirname as dirname13, join as join19, relative as relative21, isAbsolute as isAbsolute18, resolve as resolve24, basename as basename8 } from "node:path";
82429
83020
  import { tmpdir as tmpdir2 } from "node:os";
82430
83021
  import { execFile as execFileCb11 } from "node:child_process";
82431
83022
  import { promisify as promisify11 } from "node:util";
@@ -82455,7 +83046,7 @@ function matchesSubset2(actual, expected) {
82455
83046
  async function runSmokeTest(plan, root, options = {}) {
82456
83047
  const baseDir = options.baseDir ?? tmpdir2();
82457
83048
  await mkdir13(baseDir, { recursive: true });
82458
- const tmpDir = await mkdtemp3(join18(baseDir, "verify-smoke-"));
83049
+ const tmpDir = await mkdtemp3(join19(baseDir, "verify-smoke-"));
82459
83050
  const npmExec = options.npmExecutor ?? defaultNpmExecutor;
82460
83051
  const installFlags = [
82461
83052
  "--ignore-scripts",
@@ -82493,15 +83084,17 @@ async function runSmokeTest(plan, root, options = {}) {
82493
83084
  passed: true,
82494
83085
  skipped: true,
82495
83086
  details: { message: "No npm distributions in plan; smoke test skipped" },
82496
- gateResults: []
83087
+ gateResults: [],
83088
+ skillResourceClosureReceipts: []
82497
83089
  };
82498
83090
  }
82499
83091
  const results = [];
82500
83092
  const gateResults = [];
83093
+ const skillResourceClosureReceipts = [];
82501
83094
  for (const { package: pkgName, registry, targetVersion, unitId, smokeBin, smokeArgs, smokeExpectedJson } of npmDistributions) {
82502
83095
  const packageAtVersion = `${pkgName}@${targetVersion}`;
82503
83096
  const installDir = resolveUnitScopedPath(tmpDir, unitId);
82504
- await mkdir13(join18(installDir, "node_modules"), { recursive: true });
83097
+ await mkdir13(join19(installDir, "node_modules"), { recursive: true });
82505
83098
  const registryFlags = [...installFlags, "--registry", registry];
82506
83099
  const installResult = await npmExec.install(
82507
83100
  packageAtVersion,
@@ -82519,10 +83112,10 @@ async function runSmokeTest(plan, root, options = {}) {
82519
83112
  }
82520
83113
  };
82521
83114
  }
82522
- const installedPkgPath = join18(installDir, "node_modules", pkgName, "package.json");
83115
+ const installedPkgPath = join19(installDir, "node_modules", pkgName, "package.json");
82523
83116
  let installedPkg;
82524
83117
  try {
82525
- installedPkg = JSON.parse(await readFile22(installedPkgPath, "utf8"));
83118
+ installedPkg = JSON.parse(await readFile23(installedPkgPath, "utf8"));
82526
83119
  } catch {
82527
83120
  return {
82528
83121
  passed: false,
@@ -82553,7 +83146,47 @@ async function runSmokeTest(plan, root, options = {}) {
82553
83146
  }
82554
83147
  };
82555
83148
  }
82556
- const pkgRoot = join18(installDir, "node_modules", pkgName);
83149
+ const pkgRoot = join19(installDir, "node_modules", pkgName);
83150
+ if (plan.skillResourceClosure) {
83151
+ const expectedUnitReceipt = plan.skillResourceClosure.unitReceipts.find((item) => item.unitId === unitId);
83152
+ if (!expectedUnitReceipt) {
83153
+ return {
83154
+ passed: false,
83155
+ details: { error: `Skill resource closure receipt missing for npm unit "${unitId}"` }
83156
+ };
83157
+ }
83158
+ const closureResult = await checkSkillResourceClosure({
83159
+ snapshotDir: pkgRoot,
83160
+ host: "npm"
83161
+ });
83162
+ if (closureResult.findings.length > 0) {
83163
+ return {
83164
+ passed: false,
83165
+ details: {
83166
+ error: `Skill resource closure failed for ${packageAtVersion}`,
83167
+ findings: closureResult.findings
83168
+ }
83169
+ };
83170
+ }
83171
+ if (expectedUnitReceipt.skillCount > 0 && closureResult.skillCount === 0) {
83172
+ return {
83173
+ passed: false,
83174
+ details: {
83175
+ error: `Installed npm package ${packageAtVersion} contains no skills`
83176
+ }
83177
+ };
83178
+ }
83179
+ skillResourceClosureReceipts.push(createSkillResourceClosureReceipt(
83180
+ closureResult,
83181
+ {
83182
+ unitId,
83183
+ distribution: "npm",
83184
+ host: "npm",
83185
+ checkedAt: (/* @__PURE__ */ new Date()).toISOString(),
83186
+ exitCode: 0
83187
+ }
83188
+ ));
83189
+ }
82557
83190
  gateResults.push(...await runConsumerVerificationGates({
82558
83191
  plan,
82559
83192
  unitId,
@@ -82595,10 +83228,10 @@ async function runSmokeTest(plan, root, options = {}) {
82595
83228
  }
82596
83229
  };
82597
83230
  }
82598
- const binPath = resolve23(pkgRoot, binRelative);
82599
- const relBin = relative20(pkgRoot, binPath);
82600
- const sep4 = process.platform === "win32" ? "\\" : "/";
82601
- if (isAbsolute17(relBin) || relBin === ".." || relBin.startsWith(`..${sep4}`)) {
83231
+ const binPath = resolve24(pkgRoot, binRelative);
83232
+ const relBin = relative21(pkgRoot, binPath);
83233
+ const sep5 = process.platform === "win32" ? "\\" : "/";
83234
+ if (isAbsolute18(relBin) || relBin === ".." || relBin.startsWith(`..${sep5}`)) {
82602
83235
  return {
82603
83236
  passed: false,
82604
83237
  details: {
@@ -82610,10 +83243,10 @@ async function runSmokeTest(plan, root, options = {}) {
82610
83243
  }
82611
83244
  let binStat;
82612
83245
  try {
82613
- binStat = await lstat12(binPath);
83246
+ binStat = await lstat13(binPath);
82614
83247
  const [pkgRootReal, binPathReal] = await Promise.all([realpath12(pkgRoot), realpath12(binPath)]);
82615
- const relReal = relative20(pkgRootReal, binPathReal);
82616
- if (!binStat.isFile() || binStat.isSymbolicLink() || isAbsolute17(relReal) || relReal === ".." || relReal.startsWith(`..${sep4}`)) {
83248
+ const relReal = relative21(pkgRootReal, binPathReal);
83249
+ if (!binStat.isFile() || binStat.isSymbolicLink() || isAbsolute18(relReal) || relReal === ".." || relReal.startsWith(`..${sep5}`)) {
82617
83250
  throw new Error("bin is not a regular file inside the installed package");
82618
83251
  }
82619
83252
  } catch (err) {
@@ -82636,7 +83269,7 @@ async function runSmokeTest(plan, root, options = {}) {
82636
83269
  TMPDIR: installDir,
82637
83270
  TEMP: installDir,
82638
83271
  TMP: installDir,
82639
- PATH: dirname12(process.execPath),
83272
+ PATH: dirname13(process.execPath),
82640
83273
  CI: "1"
82641
83274
  }
82642
83275
  });
@@ -82714,7 +83347,8 @@ async function runSmokeTest(plan, root, options = {}) {
82714
83347
  distributions: results,
82715
83348
  count: results.length
82716
83349
  },
82717
- gateResults
83350
+ gateResults,
83351
+ skillResourceClosureReceipts
82718
83352
  };
82719
83353
  } finally {
82720
83354
  await rm7(tmpDir, { recursive: true, force: true }).catch(() => {
@@ -82744,7 +83378,7 @@ async function verifyRelease(options) {
82744
83378
  }
82745
83379
  let planRaw;
82746
83380
  try {
82747
- planRaw = await readFile22(planPath, "utf8");
83381
+ planRaw = await readFile23(planPath, "utf8");
82748
83382
  } catch (err) {
82749
83383
  throw new ReleaseError(
82750
83384
  GATE_FAILED,
@@ -82814,7 +83448,7 @@ async function verifyRelease(options) {
82814
83448
  }
82815
83449
  let approvalRaw;
82816
83450
  try {
82817
- approvalRaw = await readFile22(sourceRun.approvalPath, "utf8");
83451
+ approvalRaw = await readFile23(sourceRun.approvalPath, "utf8");
82818
83452
  } catch (error) {
82819
83453
  throw new ReleaseError(
82820
83454
  GATE_FAILED,
@@ -82872,9 +83506,9 @@ async function verifyRelease(options) {
82872
83506
  const consumerVerificationReceipts = [];
82873
83507
  const actions = plan.externalActions ?? [];
82874
83508
  const trustedVerifyRuns = [];
82875
- const planDir = dirname12(planPath);
82876
- const releaseDir = basename8(planDir) === "plans" ? dirname12(planDir) : planDir;
82877
- const runsDir = resolve23(releaseDir, "runs");
83509
+ const planDir = dirname13(planPath);
83510
+ const releaseDir = basename8(planDir) === "plans" ? dirname13(planDir) : planDir;
83511
+ const runsDir = resolve24(releaseDir, "runs");
82878
83512
  let runsDirReal = null;
82879
83513
  let authorityDirReal = null;
82880
83514
  if (previousVerifyRun) {
@@ -82887,7 +83521,7 @@ async function verifyRelease(options) {
82887
83521
  }
82888
83522
  {
82889
83523
  try {
82890
- const runsDirStat = await lstat12(runsDir);
83524
+ const runsDirStat = await lstat13(runsDir);
82891
83525
  if (runsDirStat.isSymbolicLink()) {
82892
83526
  throw new ReleaseError(
82893
83527
  GATE_FAILED,
@@ -82916,7 +83550,7 @@ async function verifyRelease(options) {
82916
83550
  runsDirReal = null;
82917
83551
  }
82918
83552
  if (runsDirReal) {
82919
- const entries = await readdir10(runsDirReal, { withFileTypes: true });
83553
+ const entries = await readdir11(runsDirReal, { withFileTypes: true });
82920
83554
  for (const entry of entries) {
82921
83555
  if (!entry.name.startsWith("verify-")) continue;
82922
83556
  if (!entry.isDirectory() || entry.isSymbolicLink()) {
@@ -82926,8 +83560,8 @@ async function verifyRelease(options) {
82926
83560
  { entry: entry.name, runsDir: runsDirReal }
82927
83561
  );
82928
83562
  }
82929
- const candidateDir = resolve23(runsDirReal, entry.name);
82930
- const candidateStat = await lstat12(candidateDir).catch(() => null);
83563
+ const candidateDir = resolve24(runsDirReal, entry.name);
83564
+ const candidateStat = await lstat13(candidateDir).catch(() => null);
82931
83565
  if (!candidateStat || candidateStat.isSymbolicLink()) {
82932
83566
  throw new ReleaseError(
82933
83567
  GATE_FAILED,
@@ -82943,7 +83577,7 @@ async function verifyRelease(options) {
82943
83577
  { candidateDir, candidateReal, runsDir: runsDirReal }
82944
83578
  );
82945
83579
  }
82946
- const candidatePath = resolve23(candidateDir, "release-run.json");
83580
+ const candidatePath = resolve24(candidateDir, "release-run.json");
82947
83581
  try {
82948
83582
  const candidate = await loadRun(candidatePath, { requireDigest: true });
82949
83583
  if (candidate.status !== "VERIFIED") continue;
@@ -83037,7 +83671,7 @@ async function verifyRelease(options) {
83037
83671
  previousReceipt: previousActionCheck,
83038
83672
  algorithmVersion: INSTALLATION_CONTRACT_ALGORITHM_VERSION
83039
83673
  });
83040
- if (skipDecision === "NOT_REQUIRED_UNCHANGED") {
83674
+ if (skipDecision === "NOT_REQUIRED_UNCHANGED" && !plan.skillResourceClosure) {
83041
83675
  adapterChecks.push({
83042
83676
  actionId: action.id,
83043
83677
  actionType: action.type,
@@ -83135,16 +83769,16 @@ async function verifyRelease(options) {
83135
83769
  evidence,
83136
83770
  env: gateEnv ?? process.env,
83137
83771
  fixedEnv: action.type === "claude-marketplace-install" ? {
83138
- HOME: resolve23(runDir, "consumers", `claude-${action.parameters.plugin}`),
83139
- CLAUDE_CONFIG_DIR: resolve23(runDir, "consumers", `claude-${action.parameters.plugin}`, ".claude")
83772
+ HOME: resolve24(runDir, "consumers", `claude-${action.parameters.plugin}`),
83773
+ CLAUDE_CONFIG_DIR: resolve24(runDir, "consumers", `claude-${action.parameters.plugin}`, ".claude")
83140
83774
  } : action.type === "codex-marketplace-install" ? {
83141
- HOME: resolve23(runDir, "consumers", `codex-${action.parameters.plugin}`),
83142
- CODEX_HOME: resolve23(runDir, "consumers", `codex-${action.parameters.plugin}`)
83775
+ HOME: resolve24(runDir, "consumers", `codex-${action.parameters.plugin}`),
83776
+ CODEX_HOME: resolve24(runDir, "consumers", `codex-${action.parameters.plugin}`)
83143
83777
  } : action.type === "codebuddy-marketplace-install" ? {
83144
- HOME: resolve23(runDir, "consumers", `codebuddy-${action.parameters.plugin}`)
83778
+ HOME: resolve24(runDir, "consumers", `codebuddy-${action.parameters.plugin}`)
83145
83779
  } : {
83146
- HOME: resolve23(runDir, "consumers", `kimi-${action.parameters.plugin}`),
83147
- KIMI_CODE_HOME: resolve23(runDir, "consumers", `kimi-${action.parameters.plugin}`)
83780
+ HOME: resolve24(runDir, "consumers", `kimi-${action.parameters.plugin}`),
83781
+ KIMI_CODE_HOME: resolve24(runDir, "consumers", `kimi-${action.parameters.plugin}`)
83148
83782
  }
83149
83783
  }));
83150
83784
  } else {
@@ -83228,10 +83862,93 @@ async function verifyRelease(options) {
83228
83862
  { expectedGateIds, observedGateIds }
83229
83863
  );
83230
83864
  }
83865
+ const skillResourceClosureReceipts = [
83866
+ ...smokeTest.skillResourceClosureReceipts ?? []
83867
+ ];
83868
+ if (plan.skillResourceClosure) {
83869
+ await evidence.append({ phase: "verify", step: "skill-resource-closure", status: "started" });
83870
+ const installSurfaces = [];
83871
+ const actionDistribution = {
83872
+ "claude-marketplace-install": "claude-plugin",
83873
+ "codex-marketplace-install": "codex-plugin",
83874
+ "kimi-marketplace-install": "kimi-plugin",
83875
+ "codebuddy-marketplace-install": "codebuddy-plugin"
83876
+ };
83877
+ for (const check of adapterChecks) {
83878
+ const distribution = actionDistribution[check.actionType];
83879
+ if (distribution && check.observation?.installPath) {
83880
+ installSurfaces.push({
83881
+ host: distribution.replace("-plugin", ""),
83882
+ distribution,
83883
+ installPath: check.observation.installPath,
83884
+ actionId: check.actionId,
83885
+ unitId: actions.find((a) => a.id === check.actionId)?.unitId
83886
+ });
83887
+ }
83888
+ }
83889
+ for (const surface of installSurfaces) {
83890
+ const closureResult = await checkSkillResourceClosure({
83891
+ snapshotDir: surface.installPath,
83892
+ host: surface.host
83893
+ });
83894
+ if (closureResult.findings.length > 0) {
83895
+ await evidence.append({
83896
+ phase: "verify",
83897
+ step: "skill-resource-closure",
83898
+ status: "failed",
83899
+ host: surface.host,
83900
+ findingCount: closureResult.findings.length,
83901
+ findings: closureResult.findings
83902
+ });
83903
+ throw new ReleaseError(
83904
+ POST_PUBLISH_VERIFY_FAILED,
83905
+ `skill resource closure check failed for ${surface.host} consumer install: ${closureResult.findings.length} finding(s)`,
83906
+ { host: surface.host, findings: closureResult.findings }
83907
+ );
83908
+ }
83909
+ const expectedUnitReceipt = plan.skillResourceClosure.unitReceipts.find((item) => item.unitId === surface.unitId);
83910
+ if (!expectedUnitReceipt || closureResult.skillCount === 0) {
83911
+ throw new ReleaseError(
83912
+ POST_PUBLISH_VERIFY_FAILED,
83913
+ `skill resource closure installed surface is empty or unbound for ${surface.distribution}`,
83914
+ { unitId: surface.unitId, distribution: surface.distribution }
83915
+ );
83916
+ }
83917
+ skillResourceClosureReceipts.push(createSkillResourceClosureReceipt(
83918
+ closureResult,
83919
+ {
83920
+ host: surface.host,
83921
+ distribution: surface.distribution,
83922
+ actionId: surface.actionId,
83923
+ unitId: surface.unitId,
83924
+ checkedAt: clockFn(),
83925
+ exitCode: 0
83926
+ }
83927
+ ));
83928
+ }
83929
+ const receiptCoverage = evaluateConsumerSkillResourceClosureReceipts(
83930
+ plan,
83931
+ skillResourceClosureReceipts
83932
+ );
83933
+ if (!receiptCoverage.passed) {
83934
+ throw new ReleaseError(
83935
+ POST_PUBLISH_VERIFY_FAILED,
83936
+ "skill resource closure receipt set does not match declared consumer distributions",
83937
+ receiptCoverage
83938
+ );
83939
+ }
83940
+ await evidence.append({
83941
+ phase: "verify",
83942
+ step: "skill-resource-closure",
83943
+ status: "completed",
83944
+ surfaceCount: installSurfaces.length,
83945
+ receipts: skillResourceClosureReceipts
83946
+ });
83947
+ }
83231
83948
  assertTransition(PUBLISHED, VERIFIED);
83232
83949
  await evidence.append({ phase: "verify", status: "completed", overallStatus: VERIFIED });
83233
83950
  const sourceRunDigest = sourceRun.runDigest ?? computeRunDigest(sourceRun);
83234
- const verifyRunPath = join18(runDir, "release-run.json");
83951
+ const verifyRunPath = join19(runDir, "release-run.json");
83235
83952
  const verifyRunState = {
83236
83953
  runId,
83237
83954
  command: "verify",
@@ -83267,6 +83984,7 @@ async function verifyRelease(options) {
83267
83984
  }),
83268
83985
  gateResults: consumerGateResults,
83269
83986
  consumerVerificationReceipts,
83987
+ skillResourceClosureReceipts,
83270
83988
  startedAt: clockFn(),
83271
83989
  finishedAt: clockFn()
83272
83990
  };
@@ -83315,6 +84033,7 @@ var init_verify = __esm({
83315
84033
  init_public_path();
83316
84034
  init_npm();
83317
84035
  init_verification_gates();
84036
+ init_skill_resource_closure();
83318
84037
  init_checkpoints();
83319
84038
  init_installation_contract();
83320
84039
  execFile10 = promisify11(execFileCb11);
@@ -83348,7 +84067,7 @@ var init_verify = __esm({
83348
84067
  exec: execFile10,
83349
84068
  env: process.env
83350
84069
  });
83351
- const userConfig = join18(cwd, ".release-skill-npmrc");
84070
+ const userConfig = join19(cwd, ".release-skill-npmrc");
83352
84071
  await writeFile8(
83353
84072
  userConfig,
83354
84073
  `registry=${normalizedRegistry}/
@@ -83408,11 +84127,11 @@ __export(publish_exports, {
83408
84127
  classifyPreObservation: () => classifyPreObservation,
83409
84128
  publishRelease: () => publishRelease
83410
84129
  });
83411
- import { readFile as readFile23, mkdir as mkdir14 } from "node:fs/promises";
83412
- import { isAbsolute as isAbsolute18, join as join19, relative as relative21 } from "node:path";
84130
+ import { readFile as readFile24, mkdir as mkdir14 } from "node:fs/promises";
84131
+ import { isAbsolute as isAbsolute19, join as join20, relative as relative22 } from "node:path";
83413
84132
  function assertInsideAssetRoot(assetRoot, candidate, label) {
83414
- const rel = relative21(assetRoot, candidate);
83415
- if (rel === "" || isAbsolute18(rel) || rel === ".." || rel.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`)) {
84133
+ const rel = relative22(assetRoot, candidate);
84134
+ if (rel === "" || isAbsolute19(rel) || rel === ".." || rel.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`)) {
83416
84135
  throw new ReleaseError(GATE_FAILED, `${label} must be a child of the production asset root`);
83417
84136
  }
83418
84137
  }
@@ -83642,7 +84361,7 @@ async function publishRelease(options) {
83642
84361
  const captureBaselineActual = typeof captureBaselineFn === "function" ? captureBaselineFn : captureBaseline;
83643
84362
  let planRaw;
83644
84363
  try {
83645
- planRaw = await readFile23(planPath, "utf8");
84364
+ planRaw = await readFile24(planPath, "utf8");
83646
84365
  } catch (err) {
83647
84366
  throw new ReleaseError(GATE_FAILED, `cannot read release plan: ${err.message}`, { planPath, cause: err.code });
83648
84367
  }
@@ -83679,6 +84398,7 @@ async function publishRelease(options) {
83679
84398
  if (productionMode && !isProductionPlan) {
83680
84399
  throw new ReleaseError(GATE_FAILED, "production publish requires a github-npm-v1 frozen plan");
83681
84400
  }
84401
+ const verifiedFrozenSnapshots = /* @__PURE__ */ new Map();
83682
84402
  if (isProductionPlan) {
83683
84403
  if (!plan.production.assetRoot || plan.production.assetRoot === ".") {
83684
84404
  throw new ReleaseError(GATE_FAILED, "production plan requires a dedicated assetRoot");
@@ -83717,6 +84437,7 @@ async function publishRelease(options) {
83717
84437
  snapshotPath: frozen.path,
83718
84438
  expectedDigest: frozen.manifestDigest
83719
84439
  });
84440
+ verifiedFrozenSnapshots.set(unit.id, snapshot.snapshotDir);
83720
84441
  assertInsideAssetRoot(assetRoot, snapshot.snapshotDir, "frozen snapshot");
83721
84442
  const git2 = await verifyFrozenGitRepository({
83722
84443
  root,
@@ -83749,10 +84470,56 @@ async function publishRelease(options) {
83749
84470
  }
83750
84471
  await evidence.append({ phase: "safety-gate", gate: "frozen-artifacts", status: "passed" });
83751
84472
  }
84473
+ if (plan.skillResourceClosure) {
84474
+ await evidence.append({ phase: "safety-gate", gate: "skill-resource-closure", status: "started" });
84475
+ const expectedReceipts = plan.skillResourceClosure.unitReceipts ?? [];
84476
+ if (plan.skillResourceClosure.checkerVersion !== CHECKER_VERSION) {
84477
+ throw new ReleaseError(
84478
+ GATE_FAILED,
84479
+ `skill resource closure checker version mismatch: plan=${plan.skillResourceClosure.checkerVersion}, current=${CHECKER_VERSION}`
84480
+ );
84481
+ }
84482
+ if (expectedReceipts.length !== plan.units.length) {
84483
+ throw new ReleaseError(GATE_FAILED, "skill resource closure receipt set does not cover every release unit");
84484
+ }
84485
+ for (const [unitId, snapshotDir] of verifiedFrozenSnapshots) {
84486
+ const expected = expectedReceipts.find((item) => item.unitId === unitId);
84487
+ if (!expected) {
84488
+ throw new ReleaseError(GATE_FAILED, `skill resource closure receipt missing for unit "${unitId}"`);
84489
+ }
84490
+ const closureResult = await checkSkillResourceClosure({
84491
+ snapshotDir,
84492
+ host: "root"
84493
+ });
84494
+ if (closureResult.findings.length > 0) {
84495
+ await evidence.append({
84496
+ phase: "safety-gate",
84497
+ gate: "skill-resource-closure",
84498
+ status: "failed",
84499
+ unitId,
84500
+ findingCount: closureResult.findings.length
84501
+ });
84502
+ throw new ReleaseError(
84503
+ GATE_FAILED,
84504
+ `skill resource closure recheck failed for unit "${unitId}": ${closureResult.findings.length} finding(s)`,
84505
+ { unitId, findings: closureResult.findings }
84506
+ );
84507
+ }
84508
+ const observed = createSkillResourceClosureReceipt(closureResult, { unitId });
84509
+ assertSkillResourceClosureReceipt(expected, observed, `unit "${unitId}"`);
84510
+ }
84511
+ await evidence.append({
84512
+ phase: "safety-gate",
84513
+ gate: "skill-resource-closure",
84514
+ status: "passed",
84515
+ receiptCount: expectedReceipts.length,
84516
+ recheckedReceiptCount: verifiedFrozenSnapshots.size
84517
+ });
84518
+ }
83752
84519
  await evidence.append({ phase: "safety-gate", gate: "approval-load", status: "started" });
83753
84520
  let approvalRaw;
83754
84521
  try {
83755
- approvalRaw = await readFile23(approvalPath, "utf8");
84522
+ approvalRaw = await readFile24(approvalPath, "utf8");
83756
84523
  } catch (err) {
83757
84524
  throw new ReleaseError(
83758
84525
  GATE_FAILED,
@@ -84023,7 +84790,7 @@ async function publishRelease(options) {
84023
84790
  }
84024
84791
  }
84025
84792
  await evidence.append({ phase: "safety-gate", gate: "global-preflight", status: "passed" });
84026
- const runPath = join19(runDir, "release-run.json");
84793
+ const runPath = join20(runDir, "release-run.json");
84027
84794
  const checkpoints = orderedActions.map((action) => {
84028
84795
  if (isMarketplaceAction(action.type)) {
84029
84796
  return {
@@ -84264,6 +85031,7 @@ var init_publish = __esm({
84264
85031
  init_baseline();
84265
85032
  init_previous_public_baseline();
84266
85033
  init_evidence();
85034
+ init_skill_resource_closure();
84267
85035
  init_checkpoints();
84268
85036
  await init_run();
84269
85037
  init_errors();
@@ -84289,8 +85057,8 @@ var init_publish = __esm({
84289
85057
  });
84290
85058
 
84291
85059
  // src/artifacts/policy.mjs
84292
- import { readFile as readFile24 } from "node:fs/promises";
84293
- import { join as join20 } from "node:path";
85060
+ import { readFile as readFile25 } from "node:fs/promises";
85061
+ import { join as join21 } from "node:path";
84294
85062
  import { createHash as createHash11 } from "node:crypto";
84295
85063
  function validateArtifactPolicy(policy) {
84296
85064
  const ok = _validate(policy);
@@ -84386,10 +85154,10 @@ async function parseSafeYamlWithinRoot(root, policyPath) {
84386
85154
  }
84387
85155
  throw err;
84388
85156
  }
84389
- const fullPath = join20(root, policyPath);
85157
+ const fullPath = join21(root, policyPath);
84390
85158
  let content;
84391
85159
  try {
84392
- content = await readFile24(fullPath, "utf8");
85160
+ content = await readFile25(fullPath, "utf8");
84393
85161
  } catch (err) {
84394
85162
  throw new ReleaseError(
84395
85163
  ARTIFACT_POLICY_INVALID,
@@ -84500,8 +85268,8 @@ var init_policy = __esm({
84500
85268
  });
84501
85269
 
84502
85270
  // src/artifacts/entry.mjs
84503
- import { lstat as lstat13, readdir as readdir11, readFile as readFile25 } from "node:fs/promises";
84504
- import { join as join21 } from "node:path";
85271
+ import { lstat as lstat14, readdir as readdir12, readFile as readFile26 } from "node:fs/promises";
85272
+ import { join as join22 } from "node:path";
84505
85273
  import { promisify as promisify12 } from "node:util";
84506
85274
  import { execFile as execFile11 } from "node:child_process";
84507
85275
  function statToGitMode(stat9) {
@@ -84521,12 +85289,12 @@ async function gitHashObject(root, absPath) {
84521
85289
  }
84522
85290
  async function enumerateTreeEntries(root, dirPath, relBase) {
84523
85291
  const entries = [];
84524
- const items = await readdir11(dirPath, { withFileTypes: true });
85292
+ const items = await readdir12(dirPath, { withFileTypes: true });
84525
85293
  for (const item of items) {
84526
85294
  if (SKIP_DIRS2.has(item.name)) continue;
84527
- const absPath = join21(dirPath, item.name);
85295
+ const absPath = join22(dirPath, item.name);
84528
85296
  const relPath = relBase ? `${relBase}/${item.name}` : item.name;
84529
- const st = await lstat13(absPath);
85297
+ const st = await lstat14(absPath);
84530
85298
  if (st.isSymbolicLink()) {
84531
85299
  throw new ReleaseError(
84532
85300
  PATH_UNSAFE,
@@ -84545,7 +85313,7 @@ async function enumerateTreeEntries(root, dirPath, relBase) {
84545
85313
  const subEntries = await enumerateTreeEntries(root, absPath, relPath);
84546
85314
  entries.push(...subEntries);
84547
85315
  } else {
84548
- const content = await readFile25(absPath);
85316
+ const content = await readFile26(absPath);
84549
85317
  entries.push(
84550
85318
  Object.freeze({
84551
85319
  path: relPath,
@@ -84575,10 +85343,10 @@ async function readEntry({ root, path: path3, source = "worktree" } = {}) {
84575
85343
  if (source !== "worktree") {
84576
85344
  throw new ReleaseError(PATH_UNSAFE, `unsupported readEntry source: ${source}`, { source });
84577
85345
  }
84578
- const absPath = join21(root, path3);
85346
+ const absPath = join22(root, path3);
84579
85347
  let st;
84580
85348
  try {
84581
- st = await lstat13(absPath);
85349
+ st = await lstat14(absPath);
84582
85350
  } catch (err) {
84583
85351
  if (err.code === "ENOENT" || err.code === "ENOTDIR") {
84584
85352
  return Object.freeze({ kind: "absent" });
@@ -84608,7 +85376,7 @@ async function readEntry({ root, path: path3, source = "worktree" } = {}) {
84608
85376
  { path: path3, nlink: st.nlink }
84609
85377
  );
84610
85378
  }
84611
- const content = await readFile25(absPath);
85379
+ const content = await readFile26(absPath);
84612
85380
  return Object.freeze({
84613
85381
  kind: "regular",
84614
85382
  path: path3,
@@ -84871,8 +85639,8 @@ var init_graph = __esm({
84871
85639
  });
84872
85640
 
84873
85641
  // src/artifacts/producer-registry.mjs
84874
- import { readFile as readFile26, readdir as readdir12, stat as stat6, mkdir as mkdir15, writeFile as writeFile9, rm as rm8 } from "node:fs/promises";
84875
- import { join as join22 } from "node:path";
85642
+ import { readFile as readFile27, readdir as readdir13, stat as stat6, mkdir as mkdir15, writeFile as writeFile9, rm as rm8 } from "node:fs/promises";
85643
+ import { join as join23 } from "node:path";
84876
85644
  import { mkdtemp as mkdtemp4 } from "node:fs/promises";
84877
85645
  import { tmpdir as tmpdir3 } from "node:os";
84878
85646
  import { createHash as createHash12 } from "node:crypto";
@@ -84893,7 +85661,7 @@ function collectStaticImports(filePath, visited = /* @__PURE__ */ new Set()) {
84893
85661
  const dir = abs.replace(/\/[^/]*$/, "");
84894
85662
  while ((match = importRe.exec(source)) !== null) {
84895
85663
  const spec = match[1];
84896
- let resolved = join22(dir, spec);
85664
+ let resolved = join23(dir, spec);
84897
85665
  if (!resolved.endsWith(".mjs")) resolved += ".mjs";
84898
85666
  results.push(...collectStaticImports(resolved, visited));
84899
85667
  }
@@ -84901,10 +85669,10 @@ function collectStaticImports(filePath, visited = /* @__PURE__ */ new Set()) {
84901
85669
  }
84902
85670
  async function createBuiltInProducerRegistry() {
84903
85671
  const producers = /* @__PURE__ */ new Map();
84904
- const lockfilePath = join22(new URL("../../..", import.meta.url).pathname, "pnpm-lock.yaml");
85672
+ const lockfilePath = join23(new URL("../../..", import.meta.url).pathname, "pnpm-lock.yaml");
84905
85673
  let lockfileBytes;
84906
85674
  try {
84907
- lockfileBytes = await readFile26(lockfilePath);
85675
+ lockfileBytes = await readFile27(lockfilePath);
84908
85676
  } catch {
84909
85677
  lockfileBytes = Buffer.from("");
84910
85678
  }
@@ -84921,7 +85689,7 @@ async function createBuiltInProducerRegistry() {
84921
85689
  const allModuleBytes = await Promise.all(
84922
85690
  allModulePaths.map(async (p) => {
84923
85691
  try {
84924
- return await readFile26(p);
85692
+ return await readFile27(p);
84925
85693
  } catch {
84926
85694
  return Buffer.from("");
84927
85695
  }
@@ -84938,16 +85706,16 @@ async function createBuiltInProducerRegistry() {
84938
85706
  }
84939
85707
  async function readDirEntries(dirPath, relBase = "") {
84940
85708
  const entries = [];
84941
- const items = await readdir12(dirPath, { withFileTypes: true });
85709
+ const items = await readdir13(dirPath, { withFileTypes: true });
84942
85710
  for (const item of items) {
84943
85711
  if (item.name === ".git") continue;
84944
- const absPath = join22(dirPath, item.name);
85712
+ const absPath = join23(dirPath, item.name);
84945
85713
  const relPath = relBase ? `${relBase}/${item.name}` : item.name;
84946
85714
  const st = await stat6(absPath);
84947
85715
  if (st.isDirectory()) {
84948
85716
  entries.push(...await readDirEntries(absPath, relPath));
84949
85717
  } else {
84950
- const content = await readFile26(absPath);
85718
+ const content = await readFile27(absPath);
84951
85719
  entries.push(Object.freeze({
84952
85720
  path: relPath,
84953
85721
  type: "blob",
@@ -84964,11 +85732,11 @@ async function readDirEntries(dirPath, relBase = "") {
84964
85732
  async function materializeEntries(entries, dirPath) {
84965
85733
  for (const entry of entries) {
84966
85734
  if (!entry.path) continue;
84967
- const targetPath = join22(dirPath, entry.path);
85735
+ const targetPath = join23(dirPath, entry.path);
84968
85736
  if (entry.type === "tree" || entry.kind === "tree") {
84969
85737
  await mkdir15(targetPath, { recursive: true });
84970
85738
  } else {
84971
- await mkdir15(join22(targetPath, ".."), { recursive: true });
85739
+ await mkdir15(join23(targetPath, ".."), { recursive: true });
84972
85740
  if (entry.content) {
84973
85741
  await writeFile9(targetPath, entry.content);
84974
85742
  }
@@ -85012,7 +85780,7 @@ async function runProducerClosure({
85012
85780
  graph,
85013
85781
  inputSnapshot,
85014
85782
  artifactIds,
85015
- tempRootFactory = /* @__PURE__ */ __name(async () => mkdtemp4(join22(tmpdir3(), "producer-")), "tempRootFactory")
85783
+ tempRootFactory = /* @__PURE__ */ __name(async () => mkdtemp4(join23(tmpdir3(), "producer-")), "tempRootFactory")
85016
85784
  } = {}) {
85017
85785
  const generatedSet = new Set(graph.topologicalOrder);
85018
85786
  for (const id of artifactIds) {
@@ -85049,7 +85817,7 @@ async function runProducerClosure({
85049
85817
  if (inputEntries) {
85050
85818
  const first = inputEntries[0];
85051
85819
  if (first && first.path) {
85052
- const absPath = first.path.startsWith("/") ? first.path : join22(process.cwd(), first.path);
85820
+ const absPath = first.path.startsWith("/") ? first.path : join23(process.cwd(), first.path);
85053
85821
  try {
85054
85822
  const st = await stat6(absPath);
85055
85823
  if (st.isDirectory()) {
@@ -85473,8 +86241,8 @@ var init_state = __esm({
85473
86241
  });
85474
86242
 
85475
86243
  // src/artifacts/artifact-plan.mjs
85476
- import { writeFile as writeFile10, mkdir as mkdir16, readFile as readFile27, rename as rename3, open as open8 } from "node:fs/promises";
85477
- import { dirname as dirname13 } from "node:path";
86244
+ import { writeFile as writeFile10, mkdir as mkdir16, readFile as readFile28, rename as rename3, open as open8 } from "node:fs/promises";
86245
+ import { dirname as dirname14 } from "node:path";
85478
86246
  function assemblePlan({
85479
86247
  operation,
85480
86248
  bindings,
@@ -85497,7 +86265,7 @@ function assemblePlan({
85497
86265
  return Object.freeze(plan);
85498
86266
  }
85499
86267
  async function writePlan(plan, outputPath) {
85500
- const dir = dirname13(outputPath);
86268
+ const dir = dirname14(outputPath);
85501
86269
  await mkdir16(dir, { recursive: true });
85502
86270
  const tmpPath = `${outputPath}.tmp`;
85503
86271
  const content = JSON.stringify(plan, null, 2);
@@ -86162,8 +86930,8 @@ var init_adoption = __esm({
86162
86930
  // src/artifacts/inspect.mjs
86163
86931
  import { promisify as promisify15 } from "node:util";
86164
86932
  import { execFile as execFile14 } from "node:child_process";
86165
- import { readdir as readdir13, stat as stat7, readFile as readFile28 } from "node:fs/promises";
86166
- import { join as join23 } from "node:path";
86933
+ import { readdir as readdir14, stat as stat7, readFile as readFile29 } from "node:fs/promises";
86934
+ import { join as join24 } from "node:path";
86167
86935
  async function hasNestedGitRoots(root) {
86168
86936
  try {
86169
86937
  const { stdout } = await execFileAsync5(
@@ -86173,9 +86941,9 @@ async function hasNestedGitRoots(root) {
86173
86941
  );
86174
86942
  const dirs = stdout.split("\n").filter((s) => s.length > 0);
86175
86943
  for (const dir of dirs) {
86176
- const absDir = join23(root, dir);
86944
+ const absDir = join24(root, dir);
86177
86945
  try {
86178
- const nestedGit = join23(absDir, ".git");
86946
+ const nestedGit = join24(absDir, ".git");
86179
86947
  await stat7(nestedGit);
86180
86948
  return true;
86181
86949
  } catch {
@@ -86434,8 +87202,8 @@ var init_inspect = __esm({
86434
87202
  });
86435
87203
 
86436
87204
  // src/artifacts/resolution.mjs
86437
- import { mkdir as mkdir17, open as open9, readFile as readFile29, stat as stat8, lstat as lstat14, chmod as chmod4 } from "node:fs/promises";
86438
- import { join as join24, resolve as resolve24, relative as relative22, isAbsolute as isAbsolute19, basename as basename9 } from "node:path";
87205
+ import { mkdir as mkdir17, open as open9, readFile as readFile30, stat as stat8, lstat as lstat15, chmod as chmod4 } from "node:fs/promises";
87206
+ import { join as join25, resolve as resolve25, relative as relative23, isAbsolute as isAbsolute20, basename as basename9 } from "node:path";
86439
87207
  function decodeBuffer(value, label) {
86440
87208
  if (value == null) return null;
86441
87209
  if (Buffer.isBuffer(value)) return value;
@@ -86537,13 +87305,13 @@ function assertSafeArtifactId(id) {
86537
87305
  }
86538
87306
  async function assertNoSymlinksInPath(root, artifactId) {
86539
87307
  const levels = [
86540
- join24(root, ".release-skill"),
86541
- join24(root, ".release-skill", "resolution"),
86542
- join24(root, ".release-skill", "resolution", artifactId)
87308
+ join25(root, ".release-skill"),
87309
+ join25(root, ".release-skill", "resolution"),
87310
+ join25(root, ".release-skill", "resolution", artifactId)
86543
87311
  ];
86544
87312
  for (const dir of levels) {
86545
87313
  try {
86546
- const st = await lstat14(dir);
87314
+ const st = await lstat15(dir);
86547
87315
  if (st.isSymbolicLink()) {
86548
87316
  throw new ReleaseError(PATH_UNSAFE, `directory is a symlink: ${dir}`, { path: dir });
86549
87317
  }
@@ -86555,11 +87323,11 @@ async function assertNoSymlinksInPath(root, artifactId) {
86555
87323
  }
86556
87324
  }
86557
87325
  async function assertSafeResolvedPath(root, artifactId, resolvedPath) {
86558
- const resolutionDir = resolve24(root, ".release-skill", "resolution", artifactId);
86559
- const resolved = resolve24(resolvedPath);
87326
+ const resolutionDir = resolve25(root, ".release-skill", "resolution", artifactId);
87327
+ const resolved = resolve25(resolvedPath);
86560
87328
  await assertNoSymlinksInPath(root, artifactId);
86561
- const rel = relative22(resolutionDir, resolved);
86562
- if (rel.startsWith("..") || isAbsolute19(rel)) {
87329
+ const rel = relative23(resolutionDir, resolved);
87330
+ if (rel.startsWith("..") || isAbsolute20(rel)) {
86563
87331
  throw new ReleaseError(
86564
87332
  PATH_UNSAFE,
86565
87333
  `resolvedPath must be inside resolution directory ${resolutionDir}`,
@@ -86574,7 +87342,7 @@ async function assertSafeResolvedPath(root, artifactId, resolvedPath) {
86574
87342
  { resolvedPath, expected: `${artifactId}.resolved`, actual: filename }
86575
87343
  );
86576
87344
  }
86577
- if (resolved !== resolve24(resolutionDir, `${artifactId}.resolved`)) {
87345
+ if (resolved !== resolve25(resolutionDir, `${artifactId}.resolved`)) {
86578
87346
  throw new ReleaseError(
86579
87347
  PATH_UNSAFE,
86580
87348
  "resolvedPath must be the exact materialized resolution file",
@@ -86583,7 +87351,7 @@ async function assertSafeResolvedPath(root, artifactId, resolvedPath) {
86583
87351
  }
86584
87352
  let st;
86585
87353
  try {
86586
- st = await lstat14(resolvedPath);
87354
+ st = await lstat15(resolvedPath);
86587
87355
  } catch (err) {
86588
87356
  throw new ReleaseError(
86589
87357
  MISSING_PARAMETERS,
@@ -86718,13 +87486,13 @@ async function materializeResolution({
86718
87486
  const template = buildConflictTemplate(artifact.conflict ?? {}, decodedBuffers);
86719
87487
  const templateDigest = sha256Hex(template);
86720
87488
  await assertNoSymlinksInPath(root, artifactId);
86721
- const resolutionDir = join24(root, ".release-skill", "resolution", artifactId);
87489
+ const resolutionDir = join25(root, ".release-skill", "resolution", artifactId);
86722
87490
  await mkdir17(resolutionDir, { recursive: true, mode: 448 });
86723
87491
  const dirStat = await stat8(resolutionDir);
86724
87492
  if ((dirStat.mode & 511) !== 448) {
86725
87493
  await chmod4(resolutionDir, 448);
86726
87494
  }
86727
- const resolvedPath = join24(resolutionDir, `${artifactId}.resolved`);
87495
+ const resolvedPath = join25(resolutionDir, `${artifactId}.resolved`);
86728
87496
  const fh = await open9(resolvedPath, "wx", 384);
86729
87497
  try {
86730
87498
  await fh.write(template, 0, template.length);
@@ -86766,7 +87534,7 @@ async function submitResolution({
86766
87534
  async function readAndValidateResolvedFile(resolvedPath) {
86767
87535
  let content;
86768
87536
  try {
86769
- content = await readFile29(resolvedPath);
87537
+ content = await readFile30(resolvedPath);
86770
87538
  } catch (err) {
86771
87539
  throw new ReleaseError(MISSING_PARAMETERS, `cannot read resolved file: ${err.message}`, { resolvedPath, cause: err.code });
86772
87540
  }
@@ -86934,8 +87702,8 @@ var artifacts_exports = {};
86934
87702
  __export(artifacts_exports, {
86935
87703
  runArtifactsCommand: () => runArtifactsCommand
86936
87704
  });
86937
- import { readFile as readFile30 } from "node:fs/promises";
86938
- import { join as join25 } from "node:path";
87705
+ import { readFile as readFile31 } from "node:fs/promises";
87706
+ import { join as join26 } from "node:path";
86939
87707
  async function runArtifactsCommand({ subcommand, args: args2, root } = {}) {
86940
87708
  if (!VALID_SUBCOMMANDS.has(subcommand)) {
86941
87709
  throw new ReleaseError(
@@ -87063,7 +87831,7 @@ async function handleAdopt({ args: args2, root }) {
87063
87831
  { subcommand: "adopt" }
87064
87832
  );
87065
87833
  }
87066
- const planRaw = await readFile30(planPath, "utf8");
87834
+ const planRaw = await readFile31(planPath, "utf8");
87067
87835
  const plan = JSON.parse(planRaw);
87068
87836
  if (expectedDigest && plan.planDigest !== expectedDigest) {
87069
87837
  throw new ReleaseError(
@@ -87078,7 +87846,7 @@ async function handleAdopt({ args: args2, root }) {
87078
87846
  if (artifact.path) {
87079
87847
  const entry = await readEntry({ root, path: artifact.path, source: "worktree" });
87080
87848
  if (entry.kind === "regular") {
87081
- const bytes = await readFile30(join25(root, artifact.path));
87849
+ const bytes = await readFile31(join26(root, artifact.path));
87082
87850
  currentEntries.set(artifact.id, Object.freeze({ ...entry, bytes, content: bytes }));
87083
87851
  } else {
87084
87852
  currentEntries.set(artifact.id, entry);
@@ -87143,7 +87911,7 @@ async function handleBootstrap({ args: args2, root }) {
87143
87911
  { subcommand: "bootstrap" }
87144
87912
  );
87145
87913
  }
87146
- const planRaw = await readFile30(planPath, "utf8");
87914
+ const planRaw = await readFile31(planPath, "utf8");
87147
87915
  const adoptionPlan = JSON.parse(planRaw);
87148
87916
  const currentEntries = /* @__PURE__ */ new Map();
87149
87917
  for (const id of new Set((adoptionPlan.protectedHunks ?? []).map((h) => h.artifactId))) {
@@ -87155,12 +87923,12 @@ async function handleBootstrap({ args: args2, root }) {
87155
87923
  if (entry.kind !== "regular") {
87156
87924
  throw new ReleaseError("PLAN_STALE", `artifact is no longer a regular file: ${id}`, { id });
87157
87925
  }
87158
- const bytes = await readFile30(join25(root, artifactPath));
87926
+ const bytes = await readFile31(join26(root, artifactPath));
87159
87927
  currentEntries.set(id, Object.freeze({ ...entry, bytes, content: bytes }));
87160
87928
  }
87161
87929
  let replacementBytes;
87162
87930
  if (action === "replace" && replacementPath) {
87163
- replacementBytes = await readFile30(replacementPath);
87931
+ replacementBytes = await readFile31(replacementPath);
87164
87932
  }
87165
87933
  const updated = await discardBootstrapHunk({
87166
87934
  adoptionPlan,
@@ -87198,7 +87966,7 @@ async function handleResolve({ args: args2, root }) {
87198
87966
  { subcommand: "resolve" }
87199
87967
  );
87200
87968
  }
87201
- const planRaw = await readFile30(planPath, "utf8");
87969
+ const planRaw = await readFile31(planPath, "utf8");
87202
87970
  const plan = JSON.parse(planRaw);
87203
87971
  if (plan.planDigest !== expectedDigest) {
87204
87972
  throw new ReleaseError(
@@ -87566,7 +88334,7 @@ var init_docs = __esm({
87566
88334
  });
87567
88335
 
87568
88336
  // bin/release-skill-cli.mjs
87569
- import { basename as basename10, dirname as dirname14, join as join26, resolve as resolve25 } from "node:path";
88337
+ import { basename as basename10, dirname as dirname15, join as join27, resolve as resolve26 } from "node:path";
87570
88338
  import { execFile as execFileCb12 } from "node:child_process";
87571
88339
  import { promisify as promisify16 } from "node:util";
87572
88340
 
@@ -87820,7 +88588,7 @@ if (!command && (args.includes("--version") || args.includes("-v"))) {
87820
88588
  } else {
87821
88589
  const { readFileSync: readFileSync5 } = await import("node:fs");
87822
88590
  const { fileURLToPath: fileURLToPath3 } = await import("node:url");
87823
- const pkgPath = join26(dirname14(fileURLToPath3(import.meta.url)), "..", "package.json");
88591
+ const pkgPath = join27(dirname15(fileURLToPath3(import.meta.url)), "..", "package.json");
87824
88592
  pkg = JSON.parse(readFileSync5(pkgPath, "utf8"));
87825
88593
  }
87826
88594
  if (hasJson) {
@@ -87941,7 +88709,7 @@ if (!COMMANDS.has(command)) {
87941
88709
  if (command === "setup") {
87942
88710
  const rootIdx = args.indexOf("--root");
87943
88711
  const rawRoot = rootIdx !== -1 && args[rootIdx + 1] ? args[rootIdx + 1] : process.cwd();
87944
- const root = resolve25(rawRoot);
88712
+ const root = resolve26(rawRoot);
87945
88713
  const answersIdx = args.indexOf("--answers");
87946
88714
  const answersPath = answersIdx !== -1 && args[answersIdx + 1] ? args[answersIdx + 1] : void 0;
87947
88715
  const confirmationIdx = args.indexOf("--confirm-setup");
@@ -87976,7 +88744,7 @@ if (command === "setup") {
87976
88744
  if (command === "assess") {
87977
88745
  const rootIdx = args.indexOf("--root");
87978
88746
  const rawRoot = rootIdx !== -1 && args[rootIdx + 1] ? args[rootIdx + 1] : process.cwd();
87979
- const root = resolve25(rawRoot);
88747
+ const root = resolve26(rawRoot);
87980
88748
  const offline = args.includes("--offline") || !args.includes("--online");
87981
88749
  const outputIdx = args.indexOf("--output");
87982
88750
  const output = outputIdx !== -1 && args[outputIdx + 1] ? args[outputIdx + 1] : void 0;
@@ -88007,7 +88775,7 @@ if (command === "assess") {
88007
88775
  if (command === "prepare") {
88008
88776
  const rootIdx = args.indexOf("--root");
88009
88777
  const rawRoot = rootIdx !== -1 && args[rootIdx + 1] ? args[rootIdx + 1] : process.cwd();
88010
- const root = resolve25(rawRoot);
88778
+ const root = resolve26(rawRoot);
88011
88779
  const offline = args.includes("--offline") || !args.includes("--online");
88012
88780
  let targetVersion;
88013
88781
  for (const flag of ["--target-version", "--version"]) {
@@ -88022,9 +88790,9 @@ if (command === "prepare") {
88022
88790
  const hookCache = !args.includes("--no-hook-cache");
88023
88791
  const production = args.includes("--production");
88024
88792
  const outputIdx = args.indexOf("--output");
88025
- const output = outputIdx !== -1 && args[outputIdx + 1] ? resolve25(args[outputIdx + 1]) : void 0;
88793
+ const output = outputIdx !== -1 && args[outputIdx + 1] ? resolve26(args[outputIdx + 1]) : void 0;
88026
88794
  const runDirIdx = args.indexOf("--run-dir");
88027
- const runDir = runDirIdx !== -1 && args[runDirIdx + 1] ? resolve25(args[runDirIdx + 1]) : void 0;
88795
+ const runDir = runDirIdx !== -1 && args[runDirIdx + 1] ? resolve26(args[runDirIdx + 1]) : void 0;
88028
88796
  try {
88029
88797
  const { prepareRelease: prepareRelease2 } = await init_prepare().then(() => prepare_exports);
88030
88798
  const { readFile: readFileFs } = await import("node:fs/promises");
@@ -88077,7 +88845,7 @@ if (command === "approve") {
88077
88845
  const actorIdx = args.indexOf("--actor");
88078
88846
  const actor = actorIdx !== -1 && args[actorIdx + 1] ? args[actorIdx + 1] : void 0;
88079
88847
  const outputIdx = args.indexOf("--output");
88080
- const outputPath = outputIdx !== -1 && args[outputIdx + 1] ? resolve25(args[outputIdx + 1]) : void 0;
88848
+ const outputPath = outputIdx !== -1 && args[outputIdx + 1] ? resolve26(args[outputIdx + 1]) : void 0;
88081
88849
  if (!planPath || !expectedDigest || !actor) {
88082
88850
  const msg = "approve requires --plan <path>, --digest <sha256>, and --actor <name>";
88083
88851
  if (hasJson) {
@@ -88089,10 +88857,10 @@ if (command === "approve") {
88089
88857
  }
88090
88858
  try {
88091
88859
  const { approvePlan: approvePlan2 } = await init_approve().then(() => approve_exports);
88092
- const resolvedPlanPath = resolve25(planPath);
88093
- const planDir = dirname14(resolvedPlanPath);
88094
- const releaseDir = basename10(planDir) === "plans" && basename10(resolvedPlanPath) === `${expectedDigest}.json` ? dirname14(planDir) : planDir;
88095
- const approvalPath = outputPath ?? join26(releaseDir, "approval-record.json");
88860
+ const resolvedPlanPath = resolve26(planPath);
88861
+ const planDir = dirname15(resolvedPlanPath);
88862
+ const releaseDir = basename10(planDir) === "plans" && basename10(resolvedPlanPath) === `${expectedDigest}.json` ? dirname15(planDir) : planDir;
88863
+ const approvalPath = outputPath ?? join27(releaseDir, "approval-record.json");
88096
88864
  const record = await approvePlan2({ planPath, expectedDigest, actor, outputPath: approvalPath });
88097
88865
  if (hasJson) {
88098
88866
  console.log(JSON.stringify(record, null, 2));
@@ -88119,13 +88887,13 @@ if (command === "approve") {
88119
88887
  if (command === "reconcile") {
88120
88888
  const rootIdx = args.indexOf("--root");
88121
88889
  const rawRoot = rootIdx !== -1 && args[rootIdx + 1] ? args[rootIdx + 1] : process.cwd();
88122
- const root = resolve25(rawRoot);
88890
+ const root = resolve26(rawRoot);
88123
88891
  const planIdx = args.indexOf("--plan");
88124
- const planPath = planIdx !== -1 && args[planIdx + 1] ? resolve25(args[planIdx + 1]) : void 0;
88892
+ const planPath = planIdx !== -1 && args[planIdx + 1] ? resolve26(args[planIdx + 1]) : void 0;
88125
88893
  const runIdx = args.indexOf("--run");
88126
- const runPath = runIdx !== -1 && args[runIdx + 1] ? resolve25(args[runIdx + 1]) : void 0;
88894
+ const runPath = runIdx !== -1 && args[runIdx + 1] ? resolve26(args[runIdx + 1]) : void 0;
88127
88895
  const approvalIdx = args.indexOf("--approval");
88128
- const approvalPath = approvalIdx !== -1 && args[approvalIdx + 1] ? resolve25(args[approvalIdx + 1]) : void 0;
88896
+ const approvalPath = approvalIdx !== -1 && args[approvalIdx + 1] ? resolve26(args[approvalIdx + 1]) : void 0;
88129
88897
  const confirmationIdx = args.indexOf("--confirm-production");
88130
88898
  const productionConfirmation = confirmationIdx !== -1 && args[confirmationIdx + 1] ? args[confirmationIdx + 1] : void 0;
88131
88899
  if (!planPath || !runPath) {
@@ -88184,11 +88952,11 @@ if (command === "reconcile") {
88184
88952
  if (command === "verify") {
88185
88953
  const rootIdx = args.indexOf("--root");
88186
88954
  const rawRoot = rootIdx !== -1 && args[rootIdx + 1] ? args[rootIdx + 1] : process.cwd();
88187
- const root = resolve25(rawRoot);
88955
+ const root = resolve26(rawRoot);
88188
88956
  const planIdx = args.indexOf("--plan");
88189
- const planPath = planIdx !== -1 && args[planIdx + 1] ? resolve25(args[planIdx + 1]) : void 0;
88957
+ const planPath = planIdx !== -1 && args[planIdx + 1] ? resolve26(args[planIdx + 1]) : void 0;
88190
88958
  const runIdx = args.indexOf("--run");
88191
- const runPath = runIdx !== -1 && args[runIdx + 1] ? resolve25(args[runIdx + 1]) : void 0;
88959
+ const runPath = runIdx !== -1 && args[runIdx + 1] ? resolve26(args[runIdx + 1]) : void 0;
88192
88960
  const verificationGatesAuthorized = args.includes("--acknowledge-gate-side-effects");
88193
88961
  if (!planPath || !runPath) {
88194
88962
  const msg = "verify requires --plan <path> and --run <path>";
@@ -88244,11 +89012,11 @@ if (command === "verify") {
88244
89012
  if (command === "publish") {
88245
89013
  const rootIdx = args.indexOf("--root");
88246
89014
  const rawRoot = rootIdx !== -1 && args[rootIdx + 1] ? args[rootIdx + 1] : process.cwd();
88247
- const root = resolve25(rawRoot);
89015
+ const root = resolve26(rawRoot);
88248
89016
  const planIdx = args.indexOf("--plan");
88249
- const planPath = planIdx !== -1 && args[planIdx + 1] ? resolve25(args[planIdx + 1]) : void 0;
89017
+ const planPath = planIdx !== -1 && args[planIdx + 1] ? resolve26(args[planIdx + 1]) : void 0;
88250
89018
  const approvalIdx = args.indexOf("--approval");
88251
- const approvalPath = approvalIdx !== -1 && args[approvalIdx + 1] ? resolve25(args[approvalIdx + 1]) : void 0;
89019
+ const approvalPath = approvalIdx !== -1 && args[approvalIdx + 1] ? resolve26(args[approvalIdx + 1]) : void 0;
88252
89020
  const confirmationIdx = args.indexOf("--confirm-production");
88253
89021
  const productionConfirmation = confirmationIdx !== -1 && args[confirmationIdx + 1] ? args[confirmationIdx + 1] : void 0;
88254
89022
  if (!planPath || !approvalPath || !productionConfirmation) {
@@ -88307,9 +89075,9 @@ if (command === "publish") {
88307
89075
  if (command === "artifacts") {
88308
89076
  const rootIdx = args.indexOf("--root");
88309
89077
  const rawRoot = rootIdx !== -1 && args[rootIdx + 1] ? args[rootIdx + 1] : process.cwd();
88310
- const root = resolve25(rawRoot);
89078
+ const root = resolve26(rawRoot);
88311
89079
  const outputIdx = args.indexOf("--output");
88312
- const output = outputIdx !== -1 && args[outputIdx + 1] ? resolve25(args[outputIdx + 1]) : void 0;
89080
+ const output = outputIdx !== -1 && args[outputIdx + 1] ? resolve26(args[outputIdx + 1]) : void 0;
88313
89081
  const subcommand = positional[1] ?? "status";
88314
89082
  try {
88315
89083
  const { runArtifactsCommand: runArtifactsCommand2 } = await Promise.resolve().then(() => (init_artifacts(), artifacts_exports));
@@ -88376,7 +89144,7 @@ if (command === "docs") {
88376
89144
  );
88377
89145
  }
88378
89146
  }
88379
- const root = resolve25(rawRoot);
89147
+ const root = resolve26(rawRoot);
88380
89148
  const valuedDocsFlags = /* @__PURE__ */ new Set(["--root", "--unit", "--confirm-refresh"]);
88381
89149
  const booleanDocsFlags = /* @__PURE__ */ new Set(["--json", "--write", "--ack-local-document-write"]);
88382
89150
  let docsSubcommand;