@hasna/skills 0.10.50 → 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.50",
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",
@@ -38426,7 +38445,8 @@ var MEASURED_CODEX_CAPABILITIES = {
38426
38445
  "codex-cli 0.158.0": ["hooks"],
38427
38446
  "codex-cli 0.159.0": ["hooks"],
38428
38447
  "codex-cli 0.159.2": ["hooks", "qualified-skill-catalog"],
38429
- "codex-cli 0.160.0": ["hooks", "qualified-skill-catalog"]
38448
+ "codex-cli 0.160.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"],
38449
+ "codex-cli 0.160.1": ["hooks", "qualified-skill-catalog", "installed-plugin-review"]
38430
38450
  };
38431
38451
  function supportsCodexNativeCapability(version, capability) {
38432
38452
  return typeof version === "string" && Object.hasOwn(MEASURED_CODEX_CAPABILITIES, version) && MEASURED_CODEX_CAPABILITIES[version].includes(capability);
@@ -39027,6 +39047,7 @@ function reviewedCodexPluginCapabilitiesUnchanged(cache, controls, read, rules)
39027
39047
  function reviewCodexPluginControls(catalog, documents, cache, cwd, read, rules, pluginSettings, plannedRules, denials = []) {
39028
39048
  if (!supportsCodexNativeCapability(catalog?.version, "qualified-skill-catalog") || catalog.cwd !== cwd)
39029
39049
  refuse3();
39050
+ const installedPluginReview = supportsCodexNativeCapability(catalog.version, "installed-plugin-review");
39030
39051
  if (!Array.isArray(denials) || denials.length > 4096 || new Set(denials.map((item) => item?.path)).size !== denials.length || denials.some((item) => !item || Object.keys(item).sort().join(",") !== "name,path,sha256" || typeof item.name !== "string" || typeof item.path !== "string" || !/^[a-f0-9]{64}$/.test(item.sha256)))
39031
39052
  refuse3();
39032
39053
  const usedDenials = new Set;
@@ -39058,7 +39079,7 @@ function reviewCodexPluginControls(catalog, documents, cache, cwd, read, rules,
39058
39079
  if (listed.length > 1)
39059
39080
  refuse3();
39060
39081
  const installed = installedPlugins.filter((plugin) => plugin.id === expectedPluginId && plugin.name === pluginName);
39061
- if (catalog.version === "codex-cli 0.160.0" && installed.length === 1 && installed[0].installed && installed[0].localVersion === basename4(located.root) && installed[0].sourceType === "local" && codexPluginSourceIsConfigControlled(installed[0])) {
39082
+ if (installedPluginReview && installed.length === 1 && installed[0].installed && installed[0].localVersion === basename4(located.root) && installed[0].sourceType === "local" && codexPluginSourceIsConfigControlled(installed[0])) {
39062
39083
  const plugin = installed[0], input = { pluginId: expectedPluginId, namespace: located.namespace, pluginParent: located.pluginParent, sourceRoot: plugin.sourcePath, sourceSha256: plugin.sourceSha256 };
39063
39084
  if (input.sourceRoot !== located.root && !input.sourceRoot.startsWith(cache + sep3) && (lstatSync7(input.sourceRoot, { throwIfNoEntry: false }) || documents.some((path) => path.startsWith(input.sourceRoot + sep3)))) {
39064
39085
  if (skills.some((skill) => skill.path === input.sourceRoot || skill.path.startsWith(input.sourceRoot + sep3)) || !sourceInputUnchanged(input, cache, read))
@@ -39067,7 +39088,7 @@ function reviewCodexPluginControls(catalog, documents, cache, cwd, read, rules,
39067
39088
  }
39068
39089
  }
39069
39090
  const settings = pluginSettings && typeof pluginSettings === "object" && !Array.isArray(pluginSettings) ? pluginSettings : undefined;
39070
- if (catalog.version === "codex-cli 0.160.0" && !listed.length && !skills.some((skill) => skill.pluginId === expectedPluginId) && installed.length === 1 && installed[0].installed && !installed[0].enabled && codexPluginSourceIsConfigControlled(installed[0]) && settings && Object.hasOwn(settings, expectedPluginId) && settings[expectedPluginId]?.enabled === false) {
39091
+ if (installedPluginReview && !listed.length && !skills.some((skill) => skill.pluginId === expectedPluginId) && installed.length === 1 && installed[0].installed && !installed[0].enabled && codexPluginSourceIsConfigControlled(installed[0]) && settings && Object.hasOwn(settings, expectedPluginId) && settings[expectedPluginId]?.enabled === false) {
39071
39092
  if (!Array.isArray(rules))
39072
39093
  refuse3();
39073
39094
  const exactPathDeny = rules.some((rule) => rule?.path === document && rule?.enabled === false);
@@ -39100,12 +39121,12 @@ function reviewCodexPluginControls(catalog, documents, cache, cwd, read, rules,
39100
39121
  const exactPathDeny = Array.isArray(rules) && rules.some((rule) => rule?.path === document && rule?.enabled === false);
39101
39122
  const nativeSkill = { name: parsed.name, path: document, pluginId: expectedPluginId, enabled: true };
39102
39123
  const denial = denials.find((item) => item.path === document);
39103
- const explicitDeny = denial !== undefined && remotePluginId !== undefined && catalog.version === "codex-cli 0.160.0" && denial.name === parsed.name && denial.sha256 === createHash8("sha256").update(read(document)).digest("hex") && Array.isArray(rules) && !rules.some((rule) => (rule?.path === document || typeof rule?.name === "string" && rule.name.trim() === parsed.name) && rule.enabled !== false) && Array.isArray(plannedRules) && plannedRules.some((rule) => rule?.path === document && rule.enabled === false);
39124
+ const explicitDeny = denial !== undefined && remotePluginId !== undefined && installedPluginReview && denial.name === parsed.name && denial.sha256 === createHash8("sha256").update(read(document)).digest("hex") && Array.isArray(rules) && !rules.some((rule) => (rule?.path === document || typeof rule?.name === "string" && rule.name.trim() === parsed.name) && rule.enabled !== false) && Array.isArray(plannedRules) && plannedRules.some((rule) => rule?.path === document && rule.enabled === false);
39104
39125
  if (denial && !explicitDeny)
39105
39126
  refuse3();
39106
39127
  if (explicitDeny)
39107
39128
  usedDenials.add(document);
39108
- const plannedPathDeny = catalog.version === "codex-cli 0.160.0" && remotePluginId !== undefined && Array.isArray(rules) && rules.some((rule) => typeof rule?.name === "string" && rule.name.trim() === parsed.name && rule.enabled === false) && !rules.some((rule) => (rule?.path === document || typeof rule?.name === "string" && rule.name.trim() === parsed.name) && rule.enabled !== false) && Array.isArray(plannedRules) && plannedRules.some((rule) => rule?.path === document && rule.enabled === false) && isCodexNativeSkillDisabled(nativeSkill, plannedRules);
39129
+ const plannedPathDeny = installedPluginReview && remotePluginId !== undefined && Array.isArray(rules) && rules.some((rule) => typeof rule?.name === "string" && rule.name.trim() === parsed.name && rule.enabled === false) && !rules.some((rule) => (rule?.path === document || typeof rule?.name === "string" && rule.name.trim() === parsed.name) && rule.enabled !== false) && Array.isArray(plannedRules) && plannedRules.some((rule) => rule?.path === document && rule.enabled === false) && isCodexNativeSkillDisabled(nativeSkill, plannedRules);
39109
39130
  if (!explicitDeny && (!exactPathDeny && !plannedPathDeny || !isCodexNativeSkillDisabled(nativeSkill, rules)))
39110
39131
  refuse3();
39111
39132
  }
@@ -40276,10 +40297,10 @@ var NATIVE_SKILL_ROOTS = [
40276
40297
  ];
40277
40298
 
40278
40299
  // src/lib/agent-integration.ts
40279
- import { createHash as createHash24, randomUUID as randomUUID4 } from "crypto";
40300
+ import { createHash as createHash25, randomUUID as randomUUID4 } from "crypto";
40280
40301
  import { isDeepStrictEqual as isDeepStrictEqual8 } from "util";
40281
- 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";
40282
- 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";
40283
40304
  import { homedir as homedir3 } from "os";
40284
40305
 
40285
40306
  // src/lib/managed-policy.ts
@@ -40287,7 +40308,202 @@ import { closeSync as closeSync11, constants as constants8, fstatSync as fstatSy
40287
40308
  import { join as join15 } from "path";
40288
40309
 
40289
40310
  // src/lib/agent-policy-limits.ts
40290
- 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
40291
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 });
40292
40508
  function object4(value) {
40293
40509
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
@@ -40341,7 +40557,7 @@ function assertAgentPolicyCollections(policy) {
40341
40557
  text(control.pluginId, 1024);
40342
40558
  text(control.namespace, 64);
40343
40559
  text(control.pluginParent);
40344
- 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));
40345
40561
  if (control.remotePluginId !== undefined)
40346
40562
  requireBound(typeof control.remotePluginId === "string" && /^[A-Za-z0-9_~-]{1,1024}$/.test(control.remotePluginId));
40347
40563
  if (control.skillsOnly !== undefined)
@@ -40353,16 +40569,24 @@ function assertAgentPolicyCollections(policy) {
40353
40569
  }
40354
40570
  if (bridge.codexInactivePlugins !== undefined) {
40355
40571
  const controls = array(bridge.codexInactivePlugins, 4096), ids = new Set;
40356
- requireBound(controls.length === 0 || object4(bridge.codexPluginSkillReview) && bridge.codexPluginSkillReview.version === "codex-cli 0.160.0" && typeof bridge.codexPluginSkillReview.catalogSha256 === "string" && /^[a-f0-9]{64}$/.test(bridge.codexPluginSkillReview.catalogSha256));
40572
+ requireBound(controls.length === 0 || object4(bridge.codexPluginSkillReview) && supportsCodexNativeCapability(bridge.codexPluginSkillReview.version, "installed-plugin-review") && typeof bridge.codexPluginSkillReview.catalogSha256 === "string" && /^[a-f0-9]{64}$/.test(bridge.codexPluginSkillReview.catalogSha256));
40357
40573
  for (const control of controls) {
40358
40574
  requireBound(object4(control) && Object.keys(control).every((key) => ["pluginId", "namespace", "pluginParent", "sourceType", "sourceSha256"].includes(key)));
40359
40575
  text(control.pluginId, 1024);
40360
40576
  text(control.namespace, 64);
40361
40577
  text(control.pluginParent);
40362
- 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));
40363
40579
  ids.add(control.pluginId);
40364
40580
  }
40365
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
+ }
40366
40590
  if (bridge.disabledBuiltins !== undefined)
40367
40591
  for (const builtin of array(bridge.disabledBuiltins, AGENT_POLICY_LIMITS.builtinNames)) {
40368
40592
  requireBound(object4(builtin));
@@ -40388,11 +40612,11 @@ function assertAgentPolicyCollections(policy) {
40388
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);
40389
40613
  for (const root of roots) {
40390
40614
  text(root);
40391
- requireBound(isAbsolute8(root) && resolve7(root) === root);
40615
+ requireBound(isAbsolute9(root) && resolve8(root) === root);
40392
40616
  }
40393
40617
  for (const parent of parents2) {
40394
40618
  text(parent);
40395
- requireBound(isAbsolute8(parent) && resolve7(parent) === parent);
40619
+ requireBound(isAbsolute9(parent) && resolve8(parent) === parent);
40396
40620
  }
40397
40621
  for (const directory of array(proof.directories, AGENT_POLICY_LIMITS.discoveryDirectories)) {
40398
40622
  requireBound(object4(directory));
@@ -40405,14 +40629,14 @@ function assertAgentPolicyCollections(policy) {
40405
40629
  }
40406
40630
  if (value.codexInstallationInputs !== undefined) {
40407
40631
  const proof = record3(value.codexInstallationInputs, 4), inputs = array(proof.plugins, 4096), ids = new Set;
40408
- requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && proof.version === "codex-cli 0.160.0" && typeof proof.catalogSha256 === "string" && /^[a-f0-9]{64}$/.test(proof.catalogSha256) && inputs.length > 0 && object4(bridge.codexPluginSkillReview) && bridge.codexPluginSkillReview.version === proof.version && bridge.codexPluginSkillReview.catalogSha256 === proof.catalogSha256);
40632
+ requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && supportsCodexNativeCapability(proof.version, "installed-plugin-review") && typeof proof.catalogSha256 === "string" && /^[a-f0-9]{64}$/.test(proof.catalogSha256) && inputs.length > 0 && object4(bridge.codexPluginSkillReview) && bridge.codexPluginSkillReview.version === proof.version && bridge.codexPluginSkillReview.catalogSha256 === proof.catalogSha256);
40409
40633
  for (const input of inputs) {
40410
40634
  requireBound(object4(input) && Object.keys(input).every((key) => ["pluginId", "namespace", "pluginParent", "sourceRoot", "sourceSha256"].includes(key)));
40411
40635
  text(input.pluginId, 1024);
40412
40636
  text(input.namespace, 64);
40413
40637
  text(input.pluginParent);
40414
40638
  text(input.sourceRoot);
40415
- 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));
40416
40640
  ids.add(input.pluginId);
40417
40641
  }
40418
40642
  if (proof.directories !== undefined)
@@ -40429,17 +40653,19 @@ function assertAgentPolicyCollections(policy) {
40429
40653
  text(source.path);
40430
40654
  requireBound(source.sha256 === null || typeof source.sha256 === "string" && /^[a-f0-9]{64}$/.test(source.sha256));
40431
40655
  if (source.hashMode !== undefined)
40432
- 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));
40433
40657
  if (source.hashMode === "claude-plugin-manifest-v1")
40434
- 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);
40435
40659
  if (source.hashMode === "sumi-settings-v1")
40436
- 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");
40437
40661
  if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4"))
40438
- 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");
40439
40663
  if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4"))
40440
- 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");
40441
40665
  if (source.hashMode === "claude-marketplace-registry" || source.hashMode === "claude-marketplace-registry-v2")
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) === "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));
40443
40669
  if (source.hashMode === "claude-plugin-registry") {
40444
40670
  requireBound(agent === "claude");
40445
40671
  const managed = array(source.managedPlugins, 64);
@@ -40454,8 +40680,8 @@ function assertAgentPolicyCollections(policy) {
40454
40680
  if (source.format !== undefined)
40455
40681
  requireBound(["json", "toml", "yaml"].includes(source.format));
40456
40682
  if (source.fields !== undefined)
40457
- for (const field of array(source.fields, AGENT_POLICY_LIMITS.fields))
40458
- text(field, 256);
40683
+ for (const field2 of array(source.fields, AGENT_POLICY_LIMITS.fields))
40684
+ text(field2, 256);
40459
40685
  }
40460
40686
  if (value.directories !== undefined)
40461
40687
  for (const directory of array(value.directories, AGENT_POLICY_LIMITS.discoveryDirectories)) {
@@ -40470,8 +40696,8 @@ function assertAgentPolicyCollections(policy) {
40470
40696
  }
40471
40697
 
40472
40698
  // src/lib/managed-policy.ts
40473
- function refusal(reason = "is unreadable") {
40474
- 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.`);
40475
40701
  }
40476
40702
  function parseManagedSkillPolicy(text2) {
40477
40703
  if (Buffer.byteLength(text2) > AGENT_POLICY_LIMITS.bytes)
@@ -40548,7 +40774,7 @@ function requiresCliSkillLoading(dataDir2 = getDataDirReadOnly()) {
40548
40774
  }
40549
40775
 
40550
40776
  // src/lib/agent-bridge.ts
40551
- import { createHash as createHash12 } from "crypto";
40777
+ import { createHash as createHash13 } from "crypto";
40552
40778
  import { lstatSync as lstatSync10, readFileSync as readFileSync11, readdirSync as readdirSync4 } from "fs";
40553
40779
  import { join as join16 } from "path";
40554
40780
  var CLI_BRIDGE_NAME = "skills-cli";
@@ -40567,7 +40793,7 @@ Use the Skills CLI as the skill authority for this station.
40567
40793
 
40568
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.
40569
40795
  `;
40570
- var CLI_BRIDGE_DIGEST = createHash12("sha256").update(markdown).digest("hex");
40796
+ var CLI_BRIDGE_DIGEST = createHash13("sha256").update(markdown).digest("hex");
40571
40797
  var CLI_BRIDGE_FILES = Object.freeze({
40572
40798
  "SKILL.md": markdown,
40573
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)}
@@ -40591,9 +40817,9 @@ function isOwnedCliBridge(path, expectedPaths) {
40591
40817
  }
40592
40818
 
40593
40819
  // src/lib/agent-discovery.ts
40594
- import { createHash as createHash22 } from "crypto";
40820
+ import { createHash as createHash23 } from "crypto";
40595
40821
  import { lstatSync as lstatSync21, readFileSync as readFileSync15, readdirSync as readdirSync7, realpathSync as realpathSync9 } from "fs";
40596
- 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";
40597
40823
  import { isDeepStrictEqual as isDeepStrictEqual6 } from "util";
40598
40824
 
40599
40825
  // node_modules/yaml/dist/index.js
@@ -40643,7 +40869,7 @@ var $visit = visit.visit;
40643
40869
  var $visitAsync = visit.visitAsync;
40644
40870
 
40645
40871
  // src/lib/agent-hermes.ts
40646
- 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";
40647
40873
  import { lstatSync as lstatSync11, readFileSync as readFileSync12, opendirSync } from "fs";
40648
40874
  var HERMES_OPT_OUT = ".no-bundled-skills";
40649
40875
  var EVENTS = ["pre_llm_call", "pre_tool_call"];
@@ -40681,7 +40907,7 @@ function quoted(value) {
40681
40907
  return `'${value.replace(/'/g, `'\\''`)}'`;
40682
40908
  }
40683
40909
  function hermesHookDefinitions(supervisor) {
40684
- if (!isAbsolute9(supervisor.runtime) || !isAbsolute9(supervisor.path))
40910
+ if (!isAbsolute10(supervisor.runtime) || !isAbsolute10(supervisor.path))
40685
40911
  throw new Error("Expected absolute Hermes supervisor paths");
40686
40912
  const entry = (event) => ({ command: `${quoted(supervisor.runtime)} ${quoted(supervisor.path)} --event ${event}`, timeout: 15, ...event === "pre_tool_call" ? { fail_closed: true } : {} });
40687
40913
  return { pre_llm_call: entry("pre_llm_call"), pre_tool_call: entry("pre_tool_call") };
@@ -40717,16 +40943,16 @@ function assertHermesEnvironment(home) {
40717
40943
  throw new Error(`NATIVE_SKILL_DRIFT: Hermes ${variable} requires a dedicated discovery adapter; unset it before using this adapter`);
40718
40944
  }
40719
40945
  const selected = process.env.HERMES_HOME?.trim();
40720
- if (selected && (!isAbsolute9(selected) || resolve8(selected) !== join17(resolve8(home), ".hermes")))
40946
+ if (selected && (!isAbsolute10(selected) || resolve9(selected) !== join17(resolve9(home), ".hermes")))
40721
40947
  throw new Error("NATIVE_SKILL_DRIFT: custom Hermes homes/profiles require their own reviewed bridge");
40722
40948
  if (process.env.HERMES_ENABLE_PROJECT_PLUGINS?.trim() && !["0", "false", "no", "off"].includes(process.env.HERMES_ENABLE_PROJECT_PLUGINS.trim().toLowerCase()))
40723
40949
  throw new Error("NATIVE_SKILL_DRIFT: Hermes project plugins require a dedicated discovery review");
40724
40950
  }
40725
40951
  function read(path) {
40726
- for (let current = path;; current = dirname8(current)) {
40952
+ for (let current = path;; current = dirname9(current)) {
40727
40953
  if (lstatSync11(current, { throwIfNoEntry: false })?.isSymbolicLink())
40728
40954
  throw new Error("NATIVE_SKILL_DRIFT: symlink Hermes protection input");
40729
- if (dirname8(current) === current)
40955
+ if (dirname9(current) === current)
40730
40956
  break;
40731
40957
  }
40732
40958
  const stat = lstatSync11(path, { throwIfNoEntry: false });
@@ -40740,7 +40966,7 @@ function assertHermesProtection(home, config, command, profile, supervisor) {
40740
40966
  assertHermesEnvironment(home);
40741
40967
  if (read(join17(home, ".hermes", HERMES_OPT_OUT)) === null)
40742
40968
  throw new Error("NATIVE_SKILL_DRIFT: Hermes bundled skill reseeding is not disabled; run skills hook install");
40743
- 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))
40744
40970
  throw new Error("NATIVE_SKILL_DRIFT: Hermes owned supervisor changed; run skills hook install");
40745
40971
  const raw = read(join17(home, ".hermes/shell-hooks-allowlist.json"));
40746
40972
  let trust;
@@ -40766,10 +40992,10 @@ function assertHermesProtection(home, config, command, profile, supervisor) {
40766
40992
  }
40767
40993
  function assertNoHermesLegacyShadow(root) {
40768
40994
  let entries = 0;
40769
- for (let cursor = resolve8(root);; cursor = dirname8(cursor)) {
40995
+ for (let cursor = resolve9(root);; cursor = dirname9(cursor)) {
40770
40996
  if (lstatSync11(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
40771
40997
  throw new Error("NATIVE_SKILL_DRIFT: symlink Hermes legacy discovery root");
40772
- if (dirname8(cursor) === cursor)
40998
+ if (dirname9(cursor) === cursor)
40773
40999
  break;
40774
41000
  }
40775
41001
  function scan(path, depth) {
@@ -40790,10 +41016,10 @@ function assertNoHermesLegacyShadow(root) {
40790
41016
  const hasDescriptor = Boolean(lstatSync11(join17(path, "SKILL.md"), { throwIfNoEntry: false }));
40791
41017
  const directory = opendirSync(path);
40792
41018
  try {
40793
- for (let child = directory.readSync();child; child = directory.readSync()) {
40794
- 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))
40795
41021
  continue;
40796
- scan(join17(path, child.name), depth + 1);
41022
+ scan(join17(path, child2.name), depth + 1);
40797
41023
  }
40798
41024
  } finally {
40799
41025
  directory.closeSync();
@@ -40850,18 +41076,18 @@ if (failed) process.exitCode = 2;
40850
41076
  }
40851
41077
 
40852
41078
  // src/lib/agent-discovery-directories.ts
40853
- import { createHash as createHash13 } from "crypto";
41079
+ import { createHash as createHash14 } from "crypto";
40854
41080
  import { lstatSync as lstatSync12, opendirSync as opendirSync2 } from "fs";
40855
- import { dirname as dirname9, isAbsolute as isAbsolute10, join as join18, resolve as resolve9 } from "path";
40856
- 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) {
40857
41083
  if (!value)
40858
41084
  throw new Error(message);
40859
41085
  }
40860
41086
  function safe(path) {
40861
- 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");
40862
- for (let cursor = path;; cursor = dirname9(cursor)) {
40863
- need4(!lstatSync12(cursor, { throwIfNoEntry: false })?.isSymbolicLink(), "Refusing symlink native discovery directory");
40864
- 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)
40865
41091
  break;
40866
41092
  }
40867
41093
  }
@@ -40875,45 +41101,45 @@ function capture(path, budget2, excludedRoots, omittedRoots = [], rows) {
40875
41101
  const root = lstatSync12(path, { throwIfNoEntry: false });
40876
41102
  if (!root)
40877
41103
  return { path, sha256: null };
40878
- need4(root.isDirectory(), "Unsupported native discovery directory input");
40879
- const hash2 = createHash13("sha256");
41104
+ need5(root.isDirectory(), "Unsupported native discovery directory input");
41105
+ const hash2 = createHash14("sha256");
40880
41106
  function walk2(current, relative5, before, depth) {
40881
- need4(depth <= 64, "Native discovery directory depth limit exceeded");
41107
+ need5(depth <= 64, "Native discovery directory depth limit exceeded");
40882
41108
  const names = [], directory = opendirSync2(current);
40883
41109
  try {
40884
41110
  for (let entry = directory.readSync();entry; entry = directory.readSync()) {
40885
- 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");
40886
41112
  names.push(entry.name);
40887
41113
  }
40888
41114
  } finally {
40889
41115
  directory.closeSync();
40890
41116
  }
40891
- 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");
40892
41118
  for (const name of names.sort()) {
40893
- const child = join18(current, name), childRelative = relative5 ? `${relative5}/${name}` : name;
40894
- if (omittedRoots.includes(child))
41119
+ const child2 = join18(current, name), childRelative = relative5 ? `${relative5}/${name}` : name;
41120
+ if (omittedRoots.includes(child2))
40895
41121
  continue;
40896
- need4(child.length <= AGENT_POLICY_LIMITS.pathCharacters, "Native discovery directory path limit exceeded");
40897
- const stat = lstatSync12(child);
40898
- 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");
40899
41125
  const row = JSON.stringify([childRelative, stat.isDirectory() ? "directory" : "file"]) + `
40900
41126
  `;
40901
41127
  budget2.bytes += Buffer.byteLength(row);
40902
- 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");
40903
41129
  hash2.update(row);
40904
41130
  rows?.push(row);
40905
- if (stat.isDirectory() && !excludedRoots.includes(child))
40906
- walk2(child, childRelative, stat, depth + 1);
41131
+ if (stat.isDirectory() && !excludedRoots.includes(child2))
41132
+ walk2(child2, childRelative, stat, depth + 1);
40907
41133
  }
40908
- 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");
40909
41135
  }
40910
41136
  walk2(path, "", root, 0);
40911
41137
  safe(path);
40912
41138
  return { path, sha256: hash2.digest("hex") };
40913
41139
  }
40914
41140
  function captureDiscoveryDirectoryProjection(paths, omittedRoots) {
40915
- need4(Array.isArray(paths) && paths.length <= AGENT_POLICY_LIMITS.discoveryDirectories && new Set(paths).size === paths.length, "Invalid projected discovery directory collection");
40916
- 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");
40917
41143
  for (const root of omittedRoots)
40918
41144
  safe(root);
40919
41145
  const budget2 = { entries: 0, bytes: 0 };
@@ -40923,62 +41149,62 @@ function captureDiscoveryDirectoryProjection(paths, omittedRoots) {
40923
41149
  });
40924
41150
  }
40925
41151
  function verifyDiscoveryDirectoryProjection(directories, omittedRoots) {
40926
- 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");
40927
41153
  let count = 0, bytes = 0;
40928
41154
  const expected = directories.map((directory) => {
40929
41155
  safe(directory.path);
40930
- need4(Array.isArray(directory.entries), "Missing reviewed directory membership inventory");
40931
- const hash2 = createHash13("sha256");
41156
+ need5(Array.isArray(directory.entries), "Missing reviewed directory membership inventory");
41157
+ const hash2 = createHash14("sha256");
40932
41158
  const kept = [];
40933
41159
  for (const row of directory.entries) {
40934
- 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");
40935
41161
  bytes += Buffer.byteLength(row);
40936
- 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");
40937
41163
  const value = JSON.parse(row);
40938
- 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) + `
40939
41165
  `, "Invalid reviewed directory member");
40940
41166
  hash2.update(row);
40941
41167
  const path = join18(directory.path, value[0]);
40942
41168
  if (!omittedRoots.some((root) => path === root || path.startsWith(root + "/")))
40943
41169
  kept.push(row);
40944
41170
  }
40945
- 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");
40946
41172
  const absent = omittedRoots.some((root) => directory.path === root || directory.path.startsWith(root + "/"));
40947
- 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") };
40948
41174
  });
40949
41175
  const current = captureDiscoveryDirectoryProjection(directories.map((item) => item.path), omittedRoots);
40950
- 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");
40951
41177
  }
40952
41178
  function captureDiscoveryDirectories(paths, excludedRoots = []) {
40953
- 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");
40954
41180
  const budget2 = { entries: 0, bytes: 0 };
40955
41181
  for (const root of excludedRoots)
40956
41182
  safe(root);
40957
41183
  return paths.map((path) => capture(path, budget2, excludedRoots));
40958
41184
  }
40959
41185
  function verifyDiscoveryDirectories(directories, excludedRoots = []) {
40960
- 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");
40961
41187
  for (const directory of directories)
40962
- 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");
40963
41189
  const current = captureDiscoveryDirectories(directories.map((directory) => directory.path), excludedRoots);
40964
41190
  for (let i = 0;i < directories.length; i++)
40965
- 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}`);
40966
41192
  }
40967
41193
 
40968
41194
  // src/lib/agent-discovery-bytes.ts
40969
- import { createHash as createHash14 } from "crypto";
41195
+ import { createHash as createHash15 } from "crypto";
40970
41196
  import { closeSync as closeSync12, constants as constants9, fstatSync as fstatSync12, lstatSync as lstatSync13, openSync as openSync12, readSync as readSync7 } from "fs";
40971
- 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";
40972
41198
  function discoveryByteBudget() {
40973
41199
  return { remaining: AGENT_POLICY_LIMITS.discoveryRawTotalBytes };
40974
41200
  }
40975
41201
  function safe2(path) {
40976
- 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"))
40977
41203
  throw new Error("Expected a canonical absolute raw discovery path");
40978
- for (let cursor = path;; cursor = dirname10(cursor)) {
41204
+ for (let cursor = path;; cursor = dirname11(cursor)) {
40979
41205
  if (lstatSync13(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
40980
41206
  throw new Error("Refusing symlink raw discovery input");
40981
- if (dirname10(cursor) === cursor)
41207
+ if (dirname11(cursor) === cursor)
40982
41208
  break;
40983
41209
  }
40984
41210
  }
@@ -40997,7 +41223,7 @@ function hashRawDiscoveryFile(path, budget2, changes) {
40997
41223
  if (bytes > AGENT_POLICY_LIMITS.discoveryRawSourceBytes)
40998
41224
  throw new Error("Raw discovery file byte limit exceeded");
40999
41225
  consume(budget2, bytes);
41000
- return createHash14("sha256").update(text2).digest("hex");
41226
+ return createHash15("sha256").update(text2).digest("hex");
41001
41227
  }
41002
41228
  const initial = lstatSync13(path, { throwIfNoEntry: false });
41003
41229
  if (!initial)
@@ -41011,7 +41237,7 @@ function hashRawDiscoveryFile(path, budget2, changes) {
41011
41237
  const opened = fstatSync12(fd);
41012
41238
  if (!opened.isFile() || !same2(initial, opened))
41013
41239
  throw new Error("Raw discovery input changed during open");
41014
- const hash2 = createHash14("sha256"), buffer = Buffer.alloc(64 * 1024);
41240
+ const hash2 = createHash15("sha256"), buffer = Buffer.alloc(64 * 1024);
41015
41241
  let bytes = 0;
41016
41242
  while (true) {
41017
41243
  const count = readSync7(fd, buffer, 0, Math.min(buffer.length, AGENT_POLICY_LIMITS.discoveryRawSourceBytes - bytes + 1), null);
@@ -41034,9 +41260,9 @@ function hashRawDiscoveryFile(path, budget2, changes) {
41034
41260
  }
41035
41261
 
41036
41262
  // src/lib/agent-discovery-path-bytes.ts
41037
- import { createHash as createHash15 } from "crypto";
41263
+ import { createHash as createHash16 } from "crypto";
41038
41264
  import { lstatSync as lstatSync14, readlinkSync as readlinkSync4 } from "fs";
41039
- 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";
41040
41266
  function identity4(stat, mutable = false) {
41041
41267
  return {
41042
41268
  dev: String(stat.dev),
@@ -41047,12 +41273,12 @@ function identity4(stat, mutable = false) {
41047
41273
  ...mutable ? { size: String(stat.size), mtimeNs: String(stat.mtimeNs), ctimeNs: String(stat.ctimeNs) } : {}
41048
41274
  };
41049
41275
  }
41050
- function canonical4(path) {
41051
- 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)
41052
41278
  throw new Error("Expected a canonical absolute discovery path");
41053
41279
  }
41054
41280
  function trace(path) {
41055
- canonical4(path);
41281
+ canonical5(path);
41056
41282
  const rows = [], paths = [];
41057
41283
  let metadataBytes = 0, steps = 0, links = 0, cursor = parse3(path).root, pending = path.slice(cursor.length).split(sep5);
41058
41284
  function record4(path2, row) {
@@ -41077,7 +41303,7 @@ function trace(path) {
41077
41303
  if (!component || component === ".")
41078
41304
  continue;
41079
41305
  if (component === "..") {
41080
- cursor = dirname11(cursor);
41306
+ cursor = dirname12(cursor);
41081
41307
  continue;
41082
41308
  }
41083
41309
  const candidate = join19(cursor, component);
@@ -41097,11 +41323,11 @@ function trace(path) {
41097
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)))
41098
41324
  throw new Error("Discovery link changed during read");
41099
41325
  record4(candidate, { type: "link", target, ...identity4(stat, true) });
41100
- if (isAbsolute12(target)) {
41326
+ if (isAbsolute13(target)) {
41101
41327
  cursor = parse3(target).root;
41102
41328
  root();
41103
41329
  }
41104
- const remainder = isAbsolute12(target) ? target.slice(parse3(target).root.length) : target;
41330
+ const remainder = isAbsolute13(target) ? target.slice(parse3(target).root.length) : target;
41105
41331
  pending = [...remainder.split(sep5), ...pending];
41106
41332
  if (pending.length + steps > AGENT_POLICY_LIMITS.discoveryPathSteps)
41107
41333
  throw new Error("Discovery path step limit exceeded");
@@ -41144,15 +41370,15 @@ function hashDiscoveryPathFile(path, budget2, changes) {
41144
41370
  const after = trace(path);
41145
41371
  if (JSON.stringify(before.rows) !== JSON.stringify(after.rows) || before.file !== after.file)
41146
41372
  throw new Error("Discovery path input changed during read");
41147
- 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");
41148
41374
  }
41149
41375
 
41150
41376
  // src/lib/claude-plugin-manifest-witness.ts
41151
- import { createHash as createHash16 } from "crypto";
41377
+ import { createHash as createHash17 } from "crypto";
41152
41378
  var CLAUDE_PLUGIN_MANIFEST_LIMITS = Object.freeze({ bytes: 1024 * 1024, depth: 32, nodes: 65536, stringCharacters: 16384 });
41153
- function requireValue(value, reason) {
41379
+ function requireValue(value, reason2) {
41154
41380
  if (!value)
41155
- throw new Error("Claude plugin manifest " + reason);
41381
+ throw new Error("Claude plugin manifest " + reason2);
41156
41382
  }
41157
41383
  function parse4(text2) {
41158
41384
  requireValue(Buffer.byteLength(text2, "utf8") <= CLAUDE_PLUGIN_MANIFEST_LIMITS.bytes, "exceeds its byte limit");
@@ -41228,7 +41454,7 @@ function parse4(text2) {
41228
41454
  requireValue(at === text2.length && root.kind === "object", "requires a JSON object without trailing content");
41229
41455
  return root;
41230
41456
  }
41231
- function canonical5(value) {
41457
+ function canonical6(value) {
41232
41458
  if (value.kind === "string")
41233
41459
  return JSON.stringify(value.value);
41234
41460
  if (value.kind === "number")
@@ -41236,19 +41462,19 @@ function canonical5(value) {
41236
41462
  if (value.kind === "literal")
41237
41463
  return value.value;
41238
41464
  if (value.kind === "array")
41239
- return "[" + value.items.map(canonical5).join(",") + "]";
41240
- 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(",") + "}";
41241
41467
  }
41242
41468
  var DESCRIPTIVE_FIELDS = new Set(["description", "version", "author", "homepage", "repository", "license", "keywords"]);
41243
- function validateText(value, field) {
41244
- 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");
41245
41471
  }
41246
41472
  function validateDescriptiveFields(manifest) {
41247
41473
  const values = new Map(manifest.entries);
41248
- for (const field of ["description", "version", "homepage", "license"]) {
41249
- const value = values.get(field);
41474
+ for (const field2 of ["description", "version", "homepage", "license"]) {
41475
+ const value = values.get(field2);
41250
41476
  if (value !== undefined)
41251
- validateText(value, field);
41477
+ validateText(value, field2);
41252
41478
  }
41253
41479
  const author = values.get("author");
41254
41480
  if (author !== undefined) {
@@ -41273,10 +41499,10 @@ function hashClaudePluginManifest(text2) {
41273
41499
  const manifest = parse4(text2);
41274
41500
  validateDescriptiveFields(manifest);
41275
41501
  const discovery = { kind: "object", entries: manifest.entries.filter(([key]) => !DESCRIPTIVE_FIELDS.has(key)) };
41276
- return createHash16("sha256").update(canonical5(discovery)).digest("hex");
41502
+ return createHash17("sha256").update(canonical6(discovery)).digest("hex");
41277
41503
  }
41278
41504
  function projectReviewedClaudePluginManifest(text2, reviewedSha256) {
41279
- 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) {
41280
41506
  throw new Error("Reviewed Claude plugin manifest changed before semantic projection");
41281
41507
  }
41282
41508
  return hashClaudePluginManifest(text2);
@@ -41284,14 +41510,14 @@ function projectReviewedClaudePluginManifest(text2, reviewedSha256) {
41284
41510
 
41285
41511
  // src/lib/plugin-discovery.ts
41286
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";
41287
- 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";
41288
41514
 
41289
41515
  // src/lib/plugin-admission.ts
41290
41516
  import { homedir as homedir2 } from "os";
41291
- 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";
41292
41518
 
41293
41519
  // src/lib/plugin-projection.ts
41294
- import { createHash as createHash17 } from "crypto";
41520
+ import { createHash as createHash18 } from "crypto";
41295
41521
  import { posix as posix2 } from "path";
41296
41522
  var PLUGIN_PROJECTION_MANIFEST = "plugin-projection.json";
41297
41523
  var PLUGIN_PROJECTION_LIMITS = Object.freeze({ files: 1024, bytes: 64 * 1024 * 1024, fileBytes: 16 * 1024 * 1024, metadataBytes: 512 * 1024, registrations: 64, history: 128 });
@@ -41302,7 +41528,7 @@ function pluginNeed(value, message) {
41302
41528
  if (!value)
41303
41529
  pluginRefusal(message);
41304
41530
  }
41305
- var pluginHash = (bytes) => createHash17("sha256").update(bytes).digest("hex");
41531
+ var pluginHash = (bytes) => createHash18("sha256").update(bytes).digest("hex");
41306
41532
  function pluginObject(value) {
41307
41533
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
41308
41534
  }
@@ -41490,9 +41716,9 @@ function buildPluginProjection(entries) {
41490
41716
  }
41491
41717
 
41492
41718
  // src/lib/plugin-projection-store.ts
41493
- import { createHash as createHash18, randomUUID as randomUUID3 } from "crypto";
41719
+ import { createHash as createHash19, randomUUID as randomUUID3 } from "crypto";
41494
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";
41495
- 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";
41496
41722
  var READ_FLAGS = constants10.O_RDONLY | constants10.O_NOFOLLOW | constants10.O_NONBLOCK;
41497
41723
  var WRITE_FLAGS = constants10.O_WRONLY | constants10.O_CREAT | constants10.O_EXCL | constants10.O_NOFOLLOW | constants10.O_NONBLOCK;
41498
41724
  var uid = () => typeof process.getuid === "function" ? BigInt(process.getuid()) : undefined;
@@ -41506,8 +41732,8 @@ function stat(path) {
41506
41732
  return pluginRefusal("Cannot inspect plugin filesystem entry");
41507
41733
  }
41508
41734
  }
41509
- function canonical6(path) {
41510
- 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");
41511
41737
  }
41512
41738
  function owner(stats, system = false) {
41513
41739
  const current = uid();
@@ -41517,8 +41743,8 @@ function same3(left, right, identityOnly = false) {
41517
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");
41518
41744
  }
41519
41745
  function ancestors(path, create = false) {
41520
- canonical6(path);
41521
- const result = [], parent = dirname12(path), filesystemRoot = parse6(parent).root;
41746
+ canonical7(path);
41747
+ const result = [], parent = dirname13(path), filesystemRoot = parse6(parent).root;
41522
41748
  let current = filesystemRoot;
41523
41749
  for (const segment of ["", ...parent.slice(filesystemRoot.length).split("/").filter(Boolean)]) {
41524
41750
  if (segment)
@@ -41546,7 +41772,7 @@ function verifyAncestors(chain, identityOnly = true) {
41546
41772
  }
41547
41773
  function privateParent(path) {
41548
41774
  const chain = ancestors(path, true), parent = chain.at(-1);
41549
- pluginNeed(parent && parent.path === dirname12(path), "Plugin storage parent is unavailable");
41775
+ pluginNeed(parent && parent.path === dirname13(path), "Plugin storage parent is unavailable");
41550
41776
  owner(parent.stat);
41551
41777
  pluginNeed((parent.stat.mode & 0o7777n) === 0o700n, "Plugin storage parent must have mode 0700");
41552
41778
  return chain;
@@ -41832,7 +42058,7 @@ function pluginExecutableDigest(path) {
41832
42058
  const opened = fstatSync13(fd, { bigint: true });
41833
42059
  same3(before, opened);
41834
42060
  fileShape(opened, maximum, "executable");
41835
- const hash2 = createHash18("sha256"), buffer = new Uint8Array(64 * 1024);
42061
+ const hash2 = createHash19("sha256"), buffer = new Uint8Array(64 * 1024);
41836
42062
  let remaining = Number(opened.size);
41837
42063
  while (remaining > 0) {
41838
42064
  const count = readSync8(fd, buffer, 0, Math.min(buffer.byteLength, remaining), null);
@@ -41857,7 +42083,7 @@ function pluginExecutableDigest(path) {
41857
42083
 
41858
42084
  // src/lib/skill-validation.ts
41859
42085
  import { existsSync as existsSync5, lstatSync as lstatSync16, readFileSync as readFileSync14, readdirSync as readdirSync6, statSync as statSync6 } from "fs";
41860
- 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";
41861
42087
 
41862
42088
  // src/lib/hosted-skill-set.ts
41863
42089
  import { existsSync as existsSync4, readFileSync as readFileSync13, readdirSync as readdirSync5, statSync as statSync5 } from "fs";
@@ -41961,7 +42187,7 @@ function sortMessages(messages) {
41961
42187
  return [...messages].sort((a, b) => a.code.localeCompare(b.code) || a.message.localeCompare(b.message));
41962
42188
  }
41963
42189
  function isSafeRelativePath(value) {
41964
- if (!value.trim() || isAbsolute14(value))
42190
+ if (!value.trim() || isAbsolute15(value))
41965
42191
  return false;
41966
42192
  const normalized = normalize3(value).replace(/\\/g, "/");
41967
42193
  return normalized !== ".." && !normalized.startsWith("../") && !normalized.includes("/../");
@@ -42326,7 +42552,7 @@ function validatePluginTarget(value) {
42326
42552
  for (const registration of value.registrations) {
42327
42553
  pluginKeys(registration, ["scope", "projectPath"]);
42328
42554
  pluginNeed(registration.scope === "user" || registration.scope === "project", "Unsupported plugin registration scope");
42329
- 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");
42330
42556
  const key = JSON.stringify([registration.scope, registration.projectPath]);
42331
42557
  pluginNeed(!scopes.has(key), "Duplicate plugin registration scope");
42332
42558
  scopes.add(key);
@@ -42334,7 +42560,7 @@ function validatePluginTarget(value) {
42334
42560
  for (const key of ["native", "resolver"]) {
42335
42561
  pluginKeys(value[key], key === "native" ? ["version", "executable", "digest"] : ["executable", "digest"]);
42336
42562
  pluginText(value[key].executable);
42337
- 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");
42338
42564
  pluginDigest(value[key].digest);
42339
42565
  }
42340
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)");
@@ -42479,14 +42705,14 @@ function validatePlan(value) {
42479
42705
  pluginNeed(observedEvidenceDigest(plan.observation) === plan.evidenceDigest, "Plugin receipt observed evidence changed");
42480
42706
  pluginNeed(identityDigest(plan) === plan.planDigest, "Plugin receipt immutable identity changed");
42481
42707
  }
42482
- var quote = (value) => `'${value.replaceAll("'", "'\\''")}'`;
42708
+ var quote2 = (value) => `'${value.replaceAll("'", "'\\''")}'`;
42483
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"';
42484
42710
  function pluginResolverCommand(binding) {
42485
- 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))}`;
42486
42712
  }
42487
42713
  function root(options) {
42488
42714
  const path = options.storeRoot ?? pluginAdmissionRoot();
42489
- pluginNeed(isAbsolute15(path) && resolve13(path) === path, "Invalid plugin admission store root");
42715
+ pluginNeed(isAbsolute16(path) && resolve14(path) === path, "Invalid plugin admission store root");
42490
42716
  return path;
42491
42717
  }
42492
42718
  function pluginBindingPath(storeRoot, id2) {
@@ -42691,15 +42917,15 @@ function validateManagedPluginWitnesses(value) {
42691
42917
  pluginNeed(typeof item.bindingId === "string" && /^[a-f0-9]{64}$/.test(item.bindingId) && !seen.has(item.bindingId), "Invalid or duplicate managed plugin witness");
42692
42918
  seen.add(item.bindingId);
42693
42919
  pluginText(item.storeRoot);
42694
- 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");
42695
42921
  }
42696
42922
  }
42697
42923
  function safe3(path) {
42698
42924
  pluginText(path);
42699
- pluginNeed(isAbsolute16(path) && resolve14(path) === path, "Invalid plugin registry path");
42700
- 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)) {
42701
42927
  pluginNeed(!lstatSync17(at, { throwIfNoEntry: false })?.isSymbolicLink(), "Plugin registry path traverses a symlink");
42702
- if (at === dirname13(at))
42928
+ if (at === dirname14(at))
42703
42929
  break;
42704
42930
  }
42705
42931
  }
@@ -42749,7 +42975,7 @@ function hashManagedPluginRegistry(path, managed) {
42749
42975
  seen.add(target.pluginId);
42750
42976
  const rows = plugins[target.pluginId];
42751
42977
  pluginNeed(Array.isArray(rows) && rows.length === target.registrations.length, "Managed plugin registration membership changed");
42752
- 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);
42753
42979
  const scopes = new Set, approvals = new Map, currentFiles = new Map;
42754
42980
  plugins[target.pluginId] = rows.map((row) => {
42755
42981
  pluginNeed(pluginObject(row), "Invalid managed plugin registration");
@@ -42765,7 +42991,7 @@ function hashManagedPluginRegistry(path, managed) {
42765
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");
42766
42992
  const approval = (producer) => {
42767
42993
  pluginText(producer);
42768
- const digest2 = `sha256:${basename6(producer)}`;
42994
+ const digest2 = `sha256:${basename7(producer)}`;
42769
42995
  const receipt2 = readPluginAdmissionReceipt(witness.storeRoot, witness.bindingId, digest2);
42770
42996
  pluginNeed(receipt2.materializedPath === producer, "Managed producer path is not an approved immutable projection");
42771
42997
  if (!verified.has(producer)) {
@@ -42827,39 +43053,39 @@ function captureManagedPluginRegistry(path, managedPlugins) {
42827
43053
  }
42828
43054
 
42829
43055
  // src/lib/claude-marketplace-registry.ts
42830
- import { createHash as createHash19 } from "crypto";
43056
+ import { createHash as createHash20 } from "crypto";
42831
43057
  import { closeSync as closeSync15, constants as constants12, fstatSync as fstatSync15, lstatSync as lstatSync18, openSync as openSync15, readSync as readSync10 } from "fs";
42832
- 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";
42833
43059
  var CLAUDE_MARKETPLACE_REGISTRY_LIMITS = Object.freeze({ bytes: 1024 * 1024, rows: 1024, depth: 32, nodes: 65536, stringCharacters: 16384, pathCharacters: 4096 });
42834
- function need5(value, reason) {
43060
+ function need6(value, reason2) {
42835
43061
  if (!value)
42836
- throw new Error(`Claude marketplace registry ${reason}`);
43062
+ throw new Error(`Claude marketplace registry ${reason2}`);
42837
43063
  }
42838
43064
  function absolutePath3(value) {
42839
- 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");
42840
43066
  }
42841
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;
42842
43068
  function parents2(path) {
42843
43069
  const result = [];
42844
- for (let at = dirname14(path);; at = dirname14(at)) {
43070
+ for (let at = dirname15(path);; at = dirname15(at)) {
42845
43071
  const stat2 = lstatSync18(at, { bigint: true });
42846
- 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");
42847
43073
  result.push([at, stat2]);
42848
- if (at === dirname14(at))
43074
+ if (at === dirname15(at))
42849
43075
  return result;
42850
43076
  }
42851
43077
  }
42852
43078
  function readRegistry2(path, budget2) {
42853
43079
  absolutePath3(path);
42854
- need5(basename7(path) === "known_marketplaces.json", "requires known_marketplaces.json");
42855
- 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");
42856
43082
  const ancestors2 = parents2(path), initial = lstatSync18(path, { bigint: true });
42857
- need5(initial.isFile() && !initial.isSymbolicLink() && initial.size <= BigInt(CLAUDE_MARKETPLACE_REGISTRY_LIMITS.bytes), "is not a bounded regular file");
42858
- 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");
42859
43085
  const fd = openSync15(path, constants12.O_RDONLY | constants12.O_NOFOLLOW | constants12.O_NONBLOCK);
42860
43086
  try {
42861
43087
  const opened = fstatSync15(fd, { bigint: true });
42862
- need5(opened.isFile() && sameFile2(initial, opened), "changed during open");
43088
+ need6(opened.isFile() && sameFile2(initial, opened), "changed during open");
42863
43089
  const bytes = Buffer.alloc(Number(opened.size) + 1);
42864
43090
  let length = 0;
42865
43091
  while (length < bytes.length) {
@@ -42869,10 +43095,10 @@ function readRegistry2(path, budget2) {
42869
43095
  length += count;
42870
43096
  }
42871
43097
  const after = fstatSync15(fd, { bigint: true }), current = lstatSync18(path, { bigint: true });
42872
- 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");
42873
43099
  for (const [ancestor, before] of ancestors2) {
42874
43100
  const now = lstatSync18(ancestor, { bigint: true });
42875
- 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");
42876
43102
  }
42877
43103
  budget2.remaining -= length;
42878
43104
  try {
@@ -42892,7 +43118,7 @@ function parse7(text2) {
42892
43118
  at++;
42893
43119
  };
42894
43120
  function string() {
42895
- need5(text2[at] === '"', "contains invalid JSON");
43121
+ need6(text2[at] === '"', "contains invalid JSON");
42896
43122
  const start = at++;
42897
43123
  while (at < text2.length) {
42898
43124
  const character = text2[at++];
@@ -42903,7 +43129,7 @@ function parse7(text2) {
42903
43129
  } catch {
42904
43130
  throw new Error("Claude marketplace registry contains invalid JSON string");
42905
43131
  }
42906
- 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");
42907
43133
  return value2;
42908
43134
  }
42909
43135
  if (character === "\\")
@@ -42912,7 +43138,7 @@ function parse7(text2) {
42912
43138
  throw new Error("Claude marketplace registry contains an unterminated JSON string");
42913
43139
  }
42914
43140
  function value(depth) {
42915
- 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");
42916
43142
  space();
42917
43143
  const character = text2[at];
42918
43144
  if (character === '"')
@@ -42926,17 +43152,17 @@ function parse7(text2) {
42926
43152
  if (object6) {
42927
43153
  space();
42928
43154
  const key = string();
42929
- need5(!keys2.has(key), "contains a duplicate JSON key");
43155
+ need6(!keys2.has(key), "contains a duplicate JSON key");
42930
43156
  keys2.add(key);
42931
43157
  space();
42932
- need5(text2[at++] === ":", "contains invalid JSON");
43158
+ need6(text2[at++] === ":", "contains invalid JSON");
42933
43159
  entries.push([key, value(depth + 1)]);
42934
43160
  } else
42935
43161
  items.push(value(depth + 1));
42936
43162
  space();
42937
43163
  if (text2[at] === end)
42938
43164
  break;
42939
- need5(text2[at++] === ",", "contains invalid JSON");
43165
+ need6(text2[at++] === ",", "contains invalid JSON");
42940
43166
  }
42941
43167
  at++;
42942
43168
  return object6 ? { kind: "object", entries } : { kind: "array", items };
@@ -42948,96 +43174,112 @@ function parse7(text2) {
42948
43174
  }
42949
43175
  numberPattern.lastIndex = at;
42950
43176
  const number = numberPattern.exec(text2);
42951
- need5(number, "contains invalid JSON");
43177
+ need6(number, "contains invalid JSON");
42952
43178
  at += number[0].length;
42953
43179
  return { kind: "number", value: number[0] };
42954
43180
  }
42955
43181
  const root2 = value(0);
42956
43182
  space();
42957
- need5(at === text2.length && root2.kind === "object", "requires a JSON object without trailing content");
42958
- 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");
42959
43185
  return root2;
42960
43186
  }
42961
43187
  function exactKeys2(value, keys2) {
42962
43188
  return value?.kind === "object" && value.entries.length === keys2.length && value.entries.every(([key]) => keys2.includes(key));
42963
43189
  }
42964
- var field = (object6, key) => object6.entries.find(([name]) => name === key)?.[1];
43190
+ var field2 = (object6, key) => object6.entries.find(([name]) => name === key)?.[1];
42965
43191
  function textField(value) {
42966
- 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");
42967
43193
  return value.value;
42968
43194
  }
42969
43195
  function normalizeRow(row, version = 1) {
42970
43196
  if (!exactKeys2(row, ["source", "installLocation", "lastUpdated"])) {
42971
43197
  if (version !== 2 || !exactKeys2(row, ["source", "installLocation", "lastUpdated", "autoUpdate"]))
42972
43198
  return;
42973
- const autoUpdate = field(row, "autoUpdate");
42974
- 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");
42975
43201
  }
42976
- const source = field(row, "source");
43202
+ const source = field2(row, "source");
42977
43203
  if (source?.kind !== "object")
42978
43204
  return;
42979
- const type = field(source, "source");
43205
+ const type = field2(source, "source");
42980
43206
  if (type?.kind !== "string" || !["github", "directory"].includes(type.value))
42981
43207
  return;
42982
43208
  const location = type.value === "github" ? "repo" : "path";
42983
43209
  if (!exactKeys2(source, ["source", location]))
42984
43210
  return;
42985
- const sourceLocation = textField(field(source, location));
43211
+ const sourceLocation = textField(field2(source, location));
42986
43212
  if (type.value === "directory")
42987
43213
  absolutePath3(sourceLocation);
42988
- absolutePath3(textField(field(row, "installLocation")));
42989
- const updated = textField(field(row, "lastUpdated"));
42990
- 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");
42991
43217
  const millis = Date.parse(updated);
42992
- 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");
42993
43219
  row.entries = row.entries.map(([key, value]) => [key, key === "lastUpdated" ? { kind: "validated-update-time" } : value]);
42994
43220
  }
42995
43221
  function captureClaudeMarketplaceRegistry(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
42996
43222
  const value = parse7(readRegistry2(path, budget2));
42997
43223
  for (const [, row] of value.entries)
42998
43224
  normalizeRow(row);
42999
- 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");
43000
43226
  return { path, hashMode: "claude-marketplace-registry", sha256: sha2562 };
43001
43227
  }
43002
43228
  function captureClaudeMarketplaceRegistryV2(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
43003
43229
  const value = parse7(readRegistry2(path, budget2));
43004
43230
  for (const [, row] of value.entries)
43005
43231
  normalizeRow(row, 2);
43006
- 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");
43007
43233
  return { path, hashMode: "claude-marketplace-registry-v2", sha256: sha2562 };
43008
43234
  }
43009
43235
 
43010
43236
  // src/lib/codex-hook-discovery-recovery.ts
43011
- import { createHash as createHash21 } from "crypto";
43237
+ import { createHash as createHash22 } from "crypto";
43012
43238
 
43013
43239
  // src/lib/codex-hook-trust-files.ts
43014
- 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";
43015
- import { createHash as createHash20 } from "crypto";
43016
- import { dirname as dirname15 } from "path";
43017
- 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) {
43018
43244
  if (!value)
43019
43245
  throw new Error(`CODEX_HOOK_TRUST_${code}`);
43020
43246
  }
43021
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
+ }
43022
43251
  function safeParents(file) {
43023
- for (let p = dirname15(file);; p = dirname15(p)) {
43252
+ for (let p = dirname16(file);; p = dirname16(p)) {
43024
43253
  const s = lstatSync19(p);
43025
- need6(s.isDirectory() && !s.isSymbolicLink(), "UNSAFE_PARENT");
43026
- need6((s.mode & 18) === 0 || s.uid === 0 && (s.mode & 512) !== 0, "UNSAFE_PARENT");
43027
- 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)
43028
43257
  break;
43029
43258
  }
43030
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
+ }
43031
43273
  function snapshot(file, privateFile = false, options = {}) {
43032
43274
  const readOnlyPackage = options.readOnlyPackage === true && !privateFile;
43033
43275
  safeParents(file);
43034
43276
  const initial = lstatSync19(file, { bigint: true });
43035
- 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");
43036
- 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");
43037
43279
  const fd = openSync16(file, constants13.O_RDONLY | constants13.O_NOFOLLOW | constants13.O_NONBLOCK);
43038
43280
  try {
43039
43281
  const before = fstatSync16(fd, { bigint: true });
43040
- need6(sameStat(initial, before), "INPUT_CHANGED");
43282
+ need7(sameStat(initial, before), "INPUT_CHANGED");
43041
43283
  const bytes = Buffer.alloc(Number(before.size) + 1);
43042
43284
  let length = 0;
43043
43285
  while (length < bytes.length) {
@@ -43046,16 +43288,16 @@ function snapshot(file, privateFile = false, options = {}) {
43046
43288
  break;
43047
43289
  length += n2;
43048
43290
  }
43049
- 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");
43050
43292
  const content = bytes.subarray(0, length), text2 = new TextDecoder("utf-8", { fatal: true }).decode(content);
43051
- 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") };
43052
43294
  } finally {
43053
43295
  closeSync16(fd);
43054
43296
  }
43055
43297
  }
43056
43298
  function unchanged2(before) {
43057
43299
  const after = snapshot(before.file, before.privateFile, before.readOnlyPackage ? { readOnlyPackage: true } : {});
43058
- 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");
43059
43301
  }
43060
43302
 
43061
43303
  // src/lib/codex-hook-additions-review.ts
@@ -43064,12 +43306,12 @@ var matchedEvents = { ...events, PreToolUse: ["preToolUse", "pre_tool_use"] };
43064
43306
  var proofs = new WeakMap;
43065
43307
 
43066
43308
  // src/lib/codex-hook-discovery-recovery.ts
43067
- var sha3 = (text2) => createHash21("sha256").update(text2).digest("hex");
43309
+ var sha3 = (text2) => createHash22("sha256").update(text2).digest("hex");
43068
43310
  var fields = [...CODEX_DISCOVERY_PROJECTION_FIELDS];
43069
43311
  var proofs2 = new WeakMap;
43070
43312
  function assertCodexHookDiscoveryRecovery(binding, witness) {
43071
43313
  const proof = proofs2.get(witness);
43072
- 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");
43073
43315
  unchanged2(proof.before);
43074
43316
  unchanged2(proof.current);
43075
43317
  proof.recheckAdditions();
@@ -43078,34 +43320,34 @@ function verifiesCodexHookDiscoverySource(binding, source, currentDigest, witnes
43078
43320
  if (!witness || source.path !== witness.configPath || source.hashMode !== "bytes")
43079
43321
  return false;
43080
43322
  assertCodexHookDiscoveryRecovery(binding, witness);
43081
- 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");
43082
43324
  return true;
43083
43325
  }
43084
43326
 
43085
43327
  // src/lib/agent-sumi.ts
43086
43328
  import { existsSync as existsSync6, lstatSync as lstatSync20, realpathSync as realpathSync8 } from "fs";
43087
- import { join as join25, resolve as resolve16 } from "path";
43329
+ import { join as join25, resolve as resolve18 } from "path";
43088
43330
  function sumiConfigDirectory(home, env = process.env) {
43089
43331
  for (const key of ["SUMI_CONFIG", "SUMI_CONFIG_CONTENT"])
43090
43332
  if (env[key] !== undefined)
43091
43333
  throw new Error(`Sumi ${key} requires a dedicated discovery adapter; unset it before Skills integration`);
43092
43334
  const selected = (key) => env[key]?.trim() ? env[key] : undefined;
43093
- 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);
43094
43336
  const explicit = selected("SUMI_CONFIG_DIR");
43095
43337
  const xdg = selected("XDG_CONFIG_HOME");
43096
43338
  const custom = selected("SUMI_HOME");
43097
- 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");
43098
43340
  if (explicit || xdg || custom)
43099
- return canonical7;
43341
+ return canonical8;
43100
43342
  const legacy = join25(home, ".config/sumi");
43101
- const a = lstatSync20(canonical7, { throwIfNoEntry: false }), b = lstatSync20(legacy, { throwIfNoEntry: false });
43102
- 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))
43103
43345
  throw new Error("Sumi config roots conflict; complete native home adoption before Skills integration");
43104
- const path = a ? canonical7 : b ? legacy : canonical7;
43346
+ const path = a ? canonical8 : b ? legacy : canonical8;
43105
43347
  if (!existsSync6(path))
43106
43348
  return path;
43107
43349
  const physical = realpathSync8(path);
43108
- if ((a?.isSymbolicLink() || b?.isSymbolicLink()) && ![canonical7, legacy].includes(physical))
43350
+ if ((a?.isSymbolicLink() || b?.isSymbolicLink()) && ![canonical8, legacy].includes(physical))
43109
43351
  throw new Error("Sumi config alias must resolve to its canonical or legacy root");
43110
43352
  return physical;
43111
43353
  }
@@ -43205,7 +43447,38 @@ var SUMI_SKILL_PERMISSIONS = [
43205
43447
  ];
43206
43448
 
43207
43449
  // src/lib/agent-discovery.ts
43208
- 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");
43209
43482
  function parseConfig(text2, path, toml = false) {
43210
43483
  try {
43211
43484
  const value = toml ? Bun.TOML.parse(text2) : JSON.parse(text2);
@@ -43217,12 +43490,12 @@ function parseConfig(text2, path, toml = false) {
43217
43490
  }
43218
43491
  }
43219
43492
  function safe4(path) {
43220
- if (!isAbsolute18(path) || path.includes("\x00"))
43493
+ if (!isAbsolute20(path) || path.includes("\x00"))
43221
43494
  throw new Error("Expected an absolute native discovery path");
43222
- for (let cursor = path;; cursor = dirname16(cursor)) {
43495
+ for (let cursor = path;; cursor = dirname17(cursor)) {
43223
43496
  if (lstatSync21(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
43224
43497
  throw new Error(`Refusing symlink native discovery input: ${cursor}`);
43225
- if (dirname16(cursor) === cursor)
43498
+ if (dirname17(cursor) === cursor)
43226
43499
  break;
43227
43500
  }
43228
43501
  }
@@ -43241,7 +43514,7 @@ function projectNativeDiscoveryFields(text2, format, fields2, path) {
43241
43514
  const object6 = format === "yaml" ? parseHermesConfig(text2) : parseConfig(text2, path, format === "toml");
43242
43515
  if (!object6 || typeof object6 !== "object" || Array.isArray(object6))
43243
43516
  throw new Error("Expected native discovery configuration object");
43244
- 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]))));
43245
43518
  }
43246
43519
  function isSupersededSettingsProjection(agent, configPath, source) {
43247
43520
  if (agent === "sumi")
@@ -43286,6 +43559,14 @@ function projected(source, changes, budget2 = discoveryByteBudget()) {
43286
43559
  throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
43287
43560
  return sha2562;
43288
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
+ }
43289
43570
  if (source.hashMode === "claude-plugin-registry") {
43290
43571
  if (source.format !== undefined || source.fields !== undefined || !source.managedPlugins || changes?.has(source.path))
43291
43572
  throw new Error("Managed plugin registry witnesses require verified native registrations");
@@ -43323,7 +43604,7 @@ function absentCodexSkillRoots(binding) {
43323
43604
  throw new Error("Invalid disabled Codex discovery proof");
43324
43605
  if (binding.method !== "reviewed" || controls.every((control) => lstatSync21(control.pluginParent, { throwIfNoEntry: false })))
43325
43606
  return [];
43326
- 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");
43327
43608
  const source = binding.sources.find((source2) => source2.path === config && source2.sha256 !== null && source2.format === undefined && source2.fields === undefined);
43328
43609
  if (!source || projected(source) !== source.sha256)
43329
43610
  throw new Error("Missing current disabled Codex configuration witness");
@@ -43331,7 +43612,7 @@ function absentCodexSkillRoots(binding) {
43331
43612
  return [...new Set(controls.map((control) => control.pluginParent))].filter((parent) => !codexDirectHookSelects(cache, parent) && absentDisabledCodexPluginParent(cache, parent, controls, rules));
43332
43613
  }
43333
43614
  function codexDirectHookSelects(cache, root2) {
43334
- 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")) ?? "");
43335
43616
  const hooks = read2(join26(codex, "hooks.json"));
43336
43617
  if (hooks !== null)
43337
43618
  hashNativeJsonControls(hooks);
@@ -43344,7 +43625,7 @@ function retiredCodexRoots(binding) {
43344
43625
  const controls = binding.codexDisabledPluginSkills;
43345
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)
43346
43627
  throw new Error("Invalid retired Codex materialization proof");
43347
- 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");
43348
43629
  const source = binding.sources.find((source2) => source2.path === config && source2.sha256 !== null && source2.format === undefined && source2.fields === undefined);
43349
43630
  if (!source || projected(source) !== source.sha256)
43350
43631
  throw new Error("Missing current retired Codex configuration witness");
@@ -43361,8 +43642,8 @@ function retiredCodexRoots(binding) {
43361
43642
  function captureRetiredCodexDiscovery(binding, controls, rules) {
43362
43643
  if (binding.agent !== "codex" || binding.method !== "reviewed" || !controls.length)
43363
43644
  return binding;
43364
- const cache = dirname16(dirname16(controls[0].pluginParent));
43365
- 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)));
43366
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();
43367
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() : [];
43368
43649
  const { codexRetiredMaterializations: previous, ...current } = binding;
@@ -43391,7 +43672,7 @@ function absentRetiredClaudeRoots(binding) {
43391
43672
  safe4(root2);
43392
43673
  if (lstatSync21(root2, { throwIfNoEntry: false }))
43393
43674
  continue;
43394
- 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");
43395
43676
  const full = (path) => binding.sources.find((item) => item.path === path && item.sha256 !== null && item.format === undefined && item.fields === undefined);
43396
43677
  const configSource = full(settings), registrySource = full(registry);
43397
43678
  if (!configSource || !registrySource || projected(configSource) !== configSource.sha256 || projected(registrySource) !== registrySource.sha256)
@@ -43408,7 +43689,7 @@ function absentRetiredClaudeRoots(binding) {
43408
43689
  if (!Array.isArray(rows) || rows.length !== 1 || rows[0]?.scope !== "user" || typeof rows[0]?.installPath !== "string")
43409
43690
  continue;
43410
43691
  const active = rows[0].installPath;
43411
- 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)
43412
43693
  continue;
43413
43694
  const activeManifest = full(join26(active, ".claude-plugin/plugin.json"));
43414
43695
  if (!activeManifest || projected(activeManifest) !== activeManifest.sha256)
@@ -43459,7 +43740,7 @@ function verifyAgentDiscovery(binding, codexRecovery) {
43459
43740
  assertMarketplaceBinding(binding, source);
43460
43741
  if (source.hashMode === "claude-plugin-registry" && binding.agent !== "claude")
43461
43742
  throw new Error("Managed Claude registry witnesses cannot apply to another agent");
43462
- 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)))
43463
43744
  throw new Error("Invalid native discovery projection");
43464
43745
  if (source.sha256 !== null && !/^[a-f0-9]{64}$/.test(source.sha256))
43465
43746
  throw new Error("Invalid native discovery digest");
@@ -43487,15 +43768,15 @@ function codexInstallationRoots(binding) {
43487
43768
  const proof = binding.codexInstallationInputs;
43488
43769
  if (proof === undefined)
43489
43770
  return [];
43490
- if (binding.agent !== "codex" || binding.method !== "reviewed" || proof.version !== "codex-cli 0.160.0" || !/^[a-f0-9]{64}$/.test(proof.catalogSha256) || !Array.isArray(proof.plugins) || !proof.plugins.length)
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)
43491
43772
  throw new Error("Invalid native installation input proof");
43492
- const cache = dirname16(dirname16(proof.plugins[0].pluginParent));
43493
- 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)));
43494
43775
  const configSource = binding.sources.find((source) => source.path === config && source.sha256 !== null && (!source.format || source.format === "toml" && source.fields?.includes("plugins")));
43495
43776
  const nativeRoots = NATIVE_SKILL_ROOTS.filter(([agent]) => agent === "codex").map(([, path]) => join26(home, path));
43496
- 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)))))
43497
43778
  throw new Error("Native installation input overlaps configuration or loading roots");
43498
- 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)))
43499
43780
  throw new Error("Missing native installation input source witness");
43500
43781
  return reviewedCodexPluginSourceRoots(cache, proof.plugins, (path) => {
43501
43782
  const text2 = read2(path);
@@ -43505,16 +43786,18 @@ function codexInstallationRoots(binding) {
43505
43786
  });
43506
43787
  }
43507
43788
  function assertMarketplaceBinding(binding, source) {
43508
- 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"))))
43509
43790
  throw new Error("Claude plugin manifest witnesses require Claude plugin discovery");
43510
- 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"))
43511
43792
  throw new Error("Sumi settings witnesses require explicit reviewed Sumi configuration");
43512
- 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"))
43513
43794
  throw new Error("Codex settings witnesses require explicit reviewed Codex configuration");
43514
- 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"))
43515
43796
  throw new Error("Claude settings witnesses require explicit reviewed Claude configuration");
43516
43797
  if ((source.hashMode === "claude-marketplace-registry" || source.hashMode === "claude-marketplace-registry-v2") && (binding.agent !== "claude" || binding.method !== "reviewed"))
43517
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");
43518
43801
  }
43519
43802
  function rebindAgentDiscovery(binding, changes) {
43520
43803
  const budget2 = discoveryByteBudget();
@@ -43547,10 +43830,10 @@ function captureDiscoveryPathSources(paths) {
43547
43830
  const budget2 = discoveryByteBudget();
43548
43831
  return paths.map((path) => ({ path, hashMode: "path-bytes", sha256: hashDiscoveryPathFile(path, budget2) }));
43549
43832
  }
43550
- function assertProjectDiscovery(agent, directories, home, canonical7 = resolve17, reviewed) {
43551
- const homeConfigPath = canonical7(agentDiscoveryConfigPath(home, agent));
43833
+ function assertProjectDiscovery(agent, directories, home, canonical8 = resolve19, reviewed) {
43834
+ const homeConfigPath = canonical8(agentDiscoveryConfigPath(home, agent));
43552
43835
  for (const directory of directories) {
43553
- const isHome = resolve17(directory) === resolve17(home);
43836
+ const isHome = resolve19(directory) === resolve19(home);
43554
43837
  if (agent === "hermes") {
43555
43838
  assertHermesEnvironment(home);
43556
43839
  continue;
@@ -43559,7 +43842,7 @@ function assertProjectDiscovery(agent, directories, home, canonical7 = resolve17
43559
43842
  continue;
43560
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"];
43561
43844
  for (const suffix of paths) {
43562
- const path = canonical7(join26(directory, suffix)), raw = read2(path);
43845
+ const path = canonical8(join26(directory, suffix)), raw = read2(path);
43563
43846
  if (raw === null)
43564
43847
  continue;
43565
43848
  const isRootAliasedHomeConfig = agent === "claude" && suffix === ".claude/settings.json" || agent === "codex" && suffix === ".codex/config.toml";
@@ -43575,7 +43858,7 @@ function assertProjectDiscovery(agent, directories, home, canonical7 = resolve17
43575
43858
  const managed = reviewed.sources.flatMap((source) => source.hashMode === "claude-plugin-registry" ? source.managedPlugins ?? [] : []);
43576
43859
  if (exact && projected(exact) === exact.sha256 && managed.length) {
43577
43860
  const bindings = managed.map((item) => readPluginBinding(item.storeRoot, item.bindingId));
43578
- 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))));
43579
43862
  }
43580
43863
  }
43581
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)))
@@ -43583,13 +43866,13 @@ function assertProjectDiscovery(agent, directories, home, canonical7 = resolve17
43583
43866
  }
43584
43867
  if (agent === "sumi")
43585
43868
  for (const name of ["plugin", "plugins"]) {
43586
- const path = canonical7(join26(directory, ".sumi", name));
43869
+ const path = canonical8(join26(directory, ".sumi", name));
43587
43870
  safe4(path);
43588
43871
  if (lstatSync21(path, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(path).length)
43589
43872
  throw new Error(`NATIVE_SKILL_DRIFT: project Sumi plugins require a dedicated discovery review: ${path}`);
43590
43873
  }
43591
43874
  if (agent === "claude") {
43592
- const commands = canonical7(join26(directory, ".claude/commands"));
43875
+ const commands = canonical8(join26(directory, ".claude/commands"));
43593
43876
  safe4(commands);
43594
43877
  if (lstatSync21(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length)
43595
43878
  throw new Error("NATIVE_SKILL_DRIFT: legacy project command discovery requires a dedicated format adapter");
@@ -43601,11 +43884,37 @@ function agentDiscoveryConfigPath(home, agent) {
43601
43884
  return sumiConfigPath(home);
43602
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"}`);
43603
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
+ }
43604
43913
  function resolveAgentDiscovery(options) {
43605
- 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;
43606
43915
  const sources = [], roots = new Set, builtinNames = [];
43607
43916
  const witness = (path, format, fields2, hashMode) => {
43608
- 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 } : {} };
43609
43918
  source.sha256 = projected(source);
43610
43919
  sources.push(source);
43611
43920
  return read2(source.path);
@@ -43627,13 +43936,13 @@ function resolveAgentDiscovery(options) {
43627
43936
  unresolved("JSONC configuration requires a supported format adapter");
43628
43937
  for (const root2 of [directory, join26(home, ".claude"), join26(home, ".agents")])
43629
43938
  for (const name of ["skill", "skills"])
43630
- roots.add(canonical7(join26(root2, name)));
43939
+ roots.add(canonical8(join26(root2, name)));
43631
43940
  if (config.skills !== undefined && (!Array.isArray(config.skills) || config.skills.some((path) => typeof path !== "string")))
43632
43941
  unresolved("skills must be a string array");
43633
43942
  for (const value of config.skills ?? []) {
43634
- 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("~/")))
43635
43944
  unresolved("remote or relative skill sources need a dedicated discovery adapter");
43636
- roots.add(canonical7(value.startsWith("~/") ? join26(home, value.slice(2)) : value));
43945
+ roots.add(canonical8(value.startsWith("~/") ? join26(home, value.slice(2)) : value));
43637
43946
  }
43638
43947
  for (const key of ["plugin", "plugins"])
43639
43948
  if (config[key] !== undefined && !Array.isArray(config[key]))
@@ -43672,23 +43981,23 @@ function resolveAgentDiscovery(options) {
43672
43981
  continue;
43673
43982
  if (normalized.startsWith("~") && normalized !== "~" && !normalized.startsWith("~/"))
43674
43983
  unresolved("user-specific tilde expansion requires a separate discovery adapter");
43675
- 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);
43676
43985
  safe4(path);
43677
43986
  roots.add(path);
43678
43987
  }
43679
43988
  }
43680
43989
  if (agent === "gemini") {
43681
- const executable2 = Bun.which("gemini");
43990
+ const executable2 = options.executable === undefined ? discoveryExecutable(agent) : options.executable;
43682
43991
  if (executable2) {
43683
43992
  let packageRoot;
43684
- 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++) {
43685
43994
  const path = join26(directory, "package.json"), raw = read2(path);
43686
43995
  if (raw !== null && parseConfig(raw, path).name === "@google/gemini-cli") {
43687
43996
  packageRoot = directory;
43688
43997
  witness(path);
43689
43998
  break;
43690
43999
  }
43691
- if (dirname16(directory) === directory)
44000
+ if (dirname17(directory) === directory)
43692
44001
  break;
43693
44002
  }
43694
44003
  if (!packageRoot)
@@ -43711,11 +44020,11 @@ function resolveAgentDiscovery(options) {
43711
44020
  if (retained.agent !== agent || retained.method !== "reviewed")
43712
44021
  unresolved("invalid retained review");
43713
44022
  verifyAgentDiscovery(retained);
43714
- 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))
43715
44024
  unresolved("retained review is missing the full agent configuration source");
43716
- 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)))
43717
44026
  unresolved("retained settings witness names another configuration source");
43718
- 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;
43719
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))
43720
44029
  unresolved("retained review is missing current runtime discovery coverage");
43721
44030
  return retained;
@@ -43727,15 +44036,15 @@ function resolveAgentDiscovery(options) {
43727
44036
  if (review.sources.some((source) => source.format !== undefined || source.fields !== undefined))
43728
44037
  throw new Error("Explicit discovery reviews require full source-file hashes");
43729
44038
  verifyAgentDiscovery(supplied);
43730
- 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)))
43731
44040
  throw new Error("Semantic settings witnesses must name the configured agent configuration source");
43732
- if (!review.sources.some((source) => source.path === canonical7(configPath)))
44041
+ if (!review.sources.some((source) => source.path === canonical8(configPath)))
43733
44042
  throw new Error("Discovery review must include the agent configuration source");
43734
- 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;
43735
44044
  const reviewedSourcesWithManifestProjection = review.sources.map((source) => {
43736
- 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")))
43737
44046
  return source;
43738
- 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");
43739
44048
  const hookStat = lstatSync21(hooksPath, { throwIfNoEntry: false });
43740
44049
  const text2 = read2(source.path);
43741
44050
  if (text2 === null)
@@ -43750,13 +44059,13 @@ function resolveAgentDiscovery(options) {
43750
44059
  if (manifest.hooks !== undefined) {
43751
44060
  if (typeof manifest.hooks !== "string")
43752
44061
  throw new Error("Reviewed Claude plugin manifest has an unsupported hooks target");
43753
- const declaredHookPath = resolve17(pluginRoot, manifest.hooks);
44062
+ const declaredHookPath = resolve19(pluginRoot, manifest.hooks);
43754
44063
  if (!declaredHookPath.startsWith(pluginRoot + sep6))
43755
44064
  throw new Error("Reviewed Claude plugin hooks target escapes its root");
43756
44065
  reviewedHookPaths.add(declaredHookPath);
43757
44066
  }
43758
44067
  for (const hooksFile of reviewedHookPaths)
43759
- 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")))
43760
44069
  throw new Error("Reviewed Claude plugin manifest requires separately reviewed exact hook file sources");
43761
44070
  return { path: source.path, sha256: manifestSha256, hashMode: "claude-plugin-manifest-v1" };
43762
44071
  });
@@ -43765,7 +44074,7 @@ function resolveAgentDiscovery(options) {
43765
44074
  return { ...supplied, roots: [...new Set([...roots, ...supplied.roots])].sort(), sources: unique, ...agent === "gemini" ? { builtinNames } : {} };
43766
44075
  }
43767
44076
  function plugin(root2) {
43768
- root2 = canonical7(root2);
44077
+ root2 = canonical8(root2);
43769
44078
  safe4(root2);
43770
44079
  const manifestPath = join26(root2, agent === "claude" ? ".claude-plugin/plugin.json" : ".codex-plugin/plugin.json");
43771
44080
  const raw = witness(manifestPath, undefined, undefined, agent === "claude" ? "claude-plugin-manifest-v1" : undefined);
@@ -43788,16 +44097,16 @@ function resolveAgentDiscovery(options) {
43788
44097
  if (agent === "claude")
43789
44098
  roots.add(join26(root2, "skills"));
43790
44099
  for (const value of declared) {
43791
- const path = resolve17(root2, value);
44100
+ const path = resolve19(root2, value);
43792
44101
  if (path !== root2 && !path.startsWith(root2 + sep6))
43793
44102
  unresolved("plugin skill path escapes its root");
43794
- roots.add(path.endsWith(`${sep6}SKILL.md`) ? dirname16(path) : path);
44103
+ roots.add(path.endsWith(`${sep6}SKILL.md`) ? dirname17(path) : path);
43795
44104
  }
43796
44105
  }
43797
44106
  if (agent === "claude") {
43798
44107
  const registrations = witness(join26(home, ".claude/plugins/installed_plugins.json"));
43799
44108
  const installed = registrations === null ? {} : parseConfig(registrations, join26(home, ".claude/plugins/installed_plugins.json")).plugins;
43800
- const commands = canonical7(join26(home, ".claude/commands"));
44109
+ const commands = canonical8(join26(home, ".claude/commands"));
43801
44110
  safe4(commands);
43802
44111
  if (lstatSync21(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length)
43803
44112
  unresolved("legacy home command discovery requires a dedicated format adapter");
@@ -43819,7 +44128,7 @@ function resolveAgentDiscovery(options) {
43819
44128
  unresolved("unsupported plugin enablement");
43820
44129
  const split = id2.lastIndexOf("@"), name = id2.slice(0, split), marketplace = id2.slice(split + 1);
43821
44130
  const market = config.marketplaces?.[marketplace] ?? (marketplace === "personal" ? { source_type: "local", source: home } : undefined);
43822
- 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))
43823
44132
  unresolved("enabled plugin marketplace is not an explicit local source");
43824
44133
  const catalogText = witness(join26(market.source, ".agents/plugins/marketplace.json"));
43825
44134
  if (catalogText === null)
@@ -43827,7 +44136,7 @@ function resolveAgentDiscovery(options) {
43827
44136
  const catalog = parseConfig(catalogText, join26(market.source, ".agents/plugins/marketplace.json")), matches = Array.isArray(catalog.plugins) ? catalog.plugins.filter((item) => item.name === name) : [];
43828
44137
  if (matches.length !== 1 || matches[0]?.source?.source !== "local" || typeof matches[0]?.source?.path !== "string")
43829
44138
  unresolved("plugin catalog source is missing or ambiguous");
43830
- plugin(resolve17(market.source, matches[0].source.path));
44139
+ plugin(resolve19(market.source, matches[0].source.path));
43831
44140
  }
43832
44141
  } else if (agent === "opencode") {
43833
44142
  if (witness(join26(home, ".config/opencode/opencode.jsonc")) !== null || witness(join26(home, ".config/opencode/config.json")) !== null)
@@ -43835,7 +44144,7 @@ function resolveAgentDiscovery(options) {
43835
44144
  if ((config.plugin?.length ?? 0) > 0 || config.skills?.urls?.length)
43836
44145
  unresolved("external plugin or remote skill source");
43837
44146
  for (const path of config.skills?.paths ?? []) {
43838
- if (typeof path !== "string" || !isAbsolute18(path))
44147
+ if (typeof path !== "string" || !isAbsolute20(path))
43839
44148
  unresolved("relative or malformed added skill root");
43840
44149
  roots.add(path);
43841
44150
  }
@@ -43844,7 +44153,7 @@ function resolveAgentDiscovery(options) {
43844
44153
  if (lstatSync21(localPlugins, { throwIfNoEntry: false }) && readdirSync7(localPlugins).some((name) => name !== "skills-cli.js"))
43845
44154
  unresolved("additional local plugin hooks require review");
43846
44155
  } else if (agent === "sumi") {
43847
- 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))
43848
44157
  unresolved("external or foreign local plugins require review");
43849
44158
  } else if (agent === "hermes") {
43850
44159
  for (const directory of [join26(home, ".hermes/plugins"), join26(home, ".hermes/hermes-agent")]) {
@@ -43874,7 +44183,7 @@ function resolveAgentDiscovery(options) {
43874
44183
  roots.add(join26(root2, "skills"));
43875
44184
  }
43876
44185
  }
43877
- 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))) } : {} };
43878
44187
  }
43879
44188
 
43880
44189
  // src/lib/agent-adapters.ts
@@ -43950,29 +44259,29 @@ var CODEX_SKILL_CONFIG_SECTIONS = /^\[\[skills\.config\]\][^\n]*(?:\n(?!\s*\[)[^
43950
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");
43951
44260
  function splitTopLevel(value, delimiter2) {
43952
44261
  const result = [];
43953
- let start = 0, square = 0, curly = 0, quote2 = null, escaped = false;
44262
+ let start = 0, square = 0, curly = 0, quote3 = null, escaped = false;
43954
44263
  for (let index = 0;index < value.length; index++) {
43955
44264
  const char = value[index];
43956
- if (quote2 === "double") {
44265
+ if (quote3 === "double") {
43957
44266
  if (escaped)
43958
44267
  escaped = false;
43959
44268
  else if (char === "\\")
43960
44269
  escaped = true;
43961
44270
  else if (char === '"')
43962
- quote2 = null;
44271
+ quote3 = null;
43963
44272
  continue;
43964
44273
  }
43965
- if (quote2 === "literal") {
44274
+ if (quote3 === "literal") {
43966
44275
  if (char === "'")
43967
- quote2 = null;
44276
+ quote3 = null;
43968
44277
  continue;
43969
44278
  }
43970
44279
  if (char === '"') {
43971
- quote2 = "double";
44280
+ quote3 = "double";
43972
44281
  continue;
43973
44282
  }
43974
44283
  if (char === "'") {
43975
- quote2 = "literal";
44284
+ quote3 = "literal";
43976
44285
  continue;
43977
44286
  }
43978
44287
  if (char === "[")
@@ -43990,7 +44299,7 @@ function splitTopLevel(value, delimiter2) {
43990
44299
  start = index + 1;
43991
44300
  }
43992
44301
  }
43993
- if (quote2 !== null || square !== 0 || curly !== 0)
44302
+ if (quote3 !== null || square !== 0 || curly !== 0)
43994
44303
  return null;
43995
44304
  result.push(value.slice(start));
43996
44305
  return result;
@@ -43998,29 +44307,29 @@ function splitTopLevel(value, delimiter2) {
43998
44307
  function inlineArrayEnd(value) {
43999
44308
  if (!value.startsWith("["))
44000
44309
  return null;
44001
- let square = 0, curly = 0, quote2 = null, escaped = false;
44310
+ let square = 0, curly = 0, quote3 = null, escaped = false;
44002
44311
  for (let index = 0;index < value.length; index++) {
44003
44312
  const char = value[index];
44004
- if (quote2 === "double") {
44313
+ if (quote3 === "double") {
44005
44314
  if (escaped)
44006
44315
  escaped = false;
44007
44316
  else if (char === "\\")
44008
44317
  escaped = true;
44009
44318
  else if (char === '"')
44010
- quote2 = null;
44319
+ quote3 = null;
44011
44320
  continue;
44012
44321
  }
44013
- if (quote2 === "literal") {
44322
+ if (quote3 === "literal") {
44014
44323
  if (char === "'")
44015
- quote2 = null;
44324
+ quote3 = null;
44016
44325
  continue;
44017
44326
  }
44018
44327
  if (char === '"') {
44019
- quote2 = "double";
44328
+ quote3 = "double";
44020
44329
  continue;
44021
44330
  }
44022
44331
  if (char === "'") {
44023
- quote2 = "literal";
44332
+ quote3 = "literal";
44024
44333
  continue;
44025
44334
  }
44026
44335
  if (char === "[")
@@ -44057,7 +44366,7 @@ function inlineRowsAsTables(value, newline) {
44057
44366
  const fields2 = splitTopLevel(row.slice(1, -1), ",");
44058
44367
  if (!fields2)
44059
44368
  return null;
44060
- const lines = fields2.map((field2) => field2.trim()).filter(Boolean);
44369
+ const lines = fields2.map((field3) => field3.trim()).filter(Boolean);
44061
44370
  if (lines.some((line) => !/^(?:path|name|enabled)\s*=/.test(line)))
44062
44371
  return null;
44063
44372
  const keys2 = lines.map((line) => line.slice(0, line.indexOf("=")).trim());
@@ -44082,27 +44391,27 @@ function normalizeCodexInlinePathConfig(text2) {
44082
44391
  const matches = [];
44083
44392
  for (const assignment of text2.matchAll(/^([ \t]*config[ \t]*=[ \t]*)(.*?)(\r?)$/gm)) {
44084
44393
  const rawValue = assignment[2].trimEnd();
44085
- let quote2 = null, escaped = false, comment = "";
44394
+ let quote3 = null, escaped = false, comment = "";
44086
44395
  for (let index = 0;index < rawValue.length; index++) {
44087
44396
  const char = rawValue[index];
44088
- if (quote2 === "double") {
44397
+ if (quote3 === "double") {
44089
44398
  if (escaped)
44090
44399
  escaped = false;
44091
44400
  else if (char === "\\")
44092
44401
  escaped = true;
44093
44402
  else if (char === '"')
44094
- quote2 = null;
44403
+ quote3 = null;
44095
44404
  continue;
44096
44405
  }
44097
- if (quote2 === "literal") {
44406
+ if (quote3 === "literal") {
44098
44407
  if (char === "'")
44099
- quote2 = null;
44408
+ quote3 = null;
44100
44409
  continue;
44101
44410
  }
44102
44411
  if (char === '"')
44103
- quote2 = "double";
44412
+ quote3 = "double";
44104
44413
  else if (char === "'")
44105
- quote2 = "literal";
44414
+ quote3 = "literal";
44106
44415
  else if (char === "#") {
44107
44416
  comment = rawValue.slice(index);
44108
44417
  break;
@@ -44213,9 +44522,9 @@ function disableCodexBundledSkills(text2) {
44213
44522
  }
44214
44523
 
44215
44524
  // src/cli/commands/runtime-launcher.ts
44216
- import { createHash as createHash23 } from "crypto";
44217
- 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";
44218
- 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";
44219
44528
  var PINNED_LAUNCHER_SCHEMA = "hasna-skills-pinned-launcher-v1";
44220
44529
  var LAUNCH_CWD_VARIABLE = "HASNA_SKILLS_LAUNCH_CWD";
44221
44530
  var PINNED_LAUNCHER_BUN_FLAGS = ["--config=/dev/null", "--no-env-file", "--no-macros", "--no-install"];
@@ -44256,10 +44565,10 @@ var PINNED_LAUNCHER_ENV_PREFIXES = ["HASNA", "SKILLS", "SKILL", "MCP", "XDG", "L
44256
44565
  var ENV_PREFIX = new RegExp(`^(${PINNED_LAUNCHER_ENV_PREFIXES.join("|")})_`);
44257
44566
  var ENV_EXACT = new Set(PINNED_LAUNCHER_ENV_NAMES);
44258
44567
  function sha2562(bytes) {
44259
- return createHash23("sha256").update(bytes).digest("hex");
44568
+ return createHash24("sha256").update(bytes).digest("hex");
44260
44569
  }
44261
44570
  function assertLauncherPath(value, code) {
44262
- if (typeof value !== "string" || !isAbsolute19(value) || /['\x00-\x1f\x7f]/.test(value))
44571
+ if (typeof value !== "string" || !isAbsolute21(value) || /['\x00-\x1f\x7f]/.test(value))
44263
44572
  throw new Error(code);
44264
44573
  }
44265
44574
  function renderPinnedLauncher(binding) {
@@ -44349,7 +44658,7 @@ function assertPinnedLauncherRuntimeSafe(runtime) {
44349
44658
  }
44350
44659
 
44351
44660
  // src/lib/agent-integration.ts
44352
- var sha4 = (data) => createHash24("sha256").update(data).digest("hex");
44661
+ var sha4 = (data) => createHash25("sha256").update(data).digest("hex");
44353
44662
  var ROOTS = NATIVE_SKILL_ROOTS;
44354
44663
  function hasTrustedDarwinAcl(fd, allowDenyOnly = false) {
44355
44664
  try {
@@ -44399,9 +44708,10 @@ function isSystemRootAlias(path) {
44399
44708
  return false;
44400
44709
  const target = `/private${path}`, link = `private${path}`;
44401
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}`;
44402
44712
  try {
44403
44713
  const before = lstatSync23(path, { bigint: true });
44404
- if (!before.isSymbolicLink() || before.uid !== 0n || readlinkSync6(path) !== link)
44714
+ if (!before.isSymbolicLink() || before.uid !== 0n || readlinkSync7(path) !== link)
44405
44715
  return false;
44406
44716
  const directories = ["/", "/private", target].map((directory) => {
44407
44717
  const stat2 = lstatSync23(directory, { bigint: true });
@@ -44414,20 +44724,20 @@ function isSystemRootAlias(path) {
44414
44724
  throw new Error("Unprotected system temporary directory");
44415
44725
  const fd = openSync18(directory, constants15.O_RDONLY | constants15.O_DIRECTORY | constants15.O_NOFOLLOW);
44416
44726
  try {
44417
- 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))
44418
44728
  throw new Error("Unverified system alias directory ACL");
44419
44729
  } finally {
44420
44730
  closeSync18(fd);
44421
44731
  }
44422
- return { directory, identity: identity5(stat2) };
44732
+ return { directory, identity: directoryIdentity(stat2) };
44423
44733
  });
44424
- 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);
44425
44735
  } catch {
44426
44736
  return false;
44427
44737
  }
44428
44738
  }
44429
44739
  function canonicalSystemPath(path) {
44430
- const absolute = resolve18(path), root2 = `/${absolute.split(sep7)[1]}`;
44740
+ const absolute = resolve20(path), root2 = `/${absolute.split(sep7)[1]}`;
44431
44741
  if (process.platform !== "darwin" || !["/var", "/tmp", "/etc"].includes(root2) || !lstatSync23(root2, { throwIfNoEntry: false })?.isSymbolicLink())
44432
44742
  return absolute;
44433
44743
  if (!isSystemRootAlias(root2))
@@ -44435,11 +44745,11 @@ function canonicalSystemPath(path) {
44435
44745
  return `/private${absolute}`;
44436
44746
  }
44437
44747
  function assertSafePath(path) {
44438
- let cursor = resolve18(path);
44748
+ let cursor = resolve20(path);
44439
44749
  while (true) {
44440
44750
  if (lstatSync23(cursor, { throwIfNoEntry: false })?.isSymbolicLink() && !isSystemRootAlias(cursor))
44441
44751
  throw new Error(`Refusing symlink path: ${cursor}`);
44442
- const parent = dirname17(cursor);
44752
+ const parent = dirname18(cursor);
44443
44753
  if (parent === cursor)
44444
44754
  return;
44445
44755
  cursor = parent;
@@ -44451,13 +44761,13 @@ function readRootAlias(home, agent) {
44451
44761
  const stat2 = lstatSync23(alias, { throwIfNoEntry: false, bigint: true });
44452
44762
  if (!stat2?.isSymbolicLink())
44453
44763
  throw new Error(`Agent root alias changed after planning: ${alias}`);
44454
- const link = readlinkSync6(alias), targetPath = resolve18(dirname17(alias), link);
44764
+ const link = readlinkSync7(alias), targetPath = resolve20(dirname18(alias), link);
44455
44765
  assertSafePath(targetPath);
44456
44766
  const targetStat = lstatSync23(targetPath, { throwIfNoEntry: false });
44457
44767
  if (!targetStat?.isDirectory())
44458
44768
  throw new Error(`Agent root alias must target an existing directory: ${alias}`);
44459
44769
  const target = realpathSync11(targetPath), inside = relative5(realHome, target);
44460
- if (!inside || inside === ".." || inside.startsWith(`..${sep7}`) || isAbsolute20(inside))
44770
+ if (!inside || inside === ".." || inside.startsWith(`..${sep7}`) || isAbsolute22(inside))
44461
44771
  throw new Error(`Agent root alias target must be inside the real home: ${alias}`);
44462
44772
  return { agent, home: realHome, alias, target, link, aliasIdentity: `${stat2.dev}:${stat2.ino}:${stat2.ctimeNs}`, targetIdentity: `${targetStat.dev}:${targetStat.ino}` };
44463
44773
  }
@@ -44483,13 +44793,13 @@ function disabledCodexSkillPaths(config, aliases) {
44483
44793
  const rows = skills.config;
44484
44794
  if (!Array.isArray(rows))
44485
44795
  return [];
44486
- 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())))
44487
44797
  return [];
44488
44798
  if (rows.some((entry) => entry.name !== undefined && entry.enabled !== false))
44489
44799
  return [];
44490
44800
  const settings = new Map;
44491
44801
  for (const entry of rows) {
44492
- if (typeof entry.path !== "string" || !isAbsolute20(entry.path))
44802
+ if (typeof entry.path !== "string" || !isAbsolute22(entry.path))
44493
44803
  continue;
44494
44804
  let document2;
44495
44805
  try {
@@ -44501,7 +44811,7 @@ function disabledCodexSkillPaths(config, aliases) {
44501
44811
  continue;
44502
44812
  settings.set(document2, [...settings.get(document2) ?? [], entry.enabled === false]);
44503
44813
  }
44504
- 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));
44505
44815
  }
44506
44816
  function recheckRootAliases(aliases) {
44507
44817
  for (const binding of aliases) {
@@ -44543,7 +44853,7 @@ function readNativeBytes(path, maximum = 64 * 1024 * 1024) {
44543
44853
  }
44544
44854
  }
44545
44855
  function treeHash(root2) {
44546
- const hash2 = createHash24("sha256");
44856
+ const hash2 = createHash25("sha256");
44547
44857
  let bytes = 0, files = 0;
44548
44858
  function visit2(path) {
44549
44859
  const stat2 = lstatSync23(path);
@@ -44575,20 +44885,20 @@ function selectNativeMigrationTargets(inventory, manifest) {
44575
44885
  const identities = new Set;
44576
44886
  const selected = [];
44577
44887
  for (const target of manifest.targets) {
44578
- if (!isAbsolute20(target.projectRoot) || resolve18(target.projectRoot) !== target.projectRoot)
44888
+ if (!isAbsolute22(target.projectRoot) || resolve20(target.projectRoot) !== target.projectRoot)
44579
44889
  throw new Error(`Native migration target project root must be an existing absolute directory: ${target.projectRoot}`);
44580
- 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));
44581
44891
  if (!existsSync7(projectRoot) || !lstatSync23(projectRoot).isDirectory())
44582
44892
  throw new Error(`Native migration target project root must be an existing absolute directory: ${target.projectRoot}`);
44583
44893
  assertSafePath(projectRoot);
44584
- 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))
44585
44895
  throw new Error(`Invalid native migration target: ${target.path}`);
44586
44896
  const identity5 = `${target.agent}\x00${canonicalSystemPath(projectRoot)}\x00${normalized}`;
44587
44897
  if (identities.has(identity5))
44588
44898
  throw new Error(`Duplicate native migration target: ${target.path}`);
44589
44899
  identities.add(identity5);
44590
- const expected = canonicalSystemPath(resolve18(target.projectRoot, target.path));
44591
- 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);
44592
44902
  if (matches.length !== 1)
44593
44903
  throw new Error(`Native migration target was not found exactly once: ${target.agent} ${target.projectRoot}/${target.path}`);
44594
44904
  const entry = matches[0];
@@ -44607,7 +44917,7 @@ function projectAncestorDirectories(projects) {
44607
44917
  if (depth >= 100)
44608
44918
  throw new Error("NATIVE_SKILL_DRIFT: project ancestor discovery limit exceeded");
44609
44919
  directories.add(path);
44610
- const parent = dirname17(path);
44920
+ const parent = dirname18(path);
44611
44921
  if (parent === path)
44612
44922
  break;
44613
44923
  path = parent;
@@ -44616,7 +44926,7 @@ function projectAncestorDirectories(projects) {
44616
44926
  return [...directories];
44617
44927
  }
44618
44928
  function isCodexSkillDiscoveryInput(path) {
44619
- for (let cursor = canonicalSystemPath(path);cursor !== dirname17(cursor); cursor = dirname17(cursor)) {
44929
+ for (let cursor = canonicalSystemPath(path);cursor !== dirname18(cursor); cursor = dirname18(cursor)) {
44620
44930
  if (ROOTS.some(([agent, root2]) => agent === "codex" && cursor.endsWith(join27(sep7, root2))))
44621
44931
  return true;
44622
44932
  }
@@ -44624,9 +44934,9 @@ function isCodexSkillDiscoveryInput(path) {
44624
44934
  }
44625
44935
  function inventoryNativeSkills(home = homedir3(), options = {}) {
44626
44936
  home = canonicalSystemPath(home);
44627
- 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))
44628
44938
  throw new Error("A reviewed cache alias requires vendor inventory and an exact absolute path");
44629
- if (options.disabledVendorPaths?.some((path) => !isAbsolute20(path) || resolve18(path) !== path))
44939
+ if (options.disabledVendorPaths?.some((path) => !isAbsolute22(path) || resolve20(path) !== path))
44630
44940
  throw new Error("Disabled vendor paths must be exact absolute paths");
44631
44941
  const reviewedCacheAlias = options.reviewedCacheAlias === undefined ? undefined : canonicalSystemPath(options.reviewedCacheAlias);
44632
44942
  const disabledVendorPaths = new Set((options.disabledVendorPaths ?? []).map(canonicalSystemPath));
@@ -44645,7 +44955,7 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
44645
44955
  roots.push(["sumi", canonicalAgentPath(join27(project, directory, name), aliases)]);
44646
44956
  }
44647
44957
  const installationInputs = options.codexInstallationInputRoots ?? [];
44648
- 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)))))
44649
44959
  throw new Error("Native installation input overlaps an unconditional skill-loading root");
44650
44960
  const entries = [], seen = new Set;
44651
44961
  const cacheScans = new Map, maxAliasProofEntries = 1e4;
@@ -44659,11 +44969,11 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
44659
44969
  }
44660
44970
  let reviewedCacheAliasFound = false;
44661
44971
  function verifiedSiblingCacheAlias(agent, path, parent) {
44662
- const link = readlinkSync6(path), lexicalTarget = resolve18(parent, link);
44663
- if (isAbsolute20(link) ? link !== lexicalTarget : dirname17(link) !== ".")
44972
+ const link = readlinkSync7(path), lexicalTarget = resolve20(parent, link);
44973
+ if (isAbsolute22(link) ? link !== lexicalTarget : dirname18(link) !== ".")
44664
44974
  return false;
44665
44975
  const target = canonicalSystemPath(lexicalTarget);
44666
- if (dirname17(target) !== parent)
44976
+ if (dirname18(target) !== parent)
44667
44977
  return false;
44668
44978
  if (!lstatSync23(target, { throwIfNoEntry: false })?.isDirectory())
44669
44979
  return false;
@@ -44712,17 +45022,17 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
44712
45022
  }
44713
45023
  const bridge = (!vendor || agent === "sumi") && isOwnedCliBridge(path, bridgePaths);
44714
45024
  const rootAlias = aliases.find((item) => path === item.target || path.startsWith(item.target + sep7));
44715
- 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 } : {} });
44716
45026
  return scan;
44717
45027
  }
44718
45028
  if (depth > (agent === "sumi" ? 32 : vendor ? 32 : 3))
44719
45029
  return { ...scan, complete: false };
44720
45030
  const children = [], directory = opendirSync5(path);
44721
45031
  try {
44722
- let child;
44723
- while ((child = directory.readSync()) !== null) {
44724
- admit(join27(path, child.name));
44725
- children.push(child);
45032
+ let child2;
45033
+ while ((child2 = directory.readSync()) !== null) {
45034
+ admit(join27(path, child2.name));
45035
+ children.push(child2);
44726
45036
  }
44727
45037
  } finally {
44728
45038
  directory.closeSync();
@@ -44738,15 +45048,15 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
44738
45048
  const isVendor = vendor || name === ".system";
44739
45049
  if (isVendor && !options.includeVendor)
44740
45050
  continue;
44741
- const child = join27(path, name);
44742
- if (isVendor && lstatSync23(child, { throwIfNoEntry: false })?.isSymbolicLink()) {
44743
- const target = statSync7(child, { throwIfNoEntry: false });
44744
- 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)) {
44745
45055
  scan.entries++;
44746
45056
  continue;
44747
45057
  }
44748
45058
  }
44749
- const childScan = visit2(agent, child, isVendor, depth + 1, pluginCache, true, configuredRoot);
45059
+ const childScan = visit2(agent, child2, isVendor, depth + 1, pluginCache, true, configuredRoot);
44750
45060
  scan.complete &&= childScan.complete;
44751
45061
  scan.hasSkills ||= childScan.hasSkills;
44752
45062
  scan.entries += childScan.entries;
@@ -44882,7 +45192,7 @@ function configureHooks(config, agent, command, profileId, nativeReady) {
44882
45192
  function disableCodexSkills(text2, skills, aliases, bridgePath) {
44883
45193
  const bundled = disableCodexBundledSkills(text2);
44884
45194
  let result = normalizeCodexInlinePathConfig(bundled);
44885
- 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));
44886
45196
  const previousConfig = Bun.TOML.parse(bundled).skills?.config;
44887
45197
  if (previousConfig !== undefined && (!Array.isArray(previousConfig) || previousConfig.some((entry) => !entry || typeof entry !== "object" || entry.path !== undefined && entry.name !== undefined)))
44888
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");
@@ -44894,7 +45204,7 @@ function disableCodexSkills(text2, skills, aliases, bridgePath) {
44894
45204
  result = result.replace(CODEX_SKILL_CONFIG_SECTIONS, (section) => {
44895
45205
  const parsed = Bun.TOML.parse(section);
44896
45206
  const declared = parsed.skills?.config?.[0];
44897
- 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))))
44898
45208
  return section;
44899
45209
  found = true;
44900
45210
  return /^\s*enabled\s*=/m.test(section) ? section.replace(/^\s*enabled\s*=.*$/m, `enabled = ${skill.enabled}`) : `${section.trimEnd()}
@@ -44915,7 +45225,7 @@ enabled = false
44915
45225
  return result;
44916
45226
  }
44917
45227
  function assertCodexInstallationInputs(home, projectDirs, inputs) {
44918
- 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)));
44919
45229
  if (inputs.some((input) => nativeRoots.some((root2) => root2 === input || root2.startsWith(input + sep7) || input.startsWith(root2 + sep7))))
44920
45230
  throw new Error("Native installation input overlaps an unconditional skill-loading root");
44921
45231
  }
@@ -44931,9 +45241,9 @@ function planAgentIntegration(options) {
44931
45241
  throw new Error("Invalid existing Skills bridge policy");
44932
45242
  if (policy.bridge?.agents !== undefined && (!Array.isArray(policy.bridge.agents) || policy.bridge.agents.some((agent) => !INTEGRATION_AGENTS.includes(agent))))
44933
45243
  throw new Error("Invalid existing bridge agent inventory");
44934
- for (const field2 of ["commands", "profiles"])
44935
- 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"))))
44936
- 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`);
44937
45247
  const priorAgents = policy.bridge?.agents ?? [];
44938
45248
  const profileId = options.profileId ?? policy.profileId ?? "default";
44939
45249
  const validateProfile = (value) => {
@@ -44948,13 +45258,18 @@ function planAgentIntegration(options) {
44948
45258
  return [agent, { command, profileId: profileId2 }];
44949
45259
  }));
44950
45260
  const retainedAgents = [];
45261
+ const priorExecutables = policy.bridge?.discoveryExecutables ?? {};
45262
+ const executables = new Map;
44951
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);
44952
45267
  const retainedReview = options.discoveryInputs === undefined && policy.bridge?.discovery?.[agent]?.method === "reviewed" ? { ...policy.bridge.discovery[agent], ...agent === "codex" ? { codexDisabledPluginSkills: policy.bridge.codexPluginSkills ?? [] } : {} } : undefined;
44953
45268
  if (retainedReview) {
44954
45269
  assertManagedAgentBridge(agent, { home, dataDir: dataDir2, projectDir: options.projectDir ?? home });
44955
45270
  retainedAgents.push(agent);
44956
45271
  }
44957
- 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 });
44958
45273
  });
44959
45274
  const codexConfigBefore = options.agents.includes("codex") ? readOptional(canonicalAgentPath(join27(home, ".codex", "config.toml"), aliases)) : null;
44960
45275
  const codexConfig = Bun.TOML.parse(codexConfigBefore ?? "");
@@ -44962,7 +45277,7 @@ function planAgentIntegration(options) {
44962
45277
  const codexPathConfig = options.agents.includes("codex") ? disableCodexSkills(codexConfigBefore ?? "", nativeSkills, aliases, canonicalAgentPath(join27(home, ".codex/skills", CLI_BRIDGE_NAME), aliases)) : undefined;
44963
45278
  const plannedCodexRules = codexPathConfig === undefined ? undefined : Bun.TOML.parse(codexPathConfig).skills?.config ?? [];
44964
45279
  const observedNativeSources = [];
44965
- 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) => {
44966
45281
  const bytes = readNativeBytes(path, 1024 * 1024);
44967
45282
  observedNativeSources.push({ path, sha256: sha4(bytes) });
44968
45283
  return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
@@ -45083,7 +45398,7 @@ function planAgentIntegration(options) {
45083
45398
  const { codexInstallationInputs: previousInputs, ...current } = rebound;
45084
45399
  const inputs = codexPluginSourceInputs.map((input) => input.sourceRoot);
45085
45400
  const directories = options.codexNativeCatalog || !previousInputs ? captureDiscoveryDirectories((binding.directories ?? []).filter((directory) => inputs.some((root2) => root2.startsWith(directory.path + sep7))).map((directory) => directory.path), inputs) : previousInputs.directories;
45086
- const installed = codexPluginSourceInputs.length ? { ...current, codexInstallationInputs: { version: "codex-cli 0.160.0", catalogSha256: codexPluginSkillReview.catalogSha256, plugins: codexPluginSourceInputs, ...directories?.length ? { directories } : {} } } : current;
45401
+ const installed = codexPluginSourceInputs.length ? { ...current, codexInstallationInputs: { version: codexPluginSkillReview.version, catalogSha256: codexPluginSkillReview.catalogSha256, plugins: codexPluginSourceInputs, ...directories?.length ? { directories } : {} } } : current;
45087
45402
  return captureRetiredCodexDiscovery(installed, codexPluginSkills, Bun.TOML.parse(changes.find((change) => change.path === canonicalAgentPath(join27(home, ".codex/config.toml"), aliases))?.after ?? codexConfigBefore ?? "").skills?.config ?? []);
45088
45403
  });
45089
45404
  const nextPolicy = { ...policy, version: 1, loading: "cli", profileId, bridge: {
@@ -45091,7 +45406,7 @@ function planAgentIntegration(options) {
45091
45406
  version: CLI_BRIDGE_VERSION,
45092
45407
  digest: CLI_BRIDGE_DIGEST,
45093
45408
  agents: [...new Set([...priorAgents, ...options.agents])].sort(),
45094
- home: resolve18(home),
45409
+ home: resolve20(home),
45095
45410
  includeVendor: true,
45096
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)) } } } : {},
45097
45412
  commands: { ...policy.bridge?.commands, ...Object.fromEntries([...bindings].map(([agent, binding]) => [agent, binding.command])) },
@@ -45101,19 +45416,30 @@ function planAgentIntegration(options) {
45101
45416
  ...options.codexNativeCatalog || codexPluginSkills.length || codexInactivePlugins.length || codexPluginSourceInputs.length ? { codexPluginSkills, codexInactivePlugins, codexPluginSkillReview } : {},
45102
45417
  discovery: { ...policy.bridge?.discovery, ...Object.fromEntries(discoveryAfter.map((binding) => [binding.agent, binding])) }
45103
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;
45104
45430
  const serializedPolicy = serializeManagedSkillPolicy(nextPolicy);
45105
45431
  if (JSON.stringify(policy) !== JSON.stringify(nextPolicy))
45106
45432
  changes.push({ path: policyPath, before: previousPolicy, after: serializedPolicy });
45107
45433
  recheckRootAliases(aliases);
45108
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 } } : {} };
45109
45435
  }
45110
- function hookProjectionRefusal(reason) {
45111
- throw new Error(`CLAUDE_MANAGED_HOOK_${reason}`);
45436
+ function hookProjectionRefusal(reason2) {
45437
+ throw new Error(`CLAUDE_MANAGED_HOOK_${reason2}`);
45112
45438
  }
45113
45439
  function projectedHookAcl(path, observed) {
45114
45440
  if (process.platform !== "darwin")
45115
45441
  return;
45116
- 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}`;
45117
45443
  const fd = openSync18(path, constants15.O_RDONLY | constants15.O_NOFOLLOW | constants15.O_NONBLOCK | (observed.isDirectory() ? constants15.O_DIRECTORY : 0));
45118
45444
  try {
45119
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))
@@ -45124,18 +45450,18 @@ function projectedHookAcl(path, observed) {
45124
45450
  }
45125
45451
  function projectedHookExecutable(command, expectedResolved) {
45126
45452
  try {
45127
- if (!isAbsolute20(command) || /[\0\r\n]/.test(command) || resolve18(command) !== command)
45453
+ if (!isAbsolute22(command) || /[\0\r\n]/.test(command) || resolve20(command) !== command)
45128
45454
  hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
45129
45455
  command = canonicalSystemPath(command);
45130
45456
  const parents3 = (file = command) => {
45131
45457
  const result = [];
45132
- for (let path = dirname17(file);; path = dirname17(path)) {
45458
+ for (let path = dirname18(file);; path = dirname18(path)) {
45133
45459
  const stat2 = lstatSync23(path, { bigint: true });
45134
- 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))
45135
45461
  hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
45136
45462
  projectedHookAcl(path, stat2);
45137
45463
  result.push(`${path}:${stat2.dev}:${stat2.ino}:${stat2.uid}:${stat2.mode}`);
45138
- if (dirname17(path) === path)
45464
+ if (dirname18(path) === path)
45139
45465
  break;
45140
45466
  }
45141
45467
  return result;
@@ -45145,22 +45471,33 @@ function projectedHookExecutable(command, expectedResolved) {
45145
45471
  hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
45146
45472
  const linkIdentity = (stat2) => `${stat2.dev}:${stat2.ino}:${stat2.mode}:${stat2.uid}:${stat2.ctimeNs}`;
45147
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");
45148
45477
  if (expectedResolved !== undefined && resolved !== expectedResolved)
45149
45478
  hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
45150
45479
  let launcher, launcherParentIdentity;
45480
+ let runtime;
45151
45481
  if (target.pinned) {
45152
45482
  launcherParentIdentity = parents3(target.physical);
45153
45483
  launcher = snapshot(target.physical, false);
45154
45484
  projectedHookAcl(launcher.file, launcher.stat);
45155
45485
  if (launcher.sha256 !== target.pinned.sha256 || (launcher.stat.mode & 0o100n) === 0n)
45156
45486
  hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
45157
- 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);
45158
45495
  }
45159
45496
  const resolvedParentIdentity = parents3(resolved);
45160
- 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 });
45161
45498
  projectedHookAcl(manifest.file, manifest.stat);
45162
45499
  const pkg = JSON.parse(manifest.text);
45163
- 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"))
45164
45501
  hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
45165
45502
  const cli = snapshot(resolved, false, { readOnlyPackage: true });
45166
45503
  projectedHookAcl(cli.file, cli.stat);
@@ -45169,7 +45506,7 @@ function projectedHookExecutable(command, expectedResolved) {
45169
45506
  const recheck = () => {
45170
45507
  try {
45171
45508
  const again = resolveLauncherCommand(command);
45172
- 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))
45173
45510
  hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
45174
45511
  if (launcher) {
45175
45512
  if (!isDeepStrictEqual8(parents3(target.physical), launcherParentIdentity))
@@ -45177,6 +45514,12 @@ function projectedHookExecutable(command, expectedResolved) {
45177
45514
  projectedHookAcl(launcher.file, launcher.stat);
45178
45515
  unchanged2(launcher);
45179
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
+ }
45180
45523
  projectedHookAcl(cli.file, cli.stat);
45181
45524
  projectedHookAcl(manifest.file, manifest.stat);
45182
45525
  unchanged2(cli);
@@ -45203,7 +45546,7 @@ function planClaudeManagedHookProjection(options) {
45203
45546
  } catch {
45204
45547
  hookProjectionRefusal("TARGET_INVALID");
45205
45548
  }
45206
- const home = resolve18(options.home ?? homedir3()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
45549
+ const home = resolve20(options.home ?? homedir3()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
45207
45550
  const policyPath = join27(dataDir2, "agent-policy.json");
45208
45551
  let policyBytes, settingsBytes, settingsPath, command, profile;
45209
45552
  try {
@@ -45295,29 +45638,28 @@ function planClaudePreToolUseHookUpdate(options) {
45295
45638
  return planClaudeHookEventsUpdate({ ...options, events: ["PreToolUse"] });
45296
45639
  }
45297
45640
  function claudeSettingsConsumers(home, path, discoveries, aliases) {
45298
- const canonical7 = (value) => canonicalAgentPath(value, aliases);
45641
+ const canonical8 = (value) => canonicalAgentPath(value, aliases);
45299
45642
  const containsSettings = (root2) => {
45300
- const distance = relative5(canonical7(root2), path);
45301
- return distance === "" || distance !== ".." && !distance.startsWith(`..${sep7}`) && !isAbsolute20(distance);
45643
+ const distance = relative5(canonical8(root2), path);
45644
+ return distance === "" || distance !== ".." && !distance.startsWith(`..${sep7}`) && !isAbsolute22(distance);
45302
45645
  };
45303
- 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);
45304
45647
  }
45305
- function verifyCoordinatedDiscovery(binding, home, aliases) {
45648
+ function verifyCoordinatedDiscovery(binding, home, aliases, executable2) {
45306
45649
  try {
45307
45650
  if (binding.method !== "automatic" && binding.method !== "reviewed")
45308
45651
  throw new Error("Invalid managed discovery method");
45309
45652
  verifyAgentDiscovery(binding);
45310
- if (binding.method === "automatic") {
45311
- const current = resolveAgentDiscovery({ home, agent: binding.agent, canonical: (path) => canonicalAgentPath(path, aliases) });
45312
- if (JSON.stringify(current) !== JSON.stringify(binding))
45313
- throw new Error("Configured native discovery roots changed during Claude update");
45314
- }
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 });
45315
45655
  } catch (error) {
45656
+ if (isDiscoveryRootUnresolved(error))
45657
+ throw error;
45316
45658
  throw new Error(`NATIVE_SKILL_DRIFT: ${error.message}`);
45317
45659
  }
45318
45660
  }
45319
45661
  function planClaudeHookEventsUpdate(options) {
45320
- const home = resolve18(options.home ?? homedir3()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
45662
+ const home = resolve20(options.home ?? homedir3()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
45321
45663
  const policyPath = join27(dataDir2, "agent-policy.json");
45322
45664
  assertSafePath(policyPath);
45323
45665
  const snapshot2 = readManagedSkillPolicySnapshot(dataDir2);
@@ -45343,8 +45685,9 @@ function planClaudeHookEventsUpdate(options) {
45343
45685
  });
45344
45686
  if (discoveries.length !== agents.length || !agents.includes("claude"))
45345
45687
  throw new Error("Missing managed Claude discovery coverage");
45688
+ const discoveryExecutables = bridge.discoveryExecutables;
45346
45689
  for (const binding of discoveries)
45347
- verifyCoordinatedDiscovery(binding, home, aliases);
45690
+ verifyCoordinatedDiscovery(binding, home, aliases, discoveryExecutables?.[binding.agent]);
45348
45691
  const consumers = claudeSettingsConsumers(home, path, discoveries, aliases);
45349
45692
  for (const agent of consumers)
45350
45693
  assertManagedAgentBridge(agent, { home, dataDir: dataDir2, projectDir: home });
@@ -45379,13 +45722,14 @@ function planClaudeHookEventsUpdate(options) {
45379
45722
  observedPolicy: { path: policyPath, before: snapshot2.text },
45380
45723
  discoveryBefore: discoveries,
45381
45724
  discoveryAfter,
45725
+ ...discoveryExecutables ? { discoveryExecutables } : {},
45382
45726
  rootAliases: aliases,
45383
45727
  managedAgentChecks: { home, agents: consumers }
45384
45728
  };
45385
45729
  }
45386
45730
  function atomicWrite2(path, content) {
45387
45731
  assertSafePath(path);
45388
- mkdirSync6(dirname17(path), { recursive: true, mode: 448 });
45732
+ mkdirSync6(dirname18(path), { recursive: true, mode: 448 });
45389
45733
  const temporary = `${path}.skills-${randomUUID4()}`;
45390
45734
  try {
45391
45735
  writeFileSync5(temporary, content, { mode: 384, flag: "wx" });
@@ -45400,7 +45744,7 @@ function planAgentSettingsWitnessUpgrade(options) {
45400
45744
  throw new Error("Invalid Codex witness target version");
45401
45745
  if (options.targetClaudeVersion !== undefined && (options.agent !== "claude" || ![3, 4].includes(options.targetClaudeVersion)))
45402
45746
  throw new Error("Invalid Claude witness target version");
45403
- const home = resolve18(options.home ?? homedir3()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
45747
+ const home = resolve20(options.home ?? homedir3()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
45404
45748
  const snapshot2 = readManagedSkillPolicySnapshot(dataDir2);
45405
45749
  if (!snapshot2 || sha4(snapshot2.text) !== options.expectedPolicySha256)
45406
45750
  throw new Error("Managed policy preimage changed");
@@ -45460,7 +45804,7 @@ function planAgentSettingsWitnessUpgrade(options) {
45460
45804
  const replacement = { ...binding, sources: rebound };
45461
45805
  verifyAgentDiscovery(replacement);
45462
45806
  const after = serializeManagedSkillPolicy({ ...policy, bridge: { ...policy.bridge, discovery: { ...policy.bridge.discovery, [options.agent]: replacement } } });
45463
- 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 })) } };
45464
45808
  }
45465
45809
  function applyAgentIntegration(plan, options = {}) {
45466
45810
  const roots = plan.changes.flatMap((change) => {
@@ -45478,10 +45822,10 @@ function applyAgentIntegrationUnlocked(plan, options = {}, assertCurrent) {
45478
45822
  throw new Error("Native settings changed after witness planning");
45479
45823
  const policyPath = join27(plan.dataDir, "agent-policy.json");
45480
45824
  assertSafePath(policyPath);
45481
- 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);
45482
45826
  readManagedSkillPolicySnapshot(plan.dataDir);
45483
45827
  for (const change of plan.changes)
45484
- if (resolve18(change.path) === resolve18(policyPath))
45828
+ if (resolve20(change.path) === resolve20(policyPath))
45485
45829
  parseManagedSkillPolicy(change.after);
45486
45830
  const aliases = plan.rootAliases ?? [];
45487
45831
  assertCurrent();
@@ -45502,7 +45846,7 @@ function applyAgentIntegrationUnlocked(plan, options = {}, assertCurrent) {
45502
45846
  assertManagedAgentBridgeWithDiscovery(agent, { home: plan.managedAgentChecks.home, dataDir: plan.dataDir, projectDir: plan.managedAgentChecks.home }, provenDiscovery?.agent === agent ? provenDiscovery : undefined);
45503
45847
  for (const binding of plan.discoveryBefore ?? []) {
45504
45848
  if (plan.managedAgentChecks)
45505
- verifyCoordinatedDiscovery(binding, plan.managedAgentChecks.home, aliases);
45849
+ verifyCoordinatedDiscovery(binding, plan.managedAgentChecks.home, aliases, plan.discoveryExecutables?.[binding.agent]);
45506
45850
  else
45507
45851
  verifyAgentDiscovery(binding);
45508
45852
  }
@@ -45534,7 +45878,7 @@ function applyAgentIntegrationUnlocked(plan, options = {}, assertCurrent) {
45534
45878
  recheckRootAliases(aliases);
45535
45879
  if (currentText(change.path) !== change.before)
45536
45880
  throw new Error(`Configuration changed after planning: ${change.path}`);
45537
- for (let directory = dirname17(change.path);!existsSync7(directory); directory = dirname17(directory))
45881
+ for (let directory = dirname18(change.path);!existsSync7(directory); directory = dirname18(directory))
45538
45882
  createdDirectories.add(directory);
45539
45883
  const after = change.after;
45540
45884
  atomicWrite2(change.path, after);
@@ -45549,7 +45893,7 @@ function applyAgentIntegrationUnlocked(plan, options = {}, assertCurrent) {
45549
45893
  throw new Error("Native settings changed during witness application");
45550
45894
  for (const binding of plan.discoveryAfter ?? []) {
45551
45895
  if (plan.managedAgentChecks)
45552
- verifyCoordinatedDiscovery(binding, plan.managedAgentChecks.home, aliases);
45896
+ verifyCoordinatedDiscovery(binding, plan.managedAgentChecks.home, aliases, plan.discoveryExecutables?.[binding.agent]);
45553
45897
  else
45554
45898
  verifyAgentDiscovery(binding);
45555
45899
  }
@@ -45606,7 +45950,7 @@ function writeArchiveJournal(path, value) {
45606
45950
  closeSync18(descriptor);
45607
45951
  descriptor = undefined;
45608
45952
  renameSync4(temporary, path);
45609
- syncArchiveDirectory(dirname17(path));
45953
+ syncArchiveDirectory(dirname18(path));
45610
45954
  } finally {
45611
45955
  if (descriptor !== undefined)
45612
45956
  closeSync18(descriptor);
@@ -45664,14 +46008,14 @@ function archiveNativeSkillsUnlocked(inventory, options, assertCurrent) {
45664
46008
  };
45665
46009
  assertSafePath(archiveRoot);
45666
46010
  const created = [];
45667
- for (let path = archiveRoot;!existsSync7(path); path = dirname17(path))
46011
+ for (let path = archiveRoot;!existsSync7(path); path = dirname18(path))
45668
46012
  created.push(path);
45669
46013
  mkdirSync6(archiveRoot, { recursive: true, mode: 448 });
45670
46014
  try {
45671
46015
  for (const directory of created)
45672
46016
  syncArchiveDirectory(directory);
45673
46017
  if (created.length)
45674
- syncArchiveDirectory(dirname17(created.at(-1)));
46018
+ syncArchiveDirectory(dirname18(created.at(-1)));
45675
46019
  writeArchiveJournal(receiptPath, journal);
45676
46020
  for (const [index, entry] of selected.entries()) {
45677
46021
  assertCurrent();
@@ -45684,7 +46028,7 @@ function archiveNativeSkillsUnlocked(inventory, options, assertCurrent) {
45684
46028
  writeArchiveJournal(receiptPath, journal);
45685
46029
  renameSync4(move.source, move.archive);
45686
46030
  moved.push(move);
45687
- syncArchiveDirectory(dirname17(move.source));
46031
+ syncArchiveDirectory(dirname18(move.source));
45688
46032
  syncArchiveDirectory(archiveRoot);
45689
46033
  verifyArchive(move);
45690
46034
  move.status = "archived";
@@ -45721,7 +46065,7 @@ function archiveNativeSkillsUnlocked(inventory, options, assertCurrent) {
45721
46065
  }
45722
46066
  if (entry.discoveryOnly) {
45723
46067
  linkSync3(entry.archive, entry.source);
45724
- syncArchiveDirectory(dirname17(entry.source));
46068
+ syncArchiveDirectory(dirname18(entry.source));
45725
46069
  unlinkSync5(entry.archive);
45726
46070
  } else {
45727
46071
  if (lstatSync23(entry.source, { throwIfNoEntry: false })) {
@@ -45732,7 +46076,7 @@ function archiveNativeSkillsUnlocked(inventory, options, assertCurrent) {
45732
46076
  renameSync4(entry.archive, entry.source);
45733
46077
  }
45734
46078
  entry.status = "restored";
45735
- syncArchiveDirectory(dirname17(entry.source));
46079
+ syncArchiveDirectory(dirname18(entry.source));
45736
46080
  syncArchiveDirectory(archiveRoot);
45737
46081
  } catch {
45738
46082
  entry.status = "recovery-required";
@@ -45757,7 +46101,7 @@ function isInertCodexPluginCacheCopy(entry, cache, allowedHostPaths, read3) {
45757
46101
  return false;
45758
46102
  const document2 = join27(entry.path, "SKILL.md");
45759
46103
  const inside = relative5(cache, entry.path);
45760
- if (!inside || isAbsolute20(inside) || inside.split(sep7).some((segment) => segment === ".."))
46104
+ if (!inside || isAbsolute22(inside) || inside.split(sep7).some((segment) => segment === ".."))
45761
46105
  return false;
45762
46106
  assertSafePath(entry.path);
45763
46107
  if (!lstatSync23(cache).isDirectory() || !lstatSync23(entry.path).isDirectory() || !lstatSync23(document2).isFile())
@@ -45777,7 +46121,7 @@ function assertManagedAgentBridge(agent, options = {}) {
45777
46121
  assertManagedAgentBridgeWithDiscovery(agent, options);
45778
46122
  }
45779
46123
  function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscovery) {
45780
- const home = resolve18(options.home ?? homedir3()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
46124
+ const home = resolve20(options.home ?? homedir3()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
45781
46125
  assertSafePath(join27(dataDir2, "agent-policy.json"));
45782
46126
  const snapshot2 = readManagedSkillPolicySnapshot(dataDir2);
45783
46127
  if (!snapshot2)
@@ -45875,12 +46219,11 @@ function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscov
45875
46219
  verifyAgentDiscovery(agent === "codex" ? { ...discovery, codexDisabledPluginSkills: binding.codexPluginSkills ?? [] } : discovery, options.codexDiscoveryRecovery);
45876
46220
  if (agent === "sumi" && discovery.method === "reviewed")
45877
46221
  resolveAgentDiscovery({ home, agent, retainedReview: discovery, canonical: (path) => canonicalAgentPath(path, aliases) });
45878
- if (discovery.method === "automatic") {
45879
- const current = resolveAgentDiscovery({ home, agent, canonical: (path) => canonicalAgentPath(path, aliases) });
45880
- if (JSON.stringify(current) !== JSON.stringify(discovery))
45881
- throw new Error("Configured native discovery roots changed");
45882
- }
46222
+ if (discovery.method === "automatic")
46223
+ verifyAutomaticDiscoveryClosure(discovery, { home, canonical: (path) => canonicalAgentPath(path, aliases), change: "Configured native discovery roots changed", executable: binding.discoveryExecutables?.[agent] });
45883
46224
  } catch (error) {
46225
+ if (isDiscoveryRootUnresolved(error))
46226
+ throw error;
45884
46227
  throw new Error(`NATIVE_SKILL_DRIFT: ${error.message}`);
45885
46228
  }
45886
46229
  let installationInputRoots = [];
@@ -45936,13 +46279,13 @@ import {
45936
46279
  statSync as statSync10,
45937
46280
  writeFileSync as writeFileSync7
45938
46281
  } from "fs";
45939
- 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";
45940
46283
 
45941
46284
  // src/lib/registry-data/index.ts
45942
46285
  var SKILLS = [];
45943
46286
 
45944
46287
  // src/lib/skill-hash.ts
45945
- import { createHash as createHash25 } from "crypto";
46288
+ import { createHash as createHash26 } from "crypto";
45946
46289
  import { existsSync as existsSync8, readdirSync as readdirSync9, readFileSync as readFileSync18, statSync as statSync8 } from "fs";
45947
46290
  import { join as join28, sep as sep8 } from "path";
45948
46291
  var CONTENT_HASH_ALGORITHM = "sha256";
@@ -46066,13 +46409,13 @@ function* bundleHashParts(files) {
46066
46409
  yield new TextEncoder().encode("\x00");
46067
46410
  }
46068
46411
  function hashBundleFiles(files) {
46069
- const hash2 = createHash25(CONTENT_HASH_ALGORITHM);
46412
+ const hash2 = createHash26(CONTENT_HASH_ALGORITHM);
46070
46413
  for (const part of bundleHashParts(files))
46071
46414
  hash2.update(part);
46072
46415
  return hash2.digest("hex");
46073
46416
  }
46074
46417
  async function hashBundleFilesCooperatively(files, check) {
46075
- const hash2 = createHash25(CONTENT_HASH_ALGORITHM);
46418
+ const hash2 = createHash26(CONTENT_HASH_ALGORITHM);
46076
46419
  let bytesSinceYield = 0;
46077
46420
  for (const part of bundleHashParts(files)) {
46078
46421
  for (let offset = 0;offset < part.byteLength; offset += 64 * 1024) {
@@ -46081,7 +46424,7 @@ async function hashBundleFilesCooperatively(files, check) {
46081
46424
  hash2.update(chunk);
46082
46425
  bytesSinceYield += chunk.byteLength;
46083
46426
  if (bytesSinceYield >= 256 * 1024) {
46084
- await new Promise((resolve19) => setImmediate(resolve19));
46427
+ await new Promise((resolve21) => setImmediate(resolve21));
46085
46428
  bytesSinceYield = 0;
46086
46429
  }
46087
46430
  }
@@ -46204,8 +46547,8 @@ function boundedManifest(raw, maxDepth) {
46204
46547
  continue;
46205
46548
  if (depth > maxDepth)
46206
46549
  contentLimit("Content hash manifest depth limit exceeded");
46207
- for (const child of Object.values(value))
46208
- pending.push({ value: child, depth: depth + 1 });
46550
+ for (const child2 of Object.values(value))
46551
+ pending.push({ value: child2, depth: depth + 1 });
46209
46552
  }
46210
46553
  return parsed;
46211
46554
  }
@@ -46234,7 +46577,7 @@ async function hashContentEntries(entries, options) {
46234
46577
  const normalized = [];
46235
46578
  let normalizedBytes = 0;
46236
46579
  let manifest;
46237
- await new Promise((resolve19) => setImmediate(resolve19));
46580
+ await new Promise((resolve21) => setImmediate(resolve21));
46238
46581
  for (const entry of snapshot2) {
46239
46582
  check();
46240
46583
  if (!coveredContentPath(entry.path))
@@ -46247,7 +46590,7 @@ async function hashContentEntries(entries, options) {
46247
46590
  contentLimit("Content hash normalized byte limit exceeded");
46248
46591
  normalizedBytes += file.content.byteLength;
46249
46592
  normalized.push(file);
46250
- await new Promise((resolve19) => setImmediate(resolve19));
46593
+ await new Promise((resolve21) => setImmediate(resolve21));
46251
46594
  }
46252
46595
  normalized.sort((a, b) => a.rel < b.rel ? -1 : a.rel > b.rel ? 1 : 0);
46253
46596
  check();
@@ -46461,7 +46804,7 @@ import {
46461
46804
  realpathSync as realpathSync12,
46462
46805
  writeFileSync as writeFileSync6
46463
46806
  } from "fs";
46464
- 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";
46465
46808
  var ANY_SEGMENT_COPY_EXCLUDES = new Set([
46466
46809
  ".git",
46467
46810
  ".DS_Store",
@@ -46511,11 +46854,11 @@ function normalizeNewPortableSkillName(name) {
46511
46854
  throw new Error(`Invalid skill name '${name}'. Include letters or numbers.`);
46512
46855
  return normalized;
46513
46856
  }
46514
- function readPortableSkillManifest(skillPath, fallbackName = basename9(skillPath)) {
46857
+ function readPortableSkillManifest(skillPath, fallbackName = basename10(skillPath)) {
46515
46858
  return readManifest(skillPath, fallbackName, normalizePortableSkillName);
46516
46859
  }
46517
46860
  function readPortableSkillManifestForImport(skillPath) {
46518
- return readManifest(skillPath, basename9(skillPath), normalizeNewPortableSkillName);
46861
+ return readManifest(skillPath, basename10(skillPath), normalizeNewPortableSkillName);
46519
46862
  }
46520
46863
  function readManifest(skillPath, fallbackName, normalizeName) {
46521
46864
  const skillJsonPath = join29(skillPath, "skill.json");
@@ -46708,7 +47051,7 @@ function ensurePortableSkillFiles(skillPath, manifest) {
46708
47051
  };
46709
47052
  const entry = next.commands[0]?.entry ?? "src/index.ts";
46710
47053
  if (entry && !existsSync9(join29(skillPath, entry))) {
46711
- mkdirSync7(dirname18(join29(skillPath, entry)), { recursive: true });
47054
+ mkdirSync7(dirname19(join29(skillPath, entry)), { recursive: true });
46712
47055
  writeFileSync6(join29(skillPath, entry), renderEntrypoint(next));
46713
47056
  }
46714
47057
  if (!existsSync9(join29(skillPath, "SKILL.md")))
@@ -47069,7 +47412,7 @@ function inferRuntimeFromCommands(commands) {
47069
47412
  function readJsonObject(path) {
47070
47413
  const parsed = JSON.parse(readFileSync19(path, "utf-8"));
47071
47414
  if (!isRecord3(parsed))
47072
- throw new Error(`${basename9(path)} must contain a JSON object`);
47415
+ throw new Error(`${basename10(path)} must contain a JSON object`);
47073
47416
  return parsed;
47074
47417
  }
47075
47418
  function hasPackageDependencies(pkgPath) {
@@ -47107,10 +47450,10 @@ function escapeJsString(value) {
47107
47450
  // src/lib/authoring-path.ts
47108
47451
  import { lstatSync as lstatSync25, realpathSync as realpathSync13 } from "fs";
47109
47452
  import { homedir as homedir4 } from "os";
47110
- 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";
47111
47454
  var NATIVE_DISCOVERY_ROOTS = NATIVE_SKILL_ROOTS.map(([, path]) => path.split("/"));
47112
47455
  function pathParts(path) {
47113
- return resolve19(path).split(sep9).filter(Boolean);
47456
+ return resolve21(path).split(sep9).filter(Boolean);
47114
47457
  }
47115
47458
  function nativeRootMatch(path) {
47116
47459
  const parts = pathParts(path);
@@ -47124,16 +47467,16 @@ function nativeRootMatch(path) {
47124
47467
  return;
47125
47468
  }
47126
47469
  function physicalPath(path) {
47127
- let cursor = resolve19(path);
47470
+ let cursor = resolve21(path);
47128
47471
  const suffix = [];
47129
47472
  while (!lstatSync25(cursor, { throwIfNoEntry: false })) {
47130
- suffix.unshift(basename10(cursor));
47131
- const parent = dirname19(cursor);
47473
+ suffix.unshift(basename11(cursor));
47474
+ const parent = dirname20(cursor);
47132
47475
  if (parent === cursor)
47133
- return resolve19(path);
47476
+ return resolve21(path);
47134
47477
  cursor = parent;
47135
47478
  }
47136
- return resolve19(realpathSync13(cursor), ...suffix);
47479
+ return resolve21(realpathSync13(cursor), ...suffix);
47137
47480
  }
47138
47481
  function contains(root2, path) {
47139
47482
  return path === root2 || path.startsWith(root2 + sep9);
@@ -47141,7 +47484,7 @@ function contains(root2, path) {
47141
47484
  function configuredRoots(home, explicitHome) {
47142
47485
  const homeData = join30(home, ".hasna", "skills");
47143
47486
  const homePolicy = readManagedSkillPolicySnapshot(homeData);
47144
- const configuredPolicy = !explicitHome && resolve19(getDataDirReadOnly()) !== resolve19(homeData) ? readManagedSkillPolicySnapshot(getDataDirReadOnly()) : null;
47487
+ const configuredPolicy = !explicitHome && resolve21(getDataDirReadOnly()) !== resolve21(homeData) ? readManagedSkillPolicySnapshot(getDataDirReadOnly()) : null;
47145
47488
  const policy = homePolicy ?? configuredPolicy;
47146
47489
  const bridge = policy?.value.bridge;
47147
47490
  if (bridge && (typeof bridge.home !== "string" || physicalPath(bridge.home) !== physicalPath(home))) {
@@ -47180,22 +47523,22 @@ function configuredRoots(home, explicitHome) {
47180
47523
  function assertPortableAuthoringPath(path, options = {}) {
47181
47524
  if (typeof path !== "string" || !path || path.includes("\x00"))
47182
47525
  throw new Error("Invalid portable authoring path");
47183
- const lexical = resolve19(path);
47526
+ const lexical = resolve21(path);
47184
47527
  const physical = physicalPath(lexical);
47185
47528
  const candidates = [lexical, physical];
47186
47529
  let native = candidates.map(nativeRootMatch).find(Boolean);
47187
- const home = resolve19(options.homeDir ?? homedir4());
47530
+ const home = resolve21(options.homeDir ?? homedir4());
47188
47531
  const defaults = NATIVE_DISCOVERY_ROOTS.map((parts) => join30(home, ...parts));
47189
47532
  defaults.push(join30(home, ".codex/plugins/cache"), join30(home, ".claude/plugins/cache"), join30(home, ".claude/plugins/synced"), join30(home, ".gemini/extensions"));
47190
47533
  for (const root2 of defaults) {
47191
- 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)))
47192
47535
  native ??= root2;
47193
47536
  }
47194
47537
  if (native) {
47195
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.`);
47196
47539
  }
47197
47540
  for (const root2 of configuredRoots(home, options.homeDir !== undefined)) {
47198
- 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))) {
47199
47542
  throw new Error(`Refusing portable Skills authoring below configured native discovery root: ${lexical}`);
47200
47543
  }
47201
47544
  }
@@ -47343,20 +47686,20 @@ function isSkillCandidate(dir) {
47343
47686
  return existsSync10(join31(dir, "SKILL.md")) || existsSync10(join31(dir, "skill.json")) || existsSync10(join31(dir, "package.json"));
47344
47687
  }
47345
47688
  function physicalImportPath(path) {
47346
- let ancestor = resolve20(path);
47689
+ let ancestor = resolve22(path);
47347
47690
  const suffix = [];
47348
47691
  while (!existsSync10(ancestor)) {
47349
- suffix.unshift(basename11(ancestor));
47350
- ancestor = dirname20(ancestor);
47692
+ suffix.unshift(basename12(ancestor));
47693
+ ancestor = dirname21(ancestor);
47351
47694
  }
47352
47695
  return join31(realpathSync14(ancestor), ...suffix);
47353
47696
  }
47354
47697
  function assertDisjointImportPaths(source, destination) {
47355
47698
  const sourcePath = realpathSync14(source);
47356
47699
  const destinationPath = physicalImportPath(destination);
47357
- const contains2 = (parent, child) => {
47358
- const path = relative7(parent, child);
47359
- 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}`);
47360
47703
  };
47361
47704
  if (contains2(sourcePath, destinationPath) || contains2(destinationPath, sourcePath)) {
47362
47705
  throw new Error("Source and destination skill directories must not overlap");
@@ -47371,8 +47714,8 @@ function portPortableSkill(sourcePath, options = {}) {
47371
47714
  const explicitName = options.name != null;
47372
47715
  const skillName = normalizeNewPortableSkillName(options.name ?? inferred.name);
47373
47716
  if (isOfficialSkillName(skillName) && !options.allowShadow) {
47374
- const sourceSlug = safeNormalizeName(basename11(absoluteSource));
47375
- 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.`;
47376
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.`);
47377
47720
  }
47378
47721
  const readOnlyDestination = join31(resolvePortableSkillsRoot(options, false), skillName);
@@ -47387,7 +47730,7 @@ function portPortableSkill(sourcePath, options = {}) {
47387
47730
  throw new Error(`Skill '${skillName}' already exists at ${destination}`);
47388
47731
  rmSync2(destination, { recursive: true, force: true });
47389
47732
  }
47390
- mkdirSync8(dirname20(destination), { recursive: true });
47733
+ mkdirSync8(dirname21(destination), { recursive: true });
47391
47734
  copySkillDirectory(absoluteSource, destination);
47392
47735
  const base = {
47393
47736
  ...inferred,
@@ -47637,7 +47980,7 @@ function safeIsDirectory(path) {
47637
47980
  }
47638
47981
  }
47639
47982
  function isSafeRelativePath2(value) {
47640
- if (!value.trim() || isAbsolute21(value))
47983
+ if (!value.trim() || isAbsolute23(value))
47641
47984
  return false;
47642
47985
  const normalized = normalize4(value).replace(/\\/g, "/");
47643
47986
  return normalized !== ".." && !normalized.startsWith("../") && !normalized.includes("/../");
@@ -47898,9 +48241,9 @@ function writeManagedSkillDirUnlocked(dir, skillMd, options, assertCurrent) {
47898
48241
  const action = dirExists ? "update" : "create";
47899
48242
  if (options.dryRun)
47900
48243
  return { action, path: skillMdPath };
47901
- const parentDir = dirname21(dir);
48244
+ const parentDir = dirname22(dir);
47902
48245
  mkdirSync9(parentDir, { recursive: true });
47903
- const transactionDir = mkdtempSync2(join32(parentDir, `.hasna-skills-write-${basename12(dir)}-`));
48246
+ const transactionDir = mkdtempSync2(join32(parentDir, `.hasna-skills-write-${basename13(dir)}-`));
47904
48247
  const candidateDir = join32(transactionDir, "candidate");
47905
48248
  const backupDir = join32(transactionDir, "backup");
47906
48249
  const candidateSkillMdPath = join32(candidateDir, "SKILL.md");
@@ -49287,11 +49630,11 @@ async function executeSelectedLocal(selected, options = {}) {
49287
49630
  throw new SkillSelectionError("INVALID_BUNDLE_PATH", "The execution bundle path exceeds its limit.");
49288
49631
  });
49289
49632
  const destination = join37(runDirectory, entry.path);
49290
- mkdirSync11(dirname22(destination), { recursive: true, mode: 448 });
49633
+ mkdirSync11(dirname23(destination), { recursive: true, mode: 448 });
49291
49634
  writeFileSync10(destination, entry.bytes, { flag: "wx", mode: entry.mode & 511 });
49292
49635
  }
49293
49636
  env.SKILLS_INPUT_JSON = input;
49294
- env.SKILLS_WORKSPACE_DIR = resolve21(options.cwd ?? process.cwd());
49637
+ env.SKILLS_WORKSPACE_DIR = resolve23(options.cwd ?? process.cwd());
49295
49638
  env.SKILLS_RUN_DIR = runDirectory;
49296
49639
  if (runtime.version) {
49297
49640
  const version = await subprocess([executable2, ...runtimeName === "bun" ? ["--no-env-file"] : [], "--version"], runDirectory, env, "", Math.min(timeoutMs, 5000));
@@ -49321,7 +49664,7 @@ async function executeSelectedLocal(selected, options = {}) {
49321
49664
  selection: selection2,
49322
49665
  target: "local",
49323
49666
  runtime: runtimeName,
49324
- inputDigest: `sha256:${createHash26("sha256").update(input).digest("hex")}`,
49667
+ inputDigest: `sha256:${createHash27("sha256").update(input).digest("hex")}`,
49325
49668
  runDirectory,
49326
49669
  ...executionGrant ? { executionGrant } : {},
49327
49670
  ...bindings ? { secretBinding: { schema: bindings.schema, selection: bindings.selection, consumer: bindings.consumer, secretsAuthority: bindings.secretsAuthority, bindings: bindings.bindings } } : {},
@@ -49332,17 +49675,17 @@ async function executeSelectedLocal(selected, options = {}) {
49332
49675
  }
49333
49676
  async function subprocess(command, cwd, env, input, timeoutMs) {
49334
49677
  return new Promise((resolveResult) => {
49335
- 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"] });
49336
49679
  let outputBytes = 0, error, ended = false;
49337
49680
  const stdout = [], stderr = [];
49338
49681
  const kill = () => {
49339
49682
  try {
49340
- if (process.platform !== "win32" && child.pid)
49341
- process.kill(-child.pid, "SIGKILL");
49683
+ if (process.platform !== "win32" && child2.pid)
49684
+ process.kill(-child2.pid, "SIGKILL");
49342
49685
  else
49343
- child.kill("SIGKILL");
49686
+ child2.kill("SIGKILL");
49344
49687
  } catch {
49345
- child.kill("SIGKILL");
49688
+ child2.kill("SIGKILL");
49346
49689
  }
49347
49690
  };
49348
49691
  const timer = setTimeout(() => {
@@ -49358,8 +49701,8 @@ async function subprocess(command, cwd, env, input, timeoutMs) {
49358
49701
  }
49359
49702
  target.push(chunk);
49360
49703
  };
49361
- child.stdout.on("data", capture2(stdout));
49362
- child.stderr.on("data", capture2(stderr));
49704
+ child2.stdout.on("data", capture2(stdout));
49705
+ child2.stderr.on("data", capture2(stderr));
49363
49706
  const finish = (code) => {
49364
49707
  if (ended)
49365
49708
  return;
@@ -49367,13 +49710,13 @@ async function subprocess(command, cwd, env, input, timeoutMs) {
49367
49710
  clearTimeout(timer);
49368
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 } : {} });
49369
49712
  };
49370
- child.on("error", () => {
49713
+ child2.on("error", () => {
49371
49714
  error = "LOCAL_RUNTIME_START_FAILED";
49372
49715
  finish(127);
49373
49716
  });
49374
- child.on("close", (code) => finish(code ?? 1));
49375
- child.stdin.on("error", () => {});
49376
- child.stdin.end(input);
49717
+ child2.on("close", (code) => finish(code ?? 1));
49718
+ child2.stdin.on("error", () => {});
49719
+ child2.stdin.end(input);
49377
49720
  });
49378
49721
  }
49379
49722
  // src/lib/remote-run-contract.ts
@@ -58611,7 +58954,7 @@ var import_node_http_handler2 = __toESM(require_dist_cjs6(), 1);
58611
58954
 
58612
58955
  // node_modules/@aws-sdk/checksums/dist-cjs/submodules/sha/index.js
58613
58956
  var { toUint8Array: toUint8Array2, concatBytes } = require_serde();
58614
- var { createHmac: createHmac2, createHash: createHash28 } = __require("crypto");
58957
+ var { createHmac: createHmac2, createHash: createHash29 } = __require("crypto");
58615
58958
  var { Sha256: Sha2562, Sha256Js, Sha256Node } = require_checksum();
58616
58959
  var BLOCK2 = 64;
58617
58960
  var DIGEST_LENGTH = 20;
@@ -58780,7 +59123,7 @@ class Sha1Js {
58780
59123
  }
58781
59124
  var hasNativeCrypto = (() => {
58782
59125
  try {
58783
- createHash28("sha1");
59126
+ createHash29("sha1");
58784
59127
  return true;
58785
59128
  } catch {
58786
59129
  return false;
@@ -58820,7 +59163,7 @@ function buildNativeClass() {
58820
59163
  this.finished = false;
58821
59164
  }
58822
59165
  createHash() {
58823
- return this.secret ? createHmac2("sha1", toBuffer(this.secret)) : createHash28("sha1");
59166
+ return this.secret ? createHmac2("sha1", toBuffer(this.secret)) : createHash29("sha1");
58824
59167
  }
58825
59168
  };
58826
59169
  }
@@ -59373,15 +59716,15 @@ function createCancelService(options) {
59373
59716
  }
59374
59717
 
59375
59718
  // src/sdk/amounts.ts
59376
- function assertCents(value, field2) {
59719
+ function assertCents(value, field3) {
59377
59720
  if (!Number.isSafeInteger(value) || value < 0) {
59378
- 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");
59379
59722
  }
59380
59723
  }
59381
- function assertReservationCents(value, field2) {
59382
- assertCents(value, field2);
59724
+ function assertReservationCents(value, field3) {
59725
+ assertCents(value, field3);
59383
59726
  if (value > 2147483647) {
59384
- throw new RangeError(field2 + " must not exceed 2147483647 cents per reservation");
59727
+ throw new RangeError(field3 + " must not exceed 2147483647 cents per reservation");
59385
59728
  }
59386
59729
  }
59387
59730
 
@@ -59389,10 +59732,10 @@ function assertReservationCents(value, field2) {
59389
59732
  import { Database as Database2 } from "bun:sqlite";
59390
59733
  import { randomUUID as randomUUID9 } from "crypto";
59391
59734
  import { mkdirSync as mkdirSync13 } from "fs";
59392
- import { dirname as dirname26 } from "path";
59735
+ import { dirname as dirname27 } from "path";
59393
59736
 
59394
59737
  // src/server/database-url.ts
59395
- import { isAbsolute as isAbsolute22, join as join39 } from "path";
59738
+ import { isAbsolute as isAbsolute24, join as join39 } from "path";
59396
59739
  import { fileURLToPath as fileURLToPath3 } from "url";
59397
59740
  var DEFAULT_SQLITE_FILENAME2 = "server.db";
59398
59741
  var SQLITE_MEMORY_PATH = ":memory:";
@@ -59428,7 +59771,7 @@ function resolveDatabaseTarget(raw) {
59428
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()}.`);
59429
59772
  }
59430
59773
  if (looksLikeSqlitePath(value)) {
59431
- const path = isAbsolute22(value) ? value : join39(process.cwd(), value);
59774
+ const path = isAbsolute24(value) ? value : join39(process.cwd(), value);
59432
59775
  return { kind: "sqlite", path, durable: true, label: `sqlite (${path})` };
59433
59776
  }
59434
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()}.`);
@@ -59452,7 +59795,7 @@ function sqlitePathFromUrl(value, scheme) {
59452
59795
  }
59453
59796
  return rest.slice(2).replace(/^\/\/+/, "/");
59454
59797
  }
59455
- return isAbsolute22(rest) ? rest : join39(process.cwd(), rest);
59798
+ return isAbsolute24(rest) ? rest : join39(process.cwd(), rest);
59456
59799
  }
59457
59800
  function looksLikeSqlitePath(value) {
59458
59801
  if (value.includes("/"))
@@ -59685,12 +60028,12 @@ class PostgresSkillSelectionStore {
59685
60028
  // src/server/sqlite-store.ts
59686
60029
  import { randomUUID as randomUUID8 } from "crypto";
59687
60030
  import { mkdirSync as mkdirSync12, readFileSync as readFileSync26, readdirSync as readdirSync13 } from "fs";
59688
- import { dirname as dirname25, join as join41 } from "path";
60031
+ import { dirname as dirname26, join as join41 } from "path";
59689
60032
 
59690
60033
  // src/server/auth.ts
59691
- import { createHash as createHash29 } from "crypto";
60034
+ import { createHash as createHash30 } from "crypto";
59692
60035
  function hashApiKey(token) {
59693
- return createHash29("sha256").update(token).digest("hex");
60036
+ return createHash30("sha256").update(token).digest("hex");
59694
60037
  }
59695
60038
  function bearerToken(request2) {
59696
60039
  const header = request2.headers.get("authorization") || "";
@@ -59744,7 +60087,7 @@ function permitsSkillsRoute(principal, method, resource) {
59744
60087
 
59745
60088
  // src/server/migrations-dir.ts
59746
60089
  import { existsSync as existsSync16 } from "fs";
59747
- import { dirname as dirname24, join as join40 } from "path";
60090
+ import { dirname as dirname25, join as join40 } from "path";
59748
60091
  var MIGRATION_DIALECTS = ["postgres", "sqlite"];
59749
60092
  var MAX_WALK_UP = 6;
59750
60093
  function findMigrationsRoot(startDirs = defaultStartDirs()) {
@@ -59754,7 +60097,7 @@ function findMigrationsRoot(startDirs = defaultStartDirs()) {
59754
60097
  const candidate2 = join40(dir, "migrations");
59755
60098
  if (MIGRATION_DIALECTS.some((dialect) => existsSync16(join40(candidate2, dialect))))
59756
60099
  return candidate2;
59757
- const parent = dirname24(dir);
60100
+ const parent = dirname25(dir);
59758
60101
  if (parent === dir)
59759
60102
  break;
59760
60103
  dir = parent;
@@ -60009,12 +60352,12 @@ class SkillLifecycleConflictError extends Error {
60009
60352
  }
60010
60353
  }
60011
60354
  function validOperatorScopeEnrollmentInput(input) {
60012
- const bounded = (value, max = 256) => typeof value === "string" && value.length > 0 && value.length <= max && !/[\u0000-\u001f\u007f]/.test(value);
60013
- 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));
60014
60357
  }
60015
60358
 
60016
60359
  // src/lib/revision.ts
60017
- import { createHash as createHash30 } from "crypto";
60360
+ import { createHash as createHash31 } from "crypto";
60018
60361
  var REVISION_ID_PATTERN = /^[0-9a-f]{64}$/;
60019
60362
  function revisionIdOf(content) {
60020
60363
  const canonicalContent = {
@@ -60035,8 +60378,8 @@ function revisionIdOf(content) {
60035
60378
  canonicalContent.archiveReason = content.archiveReason ?? null;
60036
60379
  canonicalContent.replacementSlug = content.replacementSlug ?? null;
60037
60380
  }
60038
- const canonical7 = JSON.stringify(canonicalContent);
60039
- return createHash30("sha256").update(canonical7).digest("hex");
60381
+ const canonical8 = JSON.stringify(canonicalContent);
60382
+ return createHash31("sha256").update(canonical8).digest("hex");
60040
60383
  }
60041
60384
  function revisionIdOfRecord(record4) {
60042
60385
  return revisionIdOf(record4);
@@ -60061,7 +60404,7 @@ class SqliteSkillsStore {
60061
60404
  constructor(path = SQLITE_MEMORY_PATH, options = {}) {
60062
60405
  const inMemory = path === SQLITE_MEMORY_PATH;
60063
60406
  if (!inMemory)
60064
- mkdirSync12(dirname25(path), { recursive: true });
60407
+ mkdirSync12(dirname26(path), { recursive: true });
60065
60408
  this.db = openDatabase(path);
60066
60409
  this.db.exec(`PRAGMA busy_timeout = ${Math.max(0, options.busyTimeoutMs ?? 5000)}`);
60067
60410
  if (!inMemory)
@@ -60778,8 +61121,8 @@ function openDatabase(path) {
60778
61121
  try {
60779
61122
  return new Database(path, { create: true, readwrite: true });
60780
61123
  } catch (error) {
60781
- const reason = error instanceof Error ? error.message : String(error);
60782
- 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 });
60783
61126
  }
60784
61127
  }
60785
61128
  function parseScopes(value) {
@@ -60887,7 +61230,7 @@ class SqliteGovernanceStore {
60887
61230
  closed = false;
60888
61231
  constructor(path = SQLITE_MEMORY_PATH, options = {}) {
60889
61232
  if (path !== SQLITE_MEMORY_PATH)
60890
- mkdirSync13(dirname26(path), { recursive: true });
61233
+ mkdirSync13(dirname27(path), { recursive: true });
60891
61234
  this.db = new Database2(path, { create: true, readwrite: true });
60892
61235
  this.db.exec("PRAGMA busy_timeout = 5000");
60893
61236
  this.db.exec("PRAGMA foreign_keys = ON");
@@ -61120,7 +61463,7 @@ function nextMonthPrefix(monthPrefix) {
61120
61463
  }
61121
61464
 
61122
61465
  // src/server/skills-api.ts
61123
- import { createHash as createHash31 } from "crypto";
61466
+ import { createHash as createHash32 } from "crypto";
61124
61467
  var SLUG_PATTERN = /^[a-z0-9][a-z0-9._-]*$/;
61125
61468
  var SHA256_HEX2 = /^[0-9a-f]{64}$/;
61126
61469
  var MAX_SLUG_LENGTH = 128;
@@ -61310,7 +61653,7 @@ async function parsePublishRequest(request2, config) {
61310
61653
  if (bundleBytes.byteLength === 0) {
61311
61654
  throw new SkillRequestError(400, "BUNDLE_EMPTY", "the uploaded bundle is empty");
61312
61655
  }
61313
- const sha2563 = createHash31("sha256").update(bundleBytes).digest("hex");
61656
+ const sha2563 = createHash32("sha256").update(bundleBytes).digest("hex");
61314
61657
  const claimed = optionalString(manifest.bundleSha256);
61315
61658
  if (claimed)
61316
61659
  assertSha2562(claimed);
@@ -61425,7 +61768,7 @@ async function readPublishedBundle(store, artifactStorage, principal, slug) {
61425
61768
  if (!bytes) {
61426
61769
  throw new SkillRequestError(503, "BUNDLE_BACKEND_UNAVAILABLE", "bundle storage backend unavailable");
61427
61770
  }
61428
- const actual = createHash31("sha256").update(bytes).digest("hex");
61771
+ const actual = createHash32("sha256").update(bytes).digest("hex");
61429
61772
  if (actual !== record4.bundleSha256) {
61430
61773
  throw new SkillRequestError(500, "BUNDLE_DIGEST_DRIFT", `stored bundle for '${slug}' hashes to ${actual} but was published as ${record4.bundleSha256}`);
61431
61774
  }
@@ -61482,7 +61825,7 @@ function buildPublishInput(manifest) {
61482
61825
  displayName: optionalString(manifest.displayName) ?? titleize(slug),
61483
61826
  description,
61484
61827
  category: optionalString(manifest.category) ?? "Development Tools",
61485
- tags: stringArray(manifest.tags),
61828
+ tags: stringArray2(manifest.tags),
61486
61829
  source: publishSource(optionalString(manifest.source)),
61487
61830
  kind: kindValue,
61488
61831
  ...publishVersionOf(manifest) ? { version: publishVersionOf(manifest) } : {},
@@ -61511,7 +61854,7 @@ function optionalString(value) {
61511
61854
  function optionalText(value) {
61512
61855
  return typeof value === "string" && value.trim() ? value : undefined;
61513
61856
  }
61514
- function stringArray(value) {
61857
+ function stringArray2(value) {
61515
61858
  if (!Array.isArray(value))
61516
61859
  return [];
61517
61860
  return value.filter((item) => typeof item === "string" && item.trim().length > 0).map((item) => item.trim());
@@ -61573,7 +61916,7 @@ async function readSkillVersionBundle(store, artifactStorage, principal, slug, v
61573
61916
  const bytes = await artifactStorage.readBundle(bundle2);
61574
61917
  if (!bytes)
61575
61918
  throw new SkillRequestError(503, "BUNDLE_BACKEND_UNAVAILABLE", "bundle storage backend unavailable");
61576
- const actual = createHash31("sha256").update(bytes).digest("hex");
61919
+ const actual = createHash32("sha256").update(bytes).digest("hex");
61577
61920
  if (actual !== found.bundleSha256) {
61578
61921
  throw new SkillRequestError(500, "BUNDLE_DIGEST_DRIFT", `stored bundle for '${slug}@${version2}' hashes to ${actual} but was published as ${found.bundleSha256}`);
61579
61922
  }
@@ -61656,7 +61999,7 @@ async function validatePublishedGrant(store, artifacts, principal, grant) {
61656
61999
  invalid3();
61657
62000
  }
61658
62001
  async function handleExecutionGrantApi(store, principal, request2, parts, config, artifacts) {
61659
- const [resource, id2, child, revision] = parts;
62002
+ const [resource, id2, child2, revision] = parts;
61660
62003
  if (resource !== "execution-grants")
61661
62004
  return null;
61662
62005
  if (!grantIdentifier(id2))
@@ -61664,7 +62007,7 @@ async function handleExecutionGrantApi(store, principal, request2, parts, config
61664
62007
  const { executionGrantStore: policies, selectionStore: profiles } = store;
61665
62008
  if (!policies || !profiles)
61666
62009
  refuse5(503, "EXECUTION_GRANTS_UNAVAILABLE", "This store does not support execution grants.");
61667
- const historical = parts.length === 4 && child === "versions" && grantIdentifier(revision);
62010
+ const historical = parts.length === 4 && child2 === "versions" && grantIdentifier(revision);
61668
62011
  if (request2.method === "GET" && (parts.length === 2 || historical)) {
61669
62012
  const policy = await policies.get(principal, id2, historical ? revision : undefined);
61670
62013
  if (!policy)
@@ -61703,7 +62046,7 @@ async function handleExecutionGrantApi(store, principal, request2, parts, config
61703
62046
  refuse5(409, "EXECUTION_GRANT_REVISION_CONFLICT", "Execution grant policy changed; read it before retrying.");
61704
62047
  return json(saved, create ? 201 : 200, saved.revision);
61705
62048
  }
61706
- if (request2.method === "POST" && parts.length === 3 && child === "resolve") {
62049
+ if (request2.method === "POST" && parts.length === 3 && child2 === "resolve") {
61707
62050
  const input = await body(request2, Math.min(config.requestBodyLimitBytes, 16384));
61708
62051
  let consumer;
61709
62052
  try {
@@ -61868,7 +62211,7 @@ function json2(value, status = 200, revision) {
61868
62211
  });
61869
62212
  }
61870
62213
  async function handleProfileApi(store, principal, request2, parts, config) {
61871
- const [resource, id2, child] = parts;
62214
+ const [resource, id2, child2] = parts;
61872
62215
  if (resource === "capabilities" && request2.method === "GET" && parts.length === 1)
61873
62216
  return json2({
61874
62217
  contractVersion: 1,
@@ -61934,13 +62277,13 @@ async function handleProfileApi(store, principal, request2, parts, config) {
61934
62277
  throw new SkillRequestError(409, "PROFILE_REVISION_CONFLICT", "Profile changed; read it before retrying");
61935
62278
  return json2(saved, create ? 201 : 200, saved.revision);
61936
62279
  }
61937
- 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")) {
61938
62281
  const profile2 = await adapter.getProfile(principal, id2);
61939
62282
  if (!profile2)
61940
62283
  throw new SkillRequestError(404, "PROFILE_NOT_FOUND", "Profile not found");
61941
62284
  if (profile2.selections.length > MAX_PROFILE_SELECTIONS)
61942
62285
  throw new SkillRequestError(413, "PROFILE_TOO_LARGE", "Profile exceeds the advertised selection limit");
61943
- if (!child)
62286
+ if (!child2)
61944
62287
  return json2(profile2, 200, profile2.revision);
61945
62288
  const authority2 = skillsApiRequestUrl(normalizeSkillsApiOrigin(config.publicBaseUrl), "/api/v1/").replace(/\/+$/, "");
61946
62289
  const result = resolvedProfileSnapshot(profile2, authority2);
@@ -61959,7 +62302,7 @@ async function handleProfileApi(store, principal, request2, parts, config) {
61959
62302
  throw new SkillRequestError(413, "PROFILE_TOO_LARGE", "Resolved profile exceeds the advertised profile limits");
61960
62303
  return json2(result, 200, profile2.revision);
61961
62304
  }
61962
- if (resource === "stations" && parts.length === 3 && child === "state") {
62305
+ if (resource === "stations" && parts.length === 3 && child2 === "state") {
61963
62306
  if (request2.method === "GET") {
61964
62307
  const state2 = await adapter.getStationState(principal, id2);
61965
62308
  if (!state2)
@@ -61993,7 +62336,7 @@ async function handleProfileApi(store, principal, request2, parts, config) {
61993
62336
  // src/server/runtime-store.ts
61994
62337
  import { Database as Database3 } from "bun:sqlite";
61995
62338
  import { mkdirSync as mkdirSync14 } from "fs";
61996
- import { dirname as dirname27 } from "path";
62339
+ import { dirname as dirname28 } from "path";
61997
62340
 
61998
62341
  // src/sdk/execution/types.ts
61999
62342
  var EXECUTION_PROTOCOL_VERSION = REMOTE_SKILL_RUN_CONTRACT_VERSION;
@@ -62049,7 +62392,7 @@ class RuntimeExecutionStore {
62049
62392
  }
62050
62393
  const path = target.kind === "sqlite" ? target.path : ":memory:";
62051
62394
  if (path !== ":memory:")
62052
- mkdirSync14(dirname27(path), { recursive: true });
62395
+ mkdirSync14(dirname28(path), { recursive: true });
62053
62396
  const db = new Database3(path);
62054
62397
  db.run("PRAGMA busy_timeout=5000");
62055
62398
  db.run("PRAGMA journal_mode=WAL");
@@ -62289,7 +62632,7 @@ class RuntimeExecutionStore {
62289
62632
  }
62290
62633
 
62291
62634
  // src/sdk/execution/admission.ts
62292
- import { createHash as createHash33 } from "crypto";
62635
+ import { createHash as createHash34 } from "crypto";
62293
62636
 
62294
62637
  // src/sdk/execution/image-profile.ts
62295
62638
  class ImageProfileResolutionError extends Error {
@@ -62901,11 +63244,11 @@ function ownedAdmission(admission) {
62901
63244
  };
62902
63245
  }
62903
63246
  function digestInput(input) {
62904
- return createHash33("sha256").update(canonicalJson2(input)).digest("hex");
63247
+ return createHash34("sha256").update(canonicalJson2(input)).digest("hex");
62905
63248
  }
62906
63249
 
62907
63250
  // src/sdk/execution/dispatchers/ecs.ts
62908
- import { createHash as createHash34 } from "crypto";
63251
+ import { createHash as createHash35 } from "crypto";
62909
63252
 
62910
63253
  // src/sdk/execution/state-machine.ts
62911
63254
  var LEGAL_TRANSITIONS = {
@@ -66305,13 +66648,13 @@ function observedTask(states, taskArn) {
66305
66648
  return state2.lastStatus === "STOPPED" || LIVE_TASK_STATUSES.has(state2.lastStatus) ? state2 : undefined;
66306
66649
  }
66307
66650
  function clientTokenFor(runId3, attemptId) {
66308
- 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);
66309
66652
  }
66310
66653
  function startedByFor(runId3, attemptNumber) {
66311
66654
  return `skills-exec/${runId3}/a${attemptNumber}`;
66312
66655
  }
66313
66656
  function requestDigestFor(admission, attemptId) {
66314
- return createHash34("sha256").update(canonicalJson2({ admission, attemptId })).digest("hex");
66657
+ return createHash35("sha256").update(canonicalJson2({ admission, attemptId })).digest("hex");
66315
66658
  }
66316
66659
 
66317
66660
  class EcsDispatcher {
@@ -66607,10 +66950,10 @@ function validText(value) {
66607
66950
  }
66608
66951
 
66609
66952
  // src/server/runtime-policy.ts
66610
- 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";
66611
66954
 
66612
66955
  // src/server/runtime-pure-contract.ts
66613
- import { createHash as createHash35 } from "crypto";
66956
+ import { createHash as createHash36 } from "crypto";
66614
66957
  var PURE_DESCRIPTOR = Object.freeze({
66615
66958
  id: "regex-test.v1",
66616
66959
  runtime: "bun",
@@ -66634,7 +66977,7 @@ var PURE_LIMITS = Object.freeze({
66634
66977
  maxArtifactsBytes: 0,
66635
66978
  maxConcurrency: 1
66636
66979
  });
66637
- var hash2 = (bytes) => createHash35("sha256").update(bytes).digest("hex");
66980
+ var hash2 = (bytes) => createHash36("sha256").update(bytes).digest("hex");
66638
66981
  var object7 = (v2) => {
66639
66982
  if (!v2 || typeof v2 !== "object" || Array.isArray(v2))
66640
66983
  throw Error("Pure contract requires an object");
@@ -66863,7 +67206,7 @@ function verifyRuntimeToken(token, key, admission, attempt, now = Date.now()) {
66863
67206
  const actual = Buffer.from(token);
66864
67207
  return actual.length === expected.length && timingSafeEqual2(actual, expected);
66865
67208
  }
66866
- var hashBytes = (bytes) => createHash36("sha256").update(bytes).digest("hex");
67209
+ var hashBytes = (bytes) => createHash37("sha256").update(bytes).digest("hex");
66867
67210
 
66868
67211
  // src/server/runtime-api.ts
66869
67212
  async function createRuntimeService(options) {
@@ -73239,7 +73582,7 @@ var localRunExecutor = {
73239
73582
  // src/sdk/storage.ts
73240
73583
  var artifactStorageSeam = ArtifactStorage;
73241
73584
  // src/sdk/outputs.ts
73242
- import { createHash as createHash37 } from "crypto";
73585
+ import { createHash as createHash38 } from "crypto";
73243
73586
  class DatabaseOnlyObjectStore {
73244
73587
  usesS3 = false;
73245
73588
  async materialize(run, artifact, body4) {
@@ -73286,7 +73629,7 @@ function createGovernedArtifactWriter(options) {
73286
73629
  const stamped = {
73287
73630
  ...meta,
73288
73631
  byteSize: outputBytes,
73289
- sha256: createHash37("sha256").update(persistedBytes).digest("hex"),
73632
+ sha256: createHash38("sha256").update(persistedBytes).digest("hex"),
73290
73633
  visibility: options.visibility ?? config.defaultVisibility,
73291
73634
  ...config.artifactTtlSeconds !== undefined ? { expiresAt: expiresAtFor(createdAt, config.artifactTtlSeconds) } : {}
73292
73635
  };
@@ -76928,14 +77271,14 @@ var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
76928
77271
  const shape = zod.def.shape;
76929
77272
  const propValues = {};
76930
77273
  for (const key in shape) {
76931
- const field2 = shape[key]._zod;
76932
- if (field2.values) {
77274
+ const field3 = shape[key]._zod;
77275
+ if (field3.values) {
76933
77276
  if (!Object.prototype.hasOwnProperty.call(propValues, key)) {
76934
77277
  assignProp(propValues, key, new Set);
76935
77278
  }
76936
- for (const v2 of field2.values)
77279
+ for (const v2 of field3.values)
76937
77280
  propValues[key].add(v2);
76938
- if (field2.optin !== undefined)
77281
+ if (field3.optin !== undefined)
76939
77282
  propValues[key].add(undefined);
76940
77283
  }
76941
77284
  }
@@ -78348,8 +78691,8 @@ function isRecursive(inst, stack) {
78348
78691
  return true;
78349
78692
  stack.add(inst);
78350
78693
  let result = false;
78351
- const check = (child) => {
78352
- if (!result && child?._zod && isRecursive(child, stack))
78694
+ const check = (child2) => {
78695
+ if (!result && child2?._zod && isRecursive(child2, stack))
78353
78696
  result = true;
78354
78697
  };
78355
78698
  const def = inst._zod.def;
@@ -89128,11 +89471,11 @@ var objectProcessor = (schema, ctx, _json, params) => {
89128
89471
  }
89129
89472
  const allKeys = new Set(Object.keys(shape));
89130
89473
  const requiredKeys = new Set([...allKeys].filter((key) => {
89131
- const field2 = def.shape[key];
89474
+ const field3 = def.shape[key];
89132
89475
  if (ctx.io === "input") {
89133
- return inputOptin(field2) === undefined;
89476
+ return inputOptin(field3) === undefined;
89134
89477
  } else {
89135
- return field2._zod.optout === undefined;
89478
+ return field3._zod.optout === undefined;
89136
89479
  }
89137
89480
  }));
89138
89481
  if (requiredKeys.size > 0) {
@@ -92053,7 +92396,7 @@ function date4(params) {
92053
92396
  return _coercedDate(ZodDate2, params);
92054
92397
  }
92055
92398
  // src/lib/canonical-json.ts
92056
- import { createHash as createHash38 } from "crypto";
92399
+ import { createHash as createHash39 } from "crypto";
92057
92400
  function canonicalJson3(value, maximumBytes = 2 * 1024 * 1024) {
92058
92401
  return canonicalJsonAtDepth(value, maximumBytes, 64);
92059
92402
  }
@@ -92097,7 +92440,7 @@ function canonicalJsonAtDepth(value, maximumBytes, maximumDepth) {
92097
92440
  return visit3(value, 0);
92098
92441
  }
92099
92442
  function canonicalJsonSha256(value, maximumBytes) {
92100
- return createHash38("sha256").update(canonicalJson3(value, maximumBytes)).digest("hex");
92443
+ return createHash39("sha256").update(canonicalJson3(value, maximumBytes)).digest("hex");
92101
92444
  }
92102
92445
 
92103
92446
  // src/lib/remote-recurring-contract.ts
@@ -92877,17 +93220,17 @@ function runQuoteReceipt(value) {
92877
93220
  return value;
92878
93221
  }
92879
93222
  function parseRemoteRunQuote(value) {
92880
- const quote2 = object9(value);
92881
- runQuoteReceipt(quote2.quoteReceipt);
92882
- const pricing = object9(quote2.pricing);
92883
- 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))
92884
93227
  throw new Error("Invalid quoted skill");
92885
93228
  const costCents = creditCount(pricing.costCredits ?? pricing.costCents);
92886
93229
  if (pricing.costCredits !== undefined && pricing.costCents !== undefined && pricing.costCents !== costCents)
92887
93230
  throw new Error("Inconsistent quoted credit count");
92888
- if (quote2.availability && object9(quote2.availability).status !== "available")
93231
+ if (quote3.availability && object9(quote3.availability).status !== "available")
92889
93232
  throw new Error("This skill is unavailable for remote execution");
92890
- 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` } };
92891
93234
  }
92892
93235
  function parseRemoteCreditPacks(value) {
92893
93236
  if (!Array.isArray(value))
@@ -92962,14 +93305,14 @@ function creditCheckoutFailure(value, status, key) {
92962
93305
  }
92963
93306
 
92964
93307
  // src/lib/remote-profile.ts
92965
- function customerNamePatch(input2, field2) {
92966
- 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))
92967
93310
  throw new Error("Provide only the requested name field.");
92968
- const value = input2[field2];
93311
+ const value = input2[field3];
92969
93312
  if (typeof value !== "string" || /[\p{Cc}\p{Cs}\u2028\u2029]/u.test(value) || !value.trim() || [...value.trim()].length > 100) {
92970
93313
  throw new Error("Use a name of 1\u2013100 characters without control characters or newlines.");
92971
93314
  }
92972
- return { [field2]: value.trim() };
93315
+ return { [field3]: value.trim() };
92973
93316
  }
92974
93317
  function isRecord6(value) {
92975
93318
  return !!value && typeof value === "object" && !Array.isArray(value);
@@ -93014,10 +93357,10 @@ async function readQuoteUnavailableCode(response) {
93014
93357
  let timer;
93015
93358
  let deadlineExceeded = false;
93016
93359
  const expired = Symbol("quote body deadline");
93017
- const deadline = new Promise((resolve23) => {
93360
+ const deadline = new Promise((resolve25) => {
93018
93361
  timer = setTimeout(() => {
93019
93362
  deadlineExceeded = true;
93020
- resolve23(expired);
93363
+ resolve25(expired);
93021
93364
  reader.cancel().catch(() => {});
93022
93365
  }, 1500);
93023
93366
  });
@@ -93364,18 +93707,18 @@ class RemoteSkillsClient {
93364
93707
  const maximum = creditCount(approval.maxCredits ?? approval.maxCostCents ?? 0);
93365
93708
  if (approval.maxCostCents !== undefined && approval.maxCostCents !== maximum)
93366
93709
  throw new Error("Credit approval fields disagree");
93367
- const quote2 = approval.quoteReceipt === undefined ? await this.quoteRun(slug2, input2, args, approval.inputFiles?.length ? approval.inputFiles : undefined) : undefined;
93368
- if (quote2 && quote2.pricing.costCents > maximum)
93369
- 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);
93370
93713
  const capabilities = await this.getCapabilities();
93371
93714
  if (!capabilities.capabilities.includes("runs.submit") || capabilities.billing?.boundedRunApproval !== true || capabilities.billing.unit !== "credits") {
93372
93715
  throw new Error("The configured server does not support bounded credit approval; refusing remote submission");
93373
93716
  }
93374
- return this.submitRun(quote2?.skill ?? slug2, input2, args, {
93717
+ return this.submitRun(quote3?.skill ?? slug2, input2, args, {
93375
93718
  ...approval,
93376
93719
  maxCredits: maximum,
93377
93720
  maxCostCents: maximum,
93378
- ...(quote2?.quoteReceipt ?? approval.quoteReceipt) === undefined ? {} : { quoteReceipt: quote2?.quoteReceipt ?? approval.quoteReceipt }
93721
+ ...(quote3?.quoteReceipt ?? approval.quoteReceipt) === undefined ? {} : { quoteReceipt: quote3?.quoteReceipt ?? approval.quoteReceipt }
93379
93722
  });
93380
93723
  }
93381
93724
  async getIdentity() {
@@ -93976,13 +94319,13 @@ class RemoteSkillsClient {
93976
94319
  return normalizeUpdatedSincePage(await response.json());
93977
94320
  }
93978
94321
  }
93979
- function requireOptionalString(record9, field2) {
93980
- if (record9[field2] === undefined)
94322
+ function requireOptionalString(record9, field3) {
94323
+ if (record9[field3] === undefined)
93981
94324
  return;
93982
- if (typeof record9[field2] !== "string") {
93983
- 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)`);
93984
94327
  }
93985
- return record9[field2];
94328
+ return record9[field3];
93986
94329
  }
93987
94330
  var INVALID_SKILL_VERSION_RESPONSE = "Remote skill version payload did not match the expected contract.";
93988
94331
  function isVersionRecord(value) {
@@ -94211,7 +94554,7 @@ async function requestInvitationEmail(origin, action, input2) {
94211
94554
  }
94212
94555
 
94213
94556
  // src/lib/remote-private-publications.ts
94214
- import { createHash as createHash39 } from "crypto";
94557
+ import { createHash as createHash40 } from "crypto";
94215
94558
  var PRIVATE_PUBLICATION_MAX_BYTES = 16 * 1024 * 1024;
94216
94559
  var failures2 = {
94217
94560
  INVALID_REQUEST: [400, "The publication request is invalid."],
@@ -94258,7 +94601,7 @@ var hash4 = (v2) => typeof v2 === "string" && /^[a-f0-9]{64}$/.test(v2);
94258
94601
  var record10 = (v2) => !!v2 && typeof v2 === "object" && !Array.isArray(v2);
94259
94602
  var exact = (v2, keys3) => record10(v2) && Object.keys(v2).sort().join(",") === keys3.sort().join(",");
94260
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));
94261
- var publicationSha256 = (bytes) => createHash39("sha256").update(bytes).digest("hex");
94604
+ var publicationSha256 = (bytes) => createHash40("sha256").update(bytes).digest("hex");
94262
94605
  function checkedPublicationDeclaration(value) {
94263
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)
94264
94607
  return bad();
@@ -94503,12 +94846,12 @@ class RemotePrivatePublicationsClient {
94503
94846
  previous = view;
94504
94847
  if (!["queued", "verifying"].includes(view.state) || Date.now() >= until)
94505
94848
  return view;
94506
- await new Promise((resolve23) => {
94849
+ await new Promise((resolve25) => {
94507
94850
  const timer = setTimeout(done, Math.min(1000, until - Date.now()));
94508
94851
  function done() {
94509
94852
  clearTimeout(timer);
94510
94853
  options.signal?.removeEventListener("abort", done);
94511
- resolve23();
94854
+ resolve25();
94512
94855
  }
94513
94856
  options.signal?.addEventListener("abort", done, { once: true });
94514
94857
  });
@@ -94741,19 +95084,19 @@ class RemoteSkillsAuthClient {
94741
95084
  }
94742
95085
  // src/lib/private-publication-recovery.ts
94743
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";
94744
- 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";
94745
95088
  import { randomUUID as randomUUID12 } from "crypto";
94746
95089
  var fail2 = () => {
94747
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.");
94748
95091
  };
94749
95092
  function safeDirectory(directory) {
94750
- if (!isAbsolute23(directory) || directory !== resolve23(directory) || realpathSync16(directory) !== directory)
95093
+ if (!isAbsolute25(directory) || directory !== resolve25(directory) || realpathSync16(directory) !== directory)
94751
95094
  return fail2();
94752
- for (let path2 = directory;; path2 = dirname28(path2)) {
95095
+ for (let path2 = directory;; path2 = dirname29(path2)) {
94753
95096
  const stat2 = lstatSync27(path2);
94754
95097
  if (!stat2.isDirectory() || stat2.isSymbolicLink())
94755
95098
  return fail2();
94756
- if (path2 === dirname28(path2))
95099
+ if (path2 === dirname29(path2))
94757
95100
  break;
94758
95101
  }
94759
95102
  const own2 = lstatSync27(directory);
@@ -94885,11 +95228,11 @@ async function preparePrivatePublication(client2, sourceDirectory, recoveryDirec
94885
95228
  phase: "prepared",
94886
95229
  intent: null
94887
95230
  };
94888
- if (!isAbsolute23(recoveryDirectory) || resolve23(recoveryDirectory) !== recoveryDirectory || realpathSync16(dirname28(recoveryDirectory)) !== dirname28(recoveryDirectory))
95231
+ if (!isAbsolute25(recoveryDirectory) || resolve25(recoveryDirectory) !== recoveryDirectory || realpathSync16(dirname29(recoveryDirectory)) !== dirname29(recoveryDirectory))
94889
95232
  return fail2();
94890
95233
  mkdirSync15(recoveryDirectory, { mode: 448 });
94891
95234
  safeDirectory(recoveryDirectory);
94892
- const parent = openSync19(dirname28(recoveryDirectory), constants16.O_RDONLY | constants16.O_NOFOLLOW);
95235
+ const parent = openSync19(dirname29(recoveryDirectory), constants16.O_RDONLY | constants16.O_NOFOLLOW);
94893
95236
  try {
94894
95237
  fsyncSync7(parent);
94895
95238
  } finally {