release-skill 0.6.0 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) 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 +31 -0
  7. package/INSTALL.md +2 -2
  8. package/INSTALL.zh-CN.md +2 -2
  9. package/README.md +12 -8
  10. package/README.zh-CN.md +12 -8
  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 +1028 -423
  14. package/adapters/claude/schemas/release-plan.schema.json +9 -0
  15. package/adapters/claude/schemas/release-project.schema.json +8 -0
  16. package/adapters/codex/.codex-plugin/plugin.json +2 -2
  17. package/adapters/codex/bin/release-skill.bundle.mjs +1028 -423
  18. package/adapters/codex/schemas/release-plan.schema.json +9 -0
  19. package/adapters/codex/schemas/release-project.schema.json +8 -0
  20. package/adapters/kimi/.kimi-plugin/plugin.json +1 -1
  21. package/adapters/kimi/bin/release-skill.bundle.mjs +1028 -423
  22. package/adapters/kimi/schemas/release-plan.schema.json +9 -0
  23. package/adapters/kimi/schemas/release-project.schema.json +8 -0
  24. package/adapters/workbuddy/.codebuddy-plugin/plugin.json +1 -1
  25. package/adapters/workbuddy/bin/release-skill.bundle.mjs +1028 -423
  26. package/adapters/workbuddy/schemas/release-plan.schema.json +9 -0
  27. package/adapters/workbuddy/schemas/release-project.schema.json +8 -0
  28. package/bin/release-skill-cli.mjs +11 -0
  29. package/bin/release-skill.bundle.mjs +1028 -423
  30. package/package.json +1 -1
  31. package/references/05-evidence-and-errors.md +1 -0
  32. package/schemas/release-plan.schema.json +9 -0
  33. package/schemas/release-project.schema.json +8 -0
  34. package/scripts/build-bundle.mjs +11 -2
  35. package/scripts/sync-public-files.mjs +4 -0
  36. package/src/commands/lineage.mjs +101 -32
  37. package/src/commands/prepare.mjs +273 -9
  38. package/src/commands/publish.mjs +10 -1
  39. package/src/commands/verify.mjs +22 -0
  40. package/src/core/bundle-freshness.mjs +236 -0
  41. package/src/core/errors.mjs +2 -0
  42. package/src/core/frozen-marker.mjs +97 -0
  43. package/src/core/hooks.mjs +12 -1
  44. package/src/core/skill-resource-closure.mjs +240 -10
  45. package/src/platforms/registry.mjs +12 -0
@@ -9,7 +9,9 @@ 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.6.0"});
12
+ const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.6.2"});
13
+ // Build-time source digest for the BUNDLE_STALE freshness gate (see above).
14
+ const __bundleSourceDigest = "12dcb7942e6587f1321c3f81625b0bc3f1dd64afe978ddf8084bf1a5824de23a";
13
15
 
14
16
  var __create = Object.create;
15
17
  var __defProp = Object.defineProperty;
@@ -175,6 +177,7 @@ __export(errors_exports, {
175
177
  AUTH_MISSING: () => AUTH_MISSING,
176
178
  BASELINE_CHANGED: () => BASELINE_CHANGED,
177
179
  BASE_UNAVAILABLE: () => BASE_UNAVAILABLE,
180
+ BUNDLE_STALE: () => BUNDLE_STALE,
178
181
  CONFIG_EXISTS: () => CONFIG_EXISTS,
179
182
  CONFIG_INVALID: () => CONFIG_INVALID,
180
183
  CONFIG_MISSING: () => CONFIG_MISSING,
@@ -221,7 +224,7 @@ __export(errors_exports, {
221
224
  function registerPathRedactor(fn) {
222
225
  if (typeof fn === "function") redactSensitivePaths2 = fn;
223
226
  }
224
- var redactSensitivePaths2, EXIT_CODE_MAP, CONFIG_INVALID, BASELINE_CHANGED, DIRTY_SCOPE_CONFLICT, GATE_FAILED, AUTH_MISSING, REMOTE_CONFLICT, HOOK_TIMEOUT, PARTIAL_RELEASE, POST_PUBLISH_VERIFY_FAILED, INVALID_STATE_TRANSITION, PLAN_DIGEST_MISMATCH, SECRET_DETECTED, PUBLIC_PATH_FORBIDDEN, STALE_BUILD_ARTIFACT, MISSING_PARAMETERS, PUBLIC_FILE_MISSING, SNAPSHOT_FIDELITY_FAILED, FORBIDDEN_CONTENT_DETECTED, PATH_UNSAFE, STRUCTURE_INVALID, LOCK_MIGRATION_REQUIRED, ARTIFACT_POLICY_INVALID, BASE_UNAVAILABLE, PRODUCER_NONDETERMINISTIC, PRODUCER_SCOPE_VIOLATION, ADOPTION_AMBIGUOUS, PLAN_STALE, SENSITIVE_CONFLICT, TRANSACTION_INCOMPLETE, SAFE_WRITE_UNAVAILABLE, SETUP_DIGEST_MISMATCH, CONFIG_EXISTS, RELEASE_DOCS_INVALID, RELEASE_DOCS_TRANSLATION_MISSING, RELEASE_DOCS_CONFLICT, RELEASE_DOCS_REFRESH_STALE, RELEASE_DOCS_STALE, CONSUMER_VERIFICATION_DEFERRED, CONFIG_MISSING, REMOTE_UNAVAILABLE, REF_MISSING, NOT_DEFAULT, CONTENT_MISMATCH, DIRTY_SOURCE_INPUT, ReleaseError, ALL_ERROR_CODES;
227
+ var redactSensitivePaths2, EXIT_CODE_MAP, CONFIG_INVALID, BASELINE_CHANGED, DIRTY_SCOPE_CONFLICT, GATE_FAILED, AUTH_MISSING, REMOTE_CONFLICT, HOOK_TIMEOUT, PARTIAL_RELEASE, POST_PUBLISH_VERIFY_FAILED, INVALID_STATE_TRANSITION, PLAN_DIGEST_MISMATCH, SECRET_DETECTED, PUBLIC_PATH_FORBIDDEN, STALE_BUILD_ARTIFACT, MISSING_PARAMETERS, PUBLIC_FILE_MISSING, SNAPSHOT_FIDELITY_FAILED, FORBIDDEN_CONTENT_DETECTED, PATH_UNSAFE, STRUCTURE_INVALID, LOCK_MIGRATION_REQUIRED, ARTIFACT_POLICY_INVALID, BASE_UNAVAILABLE, PRODUCER_NONDETERMINISTIC, PRODUCER_SCOPE_VIOLATION, ADOPTION_AMBIGUOUS, PLAN_STALE, SENSITIVE_CONFLICT, TRANSACTION_INCOMPLETE, SAFE_WRITE_UNAVAILABLE, SETUP_DIGEST_MISMATCH, CONFIG_EXISTS, RELEASE_DOCS_INVALID, RELEASE_DOCS_TRANSLATION_MISSING, RELEASE_DOCS_CONFLICT, RELEASE_DOCS_REFRESH_STALE, RELEASE_DOCS_STALE, CONSUMER_VERIFICATION_DEFERRED, CONFIG_MISSING, REMOTE_UNAVAILABLE, REF_MISSING, NOT_DEFAULT, CONTENT_MISMATCH, DIRTY_SOURCE_INPUT, BUNDLE_STALE, ReleaseError, ALL_ERROR_CODES;
225
228
  var init_errors = __esm({
226
229
  "src/core/errors.mjs"() {
227
230
  redactSensitivePaths2 = /* @__PURE__ */ __name((value) => value, "redactSensitivePaths");
@@ -275,7 +278,8 @@ var init_errors = __esm({
275
278
  REF_MISSING: 50,
276
279
  NOT_DEFAULT: 51,
277
280
  CONTENT_MISMATCH: 52,
278
- DIRTY_SOURCE_INPUT: 53
281
+ DIRTY_SOURCE_INPUT: 53,
282
+ BUNDLE_STALE: 54
279
283
  });
280
284
  CONFIG_INVALID = "CONFIG_INVALID";
281
285
  BASELINE_CHANGED = "BASELINE_CHANGED";
@@ -321,6 +325,7 @@ var init_errors = __esm({
321
325
  NOT_DEFAULT = "NOT_DEFAULT";
322
326
  CONTENT_MISMATCH = "CONTENT_MISMATCH";
323
327
  DIRTY_SOURCE_INPUT = "DIRTY_SOURCE_INPUT";
328
+ BUNDLE_STALE = "BUNDLE_STALE";
324
329
  ReleaseError = class _ReleaseError extends Error {
325
330
  static {
326
331
  __name(this, "ReleaseError");
@@ -21718,7 +21723,7 @@ var require_cjs = __commonJS({
21718
21723
  var require_lib2 = __commonJS({
21719
21724
  "../../node_modules/.pnpm/write-file-atomic@5.0.1/node_modules/write-file-atomic/lib/index.js"(exports, module) {
21720
21725
  "use strict";
21721
- module.exports = writeFile13;
21726
+ module.exports = writeFile14;
21722
21727
  module.exports.sync = writeFileSync2;
21723
21728
  module.exports._getTmpname = getTmpname;
21724
21729
  module.exports._cleanupOnExit = cleanupOnExit;
@@ -21848,7 +21853,7 @@ var require_lib2 = __commonJS({
21848
21853
  }
21849
21854
  }
21850
21855
  __name(writeFileAsync, "writeFileAsync");
21851
- async function writeFile13(filename, data, options, callback) {
21856
+ async function writeFile14(filename, data, options, callback) {
21852
21857
  if (options instanceof Function) {
21853
21858
  callback = options;
21854
21859
  options = {};
@@ -21864,7 +21869,7 @@ var require_lib2 = __commonJS({
21864
21869
  }
21865
21870
  return promise;
21866
21871
  }
21867
- __name(writeFile13, "writeFile");
21872
+ __name(writeFile14, "writeFile");
21868
21873
  function writeFileSync2(filename, data, options) {
21869
21874
  if (typeof options === "string") {
21870
21875
  options = { encoding: options };
@@ -22977,16 +22982,16 @@ var require_windows = __commonJS({
22977
22982
  return false;
22978
22983
  }
22979
22984
  __name(checkPathExt, "checkPathExt");
22980
- function checkStat(stat9, path15, options) {
22981
- if (!stat9.isSymbolicLink() && !stat9.isFile()) {
22985
+ function checkStat(stat10, path15, options) {
22986
+ if (!stat10.isSymbolicLink() && !stat10.isFile()) {
22982
22987
  return false;
22983
22988
  }
22984
22989
  return checkPathExt(path15, options);
22985
22990
  }
22986
22991
  __name(checkStat, "checkStat");
22987
22992
  function isexe(path15, options, cb) {
22988
- fs.stat(path15, function(er, stat9) {
22989
- cb(er, er ? false : checkStat(stat9, path15, options));
22993
+ fs.stat(path15, function(er, stat10) {
22994
+ cb(er, er ? false : checkStat(stat10, path15, options));
22990
22995
  });
22991
22996
  }
22992
22997
  __name(isexe, "isexe");
@@ -23004,8 +23009,8 @@ var require_mode = __commonJS({
23004
23009
  isexe.sync = sync;
23005
23010
  var fs = __require("fs");
23006
23011
  function isexe(path15, options, cb) {
23007
- fs.stat(path15, function(er, stat9) {
23008
- cb(er, er ? false : checkStat(stat9, options));
23012
+ fs.stat(path15, function(er, stat10) {
23013
+ cb(er, er ? false : checkStat(stat10, options));
23009
23014
  });
23010
23015
  }
23011
23016
  __name(isexe, "isexe");
@@ -23013,14 +23018,14 @@ var require_mode = __commonJS({
23013
23018
  return checkStat(fs.statSync(path15), options);
23014
23019
  }
23015
23020
  __name(sync, "sync");
23016
- function checkStat(stat9, options) {
23017
- return stat9.isFile() && checkMode(stat9, options);
23021
+ function checkStat(stat10, options) {
23022
+ return stat10.isFile() && checkMode(stat10, options);
23018
23023
  }
23019
23024
  __name(checkStat, "checkStat");
23020
- function checkMode(stat9, options) {
23021
- var mod = stat9.mode;
23022
- var uid = stat9.uid;
23023
- var gid = stat9.gid;
23025
+ function checkMode(stat10, options) {
23026
+ var mod = stat10.mode;
23027
+ var uid = stat10.uid;
23028
+ var gid = stat10.gid;
23024
23029
  var myUid = options.uid !== void 0 ? options.uid : process.getuid && process.getuid();
23025
23030
  var myGid = options.gid !== void 0 ? options.gid : process.getgid && process.getgid();
23026
23031
  var u = parseInt("100", 8);
@@ -23544,13 +23549,13 @@ var require_cross_spawn = __commonJS({
23544
23549
  var cp2 = __require("child_process");
23545
23550
  var parse2 = require_parse();
23546
23551
  var enoent = require_enoent();
23547
- function spawn4(command2, args2, options) {
23552
+ function spawn5(command2, args2, options) {
23548
23553
  const parsed = parse2(command2, args2, options);
23549
23554
  const spawned = cp2.spawn(parsed.command, parsed.args, parsed.options);
23550
23555
  enoent.hookChildProcess(spawned, parsed);
23551
23556
  return spawned;
23552
23557
  }
23553
- __name(spawn4, "spawn");
23558
+ __name(spawn5, "spawn");
23554
23559
  function spawnSync2(command2, args2, options) {
23555
23560
  const parsed = parse2(command2, args2, options);
23556
23561
  const result = cp2.spawnSync(parsed.command, parsed.args, parsed.options);
@@ -23558,8 +23563,8 @@ var require_cross_spawn = __commonJS({
23558
23563
  return result;
23559
23564
  }
23560
23565
  __name(spawnSync2, "spawnSync");
23561
- module.exports = spawn4;
23562
- module.exports.spawn = spawn4;
23566
+ module.exports = spawn5;
23567
+ module.exports.spawn = spawn5;
23563
23568
  module.exports.sync = spawnSync2;
23564
23569
  module.exports._parse = parse2;
23565
23570
  module.exports._enoent = enoent;
@@ -25725,8 +25730,8 @@ var require_graceful_fs = __commonJS({
25725
25730
  fs2.createReadStream = createReadStream2;
25726
25731
  fs2.createWriteStream = createWriteStream;
25727
25732
  var fs$readFile = fs2.readFile;
25728
- fs2.readFile = readFile40;
25729
- function readFile40(path15, options, cb) {
25733
+ fs2.readFile = readFile42;
25734
+ function readFile42(path15, options, cb) {
25730
25735
  if (typeof options === "function")
25731
25736
  cb = options, options = null;
25732
25737
  return go$readFile(path15, options, cb);
@@ -25742,10 +25747,10 @@ var require_graceful_fs = __commonJS({
25742
25747
  }
25743
25748
  __name(go$readFile, "go$readFile");
25744
25749
  }
25745
- __name(readFile40, "readFile");
25750
+ __name(readFile42, "readFile");
25746
25751
  var fs$writeFile = fs2.writeFile;
25747
- fs2.writeFile = writeFile13;
25748
- function writeFile13(path15, data, options, cb) {
25752
+ fs2.writeFile = writeFile14;
25753
+ function writeFile14(path15, data, options, cb) {
25749
25754
  if (typeof options === "function")
25750
25755
  cb = options, options = null;
25751
25756
  return go$writeFile(path15, data, options, cb);
@@ -25761,7 +25766,7 @@ var require_graceful_fs = __commonJS({
25761
25766
  }
25762
25767
  __name(go$writeFile, "go$writeFile");
25763
25768
  }
25764
- __name(writeFile13, "writeFile");
25769
+ __name(writeFile14, "writeFile");
25765
25770
  var fs$appendFile = fs2.appendFile;
25766
25771
  if (fs$appendFile)
25767
25772
  fs2.appendFile = appendFile;
@@ -25805,9 +25810,9 @@ var require_graceful_fs = __commonJS({
25805
25810
  }
25806
25811
  __name(copyFile, "copyFile");
25807
25812
  var fs$readdir = fs2.readdir;
25808
- fs2.readdir = readdir20;
25813
+ fs2.readdir = readdir21;
25809
25814
  var noReaddirOptionVersions = /^v[0-5]\./;
25810
- function readdir20(path15, options, cb) {
25815
+ function readdir21(path15, options, cb) {
25811
25816
  if (typeof options === "function")
25812
25817
  cb = options, options = null;
25813
25818
  var go$readdir = noReaddirOptionVersions.test(process.version) ? /* @__PURE__ */ __name(function go$readdir2(path16, options2, cb2, startTime) {
@@ -25846,7 +25851,7 @@ var require_graceful_fs = __commonJS({
25846
25851
  }
25847
25852
  __name(fs$readdirCallback, "fs$readdirCallback");
25848
25853
  }
25849
- __name(readdir20, "readdir");
25854
+ __name(readdir21, "readdir");
25850
25855
  if (process.version.substr(0, 4) === "v0.8") {
25851
25856
  var legStreams = legacy(fs2);
25852
25857
  ReadStream = legStreams.ReadStream;
@@ -27559,7 +27564,7 @@ var require_lib10 = __commonJS({
27559
27564
  Object.defineProperty(exports, "__esModule", { value: true });
27560
27565
  exports.createShortHash = createShortHash;
27561
27566
  exports.createHexHash = createHexHash;
27562
- exports.createHash = createHash17;
27567
+ exports.createHash = createHash18;
27563
27568
  exports.createHashFromMultipleFiles = createHashFromMultipleFiles;
27564
27569
  exports.createHashFromFile = createHashFromFile;
27565
27570
  exports.createHexHashFromFile = createHexHashFromFile;
@@ -27576,20 +27581,20 @@ var require_lib10 = __commonJS({
27576
27581
  return crypto.hash("sha256", input, "hex");
27577
27582
  }
27578
27583
  __name(createHexHash, "createHexHash");
27579
- function createHash17(input) {
27584
+ function createHash18(input) {
27580
27585
  return `sha256-${crypto.hash("sha256", input, "base64")}`;
27581
27586
  }
27582
- __name(createHash17, "createHash");
27587
+ __name(createHash18, "createHash");
27583
27588
  async function createHashFromMultipleFiles(files) {
27584
27589
  if (files.length === 1) {
27585
27590
  return createHashFromFile(files[0]);
27586
27591
  }
27587
27592
  const hashes = await Promise.all(files.map(createHashFromFile));
27588
- return createHash17(hashes.join(","));
27593
+ return createHash18(hashes.join(","));
27589
27594
  }
27590
27595
  __name(createHashFromMultipleFiles, "createHashFromMultipleFiles");
27591
27596
  async function createHashFromFile(file) {
27592
- return createHash17(await readNormalizedFile(file));
27597
+ return createHash18(await readNormalizedFile(file));
27593
27598
  }
27594
27599
  __name(createHashFromFile, "createHashFromFile");
27595
27600
  async function createHexHashFromFile(file) {
@@ -32213,7 +32218,7 @@ var init_report = __esm({
32213
32218
  init_closure();
32214
32219
  init_errors3();
32215
32220
  init_validation();
32216
- PACKAGE_META = Object.freeze({ "name": "release-skill", "version": "0.6.0" });
32221
+ PACKAGE_META = Object.freeze({ "name": "release-skill", "version": "0.6.2" });
32217
32222
  REPORT_RENDERER_VERSION = PACKAGE_META.version;
32218
32223
  SUPPORTED_REPORT_LOCALES = Object.freeze(["zh-CN", "en-US"]);
32219
32224
  EXECUTION_STATUSES = Object.freeze([
@@ -33153,10 +33158,10 @@ function lexicalPath(resource, code) {
33153
33158
  }
33154
33159
  return path15;
33155
33160
  }
33156
- function assertStat(stat9, resource, code) {
33157
- if (stat9.isSymbolicLink()) fail(code, resource, "SYMLINK");
33158
- if (!stat9.isFile()) fail(code, resource, "NOT_REGULAR_FILE");
33159
- if (stat9.nlink !== 1) fail(code, resource, "UNEXPECTED_HARDLINK_COUNT");
33161
+ function assertStat(stat10, resource, code) {
33162
+ if (stat10.isSymbolicLink()) fail(code, resource, "SYMLINK");
33163
+ if (!stat10.isFile()) fail(code, resource, "NOT_REGULAR_FILE");
33164
+ if (stat10.nlink !== 1) fail(code, resource, "UNEXPECTED_HARDLINK_COUNT");
33160
33165
  }
33161
33166
  function assertPhysicalContainment(physicalRoot, physicalPath, resource, code) {
33162
33167
  const rel = relative(physicalRoot, physicalPath);
@@ -33190,13 +33195,13 @@ function readTrustedPackageResourceSync(resource, { code = CONFIG_INVALID } = {}
33190
33195
  const classification = classifyPathInput(resource, process.platform);
33191
33196
  if (!classification.ok) fail(code, String(resource), "INVALID_RESOURCE_PATH");
33192
33197
  const path15 = lexicalPath(resource, code);
33193
- let stat9;
33198
+ let stat10;
33194
33199
  try {
33195
- stat9 = lstatSync2(path15);
33200
+ stat10 = lstatSync2(path15);
33196
33201
  } catch {
33197
33202
  fail(code, resource, "MISSING");
33198
33203
  }
33199
- assertStat(stat9, resource, code);
33204
+ assertStat(stat10, resource, code);
33200
33205
  let physicalRoot;
33201
33206
  let physicalPath;
33202
33207
  try {
@@ -33219,13 +33224,13 @@ async function readTrustedPackageResource(resource, { code = CONFIG_INVALID } =
33219
33224
  } catch (cause) {
33220
33225
  mapHarnessError(cause, resource, code);
33221
33226
  }
33222
- let stat9;
33227
+ let stat10;
33223
33228
  try {
33224
- stat9 = await lstat8(target);
33229
+ stat10 = await lstat8(target);
33225
33230
  } catch {
33226
33231
  fail(code, resource, "MISSING");
33227
33232
  }
33228
- assertStat(stat9, resource, code);
33233
+ assertStat(stat10, resource, code);
33229
33234
  try {
33230
33235
  return await readFileContained(PKG_ROOT, resource);
33231
33236
  } catch (cause) {
@@ -33465,14 +33470,14 @@ async function assertNoSymlinkAncestors(directory) {
33465
33470
  let current = join2(parsed.root, ...segments.slice(0, firstChecked));
33466
33471
  for (const segment of segments.slice(firstChecked)) {
33467
33472
  current = join2(current, segment);
33468
- let stat9;
33473
+ let stat10;
33469
33474
  try {
33470
- stat9 = await lstat9(current);
33475
+ stat10 = await lstat9(current);
33471
33476
  } catch (error) {
33472
33477
  if (error.code === "ENOENT") continue;
33473
33478
  throw error;
33474
33479
  }
33475
- if (stat9.isSymbolicLink() || !stat9.isDirectory()) {
33480
+ if (stat10.isSymbolicLink() || !stat10.isDirectory()) {
33476
33481
  throw new ReleaseError(
33477
33482
  GATE_FAILED,
33478
33483
  "release authority path contains a symlink or non-directory ancestor",
@@ -33492,8 +33497,8 @@ async function assertAuthorityFileTarget(filePath) {
33492
33497
  const absolute = resolve3(filePath);
33493
33498
  await prepareAuthorityDirectory(dirname3(absolute));
33494
33499
  try {
33495
- const stat9 = await lstat9(absolute);
33496
- if (stat9.isSymbolicLink() || !stat9.isFile()) {
33500
+ const stat10 = await lstat9(absolute);
33501
+ if (stat10.isSymbolicLink() || !stat10.isFile()) {
33497
33502
  throw new ReleaseError(
33498
33503
  GATE_FAILED,
33499
33504
  "release authority target must be a regular file, never a symlink or special file",
@@ -35538,6 +35543,9 @@ function assertRegistry(registry = PLATFORMS) {
35538
35543
  if (!platform.buildAdapter || typeof platform.buildAdapter !== "object") {
35539
35544
  throw new Error(`platform registry: ${label} buildAdapter must be an object`);
35540
35545
  }
35546
+ if (typeof platform.buildAdapter.name !== "string" || platform.buildAdapter.name.length === 0) {
35547
+ throw new Error(`platform registry: ${label} buildAdapter needs a non-empty name (its adapter directory name)`);
35548
+ }
35541
35549
  if (!VALID_LIST_OUTPUTS.has(platform.jsonProtocol?.listOutput)) {
35542
35550
  throw new Error(`platform registry: ${label} has illegal jsonProtocol.listOutput "${platform.jsonProtocol?.listOutput}"`);
35543
35551
  }
@@ -35725,6 +35733,9 @@ var init_registry2 = __esm({
35725
35733
  schemaRequiredFields: Object.freeze(["plugin", "marketplace", "entrySkill"]),
35726
35734
  skillRendering: Object.freeze({ mode: "verbatim", preamble: null, placeholder: "${CLAUDE_PLUGIN_ROOT}" }),
35727
35735
  buildAdapter: Object.freeze({
35736
+ // D6: explicit adapter directory name (adapters/claude/); assertRegistry
35737
+ // requires this on every platform.
35738
+ name: "claude",
35728
35739
  pluginDirName: ".claude-plugin",
35729
35740
  templateFileName: "plugin.json",
35730
35741
  marketplaceFileName: "marketplace.json",
@@ -35782,6 +35793,8 @@ var init_registry2 = __esm({
35782
35793
  schemaRequiredFields: Object.freeze(["plugin", "marketplace", "entrySkill"]),
35783
35794
  skillRendering: Object.freeze({ mode: "substitute", preamble: "codex", placeholder: "${CLAUDE_PLUGIN_ROOT}" }),
35784
35795
  buildAdapter: Object.freeze({
35796
+ // D6: explicit adapter directory name (adapters/codex/).
35797
+ name: "codex",
35785
35798
  pluginDirName: ".codex-plugin",
35786
35799
  templateFileName: "plugin.json",
35787
35800
  marketplaceFileName: null,
@@ -35838,6 +35851,8 @@ var init_registry2 = __esm({
35838
35851
  schemaRequiredFields: Object.freeze(["plugin", "entrySkill"]),
35839
35852
  skillRendering: Object.freeze({ mode: "substitute", preamble: "kimi", placeholder: "${CLAUDE_PLUGIN_ROOT}" }),
35840
35853
  buildAdapter: Object.freeze({
35854
+ // D6: explicit adapter directory name (adapters/kimi/).
35855
+ name: "kimi",
35841
35856
  pluginDirName: ".kimi-plugin",
35842
35857
  templateFileName: "plugin.json",
35843
35858
  marketplaceFileName: null,
@@ -37362,8 +37377,8 @@ function safeRelative(root, path15) {
37362
37377
  return rel || ".";
37363
37378
  }
37364
37379
  async function readJsonBounded(path15, label) {
37365
- const stat9 = await lstat11(path15);
37366
- if (!stat9.isFile() || stat9.isSymbolicLink() || stat9.size > MAX_JSON_BYTES) {
37380
+ const stat10 = await lstat11(path15);
37381
+ if (!stat10.isFile() || stat10.isSymbolicLink() || stat10.size > MAX_JSON_BYTES) {
37367
37382
  throw setupError(CONFIG_INVALID, `${label} must be a regular JSON file no larger than 1 MiB`, { path: path15 });
37368
37383
  }
37369
37384
  try {
@@ -37625,14 +37640,14 @@ async function pathIsGitIgnored(unitAbsDir, target) {
37625
37640
  async function classifyNpmEntryCandidate(unitAbsDir, target, trackedFiles) {
37626
37641
  const tracked = trackedFiles.includes(target);
37627
37642
  const ignored = await pathIsGitIgnored(unitAbsDir, target);
37628
- let stat9 = null;
37643
+ let stat10 = null;
37629
37644
  try {
37630
- stat9 = await lstat11(join8(unitAbsDir, target));
37645
+ stat10 = await lstat11(join8(unitAbsDir, target));
37631
37646
  } catch (error) {
37632
37647
  if (error.code !== "ENOENT") throw error;
37633
37648
  }
37634
- const exists = stat9 !== null;
37635
- const regular = stat9?.isFile() === true && stat9?.isSymbolicLink() !== true;
37649
+ const exists = stat10 !== null;
37650
+ const regular = stat10?.isFile() === true && stat10?.isSymbolicLink() !== true;
37636
37651
  const state = exists && !regular ? "NON_REGULAR" : exists && tracked ? "TRACKED_PRESENT" : exists && ignored ? "IGNORED_PRESENT" : exists ? "UNTRACKED_PRESENT" : ignored ? "IGNORED_MISSING" : "MISSING";
37637
37652
  return { path: target, state, exists, tracked, ignored };
37638
37653
  }
@@ -38524,9 +38539,9 @@ async function setupProject({ root, answersPath, write = false, confirmSetup, fa
38524
38539
  const configPath = join8(rootReal, ".release-skill", "project.yaml");
38525
38540
  let configExists = false;
38526
38541
  try {
38527
- const stat9 = await lstat11(configPath);
38542
+ const stat10 = await lstat11(configPath);
38528
38543
  configExists = true;
38529
- if (!stat9.isFile() || stat9.isSymbolicLink()) {
38544
+ if (!stat10.isFile() || stat10.isSymbolicLink()) {
38530
38545
  throw setupError(CONFIG_INVALID, "existing project.yaml must be a regular file");
38531
38546
  }
38532
38547
  } catch (error) {
@@ -39064,9 +39079,9 @@ async function assertSafeDirectoryPath({
39064
39079
  let cursor = workspaceRoot;
39065
39080
  for (const segment of rel.split(sep3).filter(Boolean)) {
39066
39081
  cursor = join9(cursor, segment);
39067
- let stat9;
39082
+ let stat10;
39068
39083
  try {
39069
- stat9 = await lstat12(cursor);
39084
+ stat10 = await lstat12(cursor);
39070
39085
  } catch (error) {
39071
39086
  failConfig(`cannot inspect public surface scan root "${configuredRoot}"`, {
39072
39087
  reason: "PUBLIC_SURFACE_SCAN_ROOT_UNSAFE",
@@ -39075,7 +39090,7 @@ async function assertSafeDirectoryPath({
39075
39090
  cause: error.code ?? "UNKNOWN"
39076
39091
  });
39077
39092
  }
39078
- if (stat9.isSymbolicLink() || !stat9.isDirectory()) {
39093
+ if (stat10.isSymbolicLink() || !stat10.isDirectory()) {
39079
39094
  failConfig(`public surface scan root or ancestor is not a physical directory: "${configuredRoot}"`, {
39080
39095
  reason: "PUBLIC_SURFACE_SCAN_ROOT_UNSAFE",
39081
39096
  unitId,
@@ -39462,24 +39477,24 @@ async function computeWorkspaceDigest(root) {
39462
39477
  `Refusing to read path outside repository root: ${relPath} resolves to ${absPath}`
39463
39478
  );
39464
39479
  }
39465
- const stat9 = await lstat13(absPath);
39480
+ const stat10 = await lstat13(absPath);
39466
39481
  let type;
39467
- if (stat9.isSymbolicLink()) {
39482
+ if (stat10.isSymbolicLink()) {
39468
39483
  type = "symlink";
39469
- } else if (stat9.isDirectory()) {
39484
+ } else if (stat10.isDirectory()) {
39470
39485
  type = "dir";
39471
- } else if (stat9.isFile()) {
39486
+ } else if (stat10.isFile()) {
39472
39487
  type = "file";
39473
39488
  } else {
39474
39489
  type = "other";
39475
39490
  }
39476
39491
  const typeMarker = `TYPE:${type}`;
39477
39492
  let content;
39478
- if (stat9.isFile()) {
39493
+ if (stat10.isFile()) {
39479
39494
  const handle = await open6(absPath, fsConstants2.O_RDONLY | fsConstants2.O_NOFOLLOW);
39480
39495
  try {
39481
39496
  const fdStat = await handle.stat();
39482
- if (fdStat.ino !== stat9.ino) {
39497
+ if (fdStat.ino !== stat10.ino) {
39483
39498
  throw new Error(
39484
39499
  `Race detected: inode changed for ${relPath} between lstat and read`
39485
39500
  );
@@ -39494,7 +39509,7 @@ async function computeWorkspaceDigest(root) {
39494
39509
  } finally {
39495
39510
  await handle.close();
39496
39511
  }
39497
- } else if (stat9.isSymbolicLink()) {
39512
+ } else if (stat10.isSymbolicLink()) {
39498
39513
  content = Buffer.from(await readlink(absPath), "utf8");
39499
39514
  } else {
39500
39515
  content = Buffer.alloc(0);
@@ -40908,7 +40923,7 @@ function validateHook(hook) {
40908
40923
  if (!hook || typeof hook !== "object" || Array.isArray(hook)) {
40909
40924
  throw new ReleaseError("INVALID_HOOK", "hook must be a non-null object");
40910
40925
  }
40911
- const { command: command2, cwd, timeoutMs, envAllowlist, cacheable, cacheInputs } = hook;
40926
+ const { command: command2, cwd, timeoutMs, envAllowlist, cacheable, cacheInputs, testSelection } = hook;
40912
40927
  if (!Array.isArray(command2) || command2.length === 0) {
40913
40928
  throw new ReleaseError("INVALID_HOOK", "hook.command must be a non-empty array");
40914
40929
  }
@@ -40963,6 +40978,12 @@ function validateHook(hook) {
40963
40978
  "hook.cacheable=true requires a non-empty hook.cacheInputs"
40964
40979
  );
40965
40980
  }
40981
+ if (testSelection !== void 0 && testSelection !== "full" && testSelection !== "incremental") {
40982
+ throw new ReleaseError(
40983
+ "INVALID_HOOK",
40984
+ 'hook.testSelection must be "full" or "incremental" when provided'
40985
+ );
40986
+ }
40966
40987
  }
40967
40988
  function buildFilteredEnv(envAllowlist, contextEnv) {
40968
40989
  const env = {};
@@ -41279,10 +41300,10 @@ async function resolveSafeCwd(executionRoot, cwd, gate) {
41279
41300
  let current = rootReal;
41280
41301
  for (const segment of rel.split(/[\\/]/).filter(Boolean)) {
41281
41302
  current = join11(current, segment);
41282
- const stat9 = await lstat14(current).catch((error) => {
41303
+ const stat10 = await lstat14(current).catch((error) => {
41283
41304
  throw gateError(gate, "cwd does not exist", { cause: error.code });
41284
41305
  });
41285
- if (stat9.isSymbolicLink()) throw gateError(gate, "cwd contains a symlink");
41306
+ if (stat10.isSymbolicLink()) throw gateError(gate, "cwd contains a symlink");
41286
41307
  }
41287
41308
  const physical = await realpath12(lexical);
41288
41309
  if (!isInside2(rootReal, physical)) throw gateError(gate, "cwd resolves outside the execution root");
@@ -41523,9 +41544,9 @@ async function runVerificationGate({
41523
41544
  return result;
41524
41545
  }
41525
41546
  async function makeTreeWritable(root) {
41526
- const stat9 = await lstat14(root);
41527
- if (!stat9.isDirectory() || stat9.isSymbolicLink()) throw new Error("gate copy root must be a real directory");
41528
- await chmod2(root, stat9.mode | 448);
41547
+ const stat10 = await lstat14(root);
41548
+ if (!stat10.isDirectory() || stat10.isSymbolicLink()) throw new Error("gate copy root must be a real directory");
41549
+ await chmod2(root, stat10.mode | 448);
41529
41550
  for (const child of await readdir7(root, { withFileTypes: true })) {
41530
41551
  const absolute = join11(root, child.name);
41531
41552
  const childStat = await lstat14(absolute);
@@ -41696,7 +41717,7 @@ function trimCandidate(value) {
41696
41717
  function isPathToken(value) {
41697
41718
  const token = trimCandidate(value);
41698
41719
  if (!token || GLOB_PATTERN.test(token)) return false;
41699
- 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);
41720
+ return BARE_PREFIXES.some((prefix) => token.startsWith(prefix)) || EXPLICIT_PREFIXES.some((prefix) => token.startsWith(prefix)) || HOME_DIRECTORY_PATTERN.test(token) || SOURCE_TREE_PATTERN.test(token) || MACHINE_ABSOLUTE_PATTERN.test(token);
41700
41721
  }
41701
41722
  function scanSnippet(snippet, line, sourceOnly, results, seen) {
41702
41723
  const candidates = snippet.match(/(?:"[^"\n]+"|'[^'\n]+'|[^\s"'`()\[\],;]+)/gu) ?? [];
@@ -41721,15 +41742,14 @@ function extractPathTokens(content) {
41721
41742
  inFence = !inFence;
41722
41743
  continue;
41723
41744
  }
41724
- const sourceOnly = SOURCE_ONLY_MARKER.test(line);
41725
- if (inFence) scanSnippet(line, lineNumber, sourceOnly, results, seen);
41745
+ if (inFence) scanSnippet(line, lineNumber, SOURCE_ONLY_MARKER.test(line), results, seen);
41726
41746
  for (const match of line.matchAll(/`([^`]+)`/gu)) {
41727
- scanSnippet(match[1], lineNumber, sourceOnly, results, seen);
41747
+ scanSnippet(match[1], lineNumber, SOURCE_ONLY_MARKER.test(match[1]), results, seen);
41728
41748
  }
41729
41749
  for (const match of line.matchAll(/\]\(([^)]+)\)/gu)) {
41730
41750
  const target = match[1].trim().split(/[?#]/u)[0];
41731
41751
  if (!/^(?:https?:|#)/iu.test(target)) {
41732
- scanSnippet(target, lineNumber, sourceOnly, results, seen);
41752
+ scanSnippet(target, lineNumber, SOURCE_ONLY_MARKER.test(match[1]), results, seen);
41733
41753
  }
41734
41754
  }
41735
41755
  }
@@ -41750,6 +41770,14 @@ function classifyReference(token, skillRoot, pluginRoot, scanRoot2) {
41750
41770
  absoluteTarget: token
41751
41771
  };
41752
41772
  }
41773
+ if (HOME_DIRECTORY_PATTERN.test(token)) {
41774
+ return {
41775
+ classification: CLASSIFICATION.HOME_DIRECTORY,
41776
+ resolutionRoot: "(home)",
41777
+ resolvedTarget: token,
41778
+ absoluteTarget: token
41779
+ };
41780
+ }
41753
41781
  if (SOURCE_TREE_PATTERN.test(token)) {
41754
41782
  return {
41755
41783
  classification: CLASSIFICATION.SOURCE_BACKJUMP,
@@ -41780,14 +41808,14 @@ async function inspectRegularFile(root, target) {
41780
41808
  }
41781
41809
  for (const part of parts) {
41782
41810
  current = join12(current, part);
41783
- let stat9;
41811
+ let stat10;
41784
41812
  try {
41785
- stat9 = await lstat15(current);
41813
+ stat10 = await lstat15(current);
41786
41814
  } catch (error) {
41787
41815
  if (error.code === "ENOENT") return { code: FINDING_CODE.RESOURCE_MISSING };
41788
41816
  throw error;
41789
41817
  }
41790
- if (stat9.isSymbolicLink()) return { code: FINDING_CODE.SYMLINK_NOT_ALLOWED };
41818
+ if (stat10.isSymbolicLink()) return { code: FINDING_CODE.SYMLINK_NOT_ALLOWED };
41791
41819
  }
41792
41820
  const targetStat = await lstat15(target);
41793
41821
  if (!targetStat.isFile() || targetStat.nlink !== 1) {
@@ -41795,8 +41823,26 @@ async function inspectRegularFile(root, target) {
41795
41823
  }
41796
41824
  return { code: null };
41797
41825
  }
41826
+ async function collectRegularFiles(dir, results) {
41827
+ let entries;
41828
+ try {
41829
+ entries = await readdir8(dir, { withFileTypes: true });
41830
+ } catch (error) {
41831
+ if (error.code === "ENOENT") return;
41832
+ throw error;
41833
+ }
41834
+ for (const entry of [...entries].sort((a, b) => a.name.localeCompare(b.name))) {
41835
+ if (entry.isSymbolicLink()) continue;
41836
+ const absolute = join12(dir, entry.name);
41837
+ if (entry.isDirectory()) {
41838
+ await collectRegularFiles(absolute, results);
41839
+ } else if (entry.isFile()) {
41840
+ results.push(absolute);
41841
+ }
41842
+ }
41843
+ }
41798
41844
  function inferSurfaceHost(surfaceId, defaultHost) {
41799
- const match = /^adapters\/([^/]+)$/u.exec(surfaceId);
41845
+ const match = ADAPTER_SURFACE_PATTERN.exec(surfaceId);
41800
41846
  return match?.[1] ?? defaultHost;
41801
41847
  }
41802
41848
  function receiptProjection(result) {
@@ -41807,6 +41853,7 @@ function receiptProjection(result) {
41807
41853
  skillCount: result.skillCount,
41808
41854
  referenceCount: result.referenceCount,
41809
41855
  sourceOnlyCount: result.sourceOnlyCount,
41856
+ sourceOnlyReferences: result.sourceOnlyReferences,
41810
41857
  findingCount: result.findings.length
41811
41858
  };
41812
41859
  }
@@ -41883,8 +41930,23 @@ async function checkSkillResourceClosure({
41883
41930
  const skillPaths = await discoverSkills(scanRoot2);
41884
41931
  const findings = [];
41885
41932
  const surfaceMap = /* @__PURE__ */ new Map();
41933
+ const skillsBySurface = /* @__PURE__ */ new Map();
41934
+ const resolvedResourcesBySurface = /* @__PURE__ */ new Map();
41935
+ const referencedTargetsBySurface = /* @__PURE__ */ new Map();
41936
+ const resourceReferencesBySurface = /* @__PURE__ */ new Map();
41937
+ const sourceOnlyReferences = [];
41886
41938
  let referenceCount = 0;
41887
41939
  let sourceOnlyCount = 0;
41940
+ const recordSourceOnlyExemption = /* @__PURE__ */ __name((surface, skill, pathToken) => {
41941
+ sourceOnlyCount += 1;
41942
+ surface.sourceOnlyCount += 1;
41943
+ sourceOnlyReferences.push({
41944
+ skill,
41945
+ line: pathToken.line,
41946
+ reference: pathToken.token,
41947
+ surface: surface.id
41948
+ });
41949
+ }, "recordSourceOnlyExemption");
41888
41950
  for (const skill of skillPaths) {
41889
41951
  const skillRoot = resolveSkillRoot(skill, scanRoot2);
41890
41952
  const pluginRoot = resolvePluginRoot(skill, scanRoot2);
@@ -41899,6 +41961,8 @@ async function checkSkillResourceClosure({
41899
41961
  };
41900
41962
  surface.skillCount += 1;
41901
41963
  surfaceMap.set(surfaceId, surface);
41964
+ if (!skillsBySurface.has(surfaceId)) skillsBySurface.set(surfaceId, []);
41965
+ skillsBySurface.get(surfaceId).push(skill);
41902
41966
  const content = await readFile12(resolve16(scanRoot2, skill), "utf8");
41903
41967
  for (const pathToken of extractPathTokens(content)) {
41904
41968
  referenceCount += 1;
@@ -41921,8 +41985,7 @@ async function checkSkillResourceClosure({
41921
41985
  };
41922
41986
  if (classification.classification === CLASSIFICATION.SOURCE_BACKJUMP) {
41923
41987
  if (pathToken.sourceOnly) {
41924
- sourceOnlyCount += 1;
41925
- surface.sourceOnlyCount += 1;
41988
+ recordSourceOnlyExemption(surface, skill, pathToken);
41926
41989
  } else {
41927
41990
  findings.push({ ...findingBase, code: FINDING_CODE.SOURCE_BACKJUMP });
41928
41991
  }
@@ -41932,6 +41995,10 @@ async function checkSkillResourceClosure({
41932
41995
  findings.push({ ...findingBase, code: FINDING_CODE.MACHINE_ABSOLUTE_PATH });
41933
41996
  continue;
41934
41997
  }
41998
+ if (classification.classification === CLASSIFICATION.HOME_DIRECTORY) {
41999
+ findings.push({ ...findingBase, code: FINDING_CODE.HOME_DIRECTORY_SEARCH });
42000
+ continue;
42001
+ }
41935
42002
  if (classification.classification === CLASSIFICATION.OUT_OF_BOUNDS) {
41936
42003
  findings.push({ ...findingBase, code: FINDING_CODE.OUT_OF_BOUNDS });
41937
42004
  continue;
@@ -41943,14 +42010,112 @@ async function checkSkillResourceClosure({
41943
42010
  );
41944
42011
  if (inspection.code) {
41945
42012
  if (pathToken.sourceOnly && inspection.code === FINDING_CODE.RESOURCE_MISSING) {
41946
- sourceOnlyCount += 1;
41947
- surface.sourceOnlyCount += 1;
42013
+ recordSourceOnlyExemption(surface, skill, pathToken);
41948
42014
  } else {
41949
42015
  findings.push({ ...findingBase, code: inspection.code });
41950
42016
  }
42017
+ continue;
42018
+ }
42019
+ const relativeResource = relativeStable(pluginRoot, classification.absoluteTarget);
42020
+ if (!resolvedResourcesBySurface.has(surfaceId)) {
42021
+ resolvedResourcesBySurface.set(surfaceId, /* @__PURE__ */ new Map());
42022
+ referencedTargetsBySurface.set(surfaceId, /* @__PURE__ */ new Set());
42023
+ resourceReferencesBySurface.set(surfaceId, /* @__PURE__ */ new Map());
42024
+ }
42025
+ resolvedResourcesBySurface.get(surfaceId).set(relativeResource, classification.absoluteTarget);
42026
+ referencedTargetsBySurface.get(surfaceId).add(classification.absoluteTarget);
42027
+ const resourceReferences = resourceReferencesBySurface.get(surfaceId);
42028
+ if (!resourceReferences.has(relativeResource)) resourceReferences.set(relativeResource, []);
42029
+ resourceReferences.get(relativeResource).push({
42030
+ surface: surfaceId,
42031
+ skill,
42032
+ line: pathToken.line
42033
+ });
42034
+ }
42035
+ }
42036
+ const contentDigestCache = /* @__PURE__ */ new Map();
42037
+ const digestOfTarget = /* @__PURE__ */ __name(async (absoluteTarget) => {
42038
+ if (!contentDigestCache.has(absoluteTarget)) {
42039
+ contentDigestCache.set(
42040
+ absoluteTarget,
42041
+ digestDocument({ content: await readFile12(absoluteTarget, "utf8") })
42042
+ );
42043
+ }
42044
+ return contentDigestCache.get(absoluteTarget);
42045
+ }, "digestOfTarget");
42046
+ const surfaceIds = [...resolvedResourcesBySurface.keys()].sort((a, b) => a.localeCompare(b));
42047
+ for (let i = 0; i < surfaceIds.length; i += 1) {
42048
+ for (let j = i + 1; j < surfaceIds.length; j += 1) {
42049
+ const [leftId, rightId] = [surfaceIds[i], surfaceIds[j]];
42050
+ const left = resolvedResourcesBySurface.get(leftId);
42051
+ const right = resolvedResourcesBySurface.get(rightId);
42052
+ const commonPaths = [...left.keys()].filter((path15) => right.has(path15)).sort((a, b) => a.localeCompare(b));
42053
+ for (const resourcePath of commonPaths) {
42054
+ const [leftDigest, rightDigest] = await Promise.all([
42055
+ digestOfTarget(left.get(resourcePath)),
42056
+ digestOfTarget(right.get(resourcePath))
42057
+ ]);
42058
+ if (leftDigest === rightDigest) continue;
42059
+ const rightSurface = surfaceMap.get(rightId);
42060
+ const driftReferences = [];
42061
+ const seenReference = /* @__PURE__ */ new Set();
42062
+ for (const surfaceId of [leftId, rightId]) {
42063
+ for (const ref of resourceReferencesBySurface.get(surfaceId)?.get(resourcePath) ?? []) {
42064
+ const key = `${ref.surface}\0${ref.skill}\0${ref.line}`;
42065
+ if (seenReference.has(key)) continue;
42066
+ seenReference.add(key);
42067
+ driftReferences.push({ surface: ref.surface, skill: ref.skill, line: ref.line });
42068
+ }
42069
+ }
42070
+ driftReferences.sort((a, b) => a.surface.localeCompare(b.surface) || a.skill.localeCompare(b.skill) || a.line - b.line);
42071
+ findings.push({
42072
+ host: rightSurface.host,
42073
+ surface: rightId,
42074
+ skill: null,
42075
+ line: null,
42076
+ reference: resourcePath,
42077
+ classification: CLASSIFICATION.RESOURCE_DRIFT,
42078
+ resolutionRoot: rightId,
42079
+ resolvedTarget: resourcePath,
42080
+ surfaces: [leftId, rightId],
42081
+ references: driftReferences,
42082
+ code: FINDING_CODE.RESOURCE_DRIFT
42083
+ });
42084
+ }
42085
+ }
42086
+ }
42087
+ for (const surfaceId of [...skillsBySurface.keys()].sort((a, b) => a.localeCompare(b))) {
42088
+ if (!ADAPTER_SURFACE_PATTERN.test(surfaceId)) continue;
42089
+ const surface = surfaceMap.get(surfaceId);
42090
+ const surfaceRootAbsolute = resolve16(scanRoot2, surfaceId);
42091
+ const referencedTargets = referencedTargetsBySurface.get(surfaceId) ?? /* @__PURE__ */ new Set();
42092
+ const stale = [];
42093
+ for (const skill of skillsBySurface.get(surfaceId)) {
42094
+ const skillDir = resolve16(scanRoot2, dirname7(skill));
42095
+ for (const closureDir of CLOSURE_RESOURCE_DIRS) {
42096
+ const files = [];
42097
+ await collectRegularFiles(join12(skillDir, closureDir), files);
42098
+ for (const absolute of files) {
42099
+ if (referencedTargets.has(absolute)) continue;
42100
+ const relativeResource = relativeStable(surfaceRootAbsolute, absolute);
42101
+ stale.push({
42102
+ host: surface.host,
42103
+ surface: surfaceId,
42104
+ skill,
42105
+ line: null,
42106
+ reference: relativeResource,
42107
+ classification: CLASSIFICATION.STALE_RESOURCE,
42108
+ resolutionRoot: surfaceId,
42109
+ resolvedTarget: relativeResource,
42110
+ code: FINDING_CODE.STALE_RESOURCE
42111
+ });
42112
+ }
41951
42113
  }
41952
42114
  }
42115
+ stale.sort((a, b) => a.skill.localeCompare(b.skill) || a.resolvedTarget.localeCompare(b.resolvedTarget));
42116
+ findings.push(...stale);
41953
42117
  }
42118
+ sourceOnlyReferences.sort((a, b) => a.skill.localeCompare(b.skill) || a.line - b.line || a.reference.localeCompare(b.reference));
41954
42119
  if (snapshotError) {
41955
42120
  findings.push({
41956
42121
  host,
@@ -41973,18 +42138,29 @@ async function checkSkillResourceClosure({
41973
42138
  skillCount: skillPaths.length,
41974
42139
  referenceCount,
41975
42140
  sourceOnlyCount,
42141
+ sourceOnlyReferences,
41976
42142
  findings
41977
42143
  };
41978
42144
  result.receiptDigest = digestDocument(receiptProjection(result));
41979
42145
  return result;
41980
42146
  }
41981
- var CHECKER_VERSION, BARE_PREFIXES, EXPLICIT_PREFIXES, SOURCE_TREE_PATTERN, MACHINE_ABSOLUTE_PATTERN, GLOB_PATTERN, SOURCE_ONLY_MARKER, TRANSPORT_EXCLUSIONS, CLASSIFICATION, FINDING_CODE;
42147
+ function evaluateDeclaredHostSurfaceCoverage(expectedHosts, surfaces) {
42148
+ const missing = [];
42149
+ for (const expectedHost of [...new Set(expectedHosts ?? [])].sort((a, b) => a.localeCompare(b))) {
42150
+ const surface = (surfaces ?? []).find((item) => item.host === expectedHost);
42151
+ if (!surface || !(surface.skillCount >= 1)) {
42152
+ missing.push({ host: expectedHost, skillCount: surface?.skillCount ?? 0 });
42153
+ }
42154
+ }
42155
+ return { passed: missing.length === 0, missing };
42156
+ }
42157
+ var CHECKER_VERSION, BARE_PREFIXES, EXPLICIT_PREFIXES, SOURCE_TREE_PATTERN, MACHINE_ABSOLUTE_PATTERN, HOME_DIRECTORY_PATTERN, ADAPTER_SURFACE_PATTERN, CLOSURE_RESOURCE_DIRS, GLOB_PATTERN, SOURCE_ONLY_MARKER, TRANSPORT_EXCLUSIONS, CLASSIFICATION, FINDING_CODE;
41982
42158
  var init_skill_resource_closure = __esm({
41983
42159
  "src/core/skill-resource-closure.mjs"() {
41984
42160
  init_src();
41985
42161
  init_errors();
41986
42162
  init_frozen();
41987
- CHECKER_VERSION = "skill-resource-closure-v1";
42163
+ CHECKER_VERSION = "skill-resource-closure-v2";
41988
42164
  BARE_PREFIXES = ["references/", "assets/", "schemas/", "examples/", "scripts/"];
41989
42165
  EXPLICIT_PREFIXES = [
41990
42166
  "<plugin-root>/",
@@ -41996,6 +42172,9 @@ var init_skill_resource_closure = __esm({
41996
42172
  ];
41997
42173
  SOURCE_TREE_PATTERN = /(?:^|\/)packages\/[A-Za-z0-9._-]+(?:\/|$)/u;
41998
42174
  MACHINE_ABSOLUTE_PATTERN = /^(?:\/(?:Users|home|root|tmp|var|etc|opt)(?:\/|$)|[A-Za-z]:[\\/])/u;
42175
+ HOME_DIRECTORY_PATTERN = /^(?:~|\$HOME|\$\{HOME\})\/.+/u;
42176
+ ADAPTER_SURFACE_PATTERN = /^adapters\/([^/]+)$/u;
42177
+ CLOSURE_RESOURCE_DIRS = Object.freeze(["references", "assets", "schemas", "examples", "scripts"]);
41999
42178
  GLOB_PATTERN = /[*?\[]/u;
42000
42179
  SOURCE_ONLY_MARKER = /(?:\bsource-only\b|仅源码包)/iu;
42001
42180
  TRANSPORT_EXCLUSIONS = Object.freeze([
@@ -42009,7 +42188,10 @@ var init_skill_resource_closure = __esm({
42009
42188
  PLUGIN_ROOT: "plugin_root",
42010
42189
  SOURCE_BACKJUMP: "source_backjump",
42011
42190
  MACHINE_ABSOLUTE: "machine_absolute",
42012
- OUT_OF_BOUNDS: "out_of_bounds"
42191
+ HOME_DIRECTORY: "home_directory",
42192
+ OUT_OF_BOUNDS: "out_of_bounds",
42193
+ RESOURCE_DRIFT: "resource_drift",
42194
+ STALE_RESOURCE: "stale_resource"
42013
42195
  });
42014
42196
  FINDING_CODE = Object.freeze({
42015
42197
  SNAPSHOT_UNSAFE: "SNAPSHOT_UNSAFE",
@@ -42017,8 +42199,11 @@ var init_skill_resource_closure = __esm({
42017
42199
  RESOURCE_NOT_REGULAR_FILE: "RESOURCE_NOT_REGULAR_FILE",
42018
42200
  SOURCE_BACKJUMP: "SOURCE_BACKJUMP",
42019
42201
  MACHINE_ABSOLUTE_PATH: "MACHINE_ABSOLUTE_PATH",
42202
+ HOME_DIRECTORY_SEARCH: "HOME_DIRECTORY_SEARCH",
42020
42203
  OUT_OF_BOUNDS: "OUT_OF_BOUNDS",
42021
- SYMLINK_NOT_ALLOWED: "SYMLINK_NOT_ALLOWED"
42204
+ SYMLINK_NOT_ALLOWED: "SYMLINK_NOT_ALLOWED",
42205
+ RESOURCE_DRIFT: "RESOURCE_DRIFT",
42206
+ STALE_RESOURCE: "STALE_RESOURCE"
42022
42207
  });
42023
42208
  __name(toPosix, "toPosix");
42024
42209
  __name(relativeStable, "relativeStable");
@@ -42033,12 +42218,14 @@ var init_skill_resource_closure = __esm({
42033
42218
  __name(stripExplicitPrefix, "stripExplicitPrefix");
42034
42219
  __name(classifyReference, "classifyReference");
42035
42220
  __name(inspectRegularFile, "inspectRegularFile");
42221
+ __name(collectRegularFiles, "collectRegularFiles");
42036
42222
  __name(inferSurfaceHost, "inferSurfaceHost");
42037
42223
  __name(receiptProjection, "receiptProjection");
42038
42224
  __name(createSkillResourceClosureReceipt, "createSkillResourceClosureReceipt");
42039
42225
  __name(assertSkillResourceClosureReceipt, "assertSkillResourceClosureReceipt");
42040
42226
  __name(evaluateConsumerSkillResourceClosureReceipts, "evaluateConsumerSkillResourceClosureReceipts");
42041
42227
  __name(checkSkillResourceClosure, "checkSkillResourceClosure");
42228
+ __name(evaluateDeclaredHostSurfaceCoverage, "evaluateDeclaredHostSurfaceCoverage");
42042
42229
  }
42043
42230
  });
42044
42231
 
@@ -43575,11 +43762,182 @@ var init_contract2 = __esm({
43575
43762
  }
43576
43763
  });
43577
43764
 
43765
+ // src/core/bundle-freshness.mjs
43766
+ import { readFile as readFile16, readdir as readdir11, stat as stat4 } from "node:fs/promises";
43767
+ import { join as join14 } from "node:path";
43768
+ import { createHash as createHash13 } from "node:crypto";
43769
+ function bundlePathFor(pkgRoot) {
43770
+ return join14(pkgRoot, BUNDLE_RELPATH);
43771
+ }
43772
+ async function listFilesSorted(dir, prefix = "") {
43773
+ const entries = await readdir11(dir, { withFileTypes: true });
43774
+ const files = [];
43775
+ for (const entry of entries.sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0)) {
43776
+ const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
43777
+ if (entry.isDirectory()) {
43778
+ files.push(...await listFilesSorted(join14(dir, entry.name), rel));
43779
+ } else if (entry.isFile()) {
43780
+ files.push(rel);
43781
+ }
43782
+ }
43783
+ return files;
43784
+ }
43785
+ async function listBundleSourceInputs(pkgRoot) {
43786
+ const inputs = [];
43787
+ for (const dir of SOURCE_DIRS) {
43788
+ const abs = join14(pkgRoot, dir);
43789
+ const st = await stat4(abs).catch(() => null);
43790
+ if (st?.isDirectory()) {
43791
+ for (const rel of await listFilesSorted(abs)) {
43792
+ inputs.push(`${dir}/${rel}`);
43793
+ }
43794
+ }
43795
+ }
43796
+ for (const rel of SOURCE_FILES) {
43797
+ const st = await stat4(join14(pkgRoot, rel)).catch(() => null);
43798
+ if (st?.isFile()) {
43799
+ inputs.push(rel.split(/[\\/]/).join("/"));
43800
+ }
43801
+ }
43802
+ return inputs.sort();
43803
+ }
43804
+ async function computeBundleSourceDigest(pkgRoot) {
43805
+ const inputs = await listBundleSourceInputs(pkgRoot);
43806
+ const hash = createHash13("sha256");
43807
+ hash.update(BUNDLE_SOURCE_DIGEST_ALGORITHM);
43808
+ hash.update("\n");
43809
+ for (const rel of inputs) {
43810
+ const content = await readFile16(join14(pkgRoot, rel));
43811
+ hash.update(rel);
43812
+ hash.update("\0");
43813
+ hash.update(createHash13("sha256").update(content).digest("hex"));
43814
+ hash.update("\n");
43815
+ }
43816
+ return hash.digest("hex");
43817
+ }
43818
+ async function readEmbeddedBundleDigest(bundlePath) {
43819
+ let content;
43820
+ try {
43821
+ content = await readFile16(bundlePath, "utf8");
43822
+ } catch {
43823
+ return null;
43824
+ }
43825
+ const match = content.match(EMBEDDED_DIGEST_PATTERN);
43826
+ return match ? match[1] : null;
43827
+ }
43828
+ async function checkBundleFreshness(pkgRoot) {
43829
+ const base = {
43830
+ applicable: true,
43831
+ fresh: false,
43832
+ embeddedDigest: null,
43833
+ sourceDigest: null,
43834
+ algorithm: BUNDLE_SOURCE_DIGEST_ALGORITHM
43835
+ };
43836
+ const srcStat = await stat4(join14(pkgRoot, "src")).catch(() => null);
43837
+ if (!srcStat?.isDirectory()) {
43838
+ return { ...base, applicable: false, reason: "installed-layout" };
43839
+ }
43840
+ const bundleStat = await stat4(bundlePathFor(pkgRoot)).catch(() => null);
43841
+ if (!bundleStat?.isFile()) {
43842
+ return { ...base, reason: "bundle-missing" };
43843
+ }
43844
+ const [embeddedDigest, sourceDigest] = await Promise.all([
43845
+ readEmbeddedBundleDigest(bundlePathFor(pkgRoot)),
43846
+ computeBundleSourceDigest(pkgRoot)
43847
+ ]);
43848
+ if (!embeddedDigest) {
43849
+ return { ...base, sourceDigest, reason: "digest-missing" };
43850
+ }
43851
+ if (embeddedDigest !== sourceDigest) {
43852
+ return { ...base, embeddedDigest, sourceDigest, reason: "digest-mismatch" };
43853
+ }
43854
+ return { ...base, fresh: true, embeddedDigest, sourceDigest, reason: "fresh" };
43855
+ }
43856
+ async function assertBundleFreshness(pkgRoot) {
43857
+ const result = await checkBundleFreshness(pkgRoot);
43858
+ if (!result.applicable) {
43859
+ return result;
43860
+ }
43861
+ if (result.fresh) {
43862
+ return result;
43863
+ }
43864
+ const reasonText = {
43865
+ "bundle-missing": "the bundle file is missing",
43866
+ "digest-missing": "the bundle carries no embedded source digest",
43867
+ "digest-mismatch": "the bundle is out of sync with src/"
43868
+ }[result.reason] ?? result.reason;
43869
+ throw new ReleaseError(
43870
+ BUNDLE_STALE,
43871
+ `bin/release-skill.bundle.mjs is stale: ${reasonText}. Rebuild it from the release-skill package root with: ${BUNDLE_REBUILD_COMMAND} (or pnpm build)`,
43872
+ {
43873
+ reason: result.reason,
43874
+ algorithm: result.algorithm,
43875
+ embeddedDigest: result.embeddedDigest,
43876
+ sourceDigest: result.sourceDigest,
43877
+ rebuildCommand: BUNDLE_REBUILD_COMMAND
43878
+ }
43879
+ );
43880
+ }
43881
+ var BUNDLE_SOURCE_DIGEST_ALGORITHM, BUNDLE_RELPATH, SOURCE_DIRS, SOURCE_FILES, EMBEDDED_DIGEST_PATTERN, BUNDLE_REBUILD_COMMAND;
43882
+ var init_bundle_freshness = __esm({
43883
+ "src/core/bundle-freshness.mjs"() {
43884
+ init_errors();
43885
+ BUNDLE_SOURCE_DIGEST_ALGORITHM = "bundle-source-digest-v1";
43886
+ BUNDLE_RELPATH = join14("bin", "release-skill.bundle.mjs");
43887
+ SOURCE_DIRS = ["src", "skills-src"];
43888
+ SOURCE_FILES = [join14("bin", "release-skill-cli.mjs"), "package.json"];
43889
+ EMBEDDED_DIGEST_PATTERN = /const __bundleSourceDigest = "([a-f0-9]{64})";/;
43890
+ __name(bundlePathFor, "bundlePathFor");
43891
+ __name(listFilesSorted, "listFilesSorted");
43892
+ __name(listBundleSourceInputs, "listBundleSourceInputs");
43893
+ __name(computeBundleSourceDigest, "computeBundleSourceDigest");
43894
+ __name(readEmbeddedBundleDigest, "readEmbeddedBundleDigest");
43895
+ __name(checkBundleFreshness, "checkBundleFreshness");
43896
+ BUNDLE_REBUILD_COMMAND = "node scripts/build-bundle.mjs";
43897
+ __name(assertBundleFreshness, "assertBundleFreshness");
43898
+ }
43899
+ });
43900
+
43901
+ // src/core/frozen-marker.mjs
43902
+ import { readFile as readFile17, writeFile as writeFile6, unlink as unlink5 } from "node:fs/promises";
43903
+ import { join as join15 } from "node:path";
43904
+ function frozenMarkerPath(releaseDir) {
43905
+ return join15(releaseDir, FROZEN_MARKER_FILENAME);
43906
+ }
43907
+ async function writeFrozenMarker(releaseDir, marker) {
43908
+ const payload = {
43909
+ planDigest: marker.planDigest,
43910
+ targetVersions: marker.targetVersions,
43911
+ createdAt: marker.createdAt,
43912
+ runId: marker.runId
43913
+ };
43914
+ const markerPath = frozenMarkerPath(releaseDir);
43915
+ await writeFile6(markerPath, JSON.stringify(payload, null, 2) + "\n", "utf8");
43916
+ return markerPath;
43917
+ }
43918
+ async function clearFrozenMarker(releaseDir) {
43919
+ try {
43920
+ await unlink5(frozenMarkerPath(releaseDir));
43921
+ return true;
43922
+ } catch {
43923
+ return false;
43924
+ }
43925
+ }
43926
+ var FROZEN_MARKER_FILENAME;
43927
+ var init_frozen_marker = __esm({
43928
+ "src/core/frozen-marker.mjs"() {
43929
+ FROZEN_MARKER_FILENAME = "FROZEN";
43930
+ __name(frozenMarkerPath, "frozenMarkerPath");
43931
+ __name(writeFrozenMarker, "writeFrozenMarker");
43932
+ __name(clearFrozenMarker, "clearFrozenMarker");
43933
+ }
43934
+ });
43935
+
43578
43936
  // src/core/source-authority.mjs
43579
43937
  import { execFile as execFileCb6 } from "node:child_process";
43580
43938
  import { promisify as promisify6 } from "node:util";
43581
- import { lstat as lstat17, mkdtemp as mkdtemp5, readFile as readFile16, readdir as readdir11, realpath as realpath14, rm as rm7 } from "node:fs/promises";
43582
- import { join as join14, relative as relative16, resolve as resolve18, sep as sep5 } from "node:path";
43939
+ import { lstat as lstat17, mkdtemp as mkdtemp5, readFile as readFile18, readdir as readdir12, realpath as realpath14, rm as rm7 } from "node:fs/promises";
43940
+ import { join as join16, relative as relative16, resolve as resolve18, sep as sep5 } from "node:path";
43583
43941
  import { tmpdir as tmpdir3 } from "node:os";
43584
43942
  async function computeSourceInputClosure({ units, root }) {
43585
43943
  const realRoot = await realpath14(resolve18(root));
@@ -43619,9 +43977,9 @@ function computeEntriesDigest(entries) {
43619
43977
  }))));
43620
43978
  }
43621
43979
  async function collectPath({ absolutePath, root, entriesByPath }) {
43622
- let stat9;
43980
+ let stat10;
43623
43981
  try {
43624
- stat9 = await lstat17(absolutePath);
43982
+ stat10 = await lstat17(absolutePath);
43625
43983
  } catch (error) {
43626
43984
  throw new ReleaseError(
43627
43985
  CONFIG_INVALID,
@@ -43630,7 +43988,7 @@ async function collectPath({ absolutePath, root, entriesByPath }) {
43630
43988
  );
43631
43989
  }
43632
43990
  const rel = toRelative(root, absolutePath);
43633
- if (stat9.isSymbolicLink()) {
43991
+ if (stat10.isSymbolicLink()) {
43634
43992
  throw new ReleaseError(
43635
43993
  CONFIG_INVALID,
43636
43994
  `source-input closure rejects symlink "${rel}"`,
@@ -43645,30 +44003,30 @@ async function collectPath({ absolutePath, root, entriesByPath }) {
43645
44003
  { path: rel }
43646
44004
  );
43647
44005
  }
43648
- if (stat9.isDirectory()) {
43649
- const children = await readdir11(absolutePath, { withFileTypes: true });
44006
+ if (stat10.isDirectory()) {
44007
+ const children = await readdir12(absolutePath, { withFileTypes: true });
43650
44008
  children.sort((left, right) => left.name.localeCompare(right.name));
43651
44009
  for (const child of children) {
43652
44010
  await collectPath({
43653
- absolutePath: join14(absolutePath, child.name),
44011
+ absolutePath: join16(absolutePath, child.name),
43654
44012
  root,
43655
44013
  entriesByPath
43656
44014
  });
43657
44015
  }
43658
44016
  return;
43659
44017
  }
43660
- if (!stat9.isFile()) {
44018
+ if (!stat10.isFile()) {
43661
44019
  throw new ReleaseError(
43662
44020
  CONFIG_INVALID,
43663
44021
  `source-input closure rejects non-regular file "${rel}"`,
43664
44022
  { path: rel }
43665
44023
  );
43666
44024
  }
43667
- const content = await readFile16(absolutePath);
44025
+ const content = await readFile18(absolutePath);
43668
44026
  entriesByPath.set(rel, {
43669
44027
  path: rel,
43670
44028
  digest: sha256Hex(content),
43671
- mode: normalizeLocalGitMode(stat9.mode)
44029
+ mode: normalizeLocalGitMode(stat10.mode)
43672
44030
  });
43673
44031
  }
43674
44032
  function resolveInside(base, candidate, containmentRoot = base) {
@@ -43894,7 +44252,7 @@ async function verifyWithTemporaryGit({
43894
44252
  if (!branchLine) {
43895
44253
  return failure(REF_MISSING, `remote ref "refs/heads/${defaultBranch}" does not exist`);
43896
44254
  }
43897
- const tempRoot = await mkdtemp5(join14(tmpdir3(), "release-skill-source-authority-"));
44255
+ const tempRoot = await mkdtemp5(join16(tmpdir3(), "release-skill-source-authority-"));
43898
44256
  try {
43899
44257
  await execFn("git", ["init", "--bare", tempRoot], {
43900
44258
  encoding: "utf8",
@@ -55969,17 +56327,17 @@ var require_polyfill = __commonJS({
55969
56327
  copyFile,
55970
56328
  lstat: lstat27,
55971
56329
  mkdir: mkdir24,
55972
- readdir: readdir20,
56330
+ readdir: readdir21,
55973
56331
  readlink: readlink2,
55974
- stat: stat9,
56332
+ stat: stat10,
55975
56333
  symlink,
55976
- unlink: unlink5,
56334
+ unlink: unlink6,
55977
56335
  utimes
55978
56336
  } = __require("fs/promises");
55979
56337
  var {
55980
56338
  dirname: dirname18,
55981
56339
  isAbsolute: isAbsolute23,
55982
- join: join32,
56340
+ join: join34,
55983
56341
  parse: parse2,
55984
56342
  resolve: resolve35,
55985
56343
  sep: sep7,
@@ -56068,7 +56426,7 @@ var require_polyfill = __commonJS({
56068
56426
  }
56069
56427
  __name(areIdentical, "areIdentical");
56070
56428
  function getStats(src, dest, opts) {
56071
- const statFunc = opts.dereference ? (file) => stat9(file, { bigint: true }) : (file) => lstat27(file, { bigint: true });
56429
+ const statFunc = opts.dereference ? (file) => stat10(file, { bigint: true }) : (file) => lstat27(file, { bigint: true });
56072
56430
  return Promise.all([
56073
56431
  statFunc(src),
56074
56432
  statFunc(dest).catch((err) => {
@@ -56091,7 +56449,7 @@ var require_polyfill = __commonJS({
56091
56449
  }
56092
56450
  __name(checkParentDir, "checkParentDir");
56093
56451
  function pathExists2(dest) {
56094
- return stat9(dest).then(
56452
+ return stat10(dest).then(
56095
56453
  () => true,
56096
56454
  // istanbul ignore next: not sure when this would occur
56097
56455
  (err) => err.code === "ENOENT" ? false : Promise.reject(err)
@@ -56106,7 +56464,7 @@ var require_polyfill = __commonJS({
56106
56464
  }
56107
56465
  let destStat;
56108
56466
  try {
56109
- destStat = await stat9(destParent, { bigint: true });
56467
+ destStat = await stat10(destParent, { bigint: true });
56110
56468
  } catch (err) {
56111
56469
  if (err.code === "ENOENT") {
56112
56470
  return;
@@ -56146,7 +56504,7 @@ var require_polyfill = __commonJS({
56146
56504
  }
56147
56505
  __name(startCopy, "startCopy");
56148
56506
  async function getStatsForCopy(destStat, src, dest, opts) {
56149
- const statFn = opts.dereference ? stat9 : lstat27;
56507
+ const statFn = opts.dereference ? stat10 : lstat27;
56150
56508
  const srcStat = await statFn(src);
56151
56509
  if (srcStat.isDirectory() && opts.recursive) {
56152
56510
  return onDir(srcStat, destStat, src, dest, opts);
@@ -56193,7 +56551,7 @@ var require_polyfill = __commonJS({
56193
56551
  __name(onFile, "onFile");
56194
56552
  async function mayCopyFile(srcStat, src, dest, opts) {
56195
56553
  if (opts.force) {
56196
- await unlink5(dest);
56554
+ await unlink6(dest);
56197
56555
  return _copyFile(srcStat, src, dest, opts);
56198
56556
  } else if (opts.errorOnExist) {
56199
56557
  throw new ERR_FS_CP_EEXIST({
@@ -56239,7 +56597,7 @@ var require_polyfill = __commonJS({
56239
56597
  }
56240
56598
  __name(setDestMode, "setDestMode");
56241
56599
  async function setDestTimestamps(src, dest) {
56242
- const updatedSrcStat = await stat9(src);
56600
+ const updatedSrcStat = await stat10(src);
56243
56601
  return utimes(dest, updatedSrcStat.atime, updatedSrcStat.mtime);
56244
56602
  }
56245
56603
  __name(setDestTimestamps, "setDestTimestamps");
@@ -56257,11 +56615,11 @@ var require_polyfill = __commonJS({
56257
56615
  }
56258
56616
  __name(mkDirAndCopy, "mkDirAndCopy");
56259
56617
  async function copyDir(src, dest, opts) {
56260
- const dir = await readdir20(src);
56618
+ const dir = await readdir21(src);
56261
56619
  for (let i = 0; i < dir.length; i++) {
56262
56620
  const item = dir[i];
56263
- const srcItem = join32(src, item);
56264
- const destItem = join32(dest, item);
56621
+ const srcItem = join34(src, item);
56622
+ const destItem = join34(dest, item);
56265
56623
  const { destStat } = await checkPaths(srcItem, destItem, opts);
56266
56624
  await startCopy(destStat, srcItem, destItem, opts);
56267
56625
  }
@@ -56295,7 +56653,7 @@ var require_polyfill = __commonJS({
56295
56653
  errno: EINVAL
56296
56654
  });
56297
56655
  }
56298
- const srcStat = await stat9(src);
56656
+ const srcStat = await stat10(src);
56299
56657
  if (srcStat.isDirectory() && isSrcSubdir(resolvedDest, resolvedSrc)) {
56300
56658
  throw new ERR_FS_CP_SYMLINK_TO_SUBDIRECTORY({
56301
56659
  message: `cannot overwrite ${resolvedDest} with ${resolvedSrc}`,
@@ -56308,7 +56666,7 @@ var require_polyfill = __commonJS({
56308
56666
  }
56309
56667
  __name(onLink, "onLink");
56310
56668
  async function copyLink(resolvedSrc, dest) {
56311
- await unlink5(dest);
56669
+ await unlink6(dest);
56312
56670
  return symlink(resolvedSrc, dest);
56313
56671
  }
56314
56672
  __name(copyLink, "copyLink");
@@ -56337,7 +56695,7 @@ var require_cp = __commonJS({
56337
56695
  // ../../node_modules/.pnpm/@npmcli+fs@4.0.0/node_modules/@npmcli/fs/lib/with-temp-dir.js
56338
56696
  var require_with_temp_dir = __commonJS({
56339
56697
  "../../node_modules/.pnpm/@npmcli+fs@4.0.0/node_modules/@npmcli/fs/lib/with-temp-dir.js"(exports, module) {
56340
- var { join: join32, sep: sep7 } = __require("path");
56698
+ var { join: join34, sep: sep7 } = __require("path");
56341
56699
  var getOptions = require_get_options();
56342
56700
  var { mkdir: mkdir24, mkdtemp: mkdtemp10, rm: rm15 } = __require("fs/promises");
56343
56701
  var withTempDir = /* @__PURE__ */ __name(async (root, fn, opts) => {
@@ -56345,7 +56703,7 @@ var require_with_temp_dir = __commonJS({
56345
56703
  copy: ["tmpPrefix"]
56346
56704
  });
56347
56705
  await mkdir24(root, { recursive: true });
56348
- const target = await mkdtemp10(join32(`${root}${sep7}`, options.tmpPrefix || ""));
56706
+ const target = await mkdtemp10(join34(`${root}${sep7}`, options.tmpPrefix || ""));
56349
56707
  let err;
56350
56708
  let result;
56351
56709
  try {
@@ -56369,14 +56727,14 @@ var require_with_temp_dir = __commonJS({
56369
56727
  // ../../node_modules/.pnpm/@npmcli+fs@4.0.0/node_modules/@npmcli/fs/lib/readdir-scoped.js
56370
56728
  var require_readdir_scoped = __commonJS({
56371
56729
  "../../node_modules/.pnpm/@npmcli+fs@4.0.0/node_modules/@npmcli/fs/lib/readdir-scoped.js"(exports, module) {
56372
- var { readdir: readdir20 } = __require("fs/promises");
56373
- var { join: join32 } = __require("path");
56730
+ var { readdir: readdir21 } = __require("fs/promises");
56731
+ var { join: join34 } = __require("path");
56374
56732
  var readdirScoped = /* @__PURE__ */ __name(async (dir) => {
56375
56733
  const results = [];
56376
- for (const item of await readdir20(dir)) {
56734
+ for (const item of await readdir21(dir)) {
56377
56735
  if (item.startsWith("@")) {
56378
- for (const scopedItem of await readdir20(join32(dir, item))) {
56379
- results.push(join32(item, scopedItem));
56736
+ for (const scopedItem of await readdir21(join34(dir, item))) {
56737
+ results.push(join34(item, scopedItem));
56380
56738
  }
56381
56739
  } else {
56382
56740
  results.push(item);
@@ -56391,7 +56749,7 @@ var require_readdir_scoped = __commonJS({
56391
56749
  // ../../node_modules/.pnpm/@npmcli+fs@4.0.0/node_modules/@npmcli/fs/lib/move-file.js
56392
56750
  var require_move_file = __commonJS({
56393
56751
  "../../node_modules/.pnpm/@npmcli+fs@4.0.0/node_modules/@npmcli/fs/lib/move-file.js"(exports, module) {
56394
- var { dirname: dirname18, join: join32, resolve: resolve35, relative: relative27, isAbsolute: isAbsolute23 } = __require("path");
56752
+ var { dirname: dirname18, join: join34, resolve: resolve35, relative: relative27, isAbsolute: isAbsolute23 } = __require("path");
56395
56753
  var fs = __require("fs/promises");
56396
56754
  var pathExists2 = /* @__PURE__ */ __name(async (path15) => {
56397
56755
  try {
@@ -56421,7 +56779,7 @@ var require_move_file = __commonJS({
56421
56779
  if (sourceStat.isDirectory()) {
56422
56780
  const files = await fs.readdir(source);
56423
56781
  await Promise.all(files.map(
56424
- (file) => moveFile(join32(source, file), join32(destination, file), options, false, symlinks)
56782
+ (file) => moveFile(join34(source, file), join34(destination, file), options, false, symlinks)
56425
56783
  ));
56426
56784
  } else if (sourceStat.isSymbolicLink()) {
56427
56785
  symlinks.push({ source, destination });
@@ -56695,10 +57053,10 @@ var require_entry_index = __commonJS({
56695
57053
  var {
56696
57054
  appendFile,
56697
57055
  mkdir: mkdir24,
56698
- readFile: readFile40,
56699
- readdir: readdir20,
57056
+ readFile: readFile42,
57057
+ readdir: readdir21,
56700
57058
  rm: rm15,
56701
- writeFile: writeFile13
57059
+ writeFile: writeFile14
56702
57060
  } = __require("fs/promises");
56703
57061
  var { Minipass } = require_commonjs();
56704
57062
  var path15 = __require("path");
@@ -56753,7 +57111,7 @@ var require_entry_index = __commonJS({
56753
57111
  }
56754
57112
  }, "teardown");
56755
57113
  const write = /* @__PURE__ */ __name(async (tmp2) => {
56756
- await writeFile13(tmp2.target, newIndex, { flag: "wx" });
57114
+ await writeFile14(tmp2.target, newIndex, { flag: "wx" });
56757
57115
  await mkdir24(path15.dirname(bucket), { recursive: true });
56758
57116
  await moveFile(tmp2.target, bucket);
56759
57117
  tmp2.moved = true;
@@ -56887,7 +57245,7 @@ ${hashEntry(stringified)} ${stringified}`);
56887
57245
  __name(ls, "ls");
56888
57246
  module.exports.bucketEntries = bucketEntries;
56889
57247
  async function bucketEntries(bucket, filter) {
56890
- const data = await readFile40(bucket, "utf8");
57248
+ const data = await readFile42(bucket, "utf8");
56891
57249
  return _bucketEntries(data, filter);
56892
57250
  }
56893
57251
  __name(bucketEntries, "bucketEntries");
@@ -56956,7 +57314,7 @@ ${hashEntry(stringified)} ${stringified}`);
56956
57314
  }
56957
57315
  __name(formatEntry, "formatEntry");
56958
57316
  function readdirOrEmpty(dir) {
56959
- return readdir20(dir).catch((err) => {
57317
+ return readdir21(dir).catch((err) => {
56960
57318
  if (err.code === "ENOENT" || err.code === "ENOTDIR") {
56961
57319
  return [];
56962
57320
  }
@@ -57452,16 +57810,16 @@ var require_read2 = __commonJS({
57452
57810
  var MAX_SINGLE_READ_SIZE = 64 * 1024 * 1024;
57453
57811
  async function read(cache, integrity, opts = {}) {
57454
57812
  const { size } = opts;
57455
- const { stat: stat9, cpath, sri } = await withContentSri(cache, integrity, async (cpath2, sri2) => {
57456
- const stat10 = size ? { size } : await fs.stat(cpath2);
57457
- return { stat: stat10, cpath: cpath2, sri: sri2 };
57813
+ const { stat: stat10, cpath, sri } = await withContentSri(cache, integrity, async (cpath2, sri2) => {
57814
+ const stat11 = size ? { size } : await fs.stat(cpath2);
57815
+ return { stat: stat11, cpath: cpath2, sri: sri2 };
57458
57816
  });
57459
- if (stat9.size > MAX_SINGLE_READ_SIZE) {
57460
- return readPipeline(cpath, stat9.size, sri, new Pipeline()).concat();
57817
+ if (stat10.size > MAX_SINGLE_READ_SIZE) {
57818
+ return readPipeline(cpath, stat10.size, sri, new Pipeline()).concat();
57461
57819
  }
57462
57820
  const data = await fs.readFile(cpath, { encoding: null });
57463
- if (stat9.size !== data.length) {
57464
- throw sizeError(stat9.size, data.length);
57821
+ if (stat10.size !== data.length) {
57822
+ throw sizeError(stat10.size, data.length);
57465
57823
  }
57466
57824
  if (!ssri.checkData(data, sri)) {
57467
57825
  throw integrityError(sri, cpath);
@@ -57488,11 +57846,11 @@ var require_read2 = __commonJS({
57488
57846
  const { size } = opts;
57489
57847
  const stream = new Pipeline();
57490
57848
  Promise.resolve().then(async () => {
57491
- const { stat: stat9, cpath, sri } = await withContentSri(cache, integrity, async (cpath2, sri2) => {
57492
- const stat10 = size ? { size } : await fs.stat(cpath2);
57493
- return { stat: stat10, cpath: cpath2, sri: sri2 };
57849
+ const { stat: stat10, cpath, sri } = await withContentSri(cache, integrity, async (cpath2, sri2) => {
57850
+ const stat11 = size ? { size } : await fs.stat(cpath2);
57851
+ return { stat: stat11, cpath: cpath2, sri: sri2 };
57494
57852
  });
57495
- return readPipeline(cpath, stat9.size, sri, stream);
57853
+ return readPipeline(cpath, stat10.size, sri, stream);
57496
57854
  }).catch((err) => stream.emit("error", err));
57497
57855
  return stream;
57498
57856
  }
@@ -57511,8 +57869,8 @@ var require_read2 = __commonJS({
57511
57869
  }
57512
57870
  try {
57513
57871
  return await withContentSri(cache, integrity, async (cpath, sri) => {
57514
- const stat9 = await fs.stat(cpath);
57515
- return { size: stat9.size, sri, stat: stat9 };
57872
+ const stat10 = await fs.stat(cpath);
57873
+ return { size: stat10.size, sri, stat: stat10 };
57516
57874
  });
57517
57875
  } catch (err) {
57518
57876
  if (err.code === "ENOENT") {
@@ -62907,11 +63265,11 @@ var require_verify = __commonJS({
62907
63265
  "use strict";
62908
63266
  var {
62909
63267
  mkdir: mkdir24,
62910
- readFile: readFile40,
63268
+ readFile: readFile42,
62911
63269
  rm: rm15,
62912
- stat: stat9,
63270
+ stat: stat10,
62913
63271
  truncate,
62914
- writeFile: writeFile13
63272
+ writeFile: writeFile14
62915
63273
  } = __require("fs/promises");
62916
63274
  var contentPath = require_path();
62917
63275
  var fsm = require_lib29();
@@ -63029,7 +63387,7 @@ var require_verify = __commonJS({
63029
63387
  }
63030
63388
  } else {
63031
63389
  stats.reclaimedCount++;
63032
- const s = await stat9(f);
63390
+ const s = await stat10(f);
63033
63391
  await rm15(f, { recursive: true, force: true });
63034
63392
  stats.reclaimedSize += s.size;
63035
63393
  }
@@ -63043,7 +63401,7 @@ var require_verify = __commonJS({
63043
63401
  async function verifyContent(filepath, sri) {
63044
63402
  const contentInfo = {};
63045
63403
  try {
63046
- const { size } = await stat9(filepath);
63404
+ const { size } = await stat10(filepath);
63047
63405
  contentInfo.size = size;
63048
63406
  contentInfo.valid = true;
63049
63407
  await ssri.checkStream(new fsm.ReadStream(filepath), sri);
@@ -63103,7 +63461,7 @@ var require_verify = __commonJS({
63103
63461
  for (const entry of bucket) {
63104
63462
  const content = contentPath(cache, entry.integrity);
63105
63463
  try {
63106
- await stat9(content);
63464
+ await stat10(content);
63107
63465
  await index.insert(cache, entry.key, entry.integrity, {
63108
63466
  metadata: entry.metadata,
63109
63467
  size: entry.size,
@@ -63129,12 +63487,12 @@ var require_verify = __commonJS({
63129
63487
  async function writeVerifile(cache, opts) {
63130
63488
  const verifile = path15.join(cache, "_lastverified");
63131
63489
  opts.log.silly("verify", "writing verifile to " + verifile);
63132
- return writeFile13(verifile, `${Date.now()}`);
63490
+ return writeFile14(verifile, `${Date.now()}`);
63133
63491
  }
63134
63492
  __name(writeVerifile, "writeVerifile");
63135
63493
  module.exports.lastRun = lastRun;
63136
63494
  async function lastRun(cache) {
63137
- const data = await readFile40(path15.join(cache, "_lastverified"), { encoding: "utf8" });
63495
+ const data = await readFile42(path15.join(cache, "_lastverified"), { encoding: "utf8" });
63138
63496
  return /* @__PURE__ */ new Date(+data);
63139
63497
  }
63140
63498
  __name(lastRun, "lastRun");
@@ -71674,7 +72032,7 @@ var require_index_min = __commonJS({
71674
72032
  var require_lib35 = __commonJS({
71675
72033
  "../../node_modules/.pnpm/which@5.0.0/node_modules/which/lib/index.js"(exports, module) {
71676
72034
  var { isexe, sync: isexeSync } = require_index_min();
71677
- var { join: join32, delimiter, sep: sep7, posix: posix3 } = __require("path");
72035
+ var { join: join34, delimiter, sep: sep7, posix: posix3 } = __require("path");
71678
72036
  var isWindows = process.platform === "win32";
71679
72037
  var rSlash = new RegExp(`[${posix3.sep}${sep7 === posix3.sep ? "" : sep7}]`.replace(/(\\)/g, "\\$1"));
71680
72038
  var rRel = new RegExp(`^\\.${rSlash.source}`);
@@ -71703,7 +72061,7 @@ var require_lib35 = __commonJS({
71703
72061
  var getPathPart = /* @__PURE__ */ __name((raw, cmd) => {
71704
72062
  const pathPart = /^".*"$/.test(raw) ? raw.slice(1, -1) : raw;
71705
72063
  const prefix = !pathPart && rRel.test(cmd) ? cmd.slice(0, 2) : "";
71706
- return prefix + join32(pathPart, cmd);
72064
+ return prefix + join34(pathPart, cmd);
71707
72065
  }, "getPathPart");
71708
72066
  var which = /* @__PURE__ */ __name(async (cmd, opt = {}) => {
71709
72067
  const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
@@ -71818,7 +72176,7 @@ var require_escape3 = __commonJS({
71818
72176
  var require_lib36 = __commonJS({
71819
72177
  "../../node_modules/.pnpm/@npmcli+promise-spawn@8.0.3/node_modules/@npmcli/promise-spawn/lib/index.js"(exports, module) {
71820
72178
  "use strict";
71821
- var { spawn: spawn4 } = __require("child_process");
72179
+ var { spawn: spawn5 } = __require("child_process");
71822
72180
  var os4 = __require("os");
71823
72181
  var which = require_lib35();
71824
72182
  var escape2 = require_escape3();
@@ -71845,7 +72203,7 @@ var require_lib36 = __commonJS({
71845
72203
  const resultError = getResult(erOpts);
71846
72204
  reject(Object.assign(er, resultError));
71847
72205
  }, "rejectWithOpts");
71848
- const proc = spawn4(cmd, args2, opts);
72206
+ const proc = spawn5(cmd, args2, opts);
71849
72207
  promise.stdin = proc.stdin;
71850
72208
  promise.process = proc;
71851
72209
  proc.on("error", rejectWithOpts);
@@ -72351,7 +72709,7 @@ var require_which3 = __commonJS({
72351
72709
  // ../../node_modules/.pnpm/@npmcli+git@6.0.3/node_modules/@npmcli/git/lib/spawn.js
72352
72710
  var require_spawn = __commonJS({
72353
72711
  "../../node_modules/.pnpm/@npmcli+git@6.0.3/node_modules/@npmcli/git/lib/spawn.js"(exports, module) {
72354
- var spawn4 = require_lib36();
72712
+ var spawn5 = require_lib36();
72355
72713
  var promiseRetry = require_promise_retry();
72356
72714
  var { log } = require_lib21();
72357
72715
  var makeError = require_make_error();
@@ -72376,7 +72734,7 @@ var require_spawn = __commonJS({
72376
72734
  if (number !== 1) {
72377
72735
  log.silly("git", `Retrying git command: ${args2.join(" ")} attempt # ${number}`);
72378
72736
  }
72379
- return spawn4(gitPath, args2, makeOpts(opts)).catch((er) => {
72737
+ return spawn5(gitPath, args2, makeOpts(opts)).catch((er) => {
72380
72738
  const gitError = makeError(er);
72381
72739
  if (!gitError.shouldRetry(number)) {
72382
72740
  throw gitError;
@@ -72500,7 +72858,7 @@ var require_lines_to_revs = __commonJS({
72500
72858
  // ../../node_modules/.pnpm/@npmcli+git@6.0.3/node_modules/@npmcli/git/lib/revs.js
72501
72859
  var require_revs = __commonJS({
72502
72860
  "../../node_modules/.pnpm/@npmcli+git@6.0.3/node_modules/@npmcli/git/lib/revs.js"(exports, module) {
72503
- var spawn4 = require_spawn();
72861
+ var spawn5 = require_spawn();
72504
72862
  var { LRUCache } = require_commonjs3();
72505
72863
  var linesToRevs = require_lines_to_revs();
72506
72864
  var revsCache = new LRUCache({
@@ -72514,7 +72872,7 @@ var require_revs = __commonJS({
72514
72872
  return cached;
72515
72873
  }
72516
72874
  }
72517
- const { stdout } = await spawn4(["ls-remote", repo], opts);
72875
+ const { stdout } = await spawn5(["ls-remote", repo], opts);
72518
72876
  const revs = linesToRevs(stdout.trim().split("\n"));
72519
72877
  revsCache.set(repo, revs);
72520
72878
  return revs;
@@ -72842,7 +73200,7 @@ var require_lib37 = __commonJS({
72842
73200
  // ../../node_modules/.pnpm/npm-normalize-package-bin@4.0.0/node_modules/npm-normalize-package-bin/lib/index.js
72843
73201
  var require_lib38 = __commonJS({
72844
73202
  "../../node_modules/.pnpm/npm-normalize-package-bin@4.0.0/node_modules/npm-normalize-package-bin/lib/index.js"(exports, module) {
72845
- var { join: join32, basename: basename12 } = __require("path");
73203
+ var { join: join34, basename: basename13 } = __require("path");
72846
73204
  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");
72847
73205
  var normalizeString = /* @__PURE__ */ __name((pkg) => {
72848
73206
  if (!pkg.name) {
@@ -72853,7 +73211,7 @@ var require_lib38 = __commonJS({
72853
73211
  }, "normalizeString");
72854
73212
  var normalizeArray = /* @__PURE__ */ __name((pkg) => {
72855
73213
  pkg.bin = pkg.bin.reduce((acc, k) => {
72856
- acc[basename12(k)] = k;
73214
+ acc[basename13(k)] = k;
72857
73215
  return acc;
72858
73216
  }, {});
72859
73217
  return normalizeObject(pkg);
@@ -72867,11 +73225,11 @@ var require_lib38 = __commonJS({
72867
73225
  const clean = {};
72868
73226
  let hasBins = false;
72869
73227
  Object.keys(orig).forEach((binKey) => {
72870
- const base = join32("/", basename12(binKey.replace(/\\|:/g, "/"))).slice(1);
73228
+ const base = join34("/", basename13(binKey.replace(/\\|:/g, "/"))).slice(1);
72871
73229
  if (typeof orig[binKey] !== "string" || !base) {
72872
73230
  return;
72873
73231
  }
72874
- const binTarget = join32("/", orig[binKey].replace(/\\/g, "/")).replace(/\\/g, "/").slice(1);
73232
+ const binTarget = join34("/", orig[binKey].replace(/\\/g, "/")).replace(/\\/g, "/").slice(1);
72875
73233
  if (!binTarget) {
72876
73234
  return;
72877
73235
  }
@@ -73058,7 +73416,7 @@ var require_clone2 = __commonJS({
73058
73416
  var { parse: parse2 } = __require("url");
73059
73417
  var path15 = __require("path");
73060
73418
  var getRevs = require_revs();
73061
- var spawn4 = require_spawn();
73419
+ var spawn5 = require_spawn();
73062
73420
  var { isWindows } = require_utils4();
73063
73421
  var pickManifest = require_lib39();
73064
73422
  var fs = __require("fs/promises");
@@ -73112,7 +73470,7 @@ var require_clone2 = __commonJS({
73112
73470
  var other = /* @__PURE__ */ __name((repo, revDoc, target, opts) => {
73113
73471
  const shallow = maybeShallow(repo, opts);
73114
73472
  const fetchOrigin = ["fetch", "origin", revDoc.rawRef].concat(shallow ? ["--depth=1"] : []);
73115
- const git3 = /* @__PURE__ */ __name((args2) => spawn4(args2, { ...opts, cwd: target }), "git");
73473
+ const git3 = /* @__PURE__ */ __name((args2) => spawn5(args2, { ...opts, cwd: target }), "git");
73116
73474
  return fs.mkdir(target, { recursive: true }).then(() => git3(["init"])).then(() => isWindows(opts) ? git3(["config", "--local", "--add", "core.longpaths", "true"]) : null).then(() => git3(["remote", "add", "origin", repo])).then(() => git3(fetchOrigin)).then(() => git3(["checkout", revDoc.sha])).then(() => updateSubmodules(target, opts)).then(() => revDoc.sha);
73117
73475
  }, "other");
73118
73476
  var branch = /* @__PURE__ */ __name((repo, revDoc, target, opts) => {
@@ -73130,7 +73488,7 @@ var require_clone2 = __commonJS({
73130
73488
  if (isWindows(opts)) {
73131
73489
  args2.push("--config", "core.longpaths=true");
73132
73490
  }
73133
- return spawn4(args2, opts).then(() => revDoc.sha);
73491
+ return spawn5(args2, opts).then(() => revDoc.sha);
73134
73492
  }, "branch");
73135
73493
  var plain = /* @__PURE__ */ __name((repo, revDoc, target, opts) => {
73136
73494
  const args2 = [
@@ -73145,14 +73503,14 @@ var require_clone2 = __commonJS({
73145
73503
  if (isWindows(opts)) {
73146
73504
  args2.push("--config", "core.longpaths=true");
73147
73505
  }
73148
- return spawn4(args2, opts).then(() => revDoc.sha);
73506
+ return spawn5(args2, opts).then(() => revDoc.sha);
73149
73507
  }, "plain");
73150
73508
  var updateSubmodules = /* @__PURE__ */ __name(async (target, opts) => {
73151
73509
  const hasSubmodules = await fs.stat(`${target}/.gitmodules`).then(() => true).catch(() => false);
73152
73510
  if (!hasSubmodules) {
73153
73511
  return null;
73154
73512
  }
73155
- return spawn4([
73513
+ return spawn5([
73156
73514
  "submodule",
73157
73515
  "update",
73158
73516
  "-q",
@@ -73163,7 +73521,7 @@ var require_clone2 = __commonJS({
73163
73521
  var unresolved = /* @__PURE__ */ __name((repo, ref, target, opts) => {
73164
73522
  const lp = isWindows(opts) ? ["--config", "core.longpaths=true"] : [];
73165
73523
  const cloneArgs = ["clone", "--mirror", "-q", repo, target + "/.git"];
73166
- const git3 = /* @__PURE__ */ __name((args2) => spawn4(args2, { ...opts, cwd: target }), "git");
73524
+ const git3 = /* @__PURE__ */ __name((args2) => spawn5(args2, { ...opts, cwd: target }), "git");
73167
73525
  return fs.mkdir(target, { recursive: true }).then(() => git3(cloneArgs.concat(lp))).then(() => git3(["init"])).then(() => git3(["checkout", ref])).then(() => updateSubmodules(target, opts)).then(() => git3(["rev-parse", "--revs-only", "HEAD"])).then(({ stdout }) => stdout.trim());
73168
73526
  }, "unresolved");
73169
73527
  }
@@ -73172,8 +73530,8 @@ var require_clone2 = __commonJS({
73172
73530
  // ../../node_modules/.pnpm/@npmcli+git@6.0.3/node_modules/@npmcli/git/lib/is.js
73173
73531
  var require_is = __commonJS({
73174
73532
  "../../node_modules/.pnpm/@npmcli+git@6.0.3/node_modules/@npmcli/git/lib/is.js"(exports, module) {
73175
- var { stat: stat9 } = __require("fs/promises");
73176
- module.exports = ({ cwd = process.cwd() } = {}) => stat9(cwd + "/.git").then(() => true, () => false);
73533
+ var { stat: stat10 } = __require("fs/promises");
73534
+ module.exports = ({ cwd = process.cwd() } = {}) => stat10(cwd + "/.git").then(() => true, () => false);
73177
73535
  }
73178
73536
  });
73179
73537
 
@@ -73200,8 +73558,8 @@ var require_find = __commonJS({
73200
73558
  // ../../node_modules/.pnpm/@npmcli+git@6.0.3/node_modules/@npmcli/git/lib/is-clean.js
73201
73559
  var require_is_clean = __commonJS({
73202
73560
  "../../node_modules/.pnpm/@npmcli+git@6.0.3/node_modules/@npmcli/git/lib/is-clean.js"(exports, module) {
73203
- var spawn4 = require_spawn();
73204
- module.exports = (opts = {}) => spawn4(["status", "--porcelain=v1", "-uno"], opts).then((res) => !res.stdout.trim().split(/\r?\n+/).map((l) => l.trim()).filter((l) => l).length);
73561
+ var spawn5 = require_spawn();
73562
+ module.exports = (opts = {}) => spawn5(["status", "--porcelain=v1", "-uno"], opts).then((res) => !res.stdout.trim().split(/\r?\n+/).map((l) => l.trim()).filter((l) => l).length);
73205
73563
  }
73206
73564
  });
73207
73565
 
@@ -75412,11 +75770,11 @@ var require_normalize = __commonJS({
75412
75770
  // ../../node_modules/.pnpm/@npmcli+package-json@6.2.0/node_modules/@npmcli/package-json/lib/read-package.js
75413
75771
  var require_read_package = __commonJS({
75414
75772
  "../../node_modules/.pnpm/@npmcli+package-json@6.2.0/node_modules/@npmcli/package-json/lib/read-package.js"(exports, module) {
75415
- var { readFile: readFile40 } = __require("fs/promises");
75773
+ var { readFile: readFile42 } = __require("fs/promises");
75416
75774
  var parseJSON = require_lib34();
75417
75775
  async function read(filename) {
75418
75776
  try {
75419
- const data = await readFile40(filename, "utf8");
75777
+ const data = await readFile42(filename, "utf8");
75420
75778
  return data;
75421
75779
  } catch (err) {
75422
75780
  err.message = `Could not read package.json: ${err}`;
@@ -75549,7 +75907,7 @@ var require_sort2 = __commonJS({
75549
75907
  // ../../node_modules/.pnpm/@npmcli+package-json@6.2.0/node_modules/@npmcli/package-json/lib/index.js
75550
75908
  var require_lib41 = __commonJS({
75551
75909
  "../../node_modules/.pnpm/@npmcli+package-json@6.2.0/node_modules/@npmcli/package-json/lib/index.js"(exports, module) {
75552
- var { readFile: readFile40, writeFile: writeFile13 } = __require("node:fs/promises");
75910
+ var { readFile: readFile42, writeFile: writeFile14 } = __require("node:fs/promises");
75553
75911
  var { resolve: resolve35 } = __require("node:path");
75554
75912
  var parseJSON = require_lib34();
75555
75913
  var updateDeps = require_update_dependencies();
@@ -75676,7 +76034,7 @@ var require_lib41 = __commonJS({
75676
76034
  const indexFile = resolve35(this.path, "index.js");
75677
76035
  let indexFileContent;
75678
76036
  try {
75679
- indexFileContent = await readFile40(indexFile, "utf8");
76037
+ indexFileContent = await readFile42(indexFile, "utf8");
75680
76038
  } catch (err) {
75681
76039
  throw parseErr;
75682
76040
  }
@@ -75764,7 +76122,7 @@ var require_lib41 = __commonJS({
75764
76122
  const fileContent = `${JSON.stringify(content, null, format)}
75765
76123
  `.replace(/\n/g, eol);
75766
76124
  if (fileContent.trim() !== this.#readFileContent.trim()) {
75767
- const written = await writeFile13(this.filename, fileContent);
76125
+ const written = await writeFile14(this.filename, fileContent);
75768
76126
  this.#readFileContent = fileContent;
75769
76127
  return written;
75770
76128
  }
@@ -82875,12 +83233,12 @@ var require_url = __commonJS({
82875
83233
  "../../node_modules/.pnpm/tuf-js@3.1.0/node_modules/tuf-js/dist/utils/url.js"(exports) {
82876
83234
  "use strict";
82877
83235
  Object.defineProperty(exports, "__esModule", { value: true });
82878
- exports.join = join32;
83236
+ exports.join = join34;
82879
83237
  var url_1 = __require("url");
82880
- function join32(base, path15) {
83238
+ function join34(base, path15) {
82881
83239
  return new url_1.URL(ensureTrailingSlash(base) + removeLeadingSlash(path15)).toString();
82882
83240
  }
82883
- __name(join32, "join");
83241
+ __name(join34, "join");
82884
83242
  function ensureTrailingSlash(path15) {
82885
83243
  return path15.endsWith("/") ? path15 : path15 + "/";
82886
83244
  }
@@ -84985,7 +85343,7 @@ var require_dist16 = __commonJS({
84985
85343
  var require_provenance = __commonJS({
84986
85344
  "../../node_modules/.pnpm/libnpmpublish@11.1.0/node_modules/libnpmpublish/lib/provenance.js"(exports, module) {
84987
85345
  var sigstore = require_dist16();
84988
- var { readFile: readFile40 } = __require("node:fs/promises");
85346
+ var { readFile: readFile42 } = __require("node:fs/promises");
84989
85347
  var ci = require_ci_info();
84990
85348
  var { env } = process;
84991
85349
  var INTOTO_PAYLOAD_TYPE = "application/vnd.in-toto+json";
@@ -85177,7 +85535,7 @@ var require_provenance = __commonJS({
85177
85535
  var verifyProvenance = /* @__PURE__ */ __name(async (subject, provenancePath) => {
85178
85536
  let provenanceBundle;
85179
85537
  try {
85180
- provenanceBundle = JSON.parse(await readFile40(provenancePath));
85538
+ provenanceBundle = JSON.parse(await readFile42(provenancePath));
85181
85539
  } catch (err) {
85182
85540
  err.message = `Invalid provenance provided: ${err.message}`;
85183
85541
  throw err;
@@ -85513,13 +85871,13 @@ __export(npm_exports, {
85513
85871
  verifyFrozenNpmTarballContract: () => verifyFrozenNpmTarballContract,
85514
85872
  verifyFrozenNpmTarballIdentity: () => verifyFrozenNpmTarballIdentity
85515
85873
  });
85516
- import { createHash as createHash13, randomUUID } from "node:crypto";
85874
+ import { createHash as createHash14, randomUUID } from "node:crypto";
85517
85875
  import { execFile as execFileCb7, spawn as spawn3 } from "node:child_process";
85518
85876
  import { gunzipSync } from "node:zlib";
85519
85877
  import { promisify as promisify7 } from "node:util";
85520
- import { dirname as dirname9, isAbsolute as isAbsolute14, join as join15, relative as relative17, resolve as resolve19 } from "node:path";
85878
+ import { dirname as dirname9, isAbsolute as isAbsolute14, join as join17, relative as relative17, resolve as resolve19 } from "node:path";
85521
85879
  import { constants as fsConstants4 } from "node:fs";
85522
- import { chmod as chmod3, lstat as lstat18, mkdtemp as mkdtemp6, open as open8, readFile as readFile17, realpath as realpath15, rm as rm8 } from "node:fs/promises";
85880
+ import { chmod as chmod3, lstat as lstat18, mkdtemp as mkdtemp6, open as open8, readFile as readFile19, realpath as realpath15, rm as rm8 } from "node:fs/promises";
85523
85881
  function validatePackageName(value) {
85524
85882
  if (typeof value !== "string" || value.length > 214 || !SAFE_PACKAGE_NAME.test(value)) {
85525
85883
  throw new Error("npm package must be a safe lowercase package name or @scope/name");
@@ -85573,7 +85931,7 @@ function expandNpmrcValue(raw, env) {
85573
85931
  async function tokensFromNpmrc(path15, key, env) {
85574
85932
  let contents;
85575
85933
  try {
85576
- contents = await readFile17(path15, "utf8");
85934
+ contents = await readFile19(path15, "utf8");
85577
85935
  } catch (err) {
85578
85936
  if (err?.code === "ENOENT") return [];
85579
85937
  throw new Error("cannot read npm authentication config");
@@ -85596,7 +85954,7 @@ async function defaultResolveAuthToken({ registry, cwd, exec, env = process.env
85596
85954
  if (env[name]) candidates.push(env[name]);
85597
85955
  }
85598
85956
  const key = registryTokenKey(registry);
85599
- candidates.push(...await tokensFromNpmrc(join15(cwd, ".npmrc"), key, env));
85957
+ candidates.push(...await tokensFromNpmrc(join17(cwd, ".npmrc"), key, env));
85600
85958
  const npmUserConfigKey = ["npm", "config", "userconfig"].join("_");
85601
85959
  const userConfig = env[npmUserConfigKey] ?? (await exec("npm", ["config", "get", "userconfig"], { cwd, shell: false })).stdout.trim();
85602
85960
  if (userConfig) candidates.push(...await tokensFromNpmrc(userConfig, key, env));
@@ -85674,12 +86032,12 @@ async function readVerifiedTarballBytes(action, root) {
85674
86032
  } finally {
85675
86033
  await source.close();
85676
86034
  }
85677
- const digest2 = createHash13("sha256").update(bytes).digest("hex");
86035
+ const digest2 = createHash14("sha256").update(bytes).digest("hex");
85678
86036
  if (digest2 !== action.tarballSha256) throw new Error("frozen npm tarball SHA-256 mismatch");
85679
86037
  if (typeof action.integrity !== "string" || !/^sha512-[A-Za-z0-9+/]+={0,2}$/.test(action.integrity)) {
85680
86038
  throw new Error("frozen npm tarball integrity must be an sha512 SRI value");
85681
86039
  }
85682
- const integrity = `sha512-${createHash13("sha512").update(bytes).digest("base64")}`;
86040
+ const integrity = `sha512-${createHash14("sha512").update(bytes).digest("base64")}`;
85683
86041
  if (integrity !== action.integrity) throw new Error("frozen npm tarball SHA-512 integrity mismatch");
85684
86042
  return bytes;
85685
86043
  }
@@ -86127,9 +86485,9 @@ var init_npm = __esm({
86127
86485
  });
86128
86486
 
86129
86487
  // src/core/run.mjs
86130
- import { lstat as lstat19, mkdir as mkdir12, readFile as readFile18 } from "node:fs/promises";
86488
+ import { lstat as lstat19, mkdir as mkdir12, readFile as readFile20 } from "node:fs/promises";
86131
86489
  import { realpathSync as realpathSync3 } from "node:fs";
86132
- import { dirname as dirname10, join as join16, resolve as resolve20, basename as basename5, relative as relative18, isAbsolute as isAbsolute15 } from "node:path";
86490
+ import { dirname as dirname10, join as join18, resolve as resolve20, basename as basename5, relative as relative18, isAbsolute as isAbsolute15 } from "node:path";
86133
86491
  function resolveDefaultRunDir(planPath, command2, runId = `${command2}-${Date.now()}`) {
86134
86492
  const absolute = resolve20(planPath);
86135
86493
  const fileName = basename5(absolute);
@@ -86139,7 +86497,7 @@ function resolveDefaultRunDir(planPath, command2, runId = `${command2}-${Date.no
86139
86497
  }
86140
86498
  if (basename5(parentDir) === "plans") {
86141
86499
  const releaseDir = dirname10(parentDir);
86142
- return join16(releaseDir, "runs", runId);
86500
+ return join18(releaseDir, "runs", runId);
86143
86501
  }
86144
86502
  return `${parentDir}/runs/${runId}`;
86145
86503
  }
@@ -86179,7 +86537,7 @@ function validateRun(run5, options = {}) {
86179
86537
  async function loadRun(runPath, options = {}) {
86180
86538
  let raw;
86181
86539
  try {
86182
- raw = await readFile18(runPath, "utf8");
86540
+ raw = await readFile20(runPath, "utf8");
86183
86541
  } catch (err) {
86184
86542
  throw new ReleaseError(
86185
86543
  GATE_FAILED,
@@ -86218,7 +86576,7 @@ function assertImmutableRunAuthority(runPath, planPath, run5) {
86218
86576
  }
86219
86577
  cursor = dirname10(cursor);
86220
86578
  }
86221
- const runsDir = join16(authorityRoot, "runs");
86579
+ const runsDir = join18(authorityRoot, "runs");
86222
86580
  const absoluteRun = realpathSync3(resolve20(runPath));
86223
86581
  const rel = relative18(runsDir, absoluteRun);
86224
86582
  if (isAbsolute15(rel) || rel === ".." || rel.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`)) {
@@ -86273,7 +86631,7 @@ async function createProductionPrepareRunDir(runDir, releaseDir) {
86273
86631
  return createProductionRunDirWithinAuthority(runDir, physicalAuthorityRoot);
86274
86632
  }
86275
86633
  async function createProductionRunDirWithinAuthority(runDir, authorityRoot) {
86276
- const runsDir = join16(authorityRoot, "runs");
86634
+ const runsDir = join18(authorityRoot, "runs");
86277
86635
  let runsStat;
86278
86636
  try {
86279
86637
  runsStat = await lstat19(runsDir);
@@ -86383,7 +86741,7 @@ async function validateStatePredecessorChain(run5, runPath, options = {}) {
86383
86741
  if (traversed > 1e5) {
86384
86742
  throw new ReleaseError(GATE_FAILED, "run state predecessor chain exceeds maximum depth");
86385
86743
  }
86386
- const previousPath = join16(dirname10(currentPath), `${String(sequence - 1).padStart(6, "0")}.json`);
86744
+ const previousPath = join18(dirname10(currentPath), `${String(sequence - 1).padStart(6, "0")}.json`);
86387
86745
  const previous = await loadRun(previousPath, {
86388
86746
  requireDigest: true,
86389
86747
  ...options.production ? { authorityPlanPath: options.planPath } : {}
@@ -86556,7 +86914,7 @@ async function writeRunAtomic(runPath, run5) {
86556
86914
  await publishFileExclusive(dir, basename5(runPath), json, { mode: 384 });
86557
86915
  } catch (cause) {
86558
86916
  if (cause?.details?.kind === HARNESS_ERROR_KINDS.EXCLUSIVE_PUBLISH_CONFLICT) {
86559
- const existing = await readFile18(runPath, "utf8").catch(() => null);
86917
+ const existing = await readFile20(runPath, "utf8").catch(() => null);
86560
86918
  if (existing === json) return Object.freeze(sealed);
86561
86919
  throw new ReleaseError(
86562
86920
  GATE_FAILED,
@@ -86576,10 +86934,10 @@ async function appendRunState(runDir, sequence, run5) {
86576
86934
  if (!Number.isSafeInteger(sequence) || sequence < 0) {
86577
86935
  throw new ReleaseError(GATE_FAILED, "run state sequence must be a non-negative integer");
86578
86936
  }
86579
- const statesDir = join16(runDir, "states");
86937
+ const statesDir = join18(runDir, "states");
86580
86938
  let previousStateDigest;
86581
86939
  if (sequence > 0) {
86582
- const previousPath = join16(statesDir, `${String(sequence - 1).padStart(6, "0")}.json`);
86940
+ const previousPath = join18(statesDir, `${String(sequence - 1).padStart(6, "0")}.json`);
86583
86941
  const previous = await loadRun(previousPath, { requireDigest: true });
86584
86942
  if (previous.stateSequence !== sequence - 1 || previous.runId !== run5.runId || previous.command !== run5.command || previous.planDigest !== run5.planDigest) {
86585
86943
  throw new ReleaseError(
@@ -86596,7 +86954,7 @@ async function appendRunState(runDir, sequence, run5) {
86596
86954
  stateSequence: sequence,
86597
86955
  ...previousStateDigest ? { previousStateDigest } : {}
86598
86956
  });
86599
- const statePath = join16(statesDir, `${String(sequence).padStart(6, "0")}.json`);
86957
+ const statePath = join18(statesDir, `${String(sequence).padStart(6, "0")}.json`);
86600
86958
  await writeRunAtomic(statePath, state);
86601
86959
  return Object.freeze({ state, statePath });
86602
86960
  }
@@ -86649,9 +87007,9 @@ __export(plugin_marketplace_exports, {
86649
87007
  });
86650
87008
  import { execFile as execFileCb8 } from "node:child_process";
86651
87009
  import { promisify as promisify8 } from "node:util";
86652
- import { readFile as readFile19, stat as stat4, mkdir as mkdir13, readdir as readdir12, realpath as realpath16, lstat as lstat20 } from "node:fs/promises";
86653
- import { join as join17, resolve as resolve21, relative as relative19, isAbsolute as isAbsolute16, basename as basename6 } from "node:path";
86654
- import { createHash as createHash14 } from "node:crypto";
87010
+ import { readFile as readFile21, stat as stat5, mkdir as mkdir13, readdir as readdir13, realpath as realpath16, lstat as lstat20 } from "node:fs/promises";
87011
+ import { join as join19, resolve as resolve21, relative as relative19, isAbsolute as isAbsolute16, basename as basename6 } from "node:path";
87012
+ import { createHash as createHash15 } from "node:crypto";
86655
87013
  function transportPayload(entries) {
86656
87014
  return entries.map(({ path: path15, type, mode, size, contentDigest }) => ({
86657
87015
  path: path15,
@@ -86736,7 +87094,7 @@ async function resolvePluginManifestFromMarketplaceEntrySource(marketIndex, plug
86736
87094
  const fullManifestRelative = pluginRootRelToSnapshot === "" ? manifestRelative : `${pluginRootRelToSnapshot}/${manifestRelative}`;
86737
87095
  let raw;
86738
87096
  try {
86739
- raw = await readFile19(manifestAbs, "utf8");
87097
+ raw = await readFile21(manifestAbs, "utf8");
86740
87098
  } catch (err) {
86741
87099
  throw new Error(
86742
87100
  `plugin manifest not found at "${fullManifestRelative}": ${err.message}`
@@ -87185,7 +87543,7 @@ async function run2(cmd, args2, options = {}) {
87185
87543
  }
87186
87544
  async function validateManifestFile(manifestPath, requiredFields) {
87187
87545
  try {
87188
- const content = await readFile19(manifestPath, "utf8");
87546
+ const content = await readFile21(manifestPath, "utf8");
87189
87547
  const manifest = JSON.parse(content);
87190
87548
  const missing = requiredFields.filter((f) => !(f in manifest));
87191
87549
  return {
@@ -87207,7 +87565,7 @@ async function checkRequiredFiles(dir, requiredFiles) {
87207
87565
  const missing = [];
87208
87566
  for (const file of requiredFiles) {
87209
87567
  try {
87210
- await stat4(resolve21(dir, file));
87568
+ await stat5(resolve21(dir, file));
87211
87569
  } catch {
87212
87570
  missing.push(file);
87213
87571
  }
@@ -87303,7 +87661,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
87303
87661
  });
87304
87662
  }
87305
87663
  try {
87306
- const s = await stat4(pluginDir);
87664
+ const s = await stat5(pluginDir);
87307
87665
  if (!s.isDirectory()) {
87308
87666
  return createResult({
87309
87667
  actionType,
@@ -88089,7 +88447,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
88089
88447
  let entrySkillFile = resolve21(pluginRootForSkill, "skills", action.entrySkill, "SKILL.md");
88090
88448
  let entrySkillExists = false;
88091
88449
  try {
88092
- await stat4(entrySkillFile);
88450
+ await stat5(entrySkillFile);
88093
88451
  entrySkillExists = true;
88094
88452
  } catch {
88095
88453
  if (action.plugin) {
@@ -88100,7 +88458,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
88100
88458
  "SKILL.md"
88101
88459
  );
88102
88460
  try {
88103
- await stat4(prefixed);
88461
+ await stat5(prefixed);
88104
88462
  entrySkillFile = prefixed;
88105
88463
  entrySkillExists = true;
88106
88464
  } catch {
@@ -88517,7 +88875,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
88517
88875
  if (actionType === ActionType.PLUGIN_MANIFEST_VALIDATE) {
88518
88876
  const manifestPath = action.manifestPath;
88519
88877
  try {
88520
- const content = await readFile19(manifestPath, "utf8");
88878
+ const content = await readFile21(manifestPath, "utf8");
88521
88879
  const manifest = JSON.parse(content);
88522
88880
  return createResult({
88523
88881
  actionType,
@@ -88612,7 +88970,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
88612
88970
  }
88613
88971
  let requirement = null;
88614
88972
  try {
88615
- requirement = JSON.parse(await readFile19(resolve21(attestationDir, KIMI_REQUIREMENT_FILE), "utf8"));
88973
+ requirement = JSON.parse(await readFile21(resolve21(attestationDir, KIMI_REQUIREMENT_FILE), "utf8"));
88616
88974
  } catch {
88617
88975
  return createResult({
88618
88976
  actionType,
@@ -88636,7 +88994,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
88636
88994
  }
88637
88995
  let attestation = null;
88638
88996
  try {
88639
- attestation = JSON.parse(await readFile19(resolve21(attestationDir, KIMI_ATTESTATION_FILE), "utf8"));
88997
+ attestation = JSON.parse(await readFile21(resolve21(attestationDir, KIMI_ATTESTATION_FILE), "utf8"));
88640
88998
  } catch {
88641
88999
  return createResult({
88642
89000
  actionType,
@@ -88803,7 +89161,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
88803
89161
  }
88804
89162
  let requirement = null;
88805
89163
  try {
88806
- requirement = JSON.parse(await readFile19(resolve21(attestationDir, CODEBUDDY_REQUIREMENT_FILE), "utf8"));
89164
+ requirement = JSON.parse(await readFile21(resolve21(attestationDir, CODEBUDDY_REQUIREMENT_FILE), "utf8"));
88807
89165
  } catch {
88808
89166
  return createResult({
88809
89167
  actionType,
@@ -88827,7 +89185,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
88827
89185
  }
88828
89186
  let attestation = null;
88829
89187
  try {
88830
- attestation = JSON.parse(await readFile19(resolve21(attestationDir, CODEBUDDY_ATTESTATION_FILE), "utf8"));
89188
+ attestation = JSON.parse(await readFile21(resolve21(attestationDir, CODEBUDDY_ATTESTATION_FILE), "utf8"));
88831
89189
  } catch {
88832
89190
  const marketplaceSource = resolveCodeBuddyMarketplaceSource(action);
88833
89191
  return createResult({
@@ -88976,13 +89334,13 @@ function createPluginMarketplaceAdapter(deps = {}) {
88976
89334
  if (codexAttestationDir) {
88977
89335
  let codexRequirement = null;
88978
89336
  try {
88979
- codexRequirement = JSON.parse(await readFile19(resolve21(codexAttestationDir, CODEX_REQUIREMENT_FILE), "utf8"));
89337
+ codexRequirement = JSON.parse(await readFile21(resolve21(codexAttestationDir, CODEX_REQUIREMENT_FILE), "utf8"));
88980
89338
  } catch {
88981
89339
  }
88982
89340
  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)) {
88983
89341
  let codexAttestation = null;
88984
89342
  try {
88985
- codexAttestation = JSON.parse(await readFile19(resolve21(codexAttestationDir, CODEX_ATTESTATION_FILE), "utf8"));
89343
+ codexAttestation = JSON.parse(await readFile21(resolve21(codexAttestationDir, CODEX_ATTESTATION_FILE), "utf8"));
88986
89344
  } catch {
88987
89345
  }
88988
89346
  if (codexAttestation) {
@@ -89037,7 +89395,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
89037
89395
  }
89038
89396
  let evidence = null;
89039
89397
  try {
89040
- const evidenceRaw = await readFile19(resolve21(runDir, "evidence", `${consumer}-${action.plugin}`, "release-skill-install-evidence.json"), "utf8");
89398
+ const evidenceRaw = await readFile21(resolve21(runDir, "evidence", `${consumer}-${action.plugin}`, "release-skill-install-evidence.json"), "utf8");
89041
89399
  evidence = JSON.parse(evidenceRaw);
89042
89400
  } catch {
89043
89401
  return createResult({
@@ -89220,7 +89578,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
89220
89578
  }
89221
89579
  try {
89222
89580
  const installedManifestPath = resolve21(installPath, platform.manifestPaths.plugin);
89223
- const installedManifestContent = await readFile19(installedManifestPath, "utf8");
89581
+ const installedManifestContent = await readFile21(installedManifestPath, "utf8");
89224
89582
  const installedManifest = JSON.parse(installedManifestContent);
89225
89583
  const expectedName = observation.plugin;
89226
89584
  if (expectedName && installedManifest.name !== expectedName) {
@@ -89651,8 +90009,8 @@ var init_postpublish = __esm({
89651
90009
  });
89652
90010
 
89653
90011
  // src/artifacts/transaction-journal.mjs
89654
- import { readdir as readdir13, readFile as readFile20, rm as rm9, stat as stat5 } from "node:fs/promises";
89655
- import { join as join18 } from "node:path";
90012
+ import { readdir as readdir14, readFile as readFile22, rm as rm9, stat as stat6 } from "node:fs/promises";
90013
+ import { join as join20 } from "node:path";
89656
90014
  function failSchema(message, details) {
89657
90015
  throw new ReleaseError(TRANSACTION_INCOMPLETE, message, details);
89658
90016
  }
@@ -90649,7 +91007,7 @@ async function pruneTerminalTransactionRecords(transactionsRoot, {
90649
91007
  if (!Number.isInteger(retentionMax) || retentionMax < 0) return summary;
90650
91008
  let entries;
90651
91009
  try {
90652
- entries = await readdir13(transactionsRoot, { withFileTypes: true });
91010
+ entries = await readdir14(transactionsRoot, { withFileTypes: true });
90653
91011
  } catch (scanErr) {
90654
91012
  summary.errors.push(`scan: ${scanErr?.code || scanErr?.message || "readdir-failed"}`);
90655
91013
  return summary;
@@ -90659,11 +91017,11 @@ async function pruneTerminalTransactionRecords(transactionsRoot, {
90659
91017
  if (txnDirs.length <= retentionMax) return summary;
90660
91018
  const terminal = [];
90661
91019
  for (const entry of txnDirs) {
90662
- const recordDir = join18(transactionsRoot, entry.name);
91020
+ const recordDir = join20(transactionsRoot, entry.name);
90663
91021
  let state = null;
90664
91022
  let createdAt = null;
90665
91023
  try {
90666
- const raw = await readFile20(join18(recordDir, "journal.json"), "utf8");
91024
+ const raw = await readFile22(join20(recordDir, "journal.json"), "utf8");
90667
91025
  const journal = JSON.parse(raw);
90668
91026
  if (journal && typeof journal === "object") {
90669
91027
  state = typeof journal.state === "string" ? journal.state : null;
@@ -90676,7 +91034,7 @@ async function pruneTerminalTransactionRecords(transactionsRoot, {
90676
91034
  let sortTime = Date.parse(createdAt);
90677
91035
  if (!Number.isFinite(sortTime)) {
90678
91036
  try {
90679
- const dirStat = await stat5(recordDir);
91037
+ const dirStat = await stat6(recordDir);
90680
91038
  sortTime = dirStat.mtimeMs;
90681
91039
  } catch {
90682
91040
  sortTime = Number.MAX_SAFE_INTEGER;
@@ -90727,7 +91085,7 @@ async function createTransactionJournal({
90727
91085
  );
90728
91086
  if (typeof root === "string" && root.length > 0) {
90729
91087
  await pruneTerminalTransactionRecords(
90730
- join18(root, ".release-skill", "transactions"),
91088
+ join20(root, ".release-skill", "transactions"),
90731
91089
  { retentionMax }
90732
91090
  );
90733
91091
  }
@@ -94862,6 +95220,7 @@ var init_refresh_service = __esm({
94862
95220
  // src/commands/prepare.mjs
94863
95221
  var prepare_exports = {};
94864
95222
  __export(prepare_exports, {
95223
+ boundedOutputTail: () => boundedOutputTail,
94865
95224
  buildExternalActions: () => buildExternalActions,
94866
95225
  decodeExternalMarketplaceIndex: () => decodeExternalMarketplaceIndex,
94867
95226
  parseExternalMarketplaceLsRemote: () => parseExternalMarketplaceLsRemote,
@@ -94873,8 +95232,8 @@ __export(prepare_exports, {
94873
95232
  resolveUnitVersion: () => resolveUnitVersion,
94874
95233
  runDeclaredHooks: () => runDeclaredHooks
94875
95234
  });
94876
- import { resolve as resolve23, relative as relative22, isAbsolute as isAbsolute18, normalize as normalize3, dirname as dirname11 } from "node:path";
94877
- import { readFile as readFile21, mkdir as mkdir14, readdir as readdir14, realpath as realpath17 } from "node:fs/promises";
95235
+ import { resolve as resolve23, relative as relative22, isAbsolute as isAbsolute18, normalize as normalize3, dirname as dirname11, basename as basename7 } from "node:path";
95236
+ import { readFile as readFile23, mkdir as mkdir14, readdir as readdir15, realpath as realpath17 } from "node:fs/promises";
94878
95237
  import { execFile as execFileCb9 } from "node:child_process";
94879
95238
  import { promisify as promisify9 } from "node:util";
94880
95239
  async function resolveUnitVersion(unit, root, explicitVersion) {
@@ -94906,7 +95265,7 @@ async function resolveUnitVersion(unit, root, explicitVersion) {
94906
95265
  }
94907
95266
  let content;
94908
95267
  try {
94909
- content = await readFile21(normalizedPath, "utf8");
95268
+ content = await readFile23(normalizedPath, "utf8");
94910
95269
  } catch (err) {
94911
95270
  throw new ReleaseError(
94912
95271
  CONFIG_INVALID,
@@ -94968,17 +95327,38 @@ async function resolveAllUnitVersions(units, root, explicitVersion, evidence) {
94968
95327
  });
94969
95328
  return resolvedVersions;
94970
95329
  }
95330
+ function boundedOutputTail(text) {
95331
+ if (typeof text !== "string" || text.length === 0) return "";
95332
+ let lines = text.split("\n");
95333
+ if (lines.length > 1 && lines[lines.length - 1] === "") {
95334
+ lines = lines.slice(0, -1);
95335
+ }
95336
+ let tail2 = lines.slice(-HOOK_OUTPUT_TAIL_MAX_LINES);
95337
+ let joined = tail2.join("\n");
95338
+ while (tail2.length > 1 && Buffer.byteLength(joined, "utf8") > HOOK_OUTPUT_TAIL_MAX_BYTES) {
95339
+ tail2 = tail2.slice(1);
95340
+ joined = tail2.join("\n");
95341
+ }
95342
+ if (Buffer.byteLength(joined, "utf8") > HOOK_OUTPUT_TAIL_MAX_BYTES) {
95343
+ const buf = Buffer.from(joined, "utf8");
95344
+ joined = buf.subarray(buf.length - HOOK_OUTPUT_TAIL_MAX_BYTES).toString("utf8");
95345
+ }
95346
+ return joined;
95347
+ }
94971
95348
  async function runDeclaredHooks(config, root, evidence, hookFn = runHook, options = {}) {
94972
95349
  const hookOrder = ["docs", "build", "test", "typecheck"];
94973
95350
  const hooks = config.hooks ?? {};
94974
95351
  const cacheEnabled = options.hookCache !== false;
95352
+ const records = [];
94975
95353
  for (const name of hookOrder) {
94976
95354
  const hook = hooks[name];
94977
95355
  if (!hook) continue;
95356
+ const selectionField = name === "test" ? { testSelection: hook.testSelection === "incremental" ? "incremental" : "full" } : {};
94978
95357
  await evidence.append({
94979
95358
  phase: "hooks",
94980
95359
  status: "started",
94981
- hookName: name
95360
+ hookName: name,
95361
+ ...selectionField
94982
95362
  });
94983
95363
  let cacheKey;
94984
95364
  if (cacheEnabled && hook.cacheable === true) {
@@ -95000,8 +95380,10 @@ async function runDeclaredHooks(config, root, evidence, hookFn = runHook, option
95000
95380
  status: "completed",
95001
95381
  hookName: name,
95002
95382
  cached: true,
95003
- cacheKey
95383
+ cacheKey,
95384
+ ...selectionField
95004
95385
  });
95386
+ records.push({ name, completed: true, cached: true, testSelection: selectionField.testSelection });
95005
95387
  continue;
95006
95388
  }
95007
95389
  }
@@ -95016,7 +95398,8 @@ async function runDeclaredHooks(config, root, evidence, hookFn = runHook, option
95016
95398
  phase: "hooks",
95017
95399
  status: "failed",
95018
95400
  hookName: name,
95019
- error: { code: err.code, message: err.message }
95401
+ error: { code: err.code, message: err.message },
95402
+ ...selectionField
95020
95403
  });
95021
95404
  throw new ReleaseError(
95022
95405
  GATE_FAILED,
@@ -95025,16 +95408,31 @@ async function runDeclaredHooks(config, root, evidence, hookFn = runHook, option
95025
95408
  );
95026
95409
  }
95027
95410
  if (result.exitCode !== 0) {
95411
+ const stdoutTail = boundedOutputTail(result.stdout);
95412
+ const stderrTail = boundedOutputTail(result.stderr);
95413
+ process.stderr.write(`[release-skill] hook "${name}" failed with exit code ${result.exitCode}
95414
+ `);
95415
+ if (stdoutTail) {
95416
+ process.stderr.write(`[release-skill] hook "${name}" stdout tail:
95417
+ ${stdoutTail}
95418
+ `);
95419
+ }
95420
+ if (stderrTail) {
95421
+ process.stderr.write(`[release-skill] hook "${name}" stderr tail:
95422
+ ${stderrTail}
95423
+ `);
95424
+ }
95028
95425
  await evidence.append({
95029
95426
  phase: "hooks",
95030
95427
  status: "failed",
95031
95428
  hookName: name,
95032
95429
  exitCode: result.exitCode,
95033
95430
  // Test runners usually emit the actionable failure summary at the
95034
- // end. Preserve bounded tails of both streams instead of the noisy
95035
- // compiler prelude at the beginning.
95036
- stdoutTail: result.stdout.slice(-4e3),
95037
- stderrTail: result.stderr.slice(-4e3)
95431
+ // end. Preserve bounded tails (last 50 lines, capped at 8 KB) of both
95432
+ // streams instead of the noisy compiler prelude at the beginning.
95433
+ stdoutTail,
95434
+ stderrTail,
95435
+ ...selectionField
95038
95436
  });
95039
95437
  throw new ReleaseError(
95040
95438
  GATE_FAILED,
@@ -95062,9 +95460,12 @@ async function runDeclaredHooks(config, root, evidence, hookFn = runHook, option
95062
95460
  phase: "hooks",
95063
95461
  status: "completed",
95064
95462
  hookName: name,
95065
- exitCode: 0
95463
+ exitCode: 0,
95464
+ ...selectionField
95066
95465
  });
95466
+ records.push({ name, completed: true, cached: false, testSelection: selectionField.testSelection });
95067
95467
  }
95468
+ return records;
95068
95469
  }
95069
95470
  async function resolveReleaseDocsPlanFn(injected) {
95070
95471
  if (typeof injected === "function") return injected;
@@ -96021,7 +96422,7 @@ async function readLatestFrozenPlan(root) {
96021
96422
  const plansDir = resolve23(root, ".release-skill", "plans");
96022
96423
  let files;
96023
96424
  try {
96024
- files = await readdir14(plansDir);
96425
+ files = await readdir15(plansDir);
96025
96426
  } catch {
96026
96427
  return null;
96027
96428
  }
@@ -96030,7 +96431,7 @@ async function readLatestFrozenPlan(root) {
96030
96431
  if (!file.endsWith(".json")) continue;
96031
96432
  let plan;
96032
96433
  try {
96033
- plan = JSON.parse(await readFile21(resolve23(plansDir, file), "utf8"));
96434
+ plan = JSON.parse(await readFile23(resolve23(plansDir, file), "utf8"));
96034
96435
  } catch {
96035
96436
  continue;
96036
96437
  }
@@ -96055,7 +96456,8 @@ async function prepareRelease(options) {
96055
96456
  verificationGatesAuthorized,
96056
96457
  production = false,
96057
96458
  workflow = "full",
96058
- observePreviousPublicBaselineFn
96459
+ observePreviousPublicBaselineFn,
96460
+ testSelection = "full"
96059
96461
  } = options ?? {};
96060
96462
  const WORKFLOW_KINDS2 = /* @__PURE__ */ new Set(["full", "docs", "config", "marketplace"]);
96061
96463
  if (!WORKFLOW_KINDS2.has(workflow)) {
@@ -96065,6 +96467,20 @@ async function prepareRelease(options) {
96065
96467
  { workflow }
96066
96468
  );
96067
96469
  }
96470
+ if (testSelection === "incremental") {
96471
+ throw new ReleaseError(
96472
+ GATE_FAILED,
96473
+ "incremental selection is not allowed at freeze time",
96474
+ { testSelection, reservedFor: "preflight mode" }
96475
+ );
96476
+ }
96477
+ if (testSelection !== "full") {
96478
+ throw new ReleaseError(
96479
+ CONFIG_INVALID,
96480
+ `unknown testSelection "${testSelection}"; expected "full" or "incremental"`,
96481
+ { testSelection }
96482
+ );
96483
+ }
96068
96484
  const trimmedWorkflow = workflow !== "full";
96069
96485
  const skipDeclaredHooks = trimmedWorkflow;
96070
96486
  const skipSnapshotVerifyGates = trimmedWorkflow;
@@ -96128,6 +96544,34 @@ async function prepareRelease(options) {
96128
96544
  ...warning
96129
96545
  });
96130
96546
  }
96547
+ await evidence.append({ phase: "bundle-freshness", status: "started" });
96548
+ const bundleFreshnessFn = options.bundleFreshnessFn ?? assertBundleFreshness;
96549
+ let bundleFreshness;
96550
+ try {
96551
+ bundleFreshness = await bundleFreshnessFn(PKG_ROOT);
96552
+ } catch (err) {
96553
+ await evidence.append({
96554
+ phase: "bundle-freshness",
96555
+ status: "blocking",
96556
+ reason: err.details?.reason ?? null,
96557
+ error: { code: err.code, message: err.message }
96558
+ });
96559
+ throw err;
96560
+ }
96561
+ if (bundleFreshness?.applicable === false) {
96562
+ await evidence.append({
96563
+ phase: "bundle-freshness",
96564
+ status: "not-applicable",
96565
+ reason: bundleFreshness.reason
96566
+ });
96567
+ } else {
96568
+ await evidence.append({
96569
+ phase: "bundle-freshness",
96570
+ status: "completed",
96571
+ algorithm: bundleFreshness?.algorithm ?? null,
96572
+ sourceDigest: bundleFreshness?.sourceDigest ?? null
96573
+ });
96574
+ }
96131
96575
  await evidence.append({
96132
96576
  phase: "workflow",
96133
96577
  status: "configured",
@@ -96210,6 +96654,7 @@ async function prepareRelease(options) {
96210
96654
  }))
96211
96655
  });
96212
96656
  }
96657
+ let hookRecords = [];
96213
96658
  if (skipDeclaredHooks) {
96214
96659
  await evidence.append({
96215
96660
  phase: "hooks",
@@ -96218,7 +96663,7 @@ async function prepareRelease(options) {
96218
96663
  });
96219
96664
  } else {
96220
96665
  await evidence.append({ phase: "hooks", status: "started" });
96221
- await runDeclaredHooks(config, realRoot, evidence, options.runHookFn ?? runHook, {
96666
+ hookRecords = await runDeclaredHooks(config, realRoot, evidence, options.runHookFn ?? runHook, {
96222
96667
  hookCache: options.hookCache,
96223
96668
  // Explicit env delivery (0.5.1 hook-env-delivery fix): the hook runner
96224
96669
  // reads envAllowlist keys exclusively from context.env, so the invoking
@@ -96734,6 +97179,47 @@ async function prepareRelease(options) {
96734
97179
  await evidence.append({ phase: "remote-check", status: "skipped", reason: "offline mode" });
96735
97180
  }
96736
97181
  await evidence.append({ phase: "plan-assembly", status: "started" });
97182
+ if (skipDeclaredHooks) {
97183
+ await evidence.append({
97184
+ phase: "full-test-gate",
97185
+ status: "skipped",
97186
+ reason: `workflow "${workflow}" trims declared hooks`
97187
+ });
97188
+ } else if (!config.hooks?.test) {
97189
+ await evidence.append({
97190
+ phase: "full-test-gate",
97191
+ status: "not-declared",
97192
+ reason: "no test hook declared; nothing can run incrementally"
97193
+ });
97194
+ } else {
97195
+ const testRecord = hookRecords.find((record) => record.name === "test");
97196
+ const satisfied = Boolean(
97197
+ testRecord && testRecord.completed && testRecord.testSelection === "full"
97198
+ );
97199
+ if (!satisfied) {
97200
+ await evidence.append({
97201
+ phase: "full-test-gate",
97202
+ status: "blocking",
97203
+ testSelection: testRecord?.testSelection ?? null,
97204
+ cached: Boolean(testRecord?.cached)
97205
+ });
97206
+ throw new ReleaseError(
97207
+ GATE_FAILED,
97208
+ testRecord?.testSelection === "incremental" ? "full-test freeze gate failed: incremental test selection cannot satisfy the freeze-time requirement of a completed full test run in this prepare run" : "full-test freeze gate failed: prepare requires a completed full-mode test hook in this run before the plan digest is computed",
97209
+ {
97210
+ gate: "full-test-freeze",
97211
+ testSelection: testRecord?.testSelection ?? null,
97212
+ cached: Boolean(testRecord?.cached)
97213
+ }
97214
+ );
97215
+ }
97216
+ await evidence.append({
97217
+ phase: "full-test-gate",
97218
+ status: "completed",
97219
+ testSelection: "full",
97220
+ cached: Boolean(testRecord.cached)
97221
+ });
97222
+ }
96737
97223
  const createdAtTimestamp = production ? normalizeGitTimestamp(clock ? clock() : (/* @__PURE__ */ new Date()).toISOString(), "plan createdAt timestamp") : null;
96738
97224
  const freezeTimestamp = production ? await readHeadCommitTimestamp(realRoot, baseline.gitHead) : null;
96739
97225
  const productionAssets = production ? await buildProductionAssets(
@@ -96764,7 +97250,11 @@ async function prepareRelease(options) {
96764
97250
  snapshotDir: manifest.outputDir,
96765
97251
  host: "root"
96766
97252
  });
96767
- const receipt = createSkillResourceClosureReceipt(closureResult, { unitId: unit.id });
97253
+ const receipt = createSkillResourceClosureReceipt(closureResult, {
97254
+ unitId: unit.id,
97255
+ preparedAt: freezeTimestamp ?? null,
97256
+ exitCode: 0
97257
+ });
96768
97258
  skillResourceClosureResults.push(receipt);
96769
97259
  if (closureResult.findings.length > 0) {
96770
97260
  await evidence.append({
@@ -96777,7 +97267,10 @@ async function prepareRelease(options) {
96777
97267
  line: f.line,
96778
97268
  reference: f.reference,
96779
97269
  classification: f.classification,
96780
- code: f.code
97270
+ code: f.code,
97271
+ // D4: RESOURCE_DRIFT findings localize via references (the
97272
+ // finding's own skill/line stay null for a cross-surface drift).
97273
+ ...f.references ? { references: f.references } : {}
96781
97274
  }))
96782
97275
  });
96783
97276
  throw new ReleaseError(
@@ -96790,6 +97283,33 @@ async function prepareRelease(options) {
96790
97283
  }
96791
97284
  );
96792
97285
  }
97286
+ const expectedHosts = (unit.distributions ?? []).map((distribution) => PLATFORMS.find((platform) => platform.distributionType === distribution.type)).filter(Boolean).map((platform) => platform.buildAdapter.name);
97287
+ const hostCoverage = evaluateDeclaredHostSurfaceCoverage(
97288
+ expectedHosts,
97289
+ closureResult.surfaces
97290
+ );
97291
+ if (!hostCoverage.passed) {
97292
+ await evidence.append({
97293
+ phase: "skill-resource-closure",
97294
+ status: "blocking",
97295
+ unitId: unit.id,
97296
+ reason: "declared-host-surface-missing",
97297
+ missingHosts: hostCoverage.missing
97298
+ });
97299
+ throw new ReleaseError(
97300
+ GATE_FAILED,
97301
+ `skill resource closure gate failed for unit "${unit.id}": declared host surface(s) missing or empty: ${hostCoverage.missing.map((item) => item.host).join(", ")}`,
97302
+ {
97303
+ unitId: unit.id,
97304
+ missingHosts: hostCoverage.missing,
97305
+ observedSurfaces: closureResult.surfaces.map((surface) => ({
97306
+ id: surface.id,
97307
+ host: surface.host,
97308
+ skillCount: surface.skillCount
97309
+ }))
97310
+ }
97311
+ );
97312
+ }
96793
97313
  await evidence.append({
96794
97314
  phase: "skill-resource-closure",
96795
97315
  status: "completed",
@@ -96799,6 +97319,10 @@ async function prepareRelease(options) {
96799
97319
  skillCount: receipt.skillCount,
96800
97320
  referenceCount: closureResult.referenceCount,
96801
97321
  sourceOnlyCount: closureResult.sourceOnlyCount,
97322
+ // D2: per-reference exemption detail for approval/audit review —
97323
+ // evidence-layer only; the receipt object (and its digest binding)
97324
+ // is intentionally left unchanged.
97325
+ sourceOnlyReferences: closureResult.sourceOnlyReferences,
96802
97326
  findingCount: 0,
96803
97327
  receiptDigest: closureResult.receiptDigest
96804
97328
  });
@@ -96890,7 +97414,7 @@ async function prepareRelease(options) {
96890
97414
  const marketplaceIndexPath = resolve23(snapshotDir, marketplaceIndexRelative);
96891
97415
  let marketplaceIndexRaw;
96892
97416
  try {
96893
- marketplaceIndexRaw = await readFile21(marketplaceIndexPath, "utf8");
97417
+ marketplaceIndexRaw = await readFile23(marketplaceIndexPath, "utf8");
96894
97418
  } catch (err) {
96895
97419
  throw new ReleaseError(
96896
97420
  GATE_FAILED,
@@ -96959,7 +97483,7 @@ async function prepareRelease(options) {
96959
97483
  const pluginManifestPath = resolve23(snapshotDir, pluginManifestRelative);
96960
97484
  let raw;
96961
97485
  try {
96962
- raw = await readFile21(pluginManifestPath, "utf8");
97486
+ raw = await readFile23(pluginManifestPath, "utf8");
96963
97487
  } catch (err) {
96964
97488
  throw new ReleaseError(
96965
97489
  GATE_FAILED,
@@ -97196,6 +97720,19 @@ async function prepareRelease(options) {
97196
97720
  planPath: writtenPath,
97197
97721
  planDigest
97198
97722
  });
97723
+ await writeFrozenMarker(releaseDir, {
97724
+ planDigest,
97725
+ targetVersions: Object.fromEntries(
97726
+ configUnits.map((unit, index) => [unit.id, resolvedVersions[index]])
97727
+ ),
97728
+ createdAt: plan.createdAt,
97729
+ runId: basename7(runDir)
97730
+ });
97731
+ await evidence.append({
97732
+ phase: "frozen-marker",
97733
+ status: "written",
97734
+ markerPath: `.release-skill/${FROZEN_MARKER_FILENAME}`
97735
+ });
97199
97736
  await evidence.finish({
97200
97737
  status: "PREPARED",
97201
97738
  planPath: writtenPath,
@@ -97231,7 +97768,7 @@ async function prepareRelease(options) {
97231
97768
  await lock.release();
97232
97769
  }
97233
97770
  }
97234
- var execFile8, CONSUMER_INSTALL_RECIPE_VERSION2, EXTERNAL_MARKETPLACE_SHA_RE2;
97771
+ var execFile8, CONSUMER_INSTALL_RECIPE_VERSION2, HOOK_OUTPUT_TAIL_MAX_LINES, HOOK_OUTPUT_TAIL_MAX_BYTES, EXTERNAL_MARKETPLACE_SHA_RE2;
97235
97772
  var init_prepare = __esm({
97236
97773
  async "src/commands/prepare.mjs"() {
97237
97774
  await init_config();
@@ -97250,6 +97787,9 @@ var init_prepare = __esm({
97250
97787
  init_contract2();
97251
97788
  init_frozen();
97252
97789
  init_errors();
97790
+ init_bundle_freshness();
97791
+ init_pkg_root();
97792
+ init_frozen_marker();
97253
97793
  init_source_authority();
97254
97794
  init_project_lock();
97255
97795
  init_previous_public_baseline();
@@ -97263,6 +97803,9 @@ var init_prepare = __esm({
97263
97803
  CONSUMER_INSTALL_RECIPE_VERSION2 = "consumer-install-v1";
97264
97804
  __name(resolveUnitVersion, "resolveUnitVersion");
97265
97805
  __name(resolveAllUnitVersions, "resolveAllUnitVersions");
97806
+ HOOK_OUTPUT_TAIL_MAX_LINES = 50;
97807
+ HOOK_OUTPUT_TAIL_MAX_BYTES = 8 * 1024;
97808
+ __name(boundedOutputTail, "boundedOutputTail");
97266
97809
  __name(runDeclaredHooks, "runDeclaredHooks");
97267
97810
  __name(resolveReleaseDocsPlanFn, "resolveReleaseDocsPlanFn");
97268
97811
  __name(runReleaseDocsFreshnessGate, "runReleaseDocsFreshnessGate");
@@ -97332,8 +97875,8 @@ var init_hooks2 = __esm({
97332
97875
  });
97333
97876
 
97334
97877
  // src/core/approval.mjs
97335
- import { readFile as readFile22 } from "node:fs/promises";
97336
- import { basename as basename7, dirname as dirname12, join as join19, resolve as resolve25 } from "node:path";
97878
+ import { readFile as readFile24 } from "node:fs/promises";
97879
+ import { basename as basename8, dirname as dirname12, join as join21, resolve as resolve25 } from "node:path";
97337
97880
  function validateApprovalRecordSchema(approval) {
97338
97881
  if (validateApprovalSchema(approval)) return;
97339
97882
  const errors = validateApprovalSchema.errors ?? [];
@@ -97352,7 +97895,7 @@ function assertImmutableApprovalAuthority(approvalPath, plan, rawApproval) {
97352
97895
  const approvalDigest = computeApprovalDigest(rawApproval);
97353
97896
  const absolute = resolve25(approvalPath);
97354
97897
  const planDirectory = dirname12(absolute);
97355
- if (basename7(absolute) !== `${approvalDigest}.json` || basename7(planDirectory) !== planDigest || basename7(dirname12(planDirectory)) !== "approvals") {
97898
+ if (basename8(absolute) !== `${approvalDigest}.json` || basename8(planDirectory) !== planDigest || basename8(dirname12(planDirectory)) !== "approvals") {
97356
97899
  throw new ReleaseError(
97357
97900
  GATE_FAILED,
97358
97901
  "production commands require approvals/<planDigest>/<approvalDigest>.json immutable authority",
@@ -97619,8 +98162,8 @@ var approve_exports = {};
97619
98162
  __export(approve_exports, {
97620
98163
  approvePlan: () => approvePlan
97621
98164
  });
97622
- import { readFile as readFile23, writeFile as writeFile6 } from "node:fs/promises";
97623
- import { resolve as resolve26, dirname as dirname13, basename as basename8 } from "node:path";
98165
+ import { readFile as readFile25, writeFile as writeFile7 } from "node:fs/promises";
98166
+ import { resolve as resolve26, dirname as dirname13, basename as basename9 } from "node:path";
97624
98167
  function defaultClock() {
97625
98168
  return (/* @__PURE__ */ new Date()).toISOString();
97626
98169
  }
@@ -97643,7 +98186,7 @@ async function approvePlan(options) {
97643
98186
  }
97644
98187
  let planRaw;
97645
98188
  try {
97646
- planRaw = await readFile23(planPath, "utf8");
98189
+ planRaw = await readFile25(planPath, "utf8");
97647
98190
  } catch (err) {
97648
98191
  throw new ReleaseError(
97649
98192
  GATE_FAILED,
@@ -97749,7 +98292,7 @@ async function approvePlan(options) {
97749
98292
  };
97750
98293
  validateApprovalRecordSchema(approvalRecord);
97751
98294
  const planDir = dirname13(resolve26(planPath));
97752
- const releaseDir = basename8(planDir) === "plans" && basename8(planPath) === `${actualDigest}.json` ? dirname13(planDir) : planDir;
98295
+ const releaseDir = basename9(planDir) === "plans" && basename9(planPath) === `${actualDigest}.json` ? dirname13(planDir) : planDir;
97753
98296
  if (plan.production?.mode === "github-npm-v1" && outputPath && resolve26(outputPath) !== resolve26(releaseDir, "approval-record.json")) {
97754
98297
  throw new ReleaseError(
97755
98298
  GATE_FAILED,
@@ -97768,10 +98311,10 @@ async function approvePlan(options) {
97768
98311
  await prepareAuthorityDirectory(dirname13(immutableApprovalPath));
97769
98312
  await assertAuthorityFileTarget(immutableApprovalPath);
97770
98313
  try {
97771
- await writeFile6(immutableApprovalPath, json, { encoding: "utf8", flag: "wx", mode: 384 });
98314
+ await writeFile7(immutableApprovalPath, json, { encoding: "utf8", flag: "wx", mode: 384 });
97772
98315
  } catch (error) {
97773
98316
  if (error.code !== "EEXIST") throw error;
97774
- const existing = await readFile23(immutableApprovalPath, "utf8");
98317
+ const existing = await readFile25(immutableApprovalPath, "utf8");
97775
98318
  if (existing !== json) {
97776
98319
  throw new ReleaseError(
97777
98320
  GATE_FAILED,
@@ -97783,7 +98326,7 @@ async function approvePlan(options) {
97783
98326
  const writePath = outputPath ?? resolve26(releaseDir, "approval-record.json");
97784
98327
  await prepareAuthorityDirectory(dirname13(writePath));
97785
98328
  await assertAuthorityFileTarget(writePath);
97786
- await writeFile6(writePath, json, "utf8");
98329
+ await writeFile7(writePath, json, "utf8");
97787
98330
  return Object.freeze({
97788
98331
  ...approvalRecord,
97789
98332
  approvalDigest,
@@ -98073,8 +98616,8 @@ __export(publish_exports, {
98073
98616
  classifyPreObservation: () => classifyPreObservation,
98074
98617
  publishRelease: () => publishRelease
98075
98618
  });
98076
- import { readFile as readFile24, mkdir as mkdir16 } from "node:fs/promises";
98077
- import { isAbsolute as isAbsolute19, join as join20, relative as relative23 } from "node:path";
98619
+ import { readFile as readFile26, mkdir as mkdir16 } from "node:fs/promises";
98620
+ import { isAbsolute as isAbsolute19, join as join22, relative as relative23 } from "node:path";
98078
98621
  function assertInsideAssetRoot(assetRoot, candidate, label) {
98079
98622
  const rel = relative23(assetRoot, candidate);
98080
98623
  if (rel === "" || isAbsolute19(rel) || rel === ".." || rel.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`)) {
@@ -98306,7 +98849,7 @@ async function publishRelease(options) {
98306
98849
  const captureBaselineActual = typeof captureBaselineFn === "function" ? captureBaselineFn : captureBaseline;
98307
98850
  let planRaw;
98308
98851
  try {
98309
- planRaw = await readFile24(planPath, "utf8");
98852
+ planRaw = await readFile26(planPath, "utf8");
98310
98853
  } catch (err) {
98311
98854
  throw new ReleaseError(GATE_FAILED, `cannot read release plan: ${err.message}`, { planPath, cause: err.code });
98312
98855
  }
@@ -98450,7 +98993,11 @@ async function publishRelease(options) {
98450
98993
  { unitId, findings: closureResult.findings }
98451
98994
  );
98452
98995
  }
98453
- const observed = createSkillResourceClosureReceipt(closureResult, { unitId });
98996
+ const observed = createSkillResourceClosureReceipt(closureResult, {
98997
+ unitId,
98998
+ preparedAt: expected.preparedAt ?? null,
98999
+ exitCode: expected.exitCode ?? 0
99000
+ });
98454
99001
  assertSkillResourceClosureReceipt(expected, observed, `unit "${unitId}"`);
98455
99002
  }
98456
99003
  await evidence.append({
@@ -98464,7 +99011,7 @@ async function publishRelease(options) {
98464
99011
  await evidence.append({ phase: "safety-gate", gate: "approval-load", status: "started" });
98465
99012
  let approvalRaw;
98466
99013
  try {
98467
- approvalRaw = await readFile24(approvalPath, "utf8");
99014
+ approvalRaw = await readFile26(approvalPath, "utf8");
98468
99015
  } catch (err) {
98469
99016
  throw new ReleaseError(
98470
99017
  GATE_FAILED,
@@ -98778,7 +99325,7 @@ async function publishRelease(options) {
98778
99325
  }
98779
99326
  }
98780
99327
  await evidence.append({ phase: "safety-gate", gate: "global-preflight", status: "passed" });
98781
- const runPath = join20(runDir, "release-run.json");
99328
+ const runPath = join22(runDir, "release-run.json");
98782
99329
  const checkpoints = orderedActions.map((action) => {
98783
99330
  if (isMarketplaceAction(action.type)) {
98784
99331
  return {
@@ -99051,8 +99598,8 @@ var reconcile_exports = {};
99051
99598
  __export(reconcile_exports, {
99052
99599
  reconcileRelease: () => reconcileRelease
99053
99600
  });
99054
- import { readFile as readFile25, mkdir as mkdir17 } from "node:fs/promises";
99055
- import { join as join21 } from "node:path";
99601
+ import { readFile as readFile27, mkdir as mkdir17 } from "node:fs/promises";
99602
+ import { join as join23 } from "node:path";
99056
99603
  function defaultClock4() {
99057
99604
  return (/* @__PURE__ */ new Date()).toISOString();
99058
99605
  }
@@ -99080,7 +99627,7 @@ async function reconcileRelease(options) {
99080
99627
  }
99081
99628
  let planRaw;
99082
99629
  try {
99083
- planRaw = await readFile25(planPath, "utf8");
99630
+ planRaw = await readFile27(planPath, "utf8");
99084
99631
  } catch (err) {
99085
99632
  throw new ReleaseError(GATE_FAILED, `cannot read release plan: ${err.message}`, { planPath, cause: err.code });
99086
99633
  }
@@ -99202,7 +99749,7 @@ async function reconcileRelease(options) {
99202
99749
  { sourceRunId: sourceRun.runId }
99203
99750
  );
99204
99751
  }
99205
- const sourceApprovalRaw = await readFile25(consumedApprovalPath, "utf8").catch((error) => {
99752
+ const sourceApprovalRaw = await readFile27(consumedApprovalPath, "utf8").catch((error) => {
99206
99753
  throw new ReleaseError(GATE_FAILED, "source run approval authority is unavailable", {
99207
99754
  sourceRunId: sourceRun.runId,
99208
99755
  cause: error.code
@@ -99364,7 +99911,7 @@ async function reconcileRelease(options) {
99364
99911
  if (approvalPath) {
99365
99912
  let approvalRaw;
99366
99913
  try {
99367
- approvalRaw = await readFile25(approvalPath, "utf8");
99914
+ approvalRaw = await readFile27(approvalPath, "utf8");
99368
99915
  } catch (err) {
99369
99916
  throw new ReleaseError(
99370
99917
  GATE_FAILED,
@@ -99977,7 +100524,7 @@ async function reconcileRelease(options) {
99977
100524
  ...normalized === "deferred" ? { reason: CONSUMER_VERIFICATION_DEFERRED, phase: "post-publish-verification" } : {}
99978
100525
  };
99979
100526
  });
99980
- const runPath = join21(runDir, "release-run.json");
100527
+ const runPath = join23(runDir, "release-run.json");
99981
100528
  const sourceRunDigest = sourceAuthorityDigest;
99982
100529
  const runState = {
99983
100530
  runId,
@@ -100057,7 +100604,7 @@ var init_reconcile = __esm({
100057
100604
  });
100058
100605
 
100059
100606
  // src/core/baseline-advance.mjs
100060
- import { readFile as readFile26, writeFile as writeFile7 } from "node:fs/promises";
100607
+ import { readFile as readFile28, writeFile as writeFile8 } from "node:fs/promises";
100061
100608
  import { execFile as execFileCb10 } from "node:child_process";
100062
100609
  import { promisify as promisify10 } from "node:util";
100063
100610
  function defaultExec(command2, args2, options = {}) {
@@ -100091,7 +100638,7 @@ async function applyBaselineAdvances({ configPath, advances, validateFn }) {
100091
100638
  }
100092
100639
  let content;
100093
100640
  try {
100094
- content = await readFile26(configPath, "utf8");
100641
+ content = await readFile28(configPath, "utf8");
100095
100642
  } catch (err) {
100096
100643
  throw new ReleaseError(
100097
100644
  GATE_FAILED,
@@ -100133,12 +100680,12 @@ async function applyBaselineAdvances({ configPath, advances, validateFn }) {
100133
100680
  return { changed: false, updatedUnits: [] };
100134
100681
  }
100135
100682
  const next = doc.toString();
100136
- await writeFile7(configPath, next, "utf8");
100683
+ await writeFile8(configPath, next, "utf8");
100137
100684
  if (typeof validateFn === "function") {
100138
100685
  try {
100139
100686
  await validateFn(configPath);
100140
100687
  } catch (err) {
100141
- await writeFile7(configPath, content, "utf8");
100688
+ await writeFile8(configPath, content, "utf8");
100142
100689
  throw new ReleaseError(
100143
100690
  GATE_FAILED,
100144
100691
  `baseline advance reverted: rewritten config failed validation: ${err.message}`,
@@ -100185,9 +100732,9 @@ __export(verify_exports, {
100185
100732
  runSmokeTest: () => runSmokeTest,
100186
100733
  verifyRelease: () => verifyRelease
100187
100734
  });
100188
- import { readFile as readFile27, writeFile as writeFile8, mkdtemp as mkdtemp7, rm as rm10, mkdir as mkdir18, lstat as lstat21, realpath as realpath18, readdir as readdir15 } from "node:fs/promises";
100735
+ import { readFile as readFile29, writeFile as writeFile9, mkdtemp as mkdtemp7, rm as rm10, mkdir as mkdir18, lstat as lstat21, realpath as realpath18, readdir as readdir16 } from "node:fs/promises";
100189
100736
  import { realpathSync as realpathSync4 } from "node:fs";
100190
- import { dirname as dirname14, join as join22, relative as relative24, isAbsolute as isAbsolute20, resolve as resolve27, basename as basename9 } from "node:path";
100737
+ import { dirname as dirname14, join as join24, relative as relative24, isAbsolute as isAbsolute20, resolve as resolve27, basename as basename10 } from "node:path";
100191
100738
  import { tmpdir as tmpdir4 } from "node:os";
100192
100739
  import { execFile as execFileCb11 } from "node:child_process";
100193
100740
  import { promisify as promisify11 } from "node:util";
@@ -100240,18 +100787,18 @@ async function collectMissingManualAttestations({
100240
100787
  const isKimi = action.type === "kimi-marketplace-install";
100241
100788
  const planDigest = isKimi ? resolveBoundPlanDigest(context) : await resolveCodeBuddyBoundPlanDigest(context);
100242
100789
  const authorityDir = isKimi ? kimiAuthorityDir(context, planDigest, action.parameters.plugin) : codebuddyAuthorityDir(context, planDigest, action.parameters.plugin);
100243
- const requirementPath = join22(
100790
+ const requirementPath = join24(
100244
100791
  authorityDir,
100245
100792
  isKimi ? KIMI_REQUIREMENT_FILE : CODEBUDDY_REQUIREMENT_FILE
100246
100793
  );
100247
- const attestationPath = join22(
100794
+ const attestationPath = join24(
100248
100795
  authorityDir,
100249
100796
  isKimi ? KIMI_ATTESTATION_FILE : CODEBUDDY_ATTESTATION_FILE
100250
100797
  );
100251
100798
  let valid = false;
100252
100799
  let reason = "attestation file is missing";
100253
100800
  try {
100254
- const attestation = JSON.parse(await readFile27(attestationPath, "utf8"));
100801
+ const attestation = JSON.parse(await readFile29(attestationPath, "utf8"));
100255
100802
  const validation = isKimi ? validateKimiAttestation(attestation, action.parameters, clockFn(), planDigest) : validateCodeBuddyAttestation(attestation, action.parameters, clockFn(), planDigest);
100256
100803
  valid = validation.valid;
100257
100804
  reason = validation.error;
@@ -100293,7 +100840,7 @@ function matchesSubset2(actual, expected) {
100293
100840
  async function runSmokeTest(plan, root, options = {}) {
100294
100841
  const baseDir = options.baseDir ?? tmpdir4();
100295
100842
  await mkdir18(baseDir, { recursive: true });
100296
- const tmpDir = await mkdtemp7(join22(baseDir, "verify-smoke-"));
100843
+ const tmpDir = await mkdtemp7(join24(baseDir, "verify-smoke-"));
100297
100844
  const npmExec = options.npmExecutor ?? defaultNpmExecutor;
100298
100845
  const installFlags = [
100299
100846
  "--ignore-scripts",
@@ -100341,7 +100888,7 @@ async function runSmokeTest(plan, root, options = {}) {
100341
100888
  for (const { package: pkgName, registry, targetVersion, unitId, smokeBin, smokeArgs, smokeExpectedJson } of npmDistributions) {
100342
100889
  const packageAtVersion = `${pkgName}@${targetVersion}`;
100343
100890
  const installDir = resolveUnitScopedPath(tmpDir, unitId);
100344
- await mkdir18(join22(installDir, "node_modules"), { recursive: true });
100891
+ await mkdir18(join24(installDir, "node_modules"), { recursive: true });
100345
100892
  const registryFlags = [...installFlags, "--registry", registry];
100346
100893
  const installResult = await npmExec.install(
100347
100894
  packageAtVersion,
@@ -100359,10 +100906,10 @@ async function runSmokeTest(plan, root, options = {}) {
100359
100906
  }
100360
100907
  };
100361
100908
  }
100362
- const installedPkgPath = join22(installDir, "node_modules", pkgName, "package.json");
100909
+ const installedPkgPath = join24(installDir, "node_modules", pkgName, "package.json");
100363
100910
  let installedPkg;
100364
100911
  try {
100365
- installedPkg = JSON.parse(await readFile27(installedPkgPath, "utf8"));
100912
+ installedPkg = JSON.parse(await readFile29(installedPkgPath, "utf8"));
100366
100913
  } catch {
100367
100914
  return {
100368
100915
  passed: false,
@@ -100393,7 +100940,7 @@ async function runSmokeTest(plan, root, options = {}) {
100393
100940
  }
100394
100941
  };
100395
100942
  }
100396
- const pkgRoot = join22(installDir, "node_modules", pkgName);
100943
+ const pkgRoot = join24(installDir, "node_modules", pkgName);
100397
100944
  {
100398
100945
  const dirIndex = await buildDirectoryFileIndex(pkgRoot);
100399
100946
  const closureResult = checkNpmEntryClosure(installedPkg, dirIndex);
@@ -100622,7 +101169,7 @@ async function runSmokeTest(plan, root, options = {}) {
100622
101169
  }
100623
101170
  async function discoverDistributeRuns({ planPath, plan }) {
100624
101171
  const planDir = dirname14(planPath);
100625
- const releaseDir = basename9(planDir) === "plans" ? dirname14(planDir) : planDir;
101172
+ const releaseDir = basename10(planDir) === "plans" ? dirname14(planDir) : planDir;
100626
101173
  const runsDir = resolve27(releaseDir, "runs");
100627
101174
  try {
100628
101175
  const runsDirStat = await lstat21(runsDir);
@@ -100654,7 +101201,7 @@ async function discoverDistributeRuns({ planPath, plan }) {
100654
101201
  return null;
100655
101202
  }
100656
101203
  const candidates = [];
100657
- const entries = await readdir15(runsDir, { withFileTypes: true });
101204
+ const entries = await readdir16(runsDir, { withFileTypes: true });
100658
101205
  for (const entry of entries) {
100659
101206
  if (!entry.name.startsWith("distribute-")) continue;
100660
101207
  if (!entry.isDirectory() || entry.isSymbolicLink()) {
@@ -100719,7 +101266,7 @@ async function verifyRelease(options) {
100719
101266
  }
100720
101267
  let planRaw;
100721
101268
  try {
100722
- planRaw = await readFile27(planPath, "utf8");
101269
+ planRaw = await readFile29(planPath, "utf8");
100723
101270
  } catch (err) {
100724
101271
  throw new ReleaseError(
100725
101272
  GATE_FAILED,
@@ -100808,7 +101355,7 @@ async function verifyRelease(options) {
100808
101355
  }
100809
101356
  let approvalRaw;
100810
101357
  try {
100811
- approvalRaw = await readFile27(sourceRun.approvalPath, "utf8");
101358
+ approvalRaw = await readFile29(sourceRun.approvalPath, "utf8");
100812
101359
  } catch (error) {
100813
101360
  throw new ReleaseError(
100814
101361
  GATE_FAILED,
@@ -100884,7 +101431,7 @@ async function verifyRelease(options) {
100884
101431
  const actions = plan.externalActions ?? [];
100885
101432
  const trustedVerifyRuns = [];
100886
101433
  const planDir = dirname14(planPath);
100887
- const releaseDir = basename9(planDir) === "plans" ? dirname14(planDir) : planDir;
101434
+ const releaseDir = basename10(planDir) === "plans" ? dirname14(planDir) : planDir;
100888
101435
  const runsDir = resolve27(releaseDir, "runs");
100889
101436
  let runsDirReal = null;
100890
101437
  let authorityDirReal = null;
@@ -100927,7 +101474,7 @@ async function verifyRelease(options) {
100927
101474
  runsDirReal = null;
100928
101475
  }
100929
101476
  if (runsDirReal) {
100930
- const entries = await readdir15(runsDirReal, { withFileTypes: true });
101477
+ const entries = await readdir16(runsDirReal, { withFileTypes: true });
100931
101478
  for (const entry of entries) {
100932
101479
  if (!entry.name.startsWith("verify-")) continue;
100933
101480
  if (!entry.isDirectory() || entry.isSymbolicLink()) {
@@ -101379,7 +101926,7 @@ async function verifyRelease(options) {
101379
101926
  assertTransition(PUBLISHED, VERIFIED);
101380
101927
  await evidence.append({ phase: "verify", status: "completed", overallStatus: VERIFIED });
101381
101928
  const sourceRunDigest = sourceRun.runDigest ?? computeRunDigest(sourceRun);
101382
- const verifyRunPath = join22(runDir, "release-run.json");
101929
+ const verifyRunPath = join24(runDir, "release-run.json");
101383
101930
  const verifyRunState = {
101384
101931
  runId,
101385
101932
  command: "verify",
@@ -101421,11 +101968,24 @@ async function verifyRelease(options) {
101421
101968
  finishedAt: clockFn()
101422
101969
  };
101423
101970
  const persistedVerifyRun = await writeRunAtomic(verifyRunPath, verifyRunState);
101971
+ try {
101972
+ const removed = await clearFrozenMarker(join24(root, ".release-skill"));
101973
+ await evidence.append({
101974
+ phase: "frozen-marker",
101975
+ status: removed ? "cleared" : "absent"
101976
+ });
101977
+ } catch (err) {
101978
+ await evidence.append({
101979
+ phase: "frozen-marker",
101980
+ status: "clear-failed",
101981
+ error: { code: err.code, message: err.message }
101982
+ });
101983
+ }
101424
101984
  let baselineAdvance = null;
101425
101985
  const baselineAdvances = deriveBaselineAdvances(plan);
101426
101986
  if (baselineAdvances.length > 0) {
101427
101987
  try {
101428
- const configAbs = configPathOpt ? isAbsolute20(configPathOpt) ? configPathOpt : join22(root, configPathOpt) : join22(root, ".release-skill/project.yaml");
101988
+ const configAbs = configPathOpt ? isAbsolute20(configPathOpt) ? configPathOpt : join24(root, configPathOpt) : join24(root, ".release-skill/project.yaml");
101429
101989
  const cleanBefore = await isWorktreeFileClean({ root, filePath: configAbs, execFn });
101430
101990
  const applyResult = await applyBaselineAdvances({
101431
101991
  configPath: configAbs,
@@ -101508,6 +102068,7 @@ var init_verify = __esm({
101508
102068
  init_baseline_advance();
101509
102069
  await init_config();
101510
102070
  init_state_machine();
102071
+ init_frozen_marker();
101511
102072
  init_public_path();
101512
102073
  init_npm();
101513
102074
  init_verification_gates();
@@ -101549,8 +102110,8 @@ var init_verify = __esm({
101549
102110
  exec: execFile9,
101550
102111
  env: process.env
101551
102112
  });
101552
- const userConfig = join22(cwd, ".release-skill-npmrc");
101553
- await writeFile8(
102113
+ const userConfig = join24(cwd, ".release-skill-npmrc");
102114
+ await writeFile9(
101554
102115
  userConfig,
101555
102116
  `registry=${normalizedRegistry}/
101556
102117
  ${registryTokenKey(normalizedRegistry)}=${token}
@@ -101612,10 +102173,10 @@ __export(distribute_exports, {
101612
102173
  });
101613
102174
  import { execFile as execFileCb12 } from "node:child_process";
101614
102175
  import { promisify as promisify12 } from "node:util";
101615
- import { realpath as realpath19, lstat as lstat22, mkdir as mkdir19, readFile as readFile28, rm as rm11 } from "node:fs/promises";
102176
+ import { realpath as realpath19, lstat as lstat22, mkdir as mkdir19, readFile as readFile30, rm as rm11 } from "node:fs/promises";
101616
102177
  import { mkdtemp as mkdtemp8 } from "node:fs/promises";
101617
102178
  import { tmpdir as tmpdir5 } from "node:os";
101618
- import { isAbsolute as isAbsolute21, join as join23, relative as relative25, resolve as resolve28 } from "node:path";
102179
+ import { isAbsolute as isAbsolute21, join as join25, relative as relative25, resolve as resolve28 } from "node:path";
101619
102180
  function defaultClock6() {
101620
102181
  return (/* @__PURE__ */ new Date()).toISOString();
101621
102182
  }
@@ -101712,7 +102273,7 @@ async function distributeRelease(options) {
101712
102273
  const hookRunner = typeof runHookFn === "function" ? runHookFn : runHook;
101713
102274
  let planRaw;
101714
102275
  try {
101715
- planRaw = await readFile28(planPath, "utf8");
102276
+ planRaw = await readFile30(planPath, "utf8");
101716
102277
  } catch (err) {
101717
102278
  throw new ReleaseError(GATE_FAILED, `cannot read release plan: ${err.message}`, { planPath, cause: err.code });
101718
102279
  }
@@ -101746,7 +102307,7 @@ async function distributeRelease(options) {
101746
102307
  } else {
101747
102308
  await mkdir19(runDir, { recursive: true });
101748
102309
  }
101749
- const runPath = join23(runDir, "release-run.json");
102310
+ const runPath = join25(runDir, "release-run.json");
101750
102311
  const evidence = createEvidenceWriter({ runDir, command: "distribute", clock: clockFn });
101751
102312
  let lineageKnown = false;
101752
102313
  let sourceRunId = null;
@@ -101821,7 +102382,7 @@ async function distributeRelease(options) {
101821
102382
  await evidence.append({ phase: "safety-gate", gate: "approval-load", status: "started" });
101822
102383
  let approvalRaw;
101823
102384
  try {
101824
- approvalRaw = await readFile28(approvalPath, "utf8");
102385
+ approvalRaw = await readFile30(approvalPath, "utf8");
101825
102386
  } catch (err) {
101826
102387
  throw new ReleaseError(GATE_FAILED, `cannot read approval record: ${err.message}`, { approvalPath, cause: err.code });
101827
102388
  }
@@ -102041,8 +102602,8 @@ async function distributeRelease(options) {
102041
102602
  }
102042
102603
  await evidence.append({ phase: "worktree", status: "started", tagCommit: postPublish.tagCommit });
102043
102604
  try {
102044
- tmpBase = await mkdtemp8(join23(tmpdir5(), "release-skill-distribute-"));
102045
- worktreePath = join23(tmpBase, "worktree");
102605
+ tmpBase = await mkdtemp8(join25(tmpdir5(), "release-skill-distribute-"));
102606
+ worktreePath = join25(tmpBase, "worktree");
102046
102607
  await exec("git", ["-C", root, "worktree", "add", "--detach", worktreePath, postPublish.tagCommit]);
102047
102608
  } catch (err) {
102048
102609
  await evidence.append({ phase: "worktree", status: "failed", error: tail(err?.stderr ?? err?.message) });
@@ -102545,7 +103106,7 @@ var release_metadata_exports = {};
102545
103106
  __export(release_metadata_exports, {
102546
103107
  updatePreviousPublicBaselines: () => updatePreviousPublicBaselines
102547
103108
  });
102548
- import { lstat as lstat23, readFile as readFile29, rename as rename4, rm as rm12, writeFile as writeFile9 } from "node:fs/promises";
103109
+ import { lstat as lstat23, readFile as readFile31, rename as rename4, rm as rm12, writeFile as writeFile10 } from "node:fs/promises";
102549
103110
  import { resolve as resolve29 } from "node:path";
102550
103111
  function assertOid(value, label) {
102551
103112
  if (typeof value !== "string" || !/^[a-f0-9]{40,64}$/.test(value)) {
@@ -102561,8 +103122,8 @@ async function updatePreviousPublicBaselines(options = {}) {
102561
103122
  let configStat;
102562
103123
  try {
102563
103124
  [plan, configRaw, configStat] = await Promise.all([
102564
- readFile29(planPath, "utf8").then(JSON.parse),
102565
- readFile29(configPath, "utf8"),
103125
+ readFile31(planPath, "utf8").then(JSON.parse),
103126
+ readFile31(configPath, "utf8"),
102566
103127
  lstat23(configPath)
102567
103128
  ]);
102568
103129
  } catch (error) {
@@ -102624,7 +103185,7 @@ async function updatePreviousPublicBaselines(options = {}) {
102624
103185
  }
102625
103186
  const tempPath = `${configPath}.${process.pid}.${Date.now()}.tmp`;
102626
103187
  try {
102627
- await writeFile9(tempPath, nextRaw, {
103188
+ await writeFile10(tempPath, nextRaw, {
102628
103189
  encoding: "utf8",
102629
103190
  mode: configStat.mode & 511,
102630
103191
  flag: "wx"
@@ -102652,7 +103213,7 @@ var ship_exports = {};
102652
103213
  __export(ship_exports, {
102653
103214
  advanceShip: () => advanceShip
102654
103215
  });
102655
- import { readFile as readFile30, lstat as lstat24, mkdir as mkdir20, rename as rename5, rm as rm13, writeFile as writeFile10 } from "node:fs/promises";
103216
+ import { readFile as readFile32, lstat as lstat24, mkdir as mkdir20, rename as rename5, rm as rm13, writeFile as writeFile11 } from "node:fs/promises";
102656
103217
  import { dirname as dirname15, resolve as resolve30 } from "node:path";
102657
103218
  async function writeJsonAtomic(path15, value) {
102658
103219
  await mkdir20(dirname15(path15), { recursive: true });
@@ -102663,7 +103224,7 @@ async function writeJsonAtomic(path15, value) {
102663
103224
  stateDigest: sha256Hex(canonicalJson2(body))
102664
103225
  };
102665
103226
  try {
102666
- await writeFile10(temp, `${JSON.stringify(sealed, null, 2)}
103227
+ await writeFile11(temp, `${JSON.stringify(sealed, null, 2)}
102667
103228
  `, {
102668
103229
  encoding: "utf8",
102669
103230
  mode: 384,
@@ -102678,11 +103239,11 @@ async function writeJsonAtomic(path15, value) {
102678
103239
  }
102679
103240
  async function readState(path15) {
102680
103241
  try {
102681
- const stat9 = await lstat24(path15);
102682
- if (!stat9.isFile() || stat9.isSymbolicLink()) {
103242
+ const stat10 = await lstat24(path15);
103243
+ if (!stat10.isFile() || stat10.isSymbolicLink()) {
102683
103244
  throw new Error("ship state must be a regular non-symlink file");
102684
103245
  }
102685
- const state = JSON.parse(await readFile30(path15, "utf8"));
103246
+ const state = JSON.parse(await readFile32(path15, "utf8"));
102686
103247
  const { stateDigest, ...body } = state;
102687
103248
  if (typeof stateDigest !== "string" || stateDigest !== sha256Hex(canonicalJson2(body)) || body.statePath !== path15) {
102688
103249
  throw new Error("ship state digest or authority path does not match");
@@ -102755,7 +103316,7 @@ function publicState(state) {
102755
103316
  }
102756
103317
  async function buildApprovalSummary(planPath) {
102757
103318
  try {
102758
- const plan = JSON.parse(await readFile30(planPath, "utf8"));
103319
+ const plan = JSON.parse(await readFile32(planPath, "utf8"));
102759
103320
  const units = (plan.units ?? []).map((unit) => ({
102760
103321
  id: unit.id,
102761
103322
  targetVersion: unit.targetVersion ?? unit.version
@@ -102825,7 +103386,7 @@ async function advanceShip(options = {}, injected = {}) {
102825
103386
  });
102826
103387
  let transportPreflight = null;
102827
103388
  if (deps.preflightGitTransports) {
102828
- const frozenPlan = JSON.parse(await readFile30(prepared.planPath, "utf8"));
103389
+ const frozenPlan = JSON.parse(await readFile32(prepared.planPath, "utf8"));
102829
103390
  transportPreflight = await deps.preflightGitTransports(frozenPlan);
102830
103391
  process.env.RELEASE_SKILL_GIT_TRANSPORT = transportPreflight.transport;
102831
103392
  }
@@ -102909,7 +103470,7 @@ async function advanceShip(options = {}, injected = {}) {
102909
103470
  await writeJsonAtomic(statePath, state);
102910
103471
  }
102911
103472
  if (state.status === "PUBLISHED" || state.status === "NEEDS_MANUAL_ATTESTATIONS") {
102912
- const plan = JSON.parse(await readFile30(state.planPath, "utf8"));
103473
+ const plan = JSON.parse(await readFile32(state.planPath, "utf8"));
102913
103474
  const needsDistribution = plan.postPublish && plan.postPublish.targets && plan.postPublish.targets.length > 0;
102914
103475
  if (needsDistribution && deps.distributeRelease) {
102915
103476
  state.status = "DISTRIBUTING";
@@ -103571,8 +104132,8 @@ var attest_exports = {};
103571
104132
  __export(attest_exports, {
103572
104133
  recordManualAttestation: () => recordManualAttestation
103573
104134
  });
103574
- import { readFile as readFile31 } from "node:fs/promises";
103575
- import { resolve as resolve31, join as join24 } from "node:path";
104135
+ import { readFile as readFile33 } from "node:fs/promises";
104136
+ import { resolve as resolve31, join as join26 } from "node:path";
103576
104137
  async function validateInstalledConsumerClosure({
103577
104138
  root,
103578
104139
  platform,
@@ -103589,7 +104150,7 @@ async function validateInstalledConsumerClosure({
103589
104150
  ]);
103590
104151
  let plan;
103591
104152
  try {
103592
- plan = JSON.parse(await readFile31(planPath, "utf8"));
104153
+ plan = JSON.parse(await readFile33(planPath, "utf8"));
103593
104154
  } catch (error) {
103594
104155
  throw new ReleaseError(
103595
104156
  GATE_FAILED,
@@ -103660,10 +104221,10 @@ async function recordManualAttestation(options = {}, injected = {}) {
103660
104221
  throw new ReleaseError(MISSING_PARAMETERS, "attest requires --result <passed|failed>");
103661
104222
  }
103662
104223
  const authorityDir = resolve31(root, ".release-skill", descriptor.directory, plugin);
103663
- const requirementPath = join24(authorityDir, descriptor.requirementFile);
104224
+ const requirementPath = join26(authorityDir, descriptor.requirementFile);
103664
104225
  let requirement;
103665
104226
  try {
103666
- requirement = JSON.parse(await readFile31(requirementPath, "utf8"));
104227
+ requirement = JSON.parse(await readFile33(requirementPath, "utf8"));
103667
104228
  } catch (error) {
103668
104229
  throw new ReleaseError(
103669
104230
  GATE_FAILED,
@@ -103713,7 +104274,7 @@ async function recordManualAttestation(options = {}, injected = {}) {
103713
104274
  extraInstalledPaths: installBinding.extraInstalledPaths
103714
104275
  } : {}
103715
104276
  };
103716
- const attestationPath = join24(authorityDir, requirement.attestationFile);
104277
+ const attestationPath = join26(authorityDir, requirement.attestationFile);
103717
104278
  await writeEvidenceAtomic(attestationPath, receipt);
103718
104279
  return {
103719
104280
  command: "attest",
@@ -103747,9 +104308,9 @@ var init_attest = __esm({
103747
104308
  });
103748
104309
 
103749
104310
  // src/artifacts/policy.mjs
103750
- import { readFile as readFile32 } from "node:fs/promises";
103751
- import { join as join25 } from "node:path";
103752
- import { createHash as createHash15 } from "node:crypto";
104311
+ import { readFile as readFile34 } from "node:fs/promises";
104312
+ import { join as join27 } from "node:path";
104313
+ import { createHash as createHash16 } from "node:crypto";
103753
104314
  function validateArtifactPolicy(policy) {
103754
104315
  const ok = _validate(policy);
103755
104316
  if (!ok) {
@@ -103844,10 +104405,10 @@ async function parseSafeYamlWithinRoot(root, policyPath) {
103844
104405
  }
103845
104406
  throw err;
103846
104407
  }
103847
- const fullPath = join25(root, policyPath);
104408
+ const fullPath = join27(root, policyPath);
103848
104409
  let content;
103849
104410
  try {
103850
- content = await readFile32(fullPath, "utf8");
104411
+ content = await readFile34(fullPath, "utf8");
103851
104412
  } catch (err) {
103852
104413
  throw new ReleaseError(
103853
104414
  ARTIFACT_POLICY_INVALID,
@@ -103898,7 +104459,7 @@ function canonicalJson3(obj) {
103898
104459
  return JSON.stringify(obj, Object.keys(obj ?? {}).sort());
103899
104460
  }
103900
104461
  function sha256Hex2(data) {
103901
- return createHash15("sha256").update(data).digest("hex");
104462
+ return createHash16("sha256").update(data).digest("hex");
103902
104463
  }
103903
104464
  function compareProtection(previousLock, policy) {
103904
104465
  if (!previousLock || !Array.isArray(previousLock.artifactIds)) {
@@ -103958,14 +104519,14 @@ var init_policy = __esm({
103958
104519
  });
103959
104520
 
103960
104521
  // src/artifacts/entry.mjs
103961
- import { lstat as lstat25, readdir as readdir16, readFile as readFile33 } from "node:fs/promises";
103962
- import { join as join26 } from "node:path";
104522
+ import { lstat as lstat25, readdir as readdir17, readFile as readFile35 } from "node:fs/promises";
104523
+ import { join as join28 } from "node:path";
103963
104524
  import { promisify as promisify16 } from "node:util";
103964
104525
  import { execFile as execFile13 } from "node:child_process";
103965
- function statToGitMode(stat9) {
103966
- if (stat9.isDirectory()) return "040000";
103967
- if (stat9.isSymbolicLink()) return "120000";
103968
- const mode = stat9.mode & 511;
104526
+ function statToGitMode(stat10) {
104527
+ if (stat10.isDirectory()) return "040000";
104528
+ if (stat10.isSymbolicLink()) return "120000";
104529
+ const mode = stat10.mode & 511;
103969
104530
  const executable = (mode & 73) !== 0;
103970
104531
  return executable ? "100755" : "100644";
103971
104532
  }
@@ -103979,10 +104540,10 @@ async function gitHashObject(root, absPath) {
103979
104540
  }
103980
104541
  async function enumerateTreeEntries(root, dirPath, relBase) {
103981
104542
  const entries = [];
103982
- const items = await readdir16(dirPath, { withFileTypes: true });
104543
+ const items = await readdir17(dirPath, { withFileTypes: true });
103983
104544
  for (const item of items) {
103984
104545
  if (SKIP_DIRS2.has(item.name)) continue;
103985
- const absPath = join26(dirPath, item.name);
104546
+ const absPath = join28(dirPath, item.name);
103986
104547
  const relPath = relBase ? `${relBase}/${item.name}` : item.name;
103987
104548
  const st = await lstat25(absPath);
103988
104549
  if (st.isSymbolicLink()) {
@@ -104003,7 +104564,7 @@ async function enumerateTreeEntries(root, dirPath, relBase) {
104003
104564
  const subEntries = await enumerateTreeEntries(root, absPath, relPath);
104004
104565
  entries.push(...subEntries);
104005
104566
  } else {
104006
- const content = await readFile33(absPath);
104567
+ const content = await readFile35(absPath);
104007
104568
  entries.push(
104008
104569
  Object.freeze({
104009
104570
  path: relPath,
@@ -104033,7 +104594,7 @@ async function readEntry({ root, path: path15, source = "worktree" } = {}) {
104033
104594
  if (source !== "worktree") {
104034
104595
  throw new ReleaseError(PATH_UNSAFE, `unsupported readEntry source: ${source}`, { source });
104035
104596
  }
104036
- const absPath = join26(root, path15);
104597
+ const absPath = join28(root, path15);
104037
104598
  let st;
104038
104599
  try {
104039
104600
  st = await lstat25(absPath);
@@ -104066,7 +104627,7 @@ async function readEntry({ root, path: path15, source = "worktree" } = {}) {
104066
104627
  { path: path15, nlink: st.nlink }
104067
104628
  );
104068
104629
  }
104069
- const content = await readFile33(absPath);
104630
+ const content = await readFile35(absPath);
104070
104631
  return Object.freeze({
104071
104632
  kind: "regular",
104072
104633
  path: path15,
@@ -104330,8 +104891,8 @@ var init_graph = __esm({
104330
104891
  });
104331
104892
 
104332
104893
  // src/artifacts/producer-registry.mjs
104333
- import { readFile as readFile34, readdir as readdir17, stat as stat6, mkdir as mkdir21, writeFile as writeFile11, rm as rm14 } from "node:fs/promises";
104334
- import { join as join27 } from "node:path";
104894
+ import { readFile as readFile36, readdir as readdir18, stat as stat7, mkdir as mkdir21, writeFile as writeFile12, rm as rm14 } from "node:fs/promises";
104895
+ import { join as join29 } from "node:path";
104335
104896
  import { mkdtemp as mkdtemp9 } from "node:fs/promises";
104336
104897
  import { tmpdir as tmpdir6 } from "node:os";
104337
104898
  import { readFileSync as readFileSync13 } from "node:fs";
@@ -104351,7 +104912,7 @@ function collectStaticImports(filePath, visited = /* @__PURE__ */ new Set()) {
104351
104912
  const dir = abs.replace(/\/[^/]*$/, "");
104352
104913
  while ((match = importRe.exec(source)) !== null) {
104353
104914
  const spec = match[1];
104354
- let resolved = join27(dir, spec);
104915
+ let resolved = join29(dir, spec);
104355
104916
  if (!resolved.endsWith(".mjs")) resolved += ".mjs";
104356
104917
  results.push(...collectStaticImports(resolved, visited));
104357
104918
  }
@@ -104359,10 +104920,10 @@ function collectStaticImports(filePath, visited = /* @__PURE__ */ new Set()) {
104359
104920
  }
104360
104921
  async function createBuiltInProducerRegistry() {
104361
104922
  const producers = /* @__PURE__ */ new Map();
104362
- const lockfilePath = join27(new URL("../../..", import.meta.url).pathname, "pnpm-lock.yaml");
104923
+ const lockfilePath = join29(new URL("../../..", import.meta.url).pathname, "pnpm-lock.yaml");
104363
104924
  let lockfileBytes;
104364
104925
  try {
104365
- lockfileBytes = await readFile34(lockfilePath);
104926
+ lockfileBytes = await readFile36(lockfilePath);
104366
104927
  } catch {
104367
104928
  lockfileBytes = Buffer.from("");
104368
104929
  }
@@ -104379,7 +104940,7 @@ async function createBuiltInProducerRegistry() {
104379
104940
  const allModuleBytes = await Promise.all(
104380
104941
  allModulePaths.map(async (p) => {
104381
104942
  try {
104382
- return await readFile34(p);
104943
+ return await readFile36(p);
104383
104944
  } catch {
104384
104945
  return Buffer.from("");
104385
104946
  }
@@ -104396,16 +104957,16 @@ async function createBuiltInProducerRegistry() {
104396
104957
  }
104397
104958
  async function readDirEntries(dirPath, relBase = "") {
104398
104959
  const entries = [];
104399
- const items = await readdir17(dirPath, { withFileTypes: true });
104960
+ const items = await readdir18(dirPath, { withFileTypes: true });
104400
104961
  for (const item of items) {
104401
104962
  if (item.name === ".git") continue;
104402
- const absPath = join27(dirPath, item.name);
104963
+ const absPath = join29(dirPath, item.name);
104403
104964
  const relPath = relBase ? `${relBase}/${item.name}` : item.name;
104404
- const st = await stat6(absPath);
104965
+ const st = await stat7(absPath);
104405
104966
  if (st.isDirectory()) {
104406
104967
  entries.push(...await readDirEntries(absPath, relPath));
104407
104968
  } else {
104408
- const content = await readFile34(absPath);
104969
+ const content = await readFile36(absPath);
104409
104970
  entries.push(Object.freeze({
104410
104971
  path: relPath,
104411
104972
  type: "blob",
@@ -104422,13 +104983,13 @@ async function readDirEntries(dirPath, relBase = "") {
104422
104983
  async function materializeEntries(entries, dirPath) {
104423
104984
  for (const entry of entries) {
104424
104985
  if (!entry.path) continue;
104425
- const targetPath2 = join27(dirPath, entry.path);
104986
+ const targetPath2 = join29(dirPath, entry.path);
104426
104987
  if (entry.type === "tree" || entry.kind === "tree") {
104427
104988
  await mkdir21(targetPath2, { recursive: true });
104428
104989
  } else {
104429
- await mkdir21(join27(targetPath2, ".."), { recursive: true });
104990
+ await mkdir21(join29(targetPath2, ".."), { recursive: true });
104430
104991
  if (entry.content) {
104431
- await writeFile11(targetPath2, entry.content);
104992
+ await writeFile12(targetPath2, entry.content);
104432
104993
  }
104433
104994
  }
104434
104995
  }
@@ -104470,7 +105031,7 @@ async function runProducerClosure({
104470
105031
  graph,
104471
105032
  inputSnapshot,
104472
105033
  artifactIds,
104473
- tempRootFactory = /* @__PURE__ */ __name(async () => mkdtemp9(join27(tmpdir6(), "producer-")), "tempRootFactory")
105034
+ tempRootFactory = /* @__PURE__ */ __name(async () => mkdtemp9(join29(tmpdir6(), "producer-")), "tempRootFactory")
104474
105035
  } = {}) {
104475
105036
  const generatedSet = new Set(graph.topologicalOrder);
104476
105037
  for (const id of artifactIds) {
@@ -104507,9 +105068,9 @@ async function runProducerClosure({
104507
105068
  if (inputEntries) {
104508
105069
  const first = inputEntries[0];
104509
105070
  if (first && first.path) {
104510
- const absPath = first.path.startsWith("/") ? first.path : join27(process.cwd(), first.path);
105071
+ const absPath = first.path.startsWith("/") ? first.path : join29(process.cwd(), first.path);
104511
105072
  try {
104512
- const st = await stat6(absPath);
105073
+ const st = await stat7(absPath);
104513
105074
  if (st.isDirectory()) {
104514
105075
  inputPath = absPath;
104515
105076
  } else {
@@ -104600,13 +105161,13 @@ var init_producer_registry = __esm({
104600
105161
  // src/artifacts/git-authority.mjs
104601
105162
  import { promisify as promisify18 } from "node:util";
104602
105163
  import { execFile as execFile15 } from "node:child_process";
104603
- import { createHash as createHash16 } from "node:crypto";
105164
+ import { createHash as createHash17 } from "node:crypto";
104604
105165
  async function git(cwd, ...args2) {
104605
105166
  const { stdout } = await execFileAsync6("git", args2, { cwd, shell: false });
104606
105167
  return stdout.trim();
104607
105168
  }
104608
105169
  function sha256Hex3(data) {
104609
- return createHash16("sha256").update(data).digest("hex");
105170
+ return createHash17("sha256").update(data).digest("hex");
104610
105171
  }
104611
105172
  async function readRepositoryIdentity(root) {
104612
105173
  let gitDir;
@@ -104932,7 +105493,7 @@ var init_state = __esm({
104932
105493
  });
104933
105494
 
104934
105495
  // src/artifacts/artifact-plan.mjs
104935
- import { writeFile as writeFile12, mkdir as mkdir22, readFile as readFile35, rename as rename6, open as open9 } from "node:fs/promises";
105496
+ import { writeFile as writeFile13, mkdir as mkdir22, readFile as readFile37, rename as rename6, open as open9 } from "node:fs/promises";
104936
105497
  import { dirname as dirname16 } from "node:path";
104937
105498
  function assemblePlan({
104938
105499
  operation,
@@ -104962,7 +105523,7 @@ async function writePlan(plan, outputPath) {
104962
105523
  const content = JSON.stringify(plan, null, 2);
104963
105524
  const fh = await open9(tmpPath, "w");
104964
105525
  try {
104965
- await writeFile12(fh, content, "utf8");
105526
+ await writeFile13(fh, content, "utf8");
104966
105527
  await fh.sync();
104967
105528
  } finally {
104968
105529
  await fh.close();
@@ -105621,8 +106182,8 @@ var init_adoption = __esm({
105621
106182
  // src/artifacts/inspect.mjs
105622
106183
  import { promisify as promisify19 } from "node:util";
105623
106184
  import { execFile as execFile16 } from "node:child_process";
105624
- import { readdir as readdir18, stat as stat7, readFile as readFile36 } from "node:fs/promises";
105625
- import { join as join28 } from "node:path";
106185
+ import { readdir as readdir19, stat as stat8, readFile as readFile38 } from "node:fs/promises";
106186
+ import { join as join30 } from "node:path";
105626
106187
  async function hasNestedGitRoots(root) {
105627
106188
  try {
105628
106189
  const { stdout } = await execFileAsync7(
@@ -105632,10 +106193,10 @@ async function hasNestedGitRoots(root) {
105632
106193
  );
105633
106194
  const dirs = stdout.split("\n").filter((s) => s.length > 0);
105634
106195
  for (const dir of dirs) {
105635
- const absDir = join28(root, dir);
106196
+ const absDir = join30(root, dir);
105636
106197
  try {
105637
- const nestedGit = join28(absDir, ".git");
105638
- await stat7(nestedGit);
106198
+ const nestedGit = join30(absDir, ".git");
106199
+ await stat8(nestedGit);
105639
106200
  return true;
105640
106201
  } catch {
105641
106202
  }
@@ -105893,8 +106454,8 @@ var init_inspect = __esm({
105893
106454
  });
105894
106455
 
105895
106456
  // src/artifacts/resolution.mjs
105896
- import { mkdir as mkdir23, open as open10, readFile as readFile37, stat as stat8, lstat as lstat26, chmod as chmod4 } from "node:fs/promises";
105897
- import { join as join29, resolve as resolve32, relative as relative26, isAbsolute as isAbsolute22, basename as basename10 } from "node:path";
106457
+ import { mkdir as mkdir23, open as open10, readFile as readFile39, stat as stat9, lstat as lstat26, chmod as chmod4 } from "node:fs/promises";
106458
+ import { join as join31, resolve as resolve32, relative as relative26, isAbsolute as isAbsolute22, basename as basename11 } from "node:path";
105898
106459
  function decodeBuffer(value, label) {
105899
106460
  if (value == null) return null;
105900
106461
  if (Buffer.isBuffer(value)) return value;
@@ -105996,9 +106557,9 @@ function assertSafeArtifactId(id) {
105996
106557
  }
105997
106558
  async function assertNoSymlinksInPath(root, artifactId) {
105998
106559
  const levels = [
105999
- join29(root, ".release-skill"),
106000
- join29(root, ".release-skill", "resolution"),
106001
- join29(root, ".release-skill", "resolution", artifactId)
106560
+ join31(root, ".release-skill"),
106561
+ join31(root, ".release-skill", "resolution"),
106562
+ join31(root, ".release-skill", "resolution", artifactId)
106002
106563
  ];
106003
106564
  for (const dir of levels) {
106004
106565
  try {
@@ -106025,7 +106586,7 @@ async function assertSafeResolvedPath(root, artifactId, resolvedPath) {
106025
106586
  { resolvedPath, resolutionDir }
106026
106587
  );
106027
106588
  }
106028
- const filename = basename10(resolvedPath);
106589
+ const filename = basename11(resolvedPath);
106029
106590
  if (filename !== `${artifactId}.resolved`) {
106030
106591
  throw new ReleaseError(
106031
106592
  PATH_UNSAFE,
@@ -106177,13 +106738,13 @@ async function materializeResolution({
106177
106738
  const template = buildConflictTemplate(artifact.conflict ?? {}, decodedBuffers);
106178
106739
  const templateDigest = sha256Hex(template);
106179
106740
  await assertNoSymlinksInPath(root, artifactId);
106180
- const resolutionDir = join29(root, ".release-skill", "resolution", artifactId);
106741
+ const resolutionDir = join31(root, ".release-skill", "resolution", artifactId);
106181
106742
  await mkdir23(resolutionDir, { recursive: true, mode: 448 });
106182
- const dirStat = await stat8(resolutionDir);
106743
+ const dirStat = await stat9(resolutionDir);
106183
106744
  if ((dirStat.mode & 511) !== 448) {
106184
106745
  await chmod4(resolutionDir, 448);
106185
106746
  }
106186
- const resolvedPath = join29(resolutionDir, `${artifactId}.resolved`);
106747
+ const resolvedPath = join31(resolutionDir, `${artifactId}.resolved`);
106187
106748
  const fh = await open10(resolvedPath, "wx", 384);
106188
106749
  try {
106189
106750
  await fh.write(template, 0, template.length);
@@ -106225,7 +106786,7 @@ async function submitResolution({
106225
106786
  async function readAndValidateResolvedFile(resolvedPath) {
106226
106787
  let content;
106227
106788
  try {
106228
- content = await readFile37(resolvedPath);
106789
+ content = await readFile39(resolvedPath);
106229
106790
  } catch (err) {
106230
106791
  throw new ReleaseError(MISSING_PARAMETERS, `cannot read resolved file: ${err.message}`, { resolvedPath, cause: err.code });
106231
106792
  }
@@ -106393,8 +106954,8 @@ var artifacts_exports = {};
106393
106954
  __export(artifacts_exports, {
106394
106955
  runArtifactsCommand: () => runArtifactsCommand
106395
106956
  });
106396
- import { readFile as readFile38 } from "node:fs/promises";
106397
- import { join as join30 } from "node:path";
106957
+ import { readFile as readFile40 } from "node:fs/promises";
106958
+ import { join as join32 } from "node:path";
106398
106959
  async function runArtifactsCommand({ subcommand, args: args2, root } = {}) {
106399
106960
  if (!VALID_SUBCOMMANDS.has(subcommand)) {
106400
106961
  throw new ReleaseError(
@@ -106522,7 +107083,7 @@ async function handleAdopt({ args: args2, root }) {
106522
107083
  { subcommand: "adopt" }
106523
107084
  );
106524
107085
  }
106525
- const planRaw = await readFile38(planPath, "utf8");
107086
+ const planRaw = await readFile40(planPath, "utf8");
106526
107087
  const plan = JSON.parse(planRaw);
106527
107088
  if (expectedDigest && plan.planDigest !== expectedDigest) {
106528
107089
  throw new ReleaseError(
@@ -106537,7 +107098,7 @@ async function handleAdopt({ args: args2, root }) {
106537
107098
  if (artifact.path) {
106538
107099
  const entry = await readEntry({ root, path: artifact.path, source: "worktree" });
106539
107100
  if (entry.kind === "regular") {
106540
- const bytes = await readFile38(join30(root, artifact.path));
107101
+ const bytes = await readFile40(join32(root, artifact.path));
106541
107102
  currentEntries.set(artifact.id, Object.freeze({ ...entry, bytes, content: bytes }));
106542
107103
  } else {
106543
107104
  currentEntries.set(artifact.id, entry);
@@ -106602,7 +107163,7 @@ async function handleBootstrap({ args: args2, root }) {
106602
107163
  { subcommand: "bootstrap" }
106603
107164
  );
106604
107165
  }
106605
- const planRaw = await readFile38(planPath, "utf8");
107166
+ const planRaw = await readFile40(planPath, "utf8");
106606
107167
  const adoptionPlan = JSON.parse(planRaw);
106607
107168
  const currentEntries = /* @__PURE__ */ new Map();
106608
107169
  for (const id of new Set((adoptionPlan.protectedHunks ?? []).map((h) => h.artifactId))) {
@@ -106614,12 +107175,12 @@ async function handleBootstrap({ args: args2, root }) {
106614
107175
  if (entry.kind !== "regular") {
106615
107176
  throw new ReleaseError("PLAN_STALE", `artifact is no longer a regular file: ${id}`, { id });
106616
107177
  }
106617
- const bytes = await readFile38(join30(root, artifactPath));
107178
+ const bytes = await readFile40(join32(root, artifactPath));
106618
107179
  currentEntries.set(id, Object.freeze({ ...entry, bytes, content: bytes }));
106619
107180
  }
106620
107181
  let replacementBytes;
106621
107182
  if (action === "replace" && replacementPath) {
106622
- replacementBytes = await readFile38(replacementPath);
107183
+ replacementBytes = await readFile40(replacementPath);
106623
107184
  }
106624
107185
  const updated = await discardBootstrapHunk({
106625
107186
  adoptionPlan,
@@ -106657,7 +107218,7 @@ async function handleResolve({ args: args2, root }) {
106657
107218
  { subcommand: "resolve" }
106658
107219
  );
106659
107220
  }
106660
- const planRaw = await readFile38(planPath, "utf8");
107221
+ const planRaw = await readFile40(planPath, "utf8");
106661
107222
  const plan = JSON.parse(planRaw);
106662
107223
  if (plan.planDigest !== expectedDigest) {
106663
107224
  throw new ReleaseError(
@@ -107038,13 +107599,14 @@ __export(lineage_exports, {
107038
107599
  listReleaseTags: () => listReleaseTags,
107039
107600
  objectExists: () => objectExists,
107040
107601
  parseArgs: () => parseArgs,
107602
+ parseCommitIdent: () => parseCommitIdent,
107041
107603
  parseReleaseTag: () => parseReleaseTag,
107042
107604
  parseSemverVersion: () => parseSemverVersion2,
107043
107605
  readCommitMeta: () => readCommitMeta,
107044
107606
  rebuildLineage: () => rebuildLineage,
107045
107607
  runLineageCommand: () => runLineageCommand
107046
107608
  });
107047
- import { execFile as execFileCb16 } from "node:child_process";
107609
+ import { execFile as execFileCb16, spawn as spawn4 } from "node:child_process";
107048
107610
  import { promisify as promisify20 } from "node:util";
107049
107611
  function parseSemverVersion2(version) {
107050
107612
  if (typeof version !== "string") {
@@ -107098,6 +107660,26 @@ async function git2(root, args2, options = {}) {
107098
107660
  });
107099
107661
  return stdout.trim();
107100
107662
  }
107663
+ async function gitRaw(root, args2, options = {}) {
107664
+ const { stdout } = await execFile17("git", args2, {
107665
+ cwd: root,
107666
+ encoding: "utf8",
107667
+ maxBuffer: 64 * 1024 * 1024,
107668
+ ...options
107669
+ });
107670
+ return stdout;
107671
+ }
107672
+ function parseCommitIdent(line) {
107673
+ if (typeof line !== "string") {
107674
+ throw new Error(`commit ident line must be a string, got ${typeof line}`);
107675
+ }
107676
+ const match = line.match(/^(.*) <([^>]*)> (\d+) ([+-]\d{4})$/);
107677
+ if (!match) {
107678
+ throw new Error(`unparseable commit ident line (fail-closed): "${line}"`);
107679
+ }
107680
+ const [, name, email, ts, tz] = match;
107681
+ return { name, email, ts, tz };
107682
+ }
107101
107683
  async function getLocalTags(root) {
107102
107684
  const output = await git2(root, ["tag", "-l", "--format=%(refname:short) %(objectname)"]);
107103
107685
  if (!output) return [];
@@ -107130,40 +107712,32 @@ async function objectExists(root, sha) {
107130
107712
  }
107131
107713
  }
107132
107714
  async function readCommitMeta(root, commitSha) {
107133
- const raw = await git2(root, ["cat-file", "commit", commitSha]);
107134
- const lines = raw.split("\n");
107135
- const headers = {};
107136
- const messageLines = [];
107137
- let inBody = false;
107138
- for (const line of lines) {
107139
- if (inBody) {
107140
- messageLines.push(line);
107141
- continue;
107142
- }
107143
- if (line === "") {
107144
- inBody = true;
107145
- continue;
107146
- }
107147
- const colon = line.indexOf(" ");
107148
- if (colon === -1) continue;
107149
- const key = line.slice(0, colon);
107150
- const value = line.slice(colon + 1);
107151
- headers[key] = value;
107715
+ const raw = await gitRaw(root, ["cat-file", "commit", commitSha]);
107716
+ const separator = raw.indexOf("\n\n");
107717
+ if (separator === -1) {
107718
+ throw new Error(`malformed commit object ${commitSha}: missing header/message separator`);
107152
107719
  }
107153
- const message = messageLines.join("\n");
107154
- const authorParts = (headers.author ?? "").split(/\s+>/);
107155
- const committerParts = (headers.committer ?? "").split(/\s+>/);
107720
+ const message = raw.slice(separator + 2);
107721
+ const headers = {};
107722
+ for (const line of raw.slice(0, separator).split("\n")) {
107723
+ if (line.startsWith(" ")) continue;
107724
+ const space = line.indexOf(" ");
107725
+ if (space === -1) continue;
107726
+ headers[line.slice(0, space)] = line.slice(space + 1);
107727
+ }
107728
+ const author = parseCommitIdent(headers.author ?? "");
107729
+ const committer = parseCommitIdent(headers.committer ?? "");
107156
107730
  return {
107157
107731
  message,
107158
107732
  author: {
107159
- name: authorParts[0] ?? "",
107160
- email: (authorParts[1] ?? "").replace(/^</, "").replace(/\d+ [+-]\d{4}$/, "").trim(),
107161
- date: (headers.author ?? "").match(/(\d+ [+-]\d{4})$/)?.[1] ?? ""
107733
+ name: author.name,
107734
+ email: author.email,
107735
+ date: `${author.ts} ${author.tz}`
107162
107736
  },
107163
107737
  committer: {
107164
- name: committerParts[0] ?? "",
107165
- email: (committerParts[1] ?? "").replace(/^</, "").replace(/\d+ [+-]\d{4}$/, "").trim(),
107166
- date: (headers.committer ?? "").match(/(\d+ [+-]\d{4})$/)?.[1] ?? ""
107738
+ name: committer.name,
107739
+ email: committer.email,
107740
+ date: `${committer.ts} ${committer.tz}`
107167
107741
  }
107168
107742
  };
107169
107743
  }
@@ -107248,7 +107822,7 @@ async function analyzeLineage(root) {
107248
107822
  async function createRebuiltCommit(root, treeSha, parentSha, message, identity2) {
107249
107823
  const args2 = ["commit-tree", treeSha];
107250
107824
  if (parentSha) args2.push("-p", parentSha);
107251
- args2.push("-m", message);
107825
+ args2.push("-F", "-");
107252
107826
  const env = {
107253
107827
  ...process.env,
107254
107828
  GIT_AUTHOR_NAME: identity2.author.name,
@@ -107258,8 +107832,31 @@ async function createRebuiltCommit(root, treeSha, parentSha, message, identity2)
107258
107832
  GIT_COMMITTER_EMAIL: identity2.committer.email,
107259
107833
  GIT_COMMITTER_DATE: identity2.committer.date
107260
107834
  };
107261
- const { stdout } = await execFile17("git", args2, { cwd: root, encoding: "utf8", env });
107262
- return stdout.trim();
107835
+ return new Promise((resolvePromise, rejectPromise) => {
107836
+ const child = spawn4("git", args2, { cwd: root, env });
107837
+ let stdout = "";
107838
+ let stderr = "";
107839
+ child.stdout.setEncoding("utf8");
107840
+ child.stderr.setEncoding("utf8");
107841
+ child.stdout.on("data", (chunk) => {
107842
+ stdout += chunk;
107843
+ });
107844
+ child.stderr.on("data", (chunk) => {
107845
+ stderr += chunk;
107846
+ });
107847
+ child.on("error", rejectPromise);
107848
+ child.on("close", (code) => {
107849
+ if (code !== 0) {
107850
+ rejectPromise(new Error(`git commit-tree failed (exit ${code}): ${stderr.trim()}`));
107851
+ return;
107852
+ }
107853
+ resolvePromise(stdout.trim());
107854
+ });
107855
+ child.stdin.on("error", () => {
107856
+ });
107857
+ child.stdin.write(message);
107858
+ child.stdin.end();
107859
+ });
107263
107860
  }
107264
107861
  async function rebuildLineage(root, options = {}) {
107265
107862
  const { dryRun = false } = options;
@@ -107386,6 +107983,8 @@ var init_lineage = __esm({
107386
107983
  __name(compareSemverVersions2, "compareSemverVersions");
107387
107984
  __name(parseReleaseTag, "parseReleaseTag");
107388
107985
  __name(git2, "git");
107986
+ __name(gitRaw, "gitRaw");
107987
+ __name(parseCommitIdent, "parseCommitIdent");
107389
107988
  __name(getLocalTags, "getLocalTags");
107390
107989
  __name(listReleaseTags, "listReleaseTags");
107391
107990
  __name(getCommitTreeHash, "getCommitTreeHash");
@@ -107436,7 +108035,7 @@ __export(route_exports, {
107436
108035
  resolvePreviousReleaseCommit: () => resolvePreviousReleaseCommit
107437
108036
  });
107438
108037
  import { execFileSync } from "node:child_process";
107439
- import { readdir as readdir19, readFile as readFile39 } from "node:fs/promises";
108038
+ import { readdir as readdir20, readFile as readFile41 } from "node:fs/promises";
107440
108039
  import { resolve as resolve33 } from "node:path";
107441
108040
  function classifyPath(path15) {
107442
108041
  if (typeof path15 !== "string" || path15.length === 0) return "ignore";
@@ -107517,13 +108116,13 @@ async function resolvePreviousReleaseCommit(root) {
107517
108116
  const cwd = resolve33(root);
107518
108117
  try {
107519
108118
  const plansDir = resolve33(cwd, ".release-skill", "plans");
107520
- const planFiles = await readdir19(plansDir).catch(() => []);
108119
+ const planFiles = await readdir20(plansDir).catch(() => []);
107521
108120
  let best = null;
107522
108121
  for (const file of planFiles) {
107523
108122
  if (!file.endsWith(".json")) continue;
107524
108123
  let plan;
107525
108124
  try {
107526
- plan = JSON.parse(await readFile39(resolve33(plansDir, file), "utf8"));
108125
+ plan = JSON.parse(await readFile41(resolve33(plansDir, file), "utf8"));
107527
108126
  } catch {
107528
108127
  continue;
107529
108128
  }
@@ -107607,14 +108206,14 @@ async function hasPartialRun(root) {
107607
108206
  const runsDir = resolve33(cwd, ".release-skill", "runs");
107608
108207
  let runDirs;
107609
108208
  try {
107610
- runDirs = await readdir19(runsDir);
108209
+ runDirs = await readdir20(runsDir);
107611
108210
  } catch {
107612
108211
  return false;
107613
108212
  }
107614
108213
  for (const runDir of runDirs) {
107615
108214
  const summaryPath = resolve33(runsDir, runDir, "summary.json");
107616
108215
  try {
107617
- const summary = JSON.parse(await readFile39(summaryPath, "utf8"));
108216
+ const summary = JSON.parse(await readFile41(summaryPath, "utf8"));
107618
108217
  if (summary?.status === "PARTIAL") return true;
107619
108218
  } catch {
107620
108219
  }
@@ -107899,7 +108498,7 @@ Workflow Profiles:
107899
108498
  });
107900
108499
 
107901
108500
  // bin/release-skill-cli.mjs
107902
- import { basename as basename11, dirname as dirname17, join as join31, resolve as resolve34 } from "node:path";
108501
+ import { basename as basename12, dirname as dirname17, join as join33, resolve as resolve34 } from "node:path";
107903
108502
  import { execFile as execFileCb17 } from "node:child_process";
107904
108503
  import { promisify as promisify21 } from "node:util";
107905
108504
 
@@ -108133,6 +108732,9 @@ Options:
108133
108732
  deterministically trim code-class gates (declared hooks, snapshot-verify gates,
108134
108733
  source-authority closure, skill-resource-closure) and record workflowDecision in the plan;
108135
108734
  config also reports whether the public bytes are unchanged (no publish path)
108735
+ --test-selection <full|incremental> Test selection for the test hook (prepare). Only 'full' is accepted at
108736
+ freeze time; 'incremental' is reserved for a future preflight mode and is rejected
108737
+ ('incremental selection is not allowed at freeze time')
108136
108738
  --answers <path> Human-reviewed setup answers JSON
108137
108739
  --write Create an absent project.yaml during setup; never overwrites
108138
108740
  --confirm-setup <digest> Confirm exact setup facts and answers before create
@@ -108185,7 +108787,7 @@ if (!command && (args.includes("--version") || args.includes("-v"))) {
108185
108787
  } else {
108186
108788
  const { readFileSync: readFileSync14 } = await import("node:fs");
108187
108789
  const { fileURLToPath: fileURLToPath3 } = await import("node:url");
108188
- const pkgPath = join31(dirname17(fileURLToPath3(import.meta.url)), "..", "package.json");
108790
+ const pkgPath = join33(dirname17(fileURLToPath3(import.meta.url)), "..", "package.json");
108189
108791
  pkg = JSON.parse(readFileSync14(pkgPath, "utf8"));
108190
108792
  }
108191
108793
  if (hasJson) {
@@ -108525,6 +109127,8 @@ if (command === "prepare") {
108525
109127
  const production = args.includes("--production");
108526
109128
  const workflowIdx = args.indexOf("--workflow");
108527
109129
  const workflow = workflowIdx !== -1 && args[workflowIdx + 1] ? args[workflowIdx + 1] : "full";
109130
+ const testSelectionIdx = args.indexOf("--test-selection");
109131
+ const testSelection = testSelectionIdx !== -1 && args[testSelectionIdx + 1] ? args[testSelectionIdx + 1] : void 0;
108528
109132
  const outputIdx = args.indexOf("--output");
108529
109133
  const output = outputIdx !== -1 && args[outputIdx + 1] ? resolve34(args[outputIdx + 1]) : void 0;
108530
109134
  const runDirIdx = args.indexOf("--run-dir");
@@ -108541,6 +109145,7 @@ if (command === "prepare") {
108541
109145
  hookCache,
108542
109146
  production,
108543
109147
  workflow,
109148
+ testSelection,
108544
109149
  output,
108545
109150
  runDir
108546
109151
  });
@@ -108630,8 +109235,8 @@ if (command === "approve") {
108630
109235
  }
108631
109236
  const resolvedPlanPath = resolve34(planPath);
108632
109237
  const planDir = dirname17(resolvedPlanPath);
108633
- const releaseDir = basename11(planDir) === "plans" && basename11(resolvedPlanPath) === `${resolvedDigest}.json` ? dirname17(planDir) : planDir;
108634
- const approvalPath = outputPath ?? join31(releaseDir, "approval-record.json");
109238
+ const releaseDir = basename12(planDir) === "plans" && basename12(resolvedPlanPath) === `${resolvedDigest}.json` ? dirname17(planDir) : planDir;
109239
+ const approvalPath = outputPath ?? join33(releaseDir, "approval-record.json");
108635
109240
  const record = await approvePlan2({ planPath, expectedDigest: resolvedDigest, actor, outputPath: approvalPath });
108636
109241
  if (hasJson) {
108637
109242
  console.log(JSON.stringify(record, null, 2));