release-skill 0.6.0 → 0.6.1

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 (36) 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 +14 -0
  7. package/INSTALL.md +2 -2
  8. package/INSTALL.zh-CN.md +2 -2
  9. package/README.md +9 -8
  10. package/README.zh-CN.md +9 -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 +705 -356
  14. package/adapters/claude/schemas/release-project.schema.json +8 -0
  15. package/adapters/codex/.codex-plugin/plugin.json +2 -2
  16. package/adapters/codex/bin/release-skill.bundle.mjs +705 -356
  17. package/adapters/codex/schemas/release-project.schema.json +8 -0
  18. package/adapters/kimi/.kimi-plugin/plugin.json +1 -1
  19. package/adapters/kimi/bin/release-skill.bundle.mjs +705 -356
  20. package/adapters/kimi/schemas/release-project.schema.json +8 -0
  21. package/adapters/workbuddy/.codebuddy-plugin/plugin.json +1 -1
  22. package/adapters/workbuddy/bin/release-skill.bundle.mjs +705 -356
  23. package/adapters/workbuddy/schemas/release-project.schema.json +8 -0
  24. package/bin/release-skill-cli.mjs +11 -0
  25. package/bin/release-skill.bundle.mjs +705 -356
  26. package/package.json +1 -1
  27. package/references/05-evidence-and-errors.md +1 -0
  28. package/schemas/release-project.schema.json +8 -0
  29. package/scripts/build-bundle.mjs +11 -2
  30. package/scripts/sync-public-files.mjs +4 -0
  31. package/src/commands/prepare.mjs +214 -8
  32. package/src/commands/verify.mjs +22 -0
  33. package/src/core/bundle-freshness.mjs +236 -0
  34. package/src/core/errors.mjs +2 -0
  35. package/src/core/frozen-marker.mjs +97 -0
  36. package/src/core/hooks.mjs +12 -1
@@ -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.1"});
13
+ // Build-time source digest for the BUNDLE_STALE freshness gate (see above).
14
+ const __bundleSourceDigest = "c51fa1df96e9ef06d5310a990e6ce2366e4878332d646b034842d0deaec549d4";
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);
@@ -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.1" });
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",
@@ -37362,8 +37367,8 @@ function safeRelative(root, path15) {
37362
37367
  return rel || ".";
37363
37368
  }
37364
37369
  async function readJsonBounded(path15, label) {
37365
- const stat9 = await lstat11(path15);
37366
- if (!stat9.isFile() || stat9.isSymbolicLink() || stat9.size > MAX_JSON_BYTES) {
37370
+ const stat10 = await lstat11(path15);
37371
+ if (!stat10.isFile() || stat10.isSymbolicLink() || stat10.size > MAX_JSON_BYTES) {
37367
37372
  throw setupError(CONFIG_INVALID, `${label} must be a regular JSON file no larger than 1 MiB`, { path: path15 });
37368
37373
  }
37369
37374
  try {
@@ -37625,14 +37630,14 @@ async function pathIsGitIgnored(unitAbsDir, target) {
37625
37630
  async function classifyNpmEntryCandidate(unitAbsDir, target, trackedFiles) {
37626
37631
  const tracked = trackedFiles.includes(target);
37627
37632
  const ignored = await pathIsGitIgnored(unitAbsDir, target);
37628
- let stat9 = null;
37633
+ let stat10 = null;
37629
37634
  try {
37630
- stat9 = await lstat11(join8(unitAbsDir, target));
37635
+ stat10 = await lstat11(join8(unitAbsDir, target));
37631
37636
  } catch (error) {
37632
37637
  if (error.code !== "ENOENT") throw error;
37633
37638
  }
37634
- const exists = stat9 !== null;
37635
- const regular = stat9?.isFile() === true && stat9?.isSymbolicLink() !== true;
37639
+ const exists = stat10 !== null;
37640
+ const regular = stat10?.isFile() === true && stat10?.isSymbolicLink() !== true;
37636
37641
  const state = exists && !regular ? "NON_REGULAR" : exists && tracked ? "TRACKED_PRESENT" : exists && ignored ? "IGNORED_PRESENT" : exists ? "UNTRACKED_PRESENT" : ignored ? "IGNORED_MISSING" : "MISSING";
37637
37642
  return { path: target, state, exists, tracked, ignored };
37638
37643
  }
@@ -38524,9 +38529,9 @@ async function setupProject({ root, answersPath, write = false, confirmSetup, fa
38524
38529
  const configPath = join8(rootReal, ".release-skill", "project.yaml");
38525
38530
  let configExists = false;
38526
38531
  try {
38527
- const stat9 = await lstat11(configPath);
38532
+ const stat10 = await lstat11(configPath);
38528
38533
  configExists = true;
38529
- if (!stat9.isFile() || stat9.isSymbolicLink()) {
38534
+ if (!stat10.isFile() || stat10.isSymbolicLink()) {
38530
38535
  throw setupError(CONFIG_INVALID, "existing project.yaml must be a regular file");
38531
38536
  }
38532
38537
  } catch (error) {
@@ -39064,9 +39069,9 @@ async function assertSafeDirectoryPath({
39064
39069
  let cursor = workspaceRoot;
39065
39070
  for (const segment of rel.split(sep3).filter(Boolean)) {
39066
39071
  cursor = join9(cursor, segment);
39067
- let stat9;
39072
+ let stat10;
39068
39073
  try {
39069
- stat9 = await lstat12(cursor);
39074
+ stat10 = await lstat12(cursor);
39070
39075
  } catch (error) {
39071
39076
  failConfig(`cannot inspect public surface scan root "${configuredRoot}"`, {
39072
39077
  reason: "PUBLIC_SURFACE_SCAN_ROOT_UNSAFE",
@@ -39075,7 +39080,7 @@ async function assertSafeDirectoryPath({
39075
39080
  cause: error.code ?? "UNKNOWN"
39076
39081
  });
39077
39082
  }
39078
- if (stat9.isSymbolicLink() || !stat9.isDirectory()) {
39083
+ if (stat10.isSymbolicLink() || !stat10.isDirectory()) {
39079
39084
  failConfig(`public surface scan root or ancestor is not a physical directory: "${configuredRoot}"`, {
39080
39085
  reason: "PUBLIC_SURFACE_SCAN_ROOT_UNSAFE",
39081
39086
  unitId,
@@ -39462,24 +39467,24 @@ async function computeWorkspaceDigest(root) {
39462
39467
  `Refusing to read path outside repository root: ${relPath} resolves to ${absPath}`
39463
39468
  );
39464
39469
  }
39465
- const stat9 = await lstat13(absPath);
39470
+ const stat10 = await lstat13(absPath);
39466
39471
  let type;
39467
- if (stat9.isSymbolicLink()) {
39472
+ if (stat10.isSymbolicLink()) {
39468
39473
  type = "symlink";
39469
- } else if (stat9.isDirectory()) {
39474
+ } else if (stat10.isDirectory()) {
39470
39475
  type = "dir";
39471
- } else if (stat9.isFile()) {
39476
+ } else if (stat10.isFile()) {
39472
39477
  type = "file";
39473
39478
  } else {
39474
39479
  type = "other";
39475
39480
  }
39476
39481
  const typeMarker = `TYPE:${type}`;
39477
39482
  let content;
39478
- if (stat9.isFile()) {
39483
+ if (stat10.isFile()) {
39479
39484
  const handle = await open6(absPath, fsConstants2.O_RDONLY | fsConstants2.O_NOFOLLOW);
39480
39485
  try {
39481
39486
  const fdStat = await handle.stat();
39482
- if (fdStat.ino !== stat9.ino) {
39487
+ if (fdStat.ino !== stat10.ino) {
39483
39488
  throw new Error(
39484
39489
  `Race detected: inode changed for ${relPath} between lstat and read`
39485
39490
  );
@@ -39494,7 +39499,7 @@ async function computeWorkspaceDigest(root) {
39494
39499
  } finally {
39495
39500
  await handle.close();
39496
39501
  }
39497
- } else if (stat9.isSymbolicLink()) {
39502
+ } else if (stat10.isSymbolicLink()) {
39498
39503
  content = Buffer.from(await readlink(absPath), "utf8");
39499
39504
  } else {
39500
39505
  content = Buffer.alloc(0);
@@ -40908,7 +40913,7 @@ function validateHook(hook) {
40908
40913
  if (!hook || typeof hook !== "object" || Array.isArray(hook)) {
40909
40914
  throw new ReleaseError("INVALID_HOOK", "hook must be a non-null object");
40910
40915
  }
40911
- const { command: command2, cwd, timeoutMs, envAllowlist, cacheable, cacheInputs } = hook;
40916
+ const { command: command2, cwd, timeoutMs, envAllowlist, cacheable, cacheInputs, testSelection } = hook;
40912
40917
  if (!Array.isArray(command2) || command2.length === 0) {
40913
40918
  throw new ReleaseError("INVALID_HOOK", "hook.command must be a non-empty array");
40914
40919
  }
@@ -40963,6 +40968,12 @@ function validateHook(hook) {
40963
40968
  "hook.cacheable=true requires a non-empty hook.cacheInputs"
40964
40969
  );
40965
40970
  }
40971
+ if (testSelection !== void 0 && testSelection !== "full" && testSelection !== "incremental") {
40972
+ throw new ReleaseError(
40973
+ "INVALID_HOOK",
40974
+ 'hook.testSelection must be "full" or "incremental" when provided'
40975
+ );
40976
+ }
40966
40977
  }
40967
40978
  function buildFilteredEnv(envAllowlist, contextEnv) {
40968
40979
  const env = {};
@@ -41279,10 +41290,10 @@ async function resolveSafeCwd(executionRoot, cwd, gate) {
41279
41290
  let current = rootReal;
41280
41291
  for (const segment of rel.split(/[\\/]/).filter(Boolean)) {
41281
41292
  current = join11(current, segment);
41282
- const stat9 = await lstat14(current).catch((error) => {
41293
+ const stat10 = await lstat14(current).catch((error) => {
41283
41294
  throw gateError(gate, "cwd does not exist", { cause: error.code });
41284
41295
  });
41285
- if (stat9.isSymbolicLink()) throw gateError(gate, "cwd contains a symlink");
41296
+ if (stat10.isSymbolicLink()) throw gateError(gate, "cwd contains a symlink");
41286
41297
  }
41287
41298
  const physical = await realpath12(lexical);
41288
41299
  if (!isInside2(rootReal, physical)) throw gateError(gate, "cwd resolves outside the execution root");
@@ -41523,9 +41534,9 @@ async function runVerificationGate({
41523
41534
  return result;
41524
41535
  }
41525
41536
  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);
41537
+ const stat10 = await lstat14(root);
41538
+ if (!stat10.isDirectory() || stat10.isSymbolicLink()) throw new Error("gate copy root must be a real directory");
41539
+ await chmod2(root, stat10.mode | 448);
41529
41540
  for (const child of await readdir7(root, { withFileTypes: true })) {
41530
41541
  const absolute = join11(root, child.name);
41531
41542
  const childStat = await lstat14(absolute);
@@ -41780,14 +41791,14 @@ async function inspectRegularFile(root, target) {
41780
41791
  }
41781
41792
  for (const part of parts) {
41782
41793
  current = join12(current, part);
41783
- let stat9;
41794
+ let stat10;
41784
41795
  try {
41785
- stat9 = await lstat15(current);
41796
+ stat10 = await lstat15(current);
41786
41797
  } catch (error) {
41787
41798
  if (error.code === "ENOENT") return { code: FINDING_CODE.RESOURCE_MISSING };
41788
41799
  throw error;
41789
41800
  }
41790
- if (stat9.isSymbolicLink()) return { code: FINDING_CODE.SYMLINK_NOT_ALLOWED };
41801
+ if (stat10.isSymbolicLink()) return { code: FINDING_CODE.SYMLINK_NOT_ALLOWED };
41791
41802
  }
41792
41803
  const targetStat = await lstat15(target);
41793
41804
  if (!targetStat.isFile() || targetStat.nlink !== 1) {
@@ -43575,11 +43586,182 @@ var init_contract2 = __esm({
43575
43586
  }
43576
43587
  });
43577
43588
 
43589
+ // src/core/bundle-freshness.mjs
43590
+ import { readFile as readFile16, readdir as readdir11, stat as stat4 } from "node:fs/promises";
43591
+ import { join as join14 } from "node:path";
43592
+ import { createHash as createHash13 } from "node:crypto";
43593
+ function bundlePathFor(pkgRoot) {
43594
+ return join14(pkgRoot, BUNDLE_RELPATH);
43595
+ }
43596
+ async function listFilesSorted(dir, prefix = "") {
43597
+ const entries = await readdir11(dir, { withFileTypes: true });
43598
+ const files = [];
43599
+ for (const entry of entries.sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0)) {
43600
+ const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
43601
+ if (entry.isDirectory()) {
43602
+ files.push(...await listFilesSorted(join14(dir, entry.name), rel));
43603
+ } else if (entry.isFile()) {
43604
+ files.push(rel);
43605
+ }
43606
+ }
43607
+ return files;
43608
+ }
43609
+ async function listBundleSourceInputs(pkgRoot) {
43610
+ const inputs = [];
43611
+ for (const dir of SOURCE_DIRS) {
43612
+ const abs = join14(pkgRoot, dir);
43613
+ const st = await stat4(abs).catch(() => null);
43614
+ if (st?.isDirectory()) {
43615
+ for (const rel of await listFilesSorted(abs)) {
43616
+ inputs.push(`${dir}/${rel}`);
43617
+ }
43618
+ }
43619
+ }
43620
+ for (const rel of SOURCE_FILES) {
43621
+ const st = await stat4(join14(pkgRoot, rel)).catch(() => null);
43622
+ if (st?.isFile()) {
43623
+ inputs.push(rel.split(/[\\/]/).join("/"));
43624
+ }
43625
+ }
43626
+ return inputs.sort();
43627
+ }
43628
+ async function computeBundleSourceDigest(pkgRoot) {
43629
+ const inputs = await listBundleSourceInputs(pkgRoot);
43630
+ const hash = createHash13("sha256");
43631
+ hash.update(BUNDLE_SOURCE_DIGEST_ALGORITHM);
43632
+ hash.update("\n");
43633
+ for (const rel of inputs) {
43634
+ const content = await readFile16(join14(pkgRoot, rel));
43635
+ hash.update(rel);
43636
+ hash.update("\0");
43637
+ hash.update(createHash13("sha256").update(content).digest("hex"));
43638
+ hash.update("\n");
43639
+ }
43640
+ return hash.digest("hex");
43641
+ }
43642
+ async function readEmbeddedBundleDigest(bundlePath) {
43643
+ let content;
43644
+ try {
43645
+ content = await readFile16(bundlePath, "utf8");
43646
+ } catch {
43647
+ return null;
43648
+ }
43649
+ const match = content.match(EMBEDDED_DIGEST_PATTERN);
43650
+ return match ? match[1] : null;
43651
+ }
43652
+ async function checkBundleFreshness(pkgRoot) {
43653
+ const base = {
43654
+ applicable: true,
43655
+ fresh: false,
43656
+ embeddedDigest: null,
43657
+ sourceDigest: null,
43658
+ algorithm: BUNDLE_SOURCE_DIGEST_ALGORITHM
43659
+ };
43660
+ const srcStat = await stat4(join14(pkgRoot, "src")).catch(() => null);
43661
+ if (!srcStat?.isDirectory()) {
43662
+ return { ...base, applicable: false, reason: "installed-layout" };
43663
+ }
43664
+ const bundleStat = await stat4(bundlePathFor(pkgRoot)).catch(() => null);
43665
+ if (!bundleStat?.isFile()) {
43666
+ return { ...base, reason: "bundle-missing" };
43667
+ }
43668
+ const [embeddedDigest, sourceDigest] = await Promise.all([
43669
+ readEmbeddedBundleDigest(bundlePathFor(pkgRoot)),
43670
+ computeBundleSourceDigest(pkgRoot)
43671
+ ]);
43672
+ if (!embeddedDigest) {
43673
+ return { ...base, sourceDigest, reason: "digest-missing" };
43674
+ }
43675
+ if (embeddedDigest !== sourceDigest) {
43676
+ return { ...base, embeddedDigest, sourceDigest, reason: "digest-mismatch" };
43677
+ }
43678
+ return { ...base, fresh: true, embeddedDigest, sourceDigest, reason: "fresh" };
43679
+ }
43680
+ async function assertBundleFreshness(pkgRoot) {
43681
+ const result = await checkBundleFreshness(pkgRoot);
43682
+ if (!result.applicable) {
43683
+ return result;
43684
+ }
43685
+ if (result.fresh) {
43686
+ return result;
43687
+ }
43688
+ const reasonText = {
43689
+ "bundle-missing": "the bundle file is missing",
43690
+ "digest-missing": "the bundle carries no embedded source digest",
43691
+ "digest-mismatch": "the bundle is out of sync with src/"
43692
+ }[result.reason] ?? result.reason;
43693
+ throw new ReleaseError(
43694
+ BUNDLE_STALE,
43695
+ `bin/release-skill.bundle.mjs is stale: ${reasonText}. Rebuild it from the release-skill package root with: ${BUNDLE_REBUILD_COMMAND} (or pnpm build)`,
43696
+ {
43697
+ reason: result.reason,
43698
+ algorithm: result.algorithm,
43699
+ embeddedDigest: result.embeddedDigest,
43700
+ sourceDigest: result.sourceDigest,
43701
+ rebuildCommand: BUNDLE_REBUILD_COMMAND
43702
+ }
43703
+ );
43704
+ }
43705
+ var BUNDLE_SOURCE_DIGEST_ALGORITHM, BUNDLE_RELPATH, SOURCE_DIRS, SOURCE_FILES, EMBEDDED_DIGEST_PATTERN, BUNDLE_REBUILD_COMMAND;
43706
+ var init_bundle_freshness = __esm({
43707
+ "src/core/bundle-freshness.mjs"() {
43708
+ init_errors();
43709
+ BUNDLE_SOURCE_DIGEST_ALGORITHM = "bundle-source-digest-v1";
43710
+ BUNDLE_RELPATH = join14("bin", "release-skill.bundle.mjs");
43711
+ SOURCE_DIRS = ["src", "skills-src"];
43712
+ SOURCE_FILES = [join14("bin", "release-skill-cli.mjs"), "package.json"];
43713
+ EMBEDDED_DIGEST_PATTERN = /const __bundleSourceDigest = "([a-f0-9]{64})";/;
43714
+ __name(bundlePathFor, "bundlePathFor");
43715
+ __name(listFilesSorted, "listFilesSorted");
43716
+ __name(listBundleSourceInputs, "listBundleSourceInputs");
43717
+ __name(computeBundleSourceDigest, "computeBundleSourceDigest");
43718
+ __name(readEmbeddedBundleDigest, "readEmbeddedBundleDigest");
43719
+ __name(checkBundleFreshness, "checkBundleFreshness");
43720
+ BUNDLE_REBUILD_COMMAND = "node scripts/build-bundle.mjs";
43721
+ __name(assertBundleFreshness, "assertBundleFreshness");
43722
+ }
43723
+ });
43724
+
43725
+ // src/core/frozen-marker.mjs
43726
+ import { readFile as readFile17, writeFile as writeFile6, unlink as unlink5 } from "node:fs/promises";
43727
+ import { join as join15 } from "node:path";
43728
+ function frozenMarkerPath(releaseDir) {
43729
+ return join15(releaseDir, FROZEN_MARKER_FILENAME);
43730
+ }
43731
+ async function writeFrozenMarker(releaseDir, marker) {
43732
+ const payload = {
43733
+ planDigest: marker.planDigest,
43734
+ targetVersions: marker.targetVersions,
43735
+ createdAt: marker.createdAt,
43736
+ runId: marker.runId
43737
+ };
43738
+ const markerPath = frozenMarkerPath(releaseDir);
43739
+ await writeFile6(markerPath, JSON.stringify(payload, null, 2) + "\n", "utf8");
43740
+ return markerPath;
43741
+ }
43742
+ async function clearFrozenMarker(releaseDir) {
43743
+ try {
43744
+ await unlink5(frozenMarkerPath(releaseDir));
43745
+ return true;
43746
+ } catch {
43747
+ return false;
43748
+ }
43749
+ }
43750
+ var FROZEN_MARKER_FILENAME;
43751
+ var init_frozen_marker = __esm({
43752
+ "src/core/frozen-marker.mjs"() {
43753
+ FROZEN_MARKER_FILENAME = "FROZEN";
43754
+ __name(frozenMarkerPath, "frozenMarkerPath");
43755
+ __name(writeFrozenMarker, "writeFrozenMarker");
43756
+ __name(clearFrozenMarker, "clearFrozenMarker");
43757
+ }
43758
+ });
43759
+
43578
43760
  // src/core/source-authority.mjs
43579
43761
  import { execFile as execFileCb6 } from "node:child_process";
43580
43762
  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";
43763
+ import { lstat as lstat17, mkdtemp as mkdtemp5, readFile as readFile18, readdir as readdir12, realpath as realpath14, rm as rm7 } from "node:fs/promises";
43764
+ import { join as join16, relative as relative16, resolve as resolve18, sep as sep5 } from "node:path";
43583
43765
  import { tmpdir as tmpdir3 } from "node:os";
43584
43766
  async function computeSourceInputClosure({ units, root }) {
43585
43767
  const realRoot = await realpath14(resolve18(root));
@@ -43619,9 +43801,9 @@ function computeEntriesDigest(entries) {
43619
43801
  }))));
43620
43802
  }
43621
43803
  async function collectPath({ absolutePath, root, entriesByPath }) {
43622
- let stat9;
43804
+ let stat10;
43623
43805
  try {
43624
- stat9 = await lstat17(absolutePath);
43806
+ stat10 = await lstat17(absolutePath);
43625
43807
  } catch (error) {
43626
43808
  throw new ReleaseError(
43627
43809
  CONFIG_INVALID,
@@ -43630,7 +43812,7 @@ async function collectPath({ absolutePath, root, entriesByPath }) {
43630
43812
  );
43631
43813
  }
43632
43814
  const rel = toRelative(root, absolutePath);
43633
- if (stat9.isSymbolicLink()) {
43815
+ if (stat10.isSymbolicLink()) {
43634
43816
  throw new ReleaseError(
43635
43817
  CONFIG_INVALID,
43636
43818
  `source-input closure rejects symlink "${rel}"`,
@@ -43645,30 +43827,30 @@ async function collectPath({ absolutePath, root, entriesByPath }) {
43645
43827
  { path: rel }
43646
43828
  );
43647
43829
  }
43648
- if (stat9.isDirectory()) {
43649
- const children = await readdir11(absolutePath, { withFileTypes: true });
43830
+ if (stat10.isDirectory()) {
43831
+ const children = await readdir12(absolutePath, { withFileTypes: true });
43650
43832
  children.sort((left, right) => left.name.localeCompare(right.name));
43651
43833
  for (const child of children) {
43652
43834
  await collectPath({
43653
- absolutePath: join14(absolutePath, child.name),
43835
+ absolutePath: join16(absolutePath, child.name),
43654
43836
  root,
43655
43837
  entriesByPath
43656
43838
  });
43657
43839
  }
43658
43840
  return;
43659
43841
  }
43660
- if (!stat9.isFile()) {
43842
+ if (!stat10.isFile()) {
43661
43843
  throw new ReleaseError(
43662
43844
  CONFIG_INVALID,
43663
43845
  `source-input closure rejects non-regular file "${rel}"`,
43664
43846
  { path: rel }
43665
43847
  );
43666
43848
  }
43667
- const content = await readFile16(absolutePath);
43849
+ const content = await readFile18(absolutePath);
43668
43850
  entriesByPath.set(rel, {
43669
43851
  path: rel,
43670
43852
  digest: sha256Hex(content),
43671
- mode: normalizeLocalGitMode(stat9.mode)
43853
+ mode: normalizeLocalGitMode(stat10.mode)
43672
43854
  });
43673
43855
  }
43674
43856
  function resolveInside(base, candidate, containmentRoot = base) {
@@ -43894,7 +44076,7 @@ async function verifyWithTemporaryGit({
43894
44076
  if (!branchLine) {
43895
44077
  return failure(REF_MISSING, `remote ref "refs/heads/${defaultBranch}" does not exist`);
43896
44078
  }
43897
- const tempRoot = await mkdtemp5(join14(tmpdir3(), "release-skill-source-authority-"));
44079
+ const tempRoot = await mkdtemp5(join16(tmpdir3(), "release-skill-source-authority-"));
43898
44080
  try {
43899
44081
  await execFn("git", ["init", "--bare", tempRoot], {
43900
44082
  encoding: "utf8",
@@ -55969,17 +56151,17 @@ var require_polyfill = __commonJS({
55969
56151
  copyFile,
55970
56152
  lstat: lstat27,
55971
56153
  mkdir: mkdir24,
55972
- readdir: readdir20,
56154
+ readdir: readdir21,
55973
56155
  readlink: readlink2,
55974
- stat: stat9,
56156
+ stat: stat10,
55975
56157
  symlink,
55976
- unlink: unlink5,
56158
+ unlink: unlink6,
55977
56159
  utimes
55978
56160
  } = __require("fs/promises");
55979
56161
  var {
55980
56162
  dirname: dirname18,
55981
56163
  isAbsolute: isAbsolute23,
55982
- join: join32,
56164
+ join: join34,
55983
56165
  parse: parse2,
55984
56166
  resolve: resolve35,
55985
56167
  sep: sep7,
@@ -56068,7 +56250,7 @@ var require_polyfill = __commonJS({
56068
56250
  }
56069
56251
  __name(areIdentical, "areIdentical");
56070
56252
  function getStats(src, dest, opts) {
56071
- const statFunc = opts.dereference ? (file) => stat9(file, { bigint: true }) : (file) => lstat27(file, { bigint: true });
56253
+ const statFunc = opts.dereference ? (file) => stat10(file, { bigint: true }) : (file) => lstat27(file, { bigint: true });
56072
56254
  return Promise.all([
56073
56255
  statFunc(src),
56074
56256
  statFunc(dest).catch((err) => {
@@ -56091,7 +56273,7 @@ var require_polyfill = __commonJS({
56091
56273
  }
56092
56274
  __name(checkParentDir, "checkParentDir");
56093
56275
  function pathExists2(dest) {
56094
- return stat9(dest).then(
56276
+ return stat10(dest).then(
56095
56277
  () => true,
56096
56278
  // istanbul ignore next: not sure when this would occur
56097
56279
  (err) => err.code === "ENOENT" ? false : Promise.reject(err)
@@ -56106,7 +56288,7 @@ var require_polyfill = __commonJS({
56106
56288
  }
56107
56289
  let destStat;
56108
56290
  try {
56109
- destStat = await stat9(destParent, { bigint: true });
56291
+ destStat = await stat10(destParent, { bigint: true });
56110
56292
  } catch (err) {
56111
56293
  if (err.code === "ENOENT") {
56112
56294
  return;
@@ -56146,7 +56328,7 @@ var require_polyfill = __commonJS({
56146
56328
  }
56147
56329
  __name(startCopy, "startCopy");
56148
56330
  async function getStatsForCopy(destStat, src, dest, opts) {
56149
- const statFn = opts.dereference ? stat9 : lstat27;
56331
+ const statFn = opts.dereference ? stat10 : lstat27;
56150
56332
  const srcStat = await statFn(src);
56151
56333
  if (srcStat.isDirectory() && opts.recursive) {
56152
56334
  return onDir(srcStat, destStat, src, dest, opts);
@@ -56193,7 +56375,7 @@ var require_polyfill = __commonJS({
56193
56375
  __name(onFile, "onFile");
56194
56376
  async function mayCopyFile(srcStat, src, dest, opts) {
56195
56377
  if (opts.force) {
56196
- await unlink5(dest);
56378
+ await unlink6(dest);
56197
56379
  return _copyFile(srcStat, src, dest, opts);
56198
56380
  } else if (opts.errorOnExist) {
56199
56381
  throw new ERR_FS_CP_EEXIST({
@@ -56239,7 +56421,7 @@ var require_polyfill = __commonJS({
56239
56421
  }
56240
56422
  __name(setDestMode, "setDestMode");
56241
56423
  async function setDestTimestamps(src, dest) {
56242
- const updatedSrcStat = await stat9(src);
56424
+ const updatedSrcStat = await stat10(src);
56243
56425
  return utimes(dest, updatedSrcStat.atime, updatedSrcStat.mtime);
56244
56426
  }
56245
56427
  __name(setDestTimestamps, "setDestTimestamps");
@@ -56257,11 +56439,11 @@ var require_polyfill = __commonJS({
56257
56439
  }
56258
56440
  __name(mkDirAndCopy, "mkDirAndCopy");
56259
56441
  async function copyDir(src, dest, opts) {
56260
- const dir = await readdir20(src);
56442
+ const dir = await readdir21(src);
56261
56443
  for (let i = 0; i < dir.length; i++) {
56262
56444
  const item = dir[i];
56263
- const srcItem = join32(src, item);
56264
- const destItem = join32(dest, item);
56445
+ const srcItem = join34(src, item);
56446
+ const destItem = join34(dest, item);
56265
56447
  const { destStat } = await checkPaths(srcItem, destItem, opts);
56266
56448
  await startCopy(destStat, srcItem, destItem, opts);
56267
56449
  }
@@ -56295,7 +56477,7 @@ var require_polyfill = __commonJS({
56295
56477
  errno: EINVAL
56296
56478
  });
56297
56479
  }
56298
- const srcStat = await stat9(src);
56480
+ const srcStat = await stat10(src);
56299
56481
  if (srcStat.isDirectory() && isSrcSubdir(resolvedDest, resolvedSrc)) {
56300
56482
  throw new ERR_FS_CP_SYMLINK_TO_SUBDIRECTORY({
56301
56483
  message: `cannot overwrite ${resolvedDest} with ${resolvedSrc}`,
@@ -56308,7 +56490,7 @@ var require_polyfill = __commonJS({
56308
56490
  }
56309
56491
  __name(onLink, "onLink");
56310
56492
  async function copyLink(resolvedSrc, dest) {
56311
- await unlink5(dest);
56493
+ await unlink6(dest);
56312
56494
  return symlink(resolvedSrc, dest);
56313
56495
  }
56314
56496
  __name(copyLink, "copyLink");
@@ -56337,7 +56519,7 @@ var require_cp = __commonJS({
56337
56519
  // ../../node_modules/.pnpm/@npmcli+fs@4.0.0/node_modules/@npmcli/fs/lib/with-temp-dir.js
56338
56520
  var require_with_temp_dir = __commonJS({
56339
56521
  "../../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");
56522
+ var { join: join34, sep: sep7 } = __require("path");
56341
56523
  var getOptions = require_get_options();
56342
56524
  var { mkdir: mkdir24, mkdtemp: mkdtemp10, rm: rm15 } = __require("fs/promises");
56343
56525
  var withTempDir = /* @__PURE__ */ __name(async (root, fn, opts) => {
@@ -56345,7 +56527,7 @@ var require_with_temp_dir = __commonJS({
56345
56527
  copy: ["tmpPrefix"]
56346
56528
  });
56347
56529
  await mkdir24(root, { recursive: true });
56348
- const target = await mkdtemp10(join32(`${root}${sep7}`, options.tmpPrefix || ""));
56530
+ const target = await mkdtemp10(join34(`${root}${sep7}`, options.tmpPrefix || ""));
56349
56531
  let err;
56350
56532
  let result;
56351
56533
  try {
@@ -56369,14 +56551,14 @@ var require_with_temp_dir = __commonJS({
56369
56551
  // ../../node_modules/.pnpm/@npmcli+fs@4.0.0/node_modules/@npmcli/fs/lib/readdir-scoped.js
56370
56552
  var require_readdir_scoped = __commonJS({
56371
56553
  "../../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");
56554
+ var { readdir: readdir21 } = __require("fs/promises");
56555
+ var { join: join34 } = __require("path");
56374
56556
  var readdirScoped = /* @__PURE__ */ __name(async (dir) => {
56375
56557
  const results = [];
56376
- for (const item of await readdir20(dir)) {
56558
+ for (const item of await readdir21(dir)) {
56377
56559
  if (item.startsWith("@")) {
56378
- for (const scopedItem of await readdir20(join32(dir, item))) {
56379
- results.push(join32(item, scopedItem));
56560
+ for (const scopedItem of await readdir21(join34(dir, item))) {
56561
+ results.push(join34(item, scopedItem));
56380
56562
  }
56381
56563
  } else {
56382
56564
  results.push(item);
@@ -56391,7 +56573,7 @@ var require_readdir_scoped = __commonJS({
56391
56573
  // ../../node_modules/.pnpm/@npmcli+fs@4.0.0/node_modules/@npmcli/fs/lib/move-file.js
56392
56574
  var require_move_file = __commonJS({
56393
56575
  "../../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");
56576
+ var { dirname: dirname18, join: join34, resolve: resolve35, relative: relative27, isAbsolute: isAbsolute23 } = __require("path");
56395
56577
  var fs = __require("fs/promises");
56396
56578
  var pathExists2 = /* @__PURE__ */ __name(async (path15) => {
56397
56579
  try {
@@ -56421,7 +56603,7 @@ var require_move_file = __commonJS({
56421
56603
  if (sourceStat.isDirectory()) {
56422
56604
  const files = await fs.readdir(source);
56423
56605
  await Promise.all(files.map(
56424
- (file) => moveFile(join32(source, file), join32(destination, file), options, false, symlinks)
56606
+ (file) => moveFile(join34(source, file), join34(destination, file), options, false, symlinks)
56425
56607
  ));
56426
56608
  } else if (sourceStat.isSymbolicLink()) {
56427
56609
  symlinks.push({ source, destination });
@@ -56695,10 +56877,10 @@ var require_entry_index = __commonJS({
56695
56877
  var {
56696
56878
  appendFile,
56697
56879
  mkdir: mkdir24,
56698
- readFile: readFile40,
56699
- readdir: readdir20,
56880
+ readFile: readFile42,
56881
+ readdir: readdir21,
56700
56882
  rm: rm15,
56701
- writeFile: writeFile13
56883
+ writeFile: writeFile14
56702
56884
  } = __require("fs/promises");
56703
56885
  var { Minipass } = require_commonjs();
56704
56886
  var path15 = __require("path");
@@ -56753,7 +56935,7 @@ var require_entry_index = __commonJS({
56753
56935
  }
56754
56936
  }, "teardown");
56755
56937
  const write = /* @__PURE__ */ __name(async (tmp2) => {
56756
- await writeFile13(tmp2.target, newIndex, { flag: "wx" });
56938
+ await writeFile14(tmp2.target, newIndex, { flag: "wx" });
56757
56939
  await mkdir24(path15.dirname(bucket), { recursive: true });
56758
56940
  await moveFile(tmp2.target, bucket);
56759
56941
  tmp2.moved = true;
@@ -56887,7 +57069,7 @@ ${hashEntry(stringified)} ${stringified}`);
56887
57069
  __name(ls, "ls");
56888
57070
  module.exports.bucketEntries = bucketEntries;
56889
57071
  async function bucketEntries(bucket, filter) {
56890
- const data = await readFile40(bucket, "utf8");
57072
+ const data = await readFile42(bucket, "utf8");
56891
57073
  return _bucketEntries(data, filter);
56892
57074
  }
56893
57075
  __name(bucketEntries, "bucketEntries");
@@ -56956,7 +57138,7 @@ ${hashEntry(stringified)} ${stringified}`);
56956
57138
  }
56957
57139
  __name(formatEntry, "formatEntry");
56958
57140
  function readdirOrEmpty(dir) {
56959
- return readdir20(dir).catch((err) => {
57141
+ return readdir21(dir).catch((err) => {
56960
57142
  if (err.code === "ENOENT" || err.code === "ENOTDIR") {
56961
57143
  return [];
56962
57144
  }
@@ -57452,16 +57634,16 @@ var require_read2 = __commonJS({
57452
57634
  var MAX_SINGLE_READ_SIZE = 64 * 1024 * 1024;
57453
57635
  async function read(cache, integrity, opts = {}) {
57454
57636
  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 };
57637
+ const { stat: stat10, cpath, sri } = await withContentSri(cache, integrity, async (cpath2, sri2) => {
57638
+ const stat11 = size ? { size } : await fs.stat(cpath2);
57639
+ return { stat: stat11, cpath: cpath2, sri: sri2 };
57458
57640
  });
57459
- if (stat9.size > MAX_SINGLE_READ_SIZE) {
57460
- return readPipeline(cpath, stat9.size, sri, new Pipeline()).concat();
57641
+ if (stat10.size > MAX_SINGLE_READ_SIZE) {
57642
+ return readPipeline(cpath, stat10.size, sri, new Pipeline()).concat();
57461
57643
  }
57462
57644
  const data = await fs.readFile(cpath, { encoding: null });
57463
- if (stat9.size !== data.length) {
57464
- throw sizeError(stat9.size, data.length);
57645
+ if (stat10.size !== data.length) {
57646
+ throw sizeError(stat10.size, data.length);
57465
57647
  }
57466
57648
  if (!ssri.checkData(data, sri)) {
57467
57649
  throw integrityError(sri, cpath);
@@ -57488,11 +57670,11 @@ var require_read2 = __commonJS({
57488
57670
  const { size } = opts;
57489
57671
  const stream = new Pipeline();
57490
57672
  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 };
57673
+ const { stat: stat10, cpath, sri } = await withContentSri(cache, integrity, async (cpath2, sri2) => {
57674
+ const stat11 = size ? { size } : await fs.stat(cpath2);
57675
+ return { stat: stat11, cpath: cpath2, sri: sri2 };
57494
57676
  });
57495
- return readPipeline(cpath, stat9.size, sri, stream);
57677
+ return readPipeline(cpath, stat10.size, sri, stream);
57496
57678
  }).catch((err) => stream.emit("error", err));
57497
57679
  return stream;
57498
57680
  }
@@ -57511,8 +57693,8 @@ var require_read2 = __commonJS({
57511
57693
  }
57512
57694
  try {
57513
57695
  return await withContentSri(cache, integrity, async (cpath, sri) => {
57514
- const stat9 = await fs.stat(cpath);
57515
- return { size: stat9.size, sri, stat: stat9 };
57696
+ const stat10 = await fs.stat(cpath);
57697
+ return { size: stat10.size, sri, stat: stat10 };
57516
57698
  });
57517
57699
  } catch (err) {
57518
57700
  if (err.code === "ENOENT") {
@@ -62907,11 +63089,11 @@ var require_verify = __commonJS({
62907
63089
  "use strict";
62908
63090
  var {
62909
63091
  mkdir: mkdir24,
62910
- readFile: readFile40,
63092
+ readFile: readFile42,
62911
63093
  rm: rm15,
62912
- stat: stat9,
63094
+ stat: stat10,
62913
63095
  truncate,
62914
- writeFile: writeFile13
63096
+ writeFile: writeFile14
62915
63097
  } = __require("fs/promises");
62916
63098
  var contentPath = require_path();
62917
63099
  var fsm = require_lib29();
@@ -63029,7 +63211,7 @@ var require_verify = __commonJS({
63029
63211
  }
63030
63212
  } else {
63031
63213
  stats.reclaimedCount++;
63032
- const s = await stat9(f);
63214
+ const s = await stat10(f);
63033
63215
  await rm15(f, { recursive: true, force: true });
63034
63216
  stats.reclaimedSize += s.size;
63035
63217
  }
@@ -63043,7 +63225,7 @@ var require_verify = __commonJS({
63043
63225
  async function verifyContent(filepath, sri) {
63044
63226
  const contentInfo = {};
63045
63227
  try {
63046
- const { size } = await stat9(filepath);
63228
+ const { size } = await stat10(filepath);
63047
63229
  contentInfo.size = size;
63048
63230
  contentInfo.valid = true;
63049
63231
  await ssri.checkStream(new fsm.ReadStream(filepath), sri);
@@ -63103,7 +63285,7 @@ var require_verify = __commonJS({
63103
63285
  for (const entry of bucket) {
63104
63286
  const content = contentPath(cache, entry.integrity);
63105
63287
  try {
63106
- await stat9(content);
63288
+ await stat10(content);
63107
63289
  await index.insert(cache, entry.key, entry.integrity, {
63108
63290
  metadata: entry.metadata,
63109
63291
  size: entry.size,
@@ -63129,12 +63311,12 @@ var require_verify = __commonJS({
63129
63311
  async function writeVerifile(cache, opts) {
63130
63312
  const verifile = path15.join(cache, "_lastverified");
63131
63313
  opts.log.silly("verify", "writing verifile to " + verifile);
63132
- return writeFile13(verifile, `${Date.now()}`);
63314
+ return writeFile14(verifile, `${Date.now()}`);
63133
63315
  }
63134
63316
  __name(writeVerifile, "writeVerifile");
63135
63317
  module.exports.lastRun = lastRun;
63136
63318
  async function lastRun(cache) {
63137
- const data = await readFile40(path15.join(cache, "_lastverified"), { encoding: "utf8" });
63319
+ const data = await readFile42(path15.join(cache, "_lastverified"), { encoding: "utf8" });
63138
63320
  return /* @__PURE__ */ new Date(+data);
63139
63321
  }
63140
63322
  __name(lastRun, "lastRun");
@@ -71674,7 +71856,7 @@ var require_index_min = __commonJS({
71674
71856
  var require_lib35 = __commonJS({
71675
71857
  "../../node_modules/.pnpm/which@5.0.0/node_modules/which/lib/index.js"(exports, module) {
71676
71858
  var { isexe, sync: isexeSync } = require_index_min();
71677
- var { join: join32, delimiter, sep: sep7, posix: posix3 } = __require("path");
71859
+ var { join: join34, delimiter, sep: sep7, posix: posix3 } = __require("path");
71678
71860
  var isWindows = process.platform === "win32";
71679
71861
  var rSlash = new RegExp(`[${posix3.sep}${sep7 === posix3.sep ? "" : sep7}]`.replace(/(\\)/g, "\\$1"));
71680
71862
  var rRel = new RegExp(`^\\.${rSlash.source}`);
@@ -71703,7 +71885,7 @@ var require_lib35 = __commonJS({
71703
71885
  var getPathPart = /* @__PURE__ */ __name((raw, cmd) => {
71704
71886
  const pathPart = /^".*"$/.test(raw) ? raw.slice(1, -1) : raw;
71705
71887
  const prefix = !pathPart && rRel.test(cmd) ? cmd.slice(0, 2) : "";
71706
- return prefix + join32(pathPart, cmd);
71888
+ return prefix + join34(pathPart, cmd);
71707
71889
  }, "getPathPart");
71708
71890
  var which = /* @__PURE__ */ __name(async (cmd, opt = {}) => {
71709
71891
  const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
@@ -72842,7 +73024,7 @@ var require_lib37 = __commonJS({
72842
73024
  // ../../node_modules/.pnpm/npm-normalize-package-bin@4.0.0/node_modules/npm-normalize-package-bin/lib/index.js
72843
73025
  var require_lib38 = __commonJS({
72844
73026
  "../../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");
73027
+ var { join: join34, basename: basename13 } = __require("path");
72846
73028
  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
73029
  var normalizeString = /* @__PURE__ */ __name((pkg) => {
72848
73030
  if (!pkg.name) {
@@ -72853,7 +73035,7 @@ var require_lib38 = __commonJS({
72853
73035
  }, "normalizeString");
72854
73036
  var normalizeArray = /* @__PURE__ */ __name((pkg) => {
72855
73037
  pkg.bin = pkg.bin.reduce((acc, k) => {
72856
- acc[basename12(k)] = k;
73038
+ acc[basename13(k)] = k;
72857
73039
  return acc;
72858
73040
  }, {});
72859
73041
  return normalizeObject(pkg);
@@ -72867,11 +73049,11 @@ var require_lib38 = __commonJS({
72867
73049
  const clean = {};
72868
73050
  let hasBins = false;
72869
73051
  Object.keys(orig).forEach((binKey) => {
72870
- const base = join32("/", basename12(binKey.replace(/\\|:/g, "/"))).slice(1);
73052
+ const base = join34("/", basename13(binKey.replace(/\\|:/g, "/"))).slice(1);
72871
73053
  if (typeof orig[binKey] !== "string" || !base) {
72872
73054
  return;
72873
73055
  }
72874
- const binTarget = join32("/", orig[binKey].replace(/\\/g, "/")).replace(/\\/g, "/").slice(1);
73056
+ const binTarget = join34("/", orig[binKey].replace(/\\/g, "/")).replace(/\\/g, "/").slice(1);
72875
73057
  if (!binTarget) {
72876
73058
  return;
72877
73059
  }
@@ -73172,8 +73354,8 @@ var require_clone2 = __commonJS({
73172
73354
  // ../../node_modules/.pnpm/@npmcli+git@6.0.3/node_modules/@npmcli/git/lib/is.js
73173
73355
  var require_is = __commonJS({
73174
73356
  "../../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);
73357
+ var { stat: stat10 } = __require("fs/promises");
73358
+ module.exports = ({ cwd = process.cwd() } = {}) => stat10(cwd + "/.git").then(() => true, () => false);
73177
73359
  }
73178
73360
  });
73179
73361
 
@@ -75412,11 +75594,11 @@ var require_normalize = __commonJS({
75412
75594
  // ../../node_modules/.pnpm/@npmcli+package-json@6.2.0/node_modules/@npmcli/package-json/lib/read-package.js
75413
75595
  var require_read_package = __commonJS({
75414
75596
  "../../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");
75597
+ var { readFile: readFile42 } = __require("fs/promises");
75416
75598
  var parseJSON = require_lib34();
75417
75599
  async function read(filename) {
75418
75600
  try {
75419
- const data = await readFile40(filename, "utf8");
75601
+ const data = await readFile42(filename, "utf8");
75420
75602
  return data;
75421
75603
  } catch (err) {
75422
75604
  err.message = `Could not read package.json: ${err}`;
@@ -75549,7 +75731,7 @@ var require_sort2 = __commonJS({
75549
75731
  // ../../node_modules/.pnpm/@npmcli+package-json@6.2.0/node_modules/@npmcli/package-json/lib/index.js
75550
75732
  var require_lib41 = __commonJS({
75551
75733
  "../../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");
75734
+ var { readFile: readFile42, writeFile: writeFile14 } = __require("node:fs/promises");
75553
75735
  var { resolve: resolve35 } = __require("node:path");
75554
75736
  var parseJSON = require_lib34();
75555
75737
  var updateDeps = require_update_dependencies();
@@ -75676,7 +75858,7 @@ var require_lib41 = __commonJS({
75676
75858
  const indexFile = resolve35(this.path, "index.js");
75677
75859
  let indexFileContent;
75678
75860
  try {
75679
- indexFileContent = await readFile40(indexFile, "utf8");
75861
+ indexFileContent = await readFile42(indexFile, "utf8");
75680
75862
  } catch (err) {
75681
75863
  throw parseErr;
75682
75864
  }
@@ -75764,7 +75946,7 @@ var require_lib41 = __commonJS({
75764
75946
  const fileContent = `${JSON.stringify(content, null, format)}
75765
75947
  `.replace(/\n/g, eol);
75766
75948
  if (fileContent.trim() !== this.#readFileContent.trim()) {
75767
- const written = await writeFile13(this.filename, fileContent);
75949
+ const written = await writeFile14(this.filename, fileContent);
75768
75950
  this.#readFileContent = fileContent;
75769
75951
  return written;
75770
75952
  }
@@ -82875,12 +83057,12 @@ var require_url = __commonJS({
82875
83057
  "../../node_modules/.pnpm/tuf-js@3.1.0/node_modules/tuf-js/dist/utils/url.js"(exports) {
82876
83058
  "use strict";
82877
83059
  Object.defineProperty(exports, "__esModule", { value: true });
82878
- exports.join = join32;
83060
+ exports.join = join34;
82879
83061
  var url_1 = __require("url");
82880
- function join32(base, path15) {
83062
+ function join34(base, path15) {
82881
83063
  return new url_1.URL(ensureTrailingSlash(base) + removeLeadingSlash(path15)).toString();
82882
83064
  }
82883
- __name(join32, "join");
83065
+ __name(join34, "join");
82884
83066
  function ensureTrailingSlash(path15) {
82885
83067
  return path15.endsWith("/") ? path15 : path15 + "/";
82886
83068
  }
@@ -84985,7 +85167,7 @@ var require_dist16 = __commonJS({
84985
85167
  var require_provenance = __commonJS({
84986
85168
  "../../node_modules/.pnpm/libnpmpublish@11.1.0/node_modules/libnpmpublish/lib/provenance.js"(exports, module) {
84987
85169
  var sigstore = require_dist16();
84988
- var { readFile: readFile40 } = __require("node:fs/promises");
85170
+ var { readFile: readFile42 } = __require("node:fs/promises");
84989
85171
  var ci = require_ci_info();
84990
85172
  var { env } = process;
84991
85173
  var INTOTO_PAYLOAD_TYPE = "application/vnd.in-toto+json";
@@ -85177,7 +85359,7 @@ var require_provenance = __commonJS({
85177
85359
  var verifyProvenance = /* @__PURE__ */ __name(async (subject, provenancePath) => {
85178
85360
  let provenanceBundle;
85179
85361
  try {
85180
- provenanceBundle = JSON.parse(await readFile40(provenancePath));
85362
+ provenanceBundle = JSON.parse(await readFile42(provenancePath));
85181
85363
  } catch (err) {
85182
85364
  err.message = `Invalid provenance provided: ${err.message}`;
85183
85365
  throw err;
@@ -85513,13 +85695,13 @@ __export(npm_exports, {
85513
85695
  verifyFrozenNpmTarballContract: () => verifyFrozenNpmTarballContract,
85514
85696
  verifyFrozenNpmTarballIdentity: () => verifyFrozenNpmTarballIdentity
85515
85697
  });
85516
- import { createHash as createHash13, randomUUID } from "node:crypto";
85698
+ import { createHash as createHash14, randomUUID } from "node:crypto";
85517
85699
  import { execFile as execFileCb7, spawn as spawn3 } from "node:child_process";
85518
85700
  import { gunzipSync } from "node:zlib";
85519
85701
  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";
85702
+ import { dirname as dirname9, isAbsolute as isAbsolute14, join as join17, relative as relative17, resolve as resolve19 } from "node:path";
85521
85703
  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";
85704
+ 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
85705
  function validatePackageName(value) {
85524
85706
  if (typeof value !== "string" || value.length > 214 || !SAFE_PACKAGE_NAME.test(value)) {
85525
85707
  throw new Error("npm package must be a safe lowercase package name or @scope/name");
@@ -85573,7 +85755,7 @@ function expandNpmrcValue(raw, env) {
85573
85755
  async function tokensFromNpmrc(path15, key, env) {
85574
85756
  let contents;
85575
85757
  try {
85576
- contents = await readFile17(path15, "utf8");
85758
+ contents = await readFile19(path15, "utf8");
85577
85759
  } catch (err) {
85578
85760
  if (err?.code === "ENOENT") return [];
85579
85761
  throw new Error("cannot read npm authentication config");
@@ -85596,7 +85778,7 @@ async function defaultResolveAuthToken({ registry, cwd, exec, env = process.env
85596
85778
  if (env[name]) candidates.push(env[name]);
85597
85779
  }
85598
85780
  const key = registryTokenKey(registry);
85599
- candidates.push(...await tokensFromNpmrc(join15(cwd, ".npmrc"), key, env));
85781
+ candidates.push(...await tokensFromNpmrc(join17(cwd, ".npmrc"), key, env));
85600
85782
  const npmUserConfigKey = ["npm", "config", "userconfig"].join("_");
85601
85783
  const userConfig = env[npmUserConfigKey] ?? (await exec("npm", ["config", "get", "userconfig"], { cwd, shell: false })).stdout.trim();
85602
85784
  if (userConfig) candidates.push(...await tokensFromNpmrc(userConfig, key, env));
@@ -85674,12 +85856,12 @@ async function readVerifiedTarballBytes(action, root) {
85674
85856
  } finally {
85675
85857
  await source.close();
85676
85858
  }
85677
- const digest2 = createHash13("sha256").update(bytes).digest("hex");
85859
+ const digest2 = createHash14("sha256").update(bytes).digest("hex");
85678
85860
  if (digest2 !== action.tarballSha256) throw new Error("frozen npm tarball SHA-256 mismatch");
85679
85861
  if (typeof action.integrity !== "string" || !/^sha512-[A-Za-z0-9+/]+={0,2}$/.test(action.integrity)) {
85680
85862
  throw new Error("frozen npm tarball integrity must be an sha512 SRI value");
85681
85863
  }
85682
- const integrity = `sha512-${createHash13("sha512").update(bytes).digest("base64")}`;
85864
+ const integrity = `sha512-${createHash14("sha512").update(bytes).digest("base64")}`;
85683
85865
  if (integrity !== action.integrity) throw new Error("frozen npm tarball SHA-512 integrity mismatch");
85684
85866
  return bytes;
85685
85867
  }
@@ -86127,9 +86309,9 @@ var init_npm = __esm({
86127
86309
  });
86128
86310
 
86129
86311
  // src/core/run.mjs
86130
- import { lstat as lstat19, mkdir as mkdir12, readFile as readFile18 } from "node:fs/promises";
86312
+ import { lstat as lstat19, mkdir as mkdir12, readFile as readFile20 } from "node:fs/promises";
86131
86313
  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";
86314
+ import { dirname as dirname10, join as join18, resolve as resolve20, basename as basename5, relative as relative18, isAbsolute as isAbsolute15 } from "node:path";
86133
86315
  function resolveDefaultRunDir(planPath, command2, runId = `${command2}-${Date.now()}`) {
86134
86316
  const absolute = resolve20(planPath);
86135
86317
  const fileName = basename5(absolute);
@@ -86139,7 +86321,7 @@ function resolveDefaultRunDir(planPath, command2, runId = `${command2}-${Date.no
86139
86321
  }
86140
86322
  if (basename5(parentDir) === "plans") {
86141
86323
  const releaseDir = dirname10(parentDir);
86142
- return join16(releaseDir, "runs", runId);
86324
+ return join18(releaseDir, "runs", runId);
86143
86325
  }
86144
86326
  return `${parentDir}/runs/${runId}`;
86145
86327
  }
@@ -86179,7 +86361,7 @@ function validateRun(run5, options = {}) {
86179
86361
  async function loadRun(runPath, options = {}) {
86180
86362
  let raw;
86181
86363
  try {
86182
- raw = await readFile18(runPath, "utf8");
86364
+ raw = await readFile20(runPath, "utf8");
86183
86365
  } catch (err) {
86184
86366
  throw new ReleaseError(
86185
86367
  GATE_FAILED,
@@ -86218,7 +86400,7 @@ function assertImmutableRunAuthority(runPath, planPath, run5) {
86218
86400
  }
86219
86401
  cursor = dirname10(cursor);
86220
86402
  }
86221
- const runsDir = join16(authorityRoot, "runs");
86403
+ const runsDir = join18(authorityRoot, "runs");
86222
86404
  const absoluteRun = realpathSync3(resolve20(runPath));
86223
86405
  const rel = relative18(runsDir, absoluteRun);
86224
86406
  if (isAbsolute15(rel) || rel === ".." || rel.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`)) {
@@ -86273,7 +86455,7 @@ async function createProductionPrepareRunDir(runDir, releaseDir) {
86273
86455
  return createProductionRunDirWithinAuthority(runDir, physicalAuthorityRoot);
86274
86456
  }
86275
86457
  async function createProductionRunDirWithinAuthority(runDir, authorityRoot) {
86276
- const runsDir = join16(authorityRoot, "runs");
86458
+ const runsDir = join18(authorityRoot, "runs");
86277
86459
  let runsStat;
86278
86460
  try {
86279
86461
  runsStat = await lstat19(runsDir);
@@ -86383,7 +86565,7 @@ async function validateStatePredecessorChain(run5, runPath, options = {}) {
86383
86565
  if (traversed > 1e5) {
86384
86566
  throw new ReleaseError(GATE_FAILED, "run state predecessor chain exceeds maximum depth");
86385
86567
  }
86386
- const previousPath = join16(dirname10(currentPath), `${String(sequence - 1).padStart(6, "0")}.json`);
86568
+ const previousPath = join18(dirname10(currentPath), `${String(sequence - 1).padStart(6, "0")}.json`);
86387
86569
  const previous = await loadRun(previousPath, {
86388
86570
  requireDigest: true,
86389
86571
  ...options.production ? { authorityPlanPath: options.planPath } : {}
@@ -86556,7 +86738,7 @@ async function writeRunAtomic(runPath, run5) {
86556
86738
  await publishFileExclusive(dir, basename5(runPath), json, { mode: 384 });
86557
86739
  } catch (cause) {
86558
86740
  if (cause?.details?.kind === HARNESS_ERROR_KINDS.EXCLUSIVE_PUBLISH_CONFLICT) {
86559
- const existing = await readFile18(runPath, "utf8").catch(() => null);
86741
+ const existing = await readFile20(runPath, "utf8").catch(() => null);
86560
86742
  if (existing === json) return Object.freeze(sealed);
86561
86743
  throw new ReleaseError(
86562
86744
  GATE_FAILED,
@@ -86576,10 +86758,10 @@ async function appendRunState(runDir, sequence, run5) {
86576
86758
  if (!Number.isSafeInteger(sequence) || sequence < 0) {
86577
86759
  throw new ReleaseError(GATE_FAILED, "run state sequence must be a non-negative integer");
86578
86760
  }
86579
- const statesDir = join16(runDir, "states");
86761
+ const statesDir = join18(runDir, "states");
86580
86762
  let previousStateDigest;
86581
86763
  if (sequence > 0) {
86582
- const previousPath = join16(statesDir, `${String(sequence - 1).padStart(6, "0")}.json`);
86764
+ const previousPath = join18(statesDir, `${String(sequence - 1).padStart(6, "0")}.json`);
86583
86765
  const previous = await loadRun(previousPath, { requireDigest: true });
86584
86766
  if (previous.stateSequence !== sequence - 1 || previous.runId !== run5.runId || previous.command !== run5.command || previous.planDigest !== run5.planDigest) {
86585
86767
  throw new ReleaseError(
@@ -86596,7 +86778,7 @@ async function appendRunState(runDir, sequence, run5) {
86596
86778
  stateSequence: sequence,
86597
86779
  ...previousStateDigest ? { previousStateDigest } : {}
86598
86780
  });
86599
- const statePath = join16(statesDir, `${String(sequence).padStart(6, "0")}.json`);
86781
+ const statePath = join18(statesDir, `${String(sequence).padStart(6, "0")}.json`);
86600
86782
  await writeRunAtomic(statePath, state);
86601
86783
  return Object.freeze({ state, statePath });
86602
86784
  }
@@ -86649,9 +86831,9 @@ __export(plugin_marketplace_exports, {
86649
86831
  });
86650
86832
  import { execFile as execFileCb8 } from "node:child_process";
86651
86833
  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";
86834
+ import { readFile as readFile21, stat as stat5, mkdir as mkdir13, readdir as readdir13, realpath as realpath16, lstat as lstat20 } from "node:fs/promises";
86835
+ import { join as join19, resolve as resolve21, relative as relative19, isAbsolute as isAbsolute16, basename as basename6 } from "node:path";
86836
+ import { createHash as createHash15 } from "node:crypto";
86655
86837
  function transportPayload(entries) {
86656
86838
  return entries.map(({ path: path15, type, mode, size, contentDigest }) => ({
86657
86839
  path: path15,
@@ -86736,7 +86918,7 @@ async function resolvePluginManifestFromMarketplaceEntrySource(marketIndex, plug
86736
86918
  const fullManifestRelative = pluginRootRelToSnapshot === "" ? manifestRelative : `${pluginRootRelToSnapshot}/${manifestRelative}`;
86737
86919
  let raw;
86738
86920
  try {
86739
- raw = await readFile19(manifestAbs, "utf8");
86921
+ raw = await readFile21(manifestAbs, "utf8");
86740
86922
  } catch (err) {
86741
86923
  throw new Error(
86742
86924
  `plugin manifest not found at "${fullManifestRelative}": ${err.message}`
@@ -87185,7 +87367,7 @@ async function run2(cmd, args2, options = {}) {
87185
87367
  }
87186
87368
  async function validateManifestFile(manifestPath, requiredFields) {
87187
87369
  try {
87188
- const content = await readFile19(manifestPath, "utf8");
87370
+ const content = await readFile21(manifestPath, "utf8");
87189
87371
  const manifest = JSON.parse(content);
87190
87372
  const missing = requiredFields.filter((f) => !(f in manifest));
87191
87373
  return {
@@ -87207,7 +87389,7 @@ async function checkRequiredFiles(dir, requiredFiles) {
87207
87389
  const missing = [];
87208
87390
  for (const file of requiredFiles) {
87209
87391
  try {
87210
- await stat4(resolve21(dir, file));
87392
+ await stat5(resolve21(dir, file));
87211
87393
  } catch {
87212
87394
  missing.push(file);
87213
87395
  }
@@ -87303,7 +87485,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
87303
87485
  });
87304
87486
  }
87305
87487
  try {
87306
- const s = await stat4(pluginDir);
87488
+ const s = await stat5(pluginDir);
87307
87489
  if (!s.isDirectory()) {
87308
87490
  return createResult({
87309
87491
  actionType,
@@ -88089,7 +88271,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
88089
88271
  let entrySkillFile = resolve21(pluginRootForSkill, "skills", action.entrySkill, "SKILL.md");
88090
88272
  let entrySkillExists = false;
88091
88273
  try {
88092
- await stat4(entrySkillFile);
88274
+ await stat5(entrySkillFile);
88093
88275
  entrySkillExists = true;
88094
88276
  } catch {
88095
88277
  if (action.plugin) {
@@ -88100,7 +88282,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
88100
88282
  "SKILL.md"
88101
88283
  );
88102
88284
  try {
88103
- await stat4(prefixed);
88285
+ await stat5(prefixed);
88104
88286
  entrySkillFile = prefixed;
88105
88287
  entrySkillExists = true;
88106
88288
  } catch {
@@ -88517,7 +88699,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
88517
88699
  if (actionType === ActionType.PLUGIN_MANIFEST_VALIDATE) {
88518
88700
  const manifestPath = action.manifestPath;
88519
88701
  try {
88520
- const content = await readFile19(manifestPath, "utf8");
88702
+ const content = await readFile21(manifestPath, "utf8");
88521
88703
  const manifest = JSON.parse(content);
88522
88704
  return createResult({
88523
88705
  actionType,
@@ -88612,7 +88794,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
88612
88794
  }
88613
88795
  let requirement = null;
88614
88796
  try {
88615
- requirement = JSON.parse(await readFile19(resolve21(attestationDir, KIMI_REQUIREMENT_FILE), "utf8"));
88797
+ requirement = JSON.parse(await readFile21(resolve21(attestationDir, KIMI_REQUIREMENT_FILE), "utf8"));
88616
88798
  } catch {
88617
88799
  return createResult({
88618
88800
  actionType,
@@ -88636,7 +88818,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
88636
88818
  }
88637
88819
  let attestation = null;
88638
88820
  try {
88639
- attestation = JSON.parse(await readFile19(resolve21(attestationDir, KIMI_ATTESTATION_FILE), "utf8"));
88821
+ attestation = JSON.parse(await readFile21(resolve21(attestationDir, KIMI_ATTESTATION_FILE), "utf8"));
88640
88822
  } catch {
88641
88823
  return createResult({
88642
88824
  actionType,
@@ -88803,7 +88985,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
88803
88985
  }
88804
88986
  let requirement = null;
88805
88987
  try {
88806
- requirement = JSON.parse(await readFile19(resolve21(attestationDir, CODEBUDDY_REQUIREMENT_FILE), "utf8"));
88988
+ requirement = JSON.parse(await readFile21(resolve21(attestationDir, CODEBUDDY_REQUIREMENT_FILE), "utf8"));
88807
88989
  } catch {
88808
88990
  return createResult({
88809
88991
  actionType,
@@ -88827,7 +89009,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
88827
89009
  }
88828
89010
  let attestation = null;
88829
89011
  try {
88830
- attestation = JSON.parse(await readFile19(resolve21(attestationDir, CODEBUDDY_ATTESTATION_FILE), "utf8"));
89012
+ attestation = JSON.parse(await readFile21(resolve21(attestationDir, CODEBUDDY_ATTESTATION_FILE), "utf8"));
88831
89013
  } catch {
88832
89014
  const marketplaceSource = resolveCodeBuddyMarketplaceSource(action);
88833
89015
  return createResult({
@@ -88976,13 +89158,13 @@ function createPluginMarketplaceAdapter(deps = {}) {
88976
89158
  if (codexAttestationDir) {
88977
89159
  let codexRequirement = null;
88978
89160
  try {
88979
- codexRequirement = JSON.parse(await readFile19(resolve21(codexAttestationDir, CODEX_REQUIREMENT_FILE), "utf8"));
89161
+ codexRequirement = JSON.parse(await readFile21(resolve21(codexAttestationDir, CODEX_REQUIREMENT_FILE), "utf8"));
88980
89162
  } catch {
88981
89163
  }
88982
89164
  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
89165
  let codexAttestation = null;
88984
89166
  try {
88985
- codexAttestation = JSON.parse(await readFile19(resolve21(codexAttestationDir, CODEX_ATTESTATION_FILE), "utf8"));
89167
+ codexAttestation = JSON.parse(await readFile21(resolve21(codexAttestationDir, CODEX_ATTESTATION_FILE), "utf8"));
88986
89168
  } catch {
88987
89169
  }
88988
89170
  if (codexAttestation) {
@@ -89037,7 +89219,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
89037
89219
  }
89038
89220
  let evidence = null;
89039
89221
  try {
89040
- const evidenceRaw = await readFile19(resolve21(runDir, "evidence", `${consumer}-${action.plugin}`, "release-skill-install-evidence.json"), "utf8");
89222
+ const evidenceRaw = await readFile21(resolve21(runDir, "evidence", `${consumer}-${action.plugin}`, "release-skill-install-evidence.json"), "utf8");
89041
89223
  evidence = JSON.parse(evidenceRaw);
89042
89224
  } catch {
89043
89225
  return createResult({
@@ -89220,7 +89402,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
89220
89402
  }
89221
89403
  try {
89222
89404
  const installedManifestPath = resolve21(installPath, platform.manifestPaths.plugin);
89223
- const installedManifestContent = await readFile19(installedManifestPath, "utf8");
89405
+ const installedManifestContent = await readFile21(installedManifestPath, "utf8");
89224
89406
  const installedManifest = JSON.parse(installedManifestContent);
89225
89407
  const expectedName = observation.plugin;
89226
89408
  if (expectedName && installedManifest.name !== expectedName) {
@@ -89651,8 +89833,8 @@ var init_postpublish = __esm({
89651
89833
  });
89652
89834
 
89653
89835
  // 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";
89836
+ import { readdir as readdir14, readFile as readFile22, rm as rm9, stat as stat6 } from "node:fs/promises";
89837
+ import { join as join20 } from "node:path";
89656
89838
  function failSchema(message, details) {
89657
89839
  throw new ReleaseError(TRANSACTION_INCOMPLETE, message, details);
89658
89840
  }
@@ -90649,7 +90831,7 @@ async function pruneTerminalTransactionRecords(transactionsRoot, {
90649
90831
  if (!Number.isInteger(retentionMax) || retentionMax < 0) return summary;
90650
90832
  let entries;
90651
90833
  try {
90652
- entries = await readdir13(transactionsRoot, { withFileTypes: true });
90834
+ entries = await readdir14(transactionsRoot, { withFileTypes: true });
90653
90835
  } catch (scanErr) {
90654
90836
  summary.errors.push(`scan: ${scanErr?.code || scanErr?.message || "readdir-failed"}`);
90655
90837
  return summary;
@@ -90659,11 +90841,11 @@ async function pruneTerminalTransactionRecords(transactionsRoot, {
90659
90841
  if (txnDirs.length <= retentionMax) return summary;
90660
90842
  const terminal = [];
90661
90843
  for (const entry of txnDirs) {
90662
- const recordDir = join18(transactionsRoot, entry.name);
90844
+ const recordDir = join20(transactionsRoot, entry.name);
90663
90845
  let state = null;
90664
90846
  let createdAt = null;
90665
90847
  try {
90666
- const raw = await readFile20(join18(recordDir, "journal.json"), "utf8");
90848
+ const raw = await readFile22(join20(recordDir, "journal.json"), "utf8");
90667
90849
  const journal = JSON.parse(raw);
90668
90850
  if (journal && typeof journal === "object") {
90669
90851
  state = typeof journal.state === "string" ? journal.state : null;
@@ -90676,7 +90858,7 @@ async function pruneTerminalTransactionRecords(transactionsRoot, {
90676
90858
  let sortTime = Date.parse(createdAt);
90677
90859
  if (!Number.isFinite(sortTime)) {
90678
90860
  try {
90679
- const dirStat = await stat5(recordDir);
90861
+ const dirStat = await stat6(recordDir);
90680
90862
  sortTime = dirStat.mtimeMs;
90681
90863
  } catch {
90682
90864
  sortTime = Number.MAX_SAFE_INTEGER;
@@ -90727,7 +90909,7 @@ async function createTransactionJournal({
90727
90909
  );
90728
90910
  if (typeof root === "string" && root.length > 0) {
90729
90911
  await pruneTerminalTransactionRecords(
90730
- join18(root, ".release-skill", "transactions"),
90912
+ join20(root, ".release-skill", "transactions"),
90731
90913
  { retentionMax }
90732
90914
  );
90733
90915
  }
@@ -94862,6 +95044,7 @@ var init_refresh_service = __esm({
94862
95044
  // src/commands/prepare.mjs
94863
95045
  var prepare_exports = {};
94864
95046
  __export(prepare_exports, {
95047
+ boundedOutputTail: () => boundedOutputTail,
94865
95048
  buildExternalActions: () => buildExternalActions,
94866
95049
  decodeExternalMarketplaceIndex: () => decodeExternalMarketplaceIndex,
94867
95050
  parseExternalMarketplaceLsRemote: () => parseExternalMarketplaceLsRemote,
@@ -94873,8 +95056,8 @@ __export(prepare_exports, {
94873
95056
  resolveUnitVersion: () => resolveUnitVersion,
94874
95057
  runDeclaredHooks: () => runDeclaredHooks
94875
95058
  });
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";
95059
+ import { resolve as resolve23, relative as relative22, isAbsolute as isAbsolute18, normalize as normalize3, dirname as dirname11, basename as basename7 } from "node:path";
95060
+ import { readFile as readFile23, mkdir as mkdir14, readdir as readdir15, realpath as realpath17 } from "node:fs/promises";
94878
95061
  import { execFile as execFileCb9 } from "node:child_process";
94879
95062
  import { promisify as promisify9 } from "node:util";
94880
95063
  async function resolveUnitVersion(unit, root, explicitVersion) {
@@ -94906,7 +95089,7 @@ async function resolveUnitVersion(unit, root, explicitVersion) {
94906
95089
  }
94907
95090
  let content;
94908
95091
  try {
94909
- content = await readFile21(normalizedPath, "utf8");
95092
+ content = await readFile23(normalizedPath, "utf8");
94910
95093
  } catch (err) {
94911
95094
  throw new ReleaseError(
94912
95095
  CONFIG_INVALID,
@@ -94968,17 +95151,38 @@ async function resolveAllUnitVersions(units, root, explicitVersion, evidence) {
94968
95151
  });
94969
95152
  return resolvedVersions;
94970
95153
  }
95154
+ function boundedOutputTail(text) {
95155
+ if (typeof text !== "string" || text.length === 0) return "";
95156
+ let lines = text.split("\n");
95157
+ if (lines.length > 1 && lines[lines.length - 1] === "") {
95158
+ lines = lines.slice(0, -1);
95159
+ }
95160
+ let tail2 = lines.slice(-HOOK_OUTPUT_TAIL_MAX_LINES);
95161
+ let joined = tail2.join("\n");
95162
+ while (tail2.length > 1 && Buffer.byteLength(joined, "utf8") > HOOK_OUTPUT_TAIL_MAX_BYTES) {
95163
+ tail2 = tail2.slice(1);
95164
+ joined = tail2.join("\n");
95165
+ }
95166
+ if (Buffer.byteLength(joined, "utf8") > HOOK_OUTPUT_TAIL_MAX_BYTES) {
95167
+ const buf = Buffer.from(joined, "utf8");
95168
+ joined = buf.subarray(buf.length - HOOK_OUTPUT_TAIL_MAX_BYTES).toString("utf8");
95169
+ }
95170
+ return joined;
95171
+ }
94971
95172
  async function runDeclaredHooks(config, root, evidence, hookFn = runHook, options = {}) {
94972
95173
  const hookOrder = ["docs", "build", "test", "typecheck"];
94973
95174
  const hooks = config.hooks ?? {};
94974
95175
  const cacheEnabled = options.hookCache !== false;
95176
+ const records = [];
94975
95177
  for (const name of hookOrder) {
94976
95178
  const hook = hooks[name];
94977
95179
  if (!hook) continue;
95180
+ const selectionField = name === "test" ? { testSelection: hook.testSelection === "incremental" ? "incremental" : "full" } : {};
94978
95181
  await evidence.append({
94979
95182
  phase: "hooks",
94980
95183
  status: "started",
94981
- hookName: name
95184
+ hookName: name,
95185
+ ...selectionField
94982
95186
  });
94983
95187
  let cacheKey;
94984
95188
  if (cacheEnabled && hook.cacheable === true) {
@@ -95000,8 +95204,10 @@ async function runDeclaredHooks(config, root, evidence, hookFn = runHook, option
95000
95204
  status: "completed",
95001
95205
  hookName: name,
95002
95206
  cached: true,
95003
- cacheKey
95207
+ cacheKey,
95208
+ ...selectionField
95004
95209
  });
95210
+ records.push({ name, completed: true, cached: true, testSelection: selectionField.testSelection });
95005
95211
  continue;
95006
95212
  }
95007
95213
  }
@@ -95016,7 +95222,8 @@ async function runDeclaredHooks(config, root, evidence, hookFn = runHook, option
95016
95222
  phase: "hooks",
95017
95223
  status: "failed",
95018
95224
  hookName: name,
95019
- error: { code: err.code, message: err.message }
95225
+ error: { code: err.code, message: err.message },
95226
+ ...selectionField
95020
95227
  });
95021
95228
  throw new ReleaseError(
95022
95229
  GATE_FAILED,
@@ -95025,16 +95232,31 @@ async function runDeclaredHooks(config, root, evidence, hookFn = runHook, option
95025
95232
  );
95026
95233
  }
95027
95234
  if (result.exitCode !== 0) {
95235
+ const stdoutTail = boundedOutputTail(result.stdout);
95236
+ const stderrTail = boundedOutputTail(result.stderr);
95237
+ process.stderr.write(`[release-skill] hook "${name}" failed with exit code ${result.exitCode}
95238
+ `);
95239
+ if (stdoutTail) {
95240
+ process.stderr.write(`[release-skill] hook "${name}" stdout tail:
95241
+ ${stdoutTail}
95242
+ `);
95243
+ }
95244
+ if (stderrTail) {
95245
+ process.stderr.write(`[release-skill] hook "${name}" stderr tail:
95246
+ ${stderrTail}
95247
+ `);
95248
+ }
95028
95249
  await evidence.append({
95029
95250
  phase: "hooks",
95030
95251
  status: "failed",
95031
95252
  hookName: name,
95032
95253
  exitCode: result.exitCode,
95033
95254
  // 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)
95255
+ // end. Preserve bounded tails (last 50 lines, capped at 8 KB) of both
95256
+ // streams instead of the noisy compiler prelude at the beginning.
95257
+ stdoutTail,
95258
+ stderrTail,
95259
+ ...selectionField
95038
95260
  });
95039
95261
  throw new ReleaseError(
95040
95262
  GATE_FAILED,
@@ -95062,9 +95284,12 @@ async function runDeclaredHooks(config, root, evidence, hookFn = runHook, option
95062
95284
  phase: "hooks",
95063
95285
  status: "completed",
95064
95286
  hookName: name,
95065
- exitCode: 0
95287
+ exitCode: 0,
95288
+ ...selectionField
95066
95289
  });
95290
+ records.push({ name, completed: true, cached: false, testSelection: selectionField.testSelection });
95067
95291
  }
95292
+ return records;
95068
95293
  }
95069
95294
  async function resolveReleaseDocsPlanFn(injected) {
95070
95295
  if (typeof injected === "function") return injected;
@@ -96021,7 +96246,7 @@ async function readLatestFrozenPlan(root) {
96021
96246
  const plansDir = resolve23(root, ".release-skill", "plans");
96022
96247
  let files;
96023
96248
  try {
96024
- files = await readdir14(plansDir);
96249
+ files = await readdir15(plansDir);
96025
96250
  } catch {
96026
96251
  return null;
96027
96252
  }
@@ -96030,7 +96255,7 @@ async function readLatestFrozenPlan(root) {
96030
96255
  if (!file.endsWith(".json")) continue;
96031
96256
  let plan;
96032
96257
  try {
96033
- plan = JSON.parse(await readFile21(resolve23(plansDir, file), "utf8"));
96258
+ plan = JSON.parse(await readFile23(resolve23(plansDir, file), "utf8"));
96034
96259
  } catch {
96035
96260
  continue;
96036
96261
  }
@@ -96055,7 +96280,8 @@ async function prepareRelease(options) {
96055
96280
  verificationGatesAuthorized,
96056
96281
  production = false,
96057
96282
  workflow = "full",
96058
- observePreviousPublicBaselineFn
96283
+ observePreviousPublicBaselineFn,
96284
+ testSelection = "full"
96059
96285
  } = options ?? {};
96060
96286
  const WORKFLOW_KINDS2 = /* @__PURE__ */ new Set(["full", "docs", "config", "marketplace"]);
96061
96287
  if (!WORKFLOW_KINDS2.has(workflow)) {
@@ -96065,6 +96291,20 @@ async function prepareRelease(options) {
96065
96291
  { workflow }
96066
96292
  );
96067
96293
  }
96294
+ if (testSelection === "incremental") {
96295
+ throw new ReleaseError(
96296
+ GATE_FAILED,
96297
+ "incremental selection is not allowed at freeze time",
96298
+ { testSelection, reservedFor: "preflight mode" }
96299
+ );
96300
+ }
96301
+ if (testSelection !== "full") {
96302
+ throw new ReleaseError(
96303
+ CONFIG_INVALID,
96304
+ `unknown testSelection "${testSelection}"; expected "full" or "incremental"`,
96305
+ { testSelection }
96306
+ );
96307
+ }
96068
96308
  const trimmedWorkflow = workflow !== "full";
96069
96309
  const skipDeclaredHooks = trimmedWorkflow;
96070
96310
  const skipSnapshotVerifyGates = trimmedWorkflow;
@@ -96128,6 +96368,34 @@ async function prepareRelease(options) {
96128
96368
  ...warning
96129
96369
  });
96130
96370
  }
96371
+ await evidence.append({ phase: "bundle-freshness", status: "started" });
96372
+ const bundleFreshnessFn = options.bundleFreshnessFn ?? assertBundleFreshness;
96373
+ let bundleFreshness;
96374
+ try {
96375
+ bundleFreshness = await bundleFreshnessFn(PKG_ROOT);
96376
+ } catch (err) {
96377
+ await evidence.append({
96378
+ phase: "bundle-freshness",
96379
+ status: "blocking",
96380
+ reason: err.details?.reason ?? null,
96381
+ error: { code: err.code, message: err.message }
96382
+ });
96383
+ throw err;
96384
+ }
96385
+ if (bundleFreshness?.applicable === false) {
96386
+ await evidence.append({
96387
+ phase: "bundle-freshness",
96388
+ status: "not-applicable",
96389
+ reason: bundleFreshness.reason
96390
+ });
96391
+ } else {
96392
+ await evidence.append({
96393
+ phase: "bundle-freshness",
96394
+ status: "completed",
96395
+ algorithm: bundleFreshness?.algorithm ?? null,
96396
+ sourceDigest: bundleFreshness?.sourceDigest ?? null
96397
+ });
96398
+ }
96131
96399
  await evidence.append({
96132
96400
  phase: "workflow",
96133
96401
  status: "configured",
@@ -96210,6 +96478,7 @@ async function prepareRelease(options) {
96210
96478
  }))
96211
96479
  });
96212
96480
  }
96481
+ let hookRecords = [];
96213
96482
  if (skipDeclaredHooks) {
96214
96483
  await evidence.append({
96215
96484
  phase: "hooks",
@@ -96218,7 +96487,7 @@ async function prepareRelease(options) {
96218
96487
  });
96219
96488
  } else {
96220
96489
  await evidence.append({ phase: "hooks", status: "started" });
96221
- await runDeclaredHooks(config, realRoot, evidence, options.runHookFn ?? runHook, {
96490
+ hookRecords = await runDeclaredHooks(config, realRoot, evidence, options.runHookFn ?? runHook, {
96222
96491
  hookCache: options.hookCache,
96223
96492
  // Explicit env delivery (0.5.1 hook-env-delivery fix): the hook runner
96224
96493
  // reads envAllowlist keys exclusively from context.env, so the invoking
@@ -96734,6 +97003,47 @@ async function prepareRelease(options) {
96734
97003
  await evidence.append({ phase: "remote-check", status: "skipped", reason: "offline mode" });
96735
97004
  }
96736
97005
  await evidence.append({ phase: "plan-assembly", status: "started" });
97006
+ if (skipDeclaredHooks) {
97007
+ await evidence.append({
97008
+ phase: "full-test-gate",
97009
+ status: "skipped",
97010
+ reason: `workflow "${workflow}" trims declared hooks`
97011
+ });
97012
+ } else if (!config.hooks?.test) {
97013
+ await evidence.append({
97014
+ phase: "full-test-gate",
97015
+ status: "not-declared",
97016
+ reason: "no test hook declared; nothing can run incrementally"
97017
+ });
97018
+ } else {
97019
+ const testRecord = hookRecords.find((record) => record.name === "test");
97020
+ const satisfied = Boolean(
97021
+ testRecord && testRecord.completed && testRecord.testSelection === "full"
97022
+ );
97023
+ if (!satisfied) {
97024
+ await evidence.append({
97025
+ phase: "full-test-gate",
97026
+ status: "blocking",
97027
+ testSelection: testRecord?.testSelection ?? null,
97028
+ cached: Boolean(testRecord?.cached)
97029
+ });
97030
+ throw new ReleaseError(
97031
+ GATE_FAILED,
97032
+ 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",
97033
+ {
97034
+ gate: "full-test-freeze",
97035
+ testSelection: testRecord?.testSelection ?? null,
97036
+ cached: Boolean(testRecord?.cached)
97037
+ }
97038
+ );
97039
+ }
97040
+ await evidence.append({
97041
+ phase: "full-test-gate",
97042
+ status: "completed",
97043
+ testSelection: "full",
97044
+ cached: Boolean(testRecord.cached)
97045
+ });
97046
+ }
96737
97047
  const createdAtTimestamp = production ? normalizeGitTimestamp(clock ? clock() : (/* @__PURE__ */ new Date()).toISOString(), "plan createdAt timestamp") : null;
96738
97048
  const freezeTimestamp = production ? await readHeadCommitTimestamp(realRoot, baseline.gitHead) : null;
96739
97049
  const productionAssets = production ? await buildProductionAssets(
@@ -96890,7 +97200,7 @@ async function prepareRelease(options) {
96890
97200
  const marketplaceIndexPath = resolve23(snapshotDir, marketplaceIndexRelative);
96891
97201
  let marketplaceIndexRaw;
96892
97202
  try {
96893
- marketplaceIndexRaw = await readFile21(marketplaceIndexPath, "utf8");
97203
+ marketplaceIndexRaw = await readFile23(marketplaceIndexPath, "utf8");
96894
97204
  } catch (err) {
96895
97205
  throw new ReleaseError(
96896
97206
  GATE_FAILED,
@@ -96959,7 +97269,7 @@ async function prepareRelease(options) {
96959
97269
  const pluginManifestPath = resolve23(snapshotDir, pluginManifestRelative);
96960
97270
  let raw;
96961
97271
  try {
96962
- raw = await readFile21(pluginManifestPath, "utf8");
97272
+ raw = await readFile23(pluginManifestPath, "utf8");
96963
97273
  } catch (err) {
96964
97274
  throw new ReleaseError(
96965
97275
  GATE_FAILED,
@@ -97196,6 +97506,19 @@ async function prepareRelease(options) {
97196
97506
  planPath: writtenPath,
97197
97507
  planDigest
97198
97508
  });
97509
+ await writeFrozenMarker(releaseDir, {
97510
+ planDigest,
97511
+ targetVersions: Object.fromEntries(
97512
+ configUnits.map((unit, index) => [unit.id, resolvedVersions[index]])
97513
+ ),
97514
+ createdAt: plan.createdAt,
97515
+ runId: basename7(runDir)
97516
+ });
97517
+ await evidence.append({
97518
+ phase: "frozen-marker",
97519
+ status: "written",
97520
+ markerPath: `.release-skill/${FROZEN_MARKER_FILENAME}`
97521
+ });
97199
97522
  await evidence.finish({
97200
97523
  status: "PREPARED",
97201
97524
  planPath: writtenPath,
@@ -97231,7 +97554,7 @@ async function prepareRelease(options) {
97231
97554
  await lock.release();
97232
97555
  }
97233
97556
  }
97234
- var execFile8, CONSUMER_INSTALL_RECIPE_VERSION2, EXTERNAL_MARKETPLACE_SHA_RE2;
97557
+ var execFile8, CONSUMER_INSTALL_RECIPE_VERSION2, HOOK_OUTPUT_TAIL_MAX_LINES, HOOK_OUTPUT_TAIL_MAX_BYTES, EXTERNAL_MARKETPLACE_SHA_RE2;
97235
97558
  var init_prepare = __esm({
97236
97559
  async "src/commands/prepare.mjs"() {
97237
97560
  await init_config();
@@ -97250,6 +97573,9 @@ var init_prepare = __esm({
97250
97573
  init_contract2();
97251
97574
  init_frozen();
97252
97575
  init_errors();
97576
+ init_bundle_freshness();
97577
+ init_pkg_root();
97578
+ init_frozen_marker();
97253
97579
  init_source_authority();
97254
97580
  init_project_lock();
97255
97581
  init_previous_public_baseline();
@@ -97263,6 +97589,9 @@ var init_prepare = __esm({
97263
97589
  CONSUMER_INSTALL_RECIPE_VERSION2 = "consumer-install-v1";
97264
97590
  __name(resolveUnitVersion, "resolveUnitVersion");
97265
97591
  __name(resolveAllUnitVersions, "resolveAllUnitVersions");
97592
+ HOOK_OUTPUT_TAIL_MAX_LINES = 50;
97593
+ HOOK_OUTPUT_TAIL_MAX_BYTES = 8 * 1024;
97594
+ __name(boundedOutputTail, "boundedOutputTail");
97266
97595
  __name(runDeclaredHooks, "runDeclaredHooks");
97267
97596
  __name(resolveReleaseDocsPlanFn, "resolveReleaseDocsPlanFn");
97268
97597
  __name(runReleaseDocsFreshnessGate, "runReleaseDocsFreshnessGate");
@@ -97332,8 +97661,8 @@ var init_hooks2 = __esm({
97332
97661
  });
97333
97662
 
97334
97663
  // 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";
97664
+ import { readFile as readFile24 } from "node:fs/promises";
97665
+ import { basename as basename8, dirname as dirname12, join as join21, resolve as resolve25 } from "node:path";
97337
97666
  function validateApprovalRecordSchema(approval) {
97338
97667
  if (validateApprovalSchema(approval)) return;
97339
97668
  const errors = validateApprovalSchema.errors ?? [];
@@ -97352,7 +97681,7 @@ function assertImmutableApprovalAuthority(approvalPath, plan, rawApproval) {
97352
97681
  const approvalDigest = computeApprovalDigest(rawApproval);
97353
97682
  const absolute = resolve25(approvalPath);
97354
97683
  const planDirectory = dirname12(absolute);
97355
- if (basename7(absolute) !== `${approvalDigest}.json` || basename7(planDirectory) !== planDigest || basename7(dirname12(planDirectory)) !== "approvals") {
97684
+ if (basename8(absolute) !== `${approvalDigest}.json` || basename8(planDirectory) !== planDigest || basename8(dirname12(planDirectory)) !== "approvals") {
97356
97685
  throw new ReleaseError(
97357
97686
  GATE_FAILED,
97358
97687
  "production commands require approvals/<planDigest>/<approvalDigest>.json immutable authority",
@@ -97619,8 +97948,8 @@ var approve_exports = {};
97619
97948
  __export(approve_exports, {
97620
97949
  approvePlan: () => approvePlan
97621
97950
  });
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";
97951
+ import { readFile as readFile25, writeFile as writeFile7 } from "node:fs/promises";
97952
+ import { resolve as resolve26, dirname as dirname13, basename as basename9 } from "node:path";
97624
97953
  function defaultClock() {
97625
97954
  return (/* @__PURE__ */ new Date()).toISOString();
97626
97955
  }
@@ -97643,7 +97972,7 @@ async function approvePlan(options) {
97643
97972
  }
97644
97973
  let planRaw;
97645
97974
  try {
97646
- planRaw = await readFile23(planPath, "utf8");
97975
+ planRaw = await readFile25(planPath, "utf8");
97647
97976
  } catch (err) {
97648
97977
  throw new ReleaseError(
97649
97978
  GATE_FAILED,
@@ -97749,7 +98078,7 @@ async function approvePlan(options) {
97749
98078
  };
97750
98079
  validateApprovalRecordSchema(approvalRecord);
97751
98080
  const planDir = dirname13(resolve26(planPath));
97752
- const releaseDir = basename8(planDir) === "plans" && basename8(planPath) === `${actualDigest}.json` ? dirname13(planDir) : planDir;
98081
+ const releaseDir = basename9(planDir) === "plans" && basename9(planPath) === `${actualDigest}.json` ? dirname13(planDir) : planDir;
97753
98082
  if (plan.production?.mode === "github-npm-v1" && outputPath && resolve26(outputPath) !== resolve26(releaseDir, "approval-record.json")) {
97754
98083
  throw new ReleaseError(
97755
98084
  GATE_FAILED,
@@ -97768,10 +98097,10 @@ async function approvePlan(options) {
97768
98097
  await prepareAuthorityDirectory(dirname13(immutableApprovalPath));
97769
98098
  await assertAuthorityFileTarget(immutableApprovalPath);
97770
98099
  try {
97771
- await writeFile6(immutableApprovalPath, json, { encoding: "utf8", flag: "wx", mode: 384 });
98100
+ await writeFile7(immutableApprovalPath, json, { encoding: "utf8", flag: "wx", mode: 384 });
97772
98101
  } catch (error) {
97773
98102
  if (error.code !== "EEXIST") throw error;
97774
- const existing = await readFile23(immutableApprovalPath, "utf8");
98103
+ const existing = await readFile25(immutableApprovalPath, "utf8");
97775
98104
  if (existing !== json) {
97776
98105
  throw new ReleaseError(
97777
98106
  GATE_FAILED,
@@ -97783,7 +98112,7 @@ async function approvePlan(options) {
97783
98112
  const writePath = outputPath ?? resolve26(releaseDir, "approval-record.json");
97784
98113
  await prepareAuthorityDirectory(dirname13(writePath));
97785
98114
  await assertAuthorityFileTarget(writePath);
97786
- await writeFile6(writePath, json, "utf8");
98115
+ await writeFile7(writePath, json, "utf8");
97787
98116
  return Object.freeze({
97788
98117
  ...approvalRecord,
97789
98118
  approvalDigest,
@@ -98073,8 +98402,8 @@ __export(publish_exports, {
98073
98402
  classifyPreObservation: () => classifyPreObservation,
98074
98403
  publishRelease: () => publishRelease
98075
98404
  });
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";
98405
+ import { readFile as readFile26, mkdir as mkdir16 } from "node:fs/promises";
98406
+ import { isAbsolute as isAbsolute19, join as join22, relative as relative23 } from "node:path";
98078
98407
  function assertInsideAssetRoot(assetRoot, candidate, label) {
98079
98408
  const rel = relative23(assetRoot, candidate);
98080
98409
  if (rel === "" || isAbsolute19(rel) || rel === ".." || rel.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`)) {
@@ -98306,7 +98635,7 @@ async function publishRelease(options) {
98306
98635
  const captureBaselineActual = typeof captureBaselineFn === "function" ? captureBaselineFn : captureBaseline;
98307
98636
  let planRaw;
98308
98637
  try {
98309
- planRaw = await readFile24(planPath, "utf8");
98638
+ planRaw = await readFile26(planPath, "utf8");
98310
98639
  } catch (err) {
98311
98640
  throw new ReleaseError(GATE_FAILED, `cannot read release plan: ${err.message}`, { planPath, cause: err.code });
98312
98641
  }
@@ -98464,7 +98793,7 @@ async function publishRelease(options) {
98464
98793
  await evidence.append({ phase: "safety-gate", gate: "approval-load", status: "started" });
98465
98794
  let approvalRaw;
98466
98795
  try {
98467
- approvalRaw = await readFile24(approvalPath, "utf8");
98796
+ approvalRaw = await readFile26(approvalPath, "utf8");
98468
98797
  } catch (err) {
98469
98798
  throw new ReleaseError(
98470
98799
  GATE_FAILED,
@@ -98778,7 +99107,7 @@ async function publishRelease(options) {
98778
99107
  }
98779
99108
  }
98780
99109
  await evidence.append({ phase: "safety-gate", gate: "global-preflight", status: "passed" });
98781
- const runPath = join20(runDir, "release-run.json");
99110
+ const runPath = join22(runDir, "release-run.json");
98782
99111
  const checkpoints = orderedActions.map((action) => {
98783
99112
  if (isMarketplaceAction(action.type)) {
98784
99113
  return {
@@ -99051,8 +99380,8 @@ var reconcile_exports = {};
99051
99380
  __export(reconcile_exports, {
99052
99381
  reconcileRelease: () => reconcileRelease
99053
99382
  });
99054
- import { readFile as readFile25, mkdir as mkdir17 } from "node:fs/promises";
99055
- import { join as join21 } from "node:path";
99383
+ import { readFile as readFile27, mkdir as mkdir17 } from "node:fs/promises";
99384
+ import { join as join23 } from "node:path";
99056
99385
  function defaultClock4() {
99057
99386
  return (/* @__PURE__ */ new Date()).toISOString();
99058
99387
  }
@@ -99080,7 +99409,7 @@ async function reconcileRelease(options) {
99080
99409
  }
99081
99410
  let planRaw;
99082
99411
  try {
99083
- planRaw = await readFile25(planPath, "utf8");
99412
+ planRaw = await readFile27(planPath, "utf8");
99084
99413
  } catch (err) {
99085
99414
  throw new ReleaseError(GATE_FAILED, `cannot read release plan: ${err.message}`, { planPath, cause: err.code });
99086
99415
  }
@@ -99202,7 +99531,7 @@ async function reconcileRelease(options) {
99202
99531
  { sourceRunId: sourceRun.runId }
99203
99532
  );
99204
99533
  }
99205
- const sourceApprovalRaw = await readFile25(consumedApprovalPath, "utf8").catch((error) => {
99534
+ const sourceApprovalRaw = await readFile27(consumedApprovalPath, "utf8").catch((error) => {
99206
99535
  throw new ReleaseError(GATE_FAILED, "source run approval authority is unavailable", {
99207
99536
  sourceRunId: sourceRun.runId,
99208
99537
  cause: error.code
@@ -99364,7 +99693,7 @@ async function reconcileRelease(options) {
99364
99693
  if (approvalPath) {
99365
99694
  let approvalRaw;
99366
99695
  try {
99367
- approvalRaw = await readFile25(approvalPath, "utf8");
99696
+ approvalRaw = await readFile27(approvalPath, "utf8");
99368
99697
  } catch (err) {
99369
99698
  throw new ReleaseError(
99370
99699
  GATE_FAILED,
@@ -99977,7 +100306,7 @@ async function reconcileRelease(options) {
99977
100306
  ...normalized === "deferred" ? { reason: CONSUMER_VERIFICATION_DEFERRED, phase: "post-publish-verification" } : {}
99978
100307
  };
99979
100308
  });
99980
- const runPath = join21(runDir, "release-run.json");
100309
+ const runPath = join23(runDir, "release-run.json");
99981
100310
  const sourceRunDigest = sourceAuthorityDigest;
99982
100311
  const runState = {
99983
100312
  runId,
@@ -100057,7 +100386,7 @@ var init_reconcile = __esm({
100057
100386
  });
100058
100387
 
100059
100388
  // src/core/baseline-advance.mjs
100060
- import { readFile as readFile26, writeFile as writeFile7 } from "node:fs/promises";
100389
+ import { readFile as readFile28, writeFile as writeFile8 } from "node:fs/promises";
100061
100390
  import { execFile as execFileCb10 } from "node:child_process";
100062
100391
  import { promisify as promisify10 } from "node:util";
100063
100392
  function defaultExec(command2, args2, options = {}) {
@@ -100091,7 +100420,7 @@ async function applyBaselineAdvances({ configPath, advances, validateFn }) {
100091
100420
  }
100092
100421
  let content;
100093
100422
  try {
100094
- content = await readFile26(configPath, "utf8");
100423
+ content = await readFile28(configPath, "utf8");
100095
100424
  } catch (err) {
100096
100425
  throw new ReleaseError(
100097
100426
  GATE_FAILED,
@@ -100133,12 +100462,12 @@ async function applyBaselineAdvances({ configPath, advances, validateFn }) {
100133
100462
  return { changed: false, updatedUnits: [] };
100134
100463
  }
100135
100464
  const next = doc.toString();
100136
- await writeFile7(configPath, next, "utf8");
100465
+ await writeFile8(configPath, next, "utf8");
100137
100466
  if (typeof validateFn === "function") {
100138
100467
  try {
100139
100468
  await validateFn(configPath);
100140
100469
  } catch (err) {
100141
- await writeFile7(configPath, content, "utf8");
100470
+ await writeFile8(configPath, content, "utf8");
100142
100471
  throw new ReleaseError(
100143
100472
  GATE_FAILED,
100144
100473
  `baseline advance reverted: rewritten config failed validation: ${err.message}`,
@@ -100185,9 +100514,9 @@ __export(verify_exports, {
100185
100514
  runSmokeTest: () => runSmokeTest,
100186
100515
  verifyRelease: () => verifyRelease
100187
100516
  });
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";
100517
+ 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
100518
  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";
100519
+ import { dirname as dirname14, join as join24, relative as relative24, isAbsolute as isAbsolute20, resolve as resolve27, basename as basename10 } from "node:path";
100191
100520
  import { tmpdir as tmpdir4 } from "node:os";
100192
100521
  import { execFile as execFileCb11 } from "node:child_process";
100193
100522
  import { promisify as promisify11 } from "node:util";
@@ -100240,18 +100569,18 @@ async function collectMissingManualAttestations({
100240
100569
  const isKimi = action.type === "kimi-marketplace-install";
100241
100570
  const planDigest = isKimi ? resolveBoundPlanDigest(context) : await resolveCodeBuddyBoundPlanDigest(context);
100242
100571
  const authorityDir = isKimi ? kimiAuthorityDir(context, planDigest, action.parameters.plugin) : codebuddyAuthorityDir(context, planDigest, action.parameters.plugin);
100243
- const requirementPath = join22(
100572
+ const requirementPath = join24(
100244
100573
  authorityDir,
100245
100574
  isKimi ? KIMI_REQUIREMENT_FILE : CODEBUDDY_REQUIREMENT_FILE
100246
100575
  );
100247
- const attestationPath = join22(
100576
+ const attestationPath = join24(
100248
100577
  authorityDir,
100249
100578
  isKimi ? KIMI_ATTESTATION_FILE : CODEBUDDY_ATTESTATION_FILE
100250
100579
  );
100251
100580
  let valid = false;
100252
100581
  let reason = "attestation file is missing";
100253
100582
  try {
100254
- const attestation = JSON.parse(await readFile27(attestationPath, "utf8"));
100583
+ const attestation = JSON.parse(await readFile29(attestationPath, "utf8"));
100255
100584
  const validation = isKimi ? validateKimiAttestation(attestation, action.parameters, clockFn(), planDigest) : validateCodeBuddyAttestation(attestation, action.parameters, clockFn(), planDigest);
100256
100585
  valid = validation.valid;
100257
100586
  reason = validation.error;
@@ -100293,7 +100622,7 @@ function matchesSubset2(actual, expected) {
100293
100622
  async function runSmokeTest(plan, root, options = {}) {
100294
100623
  const baseDir = options.baseDir ?? tmpdir4();
100295
100624
  await mkdir18(baseDir, { recursive: true });
100296
- const tmpDir = await mkdtemp7(join22(baseDir, "verify-smoke-"));
100625
+ const tmpDir = await mkdtemp7(join24(baseDir, "verify-smoke-"));
100297
100626
  const npmExec = options.npmExecutor ?? defaultNpmExecutor;
100298
100627
  const installFlags = [
100299
100628
  "--ignore-scripts",
@@ -100341,7 +100670,7 @@ async function runSmokeTest(plan, root, options = {}) {
100341
100670
  for (const { package: pkgName, registry, targetVersion, unitId, smokeBin, smokeArgs, smokeExpectedJson } of npmDistributions) {
100342
100671
  const packageAtVersion = `${pkgName}@${targetVersion}`;
100343
100672
  const installDir = resolveUnitScopedPath(tmpDir, unitId);
100344
- await mkdir18(join22(installDir, "node_modules"), { recursive: true });
100673
+ await mkdir18(join24(installDir, "node_modules"), { recursive: true });
100345
100674
  const registryFlags = [...installFlags, "--registry", registry];
100346
100675
  const installResult = await npmExec.install(
100347
100676
  packageAtVersion,
@@ -100359,10 +100688,10 @@ async function runSmokeTest(plan, root, options = {}) {
100359
100688
  }
100360
100689
  };
100361
100690
  }
100362
- const installedPkgPath = join22(installDir, "node_modules", pkgName, "package.json");
100691
+ const installedPkgPath = join24(installDir, "node_modules", pkgName, "package.json");
100363
100692
  let installedPkg;
100364
100693
  try {
100365
- installedPkg = JSON.parse(await readFile27(installedPkgPath, "utf8"));
100694
+ installedPkg = JSON.parse(await readFile29(installedPkgPath, "utf8"));
100366
100695
  } catch {
100367
100696
  return {
100368
100697
  passed: false,
@@ -100393,7 +100722,7 @@ async function runSmokeTest(plan, root, options = {}) {
100393
100722
  }
100394
100723
  };
100395
100724
  }
100396
- const pkgRoot = join22(installDir, "node_modules", pkgName);
100725
+ const pkgRoot = join24(installDir, "node_modules", pkgName);
100397
100726
  {
100398
100727
  const dirIndex = await buildDirectoryFileIndex(pkgRoot);
100399
100728
  const closureResult = checkNpmEntryClosure(installedPkg, dirIndex);
@@ -100622,7 +100951,7 @@ async function runSmokeTest(plan, root, options = {}) {
100622
100951
  }
100623
100952
  async function discoverDistributeRuns({ planPath, plan }) {
100624
100953
  const planDir = dirname14(planPath);
100625
- const releaseDir = basename9(planDir) === "plans" ? dirname14(planDir) : planDir;
100954
+ const releaseDir = basename10(planDir) === "plans" ? dirname14(planDir) : planDir;
100626
100955
  const runsDir = resolve27(releaseDir, "runs");
100627
100956
  try {
100628
100957
  const runsDirStat = await lstat21(runsDir);
@@ -100654,7 +100983,7 @@ async function discoverDistributeRuns({ planPath, plan }) {
100654
100983
  return null;
100655
100984
  }
100656
100985
  const candidates = [];
100657
- const entries = await readdir15(runsDir, { withFileTypes: true });
100986
+ const entries = await readdir16(runsDir, { withFileTypes: true });
100658
100987
  for (const entry of entries) {
100659
100988
  if (!entry.name.startsWith("distribute-")) continue;
100660
100989
  if (!entry.isDirectory() || entry.isSymbolicLink()) {
@@ -100719,7 +101048,7 @@ async function verifyRelease(options) {
100719
101048
  }
100720
101049
  let planRaw;
100721
101050
  try {
100722
- planRaw = await readFile27(planPath, "utf8");
101051
+ planRaw = await readFile29(planPath, "utf8");
100723
101052
  } catch (err) {
100724
101053
  throw new ReleaseError(
100725
101054
  GATE_FAILED,
@@ -100808,7 +101137,7 @@ async function verifyRelease(options) {
100808
101137
  }
100809
101138
  let approvalRaw;
100810
101139
  try {
100811
- approvalRaw = await readFile27(sourceRun.approvalPath, "utf8");
101140
+ approvalRaw = await readFile29(sourceRun.approvalPath, "utf8");
100812
101141
  } catch (error) {
100813
101142
  throw new ReleaseError(
100814
101143
  GATE_FAILED,
@@ -100884,7 +101213,7 @@ async function verifyRelease(options) {
100884
101213
  const actions = plan.externalActions ?? [];
100885
101214
  const trustedVerifyRuns = [];
100886
101215
  const planDir = dirname14(planPath);
100887
- const releaseDir = basename9(planDir) === "plans" ? dirname14(planDir) : planDir;
101216
+ const releaseDir = basename10(planDir) === "plans" ? dirname14(planDir) : planDir;
100888
101217
  const runsDir = resolve27(releaseDir, "runs");
100889
101218
  let runsDirReal = null;
100890
101219
  let authorityDirReal = null;
@@ -100927,7 +101256,7 @@ async function verifyRelease(options) {
100927
101256
  runsDirReal = null;
100928
101257
  }
100929
101258
  if (runsDirReal) {
100930
- const entries = await readdir15(runsDirReal, { withFileTypes: true });
101259
+ const entries = await readdir16(runsDirReal, { withFileTypes: true });
100931
101260
  for (const entry of entries) {
100932
101261
  if (!entry.name.startsWith("verify-")) continue;
100933
101262
  if (!entry.isDirectory() || entry.isSymbolicLink()) {
@@ -101379,7 +101708,7 @@ async function verifyRelease(options) {
101379
101708
  assertTransition(PUBLISHED, VERIFIED);
101380
101709
  await evidence.append({ phase: "verify", status: "completed", overallStatus: VERIFIED });
101381
101710
  const sourceRunDigest = sourceRun.runDigest ?? computeRunDigest(sourceRun);
101382
- const verifyRunPath = join22(runDir, "release-run.json");
101711
+ const verifyRunPath = join24(runDir, "release-run.json");
101383
101712
  const verifyRunState = {
101384
101713
  runId,
101385
101714
  command: "verify",
@@ -101421,11 +101750,24 @@ async function verifyRelease(options) {
101421
101750
  finishedAt: clockFn()
101422
101751
  };
101423
101752
  const persistedVerifyRun = await writeRunAtomic(verifyRunPath, verifyRunState);
101753
+ try {
101754
+ const removed = await clearFrozenMarker(join24(root, ".release-skill"));
101755
+ await evidence.append({
101756
+ phase: "frozen-marker",
101757
+ status: removed ? "cleared" : "absent"
101758
+ });
101759
+ } catch (err) {
101760
+ await evidence.append({
101761
+ phase: "frozen-marker",
101762
+ status: "clear-failed",
101763
+ error: { code: err.code, message: err.message }
101764
+ });
101765
+ }
101424
101766
  let baselineAdvance = null;
101425
101767
  const baselineAdvances = deriveBaselineAdvances(plan);
101426
101768
  if (baselineAdvances.length > 0) {
101427
101769
  try {
101428
- const configAbs = configPathOpt ? isAbsolute20(configPathOpt) ? configPathOpt : join22(root, configPathOpt) : join22(root, ".release-skill/project.yaml");
101770
+ const configAbs = configPathOpt ? isAbsolute20(configPathOpt) ? configPathOpt : join24(root, configPathOpt) : join24(root, ".release-skill/project.yaml");
101429
101771
  const cleanBefore = await isWorktreeFileClean({ root, filePath: configAbs, execFn });
101430
101772
  const applyResult = await applyBaselineAdvances({
101431
101773
  configPath: configAbs,
@@ -101508,6 +101850,7 @@ var init_verify = __esm({
101508
101850
  init_baseline_advance();
101509
101851
  await init_config();
101510
101852
  init_state_machine();
101853
+ init_frozen_marker();
101511
101854
  init_public_path();
101512
101855
  init_npm();
101513
101856
  init_verification_gates();
@@ -101549,8 +101892,8 @@ var init_verify = __esm({
101549
101892
  exec: execFile9,
101550
101893
  env: process.env
101551
101894
  });
101552
- const userConfig = join22(cwd, ".release-skill-npmrc");
101553
- await writeFile8(
101895
+ const userConfig = join24(cwd, ".release-skill-npmrc");
101896
+ await writeFile9(
101554
101897
  userConfig,
101555
101898
  `registry=${normalizedRegistry}/
101556
101899
  ${registryTokenKey(normalizedRegistry)}=${token}
@@ -101612,10 +101955,10 @@ __export(distribute_exports, {
101612
101955
  });
101613
101956
  import { execFile as execFileCb12 } from "node:child_process";
101614
101957
  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";
101958
+ import { realpath as realpath19, lstat as lstat22, mkdir as mkdir19, readFile as readFile30, rm as rm11 } from "node:fs/promises";
101616
101959
  import { mkdtemp as mkdtemp8 } from "node:fs/promises";
101617
101960
  import { tmpdir as tmpdir5 } from "node:os";
101618
- import { isAbsolute as isAbsolute21, join as join23, relative as relative25, resolve as resolve28 } from "node:path";
101961
+ import { isAbsolute as isAbsolute21, join as join25, relative as relative25, resolve as resolve28 } from "node:path";
101619
101962
  function defaultClock6() {
101620
101963
  return (/* @__PURE__ */ new Date()).toISOString();
101621
101964
  }
@@ -101712,7 +102055,7 @@ async function distributeRelease(options) {
101712
102055
  const hookRunner = typeof runHookFn === "function" ? runHookFn : runHook;
101713
102056
  let planRaw;
101714
102057
  try {
101715
- planRaw = await readFile28(planPath, "utf8");
102058
+ planRaw = await readFile30(planPath, "utf8");
101716
102059
  } catch (err) {
101717
102060
  throw new ReleaseError(GATE_FAILED, `cannot read release plan: ${err.message}`, { planPath, cause: err.code });
101718
102061
  }
@@ -101746,7 +102089,7 @@ async function distributeRelease(options) {
101746
102089
  } else {
101747
102090
  await mkdir19(runDir, { recursive: true });
101748
102091
  }
101749
- const runPath = join23(runDir, "release-run.json");
102092
+ const runPath = join25(runDir, "release-run.json");
101750
102093
  const evidence = createEvidenceWriter({ runDir, command: "distribute", clock: clockFn });
101751
102094
  let lineageKnown = false;
101752
102095
  let sourceRunId = null;
@@ -101821,7 +102164,7 @@ async function distributeRelease(options) {
101821
102164
  await evidence.append({ phase: "safety-gate", gate: "approval-load", status: "started" });
101822
102165
  let approvalRaw;
101823
102166
  try {
101824
- approvalRaw = await readFile28(approvalPath, "utf8");
102167
+ approvalRaw = await readFile30(approvalPath, "utf8");
101825
102168
  } catch (err) {
101826
102169
  throw new ReleaseError(GATE_FAILED, `cannot read approval record: ${err.message}`, { approvalPath, cause: err.code });
101827
102170
  }
@@ -102041,8 +102384,8 @@ async function distributeRelease(options) {
102041
102384
  }
102042
102385
  await evidence.append({ phase: "worktree", status: "started", tagCommit: postPublish.tagCommit });
102043
102386
  try {
102044
- tmpBase = await mkdtemp8(join23(tmpdir5(), "release-skill-distribute-"));
102045
- worktreePath = join23(tmpBase, "worktree");
102387
+ tmpBase = await mkdtemp8(join25(tmpdir5(), "release-skill-distribute-"));
102388
+ worktreePath = join25(tmpBase, "worktree");
102046
102389
  await exec("git", ["-C", root, "worktree", "add", "--detach", worktreePath, postPublish.tagCommit]);
102047
102390
  } catch (err) {
102048
102391
  await evidence.append({ phase: "worktree", status: "failed", error: tail(err?.stderr ?? err?.message) });
@@ -102545,7 +102888,7 @@ var release_metadata_exports = {};
102545
102888
  __export(release_metadata_exports, {
102546
102889
  updatePreviousPublicBaselines: () => updatePreviousPublicBaselines
102547
102890
  });
102548
- import { lstat as lstat23, readFile as readFile29, rename as rename4, rm as rm12, writeFile as writeFile9 } from "node:fs/promises";
102891
+ import { lstat as lstat23, readFile as readFile31, rename as rename4, rm as rm12, writeFile as writeFile10 } from "node:fs/promises";
102549
102892
  import { resolve as resolve29 } from "node:path";
102550
102893
  function assertOid(value, label) {
102551
102894
  if (typeof value !== "string" || !/^[a-f0-9]{40,64}$/.test(value)) {
@@ -102561,8 +102904,8 @@ async function updatePreviousPublicBaselines(options = {}) {
102561
102904
  let configStat;
102562
102905
  try {
102563
102906
  [plan, configRaw, configStat] = await Promise.all([
102564
- readFile29(planPath, "utf8").then(JSON.parse),
102565
- readFile29(configPath, "utf8"),
102907
+ readFile31(planPath, "utf8").then(JSON.parse),
102908
+ readFile31(configPath, "utf8"),
102566
102909
  lstat23(configPath)
102567
102910
  ]);
102568
102911
  } catch (error) {
@@ -102624,7 +102967,7 @@ async function updatePreviousPublicBaselines(options = {}) {
102624
102967
  }
102625
102968
  const tempPath = `${configPath}.${process.pid}.${Date.now()}.tmp`;
102626
102969
  try {
102627
- await writeFile9(tempPath, nextRaw, {
102970
+ await writeFile10(tempPath, nextRaw, {
102628
102971
  encoding: "utf8",
102629
102972
  mode: configStat.mode & 511,
102630
102973
  flag: "wx"
@@ -102652,7 +102995,7 @@ var ship_exports = {};
102652
102995
  __export(ship_exports, {
102653
102996
  advanceShip: () => advanceShip
102654
102997
  });
102655
- import { readFile as readFile30, lstat as lstat24, mkdir as mkdir20, rename as rename5, rm as rm13, writeFile as writeFile10 } from "node:fs/promises";
102998
+ import { readFile as readFile32, lstat as lstat24, mkdir as mkdir20, rename as rename5, rm as rm13, writeFile as writeFile11 } from "node:fs/promises";
102656
102999
  import { dirname as dirname15, resolve as resolve30 } from "node:path";
102657
103000
  async function writeJsonAtomic(path15, value) {
102658
103001
  await mkdir20(dirname15(path15), { recursive: true });
@@ -102663,7 +103006,7 @@ async function writeJsonAtomic(path15, value) {
102663
103006
  stateDigest: sha256Hex(canonicalJson2(body))
102664
103007
  };
102665
103008
  try {
102666
- await writeFile10(temp, `${JSON.stringify(sealed, null, 2)}
103009
+ await writeFile11(temp, `${JSON.stringify(sealed, null, 2)}
102667
103010
  `, {
102668
103011
  encoding: "utf8",
102669
103012
  mode: 384,
@@ -102678,11 +103021,11 @@ async function writeJsonAtomic(path15, value) {
102678
103021
  }
102679
103022
  async function readState(path15) {
102680
103023
  try {
102681
- const stat9 = await lstat24(path15);
102682
- if (!stat9.isFile() || stat9.isSymbolicLink()) {
103024
+ const stat10 = await lstat24(path15);
103025
+ if (!stat10.isFile() || stat10.isSymbolicLink()) {
102683
103026
  throw new Error("ship state must be a regular non-symlink file");
102684
103027
  }
102685
- const state = JSON.parse(await readFile30(path15, "utf8"));
103028
+ const state = JSON.parse(await readFile32(path15, "utf8"));
102686
103029
  const { stateDigest, ...body } = state;
102687
103030
  if (typeof stateDigest !== "string" || stateDigest !== sha256Hex(canonicalJson2(body)) || body.statePath !== path15) {
102688
103031
  throw new Error("ship state digest or authority path does not match");
@@ -102755,7 +103098,7 @@ function publicState(state) {
102755
103098
  }
102756
103099
  async function buildApprovalSummary(planPath) {
102757
103100
  try {
102758
- const plan = JSON.parse(await readFile30(planPath, "utf8"));
103101
+ const plan = JSON.parse(await readFile32(planPath, "utf8"));
102759
103102
  const units = (plan.units ?? []).map((unit) => ({
102760
103103
  id: unit.id,
102761
103104
  targetVersion: unit.targetVersion ?? unit.version
@@ -102825,7 +103168,7 @@ async function advanceShip(options = {}, injected = {}) {
102825
103168
  });
102826
103169
  let transportPreflight = null;
102827
103170
  if (deps.preflightGitTransports) {
102828
- const frozenPlan = JSON.parse(await readFile30(prepared.planPath, "utf8"));
103171
+ const frozenPlan = JSON.parse(await readFile32(prepared.planPath, "utf8"));
102829
103172
  transportPreflight = await deps.preflightGitTransports(frozenPlan);
102830
103173
  process.env.RELEASE_SKILL_GIT_TRANSPORT = transportPreflight.transport;
102831
103174
  }
@@ -102909,7 +103252,7 @@ async function advanceShip(options = {}, injected = {}) {
102909
103252
  await writeJsonAtomic(statePath, state);
102910
103253
  }
102911
103254
  if (state.status === "PUBLISHED" || state.status === "NEEDS_MANUAL_ATTESTATIONS") {
102912
- const plan = JSON.parse(await readFile30(state.planPath, "utf8"));
103255
+ const plan = JSON.parse(await readFile32(state.planPath, "utf8"));
102913
103256
  const needsDistribution = plan.postPublish && plan.postPublish.targets && plan.postPublish.targets.length > 0;
102914
103257
  if (needsDistribution && deps.distributeRelease) {
102915
103258
  state.status = "DISTRIBUTING";
@@ -103571,8 +103914,8 @@ var attest_exports = {};
103571
103914
  __export(attest_exports, {
103572
103915
  recordManualAttestation: () => recordManualAttestation
103573
103916
  });
103574
- import { readFile as readFile31 } from "node:fs/promises";
103575
- import { resolve as resolve31, join as join24 } from "node:path";
103917
+ import { readFile as readFile33 } from "node:fs/promises";
103918
+ import { resolve as resolve31, join as join26 } from "node:path";
103576
103919
  async function validateInstalledConsumerClosure({
103577
103920
  root,
103578
103921
  platform,
@@ -103589,7 +103932,7 @@ async function validateInstalledConsumerClosure({
103589
103932
  ]);
103590
103933
  let plan;
103591
103934
  try {
103592
- plan = JSON.parse(await readFile31(planPath, "utf8"));
103935
+ plan = JSON.parse(await readFile33(planPath, "utf8"));
103593
103936
  } catch (error) {
103594
103937
  throw new ReleaseError(
103595
103938
  GATE_FAILED,
@@ -103660,10 +104003,10 @@ async function recordManualAttestation(options = {}, injected = {}) {
103660
104003
  throw new ReleaseError(MISSING_PARAMETERS, "attest requires --result <passed|failed>");
103661
104004
  }
103662
104005
  const authorityDir = resolve31(root, ".release-skill", descriptor.directory, plugin);
103663
- const requirementPath = join24(authorityDir, descriptor.requirementFile);
104006
+ const requirementPath = join26(authorityDir, descriptor.requirementFile);
103664
104007
  let requirement;
103665
104008
  try {
103666
- requirement = JSON.parse(await readFile31(requirementPath, "utf8"));
104009
+ requirement = JSON.parse(await readFile33(requirementPath, "utf8"));
103667
104010
  } catch (error) {
103668
104011
  throw new ReleaseError(
103669
104012
  GATE_FAILED,
@@ -103713,7 +104056,7 @@ async function recordManualAttestation(options = {}, injected = {}) {
103713
104056
  extraInstalledPaths: installBinding.extraInstalledPaths
103714
104057
  } : {}
103715
104058
  };
103716
- const attestationPath = join24(authorityDir, requirement.attestationFile);
104059
+ const attestationPath = join26(authorityDir, requirement.attestationFile);
103717
104060
  await writeEvidenceAtomic(attestationPath, receipt);
103718
104061
  return {
103719
104062
  command: "attest",
@@ -103747,9 +104090,9 @@ var init_attest = __esm({
103747
104090
  });
103748
104091
 
103749
104092
  // 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";
104093
+ import { readFile as readFile34 } from "node:fs/promises";
104094
+ import { join as join27 } from "node:path";
104095
+ import { createHash as createHash16 } from "node:crypto";
103753
104096
  function validateArtifactPolicy(policy) {
103754
104097
  const ok = _validate(policy);
103755
104098
  if (!ok) {
@@ -103844,10 +104187,10 @@ async function parseSafeYamlWithinRoot(root, policyPath) {
103844
104187
  }
103845
104188
  throw err;
103846
104189
  }
103847
- const fullPath = join25(root, policyPath);
104190
+ const fullPath = join27(root, policyPath);
103848
104191
  let content;
103849
104192
  try {
103850
- content = await readFile32(fullPath, "utf8");
104193
+ content = await readFile34(fullPath, "utf8");
103851
104194
  } catch (err) {
103852
104195
  throw new ReleaseError(
103853
104196
  ARTIFACT_POLICY_INVALID,
@@ -103898,7 +104241,7 @@ function canonicalJson3(obj) {
103898
104241
  return JSON.stringify(obj, Object.keys(obj ?? {}).sort());
103899
104242
  }
103900
104243
  function sha256Hex2(data) {
103901
- return createHash15("sha256").update(data).digest("hex");
104244
+ return createHash16("sha256").update(data).digest("hex");
103902
104245
  }
103903
104246
  function compareProtection(previousLock, policy) {
103904
104247
  if (!previousLock || !Array.isArray(previousLock.artifactIds)) {
@@ -103958,14 +104301,14 @@ var init_policy = __esm({
103958
104301
  });
103959
104302
 
103960
104303
  // 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";
104304
+ import { lstat as lstat25, readdir as readdir17, readFile as readFile35 } from "node:fs/promises";
104305
+ import { join as join28 } from "node:path";
103963
104306
  import { promisify as promisify16 } from "node:util";
103964
104307
  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;
104308
+ function statToGitMode(stat10) {
104309
+ if (stat10.isDirectory()) return "040000";
104310
+ if (stat10.isSymbolicLink()) return "120000";
104311
+ const mode = stat10.mode & 511;
103969
104312
  const executable = (mode & 73) !== 0;
103970
104313
  return executable ? "100755" : "100644";
103971
104314
  }
@@ -103979,10 +104322,10 @@ async function gitHashObject(root, absPath) {
103979
104322
  }
103980
104323
  async function enumerateTreeEntries(root, dirPath, relBase) {
103981
104324
  const entries = [];
103982
- const items = await readdir16(dirPath, { withFileTypes: true });
104325
+ const items = await readdir17(dirPath, { withFileTypes: true });
103983
104326
  for (const item of items) {
103984
104327
  if (SKIP_DIRS2.has(item.name)) continue;
103985
- const absPath = join26(dirPath, item.name);
104328
+ const absPath = join28(dirPath, item.name);
103986
104329
  const relPath = relBase ? `${relBase}/${item.name}` : item.name;
103987
104330
  const st = await lstat25(absPath);
103988
104331
  if (st.isSymbolicLink()) {
@@ -104003,7 +104346,7 @@ async function enumerateTreeEntries(root, dirPath, relBase) {
104003
104346
  const subEntries = await enumerateTreeEntries(root, absPath, relPath);
104004
104347
  entries.push(...subEntries);
104005
104348
  } else {
104006
- const content = await readFile33(absPath);
104349
+ const content = await readFile35(absPath);
104007
104350
  entries.push(
104008
104351
  Object.freeze({
104009
104352
  path: relPath,
@@ -104033,7 +104376,7 @@ async function readEntry({ root, path: path15, source = "worktree" } = {}) {
104033
104376
  if (source !== "worktree") {
104034
104377
  throw new ReleaseError(PATH_UNSAFE, `unsupported readEntry source: ${source}`, { source });
104035
104378
  }
104036
- const absPath = join26(root, path15);
104379
+ const absPath = join28(root, path15);
104037
104380
  let st;
104038
104381
  try {
104039
104382
  st = await lstat25(absPath);
@@ -104066,7 +104409,7 @@ async function readEntry({ root, path: path15, source = "worktree" } = {}) {
104066
104409
  { path: path15, nlink: st.nlink }
104067
104410
  );
104068
104411
  }
104069
- const content = await readFile33(absPath);
104412
+ const content = await readFile35(absPath);
104070
104413
  return Object.freeze({
104071
104414
  kind: "regular",
104072
104415
  path: path15,
@@ -104330,8 +104673,8 @@ var init_graph = __esm({
104330
104673
  });
104331
104674
 
104332
104675
  // 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";
104676
+ import { readFile as readFile36, readdir as readdir18, stat as stat7, mkdir as mkdir21, writeFile as writeFile12, rm as rm14 } from "node:fs/promises";
104677
+ import { join as join29 } from "node:path";
104335
104678
  import { mkdtemp as mkdtemp9 } from "node:fs/promises";
104336
104679
  import { tmpdir as tmpdir6 } from "node:os";
104337
104680
  import { readFileSync as readFileSync13 } from "node:fs";
@@ -104351,7 +104694,7 @@ function collectStaticImports(filePath, visited = /* @__PURE__ */ new Set()) {
104351
104694
  const dir = abs.replace(/\/[^/]*$/, "");
104352
104695
  while ((match = importRe.exec(source)) !== null) {
104353
104696
  const spec = match[1];
104354
- let resolved = join27(dir, spec);
104697
+ let resolved = join29(dir, spec);
104355
104698
  if (!resolved.endsWith(".mjs")) resolved += ".mjs";
104356
104699
  results.push(...collectStaticImports(resolved, visited));
104357
104700
  }
@@ -104359,10 +104702,10 @@ function collectStaticImports(filePath, visited = /* @__PURE__ */ new Set()) {
104359
104702
  }
104360
104703
  async function createBuiltInProducerRegistry() {
104361
104704
  const producers = /* @__PURE__ */ new Map();
104362
- const lockfilePath = join27(new URL("../../..", import.meta.url).pathname, "pnpm-lock.yaml");
104705
+ const lockfilePath = join29(new URL("../../..", import.meta.url).pathname, "pnpm-lock.yaml");
104363
104706
  let lockfileBytes;
104364
104707
  try {
104365
- lockfileBytes = await readFile34(lockfilePath);
104708
+ lockfileBytes = await readFile36(lockfilePath);
104366
104709
  } catch {
104367
104710
  lockfileBytes = Buffer.from("");
104368
104711
  }
@@ -104379,7 +104722,7 @@ async function createBuiltInProducerRegistry() {
104379
104722
  const allModuleBytes = await Promise.all(
104380
104723
  allModulePaths.map(async (p) => {
104381
104724
  try {
104382
- return await readFile34(p);
104725
+ return await readFile36(p);
104383
104726
  } catch {
104384
104727
  return Buffer.from("");
104385
104728
  }
@@ -104396,16 +104739,16 @@ async function createBuiltInProducerRegistry() {
104396
104739
  }
104397
104740
  async function readDirEntries(dirPath, relBase = "") {
104398
104741
  const entries = [];
104399
- const items = await readdir17(dirPath, { withFileTypes: true });
104742
+ const items = await readdir18(dirPath, { withFileTypes: true });
104400
104743
  for (const item of items) {
104401
104744
  if (item.name === ".git") continue;
104402
- const absPath = join27(dirPath, item.name);
104745
+ const absPath = join29(dirPath, item.name);
104403
104746
  const relPath = relBase ? `${relBase}/${item.name}` : item.name;
104404
- const st = await stat6(absPath);
104747
+ const st = await stat7(absPath);
104405
104748
  if (st.isDirectory()) {
104406
104749
  entries.push(...await readDirEntries(absPath, relPath));
104407
104750
  } else {
104408
- const content = await readFile34(absPath);
104751
+ const content = await readFile36(absPath);
104409
104752
  entries.push(Object.freeze({
104410
104753
  path: relPath,
104411
104754
  type: "blob",
@@ -104422,13 +104765,13 @@ async function readDirEntries(dirPath, relBase = "") {
104422
104765
  async function materializeEntries(entries, dirPath) {
104423
104766
  for (const entry of entries) {
104424
104767
  if (!entry.path) continue;
104425
- const targetPath2 = join27(dirPath, entry.path);
104768
+ const targetPath2 = join29(dirPath, entry.path);
104426
104769
  if (entry.type === "tree" || entry.kind === "tree") {
104427
104770
  await mkdir21(targetPath2, { recursive: true });
104428
104771
  } else {
104429
- await mkdir21(join27(targetPath2, ".."), { recursive: true });
104772
+ await mkdir21(join29(targetPath2, ".."), { recursive: true });
104430
104773
  if (entry.content) {
104431
- await writeFile11(targetPath2, entry.content);
104774
+ await writeFile12(targetPath2, entry.content);
104432
104775
  }
104433
104776
  }
104434
104777
  }
@@ -104470,7 +104813,7 @@ async function runProducerClosure({
104470
104813
  graph,
104471
104814
  inputSnapshot,
104472
104815
  artifactIds,
104473
- tempRootFactory = /* @__PURE__ */ __name(async () => mkdtemp9(join27(tmpdir6(), "producer-")), "tempRootFactory")
104816
+ tempRootFactory = /* @__PURE__ */ __name(async () => mkdtemp9(join29(tmpdir6(), "producer-")), "tempRootFactory")
104474
104817
  } = {}) {
104475
104818
  const generatedSet = new Set(graph.topologicalOrder);
104476
104819
  for (const id of artifactIds) {
@@ -104507,9 +104850,9 @@ async function runProducerClosure({
104507
104850
  if (inputEntries) {
104508
104851
  const first = inputEntries[0];
104509
104852
  if (first && first.path) {
104510
- const absPath = first.path.startsWith("/") ? first.path : join27(process.cwd(), first.path);
104853
+ const absPath = first.path.startsWith("/") ? first.path : join29(process.cwd(), first.path);
104511
104854
  try {
104512
- const st = await stat6(absPath);
104855
+ const st = await stat7(absPath);
104513
104856
  if (st.isDirectory()) {
104514
104857
  inputPath = absPath;
104515
104858
  } else {
@@ -104600,13 +104943,13 @@ var init_producer_registry = __esm({
104600
104943
  // src/artifacts/git-authority.mjs
104601
104944
  import { promisify as promisify18 } from "node:util";
104602
104945
  import { execFile as execFile15 } from "node:child_process";
104603
- import { createHash as createHash16 } from "node:crypto";
104946
+ import { createHash as createHash17 } from "node:crypto";
104604
104947
  async function git(cwd, ...args2) {
104605
104948
  const { stdout } = await execFileAsync6("git", args2, { cwd, shell: false });
104606
104949
  return stdout.trim();
104607
104950
  }
104608
104951
  function sha256Hex3(data) {
104609
- return createHash16("sha256").update(data).digest("hex");
104952
+ return createHash17("sha256").update(data).digest("hex");
104610
104953
  }
104611
104954
  async function readRepositoryIdentity(root) {
104612
104955
  let gitDir;
@@ -104932,7 +105275,7 @@ var init_state = __esm({
104932
105275
  });
104933
105276
 
104934
105277
  // 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";
105278
+ import { writeFile as writeFile13, mkdir as mkdir22, readFile as readFile37, rename as rename6, open as open9 } from "node:fs/promises";
104936
105279
  import { dirname as dirname16 } from "node:path";
104937
105280
  function assemblePlan({
104938
105281
  operation,
@@ -104962,7 +105305,7 @@ async function writePlan(plan, outputPath) {
104962
105305
  const content = JSON.stringify(plan, null, 2);
104963
105306
  const fh = await open9(tmpPath, "w");
104964
105307
  try {
104965
- await writeFile12(fh, content, "utf8");
105308
+ await writeFile13(fh, content, "utf8");
104966
105309
  await fh.sync();
104967
105310
  } finally {
104968
105311
  await fh.close();
@@ -105621,8 +105964,8 @@ var init_adoption = __esm({
105621
105964
  // src/artifacts/inspect.mjs
105622
105965
  import { promisify as promisify19 } from "node:util";
105623
105966
  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";
105967
+ import { readdir as readdir19, stat as stat8, readFile as readFile38 } from "node:fs/promises";
105968
+ import { join as join30 } from "node:path";
105626
105969
  async function hasNestedGitRoots(root) {
105627
105970
  try {
105628
105971
  const { stdout } = await execFileAsync7(
@@ -105632,10 +105975,10 @@ async function hasNestedGitRoots(root) {
105632
105975
  );
105633
105976
  const dirs = stdout.split("\n").filter((s) => s.length > 0);
105634
105977
  for (const dir of dirs) {
105635
- const absDir = join28(root, dir);
105978
+ const absDir = join30(root, dir);
105636
105979
  try {
105637
- const nestedGit = join28(absDir, ".git");
105638
- await stat7(nestedGit);
105980
+ const nestedGit = join30(absDir, ".git");
105981
+ await stat8(nestedGit);
105639
105982
  return true;
105640
105983
  } catch {
105641
105984
  }
@@ -105893,8 +106236,8 @@ var init_inspect = __esm({
105893
106236
  });
105894
106237
 
105895
106238
  // 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";
106239
+ import { mkdir as mkdir23, open as open10, readFile as readFile39, stat as stat9, lstat as lstat26, chmod as chmod4 } from "node:fs/promises";
106240
+ import { join as join31, resolve as resolve32, relative as relative26, isAbsolute as isAbsolute22, basename as basename11 } from "node:path";
105898
106241
  function decodeBuffer(value, label) {
105899
106242
  if (value == null) return null;
105900
106243
  if (Buffer.isBuffer(value)) return value;
@@ -105996,9 +106339,9 @@ function assertSafeArtifactId(id) {
105996
106339
  }
105997
106340
  async function assertNoSymlinksInPath(root, artifactId) {
105998
106341
  const levels = [
105999
- join29(root, ".release-skill"),
106000
- join29(root, ".release-skill", "resolution"),
106001
- join29(root, ".release-skill", "resolution", artifactId)
106342
+ join31(root, ".release-skill"),
106343
+ join31(root, ".release-skill", "resolution"),
106344
+ join31(root, ".release-skill", "resolution", artifactId)
106002
106345
  ];
106003
106346
  for (const dir of levels) {
106004
106347
  try {
@@ -106025,7 +106368,7 @@ async function assertSafeResolvedPath(root, artifactId, resolvedPath) {
106025
106368
  { resolvedPath, resolutionDir }
106026
106369
  );
106027
106370
  }
106028
- const filename = basename10(resolvedPath);
106371
+ const filename = basename11(resolvedPath);
106029
106372
  if (filename !== `${artifactId}.resolved`) {
106030
106373
  throw new ReleaseError(
106031
106374
  PATH_UNSAFE,
@@ -106177,13 +106520,13 @@ async function materializeResolution({
106177
106520
  const template = buildConflictTemplate(artifact.conflict ?? {}, decodedBuffers);
106178
106521
  const templateDigest = sha256Hex(template);
106179
106522
  await assertNoSymlinksInPath(root, artifactId);
106180
- const resolutionDir = join29(root, ".release-skill", "resolution", artifactId);
106523
+ const resolutionDir = join31(root, ".release-skill", "resolution", artifactId);
106181
106524
  await mkdir23(resolutionDir, { recursive: true, mode: 448 });
106182
- const dirStat = await stat8(resolutionDir);
106525
+ const dirStat = await stat9(resolutionDir);
106183
106526
  if ((dirStat.mode & 511) !== 448) {
106184
106527
  await chmod4(resolutionDir, 448);
106185
106528
  }
106186
- const resolvedPath = join29(resolutionDir, `${artifactId}.resolved`);
106529
+ const resolvedPath = join31(resolutionDir, `${artifactId}.resolved`);
106187
106530
  const fh = await open10(resolvedPath, "wx", 384);
106188
106531
  try {
106189
106532
  await fh.write(template, 0, template.length);
@@ -106225,7 +106568,7 @@ async function submitResolution({
106225
106568
  async function readAndValidateResolvedFile(resolvedPath) {
106226
106569
  let content;
106227
106570
  try {
106228
- content = await readFile37(resolvedPath);
106571
+ content = await readFile39(resolvedPath);
106229
106572
  } catch (err) {
106230
106573
  throw new ReleaseError(MISSING_PARAMETERS, `cannot read resolved file: ${err.message}`, { resolvedPath, cause: err.code });
106231
106574
  }
@@ -106393,8 +106736,8 @@ var artifacts_exports = {};
106393
106736
  __export(artifacts_exports, {
106394
106737
  runArtifactsCommand: () => runArtifactsCommand
106395
106738
  });
106396
- import { readFile as readFile38 } from "node:fs/promises";
106397
- import { join as join30 } from "node:path";
106739
+ import { readFile as readFile40 } from "node:fs/promises";
106740
+ import { join as join32 } from "node:path";
106398
106741
  async function runArtifactsCommand({ subcommand, args: args2, root } = {}) {
106399
106742
  if (!VALID_SUBCOMMANDS.has(subcommand)) {
106400
106743
  throw new ReleaseError(
@@ -106522,7 +106865,7 @@ async function handleAdopt({ args: args2, root }) {
106522
106865
  { subcommand: "adopt" }
106523
106866
  );
106524
106867
  }
106525
- const planRaw = await readFile38(planPath, "utf8");
106868
+ const planRaw = await readFile40(planPath, "utf8");
106526
106869
  const plan = JSON.parse(planRaw);
106527
106870
  if (expectedDigest && plan.planDigest !== expectedDigest) {
106528
106871
  throw new ReleaseError(
@@ -106537,7 +106880,7 @@ async function handleAdopt({ args: args2, root }) {
106537
106880
  if (artifact.path) {
106538
106881
  const entry = await readEntry({ root, path: artifact.path, source: "worktree" });
106539
106882
  if (entry.kind === "regular") {
106540
- const bytes = await readFile38(join30(root, artifact.path));
106883
+ const bytes = await readFile40(join32(root, artifact.path));
106541
106884
  currentEntries.set(artifact.id, Object.freeze({ ...entry, bytes, content: bytes }));
106542
106885
  } else {
106543
106886
  currentEntries.set(artifact.id, entry);
@@ -106602,7 +106945,7 @@ async function handleBootstrap({ args: args2, root }) {
106602
106945
  { subcommand: "bootstrap" }
106603
106946
  );
106604
106947
  }
106605
- const planRaw = await readFile38(planPath, "utf8");
106948
+ const planRaw = await readFile40(planPath, "utf8");
106606
106949
  const adoptionPlan = JSON.parse(planRaw);
106607
106950
  const currentEntries = /* @__PURE__ */ new Map();
106608
106951
  for (const id of new Set((adoptionPlan.protectedHunks ?? []).map((h) => h.artifactId))) {
@@ -106614,12 +106957,12 @@ async function handleBootstrap({ args: args2, root }) {
106614
106957
  if (entry.kind !== "regular") {
106615
106958
  throw new ReleaseError("PLAN_STALE", `artifact is no longer a regular file: ${id}`, { id });
106616
106959
  }
106617
- const bytes = await readFile38(join30(root, artifactPath));
106960
+ const bytes = await readFile40(join32(root, artifactPath));
106618
106961
  currentEntries.set(id, Object.freeze({ ...entry, bytes, content: bytes }));
106619
106962
  }
106620
106963
  let replacementBytes;
106621
106964
  if (action === "replace" && replacementPath) {
106622
- replacementBytes = await readFile38(replacementPath);
106965
+ replacementBytes = await readFile40(replacementPath);
106623
106966
  }
106624
106967
  const updated = await discardBootstrapHunk({
106625
106968
  adoptionPlan,
@@ -106657,7 +107000,7 @@ async function handleResolve({ args: args2, root }) {
106657
107000
  { subcommand: "resolve" }
106658
107001
  );
106659
107002
  }
106660
- const planRaw = await readFile38(planPath, "utf8");
107003
+ const planRaw = await readFile40(planPath, "utf8");
106661
107004
  const plan = JSON.parse(planRaw);
106662
107005
  if (plan.planDigest !== expectedDigest) {
106663
107006
  throw new ReleaseError(
@@ -107436,7 +107779,7 @@ __export(route_exports, {
107436
107779
  resolvePreviousReleaseCommit: () => resolvePreviousReleaseCommit
107437
107780
  });
107438
107781
  import { execFileSync } from "node:child_process";
107439
- import { readdir as readdir19, readFile as readFile39 } from "node:fs/promises";
107782
+ import { readdir as readdir20, readFile as readFile41 } from "node:fs/promises";
107440
107783
  import { resolve as resolve33 } from "node:path";
107441
107784
  function classifyPath(path15) {
107442
107785
  if (typeof path15 !== "string" || path15.length === 0) return "ignore";
@@ -107517,13 +107860,13 @@ async function resolvePreviousReleaseCommit(root) {
107517
107860
  const cwd = resolve33(root);
107518
107861
  try {
107519
107862
  const plansDir = resolve33(cwd, ".release-skill", "plans");
107520
- const planFiles = await readdir19(plansDir).catch(() => []);
107863
+ const planFiles = await readdir20(plansDir).catch(() => []);
107521
107864
  let best = null;
107522
107865
  for (const file of planFiles) {
107523
107866
  if (!file.endsWith(".json")) continue;
107524
107867
  let plan;
107525
107868
  try {
107526
- plan = JSON.parse(await readFile39(resolve33(plansDir, file), "utf8"));
107869
+ plan = JSON.parse(await readFile41(resolve33(plansDir, file), "utf8"));
107527
107870
  } catch {
107528
107871
  continue;
107529
107872
  }
@@ -107607,14 +107950,14 @@ async function hasPartialRun(root) {
107607
107950
  const runsDir = resolve33(cwd, ".release-skill", "runs");
107608
107951
  let runDirs;
107609
107952
  try {
107610
- runDirs = await readdir19(runsDir);
107953
+ runDirs = await readdir20(runsDir);
107611
107954
  } catch {
107612
107955
  return false;
107613
107956
  }
107614
107957
  for (const runDir of runDirs) {
107615
107958
  const summaryPath = resolve33(runsDir, runDir, "summary.json");
107616
107959
  try {
107617
- const summary = JSON.parse(await readFile39(summaryPath, "utf8"));
107960
+ const summary = JSON.parse(await readFile41(summaryPath, "utf8"));
107618
107961
  if (summary?.status === "PARTIAL") return true;
107619
107962
  } catch {
107620
107963
  }
@@ -107899,7 +108242,7 @@ Workflow Profiles:
107899
108242
  });
107900
108243
 
107901
108244
  // bin/release-skill-cli.mjs
107902
- import { basename as basename11, dirname as dirname17, join as join31, resolve as resolve34 } from "node:path";
108245
+ import { basename as basename12, dirname as dirname17, join as join33, resolve as resolve34 } from "node:path";
107903
108246
  import { execFile as execFileCb17 } from "node:child_process";
107904
108247
  import { promisify as promisify21 } from "node:util";
107905
108248
 
@@ -108133,6 +108476,9 @@ Options:
108133
108476
  deterministically trim code-class gates (declared hooks, snapshot-verify gates,
108134
108477
  source-authority closure, skill-resource-closure) and record workflowDecision in the plan;
108135
108478
  config also reports whether the public bytes are unchanged (no publish path)
108479
+ --test-selection <full|incremental> Test selection for the test hook (prepare). Only 'full' is accepted at
108480
+ freeze time; 'incremental' is reserved for a future preflight mode and is rejected
108481
+ ('incremental selection is not allowed at freeze time')
108136
108482
  --answers <path> Human-reviewed setup answers JSON
108137
108483
  --write Create an absent project.yaml during setup; never overwrites
108138
108484
  --confirm-setup <digest> Confirm exact setup facts and answers before create
@@ -108185,7 +108531,7 @@ if (!command && (args.includes("--version") || args.includes("-v"))) {
108185
108531
  } else {
108186
108532
  const { readFileSync: readFileSync14 } = await import("node:fs");
108187
108533
  const { fileURLToPath: fileURLToPath3 } = await import("node:url");
108188
- const pkgPath = join31(dirname17(fileURLToPath3(import.meta.url)), "..", "package.json");
108534
+ const pkgPath = join33(dirname17(fileURLToPath3(import.meta.url)), "..", "package.json");
108189
108535
  pkg = JSON.parse(readFileSync14(pkgPath, "utf8"));
108190
108536
  }
108191
108537
  if (hasJson) {
@@ -108525,6 +108871,8 @@ if (command === "prepare") {
108525
108871
  const production = args.includes("--production");
108526
108872
  const workflowIdx = args.indexOf("--workflow");
108527
108873
  const workflow = workflowIdx !== -1 && args[workflowIdx + 1] ? args[workflowIdx + 1] : "full";
108874
+ const testSelectionIdx = args.indexOf("--test-selection");
108875
+ const testSelection = testSelectionIdx !== -1 && args[testSelectionIdx + 1] ? args[testSelectionIdx + 1] : void 0;
108528
108876
  const outputIdx = args.indexOf("--output");
108529
108877
  const output = outputIdx !== -1 && args[outputIdx + 1] ? resolve34(args[outputIdx + 1]) : void 0;
108530
108878
  const runDirIdx = args.indexOf("--run-dir");
@@ -108541,6 +108889,7 @@ if (command === "prepare") {
108541
108889
  hookCache,
108542
108890
  production,
108543
108891
  workflow,
108892
+ testSelection,
108544
108893
  output,
108545
108894
  runDir
108546
108895
  });
@@ -108630,8 +108979,8 @@ if (command === "approve") {
108630
108979
  }
108631
108980
  const resolvedPlanPath = resolve34(planPath);
108632
108981
  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");
108982
+ const releaseDir = basename12(planDir) === "plans" && basename12(resolvedPlanPath) === `${resolvedDigest}.json` ? dirname17(planDir) : planDir;
108983
+ const approvalPath = outputPath ?? join33(releaseDir, "approval-record.json");
108635
108984
  const record = await approvePlan2({ planPath, expectedDigest: resolvedDigest, actor, outputPath: approvalPath });
108636
108985
  if (hasJson) {
108637
108986
  console.log(JSON.stringify(record, null, 2));