@hasna/skills 0.10.51 → 0.10.52

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.
package/dist/sdk/index.js CHANGED
@@ -5267,8 +5267,8 @@ var require_cst_visit = __commonJS((exports) => {
5267
5267
  visit.REMOVE = REMOVE;
5268
5268
  visit.itemAtPath = (cst, path) => {
5269
5269
  let item = cst;
5270
- for (const [field, index] of path) {
5271
- const tok = item?.[field];
5270
+ for (const [field2, index] of path) {
5271
+ const tok = item?.[field2];
5272
5272
  if (tok && "items" in tok) {
5273
5273
  item = tok.items[index];
5274
5274
  } else
@@ -5278,8 +5278,8 @@ var require_cst_visit = __commonJS((exports) => {
5278
5278
  };
5279
5279
  visit.parentCollection = (cst, path) => {
5280
5280
  const parent = visit.itemAtPath(cst, path.slice(0, -1));
5281
- const field = path[path.length - 1][0];
5282
- const coll = parent?.[field];
5281
+ const field2 = path[path.length - 1][0];
5282
+ const coll = parent?.[field2];
5283
5283
  if (coll && "items" in coll)
5284
5284
  return coll;
5285
5285
  throw new Error("Parent collection not found");
@@ -5288,11 +5288,11 @@ var require_cst_visit = __commonJS((exports) => {
5288
5288
  let ctrl = visitor(item, path);
5289
5289
  if (typeof ctrl === "symbol")
5290
5290
  return ctrl;
5291
- for (const field of ["key", "value"]) {
5292
- const token = item[field];
5291
+ for (const field2 of ["key", "value"]) {
5292
+ const token = item[field2];
5293
5293
  if (token && "items" in token) {
5294
5294
  for (let i = 0;i < token.items.length; ++i) {
5295
- const ci = _visit(Object.freeze(path.concat([[field, i]])), token.items[i], visitor);
5295
+ const ci = _visit(Object.freeze(path.concat([[field2, i]])), token.items[i], visitor);
5296
5296
  if (typeof ci === "number")
5297
5297
  i = ci - 1;
5298
5298
  else if (ci === BREAK)
@@ -5302,7 +5302,7 @@ var require_cst_visit = __commonJS((exports) => {
5302
5302
  i -= 1;
5303
5303
  }
5304
5304
  }
5305
- if (typeof ctrl === "function" && field === "key")
5305
+ if (typeof ctrl === "function" && field2 === "key")
5306
5306
  ctrl = ctrl(item, path);
5307
5307
  }
5308
5308
  }
@@ -5728,9 +5728,9 @@ var require_lexer = __commonJS((exports) => {
5728
5728
  }
5729
5729
  }
5730
5730
  *parseQuotedScalar() {
5731
- const quote = this.charAt(0);
5732
- let end = this.buffer.indexOf(quote, this.pos + 1);
5733
- if (quote === "'") {
5731
+ const quote2 = this.charAt(0);
5732
+ let end = this.buffer.indexOf(quote2, this.pos + 1);
5733
+ if (quote2 === "'") {
5734
5734
  while (end !== -1 && this.buffer[end + 1] === "'")
5735
5735
  end = this.buffer.indexOf("'", end + 2);
5736
5736
  } else {
@@ -8209,7 +8209,7 @@ var require_client = __commonJS((exports) => {
8209
8209
  };
8210
8210
  };
8211
8211
  var sleep = (seconds) => {
8212
- return new Promise((resolve22) => setTimeout(resolve22, seconds * 1000));
8212
+ return new Promise((resolve24) => setTimeout(resolve24, seconds * 1000));
8213
8213
  };
8214
8214
  var waiterServiceDefaults = {
8215
8215
  minDelay: 2,
@@ -8264,14 +8264,14 @@ var require_client = __commonJS((exports) => {
8264
8264
  }
8265
8265
  await sleep(delayMs / 1000);
8266
8266
  }
8267
- const { state, reason } = await acceptorChecks(client2, input);
8268
- if (reason) {
8269
- const message = createMessageFromResponse(reason);
8267
+ const { state, reason: reason2 } = await acceptorChecks(client2, input);
8268
+ if (reason2) {
8269
+ const message = createMessageFromResponse(reason2);
8270
8270
  observedResponses[message] |= 0;
8271
8271
  observedResponses[message] += 1;
8272
8272
  }
8273
8273
  if (state !== WaiterState.RETRY) {
8274
- return { state, reason, final: reason, observedResponses };
8274
+ return { state, reason: reason2, final: reason2, observedResponses };
8275
8275
  }
8276
8276
  currentAttempt += 1;
8277
8277
  if (!didWarn403 && Date.now() >= warn403Time) {
@@ -8295,18 +8295,18 @@ var require_client = __commonJS((exports) => {
8295
8295
  warningLogger.warn(`@smithy/util-waiter WARN - 403 status code encountered during waiter polling.`);
8296
8296
  }
8297
8297
  };
8298
- var createMessageFromResponse = (reason) => {
8299
- const status = reason?.$response?.statusCode ?? reason?.$metadata?.httpStatusCode;
8300
- if (reason?.$responseBodyText) {
8301
- return `${status ? status + ": " : ""}Deserialization error for body: ${reason.$responseBodyText}`;
8298
+ var createMessageFromResponse = (reason2) => {
8299
+ const status = reason2?.$response?.statusCode ?? reason2?.$metadata?.httpStatusCode;
8300
+ if (reason2?.$responseBodyText) {
8301
+ return `${status ? status + ": " : ""}Deserialization error for body: ${reason2.$responseBodyText}`;
8302
8302
  }
8303
8303
  if (status) {
8304
- if (reason?.$response || reason?.message) {
8305
- return `${status ?? "Unknown"}: ${reason?.message}`;
8304
+ if (reason2?.$response || reason2?.message) {
8305
+ return `${status ?? "Unknown"}: ${reason2?.message}`;
8306
8306
  }
8307
8307
  return `${status}: OK`;
8308
8308
  }
8309
- return String(reason?.message ?? JSON.stringify(reason, getCircularReplacer()) ?? "Unknown");
8309
+ return String(reason2?.message ?? JSON.stringify(reason2, getCircularReplacer()) ?? "Unknown");
8310
8310
  };
8311
8311
  var exponentialBackoffWithJitter = (minDelayMs, maxDelayMs, attempt, waitUntil) => {
8312
8312
  const attemptCountCeiling = Math.log(maxDelayMs / minDelayMs) / Math.log(2) + 1;
@@ -8338,8 +8338,8 @@ var require_client = __commonJS((exports) => {
8338
8338
  };
8339
8339
  var abortTimeout = (abortSignal) => {
8340
8340
  let onAbort;
8341
- const promise = new Promise((resolve22) => {
8342
- onAbort = () => resolve22({ state: WaiterState.ABORTED });
8341
+ const promise = new Promise((resolve24) => {
8342
+ onAbort = () => resolve24({ state: WaiterState.ABORTED });
8343
8343
  if (typeof abortSignal.addEventListener === "function") {
8344
8344
  abortSignal.addEventListener("abort", onAbort);
8345
8345
  } else {
@@ -9004,7 +9004,7 @@ var require_client = __commonJS((exports) => {
9004
9004
  var require_config = __commonJS((exports) => {
9005
9005
  var { homedir: homedir7 } = __require("os");
9006
9006
  var { sep: sep11, join: join4 } = __require("path");
9007
- var { createHash: createHash27 } = __require("crypto");
9007
+ var { createHash: createHash28 } = __require("crypto");
9008
9008
  var { readFile: readFile$1 } = __require("fs/promises");
9009
9009
  var { IniSectionType } = require_dist_cjs();
9010
9010
  var { normalizeProvider } = require_client();
@@ -9159,7 +9159,7 @@ var require_config = __commonJS((exports) => {
9159
9159
  var DEFAULT_PROFILE = "default";
9160
9160
  var getProfileName = (init) => init.profile || process.env[ENV_PROFILE] || DEFAULT_PROFILE;
9161
9161
  var getSSOTokenFilepath = (id2) => {
9162
- const hasher = createHash27("sha1");
9162
+ const hasher = createHash28("sha1");
9163
9163
  const cacheName = hasher.update(id2).digest("hex");
9164
9164
  return join4(getHomeDir(), ".aws", "sso", "cache", `${cacheName}.json`);
9165
9165
  };
@@ -9477,7 +9477,7 @@ var require_config = __commonJS((exports) => {
9477
9477
  };
9478
9478
  var imdsRequest = async (options) => {
9479
9479
  const { request: request2 } = __require("http");
9480
- return new Promise((resolve22, reject) => {
9480
+ return new Promise((resolve24, reject) => {
9481
9481
  const req = request2({
9482
9482
  hostname: options.hostname,
9483
9483
  port: options.port,
@@ -9505,7 +9505,7 @@ var require_config = __commonJS((exports) => {
9505
9505
  const chunks = [];
9506
9506
  res.on("data", (chunk) => chunks.push(chunk));
9507
9507
  res.on("end", () => {
9508
- resolve22(Buffer.concat(chunks));
9508
+ resolve24(Buffer.concat(chunks));
9509
9509
  req.destroy();
9510
9510
  });
9511
9511
  });
@@ -10511,7 +10511,7 @@ var require_endpoints = __commonJS((exports) => {
10511
10511
 
10512
10512
  // node_modules/@smithy/core/dist-cjs/submodules/serde/index.js
10513
10513
  var require_serde = __commonJS((exports) => {
10514
- var { createHmac: createHmac2, createHash: createHash27, getRandomValues } = __require("crypto");
10514
+ var { createHmac: createHmac2, createHash: createHash28, getRandomValues } = __require("crypto");
10515
10515
  var { hasOwn: hasOwn2, HttpResponse } = require_transport();
10516
10516
  exports.hasOwn = hasOwn2;
10517
10517
  var { ReadStream, lstatSync: lstatSync27, fstatSync: fstatSync4 } = __require("fs");
@@ -11416,7 +11416,7 @@ var require_serde = __commonJS((exports) => {
11416
11416
  return Promise.resolve(this.hash.digest());
11417
11417
  }
11418
11418
  reset() {
11419
- this.hash = this.secret ? createHmac2(this.algorithmIdentifier, castSourceData(this.secret)) : createHash27(this.algorithmIdentifier);
11419
+ this.hash = this.secret ? createHmac2(this.algorithmIdentifier, castSourceData(this.secret)) : createHash28(this.algorithmIdentifier);
11420
11420
  }
11421
11421
  }
11422
11422
  function castSourceData(toCast, encoding) {
@@ -11861,7 +11861,7 @@ ${value}\r
11861
11861
  if (isReadableStream(stream)) {
11862
11862
  return headStream$1(stream, bytes);
11863
11863
  }
11864
- return new Promise((resolve22, reject) => {
11864
+ return new Promise((resolve24, reject) => {
11865
11865
  const collector = new Collector$1;
11866
11866
  collector.limit = bytes;
11867
11867
  stream.pipe(collector);
@@ -11872,7 +11872,7 @@ ${value}\r
11872
11872
  collector.on("error", reject);
11873
11873
  collector.on("finish", function() {
11874
11874
  const bytes2 = concatBytes(this.buffers);
11875
- resolve22(bytes2);
11875
+ resolve24(bytes2);
11876
11876
  });
11877
11877
  });
11878
11878
  };
@@ -11986,7 +11986,7 @@ ${value}\r
11986
11986
  if (isReadableStream(stream)) {
11987
11987
  return collectReadableStream(stream);
11988
11988
  }
11989
- return new Promise((resolve22, reject) => {
11989
+ return new Promise((resolve24, reject) => {
11990
11990
  const collector = new Collector;
11991
11991
  const nodeStream = stream;
11992
11992
  nodeStream.pipe(collector);
@@ -11997,7 +11997,7 @@ ${value}\r
11997
11997
  collector.on("error", reject);
11998
11998
  collector.on("finish", function() {
11999
11999
  const bytes = concatBytes(this.bufferedBytes);
12000
- resolve22(bytes);
12000
+ resolve24(bytes);
12001
12001
  });
12002
12002
  });
12003
12003
  };
@@ -12155,7 +12155,7 @@ var require_checksum = __commonJS((exports) => {
12155
12155
  var { createReadStream } = __require("fs");
12156
12156
  var { Writable } = __require("stream");
12157
12157
  var { toUint8Array, concatBytes } = require_serde();
12158
- var { createHash: createHash27, createHmac: createHmac2 } = __require("crypto");
12158
+ var { createHash: createHash28, createHmac: createHmac2 } = __require("crypto");
12159
12159
  var zlib = __require("zlib");
12160
12160
  async function blobReader(blob, onChunk, chunkSize = 1024 * 1024) {
12161
12161
  const size = blob.size;
@@ -12189,7 +12189,7 @@ var require_checksum = __commonJS((exports) => {
12189
12189
  callback();
12190
12190
  }
12191
12191
  }
12192
- var fileStreamHasher = (hashCtor, fileStream) => new Promise((resolve22, reject) => {
12192
+ var fileStreamHasher = (hashCtor, fileStream) => new Promise((resolve24, reject) => {
12193
12193
  if (!isReadStream(fileStream)) {
12194
12194
  reject(new Error("Unable to calculate hash for non-file streams."));
12195
12195
  return;
@@ -12207,7 +12207,7 @@ var require_checksum = __commonJS((exports) => {
12207
12207
  });
12208
12208
  hashCalculator.on("error", reject);
12209
12209
  hashCalculator.on("finish", function() {
12210
- hash2.digest().then(resolve22).catch(reject);
12210
+ hash2.digest().then(resolve24).catch(reject);
12211
12211
  });
12212
12212
  });
12213
12213
  var isReadStream = (stream) => typeof stream.path === "string";
@@ -12218,14 +12218,14 @@ var require_checksum = __commonJS((exports) => {
12218
12218
  const hash2 = new hashCtor;
12219
12219
  const hashCalculator = new HashCalculator(hash2);
12220
12220
  readableStream.pipe(hashCalculator);
12221
- return new Promise((resolve22, reject) => {
12221
+ return new Promise((resolve24, reject) => {
12222
12222
  readableStream.on("error", (err) => {
12223
12223
  hashCalculator.end();
12224
12224
  reject(err);
12225
12225
  });
12226
12226
  hashCalculator.on("error", reject);
12227
12227
  hashCalculator.on("finish", () => {
12228
- hash2.digest().then(resolve22).catch(reject);
12228
+ hash2.digest().then(resolve24).catch(reject);
12229
12229
  });
12230
12230
  });
12231
12231
  };
@@ -12320,7 +12320,7 @@ var require_checksum = __commonJS((exports) => {
12320
12320
  }
12321
12321
  var hasNativeCrypto$1 = (() => {
12322
12322
  try {
12323
- createHash27("md5");
12323
+ createHash28("md5");
12324
12324
  return true;
12325
12325
  } catch {
12326
12326
  return false;
@@ -12330,7 +12330,7 @@ var require_checksum = __commonJS((exports) => {
12330
12330
  function buildNativeClass$2() {
12331
12331
  return class Md5Node2 {
12332
12332
  digestLength = 16;
12333
- hash = createHash27("md5");
12333
+ hash = createHash28("md5");
12334
12334
  update(data) {
12335
12335
  this.hash.update(toUint8Array(data));
12336
12336
  }
@@ -12339,7 +12339,7 @@ var require_checksum = __commonJS((exports) => {
12339
12339
  return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
12340
12340
  }
12341
12341
  reset() {
12342
- this.hash = createHash27("md5");
12342
+ this.hash = createHash28("md5");
12343
12343
  }
12344
12344
  };
12345
12345
  }
@@ -12629,7 +12629,7 @@ var require_checksum = __commonJS((exports) => {
12629
12629
  ]);
12630
12630
  var hasNativeCrypto = (() => {
12631
12631
  try {
12632
- createHash27("sha256");
12632
+ createHash28("sha256");
12633
12633
  return true;
12634
12634
  } catch {
12635
12635
  return false;
@@ -12669,7 +12669,7 @@ var require_checksum = __commonJS((exports) => {
12669
12669
  this.finished = false;
12670
12670
  }
12671
12671
  createHash() {
12672
- return this.secret ? createHmac2("sha256", toBuffer(this.secret)) : createHash27("sha256");
12672
+ return this.secret ? createHmac2("sha256", toBuffer(this.secret)) : createHash28("sha256");
12673
12673
  }
12674
12674
  };
12675
12675
  }
@@ -13334,7 +13334,7 @@ var require_event_streams = __commonJS((exports) => {
13334
13334
  streamEnded = true;
13335
13335
  });
13336
13336
  while (!generationEnded) {
13337
- const value = await new Promise((resolve22) => setTimeout(() => resolve22(records.shift()), 0));
13337
+ const value = await new Promise((resolve24) => setTimeout(() => resolve24(records.shift()), 0));
13338
13338
  if (value) {
13339
13339
  yield value;
13340
13340
  }
@@ -14542,8 +14542,8 @@ var require_protocols = __commonJS((exports) => {
14542
14542
  fields2.forEach(this.setField.bind(this));
14543
14543
  this.encoding = encoding;
14544
14544
  }
14545
- setField(field2) {
14546
- this.entries[field2.name.toLowerCase()] = field2;
14545
+ setField(field3) {
14546
+ this.entries[field3.name.toLowerCase()] = field3;
14547
14547
  }
14548
14548
  getField(name) {
14549
14549
  return this.entries[name.toLowerCase()];
@@ -14552,7 +14552,7 @@ var require_protocols = __commonJS((exports) => {
14552
14552
  delete this.entries[name.toLowerCase()];
14553
14553
  }
14554
14554
  getByType(kind) {
14555
- return Object.values(this.entries).filter((field2) => field2.kind === kind);
14555
+ return Object.values(this.entries).filter((field3) => field3.kind === kind);
14556
14556
  }
14557
14557
  }
14558
14558
  var getHttpHandlerExtensionConfiguration = (runtimeConfig) => {
@@ -14852,7 +14852,7 @@ var require_retry = __commonJS((exports) => {
14852
14852
  }
14853
14853
  };
14854
14854
  }
14855
- var cooldown = (ms) => new Promise((resolve22) => setTimeout(resolve22, ms));
14855
+ var cooldown = (ms) => new Promise((resolve24) => setTimeout(resolve24, ms));
14856
14856
  var isRetryStrategyV2 = (retryStrategy) => typeof retryStrategy.acquireInitialRetryToken !== "undefined" && typeof retryStrategy.refreshRetryTokenForRetry !== "undefined" && typeof retryStrategy.recordSuccess !== "undefined";
14857
14857
  var getRetryErrorInfo = (error, logger) => {
14858
14858
  const errorInfo = {
@@ -14951,7 +14951,7 @@ var require_retry = __commonJS((exports) => {
14951
14951
  this.refillTokenBucket();
14952
14952
  while (amount > this.availableTokens) {
14953
14953
  const delay = (amount - this.availableTokens) / this.fillRate * 1000;
14954
- await new Promise((resolve22) => DefaultRateLimiter.setTimeoutFn(resolve22, delay));
14954
+ await new Promise((resolve24) => DefaultRateLimiter.setTimeoutFn(resolve24, delay));
14955
14955
  this.refillTokenBucket();
14956
14956
  }
14957
14957
  this.availableTokens = this.availableTokens - amount;
@@ -15293,7 +15293,7 @@ var require_retry = __commonJS((exports) => {
15293
15293
  const delayFromResponse = getDelayFromRetryAfterHeader(err.$response);
15294
15294
  const delay = Math.max(delayFromResponse || 0, delayFromDecider);
15295
15295
  totalDelay += delay;
15296
- await new Promise((resolve22) => setTimeout(resolve22, delay));
15296
+ await new Promise((resolve24) => setTimeout(resolve24, delay));
15297
15297
  continue;
15298
15298
  }
15299
15299
  if (!err.$metadata) {
@@ -18166,7 +18166,7 @@ ${toHex(hashedRequest)}`;
18166
18166
  return hash2.digest();
18167
18167
  };
18168
18168
  var getCanonicalHeaders = ({ headers }, unsignableHeaders, signableHeaders) => {
18169
- const canonical7 = {};
18169
+ const canonical8 = {};
18170
18170
  for (const headerName of Object.keys(headers).sort()) {
18171
18171
  if (headers[headerName] == undefined) {
18172
18172
  continue;
@@ -18177,9 +18177,9 @@ ${toHex(hashedRequest)}`;
18177
18177
  continue;
18178
18178
  }
18179
18179
  }
18180
- canonical7[canonicalHeaderName] = headers[headerName].trim().replace(/\s+/g, " ");
18180
+ canonical8[canonicalHeaderName] = headers[headerName].trim().replace(/\s+/g, " ");
18181
18181
  }
18182
- return canonical7;
18182
+ return canonical8;
18183
18183
  };
18184
18184
  var getPayloadHash = async ({ headers, body }, hashConstructor) => {
18185
18185
  for (const headerName in headers) {
@@ -20175,7 +20175,7 @@ var require_cbor = __commonJS((exports) => {
20175
20175
  const { memberSchemas, encodedKeys, memberNames } = cache;
20176
20176
  const z = encodedKeys.length;
20177
20177
  const result = {};
20178
- let unknownKey;
20178
+ let unknownKey2;
20179
20179
  let unknownValue;
20180
20180
  let unknownCount = 0;
20181
20181
  let hasType = false;
@@ -20197,7 +20197,7 @@ var require_cbor = __commonJS((exports) => {
20197
20197
  if (key === "__type" && typeof val === "string") {
20198
20198
  hasType = true;
20199
20199
  } else {
20200
- unknownKey = key;
20200
+ unknownKey2 = key;
20201
20201
  unknownValue = val;
20202
20202
  ++unknownCount;
20203
20203
  }
@@ -20212,7 +20212,7 @@ var require_cbor = __commonJS((exports) => {
20212
20212
  break;
20213
20213
  }
20214
20214
  if (resultEmpty && unknownCount === 1) {
20215
- result.$unknown = [unknownKey, unknownValue];
20215
+ result.$unknown = [unknownKey2, unknownValue];
20216
20216
  }
20217
20217
  } else if (hasType) {
20218
20218
  pos = startPos;
@@ -20360,7 +20360,7 @@ var require_cbor = __commonJS((exports) => {
20360
20360
  const z = encodedKeys.length;
20361
20361
  const isUnion = ns.isUnionSchema();
20362
20362
  const result = {};
20363
- let unknownKey;
20363
+ let unknownKey2;
20364
20364
  let unknownValue;
20365
20365
  let unknownCount = 0;
20366
20366
  let hint = 0;
@@ -20376,7 +20376,7 @@ var require_cbor = __commonJS((exports) => {
20376
20376
  break;
20377
20377
  }
20378
20378
  if (resultEmpty && unknownCount === 1) {
20379
- result.$unknown = [unknownKey, unknownValue];
20379
+ result.$unknown = [unknownKey2, unknownValue];
20380
20380
  }
20381
20381
  }
20382
20382
  return result;
@@ -20395,7 +20395,7 @@ var require_cbor = __commonJS((exports) => {
20395
20395
  const key = readUtf8String();
20396
20396
  const val = readValue(NormalizedSchema.of(15));
20397
20397
  if (key !== "__type") {
20398
- unknownKey = key;
20398
+ unknownKey2 = key;
20399
20399
  unknownValue = val;
20400
20400
  ++unknownCount;
20401
20401
  }
@@ -21110,8 +21110,8 @@ var require_dist_cjs5 = __commonJS((exports) => {
21110
21110
  this.attributes[name] = value;
21111
21111
  return this;
21112
21112
  }
21113
- addChildNode(child) {
21114
- this.children.push(child);
21113
+ addChildNode(child2) {
21114
+ this.children.push(child2);
21115
21115
  return this;
21116
21116
  }
21117
21117
  removeAttribute(name) {
@@ -21122,8 +21122,8 @@ var require_dist_cjs5 = __commonJS((exports) => {
21122
21122
  this.name = name;
21123
21123
  return this;
21124
21124
  }
21125
- c(child) {
21126
- this.children.push(child);
21125
+ c(child2) {
21126
+ this.children.push(child2);
21127
21127
  return this;
21128
21128
  }
21129
21129
  a(name, value) {
@@ -21132,9 +21132,9 @@ var require_dist_cjs5 = __commonJS((exports) => {
21132
21132
  }
21133
21133
  return this;
21134
21134
  }
21135
- cc(input, field2, withName = field2) {
21136
- if (input[field2] != null) {
21137
- const node = XmlNode.of(field2, input[field2]).withName(withName);
21135
+ cc(input, field3, withName = field3) {
21136
+ if (input[field3] != null) {
21137
+ const node = XmlNode.of(field3, input[field3]).withName(withName);
21138
21138
  this.c(node);
21139
21139
  }
21140
21140
  }
@@ -21240,10 +21240,10 @@ var require_dist_cjs5 = __commonJS((exports) => {
21240
21240
  }
21241
21241
  readAttrValue() {
21242
21242
  const p = this;
21243
- const quote2 = p.x[p.i];
21243
+ const quote3 = p.x[p.i];
21244
21244
  ++p.i;
21245
21245
  let value = "";
21246
- while (p.i < p.z && p.x[p.i] !== quote2) {
21246
+ while (p.i < p.z && p.x[p.i] !== quote3) {
21247
21247
  value += p.x[p.i++];
21248
21248
  }
21249
21249
  ++p.i;
@@ -21350,18 +21350,18 @@ var require_dist_cjs5 = __commonJS((exports) => {
21350
21350
  }
21351
21351
  obj["#text"] = "#text" in obj ? obj["#text"] + text2 : text2;
21352
21352
  }
21353
- for (const child of childTags) {
21354
- if (child.tag === "__proto__") {
21353
+ for (const child2 of childTags) {
21354
+ if (child2.tag === "__proto__") {
21355
21355
  writeKey(obj);
21356
21356
  }
21357
- if (child.tag in obj) {
21358
- if (Array.isArray(obj[child.tag])) {
21359
- obj[child.tag].push(child.value);
21357
+ if (child2.tag in obj) {
21358
+ if (Array.isArray(obj[child2.tag])) {
21359
+ obj[child2.tag].push(child2.value);
21360
21360
  } else {
21361
- obj[child.tag] = [obj[child.tag], child.value];
21361
+ obj[child2.tag] = [obj[child2.tag], child2.value];
21362
21362
  }
21363
21363
  } else {
21364
- obj[child.tag] = child.value;
21364
+ obj[child2.tag] = child2.value;
21365
21365
  }
21366
21366
  }
21367
21367
  for (const [k, v] of Object.entries(attrs)) {
@@ -21700,12 +21700,12 @@ var require_protocols2 = __commonJS((exports) => {
21700
21700
  return expandToDecimal(numericString) === expandToDecimal(String(value));
21701
21701
  }
21702
21702
  const normalized = numericString.replace(/(\.\d*?)0+$/, "$1").replace(/\.$/, "");
21703
- const canonical7 = String(value);
21704
- if (normalized === canonical7) {
21703
+ const canonical8 = String(value);
21704
+ if (normalized === canonical8) {
21705
21705
  return true;
21706
21706
  }
21707
- if (/[eE]/.test(canonical7)) {
21708
- return normalized === expandToDecimal(canonical7);
21707
+ if (/[eE]/.test(canonical8)) {
21708
+ return normalized === expandToDecimal(canonical8);
21709
21709
  }
21710
21710
  return false;
21711
21711
  }
@@ -24646,7 +24646,7 @@ var init_node_http = () => {};
24646
24646
 
24647
24647
  // node_modules/@smithy/credential-provider-imds/dist-es/remoteProvider/httpRequest.js
24648
24648
  function httpRequest(options) {
24649
- return new Promise((resolve22, reject) => {
24649
+ return new Promise((resolve24, reject) => {
24650
24650
  const req = node_http.request({
24651
24651
  method: "GET",
24652
24652
  ...options,
@@ -24671,7 +24671,7 @@ function httpRequest(options) {
24671
24671
  chunks.push(chunk);
24672
24672
  });
24673
24673
  res.on("end", () => {
24674
- resolve22(Buffer.concat(chunks));
24674
+ resolve24(Buffer.concat(chunks));
24675
24675
  req.destroy();
24676
24676
  });
24677
24677
  });
@@ -25036,15 +25036,15 @@ var require_dist_cjs6 = __commonJS((exports) => {
25036
25036
  var { Readable: Readable2 } = __require("stream");
25037
25037
  var http2 = __require("http2");
25038
25038
  function buildAbortError(abortSignal) {
25039
- const reason = abortSignal && typeof abortSignal === "object" && "reason" in abortSignal ? abortSignal.reason : undefined;
25040
- if (reason) {
25041
- if (reason instanceof Error) {
25039
+ const reason2 = abortSignal && typeof abortSignal === "object" && "reason" in abortSignal ? abortSignal.reason : undefined;
25040
+ if (reason2) {
25041
+ if (reason2 instanceof Error) {
25042
25042
  const abortError3 = new Error("Request aborted");
25043
25043
  abortError3.name = "AbortError";
25044
- abortError3.cause = reason;
25044
+ abortError3.cause = reason2;
25045
25045
  return abortError3;
25046
25046
  }
25047
- const abortError2 = new Error(String(reason));
25047
+ const abortError2 = new Error(String(reason2));
25048
25048
  abortError2.name = "AbortError";
25049
25049
  return abortError2;
25050
25050
  }
@@ -25168,21 +25168,21 @@ var require_dist_cjs6 = __commonJS((exports) => {
25168
25168
  let sendBody = true;
25169
25169
  if (!externalAgent && expect === "100-continue") {
25170
25170
  sendBody = await Promise.race([
25171
- new Promise((resolve22) => {
25172
- timeoutId = Number(timing.setTimeout(() => resolve22(true), Math.max(MIN_WAIT_TIME, maxContinueTimeoutMs)));
25171
+ new Promise((resolve24) => {
25172
+ timeoutId = Number(timing.setTimeout(() => resolve24(true), Math.max(MIN_WAIT_TIME, maxContinueTimeoutMs)));
25173
25173
  }),
25174
- new Promise((resolve22) => {
25174
+ new Promise((resolve24) => {
25175
25175
  httpRequest2.on("continue", () => {
25176
25176
  timing.clearTimeout(timeoutId);
25177
- resolve22(true);
25177
+ resolve24(true);
25178
25178
  });
25179
25179
  httpRequest2.on("response", () => {
25180
25180
  timing.clearTimeout(timeoutId);
25181
- resolve22(false);
25181
+ resolve24(false);
25182
25182
  });
25183
25183
  httpRequest2.on("error", () => {
25184
25184
  timing.clearTimeout(timeoutId);
25185
- resolve22(false);
25185
+ resolve24(false);
25186
25186
  });
25187
25187
  })
25188
25188
  ]);
@@ -25198,8 +25198,8 @@ var require_dist_cjs6 = __commonJS((exports) => {
25198
25198
  }
25199
25199
  if (body) {
25200
25200
  const isBuffer = Buffer.isBuffer(body);
25201
- const isString = typeof body === "string";
25202
- if (isBuffer || isString) {
25201
+ const isString2 = typeof body === "string";
25202
+ if (isBuffer || isString2) {
25203
25203
  if (isBuffer && body.byteLength === 0) {
25204
25204
  httpRequest2.end();
25205
25205
  } else {
@@ -25259,13 +25259,13 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
25259
25259
  return socketWarningTimestamp;
25260
25260
  }
25261
25261
  constructor(options) {
25262
- this.configProvider = new Promise((resolve22, reject) => {
25262
+ this.configProvider = new Promise((resolve24, reject) => {
25263
25263
  if (typeof options === "function") {
25264
25264
  options().then((_options) => {
25265
- resolve22(this.resolveDefaultConfig(_options));
25265
+ resolve24(this.resolveDefaultConfig(_options));
25266
25266
  }).catch(reject);
25267
25267
  } else {
25268
- resolve22(this.resolveDefaultConfig(options));
25268
+ resolve24(this.resolveDefaultConfig(options));
25269
25269
  }
25270
25270
  });
25271
25271
  }
@@ -25297,7 +25297,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
25297
25297
  timing.clearTimeout(socketTimeoutId);
25298
25298
  timing.clearTimeout(keepAliveTimeoutId);
25299
25299
  };
25300
- const resolve22 = async (arg) => {
25300
+ const resolve24 = async (arg) => {
25301
25301
  await writeRequestBodyPromise;
25302
25302
  clearTimeouts();
25303
25303
  _resolve(arg);
@@ -25361,7 +25361,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
25361
25361
  headers: getTransformedHeaders(res.headers),
25362
25362
  body: res
25363
25363
  });
25364
- resolve22({ response: httpResponse });
25364
+ resolve24({ response: httpResponse });
25365
25365
  });
25366
25366
  req.on("error", (err) => {
25367
25367
  if (NODEJS_TIMEOUT_ERROR_CODES.includes(err.code)) {
@@ -25693,13 +25693,13 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
25693
25693
  return new NodeHttp2Handler(instanceOrOptions);
25694
25694
  }
25695
25695
  constructor(options) {
25696
- this.configProvider = new Promise((resolve22, reject) => {
25696
+ this.configProvider = new Promise((resolve24, reject) => {
25697
25697
  if (typeof options === "function") {
25698
25698
  options().then((opts) => {
25699
- resolve22(opts || {});
25699
+ resolve24(opts || {});
25700
25700
  }).catch(reject);
25701
25701
  } else {
25702
- resolve22(options || {});
25702
+ resolve24(options || {});
25703
25703
  }
25704
25704
  });
25705
25705
  }
@@ -25724,7 +25724,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
25724
25724
  return new Promise((_resolve, _reject) => {
25725
25725
  let fulfilled = false;
25726
25726
  let writeRequestBodyPromise = undefined;
25727
- const resolve22 = async (arg) => {
25727
+ const resolve24 = async (arg) => {
25728
25728
  await writeRequestBodyPromise;
25729
25729
  _resolve(arg);
25730
25730
  };
@@ -25809,7 +25809,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
25809
25809
  body: clientHttp2Stream
25810
25810
  });
25811
25811
  fulfilled = true;
25812
- resolve22({ response: httpResponse });
25812
+ resolve24({ response: httpResponse });
25813
25813
  if (useIsolatedSession) {
25814
25814
  session.close();
25815
25815
  clientHttp2Stream.on("end", () => {
@@ -25942,7 +25942,7 @@ var retryWrapper = (toRetry, maxRetries, delayMs) => {
25942
25942
  try {
25943
25943
  return await toRetry();
25944
25944
  } catch (e3) {
25945
- await new Promise((resolve22) => setTimeout(resolve22, delayMs));
25945
+ await new Promise((resolve24) => setTimeout(resolve24, delayMs));
25946
25946
  }
25947
25947
  }
25948
25948
  return await toRetry();
@@ -29443,10 +29443,10 @@ var require_signin = __commonJS((exports) => {
29443
29443
  });
29444
29444
 
29445
29445
  // node_modules/@aws-sdk/credential-provider-ini/node_modules/@aws-sdk/credential-provider-login/dist-es/LoginCredentialsFetcher.js
29446
- import { createHash as createHash27, createPrivateKey, createPublicKey, sign } from "crypto";
29446
+ import { createHash as createHash28, createPrivateKey, createPublicKey, sign } from "crypto";
29447
29447
  import { promises as fs2 } from "fs";
29448
29448
  import { homedir as homedir7 } from "os";
29449
- import { dirname as dirname23, join as join38 } from "path";
29449
+ import { dirname as dirname24, join as join38 } from "path";
29450
29450
  var import_config28, import_protocols3, LoginCredentialsFetcher;
29451
29451
  var init_LoginCredentialsFetcher = __esm(() => {
29452
29452
  import_config28 = __toESM(require_config(), 1);
@@ -29606,7 +29606,7 @@ var init_LoginCredentialsFetcher = __esm(() => {
29606
29606
  }
29607
29607
  async saveToken(token) {
29608
29608
  const tokenFilePath = this.getTokenFilePath();
29609
- const directory = dirname23(tokenFilePath);
29609
+ const directory = dirname24(tokenFilePath);
29610
29610
  try {
29611
29611
  await fs2.mkdir(directory, { recursive: true });
29612
29612
  } catch (error) {}
@@ -29615,7 +29615,7 @@ var init_LoginCredentialsFetcher = __esm(() => {
29615
29615
  getTokenFilePath() {
29616
29616
  const directory = process.env.AWS_LOGIN_CACHE_DIRECTORY ?? join38(homedir7(), ".aws", "login", "cache");
29617
29617
  const loginSessionBytes = Buffer.from(this.loginSession, "utf8");
29618
- const loginSessionSha256 = createHash27("sha256").update(loginSessionBytes).digest("hex");
29618
+ const loginSessionSha256 = createHash28("sha256").update(loginSessionBytes).digest("hex");
29619
29619
  return join38(directory, `${loginSessionSha256}.json`);
29620
29620
  }
29621
29621
  derToRawSignature(derSignature) {
@@ -31067,7 +31067,7 @@ import { existsSync as existsSync22 } from "fs";
31067
31067
  import { join as join210 } from "path";
31068
31068
  import { existsSync as existsSync17 } from "fs";
31069
31069
  import { homedir as homedir8 } from "os";
31070
- import { join as join42, resolve as resolve22 } from "path";
31070
+ import { join as join42, resolve as resolve24 } from "path";
31071
31071
  import { homedir as pathsResolverHomedir2 } from "os";
31072
31072
  import { join as pathsResolverJoin2 } from "path";
31073
31073
  import { createHmac as createHmac4, timingSafeEqual as timingSafeEqual3 } from "crypto";
@@ -31251,9 +31251,9 @@ function exactEventsHome() {
31251
31251
  function getEventsHome() {
31252
31252
  const exact = exactEventsHome();
31253
31253
  if (exact)
31254
- return resolve22(exact);
31254
+ return resolve24(exact);
31255
31255
  const resolved = resolverHome();
31256
- return adoptResolverHome(resolved) ? resolve22(resolved) : resolve22(legacyHomeDir());
31256
+ return adoptResolverHome(resolved) ? resolve24(resolved) : resolve24(legacyHomeDir());
31257
31257
  }
31258
31258
  function getEventsDataDir(override) {
31259
31259
  return override || getEventsHome();
@@ -31793,7 +31793,7 @@ async function pinnedNativeRequest(target, addresses, method, headers, body4, si
31793
31793
  callback(null, entries);
31794
31794
  }
31795
31795
  };
31796
- return new Promise((resolve23, reject) => {
31796
+ return new Promise((resolve25, reject) => {
31797
31797
  const request2 = isHttps ? nodeHttpsRequest(requestOptions, onResponse) : nodeHttpRequest(requestOptions, onResponse);
31798
31798
  const onAbort = () => {
31799
31799
  const error = new Error("The operation was aborted.");
@@ -31820,7 +31820,7 @@ async function pinnedNativeRequest(target, addresses, method, headers, body4, si
31820
31820
  else if (Array.isArray(value))
31821
31821
  headersRecord[name] = value.join(", ");
31822
31822
  }
31823
- resolve23(new Response(Buffer.concat(chunks), { status: response.statusCode ?? 200, headers: headersRecord }));
31823
+ resolve25(new Response(Buffer.concat(chunks), { status: response.statusCode ?? 200, headers: headersRecord }));
31824
31824
  });
31825
31825
  }
31826
31826
  });
@@ -31917,25 +31917,25 @@ async function dispatchCommand(event, channel) {
31917
31917
  HASNA_EVENT_SCHEMA_VERSION: event.schemaVersion,
31918
31918
  HASNA_EVENT_JSON: eventJson
31919
31919
  };
31920
- return new Promise((resolve23) => {
31921
- const child = spawn3(channel.command.command, channel.command.args ?? [], {
31920
+ return new Promise((resolve25) => {
31921
+ const child2 = spawn3(channel.command.command, channel.command.args ?? [], {
31922
31922
  cwd: channel.command.cwd,
31923
31923
  env,
31924
31924
  stdio: ["pipe", "pipe", "pipe"]
31925
31925
  });
31926
31926
  let stdout = "";
31927
31927
  let stderr = "";
31928
- const timeout = setTimeout(() => child.kill("SIGTERM"), channel.command.timeoutMs ?? 15000);
31929
- child.stdin.end(eventJson);
31930
- child.stdout.on("data", (chunk) => {
31928
+ const timeout = setTimeout(() => child2.kill("SIGTERM"), channel.command.timeoutMs ?? 15000);
31929
+ child2.stdin.end(eventJson);
31930
+ child2.stdout.on("data", (chunk) => {
31931
31931
  stdout += chunk.toString();
31932
31932
  });
31933
- child.stderr.on("data", (chunk) => {
31933
+ child2.stderr.on("data", (chunk) => {
31934
31934
  stderr += chunk.toString();
31935
31935
  });
31936
- child.on("error", (error) => {
31936
+ child2.on("error", (error) => {
31937
31937
  clearTimeout(timeout);
31938
- resolve23({
31938
+ resolve25({
31939
31939
  attempt: 1,
31940
31940
  status: "failed",
31941
31941
  startedAt,
@@ -31945,10 +31945,10 @@ async function dispatchCommand(event, channel) {
31945
31945
  error: error.message
31946
31946
  });
31947
31947
  });
31948
- child.on("close", (code, signal) => {
31948
+ child2.on("close", (code, signal) => {
31949
31949
  clearTimeout(timeout);
31950
31950
  const success = code === 0;
31951
- resolve23({
31951
+ resolve25({
31952
31952
  attempt: 1,
31953
31953
  status: success ? "success" : "failed",
31954
31954
  startedAt,
@@ -32373,7 +32373,7 @@ var init_event_sink = __esm(() => {
32373
32373
  // package.json
32374
32374
  var package_default = {
32375
32375
  name: "@hasna/skills",
32376
- version: "0.10.51",
32376
+ version: "0.10.52",
32377
32377
  description: "Skills library for AI coding agents",
32378
32378
  type: "module",
32379
32379
  bin: {
@@ -34672,7 +34672,14 @@ async function inspectSkillBundle(bundle, options = {}) {
34672
34672
  decoder.destroy(terminalError);
34673
34673
  };
34674
34674
  const onAbort = () => stop("BUNDLE_ABORTED");
34675
- const timer = setTimeout(() => stop("BUNDLE_TIMEOUT"), Math.max(1, deadline - performance.now()));
34675
+ const expire = () => {
34676
+ const remaining = deadline - performance.now();
34677
+ if (remaining > 0)
34678
+ timer = setTimeout(expire, Math.max(1, Math.ceil(remaining)));
34679
+ else
34680
+ stop("BUNDLE_TIMEOUT");
34681
+ };
34682
+ let timer = setTimeout(expire, Math.max(1, Math.ceil(deadline - performance.now())));
34676
34683
  signal?.addEventListener("abort", onAbort, { once: true });
34677
34684
  let decompressedByteSize = 0;
34678
34685
  let bytesSinceYield = 0;
@@ -34916,8 +34923,8 @@ function profileSelectionSnapshot(selections) {
34916
34923
  // src/lib/selection-cache.ts
34917
34924
  class SkillSelectionError extends Error {
34918
34925
  code;
34919
- constructor(code, message) {
34920
- super(message);
34926
+ constructor(code, message, options) {
34927
+ super(message, options);
34921
34928
  this.code = code;
34922
34929
  this.name = "SkillSelectionError";
34923
34930
  }
@@ -35051,8 +35058,8 @@ function atomicWrite(path, bytes, mode, durable = false) {
35051
35058
  }
35052
35059
  }
35053
35060
  }
35054
- function readSelectionJson(path) {
35055
- const bytes = readRegularFile(path, MAX_PROFILE_DOCUMENT_BYTES);
35061
+ function readSelectionJson(path, maximumBytes = MAX_PROFILE_DOCUMENT_BYTES) {
35062
+ const bytes = readRegularFile(path, Math.min(maximumBytes, MAX_PROFILE_DOCUMENT_BYTES));
35056
35063
  if (!bytes)
35057
35064
  return null;
35058
35065
  try {
@@ -35064,10 +35071,10 @@ function readSelectionJson(path) {
35064
35071
  async function verifiedEntries(selection, bytes, signal, deadline) {
35065
35072
  if (`sha256:${sha256Hex(bytes)}` !== selection.bundleDigest)
35066
35073
  throw new SkillSelectionError("BUNDLE_DIGEST_MISMATCH", "The skill bundle does not match its selected digest.");
35067
- const remaining = deadline === undefined ? undefined : Math.floor(deadline - performance.now());
35074
+ const remaining = deadline === undefined ? undefined : Math.ceil(deadline - performance.now());
35068
35075
  signal?.throwIfAborted();
35069
35076
  if (remaining !== undefined && remaining <= 0)
35070
- throw new SkillSelectionError("SKILLS_API_UNAVAILABLE", "Skills session authorization deadline exceeded.");
35077
+ throw new SkillBundleInspectionError("BUNDLE_TIMEOUT", "Bundle inspection deadline exceeded");
35071
35078
  const bundle = await inspectSkillBundle(bytes, { signal, ...remaining === undefined ? {} : { limits: { timeoutMs: remaining } } });
35072
35079
  return bundle.entries;
35073
35080
  }
@@ -37311,6 +37318,10 @@ function identifier2(value) {
37311
37318
  function invalid2() {
37312
37319
  throw new Error("The Skills API returned an invalid profile response");
37313
37320
  }
37321
+ function unavailable(error, message) {
37322
+ const name = error?.name;
37323
+ return new SkillSelectionError("SKILLS_API_UNAVAILABLE", message, name === "AbortError" || name === "TimeoutError" ? { cause: new DOMException("The Skills API request was cut short", name) } : undefined);
37324
+ }
37314
37325
  function validateSelection2(value) {
37315
37326
  if (!object(value) || !identifier2(value.slug) || typeof value.version !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/.test(value.version) || value.version.includes("..") || typeof value.bundleDigest !== "string" || !/^sha256:[a-f0-9]{64}$/.test(value.bundleDigest))
37316
37327
  invalid2();
@@ -37358,8 +37369,8 @@ class HttpProfileClient {
37358
37369
  ...init.headers
37359
37370
  }
37360
37371
  });
37361
- } catch {
37362
- throw new SkillSelectionError("SKILLS_API_UNAVAILABLE", "Unable to reach the configured Skills API");
37372
+ } catch (error) {
37373
+ throw unavailable(error, "Unable to reach the configured Skills API");
37363
37374
  }
37364
37375
  if (!response.ok) {
37365
37376
  response.body?.cancel().catch(() => {});
@@ -37376,7 +37387,9 @@ class HttpProfileClient {
37376
37387
  async read(response, limit = MAX_PROFILE_DOCUMENT_BYTES) {
37377
37388
  try {
37378
37389
  return JSON.parse(new TextDecoder().decode(await readBoundedResponse(response, limit, this.signal)));
37379
- } catch {
37390
+ } catch (error) {
37391
+ if (this.signal?.aborted)
37392
+ throw unavailable(this.signal.reason ?? error, "The Skills API response was cut short");
37380
37393
  invalid2();
37381
37394
  }
37382
37395
  }
@@ -37493,6 +37506,8 @@ function inspectSkillSession(sessionId, options = {}) {
37493
37506
  loadedCount: receipt.loaded.length
37494
37507
  };
37495
37508
  }
37509
+ var SESSION_RENEWAL_REFUSAL_TTL_MS = 5 * 60 * 1000;
37510
+ var SESSION_RENEWAL_REFUSAL_MAX_BYTES = 4 * 1024;
37496
37511
  async function reconcileSkillSession(input, options = {}) {
37497
37512
  if (![input.fromProfile, input.fromRevision, input.selectionProfile, input.profileRevision].every((value) => typeof value === "string" && value.trim()) || !/^[a-f0-9]{64}$/.test(input.receiptSha256)) {
37498
37513
  throw new SkillSelectionError("INVALID_SESSION_RECONCILIATION", "Name the exact old receipt SHA256, old profile/revision and intended target profile/revision.");
@@ -37554,10 +37569,10 @@ async function reconcileSkillSession(input, options = {}) {
37554
37569
  return { applied: true, plan, planDigest, ...result };
37555
37570
  }
37556
37571
  // src/lib/selected-run.ts
37557
- import { createHash as createHash26 } from "crypto";
37572
+ import { createHash as createHash27 } from "crypto";
37558
37573
  import { spawn as spawn2 } from "child_process";
37559
37574
  import { mkdirSync as mkdirSync11, mkdtempSync as mkdtempSync3, writeFileSync as writeFileSync10, realpathSync as realpathSync15 } from "fs";
37560
- import { dirname as dirname22, join as join37, resolve as resolve21 } from "path";
37575
+ import { dirname as dirname23, join as join37, resolve as resolve23 } from "path";
37561
37576
  import { tmpdir, hostname as stationHostname2 } from "os";
37562
37577
 
37563
37578
  // src/lib/dependency-preparation.ts
@@ -37952,7 +37967,7 @@ import {
37952
37967
  writeFileSync as writeFileSync8
37953
37968
  } from "fs";
37954
37969
  import { homedir as homedir5 } from "os";
37955
- import { basename as basename12, dirname as dirname21, join as join32 } from "path";
37970
+ import { basename as basename13, dirname as dirname22, join as join32 } from "path";
37956
37971
 
37957
37972
  // src/lib/sumi-settings-witness.ts
37958
37973
  import { createHash as createHash7 } from "crypto";
@@ -38089,6 +38104,10 @@ function parse2(text) {
38089
38104
  need(root.entries.length <= CLAUDE_SETTINGS_WITNESS_LIMITS.rows, "exceeds its settings field limit");
38090
38105
  return root;
38091
38106
  }
38107
+ function parseNativeJsonObject(text) {
38108
+ need(typeof text === "string" && Buffer.byteLength(text) <= CLAUDE_SETTINGS_WITNESS_LIMITS.bytes, "exceeds its byte limit");
38109
+ return parse2(text);
38110
+ }
38092
38111
  var BOOLEAN_PREFERENCES = new Set([
38093
38112
  "autoScrollEnabled",
38094
38113
  "axScreenReader",
@@ -40278,10 +40297,10 @@ var NATIVE_SKILL_ROOTS = [
40278
40297
  ];
40279
40298
 
40280
40299
  // src/lib/agent-integration.ts
40281
- import { createHash as createHash24, randomUUID as randomUUID4 } from "crypto";
40300
+ import { createHash as createHash25, randomUUID as randomUUID4 } from "crypto";
40282
40301
  import { isDeepStrictEqual as isDeepStrictEqual8 } from "util";
40283
- import { existsSync as existsSync7, lstatSync as lstatSync23, statSync as statSync7, mkdirSync as mkdirSync6, readFileSync as readFileSync17, readdirSync as readdirSync8, opendirSync as opendirSync5, readlinkSync as readlinkSync6, realpathSync as realpathSync11, renameSync as renameSync4, rmdirSync as rmdirSync3, writeFileSync as writeFileSync5, unlinkSync as unlinkSync5, chmodSync, openSync as openSync18, closeSync as closeSync18, fsyncSync as fsyncSync6, fstatSync as fstatSync18, readSync as readSync12, constants as constants15, linkSync as linkSync3 } from "fs";
40284
- import { dirname as dirname17, join as join27, resolve as resolve18, relative as relative5, isAbsolute as isAbsolute20, sep as sep7 } from "path";
40302
+ import { existsSync as existsSync7, lstatSync as lstatSync23, statSync as statSync7, mkdirSync as mkdirSync6, readFileSync as readFileSync17, readdirSync as readdirSync8, opendirSync as opendirSync5, readlinkSync as readlinkSync7, realpathSync as realpathSync11, renameSync as renameSync4, rmdirSync as rmdirSync3, writeFileSync as writeFileSync5, unlinkSync as unlinkSync5, chmodSync, openSync as openSync18, closeSync as closeSync18, fsyncSync as fsyncSync6, fstatSync as fstatSync18, readSync as readSync12, constants as constants15, linkSync as linkSync3 } from "fs";
40303
+ import { dirname as dirname18, join as join27, resolve as resolve20, relative as relative5, isAbsolute as isAbsolute22, sep as sep7 } from "path";
40285
40304
  import { homedir as homedir3 } from "os";
40286
40305
 
40287
40306
  // src/lib/managed-policy.ts
@@ -40289,7 +40308,202 @@ import { closeSync as closeSync11, constants as constants8, fstatSync as fstatSy
40289
40308
  import { join as join15 } from "path";
40290
40309
 
40291
40310
  // src/lib/agent-policy-limits.ts
40292
- import { basename as basename5, isAbsolute as isAbsolute8, join as join14, resolve as resolve7, sep as sep4 } from "path";
40311
+ import { basename as basename6, isAbsolute as isAbsolute9, join as join14, resolve as resolve8, sep as sep4 } from "path";
40312
+
40313
+ // src/lib/claude-marketplace-entry-witness.ts
40314
+ import { createHash as createHash12 } from "crypto";
40315
+ import { basename as basename5, dirname as dirname8, isAbsolute as isAbsolute8, resolve as resolve7 } from "path";
40316
+ var CLAUDE_MARKETPLACE_ENTRY_HASH_MODE = "claude-marketplace-entry-v1";
40317
+ var DOMAIN = "hasna.skills.claude-marketplace-entry.v1\x00";
40318
+ var PATH_CHARACTERS = 4096;
40319
+ var NAME = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
40320
+ function need4(value, reason) {
40321
+ if (!value)
40322
+ throw new Error(`Claude marketplace entry witness ${reason}`);
40323
+ }
40324
+ var bounded = (key) => key.length > 64 ? `${key.slice(0, 64)}...` : key;
40325
+ var quote = (text) => JSON.stringify(text).replace(/[^\x20-\x7e]/g, (character) => `\\u${character.charCodeAt(0).toString(16).padStart(4, "0")}`);
40326
+ var child = (path, key) => path + (/^[A-Za-z0-9_$-]{1,64}$/.test(key) ? `.${key}` : `[${JSON.stringify(bounded(key))}]`);
40327
+ function unknownKey(selector, path, key) {
40328
+ throw new Error(path === null ? `${CLAUDE_MARKETPLACE_ENTRY_HASH_MODE}: unknown top-level key ${quote(bounded(key))} in ${selector.marketplace}` : `${CLAUDE_MARKETPLACE_ENTRY_HASH_MODE}: unknown key ${quote(child(path, key))} in ${selector.marketplace}`);
40329
+ }
40330
+ function knownKeys(object4, allowed, selector, path) {
40331
+ for (const [key] of object4.entries)
40332
+ if (!allowed.has(key))
40333
+ unknownKey(selector, path, key);
40334
+ }
40335
+ var reason = (error) => String(error?.message ?? error).replace(/^Claude settings witness /, "");
40336
+ var MARKETPLACE_KEYS = new Set(["$schema", "name", "owner", "plugins", "description", "version", "metadata", "forceRemoveDeletedPlugins", "allowCrossMarketplaceDependenciesOn", "renames"]);
40337
+ var MARKETPLACE_METADATA_KEYS = new Set(["description", "version", "pluginRoot"]);
40338
+ var ENTRY_BOUND_KEYS = new Set([
40339
+ "name",
40340
+ "source",
40341
+ "strict",
40342
+ "defaultEnabled",
40343
+ "dependencies",
40344
+ "relevance",
40345
+ "headers",
40346
+ "headersHelper",
40347
+ "settings",
40348
+ "userConfig",
40349
+ "types",
40350
+ "channels",
40351
+ "skills",
40352
+ "commands",
40353
+ "agents",
40354
+ "hooks",
40355
+ "mcpServers",
40356
+ "lspServers",
40357
+ "outputStyles",
40358
+ "workflows",
40359
+ "experimental",
40360
+ "themes",
40361
+ "monitors"
40362
+ ]);
40363
+ var ENTRY_OMITTED_KEYS = new Set(["$schema", "description", "version", "author", "homepage", "repository", "license", "keywords", "category", "tags", "displayName", "metadata"]);
40364
+ var EXPERIMENTAL_KEYS = new Set(["themes", "monitors", "evals"]);
40365
+ var SOURCE_KEYS = Object.freeze({
40366
+ github: ["source", "repo", "ref", "sha"],
40367
+ url: ["source", "url", "ref", "sha", "path"],
40368
+ "git-subdir": ["source", "url", "path", "ref", "sha"],
40369
+ npm: ["source", "package", "version", "registry"],
40370
+ archive: ["source", "url", "sha256"],
40371
+ command: ["source", "command", "timeout", "mode"]
40372
+ });
40373
+ var field = (object4, key) => object4.entries.find(([name]) => name === key)?.[1];
40374
+ var isString = (value) => value?.kind === "string";
40375
+ var isBoolean = (value) => value?.kind === "literal" && (value.value === "true" || value.value === "false");
40376
+ var stringArray = (value) => value?.kind === "array" && value.items.every(isString);
40377
+ var stringObject = (value) => value?.kind === "object" && value.entries.every(([, item]) => isString(item));
40378
+ function claudeMarketplaceEntrySourceValid(source) {
40379
+ const path = source?.path;
40380
+ return typeof path === "string" && path.length > 0 && path.length <= PATH_CHARACTERS && !/[\x00-\x1f\x7f]/.test(path) && isAbsolute8(path) && resolve7(path) === path && basename5(path) === "marketplace.json" && basename5(dirname8(path)) === ".claude-plugin" && typeof source.marketplace === "string" && NAME.test(source.marketplace) && !source.marketplace.includes("..") && typeof source.plugin === "string" && NAME.test(source.plugin);
40381
+ }
40382
+ function canonical4(value) {
40383
+ if (value.kind === "string")
40384
+ return JSON.stringify(value.value);
40385
+ if (value.kind === "number" || value.kind === "literal")
40386
+ return value.value;
40387
+ if (value.kind === "array")
40388
+ return "[" + value.items.map(canonical4).join(",") + "]";
40389
+ return "{" + [...value.entries].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, item]) => JSON.stringify(key) + ":" + canonical4(item)).join(",") + "}";
40390
+ }
40391
+ function validateMarketplace(root, selector) {
40392
+ knownKeys(root, MARKETPLACE_KEYS, selector, null);
40393
+ const name = field(root, "name");
40394
+ need4(isString(name) && name.value === selector.marketplace, "marketplace name does not match the reviewed binding");
40395
+ for (const key of ["$schema", "description", "version"]) {
40396
+ const value = field(root, key);
40397
+ need4(value === undefined || isString(value), `has an invalid marketplace ${key}`);
40398
+ }
40399
+ const owner = field(root, "owner");
40400
+ need4(owner === undefined || owner.kind === "object", "has an invalid marketplace owner");
40401
+ const metadata = field(root, "metadata");
40402
+ if (metadata !== undefined) {
40403
+ need4(metadata.kind === "object", "has an invalid marketplace metadata object");
40404
+ knownKeys(metadata, MARKETPLACE_METADATA_KEYS, selector, "metadata");
40405
+ for (const [key, value] of metadata.entries)
40406
+ need4(isString(value), `has an invalid marketplace metadata.${key}`);
40407
+ }
40408
+ const remove = field(root, "forceRemoveDeletedPlugins");
40409
+ need4(remove === undefined || isBoolean(remove), "has an invalid forceRemoveDeletedPlugins value");
40410
+ const cross = field(root, "allowCrossMarketplaceDependenciesOn");
40411
+ need4(cross === undefined || stringArray(cross), "has an invalid allowCrossMarketplaceDependenciesOn value");
40412
+ const renames = field(root, "renames");
40413
+ if (renames !== undefined) {
40414
+ need4(renames.kind === "object" && renames.entries.every(([, target]) => isString(target) || target.kind === "literal" && target.value === "null"), "has an invalid renames map");
40415
+ need4(!renames.entries.some(([from]) => from.toLowerCase() === selector.plugin.toLowerCase()), "plugin id is redirected by the marketplace renames map");
40416
+ }
40417
+ }
40418
+ function validateSource(source, selector, path) {
40419
+ if (isString(source)) {
40420
+ need4(source.value.length > 0, "has an empty plugin source");
40421
+ return;
40422
+ }
40423
+ need4(source?.kind === "object", "has an invalid plugin source");
40424
+ const type = field(source, "source");
40425
+ need4(isString(type) && Object.hasOwn(SOURCE_KEYS, type.value), "has an unreviewed plugin source type");
40426
+ knownKeys(source, new Set(SOURCE_KEYS[type.value]), selector, path);
40427
+ }
40428
+ function projectEntry(entry, selector) {
40429
+ const path = `plugins[${selector.plugin}]`;
40430
+ knownKeys(entry, { has: (key) => ENTRY_BOUND_KEYS.has(key) || ENTRY_OMITTED_KEYS.has(key) }, selector, path);
40431
+ const name = field(entry, "name");
40432
+ need4(isString(name) && name.value === selector.plugin, "selected entry name does not match");
40433
+ validateSource(field(entry, "source"), selector, `${path}.source`);
40434
+ for (const key of ["strict", "defaultEnabled"]) {
40435
+ const value = field(entry, key);
40436
+ need4(value === undefined || isBoolean(value), `has an invalid entry ${key}`);
40437
+ }
40438
+ const headersHelper = field(entry, "headersHelper");
40439
+ need4(headersHelper === undefined || isString(headersHelper), "has an invalid entry headersHelper");
40440
+ const experimental = field(entry, "experimental");
40441
+ if (experimental !== undefined) {
40442
+ need4(experimental.kind === "object", "has an invalid entry experimental object");
40443
+ knownKeys(experimental, EXPERIMENTAL_KEYS, selector, `${path}.experimental`);
40444
+ }
40445
+ for (const key of ["$schema", "description", "version", "homepage", "license", "category", "displayName"]) {
40446
+ const value = field(entry, key);
40447
+ need4(value === undefined || isString(value), `has an invalid entry ${key}`);
40448
+ }
40449
+ for (const [key, keys2] of [["author", new Set(["name", "email", "url"])], ["repository", new Set(["type", "url", "directory"])]]) {
40450
+ const value = field(entry, key);
40451
+ if (value?.kind === "object")
40452
+ knownKeys(value, keys2, selector, `${path}.${key}`);
40453
+ need4(value === undefined || isString(value) || stringObject(value), `has an invalid entry ${key}`);
40454
+ }
40455
+ for (const key of ["keywords", "tags"]) {
40456
+ const value = field(entry, key);
40457
+ need4(value === undefined || stringArray(value), `has an invalid entry ${key}`);
40458
+ }
40459
+ const metadata = field(entry, "metadata");
40460
+ need4(metadata === undefined || metadata.kind === "object", "has an invalid entry metadata object");
40461
+ return { kind: "object", entries: entry.entries.filter(([key]) => ENTRY_BOUND_KEYS.has(key)) };
40462
+ }
40463
+ function hashClaudeMarketplaceEntry(text, selector) {
40464
+ need4(selector && typeof selector.marketplace === "string" && NAME.test(selector.marketplace) && !selector.marketplace.includes("..") && typeof selector.plugin === "string" && NAME.test(selector.plugin), "requires an exact marketplace and plugin name");
40465
+ let root;
40466
+ try {
40467
+ root = parseNativeJsonObject(text);
40468
+ } catch (error) {
40469
+ throw new Error(`Claude marketplace entry witness cannot parse marketplace.json: ${reason(error)}`);
40470
+ }
40471
+ validateMarketplace(root, selector);
40472
+ const plugins = field(root, "plugins");
40473
+ need4(plugins?.kind === "array", "requires a plugins array");
40474
+ const entryName = (item) => {
40475
+ if (item.kind !== "object")
40476
+ return;
40477
+ const name = field(item, "name");
40478
+ return isString(name) ? name.value : undefined;
40479
+ };
40480
+ const exact = plugins.items.filter((item) => entryName(item) === selector.plugin);
40481
+ const folded = plugins.items.filter((item) => entryName(item)?.toLowerCase() === selector.plugin.toLowerCase());
40482
+ need4(exact.length > 0, "selected plugin entry is missing");
40483
+ need4(exact.length === 1 && folded.length === 1, "selected plugin entry is duplicated or ambiguous");
40484
+ const entry = projectEntry(exact[0], selector);
40485
+ const metadata = field(root, "metadata"), pluginRoot = metadata?.kind === "object" ? field(metadata, "pluginRoot") : undefined;
40486
+ const nullValue = { kind: "literal", value: "null" };
40487
+ const marketplace = { kind: "object", entries: [
40488
+ ["name", field(root, "name")],
40489
+ ["pluginRoot", pluginRoot ?? nullValue],
40490
+ ["allowCrossMarketplaceDependenciesOn", field(root, "allowCrossMarketplaceDependenciesOn") ?? nullValue]
40491
+ ] };
40492
+ const projection = { kind: "object", entries: [["marketplace", marketplace], ["plugin", entry]] };
40493
+ return createHash12("sha256").update(DOMAIN).update(canonical4(projection)).digest("hex");
40494
+ }
40495
+ function captureClaudeMarketplaceEntry(path, marketplace, plugin, budget2 = { remaining: 256 * 1024 * 1024 }) {
40496
+ need4(claudeMarketplaceEntrySourceValid({ path, marketplace, plugin }), "requires a normalized absolute .claude-plugin/marketplace.json path and exact names");
40497
+ let text;
40498
+ try {
40499
+ text = readNativeSettingsWitnessFile(path, budget2, "marketplace.json");
40500
+ } catch (error) {
40501
+ throw new Error(`Claude marketplace entry witness cannot read marketplace.json: ${reason(error)}`);
40502
+ }
40503
+ return { path, hashMode: CLAUDE_MARKETPLACE_ENTRY_HASH_MODE, marketplace, plugin, sha256: hashClaudeMarketplaceEntry(text, { marketplace, plugin }) };
40504
+ }
40505
+
40506
+ // src/lib/agent-policy-limits.ts
40293
40507
  var AGENT_POLICY_LIMITS = Object.freeze({ bytes: 1024 * 1024, agents: 16, discoverySources: 2048, discoveryRawSourceBytes: 64 * 1024 * 1024, discoveryRawTotalBytes: 256 * 1024 * 1024, discoveryPathLinks: 40, discoveryPathSteps: 256, discoveryPathSourceMetadataBytes: 64 * 1024, discoveryPathTotalMetadataBytes: 8 * 1024 * 1024, discoveryRoots: 512, discoveryDirectories: 64, discoveryDirectoryEntries: 20000, discoveryDirectoryBytes: 8 * 1024 * 1024, builtinNames: 2048, rootAliases: 2, fields: 64, pathCharacters: 4096 });
40294
40508
  function object4(value) {
40295
40509
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
@@ -40343,7 +40557,7 @@ function assertAgentPolicyCollections(policy) {
40343
40557
  text(control.pluginId, 1024);
40344
40558
  text(control.namespace, 64);
40345
40559
  text(control.pluginParent);
40346
- requireBound(isAbsolute8(control.pluginParent) && resolve7(control.pluginParent) === control.pluginParent && /^[a-f0-9]{64}$/.test(control.manifestSha256));
40560
+ requireBound(isAbsolute9(control.pluginParent) && resolve8(control.pluginParent) === control.pluginParent && /^[a-f0-9]{64}$/.test(control.manifestSha256));
40347
40561
  if (control.remotePluginId !== undefined)
40348
40562
  requireBound(typeof control.remotePluginId === "string" && /^[A-Za-z0-9_~-]{1,1024}$/.test(control.remotePluginId));
40349
40563
  if (control.skillsOnly !== undefined)
@@ -40361,10 +40575,18 @@ function assertAgentPolicyCollections(policy) {
40361
40575
  text(control.pluginId, 1024);
40362
40576
  text(control.namespace, 64);
40363
40577
  text(control.pluginParent);
40364
- requireBound(!ids.has(control.pluginId) && isAbsolute8(control.pluginParent) && resolve7(control.pluginParent) === control.pluginParent && ["local", "git", "npm"].includes(control.sourceType) && typeof control.sourceSha256 === "string" && /^[a-f0-9]{64}$/.test(control.sourceSha256));
40578
+ requireBound(!ids.has(control.pluginId) && isAbsolute9(control.pluginParent) && resolve8(control.pluginParent) === control.pluginParent && ["local", "git", "npm"].includes(control.sourceType) && typeof control.sourceSha256 === "string" && /^[a-f0-9]{64}$/.test(control.sourceSha256));
40365
40579
  ids.add(control.pluginId);
40366
40580
  }
40367
40581
  }
40582
+ if (bridge.discoveryExecutables !== undefined)
40583
+ for (const [agent, executable2] of Object.entries(record3(bridge.discoveryExecutables, AGENT_POLICY_LIMITS.agents))) {
40584
+ requireBound(agent === "gemini" && object4(executable2) && Object.keys(executable2).length === 3 && executable2.command === "gemini");
40585
+ for (const path of [executable2.path, executable2.target]) {
40586
+ text(path);
40587
+ requireBound(!/[\x00-\x1f\x7f-\x9f\u200e\u200f\u202a-\u202e\u2066-\u2069]/.test(path) && isAbsolute9(path) && resolve8(path) === path);
40588
+ }
40589
+ }
40368
40590
  if (bridge.disabledBuiltins !== undefined)
40369
40591
  for (const builtin of array(bridge.disabledBuiltins, AGENT_POLICY_LIMITS.builtinNames)) {
40370
40592
  requireBound(object4(builtin));
@@ -40390,11 +40612,11 @@ function assertAgentPolicyCollections(policy) {
40390
40612
  requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && Object.keys(proof).every((key) => ["roots", "parents", "directories"].includes(key)) && roots.length + parents2.length > 0 && new Set(roots).size === roots.length && new Set(parents2).size === parents2.length);
40391
40613
  for (const root of roots) {
40392
40614
  text(root);
40393
- requireBound(isAbsolute8(root) && resolve7(root) === root);
40615
+ requireBound(isAbsolute9(root) && resolve8(root) === root);
40394
40616
  }
40395
40617
  for (const parent of parents2) {
40396
40618
  text(parent);
40397
- requireBound(isAbsolute8(parent) && resolve7(parent) === parent);
40619
+ requireBound(isAbsolute9(parent) && resolve8(parent) === parent);
40398
40620
  }
40399
40621
  for (const directory of array(proof.directories, AGENT_POLICY_LIMITS.discoveryDirectories)) {
40400
40622
  requireBound(object4(directory));
@@ -40414,7 +40636,7 @@ function assertAgentPolicyCollections(policy) {
40414
40636
  text(input.namespace, 64);
40415
40637
  text(input.pluginParent);
40416
40638
  text(input.sourceRoot);
40417
- requireBound(!ids.has(input.pluginId) && [input.pluginParent, input.sourceRoot].every((path) => isAbsolute8(path) && resolve7(path) === path) && typeof input.sourceSha256 === "string" && /^[a-f0-9]{64}$/.test(input.sourceSha256));
40639
+ requireBound(!ids.has(input.pluginId) && [input.pluginParent, input.sourceRoot].every((path) => isAbsolute9(path) && resolve8(path) === path) && typeof input.sourceSha256 === "string" && /^[a-f0-9]{64}$/.test(input.sourceSha256));
40418
40640
  ids.add(input.pluginId);
40419
40641
  }
40420
40642
  if (proof.directories !== undefined)
@@ -40431,17 +40653,19 @@ function assertAgentPolicyCollections(policy) {
40431
40653
  text(source.path);
40432
40654
  requireBound(source.sha256 === null || typeof source.sha256 === "string" && /^[a-f0-9]{64}$/.test(source.sha256));
40433
40655
  if (source.hashMode !== undefined)
40434
- requireBound(["bytes", "path-bytes", "claude-plugin-manifest-v1", "claude-plugin-registry", "claude-marketplace-registry", "claude-settings-v1", "claude-settings-v2", "claude-settings-v3", "claude-settings-v4", "claude-marketplace-registry-v2", "codex-settings-v1", "codex-settings-v2", "codex-settings-v3", "codex-settings-v4", "sumi-settings-v1"].includes(source.hashMode) && source.format === undefined && source.fields === undefined && (source.hashMode === "bytes" || source.sha256 !== null));
40656
+ requireBound(["bytes", "path-bytes", "claude-plugin-manifest-v1", "claude-plugin-registry", "claude-marketplace-registry", "claude-settings-v1", "claude-settings-v2", "claude-settings-v3", "claude-settings-v4", "claude-marketplace-registry-v2", "codex-settings-v1", "codex-settings-v2", "codex-settings-v3", "codex-settings-v4", "sumi-settings-v1", "claude-marketplace-entry-v1"].includes(source.hashMode) && source.format === undefined && source.fields === undefined && (source.hashMode === "bytes" || source.sha256 !== null));
40435
40657
  if (source.hashMode === "claude-plugin-manifest-v1")
40436
- requireBound(agent === "claude" && value.agent === "claude" && ["automatic", "reviewed"].includes(value.method) && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute8(source.path) && resolve7(source.path) === source.path && source.path.endsWith(join14(sep4, ".claude-plugin", "plugin.json")) && source.managedPlugins === undefined);
40658
+ requireBound(agent === "claude" && value.agent === "claude" && ["automatic", "reviewed"].includes(value.method) && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute9(source.path) && resolve8(source.path) === source.path && source.path.endsWith(join14(sep4, ".claude-plugin", "plugin.json")) && source.managedPlugins === undefined);
40437
40659
  if (source.hashMode === "sumi-settings-v1")
40438
- requireBound(agent === "sumi" && value.agent === "sumi" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute8(source.path) && resolve7(source.path) === source.path && basename5(source.path) === "sumi.json");
40660
+ requireBound(agent === "sumi" && value.agent === "sumi" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute9(source.path) && resolve8(source.path) === source.path && basename6(source.path) === "sumi.json");
40439
40661
  if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4"))
40440
- requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute8(source.path) && resolve7(source.path) === source.path && basename5(source.path) === "config.toml");
40662
+ requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute9(source.path) && resolve8(source.path) === source.path && basename6(source.path) === "config.toml");
40441
40663
  if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4"))
40442
- requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute8(source.path) && resolve7(source.path) === source.path && basename5(source.path) === "settings.json");
40664
+ requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute9(source.path) && resolve8(source.path) === source.path && basename6(source.path) === "settings.json");
40443
40665
  if (source.hashMode === "claude-marketplace-registry" || source.hashMode === "claude-marketplace-registry-v2")
40444
- requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute8(source.path) && resolve7(source.path) === source.path && basename5(source.path) === "known_marketplaces.json");
40666
+ requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute9(source.path) && resolve8(source.path) === source.path && basename6(source.path) === "known_marketplaces.json");
40667
+ if (source.hashMode === "claude-marketplace-entry-v1")
40668
+ requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && claudeMarketplaceEntrySourceValid(source));
40445
40669
  if (source.hashMode === "claude-plugin-registry") {
40446
40670
  requireBound(agent === "claude");
40447
40671
  const managed = array(source.managedPlugins, 64);
@@ -40456,8 +40680,8 @@ function assertAgentPolicyCollections(policy) {
40456
40680
  if (source.format !== undefined)
40457
40681
  requireBound(["json", "toml", "yaml"].includes(source.format));
40458
40682
  if (source.fields !== undefined)
40459
- for (const field of array(source.fields, AGENT_POLICY_LIMITS.fields))
40460
- text(field, 256);
40683
+ for (const field2 of array(source.fields, AGENT_POLICY_LIMITS.fields))
40684
+ text(field2, 256);
40461
40685
  }
40462
40686
  if (value.directories !== undefined)
40463
40687
  for (const directory of array(value.directories, AGENT_POLICY_LIMITS.discoveryDirectories)) {
@@ -40472,8 +40696,8 @@ function assertAgentPolicyCollections(policy) {
40472
40696
  }
40473
40697
 
40474
40698
  // src/lib/managed-policy.ts
40475
- function refusal(reason = "is unreadable") {
40476
- return new SkillSelectionError("INVALID_AGENT_POLICY", `The Skills agent loading policy ${reason}; refusing legacy fallback.`);
40699
+ function refusal(reason2 = "is unreadable") {
40700
+ return new SkillSelectionError("INVALID_AGENT_POLICY", `The Skills agent loading policy ${reason2}; refusing legacy fallback.`);
40477
40701
  }
40478
40702
  function parseManagedSkillPolicy(text2) {
40479
40703
  if (Buffer.byteLength(text2) > AGENT_POLICY_LIMITS.bytes)
@@ -40550,7 +40774,7 @@ function requiresCliSkillLoading(dataDir2 = getDataDirReadOnly()) {
40550
40774
  }
40551
40775
 
40552
40776
  // src/lib/agent-bridge.ts
40553
- import { createHash as createHash12 } from "crypto";
40777
+ import { createHash as createHash13 } from "crypto";
40554
40778
  import { lstatSync as lstatSync10, readFileSync as readFileSync11, readdirSync as readdirSync4 } from "fs";
40555
40779
  import { join as join16 } from "path";
40556
40780
  var CLI_BRIDGE_NAME = "skills-cli";
@@ -40569,7 +40793,7 @@ Use the Skills CLI as the skill authority for this station.
40569
40793
 
40570
40794
  This bridge contains no skill payloads. Do not copy skill content into agent-native skill directories or load other native skill copies. If a Skills command refuses authority, selection, integrity, or native drift, report that refusal and use its repair guidance; do not substitute bundled or stale local content. Explicit local draft authoring remains available.
40571
40795
  `;
40572
- var CLI_BRIDGE_DIGEST = createHash12("sha256").update(markdown).digest("hex");
40796
+ var CLI_BRIDGE_DIGEST = createHash13("sha256").update(markdown).digest("hex");
40573
40797
  var CLI_BRIDGE_FILES = Object.freeze({
40574
40798
  "SKILL.md": markdown,
40575
40799
  ".hasna-skills.json": `${JSON.stringify({ managedBy: "@hasna/skills", kind: "cli-bridge", version: CLI_BRIDGE_VERSION, protocol: "selection-v1", contentSha256: CLI_BRIDGE_DIGEST }, null, 2)}
@@ -40593,9 +40817,9 @@ function isOwnedCliBridge(path, expectedPaths) {
40593
40817
  }
40594
40818
 
40595
40819
  // src/lib/agent-discovery.ts
40596
- import { createHash as createHash22 } from "crypto";
40820
+ import { createHash as createHash23 } from "crypto";
40597
40821
  import { lstatSync as lstatSync21, readFileSync as readFileSync15, readdirSync as readdirSync7, realpathSync as realpathSync9 } from "fs";
40598
- import { basename as basename8, dirname as dirname16, isAbsolute as isAbsolute18, join as join26, resolve as resolve17, sep as sep6 } from "path";
40822
+ import { basename as basename9, dirname as dirname17, isAbsolute as isAbsolute20, join as join26, resolve as resolve19, sep as sep6 } from "path";
40599
40823
  import { isDeepStrictEqual as isDeepStrictEqual6 } from "util";
40600
40824
 
40601
40825
  // node_modules/yaml/dist/index.js
@@ -40645,7 +40869,7 @@ var $visit = visit.visit;
40645
40869
  var $visitAsync = visit.visitAsync;
40646
40870
 
40647
40871
  // src/lib/agent-hermes.ts
40648
- import { dirname as dirname8, isAbsolute as isAbsolute9, join as join17, resolve as resolve8 } from "path";
40872
+ import { dirname as dirname9, isAbsolute as isAbsolute10, join as join17, resolve as resolve9 } from "path";
40649
40873
  import { lstatSync as lstatSync11, readFileSync as readFileSync12, opendirSync } from "fs";
40650
40874
  var HERMES_OPT_OUT = ".no-bundled-skills";
40651
40875
  var EVENTS = ["pre_llm_call", "pre_tool_call"];
@@ -40683,7 +40907,7 @@ function quoted(value) {
40683
40907
  return `'${value.replace(/'/g, `'\\''`)}'`;
40684
40908
  }
40685
40909
  function hermesHookDefinitions(supervisor) {
40686
- if (!isAbsolute9(supervisor.runtime) || !isAbsolute9(supervisor.path))
40910
+ if (!isAbsolute10(supervisor.runtime) || !isAbsolute10(supervisor.path))
40687
40911
  throw new Error("Expected absolute Hermes supervisor paths");
40688
40912
  const entry = (event) => ({ command: `${quoted(supervisor.runtime)} ${quoted(supervisor.path)} --event ${event}`, timeout: 15, ...event === "pre_tool_call" ? { fail_closed: true } : {} });
40689
40913
  return { pre_llm_call: entry("pre_llm_call"), pre_tool_call: entry("pre_tool_call") };
@@ -40719,16 +40943,16 @@ function assertHermesEnvironment(home) {
40719
40943
  throw new Error(`NATIVE_SKILL_DRIFT: Hermes ${variable} requires a dedicated discovery adapter; unset it before using this adapter`);
40720
40944
  }
40721
40945
  const selected = process.env.HERMES_HOME?.trim();
40722
- if (selected && (!isAbsolute9(selected) || resolve8(selected) !== join17(resolve8(home), ".hermes")))
40946
+ if (selected && (!isAbsolute10(selected) || resolve9(selected) !== join17(resolve9(home), ".hermes")))
40723
40947
  throw new Error("NATIVE_SKILL_DRIFT: custom Hermes homes/profiles require their own reviewed bridge");
40724
40948
  if (process.env.HERMES_ENABLE_PROJECT_PLUGINS?.trim() && !["0", "false", "no", "off"].includes(process.env.HERMES_ENABLE_PROJECT_PLUGINS.trim().toLowerCase()))
40725
40949
  throw new Error("NATIVE_SKILL_DRIFT: Hermes project plugins require a dedicated discovery review");
40726
40950
  }
40727
40951
  function read(path) {
40728
- for (let current = path;; current = dirname8(current)) {
40952
+ for (let current = path;; current = dirname9(current)) {
40729
40953
  if (lstatSync11(current, { throwIfNoEntry: false })?.isSymbolicLink())
40730
40954
  throw new Error("NATIVE_SKILL_DRIFT: symlink Hermes protection input");
40731
- if (dirname8(current) === current)
40955
+ if (dirname9(current) === current)
40732
40956
  break;
40733
40957
  }
40734
40958
  const stat = lstatSync11(path, { throwIfNoEntry: false });
@@ -40742,7 +40966,7 @@ function assertHermesProtection(home, config, command, profile, supervisor) {
40742
40966
  assertHermesEnvironment(home);
40743
40967
  if (read(join17(home, ".hermes", HERMES_OPT_OUT)) === null)
40744
40968
  throw new Error("NATIVE_SKILL_DRIFT: Hermes bundled skill reseeding is not disabled; run skills hook install");
40745
- if (!supervisor || !isAbsolute9(supervisor.path) || supervisor.runtime !== process.execPath || read(supervisor.path) !== renderHermesSupervisor(command, profile))
40969
+ if (!supervisor || !isAbsolute10(supervisor.path) || supervisor.runtime !== process.execPath || read(supervisor.path) !== renderHermesSupervisor(command, profile))
40746
40970
  throw new Error("NATIVE_SKILL_DRIFT: Hermes owned supervisor changed; run skills hook install");
40747
40971
  const raw = read(join17(home, ".hermes/shell-hooks-allowlist.json"));
40748
40972
  let trust;
@@ -40768,10 +40992,10 @@ function assertHermesProtection(home, config, command, profile, supervisor) {
40768
40992
  }
40769
40993
  function assertNoHermesLegacyShadow(root) {
40770
40994
  let entries = 0;
40771
- for (let cursor = resolve8(root);; cursor = dirname8(cursor)) {
40995
+ for (let cursor = resolve9(root);; cursor = dirname9(cursor)) {
40772
40996
  if (lstatSync11(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
40773
40997
  throw new Error("NATIVE_SKILL_DRIFT: symlink Hermes legacy discovery root");
40774
- if (dirname8(cursor) === cursor)
40998
+ if (dirname9(cursor) === cursor)
40775
40999
  break;
40776
41000
  }
40777
41001
  function scan(path, depth) {
@@ -40792,10 +41016,10 @@ function assertNoHermesLegacyShadow(root) {
40792
41016
  const hasDescriptor = Boolean(lstatSync11(join17(path, "SKILL.md"), { throwIfNoEntry: false }));
40793
41017
  const directory = opendirSync(path);
40794
41018
  try {
40795
- for (let child = directory.readSync();child; child = directory.readSync()) {
40796
- if (hasDescriptor && ["references", "templates", "assets", "scripts"].includes(child.name))
41019
+ for (let child2 = directory.readSync();child2; child2 = directory.readSync()) {
41020
+ if (hasDescriptor && ["references", "templates", "assets", "scripts"].includes(child2.name))
40797
41021
  continue;
40798
- scan(join17(path, child.name), depth + 1);
41022
+ scan(join17(path, child2.name), depth + 1);
40799
41023
  }
40800
41024
  } finally {
40801
41025
  directory.closeSync();
@@ -40852,18 +41076,18 @@ if (failed) process.exitCode = 2;
40852
41076
  }
40853
41077
 
40854
41078
  // src/lib/agent-discovery-directories.ts
40855
- import { createHash as createHash13 } from "crypto";
41079
+ import { createHash as createHash14 } from "crypto";
40856
41080
  import { lstatSync as lstatSync12, opendirSync as opendirSync2 } from "fs";
40857
- import { dirname as dirname9, isAbsolute as isAbsolute10, join as join18, resolve as resolve9 } from "path";
40858
- function need4(value, message) {
41081
+ import { dirname as dirname10, isAbsolute as isAbsolute11, join as join18, resolve as resolve10 } from "path";
41082
+ function need5(value, message) {
40859
41083
  if (!value)
40860
41084
  throw new Error(message);
40861
41085
  }
40862
41086
  function safe(path) {
40863
- need4(typeof path === "string" && path.length <= AGENT_POLICY_LIMITS.pathCharacters && isAbsolute10(path) && resolve9(path) === path && !path.includes("\x00"), "Expected a canonical absolute discovery directory path");
40864
- for (let cursor = path;; cursor = dirname9(cursor)) {
40865
- need4(!lstatSync12(cursor, { throwIfNoEntry: false })?.isSymbolicLink(), "Refusing symlink native discovery directory");
40866
- if (dirname9(cursor) === cursor)
41087
+ need5(typeof path === "string" && path.length <= AGENT_POLICY_LIMITS.pathCharacters && isAbsolute11(path) && resolve10(path) === path && !path.includes("\x00"), "Expected a canonical absolute discovery directory path");
41088
+ for (let cursor = path;; cursor = dirname10(cursor)) {
41089
+ need5(!lstatSync12(cursor, { throwIfNoEntry: false })?.isSymbolicLink(), "Refusing symlink native discovery directory");
41090
+ if (dirname10(cursor) === cursor)
40867
41091
  break;
40868
41092
  }
40869
41093
  }
@@ -40877,45 +41101,45 @@ function capture(path, budget2, excludedRoots, omittedRoots = [], rows) {
40877
41101
  const root = lstatSync12(path, { throwIfNoEntry: false });
40878
41102
  if (!root)
40879
41103
  return { path, sha256: null };
40880
- need4(root.isDirectory(), "Unsupported native discovery directory input");
40881
- const hash2 = createHash13("sha256");
41104
+ need5(root.isDirectory(), "Unsupported native discovery directory input");
41105
+ const hash2 = createHash14("sha256");
40882
41106
  function walk2(current, relative5, before, depth) {
40883
- need4(depth <= 64, "Native discovery directory depth limit exceeded");
41107
+ need5(depth <= 64, "Native discovery directory depth limit exceeded");
40884
41108
  const names = [], directory = opendirSync2(current);
40885
41109
  try {
40886
41110
  for (let entry = directory.readSync();entry; entry = directory.readSync()) {
40887
- need4(++budget2.entries <= AGENT_POLICY_LIMITS.discoveryDirectoryEntries, "Native discovery directory entry limit exceeded");
41111
+ need5(++budget2.entries <= AGENT_POLICY_LIMITS.discoveryDirectoryEntries, "Native discovery directory entry limit exceeded");
40888
41112
  names.push(entry.name);
40889
41113
  }
40890
41114
  } finally {
40891
41115
  directory.closeSync();
40892
41116
  }
40893
- need4(new Set(names).size === names.length, "Ambiguous native discovery directory names");
41117
+ need5(new Set(names).size === names.length, "Ambiguous native discovery directory names");
40894
41118
  for (const name of names.sort()) {
40895
- const child = join18(current, name), childRelative = relative5 ? `${relative5}/${name}` : name;
40896
- if (omittedRoots.includes(child))
41119
+ const child2 = join18(current, name), childRelative = relative5 ? `${relative5}/${name}` : name;
41120
+ if (omittedRoots.includes(child2))
40897
41121
  continue;
40898
- need4(child.length <= AGENT_POLICY_LIMITS.pathCharacters, "Native discovery directory path limit exceeded");
40899
- const stat = lstatSync12(child);
40900
- need4(stat.isFile() || stat.isDirectory(), "Refusing symlink or special native discovery directory member");
41122
+ need5(child2.length <= AGENT_POLICY_LIMITS.pathCharacters, "Native discovery directory path limit exceeded");
41123
+ const stat = lstatSync12(child2);
41124
+ need5(stat.isFile() || stat.isDirectory(), "Refusing symlink or special native discovery directory member");
40901
41125
  const row = JSON.stringify([childRelative, stat.isDirectory() ? "directory" : "file"]) + `
40902
41126
  `;
40903
41127
  budget2.bytes += Buffer.byteLength(row);
40904
- need4(budget2.bytes <= AGENT_POLICY_LIMITS.discoveryDirectoryBytes, "Native discovery directory metadata limit exceeded");
41128
+ need5(budget2.bytes <= AGENT_POLICY_LIMITS.discoveryDirectoryBytes, "Native discovery directory metadata limit exceeded");
40905
41129
  hash2.update(row);
40906
41130
  rows?.push(row);
40907
- if (stat.isDirectory() && !excludedRoots.includes(child))
40908
- walk2(child, childRelative, stat, depth + 1);
41131
+ if (stat.isDirectory() && !excludedRoots.includes(child2))
41132
+ walk2(child2, childRelative, stat, depth + 1);
40909
41133
  }
40910
- need4(same(before, lstatSync12(current, { throwIfNoEntry: false })), "Native discovery directory changed while reading");
41134
+ need5(same(before, lstatSync12(current, { throwIfNoEntry: false })), "Native discovery directory changed while reading");
40911
41135
  }
40912
41136
  walk2(path, "", root, 0);
40913
41137
  safe(path);
40914
41138
  return { path, sha256: hash2.digest("hex") };
40915
41139
  }
40916
41140
  function captureDiscoveryDirectoryProjection(paths, omittedRoots) {
40917
- need4(Array.isArray(paths) && paths.length <= AGENT_POLICY_LIMITS.discoveryDirectories && new Set(paths).size === paths.length, "Invalid projected discovery directory collection");
40918
- need4(omittedRoots.length <= AGENT_POLICY_LIMITS.discoveryRoots && new Set(omittedRoots).size === omittedRoots.length, "Invalid inactive discovery roots");
41141
+ need5(Array.isArray(paths) && paths.length <= AGENT_POLICY_LIMITS.discoveryDirectories && new Set(paths).size === paths.length, "Invalid projected discovery directory collection");
41142
+ need5(omittedRoots.length <= AGENT_POLICY_LIMITS.discoveryRoots && new Set(omittedRoots).size === omittedRoots.length, "Invalid inactive discovery roots");
40919
41143
  for (const root of omittedRoots)
40920
41144
  safe(root);
40921
41145
  const budget2 = { entries: 0, bytes: 0 };
@@ -40925,62 +41149,62 @@ function captureDiscoveryDirectoryProjection(paths, omittedRoots) {
40925
41149
  });
40926
41150
  }
40927
41151
  function verifyDiscoveryDirectoryProjection(directories, omittedRoots) {
40928
- need4(directories.length <= AGENT_POLICY_LIMITS.discoveryDirectories, "Invalid projected discovery directory collection");
41152
+ need5(directories.length <= AGENT_POLICY_LIMITS.discoveryDirectories, "Invalid projected discovery directory collection");
40929
41153
  let count = 0, bytes = 0;
40930
41154
  const expected = directories.map((directory) => {
40931
41155
  safe(directory.path);
40932
- need4(Array.isArray(directory.entries), "Missing reviewed directory membership inventory");
40933
- const hash2 = createHash13("sha256");
41156
+ need5(Array.isArray(directory.entries), "Missing reviewed directory membership inventory");
41157
+ const hash2 = createHash14("sha256");
40934
41158
  const kept = [];
40935
41159
  for (const row of directory.entries) {
40936
- need4(typeof row === "string" && ++count <= AGENT_POLICY_LIMITS.discoveryDirectoryEntries, "Invalid reviewed directory membership rows");
41160
+ need5(typeof row === "string" && ++count <= AGENT_POLICY_LIMITS.discoveryDirectoryEntries, "Invalid reviewed directory membership rows");
40937
41161
  bytes += Buffer.byteLength(row);
40938
- need4(bytes <= AGENT_POLICY_LIMITS.discoveryDirectoryBytes, "Reviewed directory membership byte limit exceeded");
41162
+ need5(bytes <= AGENT_POLICY_LIMITS.discoveryDirectoryBytes, "Reviewed directory membership byte limit exceeded");
40939
41163
  const value = JSON.parse(row);
40940
- need4(Array.isArray(value) && value.length === 2 && typeof value[0] === "string" && value[0] && !isAbsolute10(value[0]) && !value[0].split("/").some((part) => !part || part === "." || part === "..") && ["file", "directory"].includes(value[1]) && row === JSON.stringify(value) + `
41164
+ need5(Array.isArray(value) && value.length === 2 && typeof value[0] === "string" && value[0] && !isAbsolute11(value[0]) && !value[0].split("/").some((part) => !part || part === "." || part === "..") && ["file", "directory"].includes(value[1]) && row === JSON.stringify(value) + `
40941
41165
  `, "Invalid reviewed directory member");
40942
41166
  hash2.update(row);
40943
41167
  const path = join18(directory.path, value[0]);
40944
41168
  if (!omittedRoots.some((root) => path === root || path.startsWith(root + "/")))
40945
41169
  kept.push(row);
40946
41170
  }
40947
- need4(directory.sha256 === null ? directory.entries.length === 0 : hash2.digest("hex") === directory.sha256, "Reviewed directory inventory does not match its fingerprint");
41171
+ need5(directory.sha256 === null ? directory.entries.length === 0 : hash2.digest("hex") === directory.sha256, "Reviewed directory inventory does not match its fingerprint");
40948
41172
  const absent = omittedRoots.some((root) => directory.path === root || directory.path.startsWith(root + "/"));
40949
- return { path: directory.path, sha256: absent || directory.sha256 === null ? null : createHash13("sha256").update(kept.join("")).digest("hex") };
41173
+ return { path: directory.path, sha256: absent || directory.sha256 === null ? null : createHash14("sha256").update(kept.join("")).digest("hex") };
40950
41174
  });
40951
41175
  const current = captureDiscoveryDirectoryProjection(directories.map((item) => item.path), omittedRoots);
40952
- need4(current.every((item, index) => item.sha256 === expected[index].sha256), "Native discovery directory membership changed outside retired Codex roots");
41176
+ need5(current.every((item, index) => item.sha256 === expected[index].sha256), "Native discovery directory membership changed outside retired Codex roots");
40953
41177
  }
40954
41178
  function captureDiscoveryDirectories(paths, excludedRoots = []) {
40955
- need4(Array.isArray(paths) && paths.length <= AGENT_POLICY_LIMITS.discoveryDirectories && new Set(paths).size === paths.length, "Invalid native discovery directory collection");
41179
+ need5(Array.isArray(paths) && paths.length <= AGENT_POLICY_LIMITS.discoveryDirectories && new Set(paths).size === paths.length, "Invalid native discovery directory collection");
40956
41180
  const budget2 = { entries: 0, bytes: 0 };
40957
41181
  for (const root of excludedRoots)
40958
41182
  safe(root);
40959
41183
  return paths.map((path) => capture(path, budget2, excludedRoots));
40960
41184
  }
40961
41185
  function verifyDiscoveryDirectories(directories, excludedRoots = []) {
40962
- need4(Array.isArray(directories) && directories.length <= AGENT_POLICY_LIMITS.discoveryDirectories, "Invalid native discovery directory collection");
41186
+ need5(Array.isArray(directories) && directories.length <= AGENT_POLICY_LIMITS.discoveryDirectories, "Invalid native discovery directory collection");
40963
41187
  for (const directory of directories)
40964
- need4(directory && typeof directory === "object" && (directory.sha256 === null || typeof directory.sha256 === "string" && /^[a-f0-9]{64}$/.test(directory.sha256)), "Invalid native discovery directory digest");
41188
+ need5(directory && typeof directory === "object" && (directory.sha256 === null || typeof directory.sha256 === "string" && /^[a-f0-9]{64}$/.test(directory.sha256)), "Invalid native discovery directory digest");
40965
41189
  const current = captureDiscoveryDirectories(directories.map((directory) => directory.path), excludedRoots);
40966
41190
  for (let i = 0;i < directories.length; i++)
40967
- need4(current[i].sha256 === directories[i].sha256, `Native discovery directory membership changed; run skills hook install with a fresh discovery review: ${directories[i].path}`);
41191
+ need5(current[i].sha256 === directories[i].sha256, `Native discovery directory membership changed; run skills hook install with a fresh discovery review: ${directories[i].path}`);
40968
41192
  }
40969
41193
 
40970
41194
  // src/lib/agent-discovery-bytes.ts
40971
- import { createHash as createHash14 } from "crypto";
41195
+ import { createHash as createHash15 } from "crypto";
40972
41196
  import { closeSync as closeSync12, constants as constants9, fstatSync as fstatSync12, lstatSync as lstatSync13, openSync as openSync12, readSync as readSync7 } from "fs";
40973
- import { dirname as dirname10, isAbsolute as isAbsolute11, resolve as resolve10 } from "path";
41197
+ import { dirname as dirname11, isAbsolute as isAbsolute12, resolve as resolve11 } from "path";
40974
41198
  function discoveryByteBudget() {
40975
41199
  return { remaining: AGENT_POLICY_LIMITS.discoveryRawTotalBytes };
40976
41200
  }
40977
41201
  function safe2(path) {
40978
- if (typeof path !== "string" || !isAbsolute11(path) || path !== resolve10(path) || path.length > AGENT_POLICY_LIMITS.pathCharacters || path.includes("\x00"))
41202
+ if (typeof path !== "string" || !isAbsolute12(path) || path !== resolve11(path) || path.length > AGENT_POLICY_LIMITS.pathCharacters || path.includes("\x00"))
40979
41203
  throw new Error("Expected a canonical absolute raw discovery path");
40980
- for (let cursor = path;; cursor = dirname10(cursor)) {
41204
+ for (let cursor = path;; cursor = dirname11(cursor)) {
40981
41205
  if (lstatSync13(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
40982
41206
  throw new Error("Refusing symlink raw discovery input");
40983
- if (dirname10(cursor) === cursor)
41207
+ if (dirname11(cursor) === cursor)
40984
41208
  break;
40985
41209
  }
40986
41210
  }
@@ -40999,7 +41223,7 @@ function hashRawDiscoveryFile(path, budget2, changes) {
40999
41223
  if (bytes > AGENT_POLICY_LIMITS.discoveryRawSourceBytes)
41000
41224
  throw new Error("Raw discovery file byte limit exceeded");
41001
41225
  consume(budget2, bytes);
41002
- return createHash14("sha256").update(text2).digest("hex");
41226
+ return createHash15("sha256").update(text2).digest("hex");
41003
41227
  }
41004
41228
  const initial = lstatSync13(path, { throwIfNoEntry: false });
41005
41229
  if (!initial)
@@ -41013,7 +41237,7 @@ function hashRawDiscoveryFile(path, budget2, changes) {
41013
41237
  const opened = fstatSync12(fd);
41014
41238
  if (!opened.isFile() || !same2(initial, opened))
41015
41239
  throw new Error("Raw discovery input changed during open");
41016
- const hash2 = createHash14("sha256"), buffer = Buffer.alloc(64 * 1024);
41240
+ const hash2 = createHash15("sha256"), buffer = Buffer.alloc(64 * 1024);
41017
41241
  let bytes = 0;
41018
41242
  while (true) {
41019
41243
  const count = readSync7(fd, buffer, 0, Math.min(buffer.length, AGENT_POLICY_LIMITS.discoveryRawSourceBytes - bytes + 1), null);
@@ -41036,9 +41260,9 @@ function hashRawDiscoveryFile(path, budget2, changes) {
41036
41260
  }
41037
41261
 
41038
41262
  // src/lib/agent-discovery-path-bytes.ts
41039
- import { createHash as createHash15 } from "crypto";
41263
+ import { createHash as createHash16 } from "crypto";
41040
41264
  import { lstatSync as lstatSync14, readlinkSync as readlinkSync4 } from "fs";
41041
- import { dirname as dirname11, isAbsolute as isAbsolute12, join as join19, parse as parse3, resolve as resolve11, sep as sep5 } from "path";
41265
+ import { dirname as dirname12, isAbsolute as isAbsolute13, join as join19, parse as parse3, resolve as resolve12, sep as sep5 } from "path";
41042
41266
  function identity4(stat, mutable = false) {
41043
41267
  return {
41044
41268
  dev: String(stat.dev),
@@ -41049,12 +41273,12 @@ function identity4(stat, mutable = false) {
41049
41273
  ...mutable ? { size: String(stat.size), mtimeNs: String(stat.mtimeNs), ctimeNs: String(stat.ctimeNs) } : {}
41050
41274
  };
41051
41275
  }
41052
- function canonical4(path) {
41053
- if (typeof path !== "string" || !isAbsolute12(path) || path !== resolve11(path) || path.length > AGENT_POLICY_LIMITS.pathCharacters || path.includes("\x00") || Buffer.from(path).toString("utf8") !== path)
41276
+ function canonical5(path) {
41277
+ if (typeof path !== "string" || !isAbsolute13(path) || path !== resolve12(path) || path.length > AGENT_POLICY_LIMITS.pathCharacters || path.includes("\x00") || Buffer.from(path).toString("utf8") !== path)
41054
41278
  throw new Error("Expected a canonical absolute discovery path");
41055
41279
  }
41056
41280
  function trace(path) {
41057
- canonical4(path);
41281
+ canonical5(path);
41058
41282
  const rows = [], paths = [];
41059
41283
  let metadataBytes = 0, steps = 0, links = 0, cursor = parse3(path).root, pending = path.slice(cursor.length).split(sep5);
41060
41284
  function record4(path2, row) {
@@ -41079,7 +41303,7 @@ function trace(path) {
41079
41303
  if (!component || component === ".")
41080
41304
  continue;
41081
41305
  if (component === "..") {
41082
- cursor = dirname11(cursor);
41306
+ cursor = dirname12(cursor);
41083
41307
  continue;
41084
41308
  }
41085
41309
  const candidate = join19(cursor, component);
@@ -41099,11 +41323,11 @@ function trace(path) {
41099
41323
  if (!target || target.includes("\x00") || Buffer.byteLength(target) > AGENT_POLICY_LIMITS.pathCharacters || !after.isSymbolicLink() || JSON.stringify(identity4(stat, true)) !== JSON.stringify(identity4(after, true)))
41100
41324
  throw new Error("Discovery link changed during read");
41101
41325
  record4(candidate, { type: "link", target, ...identity4(stat, true) });
41102
- if (isAbsolute12(target)) {
41326
+ if (isAbsolute13(target)) {
41103
41327
  cursor = parse3(target).root;
41104
41328
  root();
41105
41329
  }
41106
- const remainder = isAbsolute12(target) ? target.slice(parse3(target).root.length) : target;
41330
+ const remainder = isAbsolute13(target) ? target.slice(parse3(target).root.length) : target;
41107
41331
  pending = [...remainder.split(sep5), ...pending];
41108
41332
  if (pending.length + steps > AGENT_POLICY_LIMITS.discoveryPathSteps)
41109
41333
  throw new Error("Discovery path step limit exceeded");
@@ -41146,15 +41370,15 @@ function hashDiscoveryPathFile(path, budget2, changes) {
41146
41370
  const after = trace(path);
41147
41371
  if (JSON.stringify(before.rows) !== JSON.stringify(after.rows) || before.file !== after.file)
41148
41372
  throw new Error("Discovery path input changed during read");
41149
- return createHash15("sha256").update(JSON.stringify({ version: 1, path, rows: before.rows, content })).digest("hex");
41373
+ return createHash16("sha256").update(JSON.stringify({ version: 1, path, rows: before.rows, content })).digest("hex");
41150
41374
  }
41151
41375
 
41152
41376
  // src/lib/claude-plugin-manifest-witness.ts
41153
- import { createHash as createHash16 } from "crypto";
41377
+ import { createHash as createHash17 } from "crypto";
41154
41378
  var CLAUDE_PLUGIN_MANIFEST_LIMITS = Object.freeze({ bytes: 1024 * 1024, depth: 32, nodes: 65536, stringCharacters: 16384 });
41155
- function requireValue(value, reason) {
41379
+ function requireValue(value, reason2) {
41156
41380
  if (!value)
41157
- throw new Error("Claude plugin manifest " + reason);
41381
+ throw new Error("Claude plugin manifest " + reason2);
41158
41382
  }
41159
41383
  function parse4(text2) {
41160
41384
  requireValue(Buffer.byteLength(text2, "utf8") <= CLAUDE_PLUGIN_MANIFEST_LIMITS.bytes, "exceeds its byte limit");
@@ -41230,7 +41454,7 @@ function parse4(text2) {
41230
41454
  requireValue(at === text2.length && root.kind === "object", "requires a JSON object without trailing content");
41231
41455
  return root;
41232
41456
  }
41233
- function canonical5(value) {
41457
+ function canonical6(value) {
41234
41458
  if (value.kind === "string")
41235
41459
  return JSON.stringify(value.value);
41236
41460
  if (value.kind === "number")
@@ -41238,19 +41462,19 @@ function canonical5(value) {
41238
41462
  if (value.kind === "literal")
41239
41463
  return value.value;
41240
41464
  if (value.kind === "array")
41241
- return "[" + value.items.map(canonical5).join(",") + "]";
41242
- return "{" + value.entries.map(([key, item]) => JSON.stringify(key) + ":" + canonical5(item)).join(",") + "}";
41465
+ return "[" + value.items.map(canonical6).join(",") + "]";
41466
+ return "{" + value.entries.map(([key, item]) => JSON.stringify(key) + ":" + canonical6(item)).join(",") + "}";
41243
41467
  }
41244
41468
  var DESCRIPTIVE_FIELDS = new Set(["description", "version", "author", "homepage", "repository", "license", "keywords"]);
41245
- function validateText(value, field) {
41246
- requireValue(value?.kind === "string" && value.value.length <= CLAUDE_PLUGIN_MANIFEST_LIMITS.stringCharacters, "has an invalid " + field + " field");
41469
+ function validateText(value, field2) {
41470
+ requireValue(value?.kind === "string" && value.value.length <= CLAUDE_PLUGIN_MANIFEST_LIMITS.stringCharacters, "has an invalid " + field2 + " field");
41247
41471
  }
41248
41472
  function validateDescriptiveFields(manifest) {
41249
41473
  const values = new Map(manifest.entries);
41250
- for (const field of ["description", "version", "homepage", "license"]) {
41251
- const value = values.get(field);
41474
+ for (const field2 of ["description", "version", "homepage", "license"]) {
41475
+ const value = values.get(field2);
41252
41476
  if (value !== undefined)
41253
- validateText(value, field);
41477
+ validateText(value, field2);
41254
41478
  }
41255
41479
  const author = values.get("author");
41256
41480
  if (author !== undefined) {
@@ -41275,10 +41499,10 @@ function hashClaudePluginManifest(text2) {
41275
41499
  const manifest = parse4(text2);
41276
41500
  validateDescriptiveFields(manifest);
41277
41501
  const discovery = { kind: "object", entries: manifest.entries.filter(([key]) => !DESCRIPTIVE_FIELDS.has(key)) };
41278
- return createHash16("sha256").update(canonical5(discovery)).digest("hex");
41502
+ return createHash17("sha256").update(canonical6(discovery)).digest("hex");
41279
41503
  }
41280
41504
  function projectReviewedClaudePluginManifest(text2, reviewedSha256) {
41281
- if (!/^[a-f0-9]{64}$/.test(reviewedSha256) || createHash16("sha256").update(text2).digest("hex") !== reviewedSha256) {
41505
+ if (!/^[a-f0-9]{64}$/.test(reviewedSha256) || createHash17("sha256").update(text2).digest("hex") !== reviewedSha256) {
41282
41506
  throw new Error("Reviewed Claude plugin manifest changed before semantic projection");
41283
41507
  }
41284
41508
  return hashClaudePluginManifest(text2);
@@ -41286,14 +41510,14 @@ function projectReviewedClaudePluginManifest(text2, reviewedSha256) {
41286
41510
 
41287
41511
  // src/lib/plugin-discovery.ts
41288
41512
  import { closeSync as closeSync14, constants as constants11, fstatSync as fstatSync14, lstatSync as lstatSync17, openSync as openSync14, opendirSync as opendirSync4, readSync as readSync9 } from "fs";
41289
- import { basename as basename6, dirname as dirname13, isAbsolute as isAbsolute16, join as join24, resolve as resolve14 } from "path";
41513
+ import { basename as basename7, dirname as dirname14, isAbsolute as isAbsolute17, join as join24, resolve as resolve15 } from "path";
41290
41514
 
41291
41515
  // src/lib/plugin-admission.ts
41292
41516
  import { homedir as homedir2 } from "os";
41293
- import { isAbsolute as isAbsolute15, join as join23, resolve as resolve13 } from "path";
41517
+ import { isAbsolute as isAbsolute16, join as join23, resolve as resolve14 } from "path";
41294
41518
 
41295
41519
  // src/lib/plugin-projection.ts
41296
- import { createHash as createHash17 } from "crypto";
41520
+ import { createHash as createHash18 } from "crypto";
41297
41521
  import { posix as posix2 } from "path";
41298
41522
  var PLUGIN_PROJECTION_MANIFEST = "plugin-projection.json";
41299
41523
  var PLUGIN_PROJECTION_LIMITS = Object.freeze({ files: 1024, bytes: 64 * 1024 * 1024, fileBytes: 16 * 1024 * 1024, metadataBytes: 512 * 1024, registrations: 64, history: 128 });
@@ -41304,7 +41528,7 @@ function pluginNeed(value, message) {
41304
41528
  if (!value)
41305
41529
  pluginRefusal(message);
41306
41530
  }
41307
- var pluginHash = (bytes) => createHash17("sha256").update(bytes).digest("hex");
41531
+ var pluginHash = (bytes) => createHash18("sha256").update(bytes).digest("hex");
41308
41532
  function pluginObject(value) {
41309
41533
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
41310
41534
  }
@@ -41492,9 +41716,9 @@ function buildPluginProjection(entries) {
41492
41716
  }
41493
41717
 
41494
41718
  // src/lib/plugin-projection-store.ts
41495
- import { createHash as createHash18, randomUUID as randomUUID3 } from "crypto";
41719
+ import { createHash as createHash19, randomUUID as randomUUID3 } from "crypto";
41496
41720
  import { constants as constants10, closeSync as closeSync13, fchmodSync, fstatSync as fstatSync13, fsyncSync as fsyncSync3, linkSync as linkSync2, lstatSync as lstatSync15, mkdirSync as mkdirSync5, openSync as openSync13, opendirSync as opendirSync3, readSync as readSync8, renameSync as renameSync3, rmdirSync as rmdirSync2, rmSync, unlinkSync as unlinkSync4, writeSync as writeSync2 } from "fs";
41497
- import { dirname as dirname12, isAbsolute as isAbsolute13, join as join20, parse as parse6, resolve as resolve12 } from "path";
41721
+ import { dirname as dirname13, isAbsolute as isAbsolute14, join as join20, parse as parse6, resolve as resolve13 } from "path";
41498
41722
  var READ_FLAGS = constants10.O_RDONLY | constants10.O_NOFOLLOW | constants10.O_NONBLOCK;
41499
41723
  var WRITE_FLAGS = constants10.O_WRONLY | constants10.O_CREAT | constants10.O_EXCL | constants10.O_NOFOLLOW | constants10.O_NONBLOCK;
41500
41724
  var uid = () => typeof process.getuid === "function" ? BigInt(process.getuid()) : undefined;
@@ -41508,8 +41732,8 @@ function stat(path) {
41508
41732
  return pluginRefusal("Cannot inspect plugin filesystem entry");
41509
41733
  }
41510
41734
  }
41511
- function canonical6(path) {
41512
- pluginNeed(typeof path === "string" && path.length <= 8192 && isAbsolute13(path) && resolve12(path) === path && !/[\x00-\x1f\x7f]/.test(path), "Plugin storage paths must be canonical absolute paths");
41735
+ function canonical7(path) {
41736
+ pluginNeed(typeof path === "string" && path.length <= 8192 && isAbsolute14(path) && resolve13(path) === path && !/[\x00-\x1f\x7f]/.test(path), "Plugin storage paths must be canonical absolute paths");
41513
41737
  }
41514
41738
  function owner(stats, system = false) {
41515
41739
  const current = uid();
@@ -41519,8 +41743,8 @@ function same3(left, right, identityOnly = false) {
41519
41743
  pluginNeed(right && left.dev === right.dev && left.ino === right.ino && left.mode === right.mode && left.uid === right.uid && left.gid === right.gid && (identityOnly || left.size === right.size && left.nlink === right.nlink && left.mtimeNs === right.mtimeNs && left.ctimeNs === right.ctimeNs), "Plugin filesystem entry changed during access");
41520
41744
  }
41521
41745
  function ancestors(path, create = false) {
41522
- canonical6(path);
41523
- const result = [], parent = dirname12(path), filesystemRoot = parse6(parent).root;
41746
+ canonical7(path);
41747
+ const result = [], parent = dirname13(path), filesystemRoot = parse6(parent).root;
41524
41748
  let current = filesystemRoot;
41525
41749
  for (const segment of ["", ...parent.slice(filesystemRoot.length).split("/").filter(Boolean)]) {
41526
41750
  if (segment)
@@ -41548,7 +41772,7 @@ function verifyAncestors(chain, identityOnly = true) {
41548
41772
  }
41549
41773
  function privateParent(path) {
41550
41774
  const chain = ancestors(path, true), parent = chain.at(-1);
41551
- pluginNeed(parent && parent.path === dirname12(path), "Plugin storage parent is unavailable");
41775
+ pluginNeed(parent && parent.path === dirname13(path), "Plugin storage parent is unavailable");
41552
41776
  owner(parent.stat);
41553
41777
  pluginNeed((parent.stat.mode & 0o7777n) === 0o700n, "Plugin storage parent must have mode 0700");
41554
41778
  return chain;
@@ -41834,7 +42058,7 @@ function pluginExecutableDigest(path) {
41834
42058
  const opened = fstatSync13(fd, { bigint: true });
41835
42059
  same3(before, opened);
41836
42060
  fileShape(opened, maximum, "executable");
41837
- const hash2 = createHash18("sha256"), buffer = new Uint8Array(64 * 1024);
42061
+ const hash2 = createHash19("sha256"), buffer = new Uint8Array(64 * 1024);
41838
42062
  let remaining = Number(opened.size);
41839
42063
  while (remaining > 0) {
41840
42064
  const count = readSync8(fd, buffer, 0, Math.min(buffer.byteLength, remaining), null);
@@ -41859,7 +42083,7 @@ function pluginExecutableDigest(path) {
41859
42083
 
41860
42084
  // src/lib/skill-validation.ts
41861
42085
  import { existsSync as existsSync5, lstatSync as lstatSync16, readFileSync as readFileSync14, readdirSync as readdirSync6, statSync as statSync6 } from "fs";
41862
- import { isAbsolute as isAbsolute14, join as join22, normalize as normalize3 } from "path";
42086
+ import { isAbsolute as isAbsolute15, join as join22, normalize as normalize3 } from "path";
41863
42087
 
41864
42088
  // src/lib/hosted-skill-set.ts
41865
42089
  import { existsSync as existsSync4, readFileSync as readFileSync13, readdirSync as readdirSync5, statSync as statSync5 } from "fs";
@@ -41963,7 +42187,7 @@ function sortMessages(messages) {
41963
42187
  return [...messages].sort((a, b) => a.code.localeCompare(b.code) || a.message.localeCompare(b.message));
41964
42188
  }
41965
42189
  function isSafeRelativePath(value) {
41966
- if (!value.trim() || isAbsolute14(value))
42190
+ if (!value.trim() || isAbsolute15(value))
41967
42191
  return false;
41968
42192
  const normalized = normalize3(value).replace(/\\/g, "/");
41969
42193
  return normalized !== ".." && !normalized.startsWith("../") && !normalized.includes("/../");
@@ -42328,7 +42552,7 @@ function validatePluginTarget(value) {
42328
42552
  for (const registration of value.registrations) {
42329
42553
  pluginKeys(registration, ["scope", "projectPath"]);
42330
42554
  pluginNeed(registration.scope === "user" || registration.scope === "project", "Unsupported plugin registration scope");
42331
- pluginNeed(registration.scope === "user" ? registration.projectPath === null : typeof registration.projectPath === "string" && isAbsolute15(registration.projectPath) && resolve13(registration.projectPath) === registration.projectPath, "Plugin scope requires its exact project path");
42555
+ pluginNeed(registration.scope === "user" ? registration.projectPath === null : typeof registration.projectPath === "string" && isAbsolute16(registration.projectPath) && resolve14(registration.projectPath) === registration.projectPath, "Plugin scope requires its exact project path");
42332
42556
  const key = JSON.stringify([registration.scope, registration.projectPath]);
42333
42557
  pluginNeed(!scopes.has(key), "Duplicate plugin registration scope");
42334
42558
  scopes.add(key);
@@ -42336,7 +42560,7 @@ function validatePluginTarget(value) {
42336
42560
  for (const key of ["native", "resolver"]) {
42337
42561
  pluginKeys(value[key], key === "native" ? ["version", "executable", "digest"] : ["executable", "digest"]);
42338
42562
  pluginText(value[key].executable);
42339
- pluginNeed(isAbsolute15(value[key].executable) && resolve13(value[key].executable) === value[key].executable, "Plugin executable must have a canonical absolute path");
42563
+ pluginNeed(isAbsolute16(value[key].executable) && resolve14(value[key].executable) === value[key].executable, "Plugin executable must have a canonical absolute path");
42340
42564
  pluginDigest(value[key].digest);
42341
42565
  }
42342
42566
  pluginNeed(["2.1.274", "2.1.276"].includes(value.native.version), "Plugin admission requires a certified Claude command-source runtime (2.1.274 or 2.1.276)");
@@ -42481,14 +42705,14 @@ function validatePlan(value) {
42481
42705
  pluginNeed(observedEvidenceDigest(plan.observation) === plan.evidenceDigest, "Plugin receipt observed evidence changed");
42482
42706
  pluginNeed(identityDigest(plan) === plan.planDigest, "Plugin receipt immutable identity changed");
42483
42707
  }
42484
- var quote = (value) => `'${value.replaceAll("'", "'\\''")}'`;
42708
+ var quote2 = (value) => `'${value.replaceAll("'", "'\\''")}'`;
42485
42709
  var resolverGuard = 'exec 9<"$1"; actual=$(/usr/bin/sha256sum /proc/self/fd/9); actual=${actual%% *}; [ "sha256:$actual" = "$2" ]; exec /proc/self/fd/9 integration plugin resolve --binding "$3"';
42486
42710
  function pluginResolverCommand(binding) {
42487
- return `${quote("/bin/sh")} -eu -c ${quote(resolverGuard)} plugin-resolver ${quote(binding.target.resolver.executable)} ${quote(binding.target.resolver.digest)} ${quote(bindingId(binding))}`;
42711
+ return `${quote2("/bin/sh")} -eu -c ${quote2(resolverGuard)} plugin-resolver ${quote2(binding.target.resolver.executable)} ${quote2(binding.target.resolver.digest)} ${quote2(bindingId(binding))}`;
42488
42712
  }
42489
42713
  function root(options) {
42490
42714
  const path = options.storeRoot ?? pluginAdmissionRoot();
42491
- pluginNeed(isAbsolute15(path) && resolve13(path) === path, "Invalid plugin admission store root");
42715
+ pluginNeed(isAbsolute16(path) && resolve14(path) === path, "Invalid plugin admission store root");
42492
42716
  return path;
42493
42717
  }
42494
42718
  function pluginBindingPath(storeRoot, id2) {
@@ -42693,15 +42917,15 @@ function validateManagedPluginWitnesses(value) {
42693
42917
  pluginNeed(typeof item.bindingId === "string" && /^[a-f0-9]{64}$/.test(item.bindingId) && !seen.has(item.bindingId), "Invalid or duplicate managed plugin witness");
42694
42918
  seen.add(item.bindingId);
42695
42919
  pluginText(item.storeRoot);
42696
- pluginNeed(isAbsolute16(item.storeRoot) && resolve14(item.storeRoot) === item.storeRoot, "Invalid plugin receipt store path");
42920
+ pluginNeed(isAbsolute17(item.storeRoot) && resolve15(item.storeRoot) === item.storeRoot, "Invalid plugin receipt store path");
42697
42921
  }
42698
42922
  }
42699
42923
  function safe3(path) {
42700
42924
  pluginText(path);
42701
- pluginNeed(isAbsolute16(path) && resolve14(path) === path, "Invalid plugin registry path");
42702
- for (let at = path;; at = dirname13(at)) {
42925
+ pluginNeed(isAbsolute17(path) && resolve15(path) === path, "Invalid plugin registry path");
42926
+ for (let at = path;; at = dirname14(at)) {
42703
42927
  pluginNeed(!lstatSync17(at, { throwIfNoEntry: false })?.isSymbolicLink(), "Plugin registry path traverses a symlink");
42704
- if (at === dirname13(at))
42928
+ if (at === dirname14(at))
42705
42929
  break;
42706
42930
  }
42707
42931
  }
@@ -42751,7 +42975,7 @@ function hashManagedPluginRegistry(path, managed) {
42751
42975
  seen.add(target.pluginId);
42752
42976
  const rows = plugins[target.pluginId];
42753
42977
  pluginNeed(Array.isArray(rows) && rows.length === target.registrations.length, "Managed plugin registration membership changed");
42754
- const [name, market] = target.pluginId.split("@"), cacheRoot = join24(dirname13(path), "cache", market, name);
42978
+ const [name, market] = target.pluginId.split("@"), cacheRoot = join24(dirname14(path), "cache", market, name);
42755
42979
  const scopes = new Set, approvals = new Map, currentFiles = new Map;
42756
42980
  plugins[target.pluginId] = rows.map((row) => {
42757
42981
  pluginNeed(pluginObject(row), "Invalid managed plugin registration");
@@ -42767,7 +42991,7 @@ function hashManagedPluginRegistry(path, managed) {
42767
42991
  pluginNeed(/^(?:[A-Za-z0-9][A-Za-z0-9._+-]*-)?[a-f0-9]{12}$/.test(row.version) && row.installPath === join24(cacheRoot, row.version), "Managed plugin cache path or version is outside its registration");
42768
42992
  const approval = (producer) => {
42769
42993
  pluginText(producer);
42770
- const digest2 = `sha256:${basename6(producer)}`;
42994
+ const digest2 = `sha256:${basename7(producer)}`;
42771
42995
  const receipt2 = readPluginAdmissionReceipt(witness.storeRoot, witness.bindingId, digest2);
42772
42996
  pluginNeed(receipt2.materializedPath === producer, "Managed producer path is not an approved immutable projection");
42773
42997
  if (!verified.has(producer)) {
@@ -42829,39 +43053,39 @@ function captureManagedPluginRegistry(path, managedPlugins) {
42829
43053
  }
42830
43054
 
42831
43055
  // src/lib/claude-marketplace-registry.ts
42832
- import { createHash as createHash19 } from "crypto";
43056
+ import { createHash as createHash20 } from "crypto";
42833
43057
  import { closeSync as closeSync15, constants as constants12, fstatSync as fstatSync15, lstatSync as lstatSync18, openSync as openSync15, readSync as readSync10 } from "fs";
42834
- import { basename as basename7, dirname as dirname14, isAbsolute as isAbsolute17, resolve as resolve15 } from "path";
43058
+ import { basename as basename8, dirname as dirname15, isAbsolute as isAbsolute18, resolve as resolve16 } from "path";
42835
43059
  var CLAUDE_MARKETPLACE_REGISTRY_LIMITS = Object.freeze({ bytes: 1024 * 1024, rows: 1024, depth: 32, nodes: 65536, stringCharacters: 16384, pathCharacters: 4096 });
42836
- function need5(value, reason) {
43060
+ function need6(value, reason2) {
42837
43061
  if (!value)
42838
- throw new Error(`Claude marketplace registry ${reason}`);
43062
+ throw new Error(`Claude marketplace registry ${reason2}`);
42839
43063
  }
42840
43064
  function absolutePath3(value) {
42841
- need5(typeof value === "string" && value.length > 0 && value.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.pathCharacters && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute17(value) && resolve15(value) === value, "requires a normalized absolute path");
43065
+ need6(typeof value === "string" && value.length > 0 && value.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.pathCharacters && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute18(value) && resolve16(value) === value, "requires a normalized absolute path");
42842
43066
  }
42843
43067
  var sameFile2 = (a, b) => a.dev === b.dev && a.ino === b.ino && a.mode === b.mode && a.uid === b.uid && a.gid === b.gid && a.nlink === b.nlink && a.size === b.size && a.mtimeNs === b.mtimeNs && a.ctimeNs === b.ctimeNs;
42844
43068
  function parents2(path) {
42845
43069
  const result = [];
42846
- for (let at = dirname14(path);; at = dirname14(at)) {
43070
+ for (let at = dirname15(path);; at = dirname15(at)) {
42847
43071
  const stat2 = lstatSync18(at, { bigint: true });
42848
- need5(stat2.isDirectory() && !stat2.isSymbolicLink(), "path traverses a symlink or non-directory");
43072
+ need6(stat2.isDirectory() && !stat2.isSymbolicLink(), "path traverses a symlink or non-directory");
42849
43073
  result.push([at, stat2]);
42850
- if (at === dirname14(at))
43074
+ if (at === dirname15(at))
42851
43075
  return result;
42852
43076
  }
42853
43077
  }
42854
43078
  function readRegistry2(path, budget2) {
42855
43079
  absolutePath3(path);
42856
- need5(basename7(path) === "known_marketplaces.json", "requires known_marketplaces.json");
42857
- need5(Number.isSafeInteger(budget2.remaining) && budget2.remaining >= 0, "has an invalid byte budget");
43080
+ need6(basename8(path) === "known_marketplaces.json", "requires known_marketplaces.json");
43081
+ need6(Number.isSafeInteger(budget2.remaining) && budget2.remaining >= 0, "has an invalid byte budget");
42858
43082
  const ancestors2 = parents2(path), initial = lstatSync18(path, { bigint: true });
42859
- need5(initial.isFile() && !initial.isSymbolicLink() && initial.size <= BigInt(CLAUDE_MARKETPLACE_REGISTRY_LIMITS.bytes), "is not a bounded regular file");
42860
- need5(initial.size <= BigInt(budget2.remaining), "exceeds its aggregate byte limit");
43083
+ need6(initial.isFile() && !initial.isSymbolicLink() && initial.size <= BigInt(CLAUDE_MARKETPLACE_REGISTRY_LIMITS.bytes), "is not a bounded regular file");
43084
+ need6(initial.size <= BigInt(budget2.remaining), "exceeds its aggregate byte limit");
42861
43085
  const fd = openSync15(path, constants12.O_RDONLY | constants12.O_NOFOLLOW | constants12.O_NONBLOCK);
42862
43086
  try {
42863
43087
  const opened = fstatSync15(fd, { bigint: true });
42864
- need5(opened.isFile() && sameFile2(initial, opened), "changed during open");
43088
+ need6(opened.isFile() && sameFile2(initial, opened), "changed during open");
42865
43089
  const bytes = Buffer.alloc(Number(opened.size) + 1);
42866
43090
  let length = 0;
42867
43091
  while (length < bytes.length) {
@@ -42871,10 +43095,10 @@ function readRegistry2(path, budget2) {
42871
43095
  length += count;
42872
43096
  }
42873
43097
  const after = fstatSync15(fd, { bigint: true }), current = lstatSync18(path, { bigint: true });
42874
- need5(current.isFile() && sameFile2(opened, after) && sameFile2(after, current) && BigInt(length) === opened.size, "changed during read");
43098
+ need6(current.isFile() && sameFile2(opened, after) && sameFile2(after, current) && BigInt(length) === opened.size, "changed during read");
42875
43099
  for (const [ancestor, before] of ancestors2) {
42876
43100
  const now = lstatSync18(ancestor, { bigint: true });
42877
- need5(now.isDirectory() && before.dev === now.dev && before.ino === now.ino && before.mode === now.mode, "parent changed during read");
43101
+ need6(now.isDirectory() && before.dev === now.dev && before.ino === now.ino && before.mode === now.mode, "parent changed during read");
42878
43102
  }
42879
43103
  budget2.remaining -= length;
42880
43104
  try {
@@ -42894,7 +43118,7 @@ function parse7(text2) {
42894
43118
  at++;
42895
43119
  };
42896
43120
  function string() {
42897
- need5(text2[at] === '"', "contains invalid JSON");
43121
+ need6(text2[at] === '"', "contains invalid JSON");
42898
43122
  const start = at++;
42899
43123
  while (at < text2.length) {
42900
43124
  const character = text2[at++];
@@ -42905,7 +43129,7 @@ function parse7(text2) {
42905
43129
  } catch {
42906
43130
  throw new Error("Claude marketplace registry contains invalid JSON string");
42907
43131
  }
42908
- need5(value2.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.stringCharacters, "exceeds its string limit");
43132
+ need6(value2.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.stringCharacters, "exceeds its string limit");
42909
43133
  return value2;
42910
43134
  }
42911
43135
  if (character === "\\")
@@ -42914,7 +43138,7 @@ function parse7(text2) {
42914
43138
  throw new Error("Claude marketplace registry contains an unterminated JSON string");
42915
43139
  }
42916
43140
  function value(depth) {
42917
- need5(depth <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.depth && ++nodes <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.nodes, "exceeds its nesting or node limit");
43141
+ need6(depth <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.depth && ++nodes <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.nodes, "exceeds its nesting or node limit");
42918
43142
  space();
42919
43143
  const character = text2[at];
42920
43144
  if (character === '"')
@@ -42928,17 +43152,17 @@ function parse7(text2) {
42928
43152
  if (object6) {
42929
43153
  space();
42930
43154
  const key = string();
42931
- need5(!keys2.has(key), "contains a duplicate JSON key");
43155
+ need6(!keys2.has(key), "contains a duplicate JSON key");
42932
43156
  keys2.add(key);
42933
43157
  space();
42934
- need5(text2[at++] === ":", "contains invalid JSON");
43158
+ need6(text2[at++] === ":", "contains invalid JSON");
42935
43159
  entries.push([key, value(depth + 1)]);
42936
43160
  } else
42937
43161
  items.push(value(depth + 1));
42938
43162
  space();
42939
43163
  if (text2[at] === end)
42940
43164
  break;
42941
- need5(text2[at++] === ",", "contains invalid JSON");
43165
+ need6(text2[at++] === ",", "contains invalid JSON");
42942
43166
  }
42943
43167
  at++;
42944
43168
  return object6 ? { kind: "object", entries } : { kind: "array", items };
@@ -42950,96 +43174,112 @@ function parse7(text2) {
42950
43174
  }
42951
43175
  numberPattern.lastIndex = at;
42952
43176
  const number = numberPattern.exec(text2);
42953
- need5(number, "contains invalid JSON");
43177
+ need6(number, "contains invalid JSON");
42954
43178
  at += number[0].length;
42955
43179
  return { kind: "number", value: number[0] };
42956
43180
  }
42957
43181
  const root2 = value(0);
42958
43182
  space();
42959
- need5(at === text2.length && root2.kind === "object", "requires a JSON object without trailing content");
42960
- need5(root2.entries.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.rows, "exceeds its marketplace row limit");
43183
+ need6(at === text2.length && root2.kind === "object", "requires a JSON object without trailing content");
43184
+ need6(root2.entries.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.rows, "exceeds its marketplace row limit");
42961
43185
  return root2;
42962
43186
  }
42963
43187
  function exactKeys2(value, keys2) {
42964
43188
  return value?.kind === "object" && value.entries.length === keys2.length && value.entries.every(([key]) => keys2.includes(key));
42965
43189
  }
42966
- var field = (object6, key) => object6.entries.find(([name]) => name === key)?.[1];
43190
+ var field2 = (object6, key) => object6.entries.find(([name]) => name === key)?.[1];
42967
43191
  function textField(value) {
42968
- need5(value?.kind === "string" && value.value.length > 0 && !/[\x00-\x1f\x7f]/.test(value.value), "contains an invalid recognized field");
43192
+ need6(value?.kind === "string" && value.value.length > 0 && !/[\x00-\x1f\x7f]/.test(value.value), "contains an invalid recognized field");
42969
43193
  return value.value;
42970
43194
  }
42971
43195
  function normalizeRow(row, version = 1) {
42972
43196
  if (!exactKeys2(row, ["source", "installLocation", "lastUpdated"])) {
42973
43197
  if (version !== 2 || !exactKeys2(row, ["source", "installLocation", "lastUpdated", "autoUpdate"]))
42974
43198
  return;
42975
- const autoUpdate = field(row, "autoUpdate");
42976
- need5(autoUpdate?.kind === "literal" && (autoUpdate.value === "true" || autoUpdate.value === "false"), "contains an invalid automatic-update preference");
43199
+ const autoUpdate = field2(row, "autoUpdate");
43200
+ need6(autoUpdate?.kind === "literal" && (autoUpdate.value === "true" || autoUpdate.value === "false"), "contains an invalid automatic-update preference");
42977
43201
  }
42978
- const source = field(row, "source");
43202
+ const source = field2(row, "source");
42979
43203
  if (source?.kind !== "object")
42980
43204
  return;
42981
- const type = field(source, "source");
43205
+ const type = field2(source, "source");
42982
43206
  if (type?.kind !== "string" || !["github", "directory"].includes(type.value))
42983
43207
  return;
42984
43208
  const location = type.value === "github" ? "repo" : "path";
42985
43209
  if (!exactKeys2(source, ["source", location]))
42986
43210
  return;
42987
- const sourceLocation = textField(field(source, location));
43211
+ const sourceLocation = textField(field2(source, location));
42988
43212
  if (type.value === "directory")
42989
43213
  absolutePath3(sourceLocation);
42990
- absolutePath3(textField(field(row, "installLocation")));
42991
- const updated = textField(field(row, "lastUpdated"));
42992
- need5(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/.test(updated), "contains an invalid recognized update timestamp");
43214
+ absolutePath3(textField(field2(row, "installLocation")));
43215
+ const updated = textField(field2(row, "lastUpdated"));
43216
+ need6(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/.test(updated), "contains an invalid recognized update timestamp");
42993
43217
  const millis = Date.parse(updated);
42994
- need5(Number.isFinite(millis) && new Date(millis).toISOString() === updated, "contains an invalid recognized update timestamp");
43218
+ need6(Number.isFinite(millis) && new Date(millis).toISOString() === updated, "contains an invalid recognized update timestamp");
42995
43219
  row.entries = row.entries.map(([key, value]) => [key, key === "lastUpdated" ? { kind: "validated-update-time" } : value]);
42996
43220
  }
42997
43221
  function captureClaudeMarketplaceRegistry(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
42998
43222
  const value = parse7(readRegistry2(path, budget2));
42999
43223
  for (const [, row] of value.entries)
43000
43224
  normalizeRow(row);
43001
- const sha2562 = createHash19("sha256").update("hasna.skills.claude-marketplace-registry.v1\x00").update(JSON.stringify(value)).digest("hex");
43225
+ const sha2562 = createHash20("sha256").update("hasna.skills.claude-marketplace-registry.v1\x00").update(JSON.stringify(value)).digest("hex");
43002
43226
  return { path, hashMode: "claude-marketplace-registry", sha256: sha2562 };
43003
43227
  }
43004
43228
  function captureClaudeMarketplaceRegistryV2(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
43005
43229
  const value = parse7(readRegistry2(path, budget2));
43006
43230
  for (const [, row] of value.entries)
43007
43231
  normalizeRow(row, 2);
43008
- const sha2562 = createHash19("sha256").update("hasna.skills.claude-marketplace-registry.v2\x00").update(JSON.stringify(value)).digest("hex");
43232
+ const sha2562 = createHash20("sha256").update("hasna.skills.claude-marketplace-registry.v2\x00").update(JSON.stringify(value)).digest("hex");
43009
43233
  return { path, hashMode: "claude-marketplace-registry-v2", sha256: sha2562 };
43010
43234
  }
43011
43235
 
43012
43236
  // src/lib/codex-hook-discovery-recovery.ts
43013
- import { createHash as createHash21 } from "crypto";
43237
+ import { createHash as createHash22 } from "crypto";
43014
43238
 
43015
43239
  // src/lib/codex-hook-trust-files.ts
43016
- import { closeSync as closeSync16, constants as constants13, fstatSync as fstatSync16, fsyncSync as fsyncSync4, lstatSync as lstatSync19, openSync as openSync16, readSync as readSync11, writeFileSync as writeFileSync4 } from "fs";
43017
- import { createHash as createHash20 } from "crypto";
43018
- import { dirname as dirname15 } from "path";
43019
- function need6(value, code) {
43240
+ import { closeSync as closeSync16, constants as constants13, fstatSync as fstatSync16, fsyncSync as fsyncSync4, lstatSync as lstatSync19, openSync as openSync16, readlinkSync as readlinkSync5, readSync as readSync11, writeFileSync as writeFileSync4 } from "fs";
43241
+ import { createHash as createHash21 } from "crypto";
43242
+ import { dirname as dirname16, isAbsolute as isAbsolute19, resolve as resolve17 } from "path";
43243
+ function need7(value, code) {
43020
43244
  if (!value)
43021
43245
  throw new Error(`CODEX_HOOK_TRUST_${code}`);
43022
43246
  }
43023
43247
  var sameStat = (a, b) => ["dev", "ino", "uid", "nlink", "mode", "size", "mtimeNs", "ctimeNs"].every((key) => a[key] === b[key]);
43248
+ function trustedAncestorOwner(uid2) {
43249
+ return BigInt(uid2) === 0n || BigInt(uid2) === BigInt(process.getuid());
43250
+ }
43024
43251
  function safeParents(file) {
43025
- for (let p = dirname15(file);; p = dirname15(p)) {
43252
+ for (let p = dirname16(file);; p = dirname16(p)) {
43026
43253
  const s = lstatSync19(p);
43027
- need6(s.isDirectory() && !s.isSymbolicLink(), "UNSAFE_PARENT");
43028
- need6((s.mode & 18) === 0 || s.uid === 0 && (s.mode & 512) !== 0, "UNSAFE_PARENT");
43029
- if (dirname15(p) === p)
43254
+ need7(s.isDirectory() && !s.isSymbolicLink() && trustedAncestorOwner(s.uid), "UNSAFE_PARENT");
43255
+ need7((s.mode & 18) === 0 || s.uid === 0 && (s.mode & 512) !== 0, "UNSAFE_PARENT");
43256
+ if (dirname16(p) === p)
43030
43257
  break;
43031
43258
  }
43032
43259
  }
43260
+ function directAliasTarget(link) {
43261
+ const text2 = readlinkSync5(link), parts = text2.split("/");
43262
+ let first = 0;
43263
+ if (isAbsolute19(text2))
43264
+ first = 1;
43265
+ else
43266
+ while (parts[first] === "..")
43267
+ first++;
43268
+ const names = parts.slice(first);
43269
+ if (!names.length || names.some((part) => part === "" || part === "." || part === ".."))
43270
+ return;
43271
+ return resolve17(dirname16(link), text2);
43272
+ }
43033
43273
  function snapshot(file, privateFile = false, options = {}) {
43034
43274
  const readOnlyPackage = options.readOnlyPackage === true && !privateFile;
43035
43275
  safeParents(file);
43036
43276
  const initial = lstatSync19(file, { bigint: true });
43037
- need6(initial.isFile() && initial.uid === BigInt(process.getuid()) && (initial.nlink === 1n || readOnlyPackage && initial.nlink > 1n) && (initial.mode & 0o022n) === 0n && (!privateFile || (initial.mode & 0o777n) === 0o600n), "UNSAFE_FILE");
43038
- need6(initial.size <= 8n * 1024n * 1024n, "FILE_BOUND");
43277
+ need7(initial.isFile() && initial.uid === BigInt(process.getuid()) && (initial.nlink === 1n || readOnlyPackage && initial.nlink > 1n) && (initial.mode & 0o022n) === 0n && (!privateFile || (initial.mode & 0o777n) === 0o600n), "UNSAFE_FILE");
43278
+ need7(initial.size <= 8n * 1024n * 1024n, "FILE_BOUND");
43039
43279
  const fd = openSync16(file, constants13.O_RDONLY | constants13.O_NOFOLLOW | constants13.O_NONBLOCK);
43040
43280
  try {
43041
43281
  const before = fstatSync16(fd, { bigint: true });
43042
- need6(sameStat(initial, before), "INPUT_CHANGED");
43282
+ need7(sameStat(initial, before), "INPUT_CHANGED");
43043
43283
  const bytes = Buffer.alloc(Number(before.size) + 1);
43044
43284
  let length = 0;
43045
43285
  while (length < bytes.length) {
@@ -43048,16 +43288,16 @@ function snapshot(file, privateFile = false, options = {}) {
43048
43288
  break;
43049
43289
  length += n2;
43050
43290
  }
43051
- need6(length === Number(before.size) && sameStat(before, fstatSync16(fd, { bigint: true })) && sameStat(before, lstatSync19(file, { bigint: true })), "INPUT_CHANGED");
43291
+ need7(length === Number(before.size) && sameStat(before, fstatSync16(fd, { bigint: true })) && sameStat(before, lstatSync19(file, { bigint: true })), "INPUT_CHANGED");
43052
43292
  const content = bytes.subarray(0, length), text2 = new TextDecoder("utf-8", { fatal: true }).decode(content);
43053
- return { file, privateFile, readOnlyPackage, text: text2, bytes: content, stat: before, sha256: createHash20("sha256").update(content).digest("hex") };
43293
+ return { file, privateFile, readOnlyPackage, text: text2, bytes: content, stat: before, sha256: createHash21("sha256").update(content).digest("hex") };
43054
43294
  } finally {
43055
43295
  closeSync16(fd);
43056
43296
  }
43057
43297
  }
43058
43298
  function unchanged2(before) {
43059
43299
  const after = snapshot(before.file, before.privateFile, before.readOnlyPackage ? { readOnlyPackage: true } : {});
43060
- need6(sameStat(before.stat, after.stat) && after.sha256 === before.sha256, "INPUT_CHANGED");
43300
+ need7(sameStat(before.stat, after.stat) && after.sha256 === before.sha256, "INPUT_CHANGED");
43061
43301
  }
43062
43302
 
43063
43303
  // src/lib/codex-hook-additions-review.ts
@@ -43066,12 +43306,12 @@ var matchedEvents = { ...events, PreToolUse: ["preToolUse", "pre_tool_use"] };
43066
43306
  var proofs = new WeakMap;
43067
43307
 
43068
43308
  // src/lib/codex-hook-discovery-recovery.ts
43069
- var sha3 = (text2) => createHash21("sha256").update(text2).digest("hex");
43309
+ var sha3 = (text2) => createHash22("sha256").update(text2).digest("hex");
43070
43310
  var fields = [...CODEX_DISCOVERY_PROJECTION_FIELDS];
43071
43311
  var proofs2 = new WeakMap;
43072
43312
  function assertCodexHookDiscoveryRecovery(binding, witness) {
43073
43313
  const proof = proofs2.get(witness);
43074
- need6(!!proof && binding.agent === "codex" && witness.discoverySha256 === sha3(JSON.stringify(binding)), "RECONCILE_DISCOVERY_RECOVERY_CHANGED");
43314
+ need7(!!proof && binding.agent === "codex" && witness.discoverySha256 === sha3(JSON.stringify(binding)), "RECONCILE_DISCOVERY_RECOVERY_CHANGED");
43075
43315
  unchanged2(proof.before);
43076
43316
  unchanged2(proof.current);
43077
43317
  proof.recheckAdditions();
@@ -43080,34 +43320,34 @@ function verifiesCodexHookDiscoverySource(binding, source, currentDigest, witnes
43080
43320
  if (!witness || source.path !== witness.configPath || source.hashMode !== "bytes")
43081
43321
  return false;
43082
43322
  assertCodexHookDiscoveryRecovery(binding, witness);
43083
- need6(source.sha256 === witness.beforeSha256 && currentDigest === witness.currentSha256, "RECONCILE_DISCOVERY_RECOVERY_CHANGED");
43323
+ need7(source.sha256 === witness.beforeSha256 && currentDigest === witness.currentSha256, "RECONCILE_DISCOVERY_RECOVERY_CHANGED");
43084
43324
  return true;
43085
43325
  }
43086
43326
 
43087
43327
  // src/lib/agent-sumi.ts
43088
43328
  import { existsSync as existsSync6, lstatSync as lstatSync20, realpathSync as realpathSync8 } from "fs";
43089
- import { join as join25, resolve as resolve16 } from "path";
43329
+ import { join as join25, resolve as resolve18 } from "path";
43090
43330
  function sumiConfigDirectory(home, env = process.env) {
43091
43331
  for (const key of ["SUMI_CONFIG", "SUMI_CONFIG_CONTENT"])
43092
43332
  if (env[key] !== undefined)
43093
43333
  throw new Error(`Sumi ${key} requires a dedicated discovery adapter; unset it before Skills integration`);
43094
43334
  const selected = (key) => env[key]?.trim() ? env[key] : undefined;
43095
- const expand = (value) => resolve16(value === "~" ? home : value.startsWith("~/") ? join25(home, value.slice(2)) : value);
43335
+ const expand = (value) => resolve18(value === "~" ? home : value.startsWith("~/") ? join25(home, value.slice(2)) : value);
43096
43336
  const explicit = selected("SUMI_CONFIG_DIR");
43097
43337
  const xdg = selected("XDG_CONFIG_HOME");
43098
43338
  const custom = selected("SUMI_HOME");
43099
- const canonical7 = explicit ? expand(explicit) : xdg ? join25(expand(xdg), "sumi") : join25(custom ? expand(custom) : join25(home, ".hasna-internal/sumi"), "config");
43339
+ const canonical8 = explicit ? expand(explicit) : xdg ? join25(expand(xdg), "sumi") : join25(custom ? expand(custom) : join25(home, ".hasna-internal/sumi"), "config");
43100
43340
  if (explicit || xdg || custom)
43101
- return canonical7;
43341
+ return canonical8;
43102
43342
  const legacy = join25(home, ".config/sumi");
43103
- const a = lstatSync20(canonical7, { throwIfNoEntry: false }), b = lstatSync20(legacy, { throwIfNoEntry: false });
43104
- if (a && b && realpathSync8(canonical7) !== realpathSync8(legacy))
43343
+ const a = lstatSync20(canonical8, { throwIfNoEntry: false }), b = lstatSync20(legacy, { throwIfNoEntry: false });
43344
+ if (a && b && realpathSync8(canonical8) !== realpathSync8(legacy))
43105
43345
  throw new Error("Sumi config roots conflict; complete native home adoption before Skills integration");
43106
- const path = a ? canonical7 : b ? legacy : canonical7;
43346
+ const path = a ? canonical8 : b ? legacy : canonical8;
43107
43347
  if (!existsSync6(path))
43108
43348
  return path;
43109
43349
  const physical = realpathSync8(path);
43110
- if ((a?.isSymbolicLink() || b?.isSymbolicLink()) && ![canonical7, legacy].includes(physical))
43350
+ if ((a?.isSymbolicLink() || b?.isSymbolicLink()) && ![canonical8, legacy].includes(physical))
43111
43351
  throw new Error("Sumi config alias must resolve to its canonical or legacy root");
43112
43352
  return physical;
43113
43353
  }
@@ -43207,7 +43447,38 @@ var SUMI_SKILL_PERMISSIONS = [
43207
43447
  ];
43208
43448
 
43209
43449
  // src/lib/agent-discovery.ts
43210
- var digest2 = (text2) => createHash22("sha256").update(text2).digest("hex");
43450
+ var DISCOVERY_RUNTIME_COMMANDS = Object.freeze({ gemini: "gemini" });
43451
+ var DISCOVERY_ROOT_UNRESOLVED = "DISCOVERY_ROOT_UNRESOLVED";
43452
+ function discoveryRootUnresolved(agent, command, detail) {
43453
+ return new Error(`${DISCOVERY_ROOT_UNRESOLVED}: ${agent} discovery cannot resolve its "${command}" executable: ${detail}. The reviewed discovery is unchanged; this is an environment gap, not drift.`);
43454
+ }
43455
+ function isDiscoveryRootUnresolved(error) {
43456
+ return error instanceof Error && error.message.startsWith(`${DISCOVERY_ROOT_UNRESOLVED}: `);
43457
+ }
43458
+ var quotedPath = (path) => JSON.stringify(path).replace(/[^\x20-\x7e]/g, (character) => `\\u${character.charCodeAt(0).toString(16).padStart(4, "0")}`);
43459
+ var realpathOrNull = (path) => {
43460
+ try {
43461
+ return realpathSync9(path);
43462
+ } catch {
43463
+ return null;
43464
+ }
43465
+ };
43466
+ function discoveryExecutable(agent) {
43467
+ const command = DISCOVERY_RUNTIME_COMMANDS[agent];
43468
+ const found = command ? Bun.which(command) : null;
43469
+ if (!command || !found)
43470
+ return null;
43471
+ const path = resolve19(found), target = realpathOrNull(path);
43472
+ return target === null ? null : { command, path, target };
43473
+ }
43474
+ function recordedDiscoveryExecutable(agent, recorded) {
43475
+ const command = DISCOVERY_RUNTIME_COMMANDS[agent];
43476
+ if (!command || recorded.command !== command)
43477
+ throw new Error(`Recorded ${agent} discovery executable names another command`);
43478
+ const target = realpathOrNull(recorded.path);
43479
+ return target === null ? null : { command, path: recorded.path, target };
43480
+ }
43481
+ var digest2 = (text2) => createHash23("sha256").update(text2).digest("hex");
43211
43482
  function parseConfig(text2, path, toml = false) {
43212
43483
  try {
43213
43484
  const value = toml ? Bun.TOML.parse(text2) : JSON.parse(text2);
@@ -43219,12 +43490,12 @@ function parseConfig(text2, path, toml = false) {
43219
43490
  }
43220
43491
  }
43221
43492
  function safe4(path) {
43222
- if (!isAbsolute18(path) || path.includes("\x00"))
43493
+ if (!isAbsolute20(path) || path.includes("\x00"))
43223
43494
  throw new Error("Expected an absolute native discovery path");
43224
- for (let cursor = path;; cursor = dirname16(cursor)) {
43495
+ for (let cursor = path;; cursor = dirname17(cursor)) {
43225
43496
  if (lstatSync21(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
43226
43497
  throw new Error(`Refusing symlink native discovery input: ${cursor}`);
43227
- if (dirname16(cursor) === cursor)
43498
+ if (dirname17(cursor) === cursor)
43228
43499
  break;
43229
43500
  }
43230
43501
  }
@@ -43243,7 +43514,7 @@ function projectNativeDiscoveryFields(text2, format, fields2, path) {
43243
43514
  const object6 = format === "yaml" ? parseHermesConfig(text2) : parseConfig(text2, path, format === "toml");
43244
43515
  if (!object6 || typeof object6 !== "object" || Array.isArray(object6))
43245
43516
  throw new Error("Expected native discovery configuration object");
43246
- return digest2(JSON.stringify(Object.fromEntries(fields2.map((field2) => [field2, object6[field2] ?? null]))));
43517
+ return digest2(JSON.stringify(Object.fromEntries(fields2.map((field3) => [field3, object6[field3] ?? null]))));
43247
43518
  }
43248
43519
  function isSupersededSettingsProjection(agent, configPath, source) {
43249
43520
  if (agent === "sumi")
@@ -43288,6 +43559,14 @@ function projected(source, changes, budget2 = discoveryByteBudget()) {
43288
43559
  throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
43289
43560
  return sha2562;
43290
43561
  }
43562
+ if (source.hashMode === "claude-marketplace-entry-v1") {
43563
+ if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256) || changes?.has(source.path) || !claudeMarketplaceEntrySourceValid(source))
43564
+ throw new Error("Claude marketplace entry witnesses require an exact reviewed entry without synthetic changes");
43565
+ const sha2562 = captureClaudeMarketplaceEntry(source.path, source.marketplace, source.plugin, budget2).sha256;
43566
+ if (sha2562 !== source.sha256)
43567
+ throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
43568
+ return sha2562;
43569
+ }
43291
43570
  if (source.hashMode === "claude-plugin-registry") {
43292
43571
  if (source.format !== undefined || source.fields !== undefined || !source.managedPlugins || changes?.has(source.path))
43293
43572
  throw new Error("Managed plugin registry witnesses require verified native registrations");
@@ -43325,7 +43604,7 @@ function absentCodexSkillRoots(binding) {
43325
43604
  throw new Error("Invalid disabled Codex discovery proof");
43326
43605
  if (binding.method !== "reviewed" || controls.every((control) => lstatSync21(control.pluginParent, { throwIfNoEntry: false })))
43327
43606
  return [];
43328
- const cache = dirname16(dirname16(controls[0].pluginParent)), config = join26(dirname16(dirname16(cache)), "config.toml");
43607
+ const cache = dirname17(dirname17(controls[0].pluginParent)), config = join26(dirname17(dirname17(cache)), "config.toml");
43329
43608
  const source = binding.sources.find((source2) => source2.path === config && source2.sha256 !== null && source2.format === undefined && source2.fields === undefined);
43330
43609
  if (!source || projected(source) !== source.sha256)
43331
43610
  throw new Error("Missing current disabled Codex configuration witness");
@@ -43333,7 +43612,7 @@ function absentCodexSkillRoots(binding) {
43333
43612
  return [...new Set(controls.map((control) => control.pluginParent))].filter((parent) => !codexDirectHookSelects(cache, parent) && absentDisabledCodexPluginParent(cache, parent, controls, rules));
43334
43613
  }
43335
43614
  function codexDirectHookSelects(cache, root2) {
43336
- const codex = dirname16(dirname16(cache)), config = Bun.TOML.parse(read2(join26(codex, "config.toml")) ?? "");
43615
+ const codex = dirname17(dirname17(cache)), config = Bun.TOML.parse(read2(join26(codex, "config.toml")) ?? "");
43337
43616
  const hooks = read2(join26(codex, "hooks.json"));
43338
43617
  if (hooks !== null)
43339
43618
  hashNativeJsonControls(hooks);
@@ -43346,7 +43625,7 @@ function retiredCodexRoots(binding) {
43346
43625
  const controls = binding.codexDisabledPluginSkills;
43347
43626
  if (binding.agent !== "codex" || binding.method !== "reviewed" || !Array.isArray(controls) || !controls.length || !Array.isArray(proof.roots) || proof.roots.length > AGENT_POLICY_LIMITS.discoveryRoots || new Set(proof.roots).size !== proof.roots.length || !Array.isArray(proof.directories) || proof.parents !== undefined && (!Array.isArray(proof.parents) || proof.parents.length > AGENT_POLICY_LIMITS.discoveryRoots || new Set(proof.parents).size !== proof.parents.length) || !proof.roots.length && !proof.parents?.length)
43348
43627
  throw new Error("Invalid retired Codex materialization proof");
43349
- const cache = dirname16(dirname16(controls[0].pluginParent)), config = join26(dirname16(dirname16(cache)), "config.toml");
43628
+ const cache = dirname17(dirname17(controls[0].pluginParent)), config = join26(dirname17(dirname17(cache)), "config.toml");
43350
43629
  const source = binding.sources.find((source2) => source2.path === config && source2.sha256 !== null && source2.format === undefined && source2.fields === undefined);
43351
43630
  if (!source || projected(source) !== source.sha256)
43352
43631
  throw new Error("Missing current retired Codex configuration witness");
@@ -43363,8 +43642,8 @@ function retiredCodexRoots(binding) {
43363
43642
  function captureRetiredCodexDiscovery(binding, controls, rules) {
43364
43643
  if (binding.agent !== "codex" || binding.method !== "reviewed" || !controls.length)
43365
43644
  return binding;
43366
- const cache = dirname16(dirname16(controls[0].pluginParent));
43367
- const candidates = binding.sources.filter((source) => source.path.endsWith(sep6 + ".codex-plugin/plugin.json") && source.sha256 !== null && source.format === undefined && source.fields === undefined && [undefined, "bytes"].includes(source.hashMode)).map((source) => dirname16(dirname16(source.path)));
43645
+ const cache = dirname17(dirname17(controls[0].pluginParent));
43646
+ const candidates = binding.sources.filter((source) => source.path.endsWith(sep6 + ".codex-plugin/plugin.json") && source.sha256 !== null && source.format === undefined && source.fields === undefined && [undefined, "bytes"].includes(source.hashMode)).map((source) => dirname17(dirname17(source.path)));
43368
43647
  const roots = [...new Set(candidates)].filter((root2) => !codexDirectHookSelects(cache, root2) && reviewedRetiredCodexRoot(cache, root2, controls, rules, (path) => read2(path), binding.codexRetiredMaterializations?.roots.includes(root2) ?? false)).sort();
43369
43648
  const parents3 = reviewedCodexPluginCapabilitiesUnchanged(cache, controls, (path) => read2(path), rules) ? [...new Set(controls.map((control) => control.pluginParent))].filter((parent) => !codexDirectHookSelects(cache, parent) && reviewedDisabledCodexPluginParent(cache, parent, controls, rules)).sort() : [];
43370
43649
  const { codexRetiredMaterializations: previous, ...current } = binding;
@@ -43393,7 +43672,7 @@ function absentRetiredClaudeRoots(binding) {
43393
43672
  safe4(root2);
43394
43673
  if (lstatSync21(root2, { throwIfNoEntry: false }))
43395
43674
  continue;
43396
- const claude = dirname16(dirname16(cache)), settings = join26(claude, "settings.json"), registry = join26(claude, "plugins/installed_plugins.json");
43675
+ const claude = dirname17(dirname17(cache)), settings = join26(claude, "settings.json"), registry = join26(claude, "plugins/installed_plugins.json");
43397
43676
  const full = (path) => binding.sources.find((item) => item.path === path && item.sha256 !== null && item.format === undefined && item.fields === undefined);
43398
43677
  const configSource = full(settings), registrySource = full(registry);
43399
43678
  if (!configSource || !registrySource || projected(configSource) !== configSource.sha256 || projected(registrySource) !== registrySource.sha256)
@@ -43410,7 +43689,7 @@ function absentRetiredClaudeRoots(binding) {
43410
43689
  if (!Array.isArray(rows) || rows.length !== 1 || rows[0]?.scope !== "user" || typeof rows[0]?.installPath !== "string")
43411
43690
  continue;
43412
43691
  const active = rows[0].installPath;
43413
- if (rows[0].version !== basename8(active) || resolve17(active) !== active || dirname16(active) !== dirname16(root2) || active === root2 || !lstatSync21(active, { throwIfNoEntry: false })?.isDirectory() || realpathSync9(active) !== active)
43692
+ if (rows[0].version !== basename9(active) || resolve19(active) !== active || dirname17(active) !== dirname17(root2) || active === root2 || !lstatSync21(active, { throwIfNoEntry: false })?.isDirectory() || realpathSync9(active) !== active)
43414
43693
  continue;
43415
43694
  const activeManifest = full(join26(active, ".claude-plugin/plugin.json"));
43416
43695
  if (!activeManifest || projected(activeManifest) !== activeManifest.sha256)
@@ -43461,7 +43740,7 @@ function verifyAgentDiscovery(binding, codexRecovery) {
43461
43740
  assertMarketplaceBinding(binding, source);
43462
43741
  if (source.hashMode === "claude-plugin-registry" && binding.agent !== "claude")
43463
43742
  throw new Error("Managed Claude registry witnesses cannot apply to another agent");
43464
- if (source.format !== undefined && (!["json", "toml", "yaml"].includes(source.format) || !Array.isArray(source.fields) || !source.fields.length || source.fields.length > 64 || source.fields.some((field2) => typeof field2 !== "string" || !field2)))
43743
+ if (source.format !== undefined && (!["json", "toml", "yaml"].includes(source.format) || !Array.isArray(source.fields) || !source.fields.length || source.fields.length > 64 || source.fields.some((field3) => typeof field3 !== "string" || !field3)))
43465
43744
  throw new Error("Invalid native discovery projection");
43466
43745
  if (source.sha256 !== null && !/^[a-f0-9]{64}$/.test(source.sha256))
43467
43746
  throw new Error("Invalid native discovery digest");
@@ -43491,13 +43770,13 @@ function codexInstallationRoots(binding) {
43491
43770
  return [];
43492
43771
  if (binding.agent !== "codex" || binding.method !== "reviewed" || !supportsCodexNativeCapability(proof.version, "installed-plugin-review") || !/^[a-f0-9]{64}$/.test(proof.catalogSha256) || !Array.isArray(proof.plugins) || !proof.plugins.length)
43493
43772
  throw new Error("Invalid native installation input proof");
43494
- const cache = dirname16(dirname16(proof.plugins[0].pluginParent));
43495
- const config = join26(dirname16(dirname16(cache)), "config.toml"), home = dirname16(dirname16(dirname16(cache)));
43773
+ const cache = dirname17(dirname17(proof.plugins[0].pluginParent));
43774
+ const config = join26(dirname17(dirname17(cache)), "config.toml"), home = dirname17(dirname17(dirname17(cache)));
43496
43775
  const configSource = binding.sources.find((source) => source.path === config && source.sha256 !== null && (!source.format || source.format === "toml" && source.fields?.includes("plugins")));
43497
43776
  const nativeRoots = NATIVE_SKILL_ROOTS.filter(([agent]) => agent === "codex").map(([, path]) => join26(home, path));
43498
- if (!configSource || proof.plugins.some((input) => nativeRoots.some((root2) => root2 === input.sourceRoot || root2.startsWith(input.sourceRoot + sep6) || input.sourceRoot.startsWith(root2 + sep6)) || binding.sources.some((source) => basename8(source.path) === "config.toml" && (source.path === input.sourceRoot || source.path.startsWith(input.sourceRoot + sep6)))))
43777
+ if (!configSource || proof.plugins.some((input) => nativeRoots.some((root2) => root2 === input.sourceRoot || root2.startsWith(input.sourceRoot + sep6) || input.sourceRoot.startsWith(root2 + sep6)) || binding.sources.some((source) => basename9(source.path) === "config.toml" && (source.path === input.sourceRoot || source.path.startsWith(input.sourceRoot + sep6)))))
43499
43778
  throw new Error("Native installation input overlaps configuration or loading roots");
43500
- if (proof.plugins.some((input) => dirname16(dirname16(input.pluginParent)) !== cache || !binding.sources.some((source) => source.path === join26(input.sourceRoot, ".codex-plugin/plugin.json") && source.sha256 !== null && source.format === undefined && source.fields === undefined)))
43779
+ if (proof.plugins.some((input) => dirname17(dirname17(input.pluginParent)) !== cache || !binding.sources.some((source) => source.path === join26(input.sourceRoot, ".codex-plugin/plugin.json") && source.sha256 !== null && source.format === undefined && source.fields === undefined)))
43501
43780
  throw new Error("Missing native installation input source witness");
43502
43781
  return reviewedCodexPluginSourceRoots(cache, proof.plugins, (path) => {
43503
43782
  const text2 = read2(path);
@@ -43507,16 +43786,18 @@ function codexInstallationRoots(binding) {
43507
43786
  });
43508
43787
  }
43509
43788
  function assertMarketplaceBinding(binding, source) {
43510
- if (source.hashMode === "claude-plugin-manifest-v1" && (binding.agent !== "claude" || basename8(source.path) !== "plugin.json" || !source.path.endsWith(join26(sep6, ".claude-plugin", "plugin.json"))))
43789
+ if (source.hashMode === "claude-plugin-manifest-v1" && (binding.agent !== "claude" || basename9(source.path) !== "plugin.json" || !source.path.endsWith(join26(sep6, ".claude-plugin", "plugin.json"))))
43511
43790
  throw new Error("Claude plugin manifest witnesses require Claude plugin discovery");
43512
- if (source.hashMode === "sumi-settings-v1" && (binding.agent !== "sumi" || binding.method !== "reviewed" || basename8(source.path) !== "sumi.json"))
43791
+ if (source.hashMode === "sumi-settings-v1" && (binding.agent !== "sumi" || binding.method !== "reviewed" || basename9(source.path) !== "sumi.json"))
43513
43792
  throw new Error("Sumi settings witnesses require explicit reviewed Sumi configuration");
43514
- if ((source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")) && (binding.agent !== "codex" || binding.method !== "reviewed" || basename8(source.path) !== "config.toml"))
43793
+ if ((source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")) && (binding.agent !== "codex" || binding.method !== "reviewed" || basename9(source.path) !== "config.toml"))
43515
43794
  throw new Error("Codex settings witnesses require explicit reviewed Codex configuration");
43516
- if ((source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4")) && (binding.agent !== "claude" || binding.method !== "reviewed" || basename8(source.path) !== "settings.json"))
43795
+ if ((source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4")) && (binding.agent !== "claude" || binding.method !== "reviewed" || basename9(source.path) !== "settings.json"))
43517
43796
  throw new Error("Claude settings witnesses require explicit reviewed Claude configuration");
43518
43797
  if ((source.hashMode === "claude-marketplace-registry" || source.hashMode === "claude-marketplace-registry-v2") && (binding.agent !== "claude" || binding.method !== "reviewed"))
43519
43798
  throw new Error("Claude marketplace witnesses require explicit reviewed Claude discovery");
43799
+ if (source.hashMode === "claude-marketplace-entry-v1" && (binding.agent !== "claude" || binding.method !== "reviewed" || !claudeMarketplaceEntrySourceValid(source)))
43800
+ throw new Error("Claude marketplace entry witnesses require explicit reviewed Claude discovery of one named entry");
43520
43801
  }
43521
43802
  function rebindAgentDiscovery(binding, changes) {
43522
43803
  const budget2 = discoveryByteBudget();
@@ -43549,10 +43830,10 @@ function captureDiscoveryPathSources(paths) {
43549
43830
  const budget2 = discoveryByteBudget();
43550
43831
  return paths.map((path) => ({ path, hashMode: "path-bytes", sha256: hashDiscoveryPathFile(path, budget2) }));
43551
43832
  }
43552
- function assertProjectDiscovery(agent, directories, home, canonical7 = resolve17, reviewed) {
43553
- const homeConfigPath = canonical7(agentDiscoveryConfigPath(home, agent));
43833
+ function assertProjectDiscovery(agent, directories, home, canonical8 = resolve19, reviewed) {
43834
+ const homeConfigPath = canonical8(agentDiscoveryConfigPath(home, agent));
43554
43835
  for (const directory of directories) {
43555
- const isHome = resolve17(directory) === resolve17(home);
43836
+ const isHome = resolve19(directory) === resolve19(home);
43556
43837
  if (agent === "hermes") {
43557
43838
  assertHermesEnvironment(home);
43558
43839
  continue;
@@ -43561,7 +43842,7 @@ function assertProjectDiscovery(agent, directories, home, canonical7 = resolve17
43561
43842
  continue;
43562
43843
  const paths = agent === "claude" ? [...isHome ? [] : [".claude/settings.json"], ".claude/settings.local.json"] : agent === "codex" ? [".codex/config.toml"] : agent === "gemini" ? [".gemini/settings.json"] : agent === "opencode" ? ["opencode.json", "opencode.jsonc", ".opencode/opencode.json", ".opencode/opencode.jsonc"] : agent === "sumi" ? ["sumi.json", "sumi.jsonc", ".sumi/sumi.json", ".sumi/sumi.jsonc"] : [".cursor/hooks.json"];
43563
43844
  for (const suffix of paths) {
43564
- const path = canonical7(join26(directory, suffix)), raw = read2(path);
43845
+ const path = canonical8(join26(directory, suffix)), raw = read2(path);
43565
43846
  if (raw === null)
43566
43847
  continue;
43567
43848
  const isRootAliasedHomeConfig = agent === "claude" && suffix === ".claude/settings.json" || agent === "codex" && suffix === ".codex/config.toml";
@@ -43577,7 +43858,7 @@ function assertProjectDiscovery(agent, directories, home, canonical7 = resolve17
43577
43858
  const managed = reviewed.sources.flatMap((source) => source.hashMode === "claude-plugin-registry" ? source.managedPlugins ?? [] : []);
43578
43859
  if (exact && projected(exact) === exact.sha256 && managed.length) {
43579
43860
  const bindings = managed.map((item) => readPluginBinding(item.storeRoot, item.bindingId));
43580
- admittedPlugins = Object.entries(config.enabledPlugins).every(([id2, enabled]) => typeof enabled === "boolean" && bindings.some((binding) => binding.target.pluginId === id2 && binding.target.registrations.some((scope) => scope.scope === "project" && scope.projectPath === canonical7(directory))));
43861
+ admittedPlugins = Object.entries(config.enabledPlugins).every(([id2, enabled]) => typeof enabled === "boolean" && bindings.some((binding) => binding.target.pluginId === id2 && binding.target.registrations.some((scope) => scope.scope === "project" && scope.projectPath === canonical8(directory))));
43581
43862
  }
43582
43863
  }
43583
43864
  if (keys2.some((key) => config[key] !== undefined && !(key === "enabledPlugins" && admittedPlugins)) || config.disableAllHooks === true || config.disableBundledSkills === false || config.hooksConfig?.enabled === false || config.permission?.skill !== undefined || config.permissions?.deny?.some((rule) => typeof rule === "string" && /^Skill(?:\(|$)/.test(rule)))
@@ -43585,13 +43866,13 @@ function assertProjectDiscovery(agent, directories, home, canonical7 = resolve17
43585
43866
  }
43586
43867
  if (agent === "sumi")
43587
43868
  for (const name of ["plugin", "plugins"]) {
43588
- const path = canonical7(join26(directory, ".sumi", name));
43869
+ const path = canonical8(join26(directory, ".sumi", name));
43589
43870
  safe4(path);
43590
43871
  if (lstatSync21(path, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(path).length)
43591
43872
  throw new Error(`NATIVE_SKILL_DRIFT: project Sumi plugins require a dedicated discovery review: ${path}`);
43592
43873
  }
43593
43874
  if (agent === "claude") {
43594
- const commands = canonical7(join26(directory, ".claude/commands"));
43875
+ const commands = canonical8(join26(directory, ".claude/commands"));
43595
43876
  safe4(commands);
43596
43877
  if (lstatSync21(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length)
43597
43878
  throw new Error("NATIVE_SKILL_DRIFT: legacy project command discovery requires a dedicated format adapter");
@@ -43603,11 +43884,37 @@ function agentDiscoveryConfigPath(home, agent) {
43603
43884
  return sumiConfigPath(home);
43604
43885
  return join26(home, agent === "hermes" ? ".hermes/config.yaml" : agent === "opencode" ? ".config/opencode/opencode.json" : `.${agent}/${agent === "codex" ? "config.toml" : agent === "cursor" ? "hooks.json" : "settings.json"}`);
43605
43886
  }
43887
+ function verifyAutomaticDiscoveryClosure(binding, options) {
43888
+ const command = DISCOVERY_RUNTIME_COMMANDS[binding.agent], recorded = options.executable;
43889
+ const onPath = discoveryExecutable(binding.agent);
43890
+ let runtime, gap;
43891
+ if (recorded) {
43892
+ runtime = recordedDiscoveryExecutable(binding.agent, recorded);
43893
+ if (runtime && runtime.target !== recorded.target)
43894
+ throw new Error(`${options.change}: the recorded ${binding.agent} executable now resolves to ${quotedPath(runtime.target)}, not the reviewed ${quotedPath(recorded.target)}`);
43895
+ if (onPath && onPath.target !== recorded.target)
43896
+ throw new Error(`${options.change}: the "${command}" on this process's PATH resolves to ${quotedPath(onPath.target)}, not the reviewed ${quotedPath(recorded.target)}`);
43897
+ if (!runtime)
43898
+ gap = `the recorded executable ${quotedPath(recorded.path)} no longer resolves. Restore it, or review the change with skills hook install`;
43899
+ } else {
43900
+ runtime = onPath;
43901
+ if (!runtime)
43902
+ gap = "it is not on this process's PATH, and the reviewed policy has no recorded executable path. Run with the PATH used for the review, or run skills hook install there to record it";
43903
+ }
43904
+ const current = resolveAgentDiscovery({ home: options.home, agent: binding.agent, canonical: options.canonical, executable: runtime });
43905
+ if (JSON.stringify(current) === JSON.stringify(binding))
43906
+ return;
43907
+ const reviewedWithRuntime = (binding.builtinNames?.length ?? 0) > 0 || binding.sources.some((source) => basename9(source.path) === "package.json");
43908
+ const otherwiseCurrent = current.method === binding.method && JSON.stringify(current.roots) === JSON.stringify(binding.roots) && JSON.stringify(current.directories) === JSON.stringify(binding.directories) && current.sources.every((source) => binding.sources.some((saved) => isDeepStrictEqual6(saved, source)));
43909
+ if (command && gap && runtime === null && reviewedWithRuntime && otherwiseCurrent)
43910
+ throw discoveryRootUnresolved(binding.agent, command, gap);
43911
+ throw new Error(options.change);
43912
+ }
43606
43913
  function resolveAgentDiscovery(options) {
43607
- const canonical7 = options.canonical ?? resolve17, home = resolve17(options.home), agent = options.agent;
43914
+ const canonical8 = options.canonical ?? resolve19, home = resolve19(options.home), agent = options.agent;
43608
43915
  const sources = [], roots = new Set, builtinNames = [];
43609
43916
  const witness = (path, format, fields2, hashMode) => {
43610
- const source = { path: canonical7(path), sha256: null, ...format ? { format, fields: fields2 } : {}, ...hashMode ? { hashMode } : {} };
43917
+ const source = { path: canonical8(path), sha256: null, ...format ? { format, fields: fields2 } : {}, ...hashMode ? { hashMode } : {} };
43611
43918
  source.sha256 = projected(source);
43612
43919
  sources.push(source);
43613
43920
  return read2(source.path);
@@ -43629,13 +43936,13 @@ function resolveAgentDiscovery(options) {
43629
43936
  unresolved("JSONC configuration requires a supported format adapter");
43630
43937
  for (const root2 of [directory, join26(home, ".claude"), join26(home, ".agents")])
43631
43938
  for (const name of ["skill", "skills"])
43632
- roots.add(canonical7(join26(root2, name)));
43939
+ roots.add(canonical8(join26(root2, name)));
43633
43940
  if (config.skills !== undefined && (!Array.isArray(config.skills) || config.skills.some((path) => typeof path !== "string")))
43634
43941
  unresolved("skills must be a string array");
43635
43942
  for (const value of config.skills ?? []) {
43636
- if (typeof value !== "string" || /[\0$]/.test(value) || !value || !(isAbsolute18(value) || value.startsWith("~/")))
43943
+ if (typeof value !== "string" || /[\0$]/.test(value) || !value || !(isAbsolute20(value) || value.startsWith("~/")))
43637
43944
  unresolved("remote or relative skill sources need a dedicated discovery adapter");
43638
- roots.add(canonical7(value.startsWith("~/") ? join26(home, value.slice(2)) : value));
43945
+ roots.add(canonical8(value.startsWith("~/") ? join26(home, value.slice(2)) : value));
43639
43946
  }
43640
43947
  for (const key of ["plugin", "plugins"])
43641
43948
  if (config[key] !== undefined && !Array.isArray(config[key]))
@@ -43674,23 +43981,23 @@ function resolveAgentDiscovery(options) {
43674
43981
  continue;
43675
43982
  if (normalized.startsWith("~") && normalized !== "~" && !normalized.startsWith("~/"))
43676
43983
  unresolved("user-specific tilde expansion requires a separate discovery adapter");
43677
- const path = normalized === "~" ? home : normalized.startsWith("~/") ? join26(home, normalized.slice(2)) : resolve17(home, ".hermes", normalized);
43984
+ const path = normalized === "~" ? home : normalized.startsWith("~/") ? join26(home, normalized.slice(2)) : resolve19(home, ".hermes", normalized);
43678
43985
  safe4(path);
43679
43986
  roots.add(path);
43680
43987
  }
43681
43988
  }
43682
43989
  if (agent === "gemini") {
43683
- const executable2 = Bun.which("gemini");
43990
+ const executable2 = options.executable === undefined ? discoveryExecutable(agent) : options.executable;
43684
43991
  if (executable2) {
43685
43992
  let packageRoot;
43686
- for (let directory = dirname16(realpathSync9(executable2)), depth = 0;depth < 8; directory = dirname16(directory), depth++) {
43993
+ for (let directory = dirname17(executable2.target), depth = 0;depth < 8; directory = dirname17(directory), depth++) {
43687
43994
  const path = join26(directory, "package.json"), raw = read2(path);
43688
43995
  if (raw !== null && parseConfig(raw, path).name === "@google/gemini-cli") {
43689
43996
  packageRoot = directory;
43690
43997
  witness(path);
43691
43998
  break;
43692
43999
  }
43693
- if (dirname16(directory) === directory)
44000
+ if (dirname17(directory) === directory)
43694
44001
  break;
43695
44002
  }
43696
44003
  if (!packageRoot)
@@ -43713,11 +44020,11 @@ function resolveAgentDiscovery(options) {
43713
44020
  if (retained.agent !== agent || retained.method !== "reviewed")
43714
44021
  unresolved("invalid retained review");
43715
44022
  verifyAgentDiscovery(retained);
43716
- if (!retained.sources.some((source) => source.path === canonical7(configPath) && source.format === undefined && source.fields === undefined))
44023
+ if (!retained.sources.some((source) => source.path === canonical8(configPath) && source.format === undefined && source.fields === undefined))
43717
44024
  unresolved("retained review is missing the full agent configuration source");
43718
- if (retained.sources.some((source) => (source.hashMode === "sumi-settings-v1" || source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4" || (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")))) && source.path !== canonical7(configPath)))
44025
+ if (retained.sources.some((source) => (source.hashMode === "sumi-settings-v1" || source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4" || (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")))) && source.path !== canonical8(configPath)))
43719
44026
  unresolved("retained settings witness names another configuration source");
43720
- const covered = supersedesSettingsProjection(agent, retained.sources, canonical7(configPath)) ? sources.filter((source) => !isSupersededSettingsProjection(agent, canonical7(configPath), source)) : sources;
44027
+ const covered = supersedesSettingsProjection(agent, retained.sources, canonical8(configPath)) ? sources.filter((source) => !isSupersededSettingsProjection(agent, canonical8(configPath), source)) : sources;
43721
44028
  if (covered.some((source) => !retained.sources.some((saved) => isDeepStrictEqual6(saved, source))) || [...roots].some((root2) => !retained.roots.includes(root2)) || agent === "gemini" && JSON.stringify(retained.builtinNames) !== JSON.stringify(builtinNames))
43722
44029
  unresolved("retained review is missing current runtime discovery coverage");
43723
44030
  return retained;
@@ -43729,15 +44036,15 @@ function resolveAgentDiscovery(options) {
43729
44036
  if (review.sources.some((source) => source.format !== undefined || source.fields !== undefined))
43730
44037
  throw new Error("Explicit discovery reviews require full source-file hashes");
43731
44038
  verifyAgentDiscovery(supplied);
43732
- if (review.sources.some((source) => (source.hashMode === "sumi-settings-v1" || source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4" || (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")))) && source.path !== canonical7(configPath)))
44039
+ if (review.sources.some((source) => (source.hashMode === "sumi-settings-v1" || source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4" || (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")))) && source.path !== canonical8(configPath)))
43733
44040
  throw new Error("Semantic settings witnesses must name the configured agent configuration source");
43734
- if (!review.sources.some((source) => source.path === canonical7(configPath)))
44041
+ if (!review.sources.some((source) => source.path === canonical8(configPath)))
43735
44042
  throw new Error("Discovery review must include the agent configuration source");
43736
- const reviewedSources = supersedesSettingsProjection(agent, review.sources, canonical7(configPath)) ? sources.filter((source) => !isSupersededSettingsProjection(agent, canonical7(configPath), source)) : sources;
44043
+ const reviewedSources = supersedesSettingsProjection(agent, review.sources, canonical8(configPath)) ? sources.filter((source) => !isSupersededSettingsProjection(agent, canonical8(configPath), source)) : sources;
43737
44044
  const reviewedSourcesWithManifestProjection = review.sources.map((source) => {
43738
- if (agent !== "claude" || source.sha256 === null || source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || source.hashMode !== undefined && source.hashMode !== "bytes" || basename8(source.path) !== "plugin.json" || !source.path.endsWith(join26(sep6, ".claude-plugin", "plugin.json")))
44045
+ if (agent !== "claude" || source.sha256 === null || source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || source.hashMode !== undefined && source.hashMode !== "bytes" || basename9(source.path) !== "plugin.json" || !source.path.endsWith(join26(sep6, ".claude-plugin", "plugin.json")))
43739
44046
  return source;
43740
- const pluginRoot = dirname16(dirname16(source.path)), hooksPath = join26(pluginRoot, "hooks/hooks.json");
44047
+ const pluginRoot = dirname17(dirname17(source.path)), hooksPath = join26(pluginRoot, "hooks/hooks.json");
43741
44048
  const hookStat = lstatSync21(hooksPath, { throwIfNoEntry: false });
43742
44049
  const text2 = read2(source.path);
43743
44050
  if (text2 === null)
@@ -43752,13 +44059,13 @@ function resolveAgentDiscovery(options) {
43752
44059
  if (manifest.hooks !== undefined) {
43753
44060
  if (typeof manifest.hooks !== "string")
43754
44061
  throw new Error("Reviewed Claude plugin manifest has an unsupported hooks target");
43755
- const declaredHookPath = resolve17(pluginRoot, manifest.hooks);
44062
+ const declaredHookPath = resolve19(pluginRoot, manifest.hooks);
43756
44063
  if (!declaredHookPath.startsWith(pluginRoot + sep6))
43757
44064
  throw new Error("Reviewed Claude plugin hooks target escapes its root");
43758
44065
  reviewedHookPaths.add(declaredHookPath);
43759
44066
  }
43760
44067
  for (const hooksFile of reviewedHookPaths)
43761
- if (!review.sources.some((hook) => hook.path === canonical7(hooksFile) && hook.sha256 !== null && hook.format === undefined && hook.fields === undefined && hook.managedPlugins === undefined && (hook.hashMode === undefined || hook.hashMode === "bytes")))
44068
+ if (!review.sources.some((hook) => hook.path === canonical8(hooksFile) && hook.sha256 !== null && hook.format === undefined && hook.fields === undefined && hook.managedPlugins === undefined && (hook.hashMode === undefined || hook.hashMode === "bytes")))
43762
44069
  throw new Error("Reviewed Claude plugin manifest requires separately reviewed exact hook file sources");
43763
44070
  return { path: source.path, sha256: manifestSha256, hashMode: "claude-plugin-manifest-v1" };
43764
44071
  });
@@ -43767,7 +44074,7 @@ function resolveAgentDiscovery(options) {
43767
44074
  return { ...supplied, roots: [...new Set([...roots, ...supplied.roots])].sort(), sources: unique, ...agent === "gemini" ? { builtinNames } : {} };
43768
44075
  }
43769
44076
  function plugin(root2) {
43770
- root2 = canonical7(root2);
44077
+ root2 = canonical8(root2);
43771
44078
  safe4(root2);
43772
44079
  const manifestPath = join26(root2, agent === "claude" ? ".claude-plugin/plugin.json" : ".codex-plugin/plugin.json");
43773
44080
  const raw = witness(manifestPath, undefined, undefined, agent === "claude" ? "claude-plugin-manifest-v1" : undefined);
@@ -43790,16 +44097,16 @@ function resolveAgentDiscovery(options) {
43790
44097
  if (agent === "claude")
43791
44098
  roots.add(join26(root2, "skills"));
43792
44099
  for (const value of declared) {
43793
- const path = resolve17(root2, value);
44100
+ const path = resolve19(root2, value);
43794
44101
  if (path !== root2 && !path.startsWith(root2 + sep6))
43795
44102
  unresolved("plugin skill path escapes its root");
43796
- roots.add(path.endsWith(`${sep6}SKILL.md`) ? dirname16(path) : path);
44103
+ roots.add(path.endsWith(`${sep6}SKILL.md`) ? dirname17(path) : path);
43797
44104
  }
43798
44105
  }
43799
44106
  if (agent === "claude") {
43800
44107
  const registrations = witness(join26(home, ".claude/plugins/installed_plugins.json"));
43801
44108
  const installed = registrations === null ? {} : parseConfig(registrations, join26(home, ".claude/plugins/installed_plugins.json")).plugins;
43802
- const commands = canonical7(join26(home, ".claude/commands"));
44109
+ const commands = canonical8(join26(home, ".claude/commands"));
43803
44110
  safe4(commands);
43804
44111
  if (lstatSync21(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length)
43805
44112
  unresolved("legacy home command discovery requires a dedicated format adapter");
@@ -43821,7 +44128,7 @@ function resolveAgentDiscovery(options) {
43821
44128
  unresolved("unsupported plugin enablement");
43822
44129
  const split = id2.lastIndexOf("@"), name = id2.slice(0, split), marketplace = id2.slice(split + 1);
43823
44130
  const market = config.marketplaces?.[marketplace] ?? (marketplace === "personal" ? { source_type: "local", source: home } : undefined);
43824
- if (split < 1 || market?.source_type !== "local" || typeof market.source !== "string" || !isAbsolute18(market.source))
44131
+ if (split < 1 || market?.source_type !== "local" || typeof market.source !== "string" || !isAbsolute20(market.source))
43825
44132
  unresolved("enabled plugin marketplace is not an explicit local source");
43826
44133
  const catalogText = witness(join26(market.source, ".agents/plugins/marketplace.json"));
43827
44134
  if (catalogText === null)
@@ -43829,7 +44136,7 @@ function resolveAgentDiscovery(options) {
43829
44136
  const catalog = parseConfig(catalogText, join26(market.source, ".agents/plugins/marketplace.json")), matches = Array.isArray(catalog.plugins) ? catalog.plugins.filter((item) => item.name === name) : [];
43830
44137
  if (matches.length !== 1 || matches[0]?.source?.source !== "local" || typeof matches[0]?.source?.path !== "string")
43831
44138
  unresolved("plugin catalog source is missing or ambiguous");
43832
- plugin(resolve17(market.source, matches[0].source.path));
44139
+ plugin(resolve19(market.source, matches[0].source.path));
43833
44140
  }
43834
44141
  } else if (agent === "opencode") {
43835
44142
  if (witness(join26(home, ".config/opencode/opencode.jsonc")) !== null || witness(join26(home, ".config/opencode/config.json")) !== null)
@@ -43837,7 +44144,7 @@ function resolveAgentDiscovery(options) {
43837
44144
  if ((config.plugin?.length ?? 0) > 0 || config.skills?.urls?.length)
43838
44145
  unresolved("external plugin or remote skill source");
43839
44146
  for (const path of config.skills?.paths ?? []) {
43840
- if (typeof path !== "string" || !isAbsolute18(path))
44147
+ if (typeof path !== "string" || !isAbsolute20(path))
43841
44148
  unresolved("relative or malformed added skill root");
43842
44149
  roots.add(path);
43843
44150
  }
@@ -43846,7 +44153,7 @@ function resolveAgentDiscovery(options) {
43846
44153
  if (lstatSync21(localPlugins, { throwIfNoEntry: false }) && readdirSync7(localPlugins).some((name) => name !== "skills-cli.js"))
43847
44154
  unresolved("additional local plugin hooks require review");
43848
44155
  } else if (agent === "sumi") {
43849
- if ((config.plugin?.length ?? 0) > 0 || (config.plugins?.length ?? 0) > 0 || sources.some((source) => source.path !== canonical7(configPath) && source.path !== canonical7(join26(sumiConfigDirectory(home), "sumi.jsonc")) && source.sha256 !== null))
44156
+ if ((config.plugin?.length ?? 0) > 0 || (config.plugins?.length ?? 0) > 0 || sources.some((source) => source.path !== canonical8(configPath) && source.path !== canonical8(join26(sumiConfigDirectory(home), "sumi.jsonc")) && source.sha256 !== null))
43850
44157
  unresolved("external or foreign local plugins require review");
43851
44158
  } else if (agent === "hermes") {
43852
44159
  for (const directory of [join26(home, ".hermes/plugins"), join26(home, ".hermes/hermes-agent")]) {
@@ -43876,7 +44183,7 @@ function resolveAgentDiscovery(options) {
43876
44183
  roots.add(join26(root2, "skills"));
43877
44184
  }
43878
44185
  }
43879
- return { agent, roots: [...roots].sort(), sources, method: "automatic", ...agent === "gemini" ? { builtinNames } : {}, ...agent === "hermes" ? { directories: captureDiscoveryDirectories([join26(home, ".hermes/plugins"), join26(home, ".hermes/hermes-agent")].map((path) => canonical7(path))) } : {} };
44186
+ return { agent, roots: [...roots].sort(), sources, method: "automatic", ...agent === "gemini" ? { builtinNames } : {}, ...agent === "hermes" ? { directories: captureDiscoveryDirectories([join26(home, ".hermes/plugins"), join26(home, ".hermes/hermes-agent")].map((path) => canonical8(path))) } : {} };
43880
44187
  }
43881
44188
 
43882
44189
  // src/lib/agent-adapters.ts
@@ -43952,29 +44259,29 @@ var CODEX_SKILL_CONFIG_SECTIONS = /^\[\[skills\.config\]\][^\n]*(?:\n(?!\s*\[)[^
43952
44259
  var codexPathConfigRefusal = () => new Error("Codex skill path controls require ordinary [[skills.config]] TOML tables or a native single-line inline array; preserve and review unsupported inline, dotted, or malformed definitions before running skills hook install");
43953
44260
  function splitTopLevel(value, delimiter2) {
43954
44261
  const result = [];
43955
- let start = 0, square = 0, curly = 0, quote2 = null, escaped = false;
44262
+ let start = 0, square = 0, curly = 0, quote3 = null, escaped = false;
43956
44263
  for (let index = 0;index < value.length; index++) {
43957
44264
  const char = value[index];
43958
- if (quote2 === "double") {
44265
+ if (quote3 === "double") {
43959
44266
  if (escaped)
43960
44267
  escaped = false;
43961
44268
  else if (char === "\\")
43962
44269
  escaped = true;
43963
44270
  else if (char === '"')
43964
- quote2 = null;
44271
+ quote3 = null;
43965
44272
  continue;
43966
44273
  }
43967
- if (quote2 === "literal") {
44274
+ if (quote3 === "literal") {
43968
44275
  if (char === "'")
43969
- quote2 = null;
44276
+ quote3 = null;
43970
44277
  continue;
43971
44278
  }
43972
44279
  if (char === '"') {
43973
- quote2 = "double";
44280
+ quote3 = "double";
43974
44281
  continue;
43975
44282
  }
43976
44283
  if (char === "'") {
43977
- quote2 = "literal";
44284
+ quote3 = "literal";
43978
44285
  continue;
43979
44286
  }
43980
44287
  if (char === "[")
@@ -43992,7 +44299,7 @@ function splitTopLevel(value, delimiter2) {
43992
44299
  start = index + 1;
43993
44300
  }
43994
44301
  }
43995
- if (quote2 !== null || square !== 0 || curly !== 0)
44302
+ if (quote3 !== null || square !== 0 || curly !== 0)
43996
44303
  return null;
43997
44304
  result.push(value.slice(start));
43998
44305
  return result;
@@ -44000,29 +44307,29 @@ function splitTopLevel(value, delimiter2) {
44000
44307
  function inlineArrayEnd(value) {
44001
44308
  if (!value.startsWith("["))
44002
44309
  return null;
44003
- let square = 0, curly = 0, quote2 = null, escaped = false;
44310
+ let square = 0, curly = 0, quote3 = null, escaped = false;
44004
44311
  for (let index = 0;index < value.length; index++) {
44005
44312
  const char = value[index];
44006
- if (quote2 === "double") {
44313
+ if (quote3 === "double") {
44007
44314
  if (escaped)
44008
44315
  escaped = false;
44009
44316
  else if (char === "\\")
44010
44317
  escaped = true;
44011
44318
  else if (char === '"')
44012
- quote2 = null;
44319
+ quote3 = null;
44013
44320
  continue;
44014
44321
  }
44015
- if (quote2 === "literal") {
44322
+ if (quote3 === "literal") {
44016
44323
  if (char === "'")
44017
- quote2 = null;
44324
+ quote3 = null;
44018
44325
  continue;
44019
44326
  }
44020
44327
  if (char === '"') {
44021
- quote2 = "double";
44328
+ quote3 = "double";
44022
44329
  continue;
44023
44330
  }
44024
44331
  if (char === "'") {
44025
- quote2 = "literal";
44332
+ quote3 = "literal";
44026
44333
  continue;
44027
44334
  }
44028
44335
  if (char === "[")
@@ -44059,7 +44366,7 @@ function inlineRowsAsTables(value, newline) {
44059
44366
  const fields2 = splitTopLevel(row.slice(1, -1), ",");
44060
44367
  if (!fields2)
44061
44368
  return null;
44062
- const lines = fields2.map((field2) => field2.trim()).filter(Boolean);
44369
+ const lines = fields2.map((field3) => field3.trim()).filter(Boolean);
44063
44370
  if (lines.some((line) => !/^(?:path|name|enabled)\s*=/.test(line)))
44064
44371
  return null;
44065
44372
  const keys2 = lines.map((line) => line.slice(0, line.indexOf("=")).trim());
@@ -44084,27 +44391,27 @@ function normalizeCodexInlinePathConfig(text2) {
44084
44391
  const matches = [];
44085
44392
  for (const assignment of text2.matchAll(/^([ \t]*config[ \t]*=[ \t]*)(.*?)(\r?)$/gm)) {
44086
44393
  const rawValue = assignment[2].trimEnd();
44087
- let quote2 = null, escaped = false, comment = "";
44394
+ let quote3 = null, escaped = false, comment = "";
44088
44395
  for (let index = 0;index < rawValue.length; index++) {
44089
44396
  const char = rawValue[index];
44090
- if (quote2 === "double") {
44397
+ if (quote3 === "double") {
44091
44398
  if (escaped)
44092
44399
  escaped = false;
44093
44400
  else if (char === "\\")
44094
44401
  escaped = true;
44095
44402
  else if (char === '"')
44096
- quote2 = null;
44403
+ quote3 = null;
44097
44404
  continue;
44098
44405
  }
44099
- if (quote2 === "literal") {
44406
+ if (quote3 === "literal") {
44100
44407
  if (char === "'")
44101
- quote2 = null;
44408
+ quote3 = null;
44102
44409
  continue;
44103
44410
  }
44104
44411
  if (char === '"')
44105
- quote2 = "double";
44412
+ quote3 = "double";
44106
44413
  else if (char === "'")
44107
- quote2 = "literal";
44414
+ quote3 = "literal";
44108
44415
  else if (char === "#") {
44109
44416
  comment = rawValue.slice(index);
44110
44417
  break;
@@ -44215,9 +44522,9 @@ function disableCodexBundledSkills(text2) {
44215
44522
  }
44216
44523
 
44217
44524
  // src/cli/commands/runtime-launcher.ts
44218
- import { createHash as createHash23 } from "crypto";
44219
- import { closeSync as closeSync17, constants as constants14, fchmodSync as fchmodSync2, fstatSync as fstatSync17, fsyncSync as fsyncSync5, lstatSync as lstatSync22, openSync as openSync17, readFileSync as readFileSync16, readlinkSync as readlinkSync5, realpathSync as realpathSync10, symlinkSync, writeSync as writeSync3 } from "fs";
44220
- import { isAbsolute as isAbsolute19 } from "path";
44525
+ import { createHash as createHash24 } from "crypto";
44526
+ import { closeSync as closeSync17, constants as constants14, fchmodSync as fchmodSync2, fstatSync as fstatSync17, fsyncSync as fsyncSync5, lstatSync as lstatSync22, openSync as openSync17, readFileSync as readFileSync16, readlinkSync as readlinkSync6, realpathSync as realpathSync10, symlinkSync, writeSync as writeSync3 } from "fs";
44527
+ import { isAbsolute as isAbsolute21 } from "path";
44221
44528
  var PINNED_LAUNCHER_SCHEMA = "hasna-skills-pinned-launcher-v1";
44222
44529
  var LAUNCH_CWD_VARIABLE = "HASNA_SKILLS_LAUNCH_CWD";
44223
44530
  var PINNED_LAUNCHER_BUN_FLAGS = ["--config=/dev/null", "--no-env-file", "--no-macros", "--no-install"];
@@ -44258,10 +44565,10 @@ var PINNED_LAUNCHER_ENV_PREFIXES = ["HASNA", "SKILLS", "SKILL", "MCP", "XDG", "L
44258
44565
  var ENV_PREFIX = new RegExp(`^(${PINNED_LAUNCHER_ENV_PREFIXES.join("|")})_`);
44259
44566
  var ENV_EXACT = new Set(PINNED_LAUNCHER_ENV_NAMES);
44260
44567
  function sha2562(bytes) {
44261
- return createHash23("sha256").update(bytes).digest("hex");
44568
+ return createHash24("sha256").update(bytes).digest("hex");
44262
44569
  }
44263
44570
  function assertLauncherPath(value, code) {
44264
- if (typeof value !== "string" || !isAbsolute19(value) || /['\x00-\x1f\x7f]/.test(value))
44571
+ if (typeof value !== "string" || !isAbsolute21(value) || /['\x00-\x1f\x7f]/.test(value))
44265
44572
  throw new Error(code);
44266
44573
  }
44267
44574
  function renderPinnedLauncher(binding) {
@@ -44351,7 +44658,7 @@ function assertPinnedLauncherRuntimeSafe(runtime) {
44351
44658
  }
44352
44659
 
44353
44660
  // src/lib/agent-integration.ts
44354
- var sha4 = (data) => createHash24("sha256").update(data).digest("hex");
44661
+ var sha4 = (data) => createHash25("sha256").update(data).digest("hex");
44355
44662
  var ROOTS = NATIVE_SKILL_ROOTS;
44356
44663
  function hasTrustedDarwinAcl(fd, allowDenyOnly = false) {
44357
44664
  try {
@@ -44401,9 +44708,10 @@ function isSystemRootAlias(path) {
44401
44708
  return false;
44402
44709
  const target = `/private${path}`, link = `private${path}`;
44403
44710
  const identity5 = (stat2) => `${stat2.dev}:${stat2.ino}:${stat2.ctimeNs}:${stat2.uid}:${stat2.mode}`;
44711
+ const directoryIdentity = (stat2) => `${stat2.dev}:${stat2.ino}:${stat2.uid}:${stat2.mode}`;
44404
44712
  try {
44405
44713
  const before = lstatSync23(path, { bigint: true });
44406
- if (!before.isSymbolicLink() || before.uid !== 0n || readlinkSync6(path) !== link)
44714
+ if (!before.isSymbolicLink() || before.uid !== 0n || readlinkSync7(path) !== link)
44407
44715
  return false;
44408
44716
  const directories = ["/", "/private", target].map((directory) => {
44409
44717
  const stat2 = lstatSync23(directory, { bigint: true });
@@ -44416,20 +44724,20 @@ function isSystemRootAlias(path) {
44416
44724
  throw new Error("Unprotected system temporary directory");
44417
44725
  const fd = openSync18(directory, constants15.O_RDONLY | constants15.O_DIRECTORY | constants15.O_NOFOLLOW);
44418
44726
  try {
44419
- if (identity5(fstatSync18(fd, { bigint: true })) !== identity5(stat2) || !hasTrustedDarwinAcl(fd) || identity5(fstatSync18(fd, { bigint: true })) !== identity5(stat2))
44727
+ if (directoryIdentity(fstatSync18(fd, { bigint: true })) !== directoryIdentity(stat2) || !hasTrustedDarwinAcl(fd) || directoryIdentity(fstatSync18(fd, { bigint: true })) !== directoryIdentity(stat2))
44420
44728
  throw new Error("Unverified system alias directory ACL");
44421
44729
  } finally {
44422
44730
  closeSync18(fd);
44423
44731
  }
44424
- return { directory, identity: identity5(stat2) };
44732
+ return { directory, identity: directoryIdentity(stat2) };
44425
44733
  });
44426
- return realpathSync11(path) === target && readlinkSync6(path) === link && identity5(lstatSync23(path, { bigint: true })) === identity5(before) && directories.every((item) => identity5(lstatSync23(item.directory, { bigint: true })) === item.identity);
44734
+ return realpathSync11(path) === target && readlinkSync7(path) === link && identity5(lstatSync23(path, { bigint: true })) === identity5(before) && directories.every((item) => directoryIdentity(lstatSync23(item.directory, { bigint: true })) === item.identity);
44427
44735
  } catch {
44428
44736
  return false;
44429
44737
  }
44430
44738
  }
44431
44739
  function canonicalSystemPath(path) {
44432
- const absolute = resolve18(path), root2 = `/${absolute.split(sep7)[1]}`;
44740
+ const absolute = resolve20(path), root2 = `/${absolute.split(sep7)[1]}`;
44433
44741
  if (process.platform !== "darwin" || !["/var", "/tmp", "/etc"].includes(root2) || !lstatSync23(root2, { throwIfNoEntry: false })?.isSymbolicLink())
44434
44742
  return absolute;
44435
44743
  if (!isSystemRootAlias(root2))
@@ -44437,11 +44745,11 @@ function canonicalSystemPath(path) {
44437
44745
  return `/private${absolute}`;
44438
44746
  }
44439
44747
  function assertSafePath(path) {
44440
- let cursor = resolve18(path);
44748
+ let cursor = resolve20(path);
44441
44749
  while (true) {
44442
44750
  if (lstatSync23(cursor, { throwIfNoEntry: false })?.isSymbolicLink() && !isSystemRootAlias(cursor))
44443
44751
  throw new Error(`Refusing symlink path: ${cursor}`);
44444
- const parent = dirname17(cursor);
44752
+ const parent = dirname18(cursor);
44445
44753
  if (parent === cursor)
44446
44754
  return;
44447
44755
  cursor = parent;
@@ -44453,13 +44761,13 @@ function readRootAlias(home, agent) {
44453
44761
  const stat2 = lstatSync23(alias, { throwIfNoEntry: false, bigint: true });
44454
44762
  if (!stat2?.isSymbolicLink())
44455
44763
  throw new Error(`Agent root alias changed after planning: ${alias}`);
44456
- const link = readlinkSync6(alias), targetPath = resolve18(dirname17(alias), link);
44764
+ const link = readlinkSync7(alias), targetPath = resolve20(dirname18(alias), link);
44457
44765
  assertSafePath(targetPath);
44458
44766
  const targetStat = lstatSync23(targetPath, { throwIfNoEntry: false });
44459
44767
  if (!targetStat?.isDirectory())
44460
44768
  throw new Error(`Agent root alias must target an existing directory: ${alias}`);
44461
44769
  const target = realpathSync11(targetPath), inside = relative5(realHome, target);
44462
- if (!inside || inside === ".." || inside.startsWith(`..${sep7}`) || isAbsolute20(inside))
44770
+ if (!inside || inside === ".." || inside.startsWith(`..${sep7}`) || isAbsolute22(inside))
44463
44771
  throw new Error(`Agent root alias target must be inside the real home: ${alias}`);
44464
44772
  return { agent, home: realHome, alias, target, link, aliasIdentity: `${stat2.dev}:${stat2.ino}:${stat2.ctimeNs}`, targetIdentity: `${targetStat.dev}:${targetStat.ino}` };
44465
44773
  }
@@ -44485,13 +44793,13 @@ function disabledCodexSkillPaths(config, aliases) {
44485
44793
  const rows = skills.config;
44486
44794
  if (!Array.isArray(rows))
44487
44795
  return [];
44488
- if (rows.some((entry) => !entry || typeof entry !== "object" || Array.isArray(entry) || typeof entry.enabled !== "boolean" || entry.path !== undefined === (entry.name !== undefined) || entry.path !== undefined && (typeof entry.path !== "string" || !isAbsolute20(entry.path)) || entry.name !== undefined && (typeof entry.name !== "string" || !entry.name.trim())))
44796
+ if (rows.some((entry) => !entry || typeof entry !== "object" || Array.isArray(entry) || typeof entry.enabled !== "boolean" || entry.path !== undefined === (entry.name !== undefined) || entry.path !== undefined && (typeof entry.path !== "string" || !isAbsolute22(entry.path)) || entry.name !== undefined && (typeof entry.name !== "string" || !entry.name.trim())))
44489
44797
  return [];
44490
44798
  if (rows.some((entry) => entry.name !== undefined && entry.enabled !== false))
44491
44799
  return [];
44492
44800
  const settings = new Map;
44493
44801
  for (const entry of rows) {
44494
- if (typeof entry.path !== "string" || !isAbsolute20(entry.path))
44802
+ if (typeof entry.path !== "string" || !isAbsolute22(entry.path))
44495
44803
  continue;
44496
44804
  let document2;
44497
44805
  try {
@@ -44503,7 +44811,7 @@ function disabledCodexSkillPaths(config, aliases) {
44503
44811
  continue;
44504
44812
  settings.set(document2, [...settings.get(document2) ?? [], entry.enabled === false]);
44505
44813
  }
44506
- return [...settings].filter(([, values]) => values.length === 1 && values[0] === true).map(([document2]) => dirname17(document2));
44814
+ return [...settings].filter(([, values]) => values.length === 1 && values[0] === true).map(([document2]) => dirname18(document2));
44507
44815
  }
44508
44816
  function recheckRootAliases(aliases) {
44509
44817
  for (const binding of aliases) {
@@ -44545,7 +44853,7 @@ function readNativeBytes(path, maximum = 64 * 1024 * 1024) {
44545
44853
  }
44546
44854
  }
44547
44855
  function treeHash(root2) {
44548
- const hash2 = createHash24("sha256");
44856
+ const hash2 = createHash25("sha256");
44549
44857
  let bytes = 0, files = 0;
44550
44858
  function visit2(path) {
44551
44859
  const stat2 = lstatSync23(path);
@@ -44577,20 +44885,20 @@ function selectNativeMigrationTargets(inventory, manifest) {
44577
44885
  const identities = new Set;
44578
44886
  const selected = [];
44579
44887
  for (const target of manifest.targets) {
44580
- if (!isAbsolute20(target.projectRoot) || resolve18(target.projectRoot) !== target.projectRoot)
44888
+ if (!isAbsolute22(target.projectRoot) || resolve20(target.projectRoot) !== target.projectRoot)
44581
44889
  throw new Error(`Native migration target project root must be an existing absolute directory: ${target.projectRoot}`);
44582
- const projectRoot = canonicalSystemPath(target.projectRoot), normalized = relative5(projectRoot, resolve18(projectRoot, target.path));
44890
+ const projectRoot = canonicalSystemPath(target.projectRoot), normalized = relative5(projectRoot, resolve20(projectRoot, target.path));
44583
44891
  if (!existsSync7(projectRoot) || !lstatSync23(projectRoot).isDirectory())
44584
44892
  throw new Error(`Native migration target project root must be an existing absolute directory: ${target.projectRoot}`);
44585
44893
  assertSafePath(projectRoot);
44586
- if (isAbsolute20(target.path) || target.path.includes("\\") || target.path.includes("\x00") || !normalized || normalized === ".." || normalized.startsWith(`..${sep7}`) || normalized !== target.path || !/^[0-9a-f]{64}$/.test(target.treeSha256))
44894
+ if (isAbsolute22(target.path) || target.path.includes("\\") || target.path.includes("\x00") || !normalized || normalized === ".." || normalized.startsWith(`..${sep7}`) || normalized !== target.path || !/^[0-9a-f]{64}$/.test(target.treeSha256))
44587
44895
  throw new Error(`Invalid native migration target: ${target.path}`);
44588
44896
  const identity5 = `${target.agent}\x00${canonicalSystemPath(projectRoot)}\x00${normalized}`;
44589
44897
  if (identities.has(identity5))
44590
44898
  throw new Error(`Duplicate native migration target: ${target.path}`);
44591
44899
  identities.add(identity5);
44592
- const expected = canonicalSystemPath(resolve18(target.projectRoot, target.path));
44593
- const matches = inventory.filter((entry2) => entry2.agent === target.agent && resolve18(entry2.path) === expected);
44900
+ const expected = canonicalSystemPath(resolve20(target.projectRoot, target.path));
44901
+ const matches = inventory.filter((entry2) => entry2.agent === target.agent && resolve20(entry2.path) === expected);
44594
44902
  if (matches.length !== 1)
44595
44903
  throw new Error(`Native migration target was not found exactly once: ${target.agent} ${target.projectRoot}/${target.path}`);
44596
44904
  const entry = matches[0];
@@ -44609,7 +44917,7 @@ function projectAncestorDirectories(projects) {
44609
44917
  if (depth >= 100)
44610
44918
  throw new Error("NATIVE_SKILL_DRIFT: project ancestor discovery limit exceeded");
44611
44919
  directories.add(path);
44612
- const parent = dirname17(path);
44920
+ const parent = dirname18(path);
44613
44921
  if (parent === path)
44614
44922
  break;
44615
44923
  path = parent;
@@ -44618,7 +44926,7 @@ function projectAncestorDirectories(projects) {
44618
44926
  return [...directories];
44619
44927
  }
44620
44928
  function isCodexSkillDiscoveryInput(path) {
44621
- for (let cursor = canonicalSystemPath(path);cursor !== dirname17(cursor); cursor = dirname17(cursor)) {
44929
+ for (let cursor = canonicalSystemPath(path);cursor !== dirname18(cursor); cursor = dirname18(cursor)) {
44622
44930
  if (ROOTS.some(([agent, root2]) => agent === "codex" && cursor.endsWith(join27(sep7, root2))))
44623
44931
  return true;
44624
44932
  }
@@ -44626,9 +44934,9 @@ function isCodexSkillDiscoveryInput(path) {
44626
44934
  }
44627
44935
  function inventoryNativeSkills(home = homedir3(), options = {}) {
44628
44936
  home = canonicalSystemPath(home);
44629
- if (options.reviewedCacheAlias !== undefined && (!options.includeVendor || !isAbsolute20(options.reviewedCacheAlias) || resolve18(options.reviewedCacheAlias) !== options.reviewedCacheAlias))
44937
+ if (options.reviewedCacheAlias !== undefined && (!options.includeVendor || !isAbsolute22(options.reviewedCacheAlias) || resolve20(options.reviewedCacheAlias) !== options.reviewedCacheAlias))
44630
44938
  throw new Error("A reviewed cache alias requires vendor inventory and an exact absolute path");
44631
- if (options.disabledVendorPaths?.some((path) => !isAbsolute20(path) || resolve18(path) !== path))
44939
+ if (options.disabledVendorPaths?.some((path) => !isAbsolute22(path) || resolve20(path) !== path))
44632
44940
  throw new Error("Disabled vendor paths must be exact absolute paths");
44633
44941
  const reviewedCacheAlias = options.reviewedCacheAlias === undefined ? undefined : canonicalSystemPath(options.reviewedCacheAlias);
44634
44942
  const disabledVendorPaths = new Set((options.disabledVendorPaths ?? []).map(canonicalSystemPath));
@@ -44647,7 +44955,7 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
44647
44955
  roots.push(["sumi", canonicalAgentPath(join27(project, directory, name), aliases)]);
44648
44956
  }
44649
44957
  const installationInputs = options.codexInstallationInputRoots ?? [];
44650
- if (installationInputs.some((input) => resolve18(input) !== input || realpathSync11(input) !== input || roots.some(([agent, path]) => agent === "codex" && (path === input || path.startsWith(input + sep7) || input.startsWith(path + sep7)))))
44958
+ if (installationInputs.some((input) => resolve20(input) !== input || realpathSync11(input) !== input || roots.some(([agent, path]) => agent === "codex" && (path === input || path.startsWith(input + sep7) || input.startsWith(path + sep7)))))
44651
44959
  throw new Error("Native installation input overlaps an unconditional skill-loading root");
44652
44960
  const entries = [], seen = new Set;
44653
44961
  const cacheScans = new Map, maxAliasProofEntries = 1e4;
@@ -44661,11 +44969,11 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
44661
44969
  }
44662
44970
  let reviewedCacheAliasFound = false;
44663
44971
  function verifiedSiblingCacheAlias(agent, path, parent) {
44664
- const link = readlinkSync6(path), lexicalTarget = resolve18(parent, link);
44665
- if (isAbsolute20(link) ? link !== lexicalTarget : dirname17(link) !== ".")
44972
+ const link = readlinkSync7(path), lexicalTarget = resolve20(parent, link);
44973
+ if (isAbsolute22(link) ? link !== lexicalTarget : dirname18(link) !== ".")
44666
44974
  return false;
44667
44975
  const target = canonicalSystemPath(lexicalTarget);
44668
- if (dirname17(target) !== parent)
44976
+ if (dirname18(target) !== parent)
44669
44977
  return false;
44670
44978
  if (!lstatSync23(target, { throwIfNoEntry: false })?.isDirectory())
44671
44979
  return false;
@@ -44714,17 +45022,17 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
44714
45022
  }
44715
45023
  const bridge = (!vendor || agent === "sumi") && isOwnedCliBridge(path, bridgePaths);
44716
45024
  const rootAlias = aliases.find((item) => path === item.target || path.startsWith(item.target + sep7));
44717
- entries.push({ agent, path, hash: treeHash(path), managed, vendor, ...agent === "codex" || isCodexSkillDiscoveryInput(path) ? { codexHome: process.env.CODEX_HOME ?? join27(home, ".codex") } : {}, ...agent === "codex" && path.startsWith(canonicalAgentPath(join27(home, ".codex", "skills", ".system"), aliases) + sep7) ? { system: true } : {}, ...bridge ? { bridge: true, bridgeHome: resolve18(home) } : {}, ...rootAlias ? { rootAlias } : {} });
45025
+ entries.push({ agent, path, hash: treeHash(path), managed, vendor, ...agent === "codex" || isCodexSkillDiscoveryInput(path) ? { codexHome: process.env.CODEX_HOME ?? join27(home, ".codex") } : {}, ...agent === "codex" && path.startsWith(canonicalAgentPath(join27(home, ".codex", "skills", ".system"), aliases) + sep7) ? { system: true } : {}, ...bridge ? { bridge: true, bridgeHome: resolve20(home) } : {}, ...rootAlias ? { rootAlias } : {} });
44718
45026
  return scan;
44719
45027
  }
44720
45028
  if (depth > (agent === "sumi" ? 32 : vendor ? 32 : 3))
44721
45029
  return { ...scan, complete: false };
44722
45030
  const children = [], directory = opendirSync5(path);
44723
45031
  try {
44724
- let child;
44725
- while ((child = directory.readSync()) !== null) {
44726
- admit(join27(path, child.name));
44727
- children.push(child);
45032
+ let child2;
45033
+ while ((child2 = directory.readSync()) !== null) {
45034
+ admit(join27(path, child2.name));
45035
+ children.push(child2);
44728
45036
  }
44729
45037
  } finally {
44730
45038
  directory.closeSync();
@@ -44740,15 +45048,15 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
44740
45048
  const isVendor = vendor || name === ".system";
44741
45049
  if (isVendor && !options.includeVendor)
44742
45050
  continue;
44743
- const child = join27(path, name);
44744
- if (isVendor && lstatSync23(child, { throwIfNoEntry: false })?.isSymbolicLink()) {
44745
- const target = statSync7(child, { throwIfNoEntry: false });
44746
- if (target?.isFile() || pluginCache && target?.isDirectory() && verifiedSiblingCacheAlias(agent, child, path)) {
45051
+ const child2 = join27(path, name);
45052
+ if (isVendor && lstatSync23(child2, { throwIfNoEntry: false })?.isSymbolicLink()) {
45053
+ const target = statSync7(child2, { throwIfNoEntry: false });
45054
+ if (target?.isFile() || pluginCache && target?.isDirectory() && verifiedSiblingCacheAlias(agent, child2, path)) {
44747
45055
  scan.entries++;
44748
45056
  continue;
44749
45057
  }
44750
45058
  }
44751
- const childScan = visit2(agent, child, isVendor, depth + 1, pluginCache, true, configuredRoot);
45059
+ const childScan = visit2(agent, child2, isVendor, depth + 1, pluginCache, true, configuredRoot);
44752
45060
  scan.complete &&= childScan.complete;
44753
45061
  scan.hasSkills ||= childScan.hasSkills;
44754
45062
  scan.entries += childScan.entries;
@@ -44884,7 +45192,7 @@ function configureHooks(config, agent, command, profileId, nativeReady) {
44884
45192
  function disableCodexSkills(text2, skills, aliases, bridgePath) {
44885
45193
  const bundled = disableCodexBundledSkills(text2);
44886
45194
  let result = normalizeCodexInlinePathConfig(bundled);
44887
- const bridgeSelector = (entry) => typeof entry.name === "string" && entry.name.trim() === CLI_BRIDGE_NAME || typeof entry.path === "string" && [resolve18(bridgePath), resolve18(join27(bridgePath, "SKILL.md"))].includes(canonicalAgentPath(entry.path, aliases));
45195
+ const bridgeSelector = (entry) => typeof entry.name === "string" && entry.name.trim() === CLI_BRIDGE_NAME || typeof entry.path === "string" && [resolve20(bridgePath), resolve20(join27(bridgePath, "SKILL.md"))].includes(canonicalAgentPath(entry.path, aliases));
44888
45196
  const previousConfig = Bun.TOML.parse(bundled).skills?.config;
44889
45197
  if (previousConfig !== undefined && (!Array.isArray(previousConfig) || previousConfig.some((entry) => !entry || typeof entry !== "object" || entry.path !== undefined && entry.name !== undefined)))
44890
45198
  throw new Error("Codex skill controls require one path or name selector per [[skills.config]] entry; review ambiguous entries before running skills hook install");
@@ -44896,7 +45204,7 @@ function disableCodexSkills(text2, skills, aliases, bridgePath) {
44896
45204
  result = result.replace(CODEX_SKILL_CONFIG_SECTIONS, (section) => {
44897
45205
  const parsed = Bun.TOML.parse(section);
44898
45206
  const declared = parsed.skills?.config?.[0];
44899
- if (!declared || !(skill.enabled && bridgeSelector(declared)) && !(typeof declared.path === "string" && [resolve18(path), resolve18(skill.path)].includes(canonicalAgentPath(declared.path, aliases))))
45207
+ if (!declared || !(skill.enabled && bridgeSelector(declared)) && !(typeof declared.path === "string" && [resolve20(path), resolve20(skill.path)].includes(canonicalAgentPath(declared.path, aliases))))
44900
45208
  return section;
44901
45209
  found = true;
44902
45210
  return /^\s*enabled\s*=/m.test(section) ? section.replace(/^\s*enabled\s*=.*$/m, `enabled = ${skill.enabled}`) : `${section.trimEnd()}
@@ -44917,7 +45225,7 @@ enabled = false
44917
45225
  return result;
44918
45226
  }
44919
45227
  function assertCodexInstallationInputs(home, projectDirs, inputs) {
44920
- const nativeRoots = [home, ...projectAncestorDirectories(projectDirs)].flatMap((directory) => ROOTS.filter(([agent]) => agent === "codex").map(([, path]) => resolve18(directory, path)));
45228
+ const nativeRoots = [home, ...projectAncestorDirectories(projectDirs)].flatMap((directory) => ROOTS.filter(([agent]) => agent === "codex").map(([, path]) => resolve20(directory, path)));
44921
45229
  if (inputs.some((input) => nativeRoots.some((root2) => root2 === input || root2.startsWith(input + sep7) || input.startsWith(root2 + sep7))))
44922
45230
  throw new Error("Native installation input overlaps an unconditional skill-loading root");
44923
45231
  }
@@ -44933,9 +45241,9 @@ function planAgentIntegration(options) {
44933
45241
  throw new Error("Invalid existing Skills bridge policy");
44934
45242
  if (policy.bridge?.agents !== undefined && (!Array.isArray(policy.bridge.agents) || policy.bridge.agents.some((agent) => !INTEGRATION_AGENTS.includes(agent))))
44935
45243
  throw new Error("Invalid existing bridge agent inventory");
44936
- for (const field2 of ["commands", "profiles"])
44937
- if (policy.bridge?.[field2] !== undefined && (!policy.bridge[field2] || typeof policy.bridge[field2] !== "object" || Array.isArray(policy.bridge[field2]) || Object.entries(policy.bridge[field2]).some(([key, value]) => !INTEGRATION_AGENTS.includes(key) || typeof value !== "string" || !value || value.includes("\x00"))))
44938
- throw new Error(`Invalid existing bridge ${field2} binding`);
45244
+ for (const field3 of ["commands", "profiles"])
45245
+ if (policy.bridge?.[field3] !== undefined && (!policy.bridge[field3] || typeof policy.bridge[field3] !== "object" || Array.isArray(policy.bridge[field3]) || Object.entries(policy.bridge[field3]).some(([key, value]) => !INTEGRATION_AGENTS.includes(key) || typeof value !== "string" || !value || value.includes("\x00"))))
45246
+ throw new Error(`Invalid existing bridge ${field3} binding`);
44939
45247
  const priorAgents = policy.bridge?.agents ?? [];
44940
45248
  const profileId = options.profileId ?? policy.profileId ?? "default";
44941
45249
  const validateProfile = (value) => {
@@ -44950,13 +45258,18 @@ function planAgentIntegration(options) {
44950
45258
  return [agent, { command, profileId: profileId2 }];
44951
45259
  }));
44952
45260
  const retainedAgents = [];
45261
+ const priorExecutables = policy.bridge?.discoveryExecutables ?? {};
45262
+ const executables = new Map;
44953
45263
  const discoveries = [...new Set(options.agents)].map((agent) => {
45264
+ const prior = priorExecutables[agent];
45265
+ const executable2 = discoveryExecutable(agent) ?? (prior ? recordedDiscoveryExecutable(agent, prior) : null);
45266
+ executables.set(agent, executable2);
44954
45267
  const retainedReview = options.discoveryInputs === undefined && policy.bridge?.discovery?.[agent]?.method === "reviewed" ? { ...policy.bridge.discovery[agent], ...agent === "codex" ? { codexDisabledPluginSkills: policy.bridge.codexPluginSkills ?? [] } : {} } : undefined;
44955
45268
  if (retainedReview) {
44956
45269
  assertManagedAgentBridge(agent, { home, dataDir: dataDir2, projectDir: options.projectDir ?? home });
44957
45270
  retainedAgents.push(agent);
44958
45271
  }
44959
- return resolveAgentDiscovery({ home, agent, reviewed: options.discoveryInputs, retainedReview, canonical: (path) => canonicalAgentPath(path, aliases) });
45272
+ return resolveAgentDiscovery({ home, agent, reviewed: options.discoveryInputs, retainedReview, canonical: (path) => canonicalAgentPath(path, aliases), executable: executable2 });
44960
45273
  });
44961
45274
  const codexConfigBefore = options.agents.includes("codex") ? readOptional(canonicalAgentPath(join27(home, ".codex", "config.toml"), aliases)) : null;
44962
45275
  const codexConfig = Bun.TOML.parse(codexConfigBefore ?? "");
@@ -44964,7 +45277,7 @@ function planAgentIntegration(options) {
44964
45277
  const codexPathConfig = options.agents.includes("codex") ? disableCodexSkills(codexConfigBefore ?? "", nativeSkills, aliases, canonicalAgentPath(join27(home, ".codex/skills", CLI_BRIDGE_NAME), aliases)) : undefined;
44965
45278
  const plannedCodexRules = codexPathConfig === undefined ? undefined : Bun.TOML.parse(codexPathConfig).skills?.config ?? [];
44966
45279
  const observedNativeSources = [];
44967
- const codexPluginControls = options.codexNativeCatalog ? reviewCodexPluginControls(options.codexNativeCatalog, nativeSkills.filter((entry) => entry.agent === "codex" && entry.vendor).map((entry) => join27(entry.path, "SKILL.md")), canonicalAgentPath(join27(home, ".codex/plugins/cache"), aliases), resolve18(options.projectDir ?? home), (path) => {
45280
+ const codexPluginControls = options.codexNativeCatalog ? reviewCodexPluginControls(options.codexNativeCatalog, nativeSkills.filter((entry) => entry.agent === "codex" && entry.vendor).map((entry) => join27(entry.path, "SKILL.md")), canonicalAgentPath(join27(home, ".codex/plugins/cache"), aliases), resolve20(options.projectDir ?? home), (path) => {
44968
45281
  const bytes = readNativeBytes(path, 1024 * 1024);
44969
45282
  observedNativeSources.push({ path, sha256: sha4(bytes) });
44970
45283
  return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
@@ -45093,7 +45406,7 @@ function planAgentIntegration(options) {
45093
45406
  version: CLI_BRIDGE_VERSION,
45094
45407
  digest: CLI_BRIDGE_DIGEST,
45095
45408
  agents: [...new Set([...priorAgents, ...options.agents])].sort(),
45096
- home: resolve18(home),
45409
+ home: resolve20(home),
45097
45410
  includeVendor: true,
45098
45411
  ...options.agents.includes("hermes") ? { supervisors: { ...policy.bridge?.supervisors, hermes: { path: join27(dataDir2, "agent-hooks", "hermes.js"), runtime: process.execPath, sha256: sha4(renderHermesSupervisor(bindings.get("hermes").command, bindings.get("hermes").profileId)) } } } : {},
45099
45412
  commands: { ...policy.bridge?.commands, ...Object.fromEntries([...bindings].map(([agent, binding]) => [agent, binding.command])) },
@@ -45103,19 +45416,30 @@ function planAgentIntegration(options) {
45103
45416
  ...options.codexNativeCatalog || codexPluginSkills.length || codexInactivePlugins.length || codexPluginSourceInputs.length ? { codexPluginSkills, codexInactivePlugins, codexPluginSkillReview } : {},
45104
45417
  discovery: { ...policy.bridge?.discovery, ...Object.fromEntries(discoveryAfter.map((binding) => [binding.agent, binding])) }
45105
45418
  } };
45419
+ const discoveryExecutables = { ...priorExecutables };
45420
+ for (const [agent, executable2] of executables) {
45421
+ if (executable2)
45422
+ discoveryExecutables[agent] = executable2;
45423
+ else
45424
+ delete discoveryExecutables[agent];
45425
+ }
45426
+ if (Object.keys(discoveryExecutables).length)
45427
+ nextPolicy.bridge.discoveryExecutables = discoveryExecutables;
45428
+ else
45429
+ delete nextPolicy.bridge.discoveryExecutables;
45106
45430
  const serializedPolicy = serializeManagedSkillPolicy(nextPolicy);
45107
45431
  if (JSON.stringify(policy) !== JSON.stringify(nextPolicy))
45108
45432
  changes.push({ path: policyPath, before: previousPolicy, after: serializedPolicy });
45109
45433
  recheckRootAliases(aliases);
45110
45434
  return { dataDir: dataDir2, profileId, changes, nativeSkills, ...observedSettings ? { observedSettings } : {}, ...observedNativeSources.length ? { observedNativeSources } : {}, ...nextPolicy.bridge.codexPluginSkillReview ? { codexPluginSkillReview: nextPolicy.bridge.codexPluginSkillReview } : {}, observedPolicy: { path: policyPath, before: previousPolicy }, discoveryBefore: discoveries, discoveryAfter, ...aliases.length ? { rootAliases: aliases } : {}, ...retainedAgents.length ? { retainedReviewChecks: { home, projectDir: options.projectDir ?? home, agents: retainedAgents } } : {} };
45111
45435
  }
45112
- function hookProjectionRefusal(reason) {
45113
- throw new Error(`CLAUDE_MANAGED_HOOK_${reason}`);
45436
+ function hookProjectionRefusal(reason2) {
45437
+ throw new Error(`CLAUDE_MANAGED_HOOK_${reason2}`);
45114
45438
  }
45115
45439
  function projectedHookAcl(path, observed) {
45116
45440
  if (process.platform !== "darwin")
45117
45441
  return;
45118
- const identity5 = (stat2) => `${stat2.dev}:${stat2.ino}:${stat2.ctimeNs}:${stat2.uid}:${stat2.mode}:${stat2.nlink}:${stat2.size}:${stat2.mtimeNs}`;
45442
+ const identity5 = observed.isDirectory() ? (stat2) => `${stat2.dev}:${stat2.ino}:${stat2.uid}:${stat2.mode}` : (stat2) => `${stat2.dev}:${stat2.ino}:${stat2.ctimeNs}:${stat2.uid}:${stat2.mode}:${stat2.nlink}:${stat2.size}:${stat2.mtimeNs}`;
45119
45443
  const fd = openSync18(path, constants15.O_RDONLY | constants15.O_NOFOLLOW | constants15.O_NONBLOCK | (observed.isDirectory() ? constants15.O_DIRECTORY : 0));
45120
45444
  try {
45121
45445
  if (identity5(fstatSync18(fd, { bigint: true })) !== identity5(observed) || !hasTrustedDarwinAcl(fd, true) || identity5(fstatSync18(fd, { bigint: true })) !== identity5(observed) || identity5(lstatSync23(path, { bigint: true })) !== identity5(observed))
@@ -45126,18 +45450,18 @@ function projectedHookAcl(path, observed) {
45126
45450
  }
45127
45451
  function projectedHookExecutable(command, expectedResolved) {
45128
45452
  try {
45129
- if (!isAbsolute20(command) || /[\0\r\n]/.test(command) || resolve18(command) !== command)
45453
+ if (!isAbsolute22(command) || /[\0\r\n]/.test(command) || resolve20(command) !== command)
45130
45454
  hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
45131
45455
  command = canonicalSystemPath(command);
45132
45456
  const parents3 = (file = command) => {
45133
45457
  const result = [];
45134
- for (let path = dirname17(file);; path = dirname17(path)) {
45458
+ for (let path = dirname18(file);; path = dirname18(path)) {
45135
45459
  const stat2 = lstatSync23(path, { bigint: true });
45136
- if (!stat2.isDirectory() || (stat2.mode & 0o022n) !== 0n && !(stat2.uid === 0n && (stat2.mode & 0o1000n) !== 0n))
45460
+ if (!stat2.isDirectory() || !trustedAncestorOwner(stat2.uid) || (stat2.mode & 0o022n) !== 0n && !(stat2.uid === 0n && (stat2.mode & 0o1000n) !== 0n))
45137
45461
  hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
45138
45462
  projectedHookAcl(path, stat2);
45139
45463
  result.push(`${path}:${stat2.dev}:${stat2.ino}:${stat2.uid}:${stat2.mode}`);
45140
- if (dirname17(path) === path)
45464
+ if (dirname18(path) === path)
45141
45465
  break;
45142
45466
  }
45143
45467
  return result;
@@ -45147,22 +45471,33 @@ function projectedHookExecutable(command, expectedResolved) {
45147
45471
  hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
45148
45472
  const linkIdentity = (stat2) => `${stat2.dev}:${stat2.ino}:${stat2.mode}:${stat2.uid}:${stat2.ctimeNs}`;
45149
45473
  const target = resolveLauncherCommand(command), resolved = target.entry;
45474
+ const direct = () => link.isSymbolicLink() ? directAliasTarget(command) === target.physical : target.physical === command;
45475
+ if (!direct())
45476
+ hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
45150
45477
  if (expectedResolved !== undefined && resolved !== expectedResolved)
45151
45478
  hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
45152
45479
  let launcher, launcherParentIdentity;
45480
+ let runtime;
45153
45481
  if (target.pinned) {
45154
45482
  launcherParentIdentity = parents3(target.physical);
45155
45483
  launcher = snapshot(target.physical, false);
45156
45484
  projectedHookAcl(launcher.file, launcher.stat);
45157
45485
  if (launcher.sha256 !== target.pinned.sha256 || (launcher.stat.mode & 0o100n) === 0n)
45158
45486
  hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
45159
- assertPinnedLauncherRuntimeSafe(target.pinned.runtime);
45487
+ const path = target.pinned.runtime;
45488
+ assertPinnedLauncherRuntimeSafe(path);
45489
+ if (resolve20(path) !== path)
45490
+ hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
45491
+ runtime = { path, parents: parents3(path), stat: lstatSync23(path, { bigint: true }) };
45492
+ if (!runtime.stat.isFile())
45493
+ hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
45494
+ projectedHookAcl(path, runtime.stat);
45160
45495
  }
45161
45496
  const resolvedParentIdentity = parents3(resolved);
45162
- const manifest = snapshot(join27(dirname17(dirname17(resolved)), "package.json"), false, { readOnlyPackage: true });
45497
+ const manifest = snapshot(join27(dirname18(dirname18(resolved)), "package.json"), false, { readOnlyPackage: true });
45163
45498
  projectedHookAcl(manifest.file, manifest.stat);
45164
45499
  const pkg = JSON.parse(manifest.text);
45165
- if (pkg.name !== "@hasna/skills" || !/^\d+\.\d+\.\d+$/.test(pkg.version) || pkg.bin?.skills !== "bin/index.js" || resolved !== join27(dirname17(manifest.file), "bin/index.js"))
45500
+ if (pkg.name !== "@hasna/skills" || !/^\d+\.\d+\.\d+$/.test(pkg.version) || pkg.bin?.skills !== "bin/index.js" || resolved !== join27(dirname18(manifest.file), "bin/index.js"))
45166
45501
  hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
45167
45502
  const cli = snapshot(resolved, false, { readOnlyPackage: true });
45168
45503
  projectedHookAcl(cli.file, cli.stat);
@@ -45171,7 +45506,7 @@ function projectedHookExecutable(command, expectedResolved) {
45171
45506
  const recheck = () => {
45172
45507
  try {
45173
45508
  const again = resolveLauncherCommand(command);
45174
- if (again.entry !== resolved || again.physical !== target.physical || linkIdentity(lstatSync23(command, { bigint: true })) !== linkIdentity(link) || !isDeepStrictEqual8(parents3(), parentIdentity) || !isDeepStrictEqual8(parents3(resolved), resolvedParentIdentity))
45509
+ if (again.entry !== resolved || again.physical !== target.physical || linkIdentity(lstatSync23(command, { bigint: true })) !== linkIdentity(link) || !direct() || !isDeepStrictEqual8(parents3(), parentIdentity) || !isDeepStrictEqual8(parents3(resolved), resolvedParentIdentity))
45175
45510
  hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
45176
45511
  if (launcher) {
45177
45512
  if (!isDeepStrictEqual8(parents3(target.physical), launcherParentIdentity))
@@ -45179,6 +45514,12 @@ function projectedHookExecutable(command, expectedResolved) {
45179
45514
  projectedHookAcl(launcher.file, launcher.stat);
45180
45515
  unchanged2(launcher);
45181
45516
  }
45517
+ if (runtime) {
45518
+ assertPinnedLauncherRuntimeSafe(runtime.path);
45519
+ if (!isDeepStrictEqual8(parents3(runtime.path), runtime.parents))
45520
+ hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
45521
+ projectedHookAcl(runtime.path, runtime.stat);
45522
+ }
45182
45523
  projectedHookAcl(cli.file, cli.stat);
45183
45524
  projectedHookAcl(manifest.file, manifest.stat);
45184
45525
  unchanged2(cli);
@@ -45205,7 +45546,7 @@ function planClaudeManagedHookProjection(options) {
45205
45546
  } catch {
45206
45547
  hookProjectionRefusal("TARGET_INVALID");
45207
45548
  }
45208
- const home = resolve18(options.home ?? homedir3()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
45549
+ const home = resolve20(options.home ?? homedir3()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
45209
45550
  const policyPath = join27(dataDir2, "agent-policy.json");
45210
45551
  let policyBytes, settingsBytes, settingsPath, command, profile;
45211
45552
  try {
@@ -45297,29 +45638,28 @@ function planClaudePreToolUseHookUpdate(options) {
45297
45638
  return planClaudeHookEventsUpdate({ ...options, events: ["PreToolUse"] });
45298
45639
  }
45299
45640
  function claudeSettingsConsumers(home, path, discoveries, aliases) {
45300
- const canonical7 = (value) => canonicalAgentPath(value, aliases);
45641
+ const canonical8 = (value) => canonicalAgentPath(value, aliases);
45301
45642
  const containsSettings = (root2) => {
45302
- const distance = relative5(canonical7(root2), path);
45303
- return distance === "" || distance !== ".." && !distance.startsWith(`..${sep7}`) && !isAbsolute20(distance);
45643
+ const distance = relative5(canonical8(root2), path);
45644
+ return distance === "" || distance !== ".." && !distance.startsWith(`..${sep7}`) && !isAbsolute22(distance);
45304
45645
  };
45305
- return discoveries.filter((binding) => binding.agent === "claude" || binding.agent === "opencode" || canonical7(join27(home, AGENT_ADAPTERS[binding.agent].config)) === path || binding.sources.some((source) => canonical7(source.path) === path) || binding.roots.some(containsSettings) || binding.directories?.some((directory) => containsSettings(directory.path))).map((binding) => binding.agent);
45646
+ return discoveries.filter((binding) => binding.agent === "claude" || binding.agent === "opencode" || canonical8(join27(home, AGENT_ADAPTERS[binding.agent].config)) === path || binding.sources.some((source) => canonical8(source.path) === path) || binding.roots.some(containsSettings) || binding.directories?.some((directory) => containsSettings(directory.path))).map((binding) => binding.agent);
45306
45647
  }
45307
- function verifyCoordinatedDiscovery(binding, home, aliases) {
45648
+ function verifyCoordinatedDiscovery(binding, home, aliases, executable2) {
45308
45649
  try {
45309
45650
  if (binding.method !== "automatic" && binding.method !== "reviewed")
45310
45651
  throw new Error("Invalid managed discovery method");
45311
45652
  verifyAgentDiscovery(binding);
45312
- if (binding.method === "automatic") {
45313
- const current = resolveAgentDiscovery({ home, agent: binding.agent, canonical: (path) => canonicalAgentPath(path, aliases) });
45314
- if (JSON.stringify(current) !== JSON.stringify(binding))
45315
- throw new Error("Configured native discovery roots changed during Claude update");
45316
- }
45653
+ if (binding.method === "automatic")
45654
+ verifyAutomaticDiscoveryClosure(binding, { home, canonical: (path) => canonicalAgentPath(path, aliases), change: "Configured native discovery roots changed during Claude update", executable: executable2 });
45317
45655
  } catch (error) {
45656
+ if (isDiscoveryRootUnresolved(error))
45657
+ throw error;
45318
45658
  throw new Error(`NATIVE_SKILL_DRIFT: ${error.message}`);
45319
45659
  }
45320
45660
  }
45321
45661
  function planClaudeHookEventsUpdate(options) {
45322
- const home = resolve18(options.home ?? homedir3()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
45662
+ const home = resolve20(options.home ?? homedir3()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
45323
45663
  const policyPath = join27(dataDir2, "agent-policy.json");
45324
45664
  assertSafePath(policyPath);
45325
45665
  const snapshot2 = readManagedSkillPolicySnapshot(dataDir2);
@@ -45345,8 +45685,9 @@ function planClaudeHookEventsUpdate(options) {
45345
45685
  });
45346
45686
  if (discoveries.length !== agents.length || !agents.includes("claude"))
45347
45687
  throw new Error("Missing managed Claude discovery coverage");
45688
+ const discoveryExecutables = bridge.discoveryExecutables;
45348
45689
  for (const binding of discoveries)
45349
- verifyCoordinatedDiscovery(binding, home, aliases);
45690
+ verifyCoordinatedDiscovery(binding, home, aliases, discoveryExecutables?.[binding.agent]);
45350
45691
  const consumers = claudeSettingsConsumers(home, path, discoveries, aliases);
45351
45692
  for (const agent of consumers)
45352
45693
  assertManagedAgentBridge(agent, { home, dataDir: dataDir2, projectDir: home });
@@ -45381,13 +45722,14 @@ function planClaudeHookEventsUpdate(options) {
45381
45722
  observedPolicy: { path: policyPath, before: snapshot2.text },
45382
45723
  discoveryBefore: discoveries,
45383
45724
  discoveryAfter,
45725
+ ...discoveryExecutables ? { discoveryExecutables } : {},
45384
45726
  rootAliases: aliases,
45385
45727
  managedAgentChecks: { home, agents: consumers }
45386
45728
  };
45387
45729
  }
45388
45730
  function atomicWrite2(path, content) {
45389
45731
  assertSafePath(path);
45390
- mkdirSync6(dirname17(path), { recursive: true, mode: 448 });
45732
+ mkdirSync6(dirname18(path), { recursive: true, mode: 448 });
45391
45733
  const temporary = `${path}.skills-${randomUUID4()}`;
45392
45734
  try {
45393
45735
  writeFileSync5(temporary, content, { mode: 384, flag: "wx" });
@@ -45402,7 +45744,7 @@ function planAgentSettingsWitnessUpgrade(options) {
45402
45744
  throw new Error("Invalid Codex witness target version");
45403
45745
  if (options.targetClaudeVersion !== undefined && (options.agent !== "claude" || ![3, 4].includes(options.targetClaudeVersion)))
45404
45746
  throw new Error("Invalid Claude witness target version");
45405
- const home = resolve18(options.home ?? homedir3()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
45747
+ const home = resolve20(options.home ?? homedir3()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
45406
45748
  const snapshot2 = readManagedSkillPolicySnapshot(dataDir2);
45407
45749
  if (!snapshot2 || sha4(snapshot2.text) !== options.expectedPolicySha256)
45408
45750
  throw new Error("Managed policy preimage changed");
@@ -45462,7 +45804,7 @@ function planAgentSettingsWitnessUpgrade(options) {
45462
45804
  const replacement = { ...binding, sources: rebound };
45463
45805
  verifyAgentDiscovery(replacement);
45464
45806
  const after = serializeManagedSkillPolicy({ ...policy, bridge: { ...policy.bridge, discovery: { ...policy.bridge.discovery, [options.agent]: replacement } } });
45465
- return { dataDir: dataDir2, profileId: policy.profileId, changes: [{ path: join27(dataDir2, "agent-policy.json"), before: snapshot2.text, after }], nativeSkills: [], observedPolicy: { path: join27(dataDir2, "agent-policy.json"), before: snapshot2.text }, observedSettings: { path: configPath, before: settings }, discoveryBefore: [replacement], discoveryAfter: [replacement], rootAliases: aliases, managedAgentChecks: { home, agents: [options.agent] }, settingsWitnessUpgrade: { agent: options.agent, path: configPath, fromHashMode: previous.hashMode ?? "bytes", fromSha256: previous.sha256, toHashMode: next.hashMode, toSha256: next.sha256, reviewedPreimage: options.reviewedPreimage, currentSettingsSha256: options.expectedSettingsSha256, replacedWitnesses: replaced.map((source) => ({ hashMode: source.hashMode ?? "bytes", sha256: source.sha256 })) } };
45807
+ return { dataDir: dataDir2, profileId: policy.profileId, changes: [{ path: join27(dataDir2, "agent-policy.json"), before: snapshot2.text, after }], nativeSkills: [], observedPolicy: { path: join27(dataDir2, "agent-policy.json"), before: snapshot2.text }, observedSettings: { path: configPath, before: settings }, discoveryBefore: [replacement], discoveryAfter: [replacement], ...policy.bridge.discoveryExecutables ? { discoveryExecutables: policy.bridge.discoveryExecutables } : {}, rootAliases: aliases, managedAgentChecks: { home, agents: [options.agent] }, settingsWitnessUpgrade: { agent: options.agent, path: configPath, fromHashMode: previous.hashMode ?? "bytes", fromSha256: previous.sha256, toHashMode: next.hashMode, toSha256: next.sha256, reviewedPreimage: options.reviewedPreimage, currentSettingsSha256: options.expectedSettingsSha256, replacedWitnesses: replaced.map((source) => ({ hashMode: source.hashMode ?? "bytes", sha256: source.sha256 })) } };
45466
45808
  }
45467
45809
  function applyAgentIntegration(plan, options = {}) {
45468
45810
  const roots = plan.changes.flatMap((change) => {
@@ -45480,10 +45822,10 @@ function applyAgentIntegrationUnlocked(plan, options = {}, assertCurrent) {
45480
45822
  throw new Error("Native settings changed after witness planning");
45481
45823
  const policyPath = join27(plan.dataDir, "agent-policy.json");
45482
45824
  assertSafePath(policyPath);
45483
- const currentText = (path) => resolve18(path) === resolve18(policyPath) ? readManagedSkillPolicySnapshot(plan.dataDir)?.text ?? null : readOptional(path);
45825
+ const currentText = (path) => resolve20(path) === resolve20(policyPath) ? readManagedSkillPolicySnapshot(plan.dataDir)?.text ?? null : readOptional(path);
45484
45826
  readManagedSkillPolicySnapshot(plan.dataDir);
45485
45827
  for (const change of plan.changes)
45486
- if (resolve18(change.path) === resolve18(policyPath))
45828
+ if (resolve20(change.path) === resolve20(policyPath))
45487
45829
  parseManagedSkillPolicy(change.after);
45488
45830
  const aliases = plan.rootAliases ?? [];
45489
45831
  assertCurrent();
@@ -45504,7 +45846,7 @@ function applyAgentIntegrationUnlocked(plan, options = {}, assertCurrent) {
45504
45846
  assertManagedAgentBridgeWithDiscovery(agent, { home: plan.managedAgentChecks.home, dataDir: plan.dataDir, projectDir: plan.managedAgentChecks.home }, provenDiscovery?.agent === agent ? provenDiscovery : undefined);
45505
45847
  for (const binding of plan.discoveryBefore ?? []) {
45506
45848
  if (plan.managedAgentChecks)
45507
- verifyCoordinatedDiscovery(binding, plan.managedAgentChecks.home, aliases);
45849
+ verifyCoordinatedDiscovery(binding, plan.managedAgentChecks.home, aliases, plan.discoveryExecutables?.[binding.agent]);
45508
45850
  else
45509
45851
  verifyAgentDiscovery(binding);
45510
45852
  }
@@ -45536,7 +45878,7 @@ function applyAgentIntegrationUnlocked(plan, options = {}, assertCurrent) {
45536
45878
  recheckRootAliases(aliases);
45537
45879
  if (currentText(change.path) !== change.before)
45538
45880
  throw new Error(`Configuration changed after planning: ${change.path}`);
45539
- for (let directory = dirname17(change.path);!existsSync7(directory); directory = dirname17(directory))
45881
+ for (let directory = dirname18(change.path);!existsSync7(directory); directory = dirname18(directory))
45540
45882
  createdDirectories.add(directory);
45541
45883
  const after = change.after;
45542
45884
  atomicWrite2(change.path, after);
@@ -45551,7 +45893,7 @@ function applyAgentIntegrationUnlocked(plan, options = {}, assertCurrent) {
45551
45893
  throw new Error("Native settings changed during witness application");
45552
45894
  for (const binding of plan.discoveryAfter ?? []) {
45553
45895
  if (plan.managedAgentChecks)
45554
- verifyCoordinatedDiscovery(binding, plan.managedAgentChecks.home, aliases);
45896
+ verifyCoordinatedDiscovery(binding, plan.managedAgentChecks.home, aliases, plan.discoveryExecutables?.[binding.agent]);
45555
45897
  else
45556
45898
  verifyAgentDiscovery(binding);
45557
45899
  }
@@ -45608,7 +45950,7 @@ function writeArchiveJournal(path, value) {
45608
45950
  closeSync18(descriptor);
45609
45951
  descriptor = undefined;
45610
45952
  renameSync4(temporary, path);
45611
- syncArchiveDirectory(dirname17(path));
45953
+ syncArchiveDirectory(dirname18(path));
45612
45954
  } finally {
45613
45955
  if (descriptor !== undefined)
45614
45956
  closeSync18(descriptor);
@@ -45666,14 +46008,14 @@ function archiveNativeSkillsUnlocked(inventory, options, assertCurrent) {
45666
46008
  };
45667
46009
  assertSafePath(archiveRoot);
45668
46010
  const created = [];
45669
- for (let path = archiveRoot;!existsSync7(path); path = dirname17(path))
46011
+ for (let path = archiveRoot;!existsSync7(path); path = dirname18(path))
45670
46012
  created.push(path);
45671
46013
  mkdirSync6(archiveRoot, { recursive: true, mode: 448 });
45672
46014
  try {
45673
46015
  for (const directory of created)
45674
46016
  syncArchiveDirectory(directory);
45675
46017
  if (created.length)
45676
- syncArchiveDirectory(dirname17(created.at(-1)));
46018
+ syncArchiveDirectory(dirname18(created.at(-1)));
45677
46019
  writeArchiveJournal(receiptPath, journal);
45678
46020
  for (const [index, entry] of selected.entries()) {
45679
46021
  assertCurrent();
@@ -45686,7 +46028,7 @@ function archiveNativeSkillsUnlocked(inventory, options, assertCurrent) {
45686
46028
  writeArchiveJournal(receiptPath, journal);
45687
46029
  renameSync4(move.source, move.archive);
45688
46030
  moved.push(move);
45689
- syncArchiveDirectory(dirname17(move.source));
46031
+ syncArchiveDirectory(dirname18(move.source));
45690
46032
  syncArchiveDirectory(archiveRoot);
45691
46033
  verifyArchive(move);
45692
46034
  move.status = "archived";
@@ -45723,7 +46065,7 @@ function archiveNativeSkillsUnlocked(inventory, options, assertCurrent) {
45723
46065
  }
45724
46066
  if (entry.discoveryOnly) {
45725
46067
  linkSync3(entry.archive, entry.source);
45726
- syncArchiveDirectory(dirname17(entry.source));
46068
+ syncArchiveDirectory(dirname18(entry.source));
45727
46069
  unlinkSync5(entry.archive);
45728
46070
  } else {
45729
46071
  if (lstatSync23(entry.source, { throwIfNoEntry: false })) {
@@ -45734,7 +46076,7 @@ function archiveNativeSkillsUnlocked(inventory, options, assertCurrent) {
45734
46076
  renameSync4(entry.archive, entry.source);
45735
46077
  }
45736
46078
  entry.status = "restored";
45737
- syncArchiveDirectory(dirname17(entry.source));
46079
+ syncArchiveDirectory(dirname18(entry.source));
45738
46080
  syncArchiveDirectory(archiveRoot);
45739
46081
  } catch {
45740
46082
  entry.status = "recovery-required";
@@ -45759,7 +46101,7 @@ function isInertCodexPluginCacheCopy(entry, cache, allowedHostPaths, read3) {
45759
46101
  return false;
45760
46102
  const document2 = join27(entry.path, "SKILL.md");
45761
46103
  const inside = relative5(cache, entry.path);
45762
- if (!inside || isAbsolute20(inside) || inside.split(sep7).some((segment) => segment === ".."))
46104
+ if (!inside || isAbsolute22(inside) || inside.split(sep7).some((segment) => segment === ".."))
45763
46105
  return false;
45764
46106
  assertSafePath(entry.path);
45765
46107
  if (!lstatSync23(cache).isDirectory() || !lstatSync23(entry.path).isDirectory() || !lstatSync23(document2).isFile())
@@ -45779,7 +46121,7 @@ function assertManagedAgentBridge(agent, options = {}) {
45779
46121
  assertManagedAgentBridgeWithDiscovery(agent, options);
45780
46122
  }
45781
46123
  function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscovery) {
45782
- const home = resolve18(options.home ?? homedir3()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
46124
+ const home = resolve20(options.home ?? homedir3()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
45783
46125
  assertSafePath(join27(dataDir2, "agent-policy.json"));
45784
46126
  const snapshot2 = readManagedSkillPolicySnapshot(dataDir2);
45785
46127
  if (!snapshot2)
@@ -45877,12 +46219,11 @@ function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscov
45877
46219
  verifyAgentDiscovery(agent === "codex" ? { ...discovery, codexDisabledPluginSkills: binding.codexPluginSkills ?? [] } : discovery, options.codexDiscoveryRecovery);
45878
46220
  if (agent === "sumi" && discovery.method === "reviewed")
45879
46221
  resolveAgentDiscovery({ home, agent, retainedReview: discovery, canonical: (path) => canonicalAgentPath(path, aliases) });
45880
- if (discovery.method === "automatic") {
45881
- const current = resolveAgentDiscovery({ home, agent, canonical: (path) => canonicalAgentPath(path, aliases) });
45882
- if (JSON.stringify(current) !== JSON.stringify(discovery))
45883
- throw new Error("Configured native discovery roots changed");
45884
- }
46222
+ if (discovery.method === "automatic")
46223
+ verifyAutomaticDiscoveryClosure(discovery, { home, canonical: (path) => canonicalAgentPath(path, aliases), change: "Configured native discovery roots changed", executable: binding.discoveryExecutables?.[agent] });
45885
46224
  } catch (error) {
46225
+ if (isDiscoveryRootUnresolved(error))
46226
+ throw error;
45886
46227
  throw new Error(`NATIVE_SKILL_DRIFT: ${error.message}`);
45887
46228
  }
45888
46229
  let installationInputRoots = [];
@@ -45938,13 +46279,13 @@ import {
45938
46279
  statSync as statSync10,
45939
46280
  writeFileSync as writeFileSync7
45940
46281
  } from "fs";
45941
- import { basename as basename11, dirname as dirname20, isAbsolute as isAbsolute21, join as join31, normalize as normalize4, relative as relative7, resolve as resolve20, sep as sep10 } from "path";
46282
+ import { basename as basename12, dirname as dirname21, isAbsolute as isAbsolute23, join as join31, normalize as normalize4, relative as relative7, resolve as resolve22, sep as sep10 } from "path";
45942
46283
 
45943
46284
  // src/lib/registry-data/index.ts
45944
46285
  var SKILLS = [];
45945
46286
 
45946
46287
  // src/lib/skill-hash.ts
45947
- import { createHash as createHash25 } from "crypto";
46288
+ import { createHash as createHash26 } from "crypto";
45948
46289
  import { existsSync as existsSync8, readdirSync as readdirSync9, readFileSync as readFileSync18, statSync as statSync8 } from "fs";
45949
46290
  import { join as join28, sep as sep8 } from "path";
45950
46291
  var CONTENT_HASH_ALGORITHM = "sha256";
@@ -46068,13 +46409,13 @@ function* bundleHashParts(files) {
46068
46409
  yield new TextEncoder().encode("\x00");
46069
46410
  }
46070
46411
  function hashBundleFiles(files) {
46071
- const hash2 = createHash25(CONTENT_HASH_ALGORITHM);
46412
+ const hash2 = createHash26(CONTENT_HASH_ALGORITHM);
46072
46413
  for (const part of bundleHashParts(files))
46073
46414
  hash2.update(part);
46074
46415
  return hash2.digest("hex");
46075
46416
  }
46076
46417
  async function hashBundleFilesCooperatively(files, check) {
46077
- const hash2 = createHash25(CONTENT_HASH_ALGORITHM);
46418
+ const hash2 = createHash26(CONTENT_HASH_ALGORITHM);
46078
46419
  let bytesSinceYield = 0;
46079
46420
  for (const part of bundleHashParts(files)) {
46080
46421
  for (let offset = 0;offset < part.byteLength; offset += 64 * 1024) {
@@ -46083,7 +46424,7 @@ async function hashBundleFilesCooperatively(files, check) {
46083
46424
  hash2.update(chunk);
46084
46425
  bytesSinceYield += chunk.byteLength;
46085
46426
  if (bytesSinceYield >= 256 * 1024) {
46086
- await new Promise((resolve19) => setImmediate(resolve19));
46427
+ await new Promise((resolve21) => setImmediate(resolve21));
46087
46428
  bytesSinceYield = 0;
46088
46429
  }
46089
46430
  }
@@ -46206,8 +46547,8 @@ function boundedManifest(raw, maxDepth) {
46206
46547
  continue;
46207
46548
  if (depth > maxDepth)
46208
46549
  contentLimit("Content hash manifest depth limit exceeded");
46209
- for (const child of Object.values(value))
46210
- pending.push({ value: child, depth: depth + 1 });
46550
+ for (const child2 of Object.values(value))
46551
+ pending.push({ value: child2, depth: depth + 1 });
46211
46552
  }
46212
46553
  return parsed;
46213
46554
  }
@@ -46236,7 +46577,7 @@ async function hashContentEntries(entries, options) {
46236
46577
  const normalized = [];
46237
46578
  let normalizedBytes = 0;
46238
46579
  let manifest;
46239
- await new Promise((resolve19) => setImmediate(resolve19));
46580
+ await new Promise((resolve21) => setImmediate(resolve21));
46240
46581
  for (const entry of snapshot2) {
46241
46582
  check();
46242
46583
  if (!coveredContentPath(entry.path))
@@ -46249,7 +46590,7 @@ async function hashContentEntries(entries, options) {
46249
46590
  contentLimit("Content hash normalized byte limit exceeded");
46250
46591
  normalizedBytes += file.content.byteLength;
46251
46592
  normalized.push(file);
46252
- await new Promise((resolve19) => setImmediate(resolve19));
46593
+ await new Promise((resolve21) => setImmediate(resolve21));
46253
46594
  }
46254
46595
  normalized.sort((a, b) => a.rel < b.rel ? -1 : a.rel > b.rel ? 1 : 0);
46255
46596
  check();
@@ -46463,7 +46804,7 @@ import {
46463
46804
  realpathSync as realpathSync12,
46464
46805
  writeFileSync as writeFileSync6
46465
46806
  } from "fs";
46466
- import { basename as basename9, dirname as dirname18, join as join29, relative as relative6 } from "path";
46807
+ import { basename as basename10, dirname as dirname19, join as join29, relative as relative6 } from "path";
46467
46808
  var ANY_SEGMENT_COPY_EXCLUDES = new Set([
46468
46809
  ".git",
46469
46810
  ".DS_Store",
@@ -46513,11 +46854,11 @@ function normalizeNewPortableSkillName(name) {
46513
46854
  throw new Error(`Invalid skill name '${name}'. Include letters or numbers.`);
46514
46855
  return normalized;
46515
46856
  }
46516
- function readPortableSkillManifest(skillPath, fallbackName = basename9(skillPath)) {
46857
+ function readPortableSkillManifest(skillPath, fallbackName = basename10(skillPath)) {
46517
46858
  return readManifest(skillPath, fallbackName, normalizePortableSkillName);
46518
46859
  }
46519
46860
  function readPortableSkillManifestForImport(skillPath) {
46520
- return readManifest(skillPath, basename9(skillPath), normalizeNewPortableSkillName);
46861
+ return readManifest(skillPath, basename10(skillPath), normalizeNewPortableSkillName);
46521
46862
  }
46522
46863
  function readManifest(skillPath, fallbackName, normalizeName) {
46523
46864
  const skillJsonPath = join29(skillPath, "skill.json");
@@ -46710,7 +47051,7 @@ function ensurePortableSkillFiles(skillPath, manifest) {
46710
47051
  };
46711
47052
  const entry = next.commands[0]?.entry ?? "src/index.ts";
46712
47053
  if (entry && !existsSync9(join29(skillPath, entry))) {
46713
- mkdirSync7(dirname18(join29(skillPath, entry)), { recursive: true });
47054
+ mkdirSync7(dirname19(join29(skillPath, entry)), { recursive: true });
46714
47055
  writeFileSync6(join29(skillPath, entry), renderEntrypoint(next));
46715
47056
  }
46716
47057
  if (!existsSync9(join29(skillPath, "SKILL.md")))
@@ -47071,7 +47412,7 @@ function inferRuntimeFromCommands(commands) {
47071
47412
  function readJsonObject(path) {
47072
47413
  const parsed = JSON.parse(readFileSync19(path, "utf-8"));
47073
47414
  if (!isRecord3(parsed))
47074
- throw new Error(`${basename9(path)} must contain a JSON object`);
47415
+ throw new Error(`${basename10(path)} must contain a JSON object`);
47075
47416
  return parsed;
47076
47417
  }
47077
47418
  function hasPackageDependencies(pkgPath) {
@@ -47109,10 +47450,10 @@ function escapeJsString(value) {
47109
47450
  // src/lib/authoring-path.ts
47110
47451
  import { lstatSync as lstatSync25, realpathSync as realpathSync13 } from "fs";
47111
47452
  import { homedir as homedir4 } from "os";
47112
- import { basename as basename10, dirname as dirname19, join as join30, resolve as resolve19, sep as sep9 } from "path";
47453
+ import { basename as basename11, dirname as dirname20, join as join30, resolve as resolve21, sep as sep9 } from "path";
47113
47454
  var NATIVE_DISCOVERY_ROOTS = NATIVE_SKILL_ROOTS.map(([, path]) => path.split("/"));
47114
47455
  function pathParts(path) {
47115
- return resolve19(path).split(sep9).filter(Boolean);
47456
+ return resolve21(path).split(sep9).filter(Boolean);
47116
47457
  }
47117
47458
  function nativeRootMatch(path) {
47118
47459
  const parts = pathParts(path);
@@ -47126,16 +47467,16 @@ function nativeRootMatch(path) {
47126
47467
  return;
47127
47468
  }
47128
47469
  function physicalPath(path) {
47129
- let cursor = resolve19(path);
47470
+ let cursor = resolve21(path);
47130
47471
  const suffix = [];
47131
47472
  while (!lstatSync25(cursor, { throwIfNoEntry: false })) {
47132
- suffix.unshift(basename10(cursor));
47133
- const parent = dirname19(cursor);
47473
+ suffix.unshift(basename11(cursor));
47474
+ const parent = dirname20(cursor);
47134
47475
  if (parent === cursor)
47135
- return resolve19(path);
47476
+ return resolve21(path);
47136
47477
  cursor = parent;
47137
47478
  }
47138
- return resolve19(realpathSync13(cursor), ...suffix);
47479
+ return resolve21(realpathSync13(cursor), ...suffix);
47139
47480
  }
47140
47481
  function contains(root2, path) {
47141
47482
  return path === root2 || path.startsWith(root2 + sep9);
@@ -47143,7 +47484,7 @@ function contains(root2, path) {
47143
47484
  function configuredRoots(home, explicitHome) {
47144
47485
  const homeData = join30(home, ".hasna", "skills");
47145
47486
  const homePolicy = readManagedSkillPolicySnapshot(homeData);
47146
- const configuredPolicy = !explicitHome && resolve19(getDataDirReadOnly()) !== resolve19(homeData) ? readManagedSkillPolicySnapshot(getDataDirReadOnly()) : null;
47487
+ const configuredPolicy = !explicitHome && resolve21(getDataDirReadOnly()) !== resolve21(homeData) ? readManagedSkillPolicySnapshot(getDataDirReadOnly()) : null;
47147
47488
  const policy = homePolicy ?? configuredPolicy;
47148
47489
  const bridge = policy?.value.bridge;
47149
47490
  if (bridge && (typeof bridge.home !== "string" || physicalPath(bridge.home) !== physicalPath(home))) {
@@ -47182,22 +47523,22 @@ function configuredRoots(home, explicitHome) {
47182
47523
  function assertPortableAuthoringPath(path, options = {}) {
47183
47524
  if (typeof path !== "string" || !path || path.includes("\x00"))
47184
47525
  throw new Error("Invalid portable authoring path");
47185
- const lexical = resolve19(path);
47526
+ const lexical = resolve21(path);
47186
47527
  const physical = physicalPath(lexical);
47187
47528
  const candidates = [lexical, physical];
47188
47529
  let native = candidates.map(nativeRootMatch).find(Boolean);
47189
- const home = resolve19(options.homeDir ?? homedir4());
47530
+ const home = resolve21(options.homeDir ?? homedir4());
47190
47531
  const defaults = NATIVE_DISCOVERY_ROOTS.map((parts) => join30(home, ...parts));
47191
47532
  defaults.push(join30(home, ".codex/plugins/cache"), join30(home, ".claude/plugins/cache"), join30(home, ".claude/plugins/synced"), join30(home, ".gemini/extensions"));
47192
47533
  for (const root2 of defaults) {
47193
- if (candidates.some((candidate2) => contains(resolve19(root2), candidate2) || contains(physicalPath(root2), candidate2)))
47534
+ if (candidates.some((candidate2) => contains(resolve21(root2), candidate2) || contains(physicalPath(root2), candidate2)))
47194
47535
  native ??= root2;
47195
47536
  }
47196
47537
  if (native) {
47197
47538
  throw new Error(`Refusing portable Skills authoring below native discovery root '${native}': ${lexical}. Set HASNA_SKILLS_DIR to a private authoring corpus outside native roots.`);
47198
47539
  }
47199
47540
  for (const root2 of configuredRoots(home, options.homeDir !== undefined)) {
47200
- if (candidates.some((candidate2) => contains(resolve19(root2), candidate2) || contains(physicalPath(root2), candidate2))) {
47541
+ if (candidates.some((candidate2) => contains(resolve21(root2), candidate2) || contains(physicalPath(root2), candidate2))) {
47201
47542
  throw new Error(`Refusing portable Skills authoring below configured native discovery root: ${lexical}`);
47202
47543
  }
47203
47544
  }
@@ -47345,20 +47686,20 @@ function isSkillCandidate(dir) {
47345
47686
  return existsSync10(join31(dir, "SKILL.md")) || existsSync10(join31(dir, "skill.json")) || existsSync10(join31(dir, "package.json"));
47346
47687
  }
47347
47688
  function physicalImportPath(path) {
47348
- let ancestor = resolve20(path);
47689
+ let ancestor = resolve22(path);
47349
47690
  const suffix = [];
47350
47691
  while (!existsSync10(ancestor)) {
47351
- suffix.unshift(basename11(ancestor));
47352
- ancestor = dirname20(ancestor);
47692
+ suffix.unshift(basename12(ancestor));
47693
+ ancestor = dirname21(ancestor);
47353
47694
  }
47354
47695
  return join31(realpathSync14(ancestor), ...suffix);
47355
47696
  }
47356
47697
  function assertDisjointImportPaths(source, destination) {
47357
47698
  const sourcePath = realpathSync14(source);
47358
47699
  const destinationPath = physicalImportPath(destination);
47359
- const contains2 = (parent, child) => {
47360
- const path = relative7(parent, child);
47361
- return path === "" || !isAbsolute21(path) && path !== ".." && !path.startsWith(`..${sep10}`);
47700
+ const contains2 = (parent, child2) => {
47701
+ const path = relative7(parent, child2);
47702
+ return path === "" || !isAbsolute23(path) && path !== ".." && !path.startsWith(`..${sep10}`);
47362
47703
  };
47363
47704
  if (contains2(sourcePath, destinationPath) || contains2(destinationPath, sourcePath)) {
47364
47705
  throw new Error("Source and destination skill directories must not overlap");
@@ -47373,8 +47714,8 @@ function portPortableSkill(sourcePath, options = {}) {
47373
47714
  const explicitName = options.name != null;
47374
47715
  const skillName = normalizeNewPortableSkillName(options.name ?? inferred.name);
47375
47716
  if (isOfficialSkillName(skillName) && !options.allowShadow) {
47376
- const sourceSlug = safeNormalizeName(basename11(absoluteSource));
47377
- const via = explicitName ? `Name '${skillName}' matches a bundled official skill.` : `Inferred name '${skillName}'${sourceSlug && sourceSlug !== skillName ? ` (from source folder '${basename11(absoluteSource)}')` : ""} matches a bundled official skill.`;
47717
+ const sourceSlug = safeNormalizeName(basename12(absoluteSource));
47718
+ const via = explicitName ? `Name '${skillName}' matches a bundled official skill.` : `Inferred name '${skillName}'${sourceSlug && sourceSlug !== skillName ? ` (from source folder '${basename12(absoluteSource)}')` : ""} matches a bundled official skill.`;
47378
47719
  throw new Error(`${via} Importing it would shadow the official '${skillName}'. ` + `Pass --name to choose a different name, or --allow-shadow to override deliberately.`);
47379
47720
  }
47380
47721
  const readOnlyDestination = join31(resolvePortableSkillsRoot(options, false), skillName);
@@ -47389,7 +47730,7 @@ function portPortableSkill(sourcePath, options = {}) {
47389
47730
  throw new Error(`Skill '${skillName}' already exists at ${destination}`);
47390
47731
  rmSync2(destination, { recursive: true, force: true });
47391
47732
  }
47392
- mkdirSync8(dirname20(destination), { recursive: true });
47733
+ mkdirSync8(dirname21(destination), { recursive: true });
47393
47734
  copySkillDirectory(absoluteSource, destination);
47394
47735
  const base = {
47395
47736
  ...inferred,
@@ -47639,7 +47980,7 @@ function safeIsDirectory(path) {
47639
47980
  }
47640
47981
  }
47641
47982
  function isSafeRelativePath2(value) {
47642
- if (!value.trim() || isAbsolute21(value))
47983
+ if (!value.trim() || isAbsolute23(value))
47643
47984
  return false;
47644
47985
  const normalized = normalize4(value).replace(/\\/g, "/");
47645
47986
  return normalized !== ".." && !normalized.startsWith("../") && !normalized.includes("/../");
@@ -47900,9 +48241,9 @@ function writeManagedSkillDirUnlocked(dir, skillMd, options, assertCurrent) {
47900
48241
  const action = dirExists ? "update" : "create";
47901
48242
  if (options.dryRun)
47902
48243
  return { action, path: skillMdPath };
47903
- const parentDir = dirname21(dir);
48244
+ const parentDir = dirname22(dir);
47904
48245
  mkdirSync9(parentDir, { recursive: true });
47905
- const transactionDir = mkdtempSync2(join32(parentDir, `.hasna-skills-write-${basename12(dir)}-`));
48246
+ const transactionDir = mkdtempSync2(join32(parentDir, `.hasna-skills-write-${basename13(dir)}-`));
47906
48247
  const candidateDir = join32(transactionDir, "candidate");
47907
48248
  const backupDir = join32(transactionDir, "backup");
47908
48249
  const candidateSkillMdPath = join32(candidateDir, "SKILL.md");
@@ -49289,11 +49630,11 @@ async function executeSelectedLocal(selected, options = {}) {
49289
49630
  throw new SkillSelectionError("INVALID_BUNDLE_PATH", "The execution bundle path exceeds its limit.");
49290
49631
  });
49291
49632
  const destination = join37(runDirectory, entry.path);
49292
- mkdirSync11(dirname22(destination), { recursive: true, mode: 448 });
49633
+ mkdirSync11(dirname23(destination), { recursive: true, mode: 448 });
49293
49634
  writeFileSync10(destination, entry.bytes, { flag: "wx", mode: entry.mode & 511 });
49294
49635
  }
49295
49636
  env.SKILLS_INPUT_JSON = input;
49296
- env.SKILLS_WORKSPACE_DIR = resolve21(options.cwd ?? process.cwd());
49637
+ env.SKILLS_WORKSPACE_DIR = resolve23(options.cwd ?? process.cwd());
49297
49638
  env.SKILLS_RUN_DIR = runDirectory;
49298
49639
  if (runtime.version) {
49299
49640
  const version = await subprocess([executable2, ...runtimeName === "bun" ? ["--no-env-file"] : [], "--version"], runDirectory, env, "", Math.min(timeoutMs, 5000));
@@ -49323,7 +49664,7 @@ async function executeSelectedLocal(selected, options = {}) {
49323
49664
  selection: selection2,
49324
49665
  target: "local",
49325
49666
  runtime: runtimeName,
49326
- inputDigest: `sha256:${createHash26("sha256").update(input).digest("hex")}`,
49667
+ inputDigest: `sha256:${createHash27("sha256").update(input).digest("hex")}`,
49327
49668
  runDirectory,
49328
49669
  ...executionGrant ? { executionGrant } : {},
49329
49670
  ...bindings ? { secretBinding: { schema: bindings.schema, selection: bindings.selection, consumer: bindings.consumer, secretsAuthority: bindings.secretsAuthority, bindings: bindings.bindings } } : {},
@@ -49334,17 +49675,17 @@ async function executeSelectedLocal(selected, options = {}) {
49334
49675
  }
49335
49676
  async function subprocess(command, cwd, env, input, timeoutMs) {
49336
49677
  return new Promise((resolveResult) => {
49337
- const child = spawn2(command[0], command.slice(1), { cwd, env, shell: false, detached: process.platform !== "win32", stdio: ["pipe", "pipe", "pipe"] });
49678
+ const child2 = spawn2(command[0], command.slice(1), { cwd, env, shell: false, detached: process.platform !== "win32", stdio: ["pipe", "pipe", "pipe"] });
49338
49679
  let outputBytes = 0, error, ended = false;
49339
49680
  const stdout = [], stderr = [];
49340
49681
  const kill = () => {
49341
49682
  try {
49342
- if (process.platform !== "win32" && child.pid)
49343
- process.kill(-child.pid, "SIGKILL");
49683
+ if (process.platform !== "win32" && child2.pid)
49684
+ process.kill(-child2.pid, "SIGKILL");
49344
49685
  else
49345
- child.kill("SIGKILL");
49686
+ child2.kill("SIGKILL");
49346
49687
  } catch {
49347
- child.kill("SIGKILL");
49688
+ child2.kill("SIGKILL");
49348
49689
  }
49349
49690
  };
49350
49691
  const timer = setTimeout(() => {
@@ -49360,8 +49701,8 @@ async function subprocess(command, cwd, env, input, timeoutMs) {
49360
49701
  }
49361
49702
  target.push(chunk);
49362
49703
  };
49363
- child.stdout.on("data", capture2(stdout));
49364
- child.stderr.on("data", capture2(stderr));
49704
+ child2.stdout.on("data", capture2(stdout));
49705
+ child2.stderr.on("data", capture2(stderr));
49365
49706
  const finish = (code) => {
49366
49707
  if (ended)
49367
49708
  return;
@@ -49369,13 +49710,13 @@ async function subprocess(command, cwd, env, input, timeoutMs) {
49369
49710
  clearTimeout(timer);
49370
49711
  resolveResult({ exitCode: error === "LOCAL_RUN_TIMEOUT" ? 124 : error ? 1 : code, stdout: Buffer.concat(stdout).toString("utf8"), stderr: Buffer.concat(stderr).toString("utf8"), ...error ? { error } : {} });
49371
49712
  };
49372
- child.on("error", () => {
49713
+ child2.on("error", () => {
49373
49714
  error = "LOCAL_RUNTIME_START_FAILED";
49374
49715
  finish(127);
49375
49716
  });
49376
- child.on("close", (code) => finish(code ?? 1));
49377
- child.stdin.on("error", () => {});
49378
- child.stdin.end(input);
49717
+ child2.on("close", (code) => finish(code ?? 1));
49718
+ child2.stdin.on("error", () => {});
49719
+ child2.stdin.end(input);
49379
49720
  });
49380
49721
  }
49381
49722
  // src/lib/remote-run-contract.ts
@@ -58613,7 +58954,7 @@ var import_node_http_handler2 = __toESM(require_dist_cjs6(), 1);
58613
58954
 
58614
58955
  // node_modules/@aws-sdk/checksums/dist-cjs/submodules/sha/index.js
58615
58956
  var { toUint8Array: toUint8Array2, concatBytes } = require_serde();
58616
- var { createHmac: createHmac2, createHash: createHash28 } = __require("crypto");
58957
+ var { createHmac: createHmac2, createHash: createHash29 } = __require("crypto");
58617
58958
  var { Sha256: Sha2562, Sha256Js, Sha256Node } = require_checksum();
58618
58959
  var BLOCK2 = 64;
58619
58960
  var DIGEST_LENGTH = 20;
@@ -58782,7 +59123,7 @@ class Sha1Js {
58782
59123
  }
58783
59124
  var hasNativeCrypto = (() => {
58784
59125
  try {
58785
- createHash28("sha1");
59126
+ createHash29("sha1");
58786
59127
  return true;
58787
59128
  } catch {
58788
59129
  return false;
@@ -58822,7 +59163,7 @@ function buildNativeClass() {
58822
59163
  this.finished = false;
58823
59164
  }
58824
59165
  createHash() {
58825
- return this.secret ? createHmac2("sha1", toBuffer(this.secret)) : createHash28("sha1");
59166
+ return this.secret ? createHmac2("sha1", toBuffer(this.secret)) : createHash29("sha1");
58826
59167
  }
58827
59168
  };
58828
59169
  }
@@ -59375,15 +59716,15 @@ function createCancelService(options) {
59375
59716
  }
59376
59717
 
59377
59718
  // src/sdk/amounts.ts
59378
- function assertCents(value, field2) {
59719
+ function assertCents(value, field3) {
59379
59720
  if (!Number.isSafeInteger(value) || value < 0) {
59380
- throw new RangeError(field2 + " must be a nonnegative safe integer number of cents");
59721
+ throw new RangeError(field3 + " must be a nonnegative safe integer number of cents");
59381
59722
  }
59382
59723
  }
59383
- function assertReservationCents(value, field2) {
59384
- assertCents(value, field2);
59724
+ function assertReservationCents(value, field3) {
59725
+ assertCents(value, field3);
59385
59726
  if (value > 2147483647) {
59386
- throw new RangeError(field2 + " must not exceed 2147483647 cents per reservation");
59727
+ throw new RangeError(field3 + " must not exceed 2147483647 cents per reservation");
59387
59728
  }
59388
59729
  }
59389
59730
 
@@ -59391,10 +59732,10 @@ function assertReservationCents(value, field2) {
59391
59732
  import { Database as Database2 } from "bun:sqlite";
59392
59733
  import { randomUUID as randomUUID9 } from "crypto";
59393
59734
  import { mkdirSync as mkdirSync13 } from "fs";
59394
- import { dirname as dirname26 } from "path";
59735
+ import { dirname as dirname27 } from "path";
59395
59736
 
59396
59737
  // src/server/database-url.ts
59397
- import { isAbsolute as isAbsolute22, join as join39 } from "path";
59738
+ import { isAbsolute as isAbsolute24, join as join39 } from "path";
59398
59739
  import { fileURLToPath as fileURLToPath3 } from "url";
59399
59740
  var DEFAULT_SQLITE_FILENAME2 = "server.db";
59400
59741
  var SQLITE_MEMORY_PATH = ":memory:";
@@ -59430,7 +59771,7 @@ function resolveDatabaseTarget(raw) {
59430
59771
  throw new Error(`unsupported database scheme "${scheme}:". Supported: postgres://, postgresql://, sqlite:, file:, ` + `an absolute or relative path to a .db/.sqlite file, ":memory:", or "memory:" (non-durable, tests only). ` + `Leave the setting empty to use the default SQLite database at ${defaultSqlitePath()}.`);
59431
59772
  }
59432
59773
  if (looksLikeSqlitePath(value)) {
59433
- const path = isAbsolute22(value) ? value : join39(process.cwd(), value);
59774
+ const path = isAbsolute24(value) ? value : join39(process.cwd(), value);
59434
59775
  return { kind: "sqlite", path, durable: true, label: `sqlite (${path})` };
59435
59776
  }
59436
59777
  throw new Error(`could not resolve a database backend from "${value}". Use postgres://\u2026, sqlite:\u2026, an absolute or ` + `relative path ending in ${SQLITE_EXTENSIONS.join("/")}, ":memory:", or leave it empty for the ` + `default SQLite database at ${defaultSqlitePath()}.`);
@@ -59454,7 +59795,7 @@ function sqlitePathFromUrl(value, scheme) {
59454
59795
  }
59455
59796
  return rest.slice(2).replace(/^\/\/+/, "/");
59456
59797
  }
59457
- return isAbsolute22(rest) ? rest : join39(process.cwd(), rest);
59798
+ return isAbsolute24(rest) ? rest : join39(process.cwd(), rest);
59458
59799
  }
59459
59800
  function looksLikeSqlitePath(value) {
59460
59801
  if (value.includes("/"))
@@ -59687,12 +60028,12 @@ class PostgresSkillSelectionStore {
59687
60028
  // src/server/sqlite-store.ts
59688
60029
  import { randomUUID as randomUUID8 } from "crypto";
59689
60030
  import { mkdirSync as mkdirSync12, readFileSync as readFileSync26, readdirSync as readdirSync13 } from "fs";
59690
- import { dirname as dirname25, join as join41 } from "path";
60031
+ import { dirname as dirname26, join as join41 } from "path";
59691
60032
 
59692
60033
  // src/server/auth.ts
59693
- import { createHash as createHash29 } from "crypto";
60034
+ import { createHash as createHash30 } from "crypto";
59694
60035
  function hashApiKey(token) {
59695
- return createHash29("sha256").update(token).digest("hex");
60036
+ return createHash30("sha256").update(token).digest("hex");
59696
60037
  }
59697
60038
  function bearerToken(request2) {
59698
60039
  const header = request2.headers.get("authorization") || "";
@@ -59746,7 +60087,7 @@ function permitsSkillsRoute(principal, method, resource) {
59746
60087
 
59747
60088
  // src/server/migrations-dir.ts
59748
60089
  import { existsSync as existsSync16 } from "fs";
59749
- import { dirname as dirname24, join as join40 } from "path";
60090
+ import { dirname as dirname25, join as join40 } from "path";
59750
60091
  var MIGRATION_DIALECTS = ["postgres", "sqlite"];
59751
60092
  var MAX_WALK_UP = 6;
59752
60093
  function findMigrationsRoot(startDirs = defaultStartDirs()) {
@@ -59756,7 +60097,7 @@ function findMigrationsRoot(startDirs = defaultStartDirs()) {
59756
60097
  const candidate2 = join40(dir, "migrations");
59757
60098
  if (MIGRATION_DIALECTS.some((dialect) => existsSync16(join40(candidate2, dialect))))
59758
60099
  return candidate2;
59759
- const parent = dirname24(dir);
60100
+ const parent = dirname25(dir);
59760
60101
  if (parent === dir)
59761
60102
  break;
59762
60103
  dir = parent;
@@ -60011,12 +60352,12 @@ class SkillLifecycleConflictError extends Error {
60011
60352
  }
60012
60353
  }
60013
60354
  function validOperatorScopeEnrollmentInput(input) {
60014
- const bounded = (value, max = 256) => typeof value === "string" && value.length > 0 && value.length <= max && !/[\u0000-\u001f\u007f]/.test(value);
60015
- return bounded(input.keyId) && bounded(input.stationId) && bounded(input.orgId) && bounded(input.operationId) && bounded(input.manifestDigest, 64) && /^[a-f0-9]{64}$/.test(input.manifestDigest) && bounded(input.operatorJobId) && bounded(input.operatorTaskArn, 512) && input.expectedScopes.length > 0 && input.expectedScopes.length <= 32 && input.expectedScopes.every((scope) => bounded(scope, 128) && /^[a-z][a-z0-9_-]*:[a-z][a-z0-9_-]*$/.test(scope));
60355
+ const bounded2 = (value, max = 256) => typeof value === "string" && value.length > 0 && value.length <= max && !/[\u0000-\u001f\u007f]/.test(value);
60356
+ return bounded2(input.keyId) && bounded2(input.stationId) && bounded2(input.orgId) && bounded2(input.operationId) && bounded2(input.manifestDigest, 64) && /^[a-f0-9]{64}$/.test(input.manifestDigest) && bounded2(input.operatorJobId) && bounded2(input.operatorTaskArn, 512) && input.expectedScopes.length > 0 && input.expectedScopes.length <= 32 && input.expectedScopes.every((scope) => bounded2(scope, 128) && /^[a-z][a-z0-9_-]*:[a-z][a-z0-9_-]*$/.test(scope));
60016
60357
  }
60017
60358
 
60018
60359
  // src/lib/revision.ts
60019
- import { createHash as createHash30 } from "crypto";
60360
+ import { createHash as createHash31 } from "crypto";
60020
60361
  var REVISION_ID_PATTERN = /^[0-9a-f]{64}$/;
60021
60362
  function revisionIdOf(content) {
60022
60363
  const canonicalContent = {
@@ -60037,8 +60378,8 @@ function revisionIdOf(content) {
60037
60378
  canonicalContent.archiveReason = content.archiveReason ?? null;
60038
60379
  canonicalContent.replacementSlug = content.replacementSlug ?? null;
60039
60380
  }
60040
- const canonical7 = JSON.stringify(canonicalContent);
60041
- return createHash30("sha256").update(canonical7).digest("hex");
60381
+ const canonical8 = JSON.stringify(canonicalContent);
60382
+ return createHash31("sha256").update(canonical8).digest("hex");
60042
60383
  }
60043
60384
  function revisionIdOfRecord(record4) {
60044
60385
  return revisionIdOf(record4);
@@ -60063,7 +60404,7 @@ class SqliteSkillsStore {
60063
60404
  constructor(path = SQLITE_MEMORY_PATH, options = {}) {
60064
60405
  const inMemory = path === SQLITE_MEMORY_PATH;
60065
60406
  if (!inMemory)
60066
- mkdirSync12(dirname25(path), { recursive: true });
60407
+ mkdirSync12(dirname26(path), { recursive: true });
60067
60408
  this.db = openDatabase(path);
60068
60409
  this.db.exec(`PRAGMA busy_timeout = ${Math.max(0, options.busyTimeoutMs ?? 5000)}`);
60069
60410
  if (!inMemory)
@@ -60780,8 +61121,8 @@ function openDatabase(path) {
60780
61121
  try {
60781
61122
  return new Database(path, { create: true, readwrite: true });
60782
61123
  } catch (error) {
60783
- const reason = error instanceof Error ? error.message : String(error);
60784
- throw new Error(`cannot open the skills database at ${path}: ${reason}. ` + "Check that the directory exists and is writable. Set HASNA_SKILLS_DATABASE_URL to choose a " + "different path or a postgres:// URL, or HASNA_SKILLS_DIR to relocate the whole data directory.", { cause: error });
61124
+ const reason2 = error instanceof Error ? error.message : String(error);
61125
+ throw new Error(`cannot open the skills database at ${path}: ${reason2}. ` + "Check that the directory exists and is writable. Set HASNA_SKILLS_DATABASE_URL to choose a " + "different path or a postgres:// URL, or HASNA_SKILLS_DIR to relocate the whole data directory.", { cause: error });
60785
61126
  }
60786
61127
  }
60787
61128
  function parseScopes(value) {
@@ -60889,7 +61230,7 @@ class SqliteGovernanceStore {
60889
61230
  closed = false;
60890
61231
  constructor(path = SQLITE_MEMORY_PATH, options = {}) {
60891
61232
  if (path !== SQLITE_MEMORY_PATH)
60892
- mkdirSync13(dirname26(path), { recursive: true });
61233
+ mkdirSync13(dirname27(path), { recursive: true });
60893
61234
  this.db = new Database2(path, { create: true, readwrite: true });
60894
61235
  this.db.exec("PRAGMA busy_timeout = 5000");
60895
61236
  this.db.exec("PRAGMA foreign_keys = ON");
@@ -61122,7 +61463,7 @@ function nextMonthPrefix(monthPrefix) {
61122
61463
  }
61123
61464
 
61124
61465
  // src/server/skills-api.ts
61125
- import { createHash as createHash31 } from "crypto";
61466
+ import { createHash as createHash32 } from "crypto";
61126
61467
  var SLUG_PATTERN = /^[a-z0-9][a-z0-9._-]*$/;
61127
61468
  var SHA256_HEX2 = /^[0-9a-f]{64}$/;
61128
61469
  var MAX_SLUG_LENGTH = 128;
@@ -61312,7 +61653,7 @@ async function parsePublishRequest(request2, config) {
61312
61653
  if (bundleBytes.byteLength === 0) {
61313
61654
  throw new SkillRequestError(400, "BUNDLE_EMPTY", "the uploaded bundle is empty");
61314
61655
  }
61315
- const sha2563 = createHash31("sha256").update(bundleBytes).digest("hex");
61656
+ const sha2563 = createHash32("sha256").update(bundleBytes).digest("hex");
61316
61657
  const claimed = optionalString(manifest.bundleSha256);
61317
61658
  if (claimed)
61318
61659
  assertSha2562(claimed);
@@ -61427,7 +61768,7 @@ async function readPublishedBundle(store, artifactStorage, principal, slug) {
61427
61768
  if (!bytes) {
61428
61769
  throw new SkillRequestError(503, "BUNDLE_BACKEND_UNAVAILABLE", "bundle storage backend unavailable");
61429
61770
  }
61430
- const actual = createHash31("sha256").update(bytes).digest("hex");
61771
+ const actual = createHash32("sha256").update(bytes).digest("hex");
61431
61772
  if (actual !== record4.bundleSha256) {
61432
61773
  throw new SkillRequestError(500, "BUNDLE_DIGEST_DRIFT", `stored bundle for '${slug}' hashes to ${actual} but was published as ${record4.bundleSha256}`);
61433
61774
  }
@@ -61484,7 +61825,7 @@ function buildPublishInput(manifest) {
61484
61825
  displayName: optionalString(manifest.displayName) ?? titleize(slug),
61485
61826
  description,
61486
61827
  category: optionalString(manifest.category) ?? "Development Tools",
61487
- tags: stringArray(manifest.tags),
61828
+ tags: stringArray2(manifest.tags),
61488
61829
  source: publishSource(optionalString(manifest.source)),
61489
61830
  kind: kindValue,
61490
61831
  ...publishVersionOf(manifest) ? { version: publishVersionOf(manifest) } : {},
@@ -61513,7 +61854,7 @@ function optionalString(value) {
61513
61854
  function optionalText(value) {
61514
61855
  return typeof value === "string" && value.trim() ? value : undefined;
61515
61856
  }
61516
- function stringArray(value) {
61857
+ function stringArray2(value) {
61517
61858
  if (!Array.isArray(value))
61518
61859
  return [];
61519
61860
  return value.filter((item) => typeof item === "string" && item.trim().length > 0).map((item) => item.trim());
@@ -61575,7 +61916,7 @@ async function readSkillVersionBundle(store, artifactStorage, principal, slug, v
61575
61916
  const bytes = await artifactStorage.readBundle(bundle2);
61576
61917
  if (!bytes)
61577
61918
  throw new SkillRequestError(503, "BUNDLE_BACKEND_UNAVAILABLE", "bundle storage backend unavailable");
61578
- const actual = createHash31("sha256").update(bytes).digest("hex");
61919
+ const actual = createHash32("sha256").update(bytes).digest("hex");
61579
61920
  if (actual !== found.bundleSha256) {
61580
61921
  throw new SkillRequestError(500, "BUNDLE_DIGEST_DRIFT", `stored bundle for '${slug}@${version2}' hashes to ${actual} but was published as ${found.bundleSha256}`);
61581
61922
  }
@@ -61658,7 +61999,7 @@ async function validatePublishedGrant(store, artifacts, principal, grant) {
61658
61999
  invalid3();
61659
62000
  }
61660
62001
  async function handleExecutionGrantApi(store, principal, request2, parts, config, artifacts) {
61661
- const [resource, id2, child, revision] = parts;
62002
+ const [resource, id2, child2, revision] = parts;
61662
62003
  if (resource !== "execution-grants")
61663
62004
  return null;
61664
62005
  if (!grantIdentifier(id2))
@@ -61666,7 +62007,7 @@ async function handleExecutionGrantApi(store, principal, request2, parts, config
61666
62007
  const { executionGrantStore: policies, selectionStore: profiles } = store;
61667
62008
  if (!policies || !profiles)
61668
62009
  refuse5(503, "EXECUTION_GRANTS_UNAVAILABLE", "This store does not support execution grants.");
61669
- const historical = parts.length === 4 && child === "versions" && grantIdentifier(revision);
62010
+ const historical = parts.length === 4 && child2 === "versions" && grantIdentifier(revision);
61670
62011
  if (request2.method === "GET" && (parts.length === 2 || historical)) {
61671
62012
  const policy = await policies.get(principal, id2, historical ? revision : undefined);
61672
62013
  if (!policy)
@@ -61705,7 +62046,7 @@ async function handleExecutionGrantApi(store, principal, request2, parts, config
61705
62046
  refuse5(409, "EXECUTION_GRANT_REVISION_CONFLICT", "Execution grant policy changed; read it before retrying.");
61706
62047
  return json(saved, create ? 201 : 200, saved.revision);
61707
62048
  }
61708
- if (request2.method === "POST" && parts.length === 3 && child === "resolve") {
62049
+ if (request2.method === "POST" && parts.length === 3 && child2 === "resolve") {
61709
62050
  const input = await body(request2, Math.min(config.requestBodyLimitBytes, 16384));
61710
62051
  let consumer;
61711
62052
  try {
@@ -61870,7 +62211,7 @@ function json2(value, status = 200, revision) {
61870
62211
  });
61871
62212
  }
61872
62213
  async function handleProfileApi(store, principal, request2, parts, config) {
61873
- const [resource, id2, child] = parts;
62214
+ const [resource, id2, child2] = parts;
61874
62215
  if (resource === "capabilities" && request2.method === "GET" && parts.length === 1)
61875
62216
  return json2({
61876
62217
  contractVersion: 1,
@@ -61936,13 +62277,13 @@ async function handleProfileApi(store, principal, request2, parts, config) {
61936
62277
  throw new SkillRequestError(409, "PROFILE_REVISION_CONFLICT", "Profile changed; read it before retrying");
61937
62278
  return json2(saved, create ? 201 : 200, saved.revision);
61938
62279
  }
61939
- if (resource === "profiles" && request2.method === "GET" && (parts.length === 2 || parts.length === 3 && child === "resolve")) {
62280
+ if (resource === "profiles" && request2.method === "GET" && (parts.length === 2 || parts.length === 3 && child2 === "resolve")) {
61940
62281
  const profile2 = await adapter.getProfile(principal, id2);
61941
62282
  if (!profile2)
61942
62283
  throw new SkillRequestError(404, "PROFILE_NOT_FOUND", "Profile not found");
61943
62284
  if (profile2.selections.length > MAX_PROFILE_SELECTIONS)
61944
62285
  throw new SkillRequestError(413, "PROFILE_TOO_LARGE", "Profile exceeds the advertised selection limit");
61945
- if (!child)
62286
+ if (!child2)
61946
62287
  return json2(profile2, 200, profile2.revision);
61947
62288
  const authority2 = skillsApiRequestUrl(normalizeSkillsApiOrigin(config.publicBaseUrl), "/api/v1/").replace(/\/+$/, "");
61948
62289
  const result = resolvedProfileSnapshot(profile2, authority2);
@@ -61961,7 +62302,7 @@ async function handleProfileApi(store, principal, request2, parts, config) {
61961
62302
  throw new SkillRequestError(413, "PROFILE_TOO_LARGE", "Resolved profile exceeds the advertised profile limits");
61962
62303
  return json2(result, 200, profile2.revision);
61963
62304
  }
61964
- if (resource === "stations" && parts.length === 3 && child === "state") {
62305
+ if (resource === "stations" && parts.length === 3 && child2 === "state") {
61965
62306
  if (request2.method === "GET") {
61966
62307
  const state2 = await adapter.getStationState(principal, id2);
61967
62308
  if (!state2)
@@ -61995,7 +62336,7 @@ async function handleProfileApi(store, principal, request2, parts, config) {
61995
62336
  // src/server/runtime-store.ts
61996
62337
  import { Database as Database3 } from "bun:sqlite";
61997
62338
  import { mkdirSync as mkdirSync14 } from "fs";
61998
- import { dirname as dirname27 } from "path";
62339
+ import { dirname as dirname28 } from "path";
61999
62340
 
62000
62341
  // src/sdk/execution/types.ts
62001
62342
  var EXECUTION_PROTOCOL_VERSION = REMOTE_SKILL_RUN_CONTRACT_VERSION;
@@ -62051,7 +62392,7 @@ class RuntimeExecutionStore {
62051
62392
  }
62052
62393
  const path = target.kind === "sqlite" ? target.path : ":memory:";
62053
62394
  if (path !== ":memory:")
62054
- mkdirSync14(dirname27(path), { recursive: true });
62395
+ mkdirSync14(dirname28(path), { recursive: true });
62055
62396
  const db = new Database3(path);
62056
62397
  db.run("PRAGMA busy_timeout=5000");
62057
62398
  db.run("PRAGMA journal_mode=WAL");
@@ -62291,7 +62632,7 @@ class RuntimeExecutionStore {
62291
62632
  }
62292
62633
 
62293
62634
  // src/sdk/execution/admission.ts
62294
- import { createHash as createHash33 } from "crypto";
62635
+ import { createHash as createHash34 } from "crypto";
62295
62636
 
62296
62637
  // src/sdk/execution/image-profile.ts
62297
62638
  class ImageProfileResolutionError extends Error {
@@ -62903,11 +63244,11 @@ function ownedAdmission(admission) {
62903
63244
  };
62904
63245
  }
62905
63246
  function digestInput(input) {
62906
- return createHash33("sha256").update(canonicalJson2(input)).digest("hex");
63247
+ return createHash34("sha256").update(canonicalJson2(input)).digest("hex");
62907
63248
  }
62908
63249
 
62909
63250
  // src/sdk/execution/dispatchers/ecs.ts
62910
- import { createHash as createHash34 } from "crypto";
63251
+ import { createHash as createHash35 } from "crypto";
62911
63252
 
62912
63253
  // src/sdk/execution/state-machine.ts
62913
63254
  var LEGAL_TRANSITIONS = {
@@ -66307,13 +66648,13 @@ function observedTask(states, taskArn) {
66307
66648
  return state2.lastStatus === "STOPPED" || LIVE_TASK_STATUSES.has(state2.lastStatus) ? state2 : undefined;
66308
66649
  }
66309
66650
  function clientTokenFor(runId3, attemptId) {
66310
- return createHash34("sha256").update(`${runId3}\x00${attemptId}`).digest("hex").slice(0, CLIENT_TOKEN_BYTES * 2);
66651
+ return createHash35("sha256").update(`${runId3}\x00${attemptId}`).digest("hex").slice(0, CLIENT_TOKEN_BYTES * 2);
66311
66652
  }
66312
66653
  function startedByFor(runId3, attemptNumber) {
66313
66654
  return `skills-exec/${runId3}/a${attemptNumber}`;
66314
66655
  }
66315
66656
  function requestDigestFor(admission, attemptId) {
66316
- return createHash34("sha256").update(canonicalJson2({ admission, attemptId })).digest("hex");
66657
+ return createHash35("sha256").update(canonicalJson2({ admission, attemptId })).digest("hex");
66317
66658
  }
66318
66659
 
66319
66660
  class EcsDispatcher {
@@ -66609,10 +66950,10 @@ function validText(value) {
66609
66950
  }
66610
66951
 
66611
66952
  // src/server/runtime-policy.ts
66612
- import { createHash as createHash36, createHmac as createHmac3, timingSafeEqual as timingSafeEqual2 } from "crypto";
66953
+ import { createHash as createHash37, createHmac as createHmac3, timingSafeEqual as timingSafeEqual2 } from "crypto";
66613
66954
 
66614
66955
  // src/server/runtime-pure-contract.ts
66615
- import { createHash as createHash35 } from "crypto";
66956
+ import { createHash as createHash36 } from "crypto";
66616
66957
  var PURE_DESCRIPTOR = Object.freeze({
66617
66958
  id: "regex-test.v1",
66618
66959
  runtime: "bun",
@@ -66636,7 +66977,7 @@ var PURE_LIMITS = Object.freeze({
66636
66977
  maxArtifactsBytes: 0,
66637
66978
  maxConcurrency: 1
66638
66979
  });
66639
- var hash2 = (bytes) => createHash35("sha256").update(bytes).digest("hex");
66980
+ var hash2 = (bytes) => createHash36("sha256").update(bytes).digest("hex");
66640
66981
  var object7 = (v2) => {
66641
66982
  if (!v2 || typeof v2 !== "object" || Array.isArray(v2))
66642
66983
  throw Error("Pure contract requires an object");
@@ -66865,7 +67206,7 @@ function verifyRuntimeToken(token, key, admission, attempt, now = Date.now()) {
66865
67206
  const actual = Buffer.from(token);
66866
67207
  return actual.length === expected.length && timingSafeEqual2(actual, expected);
66867
67208
  }
66868
- var hashBytes = (bytes) => createHash36("sha256").update(bytes).digest("hex");
67209
+ var hashBytes = (bytes) => createHash37("sha256").update(bytes).digest("hex");
66869
67210
 
66870
67211
  // src/server/runtime-api.ts
66871
67212
  async function createRuntimeService(options) {
@@ -73241,7 +73582,7 @@ var localRunExecutor = {
73241
73582
  // src/sdk/storage.ts
73242
73583
  var artifactStorageSeam = ArtifactStorage;
73243
73584
  // src/sdk/outputs.ts
73244
- import { createHash as createHash37 } from "crypto";
73585
+ import { createHash as createHash38 } from "crypto";
73245
73586
  class DatabaseOnlyObjectStore {
73246
73587
  usesS3 = false;
73247
73588
  async materialize(run, artifact, body4) {
@@ -73288,7 +73629,7 @@ function createGovernedArtifactWriter(options) {
73288
73629
  const stamped = {
73289
73630
  ...meta,
73290
73631
  byteSize: outputBytes,
73291
- sha256: createHash37("sha256").update(persistedBytes).digest("hex"),
73632
+ sha256: createHash38("sha256").update(persistedBytes).digest("hex"),
73292
73633
  visibility: options.visibility ?? config.defaultVisibility,
73293
73634
  ...config.artifactTtlSeconds !== undefined ? { expiresAt: expiresAtFor(createdAt, config.artifactTtlSeconds) } : {}
73294
73635
  };
@@ -76930,14 +77271,14 @@ var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
76930
77271
  const shape = zod.def.shape;
76931
77272
  const propValues = {};
76932
77273
  for (const key in shape) {
76933
- const field2 = shape[key]._zod;
76934
- if (field2.values) {
77274
+ const field3 = shape[key]._zod;
77275
+ if (field3.values) {
76935
77276
  if (!Object.prototype.hasOwnProperty.call(propValues, key)) {
76936
77277
  assignProp(propValues, key, new Set);
76937
77278
  }
76938
- for (const v2 of field2.values)
77279
+ for (const v2 of field3.values)
76939
77280
  propValues[key].add(v2);
76940
- if (field2.optin !== undefined)
77281
+ if (field3.optin !== undefined)
76941
77282
  propValues[key].add(undefined);
76942
77283
  }
76943
77284
  }
@@ -78350,8 +78691,8 @@ function isRecursive(inst, stack) {
78350
78691
  return true;
78351
78692
  stack.add(inst);
78352
78693
  let result = false;
78353
- const check = (child) => {
78354
- if (!result && child?._zod && isRecursive(child, stack))
78694
+ const check = (child2) => {
78695
+ if (!result && child2?._zod && isRecursive(child2, stack))
78355
78696
  result = true;
78356
78697
  };
78357
78698
  const def = inst._zod.def;
@@ -89130,11 +89471,11 @@ var objectProcessor = (schema, ctx, _json, params) => {
89130
89471
  }
89131
89472
  const allKeys = new Set(Object.keys(shape));
89132
89473
  const requiredKeys = new Set([...allKeys].filter((key) => {
89133
- const field2 = def.shape[key];
89474
+ const field3 = def.shape[key];
89134
89475
  if (ctx.io === "input") {
89135
- return inputOptin(field2) === undefined;
89476
+ return inputOptin(field3) === undefined;
89136
89477
  } else {
89137
- return field2._zod.optout === undefined;
89478
+ return field3._zod.optout === undefined;
89138
89479
  }
89139
89480
  }));
89140
89481
  if (requiredKeys.size > 0) {
@@ -92055,7 +92396,7 @@ function date4(params) {
92055
92396
  return _coercedDate(ZodDate2, params);
92056
92397
  }
92057
92398
  // src/lib/canonical-json.ts
92058
- import { createHash as createHash38 } from "crypto";
92399
+ import { createHash as createHash39 } from "crypto";
92059
92400
  function canonicalJson3(value, maximumBytes = 2 * 1024 * 1024) {
92060
92401
  return canonicalJsonAtDepth(value, maximumBytes, 64);
92061
92402
  }
@@ -92099,7 +92440,7 @@ function canonicalJsonAtDepth(value, maximumBytes, maximumDepth) {
92099
92440
  return visit3(value, 0);
92100
92441
  }
92101
92442
  function canonicalJsonSha256(value, maximumBytes) {
92102
- return createHash38("sha256").update(canonicalJson3(value, maximumBytes)).digest("hex");
92443
+ return createHash39("sha256").update(canonicalJson3(value, maximumBytes)).digest("hex");
92103
92444
  }
92104
92445
 
92105
92446
  // src/lib/remote-recurring-contract.ts
@@ -92879,17 +93220,17 @@ function runQuoteReceipt(value) {
92879
93220
  return value;
92880
93221
  }
92881
93222
  function parseRemoteRunQuote(value) {
92882
- const quote2 = object9(value);
92883
- runQuoteReceipt(quote2.quoteReceipt);
92884
- const pricing = object9(quote2.pricing);
92885
- if (typeof quote2.skill !== "string" || !/^[a-z0-9][a-z0-9-]*$/.test(quote2.skill))
93223
+ const quote3 = object9(value);
93224
+ runQuoteReceipt(quote3.quoteReceipt);
93225
+ const pricing = object9(quote3.pricing);
93226
+ if (typeof quote3.skill !== "string" || !/^[a-z0-9][a-z0-9-]*$/.test(quote3.skill))
92886
93227
  throw new Error("Invalid quoted skill");
92887
93228
  const costCents = creditCount(pricing.costCredits ?? pricing.costCents);
92888
93229
  if (pricing.costCredits !== undefined && pricing.costCents !== undefined && pricing.costCents !== costCents)
92889
93230
  throw new Error("Inconsistent quoted credit count");
92890
- if (quote2.availability && object9(quote2.availability).status !== "available")
93231
+ if (quote3.availability && object9(quote3.availability).status !== "available")
92891
93232
  throw new Error("This skill is unavailable for remote execution");
92892
- return { ...quote2, skill: quote2.skill, pricing: { ...pricing, costCredits: costCents, costCents, formattedCost: `${costCents} credits` } };
93233
+ return { ...quote3, skill: quote3.skill, pricing: { ...pricing, costCredits: costCents, costCents, formattedCost: `${costCents} credits` } };
92893
93234
  }
92894
93235
  function parseRemoteCreditPacks(value) {
92895
93236
  if (!Array.isArray(value))
@@ -92964,14 +93305,14 @@ function creditCheckoutFailure(value, status, key) {
92964
93305
  }
92965
93306
 
92966
93307
  // src/lib/remote-profile.ts
92967
- function customerNamePatch(input2, field2) {
92968
- if (!isRecord6(input2) || Object.keys(input2).length !== 1 || !Object.hasOwn(input2, field2))
93308
+ function customerNamePatch(input2, field3) {
93309
+ if (!isRecord6(input2) || Object.keys(input2).length !== 1 || !Object.hasOwn(input2, field3))
92969
93310
  throw new Error("Provide only the requested name field.");
92970
- const value = input2[field2];
93311
+ const value = input2[field3];
92971
93312
  if (typeof value !== "string" || /[\p{Cc}\p{Cs}\u2028\u2029]/u.test(value) || !value.trim() || [...value.trim()].length > 100) {
92972
93313
  throw new Error("Use a name of 1\u2013100 characters without control characters or newlines.");
92973
93314
  }
92974
- return { [field2]: value.trim() };
93315
+ return { [field3]: value.trim() };
92975
93316
  }
92976
93317
  function isRecord6(value) {
92977
93318
  return !!value && typeof value === "object" && !Array.isArray(value);
@@ -93016,10 +93357,10 @@ async function readQuoteUnavailableCode(response) {
93016
93357
  let timer;
93017
93358
  let deadlineExceeded = false;
93018
93359
  const expired = Symbol("quote body deadline");
93019
- const deadline = new Promise((resolve23) => {
93360
+ const deadline = new Promise((resolve25) => {
93020
93361
  timer = setTimeout(() => {
93021
93362
  deadlineExceeded = true;
93022
- resolve23(expired);
93363
+ resolve25(expired);
93023
93364
  reader.cancel().catch(() => {});
93024
93365
  }, 1500);
93025
93366
  });
@@ -93366,18 +93707,18 @@ class RemoteSkillsClient {
93366
93707
  const maximum = creditCount(approval.maxCredits ?? approval.maxCostCents ?? 0);
93367
93708
  if (approval.maxCostCents !== undefined && approval.maxCostCents !== maximum)
93368
93709
  throw new Error("Credit approval fields disagree");
93369
- const quote2 = approval.quoteReceipt === undefined ? await this.quoteRun(slug2, input2, args, approval.inputFiles?.length ? approval.inputFiles : undefined) : undefined;
93370
- if (quote2 && quote2.pricing.costCents > maximum)
93371
- throw new RemoteCreditApprovalError(quote2.pricing.costCents, maximum);
93710
+ const quote3 = approval.quoteReceipt === undefined ? await this.quoteRun(slug2, input2, args, approval.inputFiles?.length ? approval.inputFiles : undefined) : undefined;
93711
+ if (quote3 && quote3.pricing.costCents > maximum)
93712
+ throw new RemoteCreditApprovalError(quote3.pricing.costCents, maximum);
93372
93713
  const capabilities = await this.getCapabilities();
93373
93714
  if (!capabilities.capabilities.includes("runs.submit") || capabilities.billing?.boundedRunApproval !== true || capabilities.billing.unit !== "credits") {
93374
93715
  throw new Error("The configured server does not support bounded credit approval; refusing remote submission");
93375
93716
  }
93376
- return this.submitRun(quote2?.skill ?? slug2, input2, args, {
93717
+ return this.submitRun(quote3?.skill ?? slug2, input2, args, {
93377
93718
  ...approval,
93378
93719
  maxCredits: maximum,
93379
93720
  maxCostCents: maximum,
93380
- ...(quote2?.quoteReceipt ?? approval.quoteReceipt) === undefined ? {} : { quoteReceipt: quote2?.quoteReceipt ?? approval.quoteReceipt }
93721
+ ...(quote3?.quoteReceipt ?? approval.quoteReceipt) === undefined ? {} : { quoteReceipt: quote3?.quoteReceipt ?? approval.quoteReceipt }
93381
93722
  });
93382
93723
  }
93383
93724
  async getIdentity() {
@@ -93978,13 +94319,13 @@ class RemoteSkillsClient {
93978
94319
  return normalizeUpdatedSincePage(await response.json());
93979
94320
  }
93980
94321
  }
93981
- function requireOptionalString(record9, field2) {
93982
- if (record9[field2] === undefined)
94322
+ function requireOptionalString(record9, field3) {
94323
+ if (record9[field3] === undefined)
93983
94324
  return;
93984
- if (typeof record9[field2] !== "string") {
93985
- throw new Error(`Remote payload did not match the expected contract (${field2} must be a string when present)`);
94325
+ if (typeof record9[field3] !== "string") {
94326
+ throw new Error(`Remote payload did not match the expected contract (${field3} must be a string when present)`);
93986
94327
  }
93987
- return record9[field2];
94328
+ return record9[field3];
93988
94329
  }
93989
94330
  var INVALID_SKILL_VERSION_RESPONSE = "Remote skill version payload did not match the expected contract.";
93990
94331
  function isVersionRecord(value) {
@@ -94213,7 +94554,7 @@ async function requestInvitationEmail(origin, action, input2) {
94213
94554
  }
94214
94555
 
94215
94556
  // src/lib/remote-private-publications.ts
94216
- import { createHash as createHash39 } from "crypto";
94557
+ import { createHash as createHash40 } from "crypto";
94217
94558
  var PRIVATE_PUBLICATION_MAX_BYTES = 16 * 1024 * 1024;
94218
94559
  var failures2 = {
94219
94560
  INVALID_REQUEST: [400, "The publication request is invalid."],
@@ -94260,7 +94601,7 @@ var hash4 = (v2) => typeof v2 === "string" && /^[a-f0-9]{64}$/.test(v2);
94260
94601
  var record10 = (v2) => !!v2 && typeof v2 === "object" && !Array.isArray(v2);
94261
94602
  var exact = (v2, keys3) => record10(v2) && Object.keys(v2).sort().join(",") === keys3.sort().join(",");
94262
94603
  var date5 = (v2) => typeof v2 === "string" && /^\d{4}-\d\d-\d\dT[0-9:.]+(?:Z|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/.test(v2) && Number.isFinite(Date.parse(v2));
94263
- var publicationSha256 = (bytes) => createHash39("sha256").update(bytes).digest("hex");
94604
+ var publicationSha256 = (bytes) => createHash40("sha256").update(bytes).digest("hex");
94264
94605
  function checkedPublicationDeclaration(value) {
94265
94606
  if (!exact(value, ["idempotencyKey", "version", "expectedCurrentVersionId", "manifestText", "archiveSha256", "archiveByteSize"]) || !publicationUuid(value.idempotencyKey) || !(value.expectedCurrentVersionId === null || publicationUuid(value.expectedCurrentVersionId)) || typeof value.version !== "string" || !value.version || value.version.length > 128 || /[\p{Cc}\p{Cs}]/u.test(value.version) || typeof value.manifestText !== "string" || Buffer.byteLength(value.manifestText) > 16384 || !hash4(value.archiveSha256) || !Number.isSafeInteger(value.archiveByteSize) || Number(value.archiveByteSize) < 1 || Number(value.archiveByteSize) > PRIVATE_PUBLICATION_MAX_BYTES)
94266
94607
  return bad();
@@ -94505,12 +94846,12 @@ class RemotePrivatePublicationsClient {
94505
94846
  previous = view;
94506
94847
  if (!["queued", "verifying"].includes(view.state) || Date.now() >= until)
94507
94848
  return view;
94508
- await new Promise((resolve23) => {
94849
+ await new Promise((resolve25) => {
94509
94850
  const timer = setTimeout(done, Math.min(1000, until - Date.now()));
94510
94851
  function done() {
94511
94852
  clearTimeout(timer);
94512
94853
  options.signal?.removeEventListener("abort", done);
94513
- resolve23();
94854
+ resolve25();
94514
94855
  }
94515
94856
  options.signal?.addEventListener("abort", done, { once: true });
94516
94857
  });
@@ -94743,19 +95084,19 @@ class RemoteSkillsAuthClient {
94743
95084
  }
94744
95085
  // src/lib/private-publication-recovery.ts
94745
95086
  import { constants as constants16, closeSync as closeSync19, fsyncSync as fsyncSync7, fstatSync as fstatSync19, lstatSync as lstatSync27, mkdirSync as mkdirSync15, openSync as openSync19, readSync as readSync13, realpathSync as realpathSync16, renameSync as renameSync7, unlinkSync as unlinkSync6, writeFileSync as writeFileSync11 } from "fs";
94746
- import { dirname as dirname28, isAbsolute as isAbsolute23, join as join43, resolve as resolve23 } from "path";
95087
+ import { dirname as dirname29, isAbsolute as isAbsolute25, join as join43, resolve as resolve25 } from "path";
94747
95088
  import { randomUUID as randomUUID12 } from "crypto";
94748
95089
  var fail2 = () => {
94749
95090
  throw new PrivatePublicationError("PUBLICATION_RECOVERY_INVALID", "The recovery directory is invalid or changed. Preserve it and inspect the existing intent; do not start a replacement automatically.");
94750
95091
  };
94751
95092
  function safeDirectory(directory) {
94752
- if (!isAbsolute23(directory) || directory !== resolve23(directory) || realpathSync16(directory) !== directory)
95093
+ if (!isAbsolute25(directory) || directory !== resolve25(directory) || realpathSync16(directory) !== directory)
94753
95094
  return fail2();
94754
- for (let path2 = directory;; path2 = dirname28(path2)) {
95095
+ for (let path2 = directory;; path2 = dirname29(path2)) {
94755
95096
  const stat2 = lstatSync27(path2);
94756
95097
  if (!stat2.isDirectory() || stat2.isSymbolicLink())
94757
95098
  return fail2();
94758
- if (path2 === dirname28(path2))
95099
+ if (path2 === dirname29(path2))
94759
95100
  break;
94760
95101
  }
94761
95102
  const own2 = lstatSync27(directory);
@@ -94887,11 +95228,11 @@ async function preparePrivatePublication(client2, sourceDirectory, recoveryDirec
94887
95228
  phase: "prepared",
94888
95229
  intent: null
94889
95230
  };
94890
- if (!isAbsolute23(recoveryDirectory) || resolve23(recoveryDirectory) !== recoveryDirectory || realpathSync16(dirname28(recoveryDirectory)) !== dirname28(recoveryDirectory))
95231
+ if (!isAbsolute25(recoveryDirectory) || resolve25(recoveryDirectory) !== recoveryDirectory || realpathSync16(dirname29(recoveryDirectory)) !== dirname29(recoveryDirectory))
94891
95232
  return fail2();
94892
95233
  mkdirSync15(recoveryDirectory, { mode: 448 });
94893
95234
  safeDirectory(recoveryDirectory);
94894
- const parent = openSync19(dirname28(recoveryDirectory), constants16.O_RDONLY | constants16.O_NOFOLLOW);
95235
+ const parent = openSync19(dirname29(recoveryDirectory), constants16.O_RDONLY | constants16.O_NOFOLLOW);
94895
95236
  try {
94896
95237
  fsyncSync7(parent);
94897
95238
  } finally {