@hasna/skills 0.10.46 → 0.10.48

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
@@ -3724,10 +3724,10 @@ var require_resolve_block_map = __commonJS((exports) => {
3724
3724
  let offset = bm.offset;
3725
3725
  let commentEnd = null;
3726
3726
  for (const collItem of bm.items) {
3727
- const { start, key, sep: sep4, value } = collItem;
3727
+ const { start, key, sep: sep5, value } = collItem;
3728
3728
  const keyProps = resolveProps.resolveProps(start, {
3729
3729
  indicator: "explicit-key-ind",
3730
- next: key ?? sep4?.[0],
3730
+ next: key ?? sep5?.[0],
3731
3731
  offset,
3732
3732
  onError,
3733
3733
  parentIndent: bm.indent,
@@ -3741,7 +3741,7 @@ var require_resolve_block_map = __commonJS((exports) => {
3741
3741
  else if ("indent" in key && key.indent !== bm.indent)
3742
3742
  onError(offset, "BAD_INDENT", startColMsg);
3743
3743
  }
3744
- if (!keyProps.anchor && !keyProps.tag && !sep4) {
3744
+ if (!keyProps.anchor && !keyProps.tag && !sep5) {
3745
3745
  commentEnd = keyProps.end;
3746
3746
  if (keyProps.comment) {
3747
3747
  if (map.comment)
@@ -3766,7 +3766,7 @@ var require_resolve_block_map = __commonJS((exports) => {
3766
3766
  ctx.atKey = false;
3767
3767
  if (utilMapIncludes.mapIncludes(ctx, map.items, keyNode))
3768
3768
  onError(keyStart, "DUPLICATE_KEY", "Map keys must be unique");
3769
- const valueProps = resolveProps.resolveProps(sep4 ?? [], {
3769
+ const valueProps = resolveProps.resolveProps(sep5 ?? [], {
3770
3770
  indicator: "map-value-ind",
3771
3771
  next: value,
3772
3772
  offset: keyNode.range[2],
@@ -3782,7 +3782,7 @@ var require_resolve_block_map = __commonJS((exports) => {
3782
3782
  if (ctx.options.strict && keyProps.start < valueProps.found.offset - 1024)
3783
3783
  onError(keyNode.range, "KEY_OVER_1024_CHARS", "The : indicator must be at most 1024 chars after the start of an implicit block mapping key");
3784
3784
  }
3785
- const valueNode = value ? composeNode(ctx, value, valueProps, onError) : composeEmptyNode(ctx, offset, sep4, null, valueProps, onError);
3785
+ const valueNode = value ? composeNode(ctx, value, valueProps, onError) : composeEmptyNode(ctx, offset, sep5, null, valueProps, onError);
3786
3786
  if (ctx.schema.compat)
3787
3787
  utilFlowIndentCheck.flowIndentCheck(bm.indent, value, onError);
3788
3788
  offset = valueNode.range[2];
@@ -3868,7 +3868,7 @@ var require_resolve_end = __commonJS((exports) => {
3868
3868
  let comment = "";
3869
3869
  if (end) {
3870
3870
  let hasSpace = false;
3871
- let sep4 = "";
3871
+ let sep5 = "";
3872
3872
  for (const token of end) {
3873
3873
  const { source, type } = token;
3874
3874
  switch (type) {
@@ -3882,13 +3882,13 @@ var require_resolve_end = __commonJS((exports) => {
3882
3882
  if (!comment)
3883
3883
  comment = cb;
3884
3884
  else
3885
- comment += sep4 + cb;
3886
- sep4 = "";
3885
+ comment += sep5 + cb;
3886
+ sep5 = "";
3887
3887
  break;
3888
3888
  }
3889
3889
  case "newline":
3890
3890
  if (comment)
3891
- sep4 += source;
3891
+ sep5 += source;
3892
3892
  hasSpace = true;
3893
3893
  break;
3894
3894
  default:
@@ -3928,18 +3928,18 @@ var require_resolve_flow_collection = __commonJS((exports) => {
3928
3928
  let offset = fc.offset + fc.start.source.length;
3929
3929
  for (let i = 0;i < fc.items.length; ++i) {
3930
3930
  const collItem = fc.items[i];
3931
- const { start, key, sep: sep4, value } = collItem;
3931
+ const { start, key, sep: sep5, value } = collItem;
3932
3932
  const props = resolveProps.resolveProps(start, {
3933
3933
  flow: fcName,
3934
3934
  indicator: "explicit-key-ind",
3935
- next: key ?? sep4?.[0],
3935
+ next: key ?? sep5?.[0],
3936
3936
  offset,
3937
3937
  onError,
3938
3938
  parentIndent: fc.indent,
3939
3939
  startOnNewline: false
3940
3940
  });
3941
3941
  if (!props.found) {
3942
- if (!props.anchor && !props.tag && !sep4 && !value) {
3942
+ if (!props.anchor && !props.tag && !sep5 && !value) {
3943
3943
  if (i === 0 && props.comma)
3944
3944
  onError(props.comma, "UNEXPECTED_TOKEN", `Unexpected , in ${fcName}`);
3945
3945
  else if (i < fc.items.length - 1)
@@ -3991,8 +3991,8 @@ var require_resolve_flow_collection = __commonJS((exports) => {
3991
3991
  }
3992
3992
  }
3993
3993
  }
3994
- if (!isMap && !sep4 && !props.found) {
3995
- const valueNode = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end, sep4, null, props, onError);
3994
+ if (!isMap && !sep5 && !props.found) {
3995
+ const valueNode = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end, sep5, null, props, onError);
3996
3996
  coll.items.push(valueNode);
3997
3997
  offset = valueNode.range[2];
3998
3998
  if (isBlock(value))
@@ -4004,7 +4004,7 @@ var require_resolve_flow_collection = __commonJS((exports) => {
4004
4004
  if (isBlock(key))
4005
4005
  onError(keyNode.range, "BLOCK_IN_FLOW", blockMsg);
4006
4006
  ctx.atKey = false;
4007
- const valueProps = resolveProps.resolveProps(sep4 ?? [], {
4007
+ const valueProps = resolveProps.resolveProps(sep5 ?? [], {
4008
4008
  flow: fcName,
4009
4009
  indicator: "map-value-ind",
4010
4010
  next: value,
@@ -4015,8 +4015,8 @@ var require_resolve_flow_collection = __commonJS((exports) => {
4015
4015
  });
4016
4016
  if (valueProps.found) {
4017
4017
  if (!isMap && !props.found && ctx.options.strict) {
4018
- if (sep4)
4019
- for (const st of sep4) {
4018
+ if (sep5)
4019
+ for (const st of sep5) {
4020
4020
  if (st === valueProps.found)
4021
4021
  break;
4022
4022
  if (st.type === "newline") {
@@ -4033,7 +4033,7 @@ var require_resolve_flow_collection = __commonJS((exports) => {
4033
4033
  else
4034
4034
  onError(valueProps.start, "MISSING_CHAR", `Missing , or : between ${fcName} items`);
4035
4035
  }
4036
- const valueNode = value ? composeNode(ctx, value, valueProps, onError) : valueProps.found ? composeEmptyNode(ctx, valueProps.end, sep4, null, valueProps, onError) : null;
4036
+ const valueNode = value ? composeNode(ctx, value, valueProps, onError) : valueProps.found ? composeEmptyNode(ctx, valueProps.end, sep5, null, valueProps, onError) : null;
4037
4037
  if (valueNode) {
4038
4038
  if (isBlock(value))
4039
4039
  onError(valueNode.range, "BLOCK_IN_FLOW", blockMsg);
@@ -4210,7 +4210,7 @@ var require_resolve_block_scalar = __commonJS((exports) => {
4210
4210
  chompStart = i + 1;
4211
4211
  }
4212
4212
  let value = "";
4213
- let sep4 = "";
4213
+ let sep5 = "";
4214
4214
  let prevMoreIndented = false;
4215
4215
  for (let i = 0;i < contentStart; ++i)
4216
4216
  value += lines[i][0].slice(trimIndent) + `
@@ -4228,33 +4228,33 @@ var require_resolve_block_scalar = __commonJS((exports) => {
4228
4228
  indent = "";
4229
4229
  }
4230
4230
  if (type === Scalar.Scalar.BLOCK_LITERAL) {
4231
- value += sep4 + indent.slice(trimIndent) + content;
4232
- sep4 = `
4231
+ value += sep5 + indent.slice(trimIndent) + content;
4232
+ sep5 = `
4233
4233
  `;
4234
4234
  } else if (indent.length > trimIndent || content[0] === "\t") {
4235
- if (sep4 === " ")
4236
- sep4 = `
4235
+ if (sep5 === " ")
4236
+ sep5 = `
4237
4237
  `;
4238
- else if (!prevMoreIndented && sep4 === `
4238
+ else if (!prevMoreIndented && sep5 === `
4239
4239
  `)
4240
- sep4 = `
4240
+ sep5 = `
4241
4241
 
4242
4242
  `;
4243
- value += sep4 + indent.slice(trimIndent) + content;
4244
- sep4 = `
4243
+ value += sep5 + indent.slice(trimIndent) + content;
4244
+ sep5 = `
4245
4245
  `;
4246
4246
  prevMoreIndented = true;
4247
4247
  } else if (content === "") {
4248
- if (sep4 === `
4248
+ if (sep5 === `
4249
4249
  `)
4250
4250
  value += `
4251
4251
  `;
4252
4252
  else
4253
- sep4 = `
4253
+ sep5 = `
4254
4254
  `;
4255
4255
  } else {
4256
- value += sep4 + content;
4257
- sep4 = " ";
4256
+ value += sep5 + content;
4257
+ sep5 = " ";
4258
4258
  prevMoreIndented = false;
4259
4259
  }
4260
4260
  }
@@ -4435,27 +4435,27 @@ var require_resolve_flow_scalar = __commonJS((exports) => {
4435
4435
  if (!match)
4436
4436
  return source;
4437
4437
  let res = match[1];
4438
- let sep4 = " ";
4438
+ let sep5 = " ";
4439
4439
  let pos = first.lastIndex;
4440
4440
  line.lastIndex = pos;
4441
4441
  while (match = line.exec(source)) {
4442
4442
  if (match[1] === "") {
4443
- if (sep4 === `
4443
+ if (sep5 === `
4444
4444
  `)
4445
- res += sep4;
4445
+ res += sep5;
4446
4446
  else
4447
- sep4 = `
4447
+ sep5 = `
4448
4448
  `;
4449
4449
  } else {
4450
- res += sep4 + match[1];
4451
- sep4 = " ";
4450
+ res += sep5 + match[1];
4451
+ sep5 = " ";
4452
4452
  }
4453
4453
  pos = line.lastIndex;
4454
4454
  }
4455
4455
  const last = /[ \t]*(.*)/sy;
4456
4456
  last.lastIndex = pos;
4457
4457
  match = last.exec(source);
4458
- return res + sep4 + (match?.[1] ?? "");
4458
+ return res + sep5 + (match?.[1] ?? "");
4459
4459
  }
4460
4460
  function doubleQuotedValue(source, onError) {
4461
4461
  let res = "";
@@ -5236,14 +5236,14 @@ var require_cst_stringify = __commonJS((exports) => {
5236
5236
  }
5237
5237
  }
5238
5238
  }
5239
- function stringifyItem({ start, key, sep: sep4, value }) {
5239
+ function stringifyItem({ start, key, sep: sep5, value }) {
5240
5240
  let res = "";
5241
5241
  for (const st of start)
5242
5242
  res += st.source;
5243
5243
  if (key)
5244
5244
  res += stringifyToken(key);
5245
- if (sep4)
5246
- for (const st of sep4)
5245
+ if (sep5)
5246
+ for (const st of sep5)
5247
5247
  res += st.source;
5248
5248
  if (value)
5249
5249
  res += stringifyToken(value);
@@ -6391,18 +6391,18 @@ var require_parser = __commonJS((exports) => {
6391
6391
  if (this.type === "map-value-ind") {
6392
6392
  const prev = getPrevProps(this.peek(2));
6393
6393
  const start = getFirstKeyStartProps(prev);
6394
- let sep4;
6394
+ let sep5;
6395
6395
  if (scalar2.end) {
6396
- sep4 = scalar2.end;
6397
- sep4.push(this.sourceToken);
6396
+ sep5 = scalar2.end;
6397
+ sep5.push(this.sourceToken);
6398
6398
  delete scalar2.end;
6399
6399
  } else
6400
- sep4 = [this.sourceToken];
6400
+ sep5 = [this.sourceToken];
6401
6401
  const map = {
6402
6402
  type: "block-map",
6403
6403
  offset: scalar2.offset,
6404
6404
  indent: scalar2.indent,
6405
- items: [{ start, key: scalar2, sep: sep4 }]
6405
+ items: [{ start, key: scalar2, sep: sep5 }]
6406
6406
  };
6407
6407
  this.onKeyLine = true;
6408
6408
  this.stack[this.stack.length - 1] = map;
@@ -6556,15 +6556,15 @@ var require_parser = __commonJS((exports) => {
6556
6556
  } else if (isFlowToken(it.key) && !includesToken(it.sep, "newline")) {
6557
6557
  const start2 = getFirstKeyStartProps(it.start);
6558
6558
  const key = it.key;
6559
- const sep4 = it.sep;
6560
- sep4.push(this.sourceToken);
6559
+ const sep5 = it.sep;
6560
+ sep5.push(this.sourceToken);
6561
6561
  delete it.key;
6562
6562
  delete it.sep;
6563
6563
  this.stack.push({
6564
6564
  type: "block-map",
6565
6565
  offset: this.offset,
6566
6566
  indent: this.indent,
6567
- items: [{ start: start2, key, sep: sep4 }]
6567
+ items: [{ start: start2, key, sep: sep5 }]
6568
6568
  });
6569
6569
  } else if (start.length > 0) {
6570
6570
  it.sep = it.sep.concat(start, this.sourceToken);
@@ -6758,13 +6758,13 @@ var require_parser = __commonJS((exports) => {
6758
6758
  const prev = getPrevProps(parent);
6759
6759
  const start = getFirstKeyStartProps(prev);
6760
6760
  fixFlowSeqItems(fc);
6761
- const sep4 = fc.end.splice(1, fc.end.length);
6762
- sep4.push(this.sourceToken);
6761
+ const sep5 = fc.end.splice(1, fc.end.length);
6762
+ sep5.push(this.sourceToken);
6763
6763
  const map = {
6764
6764
  type: "block-map",
6765
6765
  offset: fc.offset,
6766
6766
  indent: fc.indent,
6767
- items: [{ start, key: fc, sep: sep4 }]
6767
+ items: [{ start, key: fc, sep: sep5 }]
6768
6768
  };
6769
6769
  this.onKeyLine = true;
6770
6770
  this.stack[this.stack.length - 1] = map;
@@ -9003,8 +9003,8 @@ var require_client = __commonJS((exports) => {
9003
9003
  // node_modules/@smithy/core/dist-cjs/submodules/config/index.js
9004
9004
  var require_config = __commonJS((exports) => {
9005
9005
  var { homedir: homedir7 } = __require("os");
9006
- var { sep: sep10, join: join4 } = __require("path");
9007
- var { createHash: createHash25 } = __require("crypto");
9006
+ var { sep: sep11, join: join4 } = __require("path");
9007
+ var { createHash: createHash26 } = __require("crypto");
9008
9008
  var { readFile: readFile$1 } = __require("fs/promises");
9009
9009
  var { IniSectionType } = require_dist_cjs();
9010
9010
  var { normalizeProvider } = require_client();
@@ -9143,7 +9143,7 @@ var require_config = __commonJS((exports) => {
9143
9143
  return "DEFAULT";
9144
9144
  };
9145
9145
  var getHomeDir = () => {
9146
- const { HOME, USERPROFILE, HOMEPATH, HOMEDRIVE = `C:${sep10}` } = process.env;
9146
+ const { HOME, USERPROFILE, HOMEPATH, HOMEDRIVE = `C:${sep11}` } = process.env;
9147
9147
  if (HOME)
9148
9148
  return HOME;
9149
9149
  if (USERPROFILE)
@@ -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 = createHash25("sha1");
9162
+ const hasher = createHash26("sha1");
9163
9163
  const cacheName = hasher.update(id2).digest("hex");
9164
9164
  return join4(getHomeDir(), ".aws", "sso", "cache", `${cacheName}.json`);
9165
9165
  };
@@ -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: createHash25, getRandomValues } = __require("crypto");
10514
+ var { createHmac: createHmac2, createHash: createHash26, getRandomValues } = __require("crypto");
10515
10515
  var { hasOwn: hasOwn2, HttpResponse } = require_transport();
10516
10516
  exports.hasOwn = hasOwn2;
10517
10517
  var { ReadStream, lstatSync: lstatSync26, 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)) : createHash25(this.algorithmIdentifier);
11419
+ this.hash = this.secret ? createHmac2(this.algorithmIdentifier, castSourceData(this.secret)) : createHash26(this.algorithmIdentifier);
11420
11420
  }
11421
11421
  }
11422
11422
  function castSourceData(toCast, encoding) {
@@ -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: createHash25, createHmac: createHmac2 } = __require("crypto");
12158
+ var { createHash: createHash26, 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;
@@ -12320,7 +12320,7 @@ var require_checksum = __commonJS((exports) => {
12320
12320
  }
12321
12321
  var hasNativeCrypto$1 = (() => {
12322
12322
  try {
12323
- createHash25("md5");
12323
+ createHash26("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 = createHash25("md5");
12333
+ hash = createHash26("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 = createHash25("md5");
12342
+ this.hash = createHash26("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
- createHash25("sha256");
12632
+ createHash26("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)) : createHash25("sha256");
12672
+ return this.secret ? createHmac2("sha256", toBuffer(this.secret)) : createHash26("sha256");
12673
12673
  }
12674
12674
  };
12675
12675
  }
@@ -17515,8 +17515,8 @@ More information can be found at: https://a.co/c895JFp`);
17515
17515
  };
17516
17516
  var createUserAgentStringParsingProvider = ({ serviceId, clientVersion }) => async (config) => {
17517
17517
  const module2 = require_es5();
17518
- const parse7 = module2.parse ?? module2.default.parse ?? (() => "");
17519
- const parsedUA = typeof window !== "undefined" && window?.navigator?.userAgent ? parse7(window.navigator.userAgent) : undefined;
17518
+ const parse8 = module2.parse ?? module2.default.parse ?? (() => "");
17519
+ const parsedUA = typeof window !== "undefined" && window?.navigator?.userAgent ? parse8(window.navigator.userAgent) : undefined;
17520
17520
  const sections = [
17521
17521
  ["aws-sdk-js", clientVersion],
17522
17522
  ["ua", "2.1"],
@@ -18166,7 +18166,7 @@ ${toHex(hashedRequest)}`;
18166
18166
  return hash2.digest();
18167
18167
  };
18168
18168
  var getCanonicalHeaders = ({ headers }, unsignableHeaders, signableHeaders) => {
18169
- const canonical6 = {};
18169
+ const canonical7 = {};
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
- canonical6[canonicalHeaderName] = headers[headerName].trim().replace(/\s+/g, " ");
18180
+ canonical7[canonicalHeaderName] = headers[headerName].trim().replace(/\s+/g, " ");
18181
18181
  }
18182
- return canonical6;
18182
+ return canonical7;
18183
18183
  };
18184
18184
  var getPayloadHash = async ({ headers, body }, hashConstructor) => {
18185
18185
  for (const headerName in headers) {
@@ -18542,7 +18542,7 @@ var require_dist_cjs4 = __commonJS((exports) => {
18542
18542
  var require_util = __commonJS((exports) => {
18543
18543
  var { buildQueryString } = require_protocols();
18544
18544
  var validate = (str) => typeof str === "string" && str.indexOf("arn:") === 0 && str.split(":").length >= 6;
18545
- var parse7 = (arn) => {
18545
+ var parse8 = (arn) => {
18546
18546
  const segments = arn.split(":");
18547
18547
  if (segments.length < 6 || segments[0] !== "arn")
18548
18548
  throw new Error("Malformed ARN");
@@ -18592,7 +18592,7 @@ var require_util = __commonJS((exports) => {
18592
18592
  }
18593
18593
  exports.build = build;
18594
18594
  exports.formatUrl = formatUrl;
18595
- exports.parse = parse7;
18595
+ exports.parse = parse8;
18596
18596
  exports.validate = validate;
18597
18597
  });
18598
18598
 
@@ -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 canonical6 = String(value);
21704
- if (normalized === canonical6) {
21703
+ const canonical7 = String(value);
21704
+ if (normalized === canonical7) {
21705
21705
  return true;
21706
21706
  }
21707
- if (/[eE]/.test(canonical6)) {
21708
- return normalized === expandToDecimal(canonical6);
21707
+ if (/[eE]/.test(canonical7)) {
21708
+ return normalized === expandToDecimal(canonical7);
21709
21709
  }
21710
21710
  return false;
21711
21711
  }
@@ -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 createHash25, createPrivateKey, createPublicKey, sign } from "crypto";
29446
+ import { createHash as createHash26, 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 join37 } from "path";
29449
+ import { dirname as dirname23, 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);
@@ -29613,10 +29613,10 @@ var init_LoginCredentialsFetcher = __esm(() => {
29613
29613
  await fs2.writeFile(tokenFilePath, JSON.stringify(token, null, 2), "utf8");
29614
29614
  }
29615
29615
  getTokenFilePath() {
29616
- const directory = process.env.AWS_LOGIN_CACHE_DIRECTORY ?? join37(homedir7(), ".aws", "login", "cache");
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 = createHash25("sha256").update(loginSessionBytes).digest("hex");
29619
- return join37(directory, `${loginSessionSha256}.json`);
29618
+ const loginSessionSha256 = createHash26("sha256").update(loginSessionBytes).digest("hex");
29619
+ return join38(directory, `${loginSessionSha256}.json`);
29620
29620
  }
29621
29621
  derToRawSignature(derSignature) {
29622
29622
  let offset = 2;
@@ -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 join41, resolve as resolve22 } from "path";
31070
+ import { join as join42, resolve as resolve22 } 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";
@@ -31228,7 +31228,7 @@ function effectiveHome2() {
31228
31228
  return process.env["HOME"] || process.env["USERPROFILE"] || homedir8();
31229
31229
  }
31230
31230
  function legacyHomeDir() {
31231
- return join41(effectiveHome2(), ".hasna", "events");
31231
+ return join42(effectiveHome2(), ".hasna", "events");
31232
31232
  }
31233
31233
  function resolverHome() {
31234
31234
  return dataDir2({ app: "events", home: effectiveHome2() || undefined });
@@ -31237,7 +31237,7 @@ function adoptResolverHome(resolved, env = process.env) {
31237
31237
  const dataOverride = env.HASNA_DATA_HOME;
31238
31238
  if (typeof dataOverride === "string" && dataOverride.trim().length > 0)
31239
31239
  return true;
31240
- return existsSync17(join41(resolved, EVENTS_STORE_SENTINEL_FILE));
31240
+ return existsSync17(join42(resolved, EVENTS_STORE_SENTINEL_FILE));
31241
31241
  }
31242
31242
  function exactEventsHome() {
31243
31243
  const dir = process.env[HASNA_EVENTS_DIR_ENV];
@@ -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.46",
32376
+ version: "0.10.48",
32377
32377
  description: "Skills library for AI coding agents",
32378
32378
  type: "module",
32379
32379
  bin: {
@@ -32525,7 +32525,7 @@ function describeRemoteFiles(files) {
32525
32525
  function sha256(bytes) {
32526
32526
  return createHash("sha256").update(bytes).digest("hex");
32527
32527
  }
32528
- async function readBoundedResponse(response, maximum) {
32528
+ async function readBoundedResponse(response, maximum, signal) {
32529
32529
  if (!Number.isSafeInteger(maximum) || maximum < 0 || maximum > MAX_REMOTE_FILE_BYTES)
32530
32530
  throw new Error("Invalid artifact size limit");
32531
32531
  const length = response.headers.get("content-length");
@@ -32536,11 +32536,18 @@ async function readBoundedResponse(response, maximum) {
32536
32536
  const reader = response.body?.getReader();
32537
32537
  if (!reader)
32538
32538
  return new Uint8Array;
32539
+ signal?.throwIfAborted();
32540
+ const abort = () => {
32541
+ reader.cancel().catch(() => {});
32542
+ };
32543
+ signal?.addEventListener("abort", abort, { once: true });
32539
32544
  const chunks = [];
32540
32545
  let size = 0;
32541
32546
  try {
32542
32547
  while (true) {
32548
+ signal?.throwIfAborted();
32543
32549
  const next = await reader.read();
32550
+ signal?.throwIfAborted();
32544
32551
  if (next.done)
32545
32552
  break;
32546
32553
  size += next.value.byteLength;
@@ -32552,6 +32559,7 @@ async function readBoundedResponse(response, maximum) {
32552
32559
  await reader.cancel().catch(() => {});
32553
32560
  throw error;
32554
32561
  } finally {
32562
+ signal?.removeEventListener("abort", abort);
32555
32563
  reader.releaseLock();
32556
32564
  }
32557
32565
  const bytes = new Uint8Array(size);
@@ -34927,7 +34935,7 @@ function hash(value) {
34927
34935
  return createHash3("sha256").update(JSON.stringify(value)).digest("hex");
34928
34936
  }
34929
34937
  function validateSelection(selection) {
34930
- if (!selection || !/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(selection.slug) || !isValidSkillVersion(selection.version) || !/^sha256:[a-f0-9]{64}$/.test(selection.bundleDigest) || typeof selection.workspaceId !== "string" || !selection.workspaceId.trim() || typeof selection.profileRevision !== "string" || !selection.profileRevision.trim()) {
34938
+ if (!selection || !/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(selection.slug) || !isValidSkillVersion(selection.version) || !/^sha256:[a-f0-9]{64}$/.test(selection.bundleDigest) || typeof selection.workspaceId !== "string" || !selection.workspaceId.trim() || selection.authorizationEpoch !== undefined && (typeof selection.authorizationEpoch !== "string" || !/^[a-f0-9]{32}$/.test(selection.authorizationEpoch)) || typeof selection.profileRevision !== "string" || !selection.profileRevision.trim()) {
34931
34939
  throw new SkillSelectionError("INVALID_SELECTION", "A skill selection must carry an exact version, digest, workspace and profile revision.");
34932
34940
  }
34933
34941
  const aliasError = selectionAliasError([selection]);
@@ -35053,17 +35061,21 @@ function readSelectionJson(path) {
35053
35061
  throw new SkillSelectionError("INVALID_RECEIPT", "The Skills selection receipt is unreadable; sync the profile again.");
35054
35062
  }
35055
35063
  }
35056
- async function verifiedEntries(selection, bytes) {
35064
+ async function verifiedEntries(selection, bytes, signal, deadline) {
35057
35065
  if (`sha256:${sha256Hex(bytes)}` !== selection.bundleDigest)
35058
35066
  throw new SkillSelectionError("BUNDLE_DIGEST_MISMATCH", "The skill bundle does not match its selected digest.");
35059
- const bundle = await inspectSkillBundle(bytes);
35067
+ const remaining = deadline === undefined ? undefined : Math.floor(deadline - performance.now());
35068
+ signal?.throwIfAborted();
35069
+ if (remaining !== undefined && remaining <= 0)
35070
+ throw new SkillSelectionError("SKILLS_API_UNAVAILABLE", "Skills session authorization deadline exceeded.");
35071
+ const bundle = await inspectSkillBundle(bytes, { signal, ...remaining === undefined ? {} : { limits: { timeoutMs: remaining } } });
35060
35072
  return bundle.entries;
35061
35073
  }
35062
35074
  async function readCachedSelection(selection, options = {}) {
35063
35075
  const bytes = readRegularFile(selectionBundlePath(selection, options), SKILL_BUNDLE_INSPECTION_LIMITS.compressedBytes);
35064
35076
  return bytes ? verifiedEntries(selection, bytes) : null;
35065
35077
  }
35066
- async function cacheSelectionBundle(selection, response, options = {}) {
35078
+ async function verifySelectionBundleResponse(selection, response, signal, deadline) {
35067
35079
  validateSelection(selection);
35068
35080
  if (!response?.ok)
35069
35081
  throw new SkillSelectionError("BUNDLE_UNAVAILABLE", `The selected skill bundle is unavailable${response ? ` (HTTP ${response.status})` : ""}.`);
@@ -35073,15 +35085,27 @@ async function cacheSelectionBundle(selection, response, options = {}) {
35073
35085
  await response.body?.cancel();
35074
35086
  throw new SkillSelectionError("BUNDLE_IDENTITY_MISMATCH", "The returned bundle does not match the selected version and digest.");
35075
35087
  }
35088
+ const epoch = response.headers.get("X-Skill-Authorization-Epoch");
35089
+ if (selection.authorizationEpoch !== undefined && epoch !== selection.authorizationEpoch) {
35090
+ response.body?.cancel().catch(() => {});
35091
+ throw new SkillSelectionError("SESSION_RECONCILIATION_REQUIRED", "The selected bundle lifecycle authorization changed or is unavailable.");
35092
+ }
35076
35093
  const maximum = SKILL_BUNDLE_INSPECTION_LIMITS.compressedBytes;
35077
35094
  const reader = response.body?.getReader();
35078
35095
  if (!reader)
35079
35096
  throw new SkillSelectionError("BUNDLE_UNAVAILABLE", "The selected bundle response has no body.");
35097
+ signal?.throwIfAborted();
35098
+ const abort = () => {
35099
+ reader.cancel().catch(() => {});
35100
+ };
35101
+ signal?.addEventListener("abort", abort, { once: true });
35080
35102
  const chunks = [];
35081
35103
  let length = 0;
35082
35104
  try {
35083
35105
  while (true) {
35106
+ signal?.throwIfAborted();
35084
35107
  const next = await reader.read();
35108
+ signal?.throwIfAborted();
35085
35109
  if (next.done)
35086
35110
  break;
35087
35111
  length += next.value.byteLength;
@@ -35090,9 +35114,10 @@ async function cacheSelectionBundle(selection, response, options = {}) {
35090
35114
  chunks.push(next.value);
35091
35115
  }
35092
35116
  } catch (error) {
35093
- await reader.cancel().catch(() => {});
35117
+ reader.cancel().catch(() => {});
35094
35118
  throw error;
35095
35119
  } finally {
35120
+ signal?.removeEventListener("abort", abort);
35096
35121
  reader.releaseLock();
35097
35122
  }
35098
35123
  const bytes = new Uint8Array(length);
@@ -35101,7 +35126,12 @@ async function cacheSelectionBundle(selection, response, options = {}) {
35101
35126
  bytes.set(chunk, offset);
35102
35127
  offset += chunk.byteLength;
35103
35128
  }
35104
- const entries = await verifiedEntries(selection, bytes);
35129
+ const entries = await verifiedEntries(selection, bytes, signal, deadline);
35130
+ return { bytes, entries };
35131
+ }
35132
+ async function cacheSelectionBundle(selection, response, options = {}) {
35133
+ const { bytes, entries } = await verifySelectionBundleResponse(selection, response);
35134
+ const maximum = SKILL_BUNDLE_INSPECTION_LIMITS.compressedBytes;
35105
35135
  const path = selectionBundlePath(selection, options);
35106
35136
  const existing = readRegularFile(path, maximum);
35107
35137
  if (existing)
@@ -37301,10 +37331,12 @@ function validateSelection2(value) {
37301
37331
 
37302
37332
  class HttpProfileClient {
37303
37333
  key;
37334
+ signal;
37304
37335
  authority;
37305
37336
  origin;
37306
- constructor(key, origin) {
37337
+ constructor(key, origin, signal) {
37307
37338
  this.key = key;
37339
+ this.signal = signal;
37308
37340
  if (!key.trim())
37309
37341
  throw new Error("A Skills credential is required");
37310
37342
  this.origin = normalizeSkillsApiOrigin(origin);
@@ -37318,7 +37350,7 @@ class HttpProfileClient {
37318
37350
  ...init,
37319
37351
  redirect: "error",
37320
37352
  credentials: "omit",
37321
- signal: AbortSignal.timeout(15000),
37353
+ signal: this.signal ? AbortSignal.any([this.signal, AbortSignal.timeout(15000)]) : AbortSignal.timeout(15000),
37322
37354
  headers: {
37323
37355
  "Content-Type": "application/json",
37324
37356
  "User-Agent": `hasna-skills/${package_default.version}`,
@@ -37343,22 +37375,28 @@ class HttpProfileClient {
37343
37375
  }
37344
37376
  async read(response, limit = MAX_PROFILE_DOCUMENT_BYTES) {
37345
37377
  try {
37346
- return JSON.parse(new TextDecoder().decode(await readBoundedResponse(response, limit)));
37378
+ return JSON.parse(new TextDecoder().decode(await readBoundedResponse(response, limit, this.signal)));
37347
37379
  } catch {
37348
37380
  invalid2();
37349
37381
  }
37350
37382
  }
37383
+ async supportsPinRenewal() {
37384
+ const result = await this.read(await this.request("/capabilities"));
37385
+ if (!object(result) || !Array.isArray(result.capabilities))
37386
+ invalid2();
37387
+ return result.capabilities.includes("skills.session-pin-renewal");
37388
+ }
37351
37389
  async resolveProfile(id2) {
37352
37390
  if (!identifier2(id2))
37353
37391
  throw new Error("Invalid selection profile id");
37354
- const result = await this.read(await this.request(`/profiles/${encodeURIComponent(id2)}/resolve`), MAX_RESOLVED_PROFILE_BYTES);
37392
+ const result = await this.read(await this.request(`/profiles/${encodeURIComponent(id2)}/resolve?pinAuthorization=epoch-v1`), MAX_RESOLVED_PROFILE_BYTES);
37355
37393
  if (!object(result) || result.profileId !== id2 || result.authority !== this.authority || !identifier2(result.workspaceId) || !identifier2(result.profileRevision) || !Array.isArray(result.selections) || result.selections.length > MAX_PROFILE_SELECTIONS)
37356
37394
  invalid2();
37357
37395
  const seen = new Set;
37358
37396
  for (const entry of result.selections) {
37359
37397
  validateSelection2(entry);
37360
37398
  const item = entry;
37361
- if (seen.has(item.slug) || item.authority !== this.authority || item.workspaceId !== result.workspaceId || item.profileRevision !== result.profileRevision)
37399
+ if (item.authorizationEpoch !== undefined && (typeof item.authorizationEpoch !== "string" || !/^[a-f0-9]{32}$/.test(item.authorizationEpoch)) || seen.has(item.slug) || item.authority !== this.authority || item.workspaceId !== result.workspaceId || item.profileRevision !== result.profileRevision)
37362
37400
  invalid2();
37363
37401
  seen.add(item.slug);
37364
37402
  }
@@ -37405,7 +37443,7 @@ class HttpProfileClient {
37405
37443
  return this.request(`/skills/${encodeURIComponent(slug)}/versions/${encodeURIComponent(version)}/bundle`);
37406
37444
  }
37407
37445
  }
37408
- async function createProfileClient() {
37446
+ async function createProfileClient(signal) {
37409
37447
  let connection;
37410
37448
  try {
37411
37449
  connection = await resolveSkillsConnection();
@@ -37417,7 +37455,7 @@ async function createProfileClient() {
37417
37455
  }
37418
37456
  if (!connection)
37419
37457
  throw new Error("Selection profiles require a configured Skills API");
37420
- return new HttpProfileClient(connection.apiKey, connection.apiOrigin);
37458
+ return new HttpProfileClient(connection.apiKey, connection.apiOrigin, signal);
37421
37459
  }
37422
37460
  // src/lib/session-reconciliation.ts
37423
37461
  import { createHash as createHash4 } from "crypto";
@@ -37516,10 +37554,10 @@ async function reconcileSkillSession(input, options = {}) {
37516
37554
  return { applied: true, plan, planDigest, ...result };
37517
37555
  }
37518
37556
  // src/lib/selected-run.ts
37519
- import { createHash as createHash24 } from "crypto";
37557
+ import { createHash as createHash25 } from "crypto";
37520
37558
  import { spawn as spawn2 } from "child_process";
37521
37559
  import { mkdirSync as mkdirSync11, mkdtempSync as mkdtempSync3, writeFileSync as writeFileSync10, realpathSync as realpathSync14 } from "fs";
37522
- import { dirname as dirname22, join as join36, resolve as resolve21 } from "path";
37560
+ import { dirname as dirname22, join as join37, resolve as resolve21 } from "path";
37523
37561
  import { tmpdir, hostname as stationHostname2 } from "os";
37524
37562
 
37525
37563
  // src/lib/dependency-preparation.ts
@@ -37731,7 +37769,7 @@ async function prepareSkillDependencies(skillPath, env, timeoutMs = DEFAULT_PREP
37731
37769
 
37732
37770
  // src/lib/skillinfo.ts
37733
37771
  import { existsSync as existsSync15, readFileSync as readFileSync23 } from "fs";
37734
- import { join as join35 } from "path";
37772
+ import { join as join36 } from "path";
37735
37773
 
37736
37774
  // src/lib/codex-corpus-write.ts
37737
37775
  import { KernelLock } from "@hasna/contracts/kernel-lock";
@@ -37896,7 +37934,7 @@ function withCodexCorpusWrite(roots, run, options = {}) {
37896
37934
 
37897
37935
  // src/lib/installer.ts
37898
37936
  import { existsSync as existsSync14, readFileSync as readFileSync22, rmSync as rmSync4 } from "fs";
37899
- import { join as join34 } from "path";
37937
+ import { join as join35 } from "path";
37900
37938
  import { homedir as homedir6 } from "os";
37901
37939
 
37902
37940
  // src/lib/agent-sync.ts
@@ -37914,7 +37952,7 @@ import {
37914
37952
  writeFileSync as writeFileSync8
37915
37953
  } from "fs";
37916
37954
  import { homedir as homedir5 } from "os";
37917
- import { basename as basename12, dirname as dirname21, join as join31 } from "path";
37955
+ import { basename as basename12, dirname as dirname21, join as join32 } from "path";
37918
37956
 
37919
37957
  // src/lib/sumi-settings-witness.ts
37920
37958
  import { createHash as createHash7 } from "crypto";
@@ -40214,18 +40252,18 @@ var NATIVE_SKILL_ROOTS = [
40214
40252
  ];
40215
40253
 
40216
40254
  // src/lib/agent-integration.ts
40217
- import { createHash as createHash22, randomUUID as randomUUID4 } from "crypto";
40255
+ import { createHash as createHash23, randomUUID as randomUUID4 } from "crypto";
40218
40256
  import { isDeepStrictEqual as isDeepStrictEqual8 } from "util";
40219
40257
  import { existsSync as existsSync7, lstatSync as lstatSync22, statSync as statSync7, mkdirSync as mkdirSync6, readFileSync as readFileSync16, readdirSync as readdirSync8, opendirSync as opendirSync5, readlinkSync as readlinkSync5, realpathSync as realpathSync10, renameSync as renameSync4, rmdirSync as rmdirSync3, writeFileSync as writeFileSync5, unlinkSync as unlinkSync5, chmodSync, openSync as openSync17, closeSync as closeSync17, fsyncSync as fsyncSync5, fstatSync as fstatSync17, readSync as readSync12, constants as constants14, linkSync as linkSync3 } from "fs";
40220
- import { dirname as dirname17, join as join26, resolve as resolve18, relative as relative5, isAbsolute as isAbsolute19, sep as sep6 } from "path";
40258
+ import { dirname as dirname17, join as join27, resolve as resolve18, relative as relative5, isAbsolute as isAbsolute19, sep as sep7 } from "path";
40221
40259
  import { homedir as homedir3 } from "os";
40222
40260
 
40223
40261
  // src/lib/managed-policy.ts
40224
40262
  import { closeSync as closeSync11, constants as constants8, fstatSync as fstatSync11, lstatSync as lstatSync9, openSync as openSync11, readSync as readSync6 } from "fs";
40225
- import { join as join14 } from "path";
40263
+ import { join as join15 } from "path";
40226
40264
 
40227
40265
  // src/lib/agent-policy-limits.ts
40228
- import { basename as basename5, isAbsolute as isAbsolute8, resolve as resolve7 } from "path";
40266
+ import { basename as basename5, isAbsolute as isAbsolute8, join as join14, resolve as resolve7, sep as sep4 } from "path";
40229
40267
  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 });
40230
40268
  function object4(value) {
40231
40269
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
@@ -40367,7 +40405,9 @@ function assertAgentPolicyCollections(policy) {
40367
40405
  text(source.path);
40368
40406
  requireBound(source.sha256 === null || typeof source.sha256 === "string" && /^[a-f0-9]{64}$/.test(source.sha256));
40369
40407
  if (source.hashMode !== undefined)
40370
- requireBound(["bytes", "path-bytes", "claude-plugin-registry", "claude-marketplace-registry", "claude-settings-v1", "claude-settings-v2", "claude-settings-v3", "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));
40408
+ requireBound(["bytes", "path-bytes", "claude-plugin-manifest-v1", "claude-plugin-registry", "claude-marketplace-registry", "claude-settings-v1", "claude-settings-v2", "claude-settings-v3", "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));
40409
+ if (source.hashMode === "claude-plugin-manifest-v1")
40410
+ 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);
40371
40411
  if (source.hashMode === "sumi-settings-v1")
40372
40412
  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");
40373
40413
  if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4"))
@@ -40436,7 +40476,7 @@ function serializeManagedSkillPolicy(value) {
40436
40476
  return text2;
40437
40477
  }
40438
40478
  function readManagedSkillPolicySnapshot(dataDir2 = getDataDirReadOnly()) {
40439
- const path = join14(dataDir2, "agent-policy.json");
40479
+ const path = join15(dataDir2, "agent-policy.json");
40440
40480
  let descriptor, observed = false;
40441
40481
  try {
40442
40482
  const stat = lstatSync9(path);
@@ -40486,7 +40526,7 @@ function requiresCliSkillLoading(dataDir2 = getDataDirReadOnly()) {
40486
40526
  // src/lib/agent-bridge.ts
40487
40527
  import { createHash as createHash12 } from "crypto";
40488
40528
  import { lstatSync as lstatSync10, readFileSync as readFileSync11, readdirSync as readdirSync4 } from "fs";
40489
- import { join as join15 } from "path";
40529
+ import { join as join16 } from "path";
40490
40530
  var CLI_BRIDGE_NAME = "skills-cli";
40491
40531
  var CLI_BRIDGE_VERSION = 1;
40492
40532
  var markdown = `---
@@ -40518,7 +40558,7 @@ function isOwnedCliBridge(path, expectedPaths) {
40518
40558
  if (JSON.stringify(readdirSync4(path).sort()) !== JSON.stringify(Object.keys(CLI_BRIDGE_FILES).sort()))
40519
40559
  return false;
40520
40560
  return Object.entries(CLI_BRIDGE_FILES).every(([name, content]) => {
40521
- const file = join15(path, name), stat = lstatSync10(file);
40561
+ const file = join16(path, name), stat = lstatSync10(file);
40522
40562
  return stat.isFile() && !stat.isSymbolicLink() && stat.size === Buffer.byteLength(content) && readFileSync11(file, "utf8") === content;
40523
40563
  });
40524
40564
  } catch {
@@ -40527,9 +40567,9 @@ function isOwnedCliBridge(path, expectedPaths) {
40527
40567
  }
40528
40568
 
40529
40569
  // src/lib/agent-discovery.ts
40530
- import { createHash as createHash21 } from "crypto";
40570
+ import { createHash as createHash22 } from "crypto";
40531
40571
  import { lstatSync as lstatSync21, readFileSync as readFileSync15, readdirSync as readdirSync7, realpathSync as realpathSync9 } from "fs";
40532
- import { basename as basename8, dirname as dirname16, isAbsolute as isAbsolute18, join as join25, resolve as resolve17, sep as sep5 } from "path";
40572
+ import { basename as basename8, dirname as dirname16, isAbsolute as isAbsolute18, join as join26, resolve as resolve17, sep as sep6 } from "path";
40533
40573
  import { isDeepStrictEqual as isDeepStrictEqual6 } from "util";
40534
40574
 
40535
40575
  // node_modules/yaml/dist/index.js
@@ -40579,7 +40619,7 @@ var $visit = visit.visit;
40579
40619
  var $visitAsync = visit.visitAsync;
40580
40620
 
40581
40621
  // src/lib/agent-hermes.ts
40582
- import { dirname as dirname8, isAbsolute as isAbsolute9, join as join16, resolve as resolve8 } from "path";
40622
+ import { dirname as dirname8, isAbsolute as isAbsolute9, join as join17, resolve as resolve8 } from "path";
40583
40623
  import { lstatSync as lstatSync11, readFileSync as readFileSync12, opendirSync } from "fs";
40584
40624
  var HERMES_OPT_OUT = ".no-bundled-skills";
40585
40625
  var EVENTS = ["pre_llm_call", "pre_tool_call"];
@@ -40653,7 +40693,7 @@ function assertHermesEnvironment(home) {
40653
40693
  throw new Error(`NATIVE_SKILL_DRIFT: Hermes ${variable} requires a dedicated discovery adapter; unset it before using this adapter`);
40654
40694
  }
40655
40695
  const selected = process.env.HERMES_HOME?.trim();
40656
- if (selected && (!isAbsolute9(selected) || resolve8(selected) !== join16(resolve8(home), ".hermes")))
40696
+ if (selected && (!isAbsolute9(selected) || resolve8(selected) !== join17(resolve8(home), ".hermes")))
40657
40697
  throw new Error("NATIVE_SKILL_DRIFT: custom Hermes homes/profiles require their own reviewed bridge");
40658
40698
  if (process.env.HERMES_ENABLE_PROJECT_PLUGINS?.trim() && !["0", "false", "no", "off"].includes(process.env.HERMES_ENABLE_PROJECT_PLUGINS.trim().toLowerCase()))
40659
40699
  throw new Error("NATIVE_SKILL_DRIFT: Hermes project plugins require a dedicated discovery review");
@@ -40674,11 +40714,11 @@ function read(path) {
40674
40714
  }
40675
40715
  function assertHermesProtection(home, config, command, profile, supervisor) {
40676
40716
  assertHermesEnvironment(home);
40677
- if (read(join16(home, ".hermes", HERMES_OPT_OUT)) === null)
40717
+ if (read(join17(home, ".hermes", HERMES_OPT_OUT)) === null)
40678
40718
  throw new Error("NATIVE_SKILL_DRIFT: Hermes bundled skill reseeding is not disabled; run skills hook install");
40679
40719
  if (!supervisor || !isAbsolute9(supervisor.path) || supervisor.runtime !== process.execPath || read(supervisor.path) !== renderHermesSupervisor(command, profile))
40680
40720
  throw new Error("NATIVE_SKILL_DRIFT: Hermes owned supervisor changed; run skills hook install");
40681
- const raw = read(join16(home, ".hermes/shell-hooks-allowlist.json"));
40721
+ const raw = read(join17(home, ".hermes/shell-hooks-allowlist.json"));
40682
40722
  let trust;
40683
40723
  try {
40684
40724
  trust = raw === null ? undefined : JSON.parse(raw);
@@ -40721,15 +40761,15 @@ function assertNoHermesLegacyShadow(root) {
40721
40761
  throw new Error("NATIVE_SKILL_DRIFT: unsupported Hermes legacy discovery input");
40722
40762
  return;
40723
40763
  }
40724
- if (lstatSync11(join16(path, "skills-cli.md"), { throwIfNoEntry: false }))
40764
+ if (lstatSync11(join17(path, "skills-cli.md"), { throwIfNoEntry: false }))
40725
40765
  throw new Error("NATIVE_SKILL_DRIFT: legacy Hermes skills-cli.md can shadow the owned bridge; preserve and retire it before continuing");
40726
- const hasDescriptor = Boolean(lstatSync11(join16(path, "SKILL.md"), { throwIfNoEntry: false }));
40766
+ const hasDescriptor = Boolean(lstatSync11(join17(path, "SKILL.md"), { throwIfNoEntry: false }));
40727
40767
  const directory = opendirSync(path);
40728
40768
  try {
40729
40769
  for (let child = directory.readSync();child; child = directory.readSync()) {
40730
40770
  if (hasDescriptor && ["references", "templates", "assets", "scripts"].includes(child.name))
40731
40771
  continue;
40732
- scan(join16(path, child.name), depth + 1);
40772
+ scan(join17(path, child.name), depth + 1);
40733
40773
  }
40734
40774
  } finally {
40735
40775
  directory.closeSync();
@@ -40788,7 +40828,7 @@ if (failed) process.exitCode = 2;
40788
40828
  // src/lib/agent-discovery-directories.ts
40789
40829
  import { createHash as createHash13 } from "crypto";
40790
40830
  import { lstatSync as lstatSync12, opendirSync as opendirSync2 } from "fs";
40791
- import { dirname as dirname9, isAbsolute as isAbsolute10, join as join17, resolve as resolve9 } from "path";
40831
+ import { dirname as dirname9, isAbsolute as isAbsolute10, join as join18, resolve as resolve9 } from "path";
40792
40832
  function need4(value, message) {
40793
40833
  if (!value)
40794
40834
  throw new Error(message);
@@ -40826,7 +40866,7 @@ function capture(path, budget2, excludedRoots, omittedRoots = [], rows) {
40826
40866
  }
40827
40867
  need4(new Set(names).size === names.length, "Ambiguous native discovery directory names");
40828
40868
  for (const name of names.sort()) {
40829
- const child = join17(current, name), childRelative = relative5 ? `${relative5}/${name}` : name;
40869
+ const child = join18(current, name), childRelative = relative5 ? `${relative5}/${name}` : name;
40830
40870
  if (omittedRoots.includes(child))
40831
40871
  continue;
40832
40872
  need4(child.length <= AGENT_POLICY_LIMITS.pathCharacters, "Native discovery directory path limit exceeded");
@@ -40874,7 +40914,7 @@ function verifyDiscoveryDirectoryProjection(directories, omittedRoots) {
40874
40914
  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) + `
40875
40915
  `, "Invalid reviewed directory member");
40876
40916
  hash2.update(row);
40877
- const path = join17(directory.path, value[0]);
40917
+ const path = join18(directory.path, value[0]);
40878
40918
  if (!omittedRoots.some((root) => path === root || path.startsWith(root + "/")))
40879
40919
  kept.push(row);
40880
40920
  }
@@ -40972,7 +41012,7 @@ function hashRawDiscoveryFile(path, budget2, changes) {
40972
41012
  // src/lib/agent-discovery-path-bytes.ts
40973
41013
  import { createHash as createHash15 } from "crypto";
40974
41014
  import { lstatSync as lstatSync14, readlinkSync as readlinkSync4 } from "fs";
40975
- import { dirname as dirname11, isAbsolute as isAbsolute12, join as join18, parse as parse3, resolve as resolve11, sep as sep4 } from "path";
41015
+ import { dirname as dirname11, isAbsolute as isAbsolute12, join as join19, parse as parse3, resolve as resolve11, sep as sep5 } from "path";
40976
41016
  function identity4(stat, mutable = false) {
40977
41017
  return {
40978
41018
  dev: String(stat.dev),
@@ -40990,7 +41030,7 @@ function canonical4(path) {
40990
41030
  function trace(path) {
40991
41031
  canonical4(path);
40992
41032
  const rows = [], paths = [];
40993
- let metadataBytes = 0, steps = 0, links = 0, cursor = parse3(path).root, pending = path.slice(cursor.length).split(sep4);
41033
+ let metadataBytes = 0, steps = 0, links = 0, cursor = parse3(path).root, pending = path.slice(cursor.length).split(sep5);
40994
41034
  function record4(path2, row) {
40995
41035
  const value = { path: path2, ...row };
40996
41036
  metadataBytes += Buffer.byteLength(JSON.stringify(value));
@@ -41016,7 +41056,7 @@ function trace(path) {
41016
41056
  cursor = dirname11(cursor);
41017
41057
  continue;
41018
41058
  }
41019
- const candidate = join18(cursor, component);
41059
+ const candidate = join19(cursor, component);
41020
41060
  if (candidate.length > AGENT_POLICY_LIMITS.pathCharacters)
41021
41061
  throw new Error("Discovery resolved path length limit exceeded");
41022
41062
  const stat = lstatSync14(candidate, { bigint: true, throwIfNoEntry: false });
@@ -41038,7 +41078,7 @@ function trace(path) {
41038
41078
  root();
41039
41079
  }
41040
41080
  const remainder = isAbsolute12(target) ? target.slice(parse3(target).root.length) : target;
41041
- pending = [...remainder.split(sep4), ...pending];
41081
+ pending = [...remainder.split(sep5), ...pending];
41042
41082
  if (pending.length + steps > AGENT_POLICY_LIMITS.discoveryPathSteps)
41043
41083
  throw new Error("Discovery path step limit exceeded");
41044
41084
  continue;
@@ -41062,7 +41102,7 @@ function hashDiscoveryPathFile(path, budget2, changes) {
41062
41102
  let createsMissingPath = false;
41063
41103
  if (before.missing !== null && changes) {
41064
41104
  for (const target of changes.keys()) {
41065
- if (target === before.missing || target.startsWith(before.missing + sep4)) {
41105
+ if (target === before.missing || target.startsWith(before.missing + sep5)) {
41066
41106
  createsMissingPath = true;
41067
41107
  break;
41068
41108
  }
@@ -41083,16 +41123,151 @@ function hashDiscoveryPathFile(path, budget2, changes) {
41083
41123
  return createHash15("sha256").update(JSON.stringify({ version: 1, path, rows: before.rows, content })).digest("hex");
41084
41124
  }
41085
41125
 
41126
+ // src/lib/claude-plugin-manifest-witness.ts
41127
+ import { createHash as createHash16 } from "crypto";
41128
+ var CLAUDE_PLUGIN_MANIFEST_LIMITS = Object.freeze({ bytes: 1024 * 1024, depth: 32, nodes: 65536, stringCharacters: 16384 });
41129
+ function requireValue(value, reason) {
41130
+ if (!value)
41131
+ throw new Error("Claude plugin manifest " + reason);
41132
+ }
41133
+ function parse4(text2) {
41134
+ requireValue(Buffer.byteLength(text2, "utf8") <= CLAUDE_PLUGIN_MANIFEST_LIMITS.bytes, "exceeds its byte limit");
41135
+ let at = 0, nodes = 0;
41136
+ const numberPattern = /-?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?/y;
41137
+ const space = () => {
41138
+ while (at < text2.length && /[\x20\t\r\n]/.test(text2[at]))
41139
+ at++;
41140
+ };
41141
+ function string() {
41142
+ requireValue(text2[at] === '"', "contains invalid JSON");
41143
+ const start = at++;
41144
+ while (at < text2.length) {
41145
+ const character = text2[at++];
41146
+ if (character === '"') {
41147
+ let value2;
41148
+ try {
41149
+ value2 = JSON.parse(text2.slice(start, at));
41150
+ } catch {
41151
+ throw new Error("Claude plugin manifest contains invalid JSON string");
41152
+ }
41153
+ requireValue(value2.length <= CLAUDE_PLUGIN_MANIFEST_LIMITS.stringCharacters, "exceeds its string limit");
41154
+ return value2;
41155
+ }
41156
+ if (character === "\\")
41157
+ at++;
41158
+ }
41159
+ throw new Error("Claude plugin manifest contains an unterminated JSON string");
41160
+ }
41161
+ function value(depth) {
41162
+ requireValue(depth <= CLAUDE_PLUGIN_MANIFEST_LIMITS.depth && ++nodes <= CLAUDE_PLUGIN_MANIFEST_LIMITS.nodes, "exceeds its nesting or node limit");
41163
+ space();
41164
+ const character = text2[at];
41165
+ if (character === '"')
41166
+ return { kind: "string", value: string() };
41167
+ if (character === "{" || character === "[") {
41168
+ at++;
41169
+ space();
41170
+ const object6 = character === "{", end = object6 ? "}" : "]", entries = [], items = [], keys2 = new Set;
41171
+ if (text2[at] !== end)
41172
+ while (true) {
41173
+ if (object6) {
41174
+ space();
41175
+ const key = string();
41176
+ requireValue(!keys2.has(key), "contains a duplicate JSON key");
41177
+ keys2.add(key);
41178
+ space();
41179
+ requireValue(text2[at++] === ":", "contains invalid JSON");
41180
+ entries.push([key, value(depth + 1)]);
41181
+ } else
41182
+ items.push(value(depth + 1));
41183
+ space();
41184
+ if (text2[at] === end)
41185
+ break;
41186
+ requireValue(text2[at++] === ",", "contains invalid JSON");
41187
+ }
41188
+ at++;
41189
+ return object6 ? { kind: "object", entries } : { kind: "array", items };
41190
+ }
41191
+ for (const literal of ["true", "false", "null"])
41192
+ if (text2.startsWith(literal, at)) {
41193
+ at += literal.length;
41194
+ return { kind: "literal", value: literal };
41195
+ }
41196
+ numberPattern.lastIndex = at;
41197
+ const number = numberPattern.exec(text2);
41198
+ requireValue(number, "contains invalid JSON");
41199
+ at += number[0].length;
41200
+ return { kind: "number", value: number[0] };
41201
+ }
41202
+ const root = value(0);
41203
+ space();
41204
+ requireValue(at === text2.length && root.kind === "object", "requires a JSON object without trailing content");
41205
+ return root;
41206
+ }
41207
+ function canonical5(value) {
41208
+ if (value.kind === "string")
41209
+ return JSON.stringify(value.value);
41210
+ if (value.kind === "number")
41211
+ return value.value;
41212
+ if (value.kind === "literal")
41213
+ return value.value;
41214
+ if (value.kind === "array")
41215
+ return "[" + value.items.map(canonical5).join(",") + "]";
41216
+ return "{" + value.entries.map(([key, item]) => JSON.stringify(key) + ":" + canonical5(item)).join(",") + "}";
41217
+ }
41218
+ var DESCRIPTIVE_FIELDS = new Set(["description", "version", "author", "homepage", "repository", "license", "keywords"]);
41219
+ function validateText(value, field) {
41220
+ requireValue(value?.kind === "string" && value.value.length <= CLAUDE_PLUGIN_MANIFEST_LIMITS.stringCharacters, "has an invalid " + field + " field");
41221
+ }
41222
+ function validateDescriptiveFields(manifest) {
41223
+ const values = new Map(manifest.entries);
41224
+ for (const field of ["description", "version", "homepage", "license"]) {
41225
+ const value = values.get(field);
41226
+ if (value !== undefined)
41227
+ validateText(value, field);
41228
+ }
41229
+ const author = values.get("author");
41230
+ if (author !== undefined) {
41231
+ if (author.kind === "string")
41232
+ validateText(author, "author");
41233
+ else {
41234
+ requireValue(author.kind === "object" && author.entries.every(([key, value]) => ["name", "email", "url"].includes(key) && value.kind === "string" && value.value.length <= CLAUDE_PLUGIN_MANIFEST_LIMITS.stringCharacters), "has an invalid author field");
41235
+ }
41236
+ }
41237
+ const repository = values.get("repository");
41238
+ if (repository !== undefined) {
41239
+ if (repository.kind === "string")
41240
+ validateText(repository, "repository");
41241
+ else
41242
+ requireValue(repository.kind === "object" && repository.entries.every(([key, value]) => ["type", "url", "directory"].includes(key) && value.kind === "string" && value.value.length <= CLAUDE_PLUGIN_MANIFEST_LIMITS.stringCharacters), "has an invalid repository field");
41243
+ }
41244
+ const keywords = values.get("keywords");
41245
+ if (keywords !== undefined)
41246
+ requireValue(keywords.kind === "array" && keywords.items.every((value) => value.kind === "string" && value.value.length <= CLAUDE_PLUGIN_MANIFEST_LIMITS.stringCharacters), "has an invalid keywords field");
41247
+ }
41248
+ function hashClaudePluginManifest(text2) {
41249
+ const manifest = parse4(text2);
41250
+ validateDescriptiveFields(manifest);
41251
+ const discovery = { kind: "object", entries: manifest.entries.filter(([key]) => !DESCRIPTIVE_FIELDS.has(key)) };
41252
+ return createHash16("sha256").update(canonical5(discovery)).digest("hex");
41253
+ }
41254
+ function projectReviewedClaudePluginManifest(text2, reviewedSha256) {
41255
+ if (!/^[a-f0-9]{64}$/.test(reviewedSha256) || createHash16("sha256").update(text2).digest("hex") !== reviewedSha256) {
41256
+ throw new Error("Reviewed Claude plugin manifest changed before semantic projection");
41257
+ }
41258
+ return hashClaudePluginManifest(text2);
41259
+ }
41260
+
41086
41261
  // src/lib/plugin-discovery.ts
41087
41262
  import { closeSync as closeSync14, constants as constants11, fstatSync as fstatSync14, lstatSync as lstatSync17, openSync as openSync14, opendirSync as opendirSync4, readSync as readSync9 } from "fs";
41088
- import { basename as basename6, dirname as dirname13, isAbsolute as isAbsolute16, join as join23, resolve as resolve14 } from "path";
41263
+ import { basename as basename6, dirname as dirname13, isAbsolute as isAbsolute16, join as join24, resolve as resolve14 } from "path";
41089
41264
 
41090
41265
  // src/lib/plugin-admission.ts
41091
41266
  import { homedir as homedir2 } from "os";
41092
- import { isAbsolute as isAbsolute15, join as join22, resolve as resolve13 } from "path";
41267
+ import { isAbsolute as isAbsolute15, join as join23, resolve as resolve13 } from "path";
41093
41268
 
41094
41269
  // src/lib/plugin-projection.ts
41095
- import { createHash as createHash16 } from "crypto";
41270
+ import { createHash as createHash17 } from "crypto";
41096
41271
  import { posix as posix2 } from "path";
41097
41272
  var PLUGIN_PROJECTION_MANIFEST = "plugin-projection.json";
41098
41273
  var PLUGIN_PROJECTION_LIMITS = Object.freeze({ files: 1024, bytes: 64 * 1024 * 1024, fileBytes: 16 * 1024 * 1024, metadataBytes: 512 * 1024, registrations: 64, history: 128 });
@@ -41103,7 +41278,7 @@ function pluginNeed(value, message) {
41103
41278
  if (!value)
41104
41279
  pluginRefusal(message);
41105
41280
  }
41106
- var pluginHash = (bytes) => createHash16("sha256").update(bytes).digest("hex");
41281
+ var pluginHash = (bytes) => createHash17("sha256").update(bytes).digest("hex");
41107
41282
  function pluginObject(value) {
41108
41283
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
41109
41284
  }
@@ -41119,7 +41294,7 @@ function pluginId(value) {
41119
41294
  function pluginDigest(value) {
41120
41295
  pluginNeed(typeof value === "string" && /^sha256:[a-f0-9]{64}$/.test(value), "Invalid plugin tree digest");
41121
41296
  }
41122
- function parse4(bytes) {
41297
+ function parse5(bytes) {
41123
41298
  pluginNeed(bytes.byteLength <= PLUGIN_PROJECTION_LIMITS.metadataBytes, "Plugin metadata exceeds its limit");
41124
41299
  try {
41125
41300
  return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
@@ -41210,7 +41385,7 @@ function buildPluginProjection(entries) {
41210
41385
  pluginFileWitnesses(entries);
41211
41386
  const contract = entries.filter((item) => item.path === PLUGIN_PROJECTION_MANIFEST);
41212
41387
  pluginNeed(contract.length === 1, "The selected bundle has no unique plugin projection manifest");
41213
- const manifest = parse4(contract[0].bytes);
41388
+ const manifest = parse5(contract[0].bytes);
41214
41389
  validatePluginManifest(manifest);
41215
41390
  const original = entries.filter((item) => item.path.startsWith("original/")).map((item) => ({ ...item, path: item.path.slice(9) }));
41216
41391
  pluginNeed(!original.some((item) => [".in_use", ".orphaned_at", ".gcs-sha", ".links_materialized"].some((path) => within(item.path, path))), "Original plugin packages cannot supply native runtime metadata");
@@ -41218,7 +41393,7 @@ function buildPluginProjection(entries) {
41218
41393
  pluginNeed(originalTreeDigest === manifest.upstream.treeDigest, "The original plugin package differs from its immutable provenance");
41219
41394
  const native = original.find((item) => item.path === ".claude-plugin/plugin.json");
41220
41395
  pluginNeed(native, "The original plugin manifest is missing");
41221
- const config = parse4(native.bytes);
41396
+ const config = parse5(native.bytes);
41222
41397
  pluginKeys(config, MANIFEST_FIELDS);
41223
41398
  pluginNeed(config.name === manifest.pluginId.split("@")[0] && (manifest.upstream.version === null ? !Object.hasOwn(config, "version") : config.version === manifest.upstream.version), "Original plugin identity differs from its contract");
41224
41399
  const skillRoots = ["skills", ...declaredPaths(config.skills)], commandRoots = ["commands", ...declaredPaths(config.commands)];
@@ -41262,7 +41437,7 @@ function buildPluginProjection(entries) {
41262
41437
  if (item.path === native.path)
41263
41438
  continue;
41264
41439
  if (item.path.toLowerCase() === "package.json") {
41265
- const pkg = parse4(item.bytes);
41440
+ const pkg = parse5(item.bytes);
41266
41441
  pluginNeed(pluginObject(pkg), "Invalid plugin package metadata");
41267
41442
  for (const key of ["scripts", "dependencies", "optionalDependencies", "devDependencies", "peerDependencies", "workspaces", "bundledDependencies", "bundleDependencies", "packageManager"])
41268
41443
  pluginNeed(pkg[key] === undefined, "Upstream package installation is outside plugin admission");
@@ -41291,9 +41466,9 @@ function buildPluginProjection(entries) {
41291
41466
  }
41292
41467
 
41293
41468
  // src/lib/plugin-projection-store.ts
41294
- import { createHash as createHash17, randomUUID as randomUUID3 } from "crypto";
41469
+ import { createHash as createHash18, randomUUID as randomUUID3 } from "crypto";
41295
41470
  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";
41296
- import { dirname as dirname12, isAbsolute as isAbsolute13, join as join19, parse as parse5, resolve as resolve12 } from "path";
41471
+ import { dirname as dirname12, isAbsolute as isAbsolute13, join as join20, parse as parse6, resolve as resolve12 } from "path";
41297
41472
  var READ_FLAGS = constants10.O_RDONLY | constants10.O_NOFOLLOW | constants10.O_NONBLOCK;
41298
41473
  var WRITE_FLAGS = constants10.O_WRONLY | constants10.O_CREAT | constants10.O_EXCL | constants10.O_NOFOLLOW | constants10.O_NONBLOCK;
41299
41474
  var uid = () => typeof process.getuid === "function" ? BigInt(process.getuid()) : undefined;
@@ -41307,7 +41482,7 @@ function stat(path) {
41307
41482
  return pluginRefusal("Cannot inspect plugin filesystem entry");
41308
41483
  }
41309
41484
  }
41310
- function canonical5(path) {
41485
+ function canonical6(path) {
41311
41486
  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");
41312
41487
  }
41313
41488
  function owner(stats, system = false) {
@@ -41318,12 +41493,12 @@ function same3(left, right, identityOnly = false) {
41318
41493
  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");
41319
41494
  }
41320
41495
  function ancestors(path, create = false) {
41321
- canonical5(path);
41322
- const result = [], parent = dirname12(path), filesystemRoot = parse5(parent).root;
41496
+ canonical6(path);
41497
+ const result = [], parent = dirname12(path), filesystemRoot = parse6(parent).root;
41323
41498
  let current = filesystemRoot;
41324
41499
  for (const segment of ["", ...parent.slice(filesystemRoot.length).split("/").filter(Boolean)]) {
41325
41500
  if (segment)
41326
- current = join19(current, segment);
41501
+ current = join20(current, segment);
41327
41502
  let currentStat = stat(current);
41328
41503
  if (!currentStat && create) {
41329
41504
  try {
@@ -41438,7 +41613,7 @@ function snapshotPluginTree(root, options = {}) {
41438
41613
  pluginNeed(++visited <= PLUGIN_PROJECTION_LIMITS.files * 50, "Plugin tree membership exceeds its limit");
41439
41614
  const path = relative5 ? `${relative5}/${name}` : name;
41440
41615
  pluginNeed(new TextEncoder().encode(path).byteLength <= 100 && !/[\\:\x00-\x1f\x7f]/u.test(path), "Plugin entry path exceeds its limit or is unsafe");
41441
- const absolute = join19(directory, name), entryStat = stat(absolute);
41616
+ const absolute = join20(directory, name), entryStat = stat(absolute);
41442
41617
  pluginNeed(entryStat, "Plugin tree member disappeared");
41443
41618
  if (relative5 === "" && name === ".orphaned_at" && (options.nativeRuntime === "claude-2.1.274" || options.nativeRuntime === "claude-2.1.276")) {
41444
41619
  const bytes2 = readBytes(absolute, 32, "native-pin");
@@ -41455,7 +41630,7 @@ function snapshotPluginTree(root, options = {}) {
41455
41630
  directories.push({ path: absolute, stat: entryStat, names: pins });
41456
41631
  for (const pin of pins) {
41457
41632
  pluginNeed(/^[1-9][0-9]{0,9}$/.test(pin) && Number(pin) <= 2147483647, "Unrecognized native plugin pin name");
41458
- const pinPath = join19(absolute, pin), pinStat = stat(pinPath);
41633
+ const pinPath = join20(absolute, pin), pinStat = stat(pinPath);
41459
41634
  pluginNeed(pinStat, "Native plugin pin disappeared");
41460
41635
  const bytes2 = readBytes(pinPath, 4096, "native-pin");
41461
41636
  let value;
@@ -41553,7 +41728,7 @@ function materializePluginTree(root, entries) {
41553
41728
  mkdirSync5(staging, { mode: 448 });
41554
41729
  staged = stat(staging);
41555
41730
  for (const entry of entries) {
41556
- const path = join19(staging, entry.path);
41731
+ const path = join20(staging, entry.path);
41557
41732
  ancestors(path, true);
41558
41733
  writeExclusive(path, entry.bytes, entry.mode);
41559
41734
  }
@@ -41633,7 +41808,7 @@ function pluginExecutableDigest(path) {
41633
41808
  const opened = fstatSync13(fd, { bigint: true });
41634
41809
  same3(before, opened);
41635
41810
  fileShape(opened, maximum, "executable");
41636
- const hash2 = createHash17("sha256"), buffer = new Uint8Array(64 * 1024);
41811
+ const hash2 = createHash18("sha256"), buffer = new Uint8Array(64 * 1024);
41637
41812
  let remaining = Number(opened.size);
41638
41813
  while (remaining > 0) {
41639
41814
  const count = readSync8(fd, buffer, 0, Math.min(buffer.byteLength, remaining), null);
@@ -41658,11 +41833,11 @@ function pluginExecutableDigest(path) {
41658
41833
 
41659
41834
  // src/lib/skill-validation.ts
41660
41835
  import { existsSync as existsSync5, lstatSync as lstatSync16, readFileSync as readFileSync14, readdirSync as readdirSync6, statSync as statSync6 } from "fs";
41661
- import { isAbsolute as isAbsolute14, join as join21, normalize as normalize3 } from "path";
41836
+ import { isAbsolute as isAbsolute14, join as join22, normalize as normalize3 } from "path";
41662
41837
 
41663
41838
  // src/lib/hosted-skill-set.ts
41664
41839
  import { existsSync as existsSync4, readFileSync as readFileSync13, readdirSync as readdirSync5, statSync as statSync5 } from "fs";
41665
- import { join as join20 } from "path";
41840
+ import { join as join21 } from "path";
41666
41841
  var HOSTED_RUNTIMES = new Set(["hosted"]);
41667
41842
  var HOSTED_SOURCES = new Set(["remote", "private-hosted"]);
41668
41843
  function normalizeMarker(value) {
@@ -41675,7 +41850,7 @@ function isHostedMetadataPackage(pkg) {
41675
41850
  return HOSTED_RUNTIMES.has(normalizeMarker(skills.runtime)) || HOSTED_SOURCES.has(normalizeMarker(skills.source));
41676
41851
  }
41677
41852
  function isHostedMetadataSkillDir(skillDir) {
41678
- const pkgPath = join20(skillDir, "package.json");
41853
+ const pkgPath = join21(skillDir, "package.json");
41679
41854
  if (!existsSync4(pkgPath))
41680
41855
  return false;
41681
41856
  try {
@@ -41775,7 +41950,7 @@ function validateRuntimeEntry(skillPath, entrypoint, issues, warnings) {
41775
41950
  const parts = entrypoint.split("/");
41776
41951
  let current = skillPath;
41777
41952
  for (let index = 0;index < parts.length; index++) {
41778
- current = join21(current, parts[index]);
41953
+ current = join22(current, parts[index]);
41779
41954
  let info;
41780
41955
  try {
41781
41956
  info = lstatSync16(current);
@@ -41891,7 +42066,7 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
41891
42066
  add(issues, "skill.name_invalid", `Skill name '${bareName}' must use lowercase letters, numbers, dots, underscores, or hyphens`);
41892
42067
  }
41893
42068
  for (const entry of readdirSync6(skillPath).sort()) {
41894
- const entryPath = join21(skillPath, entry);
42069
+ const entryPath = join22(skillPath, entry);
41895
42070
  if (RESERVED_SKILL_ENTRIES.has(entry)) {
41896
42071
  add(issues, "skill.reserved_file", `Reserved file '${entry}' is not allowed in skill packages`);
41897
42072
  }
@@ -41903,13 +42078,13 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
41903
42078
  }
41904
42079
  }
41905
42080
  for (const docFile of DOC_FILES) {
41906
- if (existsSync5(join21(skillPath, docFile)))
42081
+ if (existsSync5(join22(skillPath, docFile)))
41907
42082
  metadata.docFiles.push(docFile);
41908
42083
  }
41909
42084
  if (metadata.docFiles.length === 0) {
41910
42085
  add(issues, "skill.docs_missing", "Missing documentation file: expected SKILL.md, README.md, or CLAUDE.md");
41911
42086
  }
41912
- const skillMdPath = join21(skillPath, "SKILL.md");
42087
+ const skillMdPath = join22(skillPath, "SKILL.md");
41913
42088
  if (existsSync5(skillMdPath)) {
41914
42089
  const frontmatter = parseSkillFrontmatter(readFileSync14(skillMdPath, "utf-8"));
41915
42090
  if (!frontmatter) {
@@ -41953,7 +42128,7 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
41953
42128
  }
41954
42129
  metadata.kind = resolvedKind;
41955
42130
  const isInstruction = resolvedKind === "instruction";
41956
- const pkgPath = join21(skillPath, "package.json");
42131
+ const pkgPath = join22(skillPath, "package.json");
41957
42132
  if (!existsSync5(pkgPath)) {
41958
42133
  if (!isInstruction)
41959
42134
  add(issues, "package.missing", "Missing package.json");
@@ -42012,7 +42187,7 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
42012
42187
  add(issues, "package.bin_target_unsafe", `package.json bin '${command}' target '${target}' must stay inside the skill directory`);
42013
42188
  continue;
42014
42189
  }
42015
- const targetPath = join21(skillPath, target);
42190
+ const targetPath = join22(skillPath, target);
42016
42191
  if (!existsSync5(targetPath)) {
42017
42192
  add(warnings, "package.bin_target_missing", `package.json bin '${command}' target '${target}' is not present before build`);
42018
42193
  } else if (statSync6(targetPath).isDirectory()) {
@@ -42030,9 +42205,9 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
42030
42205
  metadata.runtime = "none";
42031
42206
  } else {
42032
42207
  metadata.runtime = hostedMetadata ? "hosted" : "local";
42033
- const srcDir = join21(skillPath, "src");
42208
+ const srcDir = join22(skillPath, "src");
42034
42209
  let declaredEntrypoint;
42035
- const manifestPath = join21(skillPath, "skill.json");
42210
+ const manifestPath = join22(skillPath, "skill.json");
42036
42211
  if (!hostedMetadata && existsSync5(manifestPath)) {
42037
42212
  try {
42038
42213
  const manifest = asRecord(readJsonFile(manifestPath));
@@ -42049,10 +42224,10 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
42049
42224
  validateRuntimeEntry(skillPath, declaredEntrypoint, issues, warnings);
42050
42225
  } else if (!existsSync5(srcDir)) {
42051
42226
  add(issues, "skill.src_missing", "Missing src/ directory");
42052
- } else if (!existsSync5(join21(srcDir, "index.ts")) && !existsSync5(join21(srcDir, "index.js"))) {
42227
+ } else if (!existsSync5(join22(srcDir, "index.ts")) && !existsSync5(join22(srcDir, "index.js"))) {
42053
42228
  add(issues, "skill.src_index_missing", "Missing src/index.ts or src/index.js");
42054
42229
  } else {
42055
- const indexPath = existsSync5(join21(srcDir, "index.ts")) ? join21(srcDir, "index.ts") : join21(srcDir, "index.js");
42230
+ const indexPath = existsSync5(join22(srcDir, "index.ts")) ? join22(srcDir, "index.ts") : join22(srcDir, "index.js");
42056
42231
  const size = statSync6(indexPath).size;
42057
42232
  if (size < 50)
42058
42233
  add(warnings, "skill.src_index_minimal", `Source entry point is very small (${size}B)`);
@@ -42077,7 +42252,7 @@ function validateRegistryConsistency(registry, skillsDir) {
42077
42252
  return false;
42078
42253
  })));
42079
42254
  const skillDirs = existsSync5(skillsDir) ? readdirSync6(skillsDir).filter((entry) => {
42080
- const fullPath = join21(skillsDir, entry);
42255
+ const fullPath = join22(skillsDir, entry);
42081
42256
  return !entry.startsWith(".") && entry !== "_common" && statSync6(fullPath).isDirectory();
42082
42257
  }) : [];
42083
42258
  const directoryNames2 = new Set(skillDirs);
@@ -42116,7 +42291,7 @@ function describeEntries(entries) {
42116
42291
 
42117
42292
  // src/lib/plugin-admission.ts
42118
42293
  function pluginAdmissionRoot() {
42119
- return join22(homedir2(), ".hasna", "skills", "plugin-admission");
42294
+ return join23(homedir2(), ".hasna", "skills", "plugin-admission");
42120
42295
  }
42121
42296
  function validatePluginTarget(value) {
42122
42297
  pluginKeys(value, ["schemaVersion", "pluginId", "registrations", "native", "resolver"]);
@@ -42292,12 +42467,12 @@ function root(options) {
42292
42467
  }
42293
42468
  function pluginBindingPath(storeRoot, id2) {
42294
42469
  pluginNeed(/^[a-f0-9]{64}$/.test(id2), "Invalid plugin binding identifier");
42295
- return join22(storeRoot, "bindings", `${id2}.json`);
42470
+ return join23(storeRoot, "bindings", `${id2}.json`);
42296
42471
  }
42297
42472
  function pluginReceiptPath(storeRoot, id2, digest2) {
42298
42473
  pluginNeed(/^[a-f0-9]{64}$/.test(id2), "Invalid plugin binding identifier");
42299
42474
  pluginDigest(digest2);
42300
- return join22(storeRoot, "receipts", id2, `${digest2.slice(7)}.json`);
42475
+ return join23(storeRoot, "receipts", id2, `${digest2.slice(7)}.json`);
42301
42476
  }
42302
42477
  function readPluginBinding(storeRoot, id2) {
42303
42478
  const value = readPluginJson(pluginBindingPath(storeRoot, id2));
@@ -42317,7 +42492,7 @@ function readPluginAdmissionReceipt(storeRoot, id2, digest2) {
42317
42492
  pluginNeed(receipt.plan.bindingId === id2 && receipt.plan.planDigest === digest2, "Plugin receipt identity differs from its filename");
42318
42493
  const binding = readPluginBinding(storeRoot, id2);
42319
42494
  pluginNeed(canonicalJson(binding) === canonicalJson(receipt.plan.binding) && receipt.plan.sourceCommand === pluginResolverCommand(binding), "Plugin receipt binding changed");
42320
- pluginNeed(receipt.materializedPath === join22(storeRoot, "objects", id2, digest2.slice(7)), "Plugin receipt points outside its immutable materialization");
42495
+ pluginNeed(receipt.materializedPath === join23(storeRoot, "objects", id2, digest2.slice(7)), "Plugin receipt points outside its immutable materialization");
42321
42496
  pluginText(receipt.admittedAt, 64);
42322
42497
  pluginNeed(Number.isFinite(Date.parse(receipt.admittedAt)), "Invalid plugin admission time");
42323
42498
  return receipt;
@@ -42458,7 +42633,7 @@ async function admitPlugin(spec, profileId, target, approvedDigest, approvedEvid
42458
42633
  const { plan, projection } = await candidate(spec, profileId, target, options);
42459
42634
  pluginNeed(plan.planDigest === approvedDigest, "The plugin plan changed since review; obtain and review a new plan");
42460
42635
  pluginNeed(plan.evidenceDigest === approvedEvidenceDigest, "The plugin routing evidence changed since review; obtain and review a new plan");
42461
- const store = root(options), materializedPath = join22(store, "objects", plan.bindingId, plan.planDigest.slice(7));
42636
+ const store = root(options), materializedPath = join23(store, "objects", plan.bindingId, plan.planDigest.slice(7));
42462
42637
  materializePluginTree(materializedPath, projection.files);
42463
42638
  writePluginJsonImmutable(pluginBindingPath(store, plan.bindingId), plan.binding);
42464
42639
  const path = pluginReceiptPath(store, plan.bindingId, plan.planDigest), existing = readPluginJson(path);
@@ -42550,7 +42725,7 @@ function hashManagedPluginRegistry(path, managed) {
42550
42725
  seen.add(target.pluginId);
42551
42726
  const rows = plugins[target.pluginId];
42552
42727
  pluginNeed(Array.isArray(rows) && rows.length === target.registrations.length, "Managed plugin registration membership changed");
42553
- const [name, market] = target.pluginId.split("@"), cacheRoot = join23(dirname13(path), "cache", market, name);
42728
+ const [name, market] = target.pluginId.split("@"), cacheRoot = join24(dirname13(path), "cache", market, name);
42554
42729
  const scopes = new Set, approvals = new Map, currentFiles = new Map;
42555
42730
  plugins[target.pluginId] = rows.map((row) => {
42556
42731
  pluginNeed(pluginObject(row), "Invalid managed plugin registration");
@@ -42563,7 +42738,7 @@ function hashManagedPluginRegistry(path, managed) {
42563
42738
  pluginText(row.sourceProducerPath);
42564
42739
  pluginText(row.lastUpdated, 64);
42565
42740
  pluginNeed(Number.isFinite(Date.parse(row.lastUpdated)), "Invalid managed plugin update timestamp");
42566
- pluginNeed(/^(?:[A-Za-z0-9][A-Za-z0-9._+-]*-)?[a-f0-9]{12}$/.test(row.version) && row.installPath === join23(cacheRoot, row.version), "Managed plugin cache path or version is outside its registration");
42741
+ 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");
42567
42742
  const approval = (producer) => {
42568
42743
  pluginText(producer);
42569
42744
  const digest2 = `sha256:${basename6(producer)}`;
@@ -42606,11 +42781,11 @@ function hashManagedPluginRegistry(path, managed) {
42606
42781
  directory.closeSync();
42607
42782
  }
42608
42783
  for (const version of names.sort()) {
42609
- const files = pluginFileWitnesses(snapshotPluginTree(join23(cacheRoot, version), { nativeRuntime: `claude-${target.native.version}` }));
42784
+ const files = pluginFileWitnesses(snapshotPluginTree(join24(cacheRoot, version), { nativeRuntime: `claude-${target.native.version}` }));
42610
42785
  verifiedBytes += files.reduce((total, file) => total + file.size, 0);
42611
42786
  pluginNeed(verifiedBytes <= 256 * 1024 * 1024, "Managed plugin verification exceeds its aggregate byte budget");
42612
42787
  const serialized = JSON.stringify(files);
42613
- const expected = currentFiles.get(join23(cacheRoot, version));
42788
+ const expected = currentFiles.get(join24(cacheRoot, version));
42614
42789
  pluginNeed(expected === undefined || serialized === expected, "Current native cache differs from its exact registered producer receipt");
42615
42790
  pluginNeed([...approvals.values()].some((receipt) => nativeVersionMatches(version, receipt) && JSON.stringify(receipt.plan.files) === serialized), "A retained native plugin cache version differs from every approved projection");
42616
42791
  }
@@ -42628,7 +42803,7 @@ function captureManagedPluginRegistry(path, managedPlugins) {
42628
42803
  }
42629
42804
 
42630
42805
  // src/lib/claude-marketplace-registry.ts
42631
- import { createHash as createHash18 } from "crypto";
42806
+ import { createHash as createHash19 } from "crypto";
42632
42807
  import { closeSync as closeSync15, constants as constants12, fstatSync as fstatSync15, lstatSync as lstatSync18, openSync as openSync15, readSync as readSync10 } from "fs";
42633
42808
  import { basename as basename7, dirname as dirname14, isAbsolute as isAbsolute17, resolve as resolve15 } from "path";
42634
42809
  var CLAUDE_MARKETPLACE_REGISTRY_LIMITS = Object.freeze({ bytes: 1024 * 1024, rows: 1024, depth: 32, nodes: 65536, stringCharacters: 16384, pathCharacters: 4096 });
@@ -42685,7 +42860,7 @@ function readRegistry2(path, budget2) {
42685
42860
  closeSync15(fd);
42686
42861
  }
42687
42862
  }
42688
- function parse6(text2) {
42863
+ function parse7(text2) {
42689
42864
  let at = 0, nodes = 0;
42690
42865
  const numberPattern = /-?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?/y;
42691
42866
  const space = () => {
@@ -42794,26 +42969,26 @@ function normalizeRow(row, version = 1) {
42794
42969
  row.entries = row.entries.map(([key, value]) => [key, key === "lastUpdated" ? { kind: "validated-update-time" } : value]);
42795
42970
  }
42796
42971
  function captureClaudeMarketplaceRegistry(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
42797
- const value = parse6(readRegistry2(path, budget2));
42972
+ const value = parse7(readRegistry2(path, budget2));
42798
42973
  for (const [, row] of value.entries)
42799
42974
  normalizeRow(row);
42800
- const sha2562 = createHash18("sha256").update("hasna.skills.claude-marketplace-registry.v1\x00").update(JSON.stringify(value)).digest("hex");
42975
+ const sha2562 = createHash19("sha256").update("hasna.skills.claude-marketplace-registry.v1\x00").update(JSON.stringify(value)).digest("hex");
42801
42976
  return { path, hashMode: "claude-marketplace-registry", sha256: sha2562 };
42802
42977
  }
42803
42978
  function captureClaudeMarketplaceRegistryV2(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
42804
- const value = parse6(readRegistry2(path, budget2));
42979
+ const value = parse7(readRegistry2(path, budget2));
42805
42980
  for (const [, row] of value.entries)
42806
42981
  normalizeRow(row, 2);
42807
- const sha2562 = createHash18("sha256").update("hasna.skills.claude-marketplace-registry.v2\x00").update(JSON.stringify(value)).digest("hex");
42982
+ const sha2562 = createHash19("sha256").update("hasna.skills.claude-marketplace-registry.v2\x00").update(JSON.stringify(value)).digest("hex");
42808
42983
  return { path, hashMode: "claude-marketplace-registry-v2", sha256: sha2562 };
42809
42984
  }
42810
42985
 
42811
42986
  // src/lib/codex-hook-discovery-recovery.ts
42812
- import { createHash as createHash20 } from "crypto";
42987
+ import { createHash as createHash21 } from "crypto";
42813
42988
 
42814
42989
  // src/lib/codex-hook-trust-files.ts
42815
42990
  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";
42816
- import { createHash as createHash19 } from "crypto";
42991
+ import { createHash as createHash20 } from "crypto";
42817
42992
  import { dirname as dirname15 } from "path";
42818
42993
  function need6(value, code) {
42819
42994
  if (!value)
@@ -42849,7 +43024,7 @@ function snapshot(file, privateFile = false, options = {}) {
42849
43024
  }
42850
43025
  need6(length === Number(before.size) && sameStat(before, fstatSync16(fd, { bigint: true })) && sameStat(before, lstatSync19(file, { bigint: true })), "INPUT_CHANGED");
42851
43026
  const content = bytes.subarray(0, length), text2 = new TextDecoder("utf-8", { fatal: true }).decode(content);
42852
- return { file, privateFile, readOnlyPackage, text: text2, bytes: content, stat: before, sha256: createHash19("sha256").update(content).digest("hex") };
43027
+ return { file, privateFile, readOnlyPackage, text: text2, bytes: content, stat: before, sha256: createHash20("sha256").update(content).digest("hex") };
42853
43028
  } finally {
42854
43029
  closeSync16(fd);
42855
43030
  }
@@ -42865,7 +43040,7 @@ var matchedEvents = { ...events, PreToolUse: ["preToolUse", "pre_tool_use"] };
42865
43040
  var proofs = new WeakMap;
42866
43041
 
42867
43042
  // src/lib/codex-hook-discovery-recovery.ts
42868
- var sha3 = (text2) => createHash20("sha256").update(text2).digest("hex");
43043
+ var sha3 = (text2) => createHash21("sha256").update(text2).digest("hex");
42869
43044
  var fields = [...CODEX_DISCOVERY_PROJECTION_FIELDS];
42870
43045
  var proofs2 = new WeakMap;
42871
43046
  function assertCodexHookDiscoveryRecovery(binding, witness) {
@@ -42885,36 +43060,36 @@ function verifiesCodexHookDiscoverySource(binding, source, currentDigest, witnes
42885
43060
 
42886
43061
  // src/lib/agent-sumi.ts
42887
43062
  import { existsSync as existsSync6, lstatSync as lstatSync20, realpathSync as realpathSync8 } from "fs";
42888
- import { join as join24, resolve as resolve16 } from "path";
43063
+ import { join as join25, resolve as resolve16 } from "path";
42889
43064
  function sumiConfigDirectory(home, env = process.env) {
42890
43065
  for (const key of ["SUMI_CONFIG", "SUMI_CONFIG_CONTENT"])
42891
43066
  if (env[key] !== undefined)
42892
43067
  throw new Error(`Sumi ${key} requires a dedicated discovery adapter; unset it before Skills integration`);
42893
43068
  const selected = (key) => env[key]?.trim() ? env[key] : undefined;
42894
- const expand = (value) => resolve16(value === "~" ? home : value.startsWith("~/") ? join24(home, value.slice(2)) : value);
43069
+ const expand = (value) => resolve16(value === "~" ? home : value.startsWith("~/") ? join25(home, value.slice(2)) : value);
42895
43070
  const explicit = selected("SUMI_CONFIG_DIR");
42896
43071
  const xdg = selected("XDG_CONFIG_HOME");
42897
43072
  const custom = selected("SUMI_HOME");
42898
- const canonical6 = explicit ? expand(explicit) : xdg ? join24(expand(xdg), "sumi") : join24(custom ? expand(custom) : join24(home, ".hasna-internal/sumi"), "config");
43073
+ const canonical7 = explicit ? expand(explicit) : xdg ? join25(expand(xdg), "sumi") : join25(custom ? expand(custom) : join25(home, ".hasna-internal/sumi"), "config");
42899
43074
  if (explicit || xdg || custom)
42900
- return canonical6;
42901
- const legacy = join24(home, ".config/sumi");
42902
- const a = lstatSync20(canonical6, { throwIfNoEntry: false }), b = lstatSync20(legacy, { throwIfNoEntry: false });
42903
- if (a && b && realpathSync8(canonical6) !== realpathSync8(legacy))
43075
+ return canonical7;
43076
+ const legacy = join25(home, ".config/sumi");
43077
+ const a = lstatSync20(canonical7, { throwIfNoEntry: false }), b = lstatSync20(legacy, { throwIfNoEntry: false });
43078
+ if (a && b && realpathSync8(canonical7) !== realpathSync8(legacy))
42904
43079
  throw new Error("Sumi config roots conflict; complete native home adoption before Skills integration");
42905
- const path = a ? canonical6 : b ? legacy : canonical6;
43080
+ const path = a ? canonical7 : b ? legacy : canonical7;
42906
43081
  if (!existsSync6(path))
42907
43082
  return path;
42908
43083
  const physical = realpathSync8(path);
42909
- if ((a?.isSymbolicLink() || b?.isSymbolicLink()) && ![canonical6, legacy].includes(physical))
43084
+ if ((a?.isSymbolicLink() || b?.isSymbolicLink()) && ![canonical7, legacy].includes(physical))
42910
43085
  throw new Error("Sumi config alias must resolve to its canonical or legacy root");
42911
43086
  return physical;
42912
43087
  }
42913
43088
  function sumiBridgeRoot(home) {
42914
- return join24(sumiConfigDirectory(home), "skills");
43089
+ return join25(sumiConfigDirectory(home), "skills");
42915
43090
  }
42916
43091
  function sumiConfigPath(home) {
42917
- return join24(sumiConfigDirectory(home), "sumi.json");
43092
+ return join25(sumiConfigDirectory(home), "sumi.json");
42918
43093
  }
42919
43094
  function renderSumiPlugin(command, profile) {
42920
43095
  return renderSumiPluginVersion(command, profile, false);
@@ -43006,7 +43181,7 @@ var SUMI_SKILL_PERMISSIONS = [
43006
43181
  ];
43007
43182
 
43008
43183
  // src/lib/agent-discovery.ts
43009
- var digest2 = (text2) => createHash21("sha256").update(text2).digest("hex");
43184
+ var digest2 = (text2) => createHash22("sha256").update(text2).digest("hex");
43010
43185
  function parseConfig(text2, path, toml = false) {
43011
43186
  try {
43012
43187
  const value = toml ? Bun.TOML.parse(text2) : JSON.parse(text2);
@@ -43092,6 +43267,12 @@ function projected(source, changes, budget2 = discoveryByteBudget()) {
43092
43267
  throw new Error("Managed plugin registry witnesses require verified native registrations");
43093
43268
  return hashManagedPluginRegistry(source.path, source.managedPlugins);
43094
43269
  }
43270
+ if (source.hashMode === "claude-plugin-manifest-v1") {
43271
+ if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || changes?.has(source.path))
43272
+ throw new Error("Claude plugin manifest witnesses require a native discovery source without synthetic changes");
43273
+ const text3 = read2(source.path);
43274
+ return text3 === null ? null : hashClaudePluginManifest(text3);
43275
+ }
43095
43276
  if (source.managedPlugins !== undefined)
43096
43277
  throw new Error("Managed plugin rules require a typed registry witness");
43097
43278
  if (source.hashMode !== undefined) {
@@ -43118,7 +43299,7 @@ function absentCodexSkillRoots(binding) {
43118
43299
  throw new Error("Invalid disabled Codex discovery proof");
43119
43300
  if (binding.method !== "reviewed" || controls.every((control) => lstatSync21(control.pluginParent, { throwIfNoEntry: false })))
43120
43301
  return [];
43121
- const cache = dirname16(dirname16(controls[0].pluginParent)), config = join25(dirname16(dirname16(cache)), "config.toml");
43302
+ const cache = dirname16(dirname16(controls[0].pluginParent)), config = join26(dirname16(dirname16(cache)), "config.toml");
43122
43303
  const source = binding.sources.find((source2) => source2.path === config && source2.sha256 !== null && source2.format === undefined && source2.fields === undefined);
43123
43304
  if (!source || projected(source) !== source.sha256)
43124
43305
  throw new Error("Missing current disabled Codex configuration witness");
@@ -43126,8 +43307,8 @@ function absentCodexSkillRoots(binding) {
43126
43307
  return [...new Set(controls.map((control) => control.pluginParent))].filter((parent) => !codexDirectHookSelects(cache, parent) && absentDisabledCodexPluginParent(cache, parent, controls, rules));
43127
43308
  }
43128
43309
  function codexDirectHookSelects(cache, root2) {
43129
- const codex = dirname16(dirname16(cache)), config = Bun.TOML.parse(read2(join25(codex, "config.toml")) ?? "");
43130
- const hooks = read2(join25(codex, "hooks.json"));
43310
+ const codex = dirname16(dirname16(cache)), config = Bun.TOML.parse(read2(join26(codex, "config.toml")) ?? "");
43311
+ const hooks = read2(join26(codex, "hooks.json"));
43131
43312
  if (hooks !== null)
43132
43313
  hashNativeJsonControls(hooks);
43133
43314
  return JSON.stringify(config.hooks ?? {}).includes(root2) || hooks !== null && JSON.stringify(JSON.parse(hooks)).includes(root2);
@@ -43139,7 +43320,7 @@ function retiredCodexRoots(binding) {
43139
43320
  const controls = binding.codexDisabledPluginSkills;
43140
43321
  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)
43141
43322
  throw new Error("Invalid retired Codex materialization proof");
43142
- const cache = dirname16(dirname16(controls[0].pluginParent)), config = join25(dirname16(dirname16(cache)), "config.toml");
43323
+ const cache = dirname16(dirname16(controls[0].pluginParent)), config = join26(dirname16(dirname16(cache)), "config.toml");
43143
43324
  const source = binding.sources.find((source2) => source2.path === config && source2.sha256 !== null && source2.format === undefined && source2.fields === undefined);
43144
43325
  if (!source || projected(source) !== source.sha256)
43145
43326
  throw new Error("Missing current retired Codex configuration witness");
@@ -43147,7 +43328,7 @@ function retiredCodexRoots(binding) {
43147
43328
  if ((proof.parents ?? []).some((parent) => codexDirectHookSelects(cache, parent) || !reviewedDisabledCodexPluginParent(cache, parent, controls, rules)) || !reviewedCodexPluginCapabilitiesUnchanged(cache, controls, (path) => read2(path), rules))
43148
43329
  throw new Error("Retired Codex parent capabilities changed");
43149
43330
  for (const root2 of proof.roots) {
43150
- const manifest = binding.sources.find((source2) => source2.path === join25(root2, ".codex-plugin/plugin.json") && source2.sha256 !== null && source2.format === undefined && source2.fields === undefined && [undefined, "bytes"].includes(source2.hashMode));
43331
+ const manifest = binding.sources.find((source2) => source2.path === join26(root2, ".codex-plugin/plugin.json") && source2.sha256 !== null && source2.format === undefined && source2.fields === undefined && [undefined, "bytes"].includes(source2.hashMode));
43151
43332
  if (!manifest || codexDirectHookSelects(cache, root2) || !reviewedRetiredCodexRoot(cache, root2, controls, rules, (path) => read2(path), true))
43152
43333
  throw new Error("Retired Codex materialization changed");
43153
43334
  }
@@ -43157,14 +43338,14 @@ function captureRetiredCodexDiscovery(binding, controls, rules) {
43157
43338
  if (binding.agent !== "codex" || binding.method !== "reviewed" || !controls.length)
43158
43339
  return binding;
43159
43340
  const cache = dirname16(dirname16(controls[0].pluginParent));
43160
- const candidates = binding.sources.filter((source) => source.path.endsWith(sep5 + ".codex-plugin/plugin.json") && source.sha256 !== null && source.format === undefined && source.fields === undefined && [undefined, "bytes"].includes(source.hashMode)).map((source) => dirname16(dirname16(source.path)));
43341
+ 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)));
43161
43342
  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();
43162
43343
  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() : [];
43163
43344
  const { codexRetiredMaterializations: previous, ...current } = binding;
43164
43345
  if (!roots.length && !parents3.length)
43165
43346
  return current;
43166
43347
  const installation = codexInstallationRoots(binding);
43167
- const directories = (binding.directories ?? []).filter((directory) => !installation.some((root2) => directory.path === root2 || directory.path.startsWith(root2 + sep5) || root2.startsWith(directory.path + sep5)));
43348
+ const directories = (binding.directories ?? []).filter((directory) => !installation.some((root2) => directory.path === root2 || directory.path.startsWith(root2 + sep6) || root2.startsWith(directory.path + sep6)));
43168
43349
  if (previous && isDeepStrictEqual6(previous.roots, roots) && isDeepStrictEqual6(previous.parents, parents3) && isDeepStrictEqual6(previous.directories.map((item) => item.path), directories.map((item) => item.path)))
43169
43350
  return { ...current, codexRetiredMaterializations: previous };
43170
43351
  return { ...current, codexRetiredMaterializations: { roots, parents: parents3, directories: captureDiscoveryDirectoryProjection(directories.map((item) => item.path), roots) } };
@@ -43176,17 +43357,17 @@ function absentRetiredClaudeRoots(binding) {
43176
43357
  for (const source of binding.sources) {
43177
43358
  if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || ![undefined, "bytes"].includes(source.hashMode) || source.sha256 === null)
43178
43359
  continue;
43179
- const marker = sep5 + ".claude" + sep5 + "plugins" + sep5 + "cache" + sep5, at = source.path.indexOf(marker);
43360
+ const marker = sep6 + ".claude" + sep6 + "plugins" + sep6 + "cache" + sep6, at = source.path.indexOf(marker);
43180
43361
  if (at < 0 || source.path.indexOf(marker, at + 1) >= 0)
43181
43362
  continue;
43182
- const cache = source.path.slice(0, at + marker.length - 1), parts = source.path.slice(at + marker.length).split(sep5);
43363
+ const cache = source.path.slice(0, at + marker.length - 1), parts = source.path.slice(at + marker.length).split(sep6);
43183
43364
  if (parts.length < 4 || parts.slice(0, 3).some((part) => !part || part === "." || part === ".."))
43184
43365
  continue;
43185
- const root2 = join25(cache, ...parts.slice(0, 3));
43366
+ const root2 = join26(cache, ...parts.slice(0, 3));
43186
43367
  safe4(root2);
43187
43368
  if (lstatSync21(root2, { throwIfNoEntry: false }))
43188
43369
  continue;
43189
- const claude = dirname16(dirname16(cache)), settings = join25(claude, "settings.json"), registry = join25(claude, "plugins/installed_plugins.json");
43370
+ const claude = dirname16(dirname16(cache)), settings = join26(claude, "settings.json"), registry = join26(claude, "plugins/installed_plugins.json");
43190
43371
  const full = (path) => binding.sources.find((item) => item.path === path && item.sha256 !== null && item.format === undefined && item.fields === undefined);
43191
43372
  const configSource = full(settings), registrySource = full(registry);
43192
43373
  if (!configSource || !registrySource || projected(configSource) !== configSource.sha256 || projected(registrySource) !== registrySource.sha256)
@@ -43205,10 +43386,10 @@ function absentRetiredClaudeRoots(binding) {
43205
43386
  const active = rows[0].installPath;
43206
43387
  if (rows[0].version !== basename8(active) || resolve17(active) !== active || dirname16(active) !== dirname16(root2) || active === root2 || !lstatSync21(active, { throwIfNoEntry: false })?.isDirectory() || realpathSync9(active) !== active)
43207
43388
  continue;
43208
- const activeManifest = full(join25(active, ".claude-plugin/plugin.json"));
43389
+ const activeManifest = full(join26(active, ".claude-plugin/plugin.json"));
43209
43390
  if (!activeManifest || projected(activeManifest) !== activeManifest.sha256)
43210
43391
  continue;
43211
- if (Object.values(installed.plugins).some((value) => !Array.isArray(value) || value.some((row) => !row || typeof row.installPath !== "string" || row.installPath === root2 || row.installPath.startsWith(root2 + sep5) || root2.startsWith(row.installPath + sep5))))
43392
+ if (Object.values(installed.plugins).some((value) => !Array.isArray(value) || value.some((row) => !row || typeof row.installPath !== "string" || row.installPath === root2 || row.installPath.startsWith(root2 + sep6) || root2.startsWith(row.installPath + sep6))))
43212
43393
  continue;
43213
43394
  result.add(root2);
43214
43395
  }
@@ -43223,10 +43404,10 @@ function verifyAgentDiscovery(binding, codexRecovery) {
43223
43404
  throw new Error("Hermes discovery requires directory membership coverage; run skills hook install with a fresh discovery review");
43224
43405
  const installationRoots = codexInstallationRoots(binding);
43225
43406
  const retiredRoots = retiredCodexRoots(binding);
43226
- const installationInput = (path) => installationRoots.some((root2) => path === root2 || path.startsWith(root2 + sep5));
43407
+ const installationInput = (path) => installationRoots.some((root2) => path === root2 || path.startsWith(root2 + sep6));
43227
43408
  if (binding.directories !== undefined) {
43228
43409
  const projected2 = binding.codexInstallationInputs?.directories ?? [];
43229
- const ancestors2 = binding.directories.filter((directory) => installationRoots.some((root2) => root2.startsWith(directory.path + sep5)));
43410
+ const ancestors2 = binding.directories.filter((directory) => installationRoots.some((root2) => root2.startsWith(directory.path + sep6)));
43230
43411
  if (projected2.length !== ancestors2.length || projected2.some((directory) => !ancestors2.some((original) => original.path === directory.path)))
43231
43412
  throw new Error("Missing installation input directory projection");
43232
43413
  const ordinary = binding.directories.filter((directory) => !installationInput(directory.path) && !ancestors2.includes(directory));
@@ -43262,7 +43443,7 @@ function verifyAgentDiscovery(binding, codexRecovery) {
43262
43443
  safe4(source.path);
43263
43444
  continue;
43264
43445
  }
43265
- if (absentRoots.some((root2) => source.path.startsWith(root2 + sep5)) && source.format === undefined && source.fields === undefined && source.managedPlugins === undefined && [undefined, "bytes"].includes(source.hashMode)) {
43446
+ if (absentRoots.some((root2) => source.path.startsWith(root2 + sep6)) && source.format === undefined && source.fields === undefined && source.managedPlugins === undefined && [undefined, "bytes"].includes(source.hashMode)) {
43266
43447
  safe4(source.path);
43267
43448
  continue;
43268
43449
  }
@@ -43285,12 +43466,12 @@ function codexInstallationRoots(binding) {
43285
43466
  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)
43286
43467
  throw new Error("Invalid native installation input proof");
43287
43468
  const cache = dirname16(dirname16(proof.plugins[0].pluginParent));
43288
- const config = join25(dirname16(dirname16(cache)), "config.toml"), home = dirname16(dirname16(dirname16(cache)));
43469
+ const config = join26(dirname16(dirname16(cache)), "config.toml"), home = dirname16(dirname16(dirname16(cache)));
43289
43470
  const configSource = binding.sources.find((source) => source.path === config && source.sha256 !== null && (!source.format || source.format === "toml" && source.fields?.includes("plugins")));
43290
- const nativeRoots = NATIVE_SKILL_ROOTS.filter(([agent]) => agent === "codex").map(([, path]) => join25(home, path));
43291
- if (!configSource || proof.plugins.some((input) => nativeRoots.some((root2) => root2 === input.sourceRoot || root2.startsWith(input.sourceRoot + sep5) || input.sourceRoot.startsWith(root2 + sep5)) || binding.sources.some((source) => basename8(source.path) === "config.toml" && (source.path === input.sourceRoot || source.path.startsWith(input.sourceRoot + sep5)))))
43471
+ const nativeRoots = NATIVE_SKILL_ROOTS.filter(([agent]) => agent === "codex").map(([, path]) => join26(home, path));
43472
+ 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)))))
43292
43473
  throw new Error("Native installation input overlaps configuration or loading roots");
43293
- if (proof.plugins.some((input) => dirname16(dirname16(input.pluginParent)) !== cache || !binding.sources.some((source) => source.path === join25(input.sourceRoot, ".codex-plugin/plugin.json") && source.sha256 !== null && source.format === undefined && source.fields === undefined)))
43474
+ 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)))
43294
43475
  throw new Error("Missing native installation input source witness");
43295
43476
  return reviewedCodexPluginSourceRoots(cache, proof.plugins, (path) => {
43296
43477
  const text2 = read2(path);
@@ -43300,6 +43481,8 @@ function codexInstallationRoots(binding) {
43300
43481
  });
43301
43482
  }
43302
43483
  function assertMarketplaceBinding(binding, source) {
43484
+ if (source.hashMode === "claude-plugin-manifest-v1" && (binding.agent !== "claude" || basename8(source.path) !== "plugin.json" || !source.path.endsWith(join26(sep6, ".claude-plugin", "plugin.json"))))
43485
+ throw new Error("Claude plugin manifest witnesses require Claude plugin discovery");
43303
43486
  if (source.hashMode === "sumi-settings-v1" && (binding.agent !== "sumi" || binding.method !== "reviewed" || basename8(source.path) !== "sumi.json"))
43304
43487
  throw new Error("Sumi settings witnesses require explicit reviewed Sumi configuration");
43305
43488
  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"))
@@ -43314,7 +43497,7 @@ function rebindAgentDiscovery(binding, changes) {
43314
43497
  const installationRoots = codexInstallationRoots(binding), absentRoots = [...absentCodexSkillRoots(binding), ...absentRetiredClaudeRoots(binding), ...retiredCodexRoots(binding).filter((root2) => !lstatSync21(root2, { throwIfNoEntry: false }))];
43315
43498
  const rebound = { ...binding, sources: binding.sources.map((source) => {
43316
43499
  assertMarketplaceBinding(binding, source);
43317
- if (!changes.has(source.path) && (installationRoots.some((root2) => source.path.startsWith(root2 + sep5)) || absentRoots.some((root2) => source.path.startsWith(root2 + sep5)) && source.format === undefined && source.fields === undefined && source.managedPlugins === undefined && [undefined, "bytes"].includes(source.hashMode)))
43500
+ if (!changes.has(source.path) && (installationRoots.some((root2) => source.path.startsWith(root2 + sep6)) || absentRoots.some((root2) => source.path.startsWith(root2 + sep6)) && source.format === undefined && source.fields === undefined && source.managedPlugins === undefined && [undefined, "bytes"].includes(source.hashMode)))
43318
43501
  return source;
43319
43502
  const sha2562 = projected(source, changes, budget2);
43320
43503
  if (!changes.has(source.path) && sha2562 !== source.sha256)
@@ -43340,8 +43523,8 @@ function captureDiscoveryPathSources(paths) {
43340
43523
  const budget2 = discoveryByteBudget();
43341
43524
  return paths.map((path) => ({ path, hashMode: "path-bytes", sha256: hashDiscoveryPathFile(path, budget2) }));
43342
43525
  }
43343
- function assertProjectDiscovery(agent, directories, home, canonical6 = resolve17, reviewed) {
43344
- const homeConfigPath = canonical6(agentDiscoveryConfigPath(home, agent));
43526
+ function assertProjectDiscovery(agent, directories, home, canonical7 = resolve17, reviewed) {
43527
+ const homeConfigPath = canonical7(agentDiscoveryConfigPath(home, agent));
43345
43528
  for (const directory of directories) {
43346
43529
  const isHome = resolve17(directory) === resolve17(home);
43347
43530
  if (agent === "hermes") {
@@ -43352,7 +43535,7 @@ function assertProjectDiscovery(agent, directories, home, canonical6 = resolve17
43352
43535
  continue;
43353
43536
  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"];
43354
43537
  for (const suffix of paths) {
43355
- const path = canonical6(join25(directory, suffix)), raw = read2(path);
43538
+ const path = canonical7(join26(directory, suffix)), raw = read2(path);
43356
43539
  if (raw === null)
43357
43540
  continue;
43358
43541
  const isRootAliasedHomeConfig = agent === "claude" && suffix === ".claude/settings.json" || agent === "codex" && suffix === ".codex/config.toml";
@@ -43368,7 +43551,7 @@ function assertProjectDiscovery(agent, directories, home, canonical6 = resolve17
43368
43551
  const managed = reviewed.sources.flatMap((source) => source.hashMode === "claude-plugin-registry" ? source.managedPlugins ?? [] : []);
43369
43552
  if (exact && projected(exact) === exact.sha256 && managed.length) {
43370
43553
  const bindings = managed.map((item) => readPluginBinding(item.storeRoot, item.bindingId));
43371
- 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 === canonical6(directory))));
43554
+ 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))));
43372
43555
  }
43373
43556
  }
43374
43557
  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)))
@@ -43376,13 +43559,13 @@ function assertProjectDiscovery(agent, directories, home, canonical6 = resolve17
43376
43559
  }
43377
43560
  if (agent === "sumi")
43378
43561
  for (const name of ["plugin", "plugins"]) {
43379
- const path = canonical6(join25(directory, ".sumi", name));
43562
+ const path = canonical7(join26(directory, ".sumi", name));
43380
43563
  safe4(path);
43381
43564
  if (lstatSync21(path, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(path).length)
43382
43565
  throw new Error(`NATIVE_SKILL_DRIFT: project Sumi plugins require a dedicated discovery review: ${path}`);
43383
43566
  }
43384
43567
  if (agent === "claude") {
43385
- const commands = canonical6(join25(directory, ".claude/commands"));
43568
+ const commands = canonical7(join26(directory, ".claude/commands"));
43386
43569
  safe4(commands);
43387
43570
  if (lstatSync21(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length)
43388
43571
  throw new Error("NATIVE_SKILL_DRIFT: legacy project command discovery requires a dedicated format adapter");
@@ -43392,13 +43575,13 @@ function assertProjectDiscovery(agent, directories, home, canonical6 = resolve17
43392
43575
  function agentDiscoveryConfigPath(home, agent) {
43393
43576
  if (agent === "sumi")
43394
43577
  return sumiConfigPath(home);
43395
- return join25(home, agent === "hermes" ? ".hermes/config.yaml" : agent === "opencode" ? ".config/opencode/opencode.json" : `.${agent}/${agent === "codex" ? "config.toml" : agent === "cursor" ? "hooks.json" : "settings.json"}`);
43578
+ 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"}`);
43396
43579
  }
43397
43580
  function resolveAgentDiscovery(options) {
43398
- const canonical6 = options.canonical ?? resolve17, home = resolve17(options.home), agent = options.agent;
43581
+ const canonical7 = options.canonical ?? resolve17, home = resolve17(options.home), agent = options.agent;
43399
43582
  const sources = [], roots = new Set, builtinNames = [];
43400
- const witness = (path, format, fields2) => {
43401
- const source = { path: canonical6(path), sha256: null, ...format ? { format, fields: fields2 } : {} };
43583
+ const witness = (path, format, fields2, hashMode) => {
43584
+ const source = { path: canonical7(path), sha256: null, ...format ? { format, fields: fields2 } : {}, ...hashMode ? { hashMode } : {} };
43402
43585
  source.sha256 = projected(source);
43403
43586
  sources.push(source);
43404
43587
  return read2(source.path);
@@ -43411,31 +43594,34 @@ function resolveAgentDiscovery(options) {
43411
43594
  const unresolved = (detail) => {
43412
43595
  throw new Error(`Native discovery is unresolved (${agent}: ${detail}); provide a reviewed --discovery-inputs file`);
43413
43596
  };
43597
+ if (options.reviewed && (options.reviewed.version !== 1 || !Array.isArray(options.reviewed.agents) || options.reviewed.agents.some((item) => !item || typeof item !== "object") || new Set(options.reviewed.agents.map((item) => item.agent)).size !== options.reviewed.agents.length))
43598
+ throw new Error("Invalid --discovery-inputs version or agents");
43599
+ const review = options.reviewed?.agents.find((item) => item.agent === agent);
43414
43600
  if (agent === "sumi") {
43415
43601
  const directory = sumiConfigDirectory(home);
43416
- if (witness(join25(directory, "sumi.jsonc")) !== null)
43602
+ if (witness(join26(directory, "sumi.jsonc")) !== null)
43417
43603
  unresolved("JSONC configuration requires a supported format adapter");
43418
- for (const root2 of [directory, join25(home, ".claude"), join25(home, ".agents")])
43604
+ for (const root2 of [directory, join26(home, ".claude"), join26(home, ".agents")])
43419
43605
  for (const name of ["skill", "skills"])
43420
- roots.add(canonical6(join25(root2, name)));
43606
+ roots.add(canonical7(join26(root2, name)));
43421
43607
  if (config.skills !== undefined && (!Array.isArray(config.skills) || config.skills.some((path) => typeof path !== "string")))
43422
43608
  unresolved("skills must be a string array");
43423
43609
  for (const value of config.skills ?? []) {
43424
43610
  if (typeof value !== "string" || /[\0$]/.test(value) || !value || !(isAbsolute18(value) || value.startsWith("~/")))
43425
43611
  unresolved("remote or relative skill sources need a dedicated discovery adapter");
43426
- roots.add(canonical6(value.startsWith("~/") ? join25(home, value.slice(2)) : value));
43612
+ roots.add(canonical7(value.startsWith("~/") ? join26(home, value.slice(2)) : value));
43427
43613
  }
43428
43614
  for (const key of ["plugin", "plugins"])
43429
43615
  if (config[key] !== undefined && !Array.isArray(config[key]))
43430
43616
  unresolved(`${key} must be an array`);
43431
- const plugins = [join25(directory, "plugin"), join25(directory, "plugins")];
43617
+ const plugins = [join26(directory, "plugin"), join26(directory, "plugins")];
43432
43618
  for (const path of plugins) {
43433
43619
  safe4(path);
43434
43620
  if (lstatSync21(path, { throwIfNoEntry: false })?.isDirectory())
43435
43621
  for (const name of readdirSync7(path).sort()) {
43436
43622
  if (name === "skills-cli.js" && path === plugins[1])
43437
43623
  continue;
43438
- const target = join25(path, name);
43624
+ const target = join26(path, name);
43439
43625
  if (!lstatSync21(target).isFile())
43440
43626
  unresolved("local plugin packages need a dedicated discovery adapter");
43441
43627
  witness(target);
@@ -43448,7 +43634,7 @@ function resolveAgentDiscovery(options) {
43448
43634
  }
43449
43635
  }
43450
43636
  if (agent === "hermes") {
43451
- const profile = witness(join25(home, ".hermes/active_profile"));
43637
+ const profile = witness(join26(home, ".hermes/active_profile"));
43452
43638
  if (profile?.trim() && profile.trim() !== "default")
43453
43639
  unresolved("a non-default profile is active");
43454
43640
  const declared = config.skills?.external_dirs ?? [], paths = typeof declared === "string" ? [declared] : declared;
@@ -43462,7 +43648,7 @@ function resolveAgentDiscovery(options) {
43462
43648
  continue;
43463
43649
  if (normalized.startsWith("~") && normalized !== "~" && !normalized.startsWith("~/"))
43464
43650
  unresolved("user-specific tilde expansion requires a separate discovery adapter");
43465
- const path = normalized === "~" ? home : normalized.startsWith("~/") ? join25(home, normalized.slice(2)) : resolve17(home, ".hermes", normalized);
43651
+ const path = normalized === "~" ? home : normalized.startsWith("~/") ? join26(home, normalized.slice(2)) : resolve17(home, ".hermes", normalized);
43466
43652
  safe4(path);
43467
43653
  roots.add(path);
43468
43654
  }
@@ -43472,7 +43658,7 @@ function resolveAgentDiscovery(options) {
43472
43658
  if (executable2) {
43473
43659
  let packageRoot;
43474
43660
  for (let directory = dirname16(realpathSync9(executable2)), depth = 0;depth < 8; directory = dirname16(directory), depth++) {
43475
- const path = join25(directory, "package.json"), raw = read2(path);
43661
+ const path = join26(directory, "package.json"), raw = read2(path);
43476
43662
  if (raw !== null && parseConfig(raw, path).name === "@google/gemini-cli") {
43477
43663
  packageRoot = directory;
43478
43664
  witness(path);
@@ -43483,12 +43669,12 @@ function resolveAgentDiscovery(options) {
43483
43669
  }
43484
43670
  if (!packageRoot)
43485
43671
  unresolved("installed Gemini package layout is not recognized");
43486
- const builtinRoot = join25(packageRoot, "bundle/builtin");
43672
+ const builtinRoot = join26(packageRoot, "bundle/builtin");
43487
43673
  safe4(builtinRoot);
43488
43674
  if (!lstatSync21(builtinRoot, { throwIfNoEntry: false })?.isDirectory())
43489
43675
  unresolved("installed Gemini builtin root is missing");
43490
43676
  for (const name of readdirSync7(builtinRoot).sort()) {
43491
- const text2 = witness(join25(builtinRoot, name, "SKILL.md"));
43677
+ const text2 = witness(join26(builtinRoot, name, "SKILL.md"));
43492
43678
  const match = text2?.match(/^---\r?\n[\s\S]*?^name:\s*([a-z0-9][a-z0-9-]*)\s*$/m);
43493
43679
  if (!match?.[1] || builtinNames.includes(match[1]))
43494
43680
  unresolved("installed Gemini builtin name is missing or ambiguous");
@@ -43501,18 +43687,15 @@ function resolveAgentDiscovery(options) {
43501
43687
  if (retained.agent !== agent || retained.method !== "reviewed")
43502
43688
  unresolved("invalid retained review");
43503
43689
  verifyAgentDiscovery(retained);
43504
- if (!retained.sources.some((source) => source.path === canonical6(configPath) && source.format === undefined && source.fields === undefined))
43690
+ if (!retained.sources.some((source) => source.path === canonical7(configPath) && source.format === undefined && source.fields === undefined))
43505
43691
  unresolved("retained review is missing the full agent configuration source");
43506
- 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 === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")))) && source.path !== canonical6(configPath)))
43692
+ 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 === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")))) && source.path !== canonical7(configPath)))
43507
43693
  unresolved("retained settings witness names another configuration source");
43508
- const covered = supersedesSettingsProjection(agent, retained.sources, canonical6(configPath)) ? sources.filter((source) => !isSupersededSettingsProjection(agent, canonical6(configPath), source)) : sources;
43694
+ const covered = supersedesSettingsProjection(agent, retained.sources, canonical7(configPath)) ? sources.filter((source) => !isSupersededSettingsProjection(agent, canonical7(configPath), source)) : sources;
43509
43695
  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))
43510
43696
  unresolved("retained review is missing current runtime discovery coverage");
43511
43697
  return retained;
43512
43698
  }
43513
- if (options.reviewed && (options.reviewed.version !== 1 || !Array.isArray(options.reviewed.agents) || options.reviewed.agents.some((item) => !item || typeof item !== "object") || new Set(options.reviewed.agents.map((item) => item.agent)).size !== options.reviewed.agents.length))
43514
- throw new Error("Invalid --discovery-inputs version or agents");
43515
- const review = options.reviewed?.agents.find((item) => item.agent === agent);
43516
43699
  if (review) {
43517
43700
  if (review.pluginHooks !== "reviewed-no-skill-injection" || !Array.isArray(review.sources) || !review.sources.length || !Array.isArray(review.roots))
43518
43701
  throw new Error("Discovery review must bind sources and confirm plugin hooks do not inject retired skills");
@@ -43520,47 +43703,77 @@ function resolveAgentDiscovery(options) {
43520
43703
  if (review.sources.some((source) => source.format !== undefined || source.fields !== undefined))
43521
43704
  throw new Error("Explicit discovery reviews require full source-file hashes");
43522
43705
  verifyAgentDiscovery(supplied);
43523
- 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 === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")))) && source.path !== canonical6(configPath)))
43706
+ 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 === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")))) && source.path !== canonical7(configPath)))
43524
43707
  throw new Error("Semantic settings witnesses must name the configured agent configuration source");
43525
- if (!review.sources.some((source) => source.path === canonical6(configPath)))
43708
+ if (!review.sources.some((source) => source.path === canonical7(configPath)))
43526
43709
  throw new Error("Discovery review must include the agent configuration source");
43527
- const reviewedSources = supersedesSettingsProjection(agent, review.sources, canonical6(configPath)) ? sources.filter((source) => !isSupersededSettingsProjection(agent, canonical6(configPath), source)) : sources;
43528
- return { ...supplied, roots: [...new Set([...roots, ...supplied.roots])].sort(), sources: [...reviewedSources, ...review.sources], ...agent === "gemini" ? { builtinNames } : {} };
43710
+ const reviewedSources = supersedesSettingsProjection(agent, review.sources, canonical7(configPath)) ? sources.filter((source) => !isSupersededSettingsProjection(agent, canonical7(configPath), source)) : sources;
43711
+ const reviewedSourcesWithManifestProjection = review.sources.map((source) => {
43712
+ 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")))
43713
+ return source;
43714
+ const pluginRoot = dirname16(dirname16(source.path)), hooksPath = join26(pluginRoot, "hooks/hooks.json");
43715
+ const hookStat = lstatSync21(hooksPath, { throwIfNoEntry: false });
43716
+ const text2 = read2(source.path);
43717
+ if (text2 === null)
43718
+ throw new Error("Reviewed Claude plugin manifest is missing");
43719
+ const manifestSha256 = projectReviewedClaudePluginManifest(text2, source.sha256 ?? "");
43720
+ const manifest = JSON.parse(text2);
43721
+ if (!manifest || typeof manifest !== "object" || Array.isArray(manifest))
43722
+ throw new Error("Reviewed Claude plugin manifest must be an object");
43723
+ const reviewedHookPaths = new Set;
43724
+ if (hookStat)
43725
+ reviewedHookPaths.add(hooksPath);
43726
+ if (manifest.hooks !== undefined) {
43727
+ if (typeof manifest.hooks !== "string")
43728
+ throw new Error("Reviewed Claude plugin manifest has an unsupported hooks target");
43729
+ const declaredHookPath = resolve17(pluginRoot, manifest.hooks);
43730
+ if (!declaredHookPath.startsWith(pluginRoot + sep6))
43731
+ throw new Error("Reviewed Claude plugin hooks target escapes its root");
43732
+ reviewedHookPaths.add(declaredHookPath);
43733
+ }
43734
+ for (const hooksFile of reviewedHookPaths)
43735
+ 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")))
43736
+ throw new Error("Reviewed Claude plugin manifest requires separately reviewed exact hook file sources");
43737
+ return { path: source.path, sha256: manifestSha256, hashMode: "claude-plugin-manifest-v1" };
43738
+ });
43739
+ const combined = [...reviewedSources, ...reviewedSourcesWithManifestProjection];
43740
+ const unique = combined.filter((source, index) => combined.findIndex((candidate2) => isDeepStrictEqual6(candidate2, source)) === index);
43741
+ return { ...supplied, roots: [...new Set([...roots, ...supplied.roots])].sort(), sources: unique, ...agent === "gemini" ? { builtinNames } : {} };
43529
43742
  }
43530
43743
  function plugin(root2) {
43531
- root2 = canonical6(root2);
43744
+ root2 = canonical7(root2);
43532
43745
  safe4(root2);
43533
- const manifestPath = join25(root2, agent === "claude" ? ".claude-plugin/plugin.json" : ".codex-plugin/plugin.json");
43534
- const raw = witness(manifestPath);
43746
+ const manifestPath = join26(root2, agent === "claude" ? ".claude-plugin/plugin.json" : ".codex-plugin/plugin.json");
43747
+ const raw = witness(manifestPath, undefined, undefined, agent === "claude" ? "claude-plugin-manifest-v1" : undefined);
43535
43748
  if (raw === null)
43536
43749
  unresolved("plugin manifest missing");
43537
43750
  const manifest = parseConfig(raw, manifestPath);
43538
- const hooks = witness(join25(root2, "hooks/hooks.json"));
43751
+ const hooks = witness(join26(root2, "hooks/hooks.json"));
43539
43752
  if (manifest.hooks !== undefined || hooks !== null)
43540
43753
  unresolved("plugin hooks require a separate no-skill-injection review");
43541
- const commands = join25(root2, "commands");
43754
+ const commands = join26(root2, "commands");
43542
43755
  safe4(commands);
43543
43756
  if (agent === "claude" && (manifest.commands !== undefined || lstatSync21(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length))
43544
43757
  unresolved("legacy command discovery requires retirement or a dedicated format adapter");
43545
- const rootSkill = witness(join25(root2, "SKILL.md"));
43758
+ const rootSkill = witness(join26(root2, "SKILL.md"));
43546
43759
  if (rootSkill !== null)
43547
43760
  roots.add(root2);
43548
43761
  const declared = manifest.skills === undefined ? ["./skills"] : typeof manifest.skills === "string" ? [manifest.skills] : manifest.skills;
43549
43762
  if (!Array.isArray(declared) || declared.some((path) => typeof path !== "string"))
43550
43763
  unresolved("unsupported plugin skill paths");
43551
43764
  if (agent === "claude")
43552
- roots.add(join25(root2, "skills"));
43765
+ roots.add(join26(root2, "skills"));
43553
43766
  for (const value of declared) {
43554
43767
  const path = resolve17(root2, value);
43555
- if (path !== root2 && !path.startsWith(root2 + sep5))
43768
+ if (path !== root2 && !path.startsWith(root2 + sep6))
43556
43769
  unresolved("plugin skill path escapes its root");
43557
- roots.add(path.endsWith(`${sep5}SKILL.md`) ? dirname16(path) : path);
43770
+ roots.add(path.endsWith(`${sep6}SKILL.md`) ? dirname16(path) : path);
43558
43771
  }
43559
43772
  }
43560
43773
  if (agent === "claude") {
43561
- const registrations = witness(join25(home, ".claude/plugins/installed_plugins.json"));
43562
- const installed = registrations === null ? {} : parseConfig(registrations, join25(home, ".claude/plugins/installed_plugins.json")).plugins;
43563
- const commands = canonical6(join25(home, ".claude/commands"));
43774
+ const registrations = witness(join26(home, ".claude/plugins/installed_plugins.json"));
43775
+ const installed = registrations === null ? {} : parseConfig(registrations, join26(home, ".claude/plugins/installed_plugins.json")).plugins;
43776
+ const commands = canonical7(join26(home, ".claude/commands"));
43564
43777
  safe4(commands);
43565
43778
  if (lstatSync21(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length)
43566
43779
  unresolved("legacy home command discovery requires a dedicated format adapter");
@@ -43584,16 +43797,16 @@ function resolveAgentDiscovery(options) {
43584
43797
  const market = config.marketplaces?.[marketplace] ?? (marketplace === "personal" ? { source_type: "local", source: home } : undefined);
43585
43798
  if (split < 1 || market?.source_type !== "local" || typeof market.source !== "string" || !isAbsolute18(market.source))
43586
43799
  unresolved("enabled plugin marketplace is not an explicit local source");
43587
- const catalogText = witness(join25(market.source, ".agents/plugins/marketplace.json"));
43800
+ const catalogText = witness(join26(market.source, ".agents/plugins/marketplace.json"));
43588
43801
  if (catalogText === null)
43589
43802
  unresolved("marketplace catalog missing");
43590
- const catalog = parseConfig(catalogText, join25(market.source, ".agents/plugins/marketplace.json")), matches = Array.isArray(catalog.plugins) ? catalog.plugins.filter((item) => item.name === name) : [];
43803
+ const catalog = parseConfig(catalogText, join26(market.source, ".agents/plugins/marketplace.json")), matches = Array.isArray(catalog.plugins) ? catalog.plugins.filter((item) => item.name === name) : [];
43591
43804
  if (matches.length !== 1 || matches[0]?.source?.source !== "local" || typeof matches[0]?.source?.path !== "string")
43592
43805
  unresolved("plugin catalog source is missing or ambiguous");
43593
43806
  plugin(resolve17(market.source, matches[0].source.path));
43594
43807
  }
43595
43808
  } else if (agent === "opencode") {
43596
- if (witness(join25(home, ".config/opencode/opencode.jsonc")) !== null || witness(join25(home, ".config/opencode/config.json")) !== null)
43809
+ if (witness(join26(home, ".config/opencode/opencode.jsonc")) !== null || witness(join26(home, ".config/opencode/config.json")) !== null)
43597
43810
  unresolved("additional config layers require review");
43598
43811
  if ((config.plugin?.length ?? 0) > 0 || config.skills?.urls?.length)
43599
43812
  unresolved("external plugin or remote skill source");
@@ -43602,15 +43815,15 @@ function resolveAgentDiscovery(options) {
43602
43815
  unresolved("relative or malformed added skill root");
43603
43816
  roots.add(path);
43604
43817
  }
43605
- const localPlugins = join25(home, ".config/opencode/plugins");
43818
+ const localPlugins = join26(home, ".config/opencode/plugins");
43606
43819
  safe4(localPlugins);
43607
43820
  if (lstatSync21(localPlugins, { throwIfNoEntry: false }) && readdirSync7(localPlugins).some((name) => name !== "skills-cli.js"))
43608
43821
  unresolved("additional local plugin hooks require review");
43609
43822
  } else if (agent === "sumi") {
43610
- if ((config.plugin?.length ?? 0) > 0 || (config.plugins?.length ?? 0) > 0 || sources.some((source) => source.path !== canonical6(configPath) && source.path !== canonical6(join25(sumiConfigDirectory(home), "sumi.jsonc")) && source.sha256 !== null))
43823
+ 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))
43611
43824
  unresolved("external or foreign local plugins require review");
43612
43825
  } else if (agent === "hermes") {
43613
- for (const directory of [join25(home, ".hermes/plugins"), join25(home, ".hermes/hermes-agent")]) {
43826
+ for (const directory of [join26(home, ".hermes/plugins"), join26(home, ".hermes/hermes-agent")]) {
43614
43827
  safe4(directory);
43615
43828
  if (lstatSync21(directory, { throwIfNoEntry: false }))
43616
43829
  unresolved("installed runtime/plugin discovery requires reviewed source bindings");
@@ -43620,24 +43833,24 @@ function resolveAgentDiscovery(options) {
43620
43833
  } else if (agent === "gemini") {
43621
43834
  if (Object.keys(config.extensions ?? {}).length || config.skills?.paths?.length)
43622
43835
  unresolved("custom extension or skill paths");
43623
- const directory = join25(home, ".gemini/extensions");
43836
+ const directory = join26(home, ".gemini/extensions");
43624
43837
  safe4(directory);
43625
43838
  if (lstatSync21(directory, { throwIfNoEntry: false }))
43626
43839
  for (const name of readdirSync7(directory)) {
43627
- const root2 = join25(directory, name);
43840
+ const root2 = join26(directory, name);
43628
43841
  safe4(root2);
43629
43842
  if (!lstatSync21(root2)?.isDirectory())
43630
43843
  continue;
43631
- const raw = witness(join25(root2, "gemini-extension.json"));
43844
+ const raw = witness(join26(root2, "gemini-extension.json"));
43632
43845
  if (raw === null)
43633
43846
  unresolved("extension registration missing");
43634
- const manifest = parseConfig(raw, join25(root2, "gemini-extension.json"));
43635
- if (manifest.hooks !== undefined || witness(join25(root2, "hooks/hooks.json")) !== null || witness(join25(root2, ".gemini-extension-install.json")) !== null)
43847
+ const manifest = parseConfig(raw, join26(root2, "gemini-extension.json"));
43848
+ if (manifest.hooks !== undefined || witness(join26(root2, "hooks/hooks.json")) !== null || witness(join26(root2, ".gemini-extension-install.json")) !== null)
43636
43849
  unresolved("extension hooks or linked registration require review");
43637
- roots.add(join25(root2, "skills"));
43850
+ roots.add(join26(root2, "skills"));
43638
43851
  }
43639
43852
  }
43640
- return { agent, roots: [...roots].sort(), sources, method: "automatic", ...agent === "gemini" ? { builtinNames } : {}, ...agent === "hermes" ? { directories: captureDiscoveryDirectories([join25(home, ".hermes/plugins"), join25(home, ".hermes/hermes-agent")].map((path) => canonical6(path))) } : {} };
43853
+ 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))) } : {} };
43641
43854
  }
43642
43855
 
43643
43856
  // src/lib/agent-adapters.ts
@@ -43976,7 +44189,7 @@ function disableCodexBundledSkills(text2) {
43976
44189
  }
43977
44190
 
43978
44191
  // src/lib/agent-integration.ts
43979
- var sha4 = (data) => createHash22("sha256").update(data).digest("hex");
44192
+ var sha4 = (data) => createHash23("sha256").update(data).digest("hex");
43980
44193
  var ROOTS = NATIVE_SKILL_ROOTS;
43981
44194
  function hasTrustedDarwinAcl(fd, allowDenyOnly = false) {
43982
44195
  try {
@@ -44054,7 +44267,7 @@ function isSystemRootAlias(path) {
44054
44267
  }
44055
44268
  }
44056
44269
  function canonicalSystemPath(path) {
44057
- const absolute = resolve18(path), root2 = `/${absolute.split(sep6)[1]}`;
44270
+ const absolute = resolve18(path), root2 = `/${absolute.split(sep7)[1]}`;
44058
44271
  if (process.platform !== "darwin" || !["/var", "/tmp", "/etc"].includes(root2) || !lstatSync22(root2, { throwIfNoEntry: false })?.isSymbolicLink())
44059
44272
  return absolute;
44060
44273
  if (!isSystemRootAlias(root2))
@@ -44074,7 +44287,7 @@ function assertSafePath(path) {
44074
44287
  }
44075
44288
  function readRootAlias(home, agent) {
44076
44289
  assertSafePath(home);
44077
- const realHome = realpathSync10(home), alias = join26(realHome, `.${agent}`);
44290
+ const realHome = realpathSync10(home), alias = join27(realHome, `.${agent}`);
44078
44291
  const stat2 = lstatSync22(alias, { throwIfNoEntry: false, bigint: true });
44079
44292
  if (!stat2?.isSymbolicLink())
44080
44293
  throw new Error(`Agent root alias changed after planning: ${alias}`);
@@ -44084,7 +44297,7 @@ function readRootAlias(home, agent) {
44084
44297
  if (!targetStat?.isDirectory())
44085
44298
  throw new Error(`Agent root alias must target an existing directory: ${alias}`);
44086
44299
  const target = realpathSync10(targetPath), inside = relative5(realHome, target);
44087
- if (!inside || inside === ".." || inside.startsWith(`..${sep6}`) || isAbsolute19(inside))
44300
+ if (!inside || inside === ".." || inside.startsWith(`..${sep7}`) || isAbsolute19(inside))
44088
44301
  throw new Error(`Agent root alias target must be inside the real home: ${alias}`);
44089
44302
  return { agent, home: realHome, alias, target, link, aliasIdentity: `${stat2.dev}:${stat2.ino}:${stat2.ctimeNs}`, targetIdentity: `${targetStat.dev}:${targetStat.ino}` };
44090
44303
  }
@@ -44093,15 +44306,15 @@ function rootAliases(home, allowed = false) {
44093
44306
  return [];
44094
44307
  const result = [];
44095
44308
  for (const agent of ["claude", "codex"])
44096
- if (lstatSync22(join26(home, `.${agent}`), { throwIfNoEntry: false })?.isSymbolicLink())
44309
+ if (lstatSync22(join27(home, `.${agent}`), { throwIfNoEntry: false })?.isSymbolicLink())
44097
44310
  result.push(readRootAlias(home, agent));
44098
- if (result.some((item, index) => result.slice(index + 1).some((other) => item.target === other.target || item.target.startsWith(other.target + sep6) || other.target.startsWith(item.target + sep6))))
44311
+ if (result.some((item, index) => result.slice(index + 1).some((other) => item.target === other.target || item.target.startsWith(other.target + sep7) || other.target.startsWith(item.target + sep7))))
44099
44312
  throw new Error("Agent root alias targets must not overlap");
44100
44313
  return result;
44101
44314
  }
44102
44315
  function canonicalAgentPath(path, aliases) {
44103
- const absolute = canonicalSystemPath(path), binding = aliases.find((item) => absolute === item.alias || absolute.startsWith(item.alias + sep6));
44104
- return binding ? join26(binding.target, relative5(binding.alias, absolute)) : absolute;
44316
+ const absolute = canonicalSystemPath(path), binding = aliases.find((item) => absolute === item.alias || absolute.startsWith(item.alias + sep7));
44317
+ return binding ? join27(binding.target, relative5(binding.alias, absolute)) : absolute;
44105
44318
  }
44106
44319
  function disabledCodexSkillPaths(config, aliases) {
44107
44320
  const skills = config.skills;
@@ -44124,7 +44337,7 @@ function disabledCodexSkillPaths(config, aliases) {
44124
44337
  } catch {
44125
44338
  continue;
44126
44339
  }
44127
- if (!document2.endsWith(`${sep6}SKILL.md`))
44340
+ if (!document2.endsWith(`${sep7}SKILL.md`))
44128
44341
  continue;
44129
44342
  settings.set(document2, [...settings.get(document2) ?? [], entry.enabled === false]);
44130
44343
  }
@@ -44132,7 +44345,7 @@ function disabledCodexSkillPaths(config, aliases) {
44132
44345
  }
44133
44346
  function recheckRootAliases(aliases) {
44134
44347
  for (const binding of aliases) {
44135
- if (!["claude", "codex"].includes(binding.agent) || binding.alias !== join26(binding.home, `.${binding.agent}`))
44348
+ if (!["claude", "codex"].includes(binding.agent) || binding.alias !== join27(binding.home, `.${binding.agent}`))
44136
44349
  throw new Error("Invalid agent root alias binding");
44137
44350
  const current = readRootAlias(binding.home, binding.agent);
44138
44351
  if (JSON.stringify(current) !== JSON.stringify(binding))
@@ -44170,7 +44383,7 @@ function readNativeBytes(path, maximum = 64 * 1024 * 1024) {
44170
44383
  }
44171
44384
  }
44172
44385
  function treeHash(root2) {
44173
- const hash2 = createHash22("sha256");
44386
+ const hash2 = createHash23("sha256");
44174
44387
  let bytes = 0, files = 0;
44175
44388
  function visit2(path) {
44176
44389
  const stat2 = lstatSync22(path);
@@ -44180,7 +44393,7 @@ function treeHash(root2) {
44180
44393
  if (stat2.isDirectory()) {
44181
44394
  hash2.update(`d\x00${rel}\x00`);
44182
44395
  for (const name of readdirSync8(path).sort())
44183
- visit2(join26(path, name));
44396
+ visit2(join27(path, name));
44184
44397
  return;
44185
44398
  }
44186
44399
  if (!stat2.isFile())
@@ -44208,7 +44421,7 @@ function selectNativeMigrationTargets(inventory, manifest) {
44208
44421
  if (!existsSync7(projectRoot) || !lstatSync22(projectRoot).isDirectory())
44209
44422
  throw new Error(`Native migration target project root must be an existing absolute directory: ${target.projectRoot}`);
44210
44423
  assertSafePath(projectRoot);
44211
- if (isAbsolute19(target.path) || target.path.includes("\\") || target.path.includes("\x00") || !normalized || normalized === ".." || normalized.startsWith(`..${sep6}`) || normalized !== target.path || !/^[0-9a-f]{64}$/.test(target.treeSha256))
44424
+ if (isAbsolute19(target.path) || target.path.includes("\\") || target.path.includes("\x00") || !normalized || normalized === ".." || normalized.startsWith(`..${sep7}`) || normalized !== target.path || !/^[0-9a-f]{64}$/.test(target.treeSha256))
44212
44425
  throw new Error(`Invalid native migration target: ${target.path}`);
44213
44426
  const identity5 = `${target.agent}\x00${canonicalSystemPath(projectRoot)}\x00${normalized}`;
44214
44427
  if (identities.has(identity5))
@@ -44244,7 +44457,7 @@ function projectAncestorDirectories(projects) {
44244
44457
  }
44245
44458
  function isCodexSkillDiscoveryInput(path) {
44246
44459
  for (let cursor = canonicalSystemPath(path);cursor !== dirname17(cursor); cursor = dirname17(cursor)) {
44247
- if (ROOTS.some(([agent, root2]) => agent === "codex" && cursor.endsWith(join26(sep6, root2))))
44460
+ if (ROOTS.some(([agent, root2]) => agent === "codex" && cursor.endsWith(join27(sep7, root2))))
44248
44461
  return true;
44249
44462
  }
44250
44463
  return false;
@@ -44261,18 +44474,18 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
44261
44474
  const selectedAgents = options.agents ? new Set(options.agents) : undefined;
44262
44475
  const includesAgent = (agent) => !selectedAgents || selectedAgents.has(agent);
44263
44476
  const rootDefinitions = selectedAgents ? ROOTS.filter(([agent, path]) => selectedAgents.has(agent) || selectedAgents.has("hermes") && agent === "codex" && path === ".agents/skills") : ROOTS;
44264
- const roots = rootDefinitions.map(([agent, path]) => [agent, canonicalAgentPath(join26(home, path), aliases)]);
44265
- const bridgePaths = Object.entries(AGENT_ADAPTERS).filter(([agent]) => agent !== "sumi" || includesAgent("sumi")).map(([agent, adapter]) => canonicalAgentPath(join26(agent === "sumi" ? sumiBridgeRoot(home) : join26(home, adapter.root), CLI_BRIDGE_NAME), aliases));
44477
+ const roots = rootDefinitions.map(([agent, path]) => [agent, canonicalAgentPath(join27(home, path), aliases)]);
44478
+ const bridgePaths = Object.entries(AGENT_ADAPTERS).filter(([agent]) => agent !== "sumi" || includesAgent("sumi")).map(([agent, adapter]) => canonicalAgentPath(join27(agent === "sumi" ? sumiBridgeRoot(home) : join27(home, adapter.root), CLI_BRIDGE_NAME), aliases));
44266
44479
  for (const project of projectAncestorDirectories([...options.projectDirs ?? [], ...options.projectDir ? [options.projectDir] : []])) {
44267
44480
  for (const [agent, path] of rootDefinitions)
44268
- roots.push([agent, canonicalAgentPath(join26(project, path), aliases)]);
44481
+ roots.push([agent, canonicalAgentPath(join27(project, path), aliases)]);
44269
44482
  if (selectedAgents?.has("sumi"))
44270
44483
  for (const directory of [".claude", ".agents"])
44271
44484
  for (const name of ["skill", "skills"])
44272
- roots.push(["sumi", canonicalAgentPath(join26(project, directory, name), aliases)]);
44485
+ roots.push(["sumi", canonicalAgentPath(join27(project, directory, name), aliases)]);
44273
44486
  }
44274
44487
  const installationInputs = options.codexInstallationInputRoots ?? [];
44275
- if (installationInputs.some((input) => resolve18(input) !== input || realpathSync10(input) !== input || roots.some(([agent, path]) => agent === "codex" && (path === input || path.startsWith(input + sep6) || input.startsWith(path + sep6)))))
44488
+ if (installationInputs.some((input) => resolve18(input) !== input || realpathSync10(input) !== input || roots.some(([agent, path]) => agent === "codex" && (path === input || path.startsWith(input + sep7) || input.startsWith(path + sep7)))))
44276
44489
  throw new Error("Native installation input overlaps an unconditional skill-loading root");
44277
44490
  const entries = [], seen = new Set;
44278
44491
  const cacheScans = new Map, maxAliasProofEntries = 1e4;
@@ -44298,7 +44511,7 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
44298
44511
  if (!scan?.complete || scan.entries > maxAliasProofEntries)
44299
44512
  return false;
44300
44513
  if (scan.hasSkills) {
44301
- const targetSkills = entries.filter((entry) => entry.agent === agent && entry.vendor && (entry.path === target || entry.path.startsWith(target + sep6)));
44514
+ const targetSkills = entries.filter((entry) => entry.agent === agent && entry.vendor && (entry.path === target || entry.path.startsWith(target + sep7)));
44302
44515
  if (path === reviewedCacheAlias && targetSkills.length > 0)
44303
44516
  reviewedCacheAliasFound = true;
44304
44517
  if (agent === "codex" && targetSkills.length > 0 && targetSkills.every((entry) => disabledVendorPaths.has(entry.path) || options.disabledVendorSkill?.(entry) === true))
@@ -44313,7 +44526,7 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
44313
44526
  admit(path);
44314
44527
  const scan = { complete: true, hasSkills: false, entries: 1 };
44315
44528
  assertSafePath(path);
44316
- if (configuredRoot && agent === "codex" && installationInputs.some((root2) => path === root2 || path.startsWith(`${root2}${sep6}`)))
44529
+ if (configuredRoot && agent === "codex" && installationInputs.some((root2) => path === root2 || path.startsWith(`${root2}${sep7}`)))
44317
44530
  return scan;
44318
44531
  if (!existsSync7(path))
44319
44532
  return scan;
@@ -44325,21 +44538,21 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
44325
44538
  }
44326
44539
  if (!stat2.isDirectory())
44327
44540
  throw new Error(`Unsupported native discovery entry: ${path}`);
44328
- if (existsSync7(join26(path, "SKILL.md"))) {
44541
+ if (existsSync7(join27(path, "SKILL.md"))) {
44329
44542
  scan.hasSkills = true;
44330
44543
  if (seen.has(path))
44331
44544
  return scan;
44332
44545
  seen.add(path);
44333
44546
  let managed = false;
44334
- const marker = join26(path, ".hasna-skills.json");
44547
+ const marker = join27(path, ".hasna-skills.json");
44335
44548
  if (existsSync7(marker)) {
44336
44549
  try {
44337
44550
  managed = JSON.parse(readFileSync16(marker, "utf8")).managedBy === "@hasna/skills";
44338
44551
  } catch {}
44339
44552
  }
44340
44553
  const bridge = (!vendor || agent === "sumi") && isOwnedCliBridge(path, bridgePaths);
44341
- const rootAlias = aliases.find((item) => path === item.target || path.startsWith(item.target + sep6));
44342
- entries.push({ agent, path, hash: treeHash(path), managed, vendor, ...agent === "codex" || isCodexSkillDiscoveryInput(path) ? { codexHome: process.env.CODEX_HOME ?? join26(home, ".codex") } : {}, ...agent === "codex" && path.startsWith(canonicalAgentPath(join26(home, ".codex", "skills", ".system"), aliases) + sep6) ? { system: true } : {}, ...bridge ? { bridge: true, bridgeHome: resolve18(home) } : {}, ...rootAlias ? { rootAlias } : {} });
44554
+ const rootAlias = aliases.find((item) => path === item.target || path.startsWith(item.target + sep7));
44555
+ 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 } : {} });
44343
44556
  return scan;
44344
44557
  }
44345
44558
  if (depth > (agent === "sumi" ? 32 : vendor ? 32 : 3))
@@ -44348,7 +44561,7 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
44348
44561
  try {
44349
44562
  let child;
44350
44563
  while ((child = directory.readSync()) !== null) {
44351
- admit(join26(path, child.name));
44564
+ admit(join27(path, child.name));
44352
44565
  children.push(child);
44353
44566
  }
44354
44567
  } finally {
@@ -44360,12 +44573,12 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
44360
44573
  for (const { name } of children) {
44361
44574
  if (name === "node_modules")
44362
44575
  continue;
44363
- if (name.startsWith(".") && name !== ".system" && agent !== "hermes" && agent !== "sumi" && !(options.guardHermes && `${path}${sep6}`.includes(`${sep6}.agents${sep6}skills${sep6}`)))
44576
+ if (name.startsWith(".") && name !== ".system" && agent !== "hermes" && agent !== "sumi" && !(options.guardHermes && `${path}${sep7}`.includes(`${sep7}.agents${sep7}skills${sep7}`)))
44364
44577
  continue;
44365
44578
  const isVendor = vendor || name === ".system";
44366
44579
  if (isVendor && !options.includeVendor)
44367
44580
  continue;
44368
- const child = join26(path, name);
44581
+ const child = join27(path, name);
44369
44582
  if (isVendor && lstatSync22(child, { throwIfNoEntry: false })?.isSymbolicLink()) {
44370
44583
  const target = statSync7(child, { throwIfNoEntry: false });
44371
44584
  if (target?.isFile() || pluginCache && target?.isDirectory() && verifiedSiblingCacheAlias(agent, child, path)) {
@@ -44383,7 +44596,7 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
44383
44596
  return scan;
44384
44597
  }
44385
44598
  function scanRoot(agent, path, vendor = false, pluginCache = false, configuredRoot = false) {
44386
- if (agent === "hermes" || options.guardHermes && `${path}${sep6}`.includes(`${sep6}.agents${sep6}skills${sep6}`))
44599
+ if (agent === "hermes" || options.guardHermes && `${path}${sep7}`.includes(`${sep7}.agents${sep7}skills${sep7}`))
44387
44600
  assertNoHermesLegacyShadow(path);
44388
44601
  if (!visit2(agent, path, vendor, 0, pluginCache, false, configuredRoot).complete)
44389
44602
  throw new Error(`Native skill discovery limit exceeded; review this root before continuing: ${path}`);
@@ -44392,11 +44605,11 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
44392
44605
  scanRoot(agent, path);
44393
44606
  if (options.includeVendor) {
44394
44607
  for (const agent of ["codex", "claude"].filter(includesAgent))
44395
- scanRoot(agent, canonicalAgentPath(join26(home, `.${agent}`, "plugins", "cache"), aliases), true, true);
44608
+ scanRoot(agent, canonicalAgentPath(join27(home, `.${agent}`, "plugins", "cache"), aliases), true, true);
44396
44609
  if (includesAgent("claude"))
44397
- scanRoot("claude", canonicalAgentPath(join26(home, ".claude", "plugins", "synced"), aliases), true);
44610
+ scanRoot("claude", canonicalAgentPath(join27(home, ".claude", "plugins", "synced"), aliases), true);
44398
44611
  if (includesAgent("gemini"))
44399
- scanRoot("gemini", join26(home, ".gemini", "extensions"), true);
44612
+ scanRoot("gemini", join27(home, ".gemini", "extensions"), true);
44400
44613
  }
44401
44614
  const configured = options.configured ? INTEGRATION_AGENTS.filter(includesAgent).flatMap((agent) => resolveAgentDiscovery({ home, agent, reviewed: options.discoveryInputs, canonical: (path) => canonicalAgentPath(path, aliases) }).roots.map((path) => ({ agent, path }))) : [];
44402
44615
  for (const root2 of [...options.agentRoots ?? [], ...configured])
@@ -44509,14 +44722,14 @@ function configureHooks(config, agent, command, profileId, nativeReady) {
44509
44722
  function disableCodexSkills(text2, skills, aliases, bridgePath) {
44510
44723
  const bundled = disableCodexBundledSkills(text2);
44511
44724
  let result = normalizeCodexInlinePathConfig(bundled);
44512
- const bridgeSelector = (entry) => typeof entry.name === "string" && entry.name.trim() === CLI_BRIDGE_NAME || typeof entry.path === "string" && [resolve18(bridgePath), resolve18(join26(bridgePath, "SKILL.md"))].includes(canonicalAgentPath(entry.path, aliases));
44725
+ 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));
44513
44726
  const previousConfig = Bun.TOML.parse(bundled).skills?.config;
44514
44727
  if (previousConfig !== undefined && (!Array.isArray(previousConfig) || previousConfig.some((entry) => !entry || typeof entry !== "object" || entry.path !== undefined && entry.name !== undefined)))
44515
44728
  throw new Error("Codex skill controls require one path or name selector per [[skills.config]] entry; review ambiguous entries before running skills hook install");
44516
44729
  const bridgeNeedsRepair = previousConfig?.some((entry) => entry.enabled === false && bridgeSelector(entry));
44517
44730
  const selections = [...skills.filter((entry) => entry.agent === "codex" && !entry.bridge).map((skill) => ({ path: skill.path, enabled: false })), { path: bridgePath, enabled: true }];
44518
44731
  for (const skill of selections) {
44519
- const path = join26(skill.path, "SKILL.md");
44732
+ const path = join27(skill.path, "SKILL.md");
44520
44733
  let found = false;
44521
44734
  result = result.replace(CODEX_SKILL_CONFIG_SECTIONS, (section) => {
44522
44735
  const parsed = Bun.TOML.parse(section);
@@ -44543,7 +44756,7 @@ enabled = false
44543
44756
  }
44544
44757
  function assertCodexInstallationInputs(home, projectDirs, inputs) {
44545
44758
  const nativeRoots = [home, ...projectAncestorDirectories(projectDirs)].flatMap((directory) => ROOTS.filter(([agent]) => agent === "codex").map(([, path]) => resolve18(directory, path)));
44546
- if (inputs.some((input) => nativeRoots.some((root2) => root2 === input || root2.startsWith(input + sep6) || input.startsWith(root2 + sep6))))
44759
+ if (inputs.some((input) => nativeRoots.some((root2) => root2 === input || root2.startsWith(input + sep7) || input.startsWith(root2 + sep7))))
44547
44760
  throw new Error("Native installation input overlaps an unconditional skill-loading root");
44548
44761
  }
44549
44762
  function planAgentIntegration(options) {
@@ -44551,7 +44764,7 @@ function planAgentIntegration(options) {
44551
44764
  throw new Error("Explicit Codex skill denials require a fresh native catalog and discovery review");
44552
44765
  const home = options.home ?? homedir3(), dataDir2 = options.dataDir ?? getDataDirReadOnly();
44553
44766
  const aliases = rootAliases(home, options.allowRootAliases);
44554
- const policyPath = join26(dataDir2, "agent-policy.json");
44767
+ const policyPath = join27(dataDir2, "agent-policy.json");
44555
44768
  assertSafePath(policyPath);
44556
44769
  const priorSnapshot = readManagedSkillPolicySnapshot(dataDir2), previousPolicy = priorSnapshot?.text ?? null, policy = priorSnapshot?.value ?? {};
44557
44770
  if (policy.bridge !== undefined && (!policy.bridge || typeof policy.bridge !== "object" || Array.isArray(policy.bridge)))
@@ -44583,28 +44796,28 @@ function planAgentIntegration(options) {
44583
44796
  }
44584
44797
  return resolveAgentDiscovery({ home, agent, reviewed: options.discoveryInputs, retainedReview, canonical: (path) => canonicalAgentPath(path, aliases) });
44585
44798
  });
44586
- const codexConfigBefore = options.agents.includes("codex") ? readOptional(canonicalAgentPath(join26(home, ".codex", "config.toml"), aliases)) : null;
44799
+ const codexConfigBefore = options.agents.includes("codex") ? readOptional(canonicalAgentPath(join27(home, ".codex", "config.toml"), aliases)) : null;
44587
44800
  const codexConfig = Bun.TOML.parse(codexConfigBefore ?? "");
44588
44801
  const nativeSkills = inventoryNativeSkills(home, { includeVendor: true, guardHermes: options.agents.includes("hermes"), agents: options.agents, projectDir: options.projectDir, agentRoots: discoveries.flatMap((binding) => binding.roots.map((path) => ({ agent: binding.agent, path }))), allowRootAliases: options.allowRootAliases, reviewedCacheAlias: options.reviewedCacheAlias, disabledVendorPaths: disabledCodexSkillPaths(codexConfig, aliases) });
44589
- const codexPathConfig = options.agents.includes("codex") ? disableCodexSkills(codexConfigBefore ?? "", nativeSkills, aliases, canonicalAgentPath(join26(home, ".codex/skills", CLI_BRIDGE_NAME), aliases)) : undefined;
44802
+ const codexPathConfig = options.agents.includes("codex") ? disableCodexSkills(codexConfigBefore ?? "", nativeSkills, aliases, canonicalAgentPath(join27(home, ".codex/skills", CLI_BRIDGE_NAME), aliases)) : undefined;
44590
44803
  const plannedCodexRules = codexPathConfig === undefined ? undefined : Bun.TOML.parse(codexPathConfig).skills?.config ?? [];
44591
44804
  const observedNativeSources = [];
44592
- const codexPluginControls = options.codexNativeCatalog ? reviewCodexPluginControls(options.codexNativeCatalog, nativeSkills.filter((entry) => entry.agent === "codex" && entry.vendor).map((entry) => join26(entry.path, "SKILL.md")), canonicalAgentPath(join26(home, ".codex/plugins/cache"), aliases), resolve18(options.projectDir ?? home), (path) => {
44805
+ 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) => {
44593
44806
  const bytes = readNativeBytes(path, 1024 * 1024);
44594
44807
  observedNativeSources.push({ path, sha256: sha4(bytes) });
44595
44808
  return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
44596
44809
  }, codexConfig.skills?.config ?? [], codexConfig.plugins, plannedCodexRules, options.codexSkillDenials) : { skills: policy.bridge?.codexPluginSkills ?? [], inactivePlugins: policy.bridge?.codexInactivePlugins ?? [], sourceInputs: policy.bridge?.discovery?.codex?.codexInstallationInputs?.plugins ?? [] };
44597
- const cache = canonicalAgentPath(join26(home, ".codex/plugins/cache"), aliases);
44810
+ const cache = canonicalAgentPath(join27(home, ".codex/plugins/cache"), aliases);
44598
44811
  const retired = (policy.bridge?.codexPluginSkills ?? []).filter((control) => absentDisabledCodexPluginParent(cache, control.pluginParent, policy.bridge.codexPluginSkills, codexConfig.skills?.config ?? []));
44599
44812
  for (const denial of options.codexSkillDenials ?? []) {
44600
44813
  const control = codexPluginControls.skills.find((item) => item.name === denial.name);
44601
44814
  if (!control)
44602
44815
  throw new Error("Explicit Codex denial did not resolve a reviewed identity");
44603
- const root2 = join26(control.pluginParent, relative5(control.pluginParent, denial.path).split(sep6)[0]);
44816
+ const root2 = join27(control.pluginParent, relative5(control.pluginParent, denial.path).split(sep7)[0]);
44604
44817
  const review = options.discoveryInputs.agents.find((item) => item.agent === "codex");
44605
- for (const path of [join26(root2, ".app.json"), join26(root2, ".mcp.json"), join26(root2, "hooks")])
44818
+ for (const path of [join27(root2, ".app.json"), join27(root2, ".mcp.json"), join27(root2, "hooks")])
44606
44819
  observedNativeSources.push({ path, sha256: nativeSourceDigest(path) });
44607
- const files = [join26(root2, ".codex-plugin/plugin.json"), ...control.appSha256 ? [join26(root2, ".app.json")] : [], ...control.mcpSha256 ? [join26(root2, ".mcp.json")] : []];
44820
+ const files = [join27(root2, ".codex-plugin/plugin.json"), ...control.appSha256 ? [join27(root2, ".app.json")] : [], ...control.mcpSha256 ? [join27(root2, ".mcp.json")] : []];
44608
44821
  for (const path of files)
44609
44822
  if (!review?.sources.some((source) => source.path === path && source.format === undefined && source.fields === undefined && [undefined, "bytes"].includes(source.hashMode) && source.sha256 === sha4(readNativeBytes(path, 1024 * 1024))))
44610
44823
  throw new Error("Explicit Codex denial requires current full manifest and capability discovery witnesses");
@@ -44613,12 +44826,12 @@ function planAgentIntegration(options) {
44613
44826
  for (const discovery of discoveries)
44614
44827
  if (discovery.agent === "codex" && discovery.method === "reviewed")
44615
44828
  discovery.codexDisabledPluginSkills = codexPluginSkills;
44616
- if (options.agents.includes("codex") && !options.codexNativeCatalog && codexPluginSkills.length && !reviewedCodexPluginCapabilitiesUnchanged(canonicalAgentPath(join26(home, ".codex/plugins/cache"), aliases), codexPluginSkills, (path) => new TextDecoder("utf-8", { fatal: true }).decode(readNativeBytes(path, 1024 * 1024)), codexConfig.skills?.config ?? [])) {
44829
+ if (options.agents.includes("codex") && !options.codexNativeCatalog && codexPluginSkills.length && !reviewedCodexPluginCapabilitiesUnchanged(canonicalAgentPath(join27(home, ".codex/plugins/cache"), aliases), codexPluginSkills, (path) => new TextDecoder("utf-8", { fatal: true }).decode(readNativeBytes(path, 1024 * 1024)), codexConfig.skills?.config ?? [])) {
44617
44830
  throw new Error("NATIVE_SKILL_DRIFT: reviewed native plugin capability controls changed; provide a fresh native catalog and discovery review");
44618
44831
  }
44619
44832
  const codexInactivePlugins = codexPluginControls.inactivePlugins;
44620
44833
  const codexDiscovery = discoveries.find((binding) => binding.agent === "codex");
44621
- const codexPluginSourceInputs = codexPluginControls.sourceInputs.filter((input) => codexDiscovery?.method === "reviewed" && codexDiscovery.roots.some((root2) => root2 === input.sourceRoot || root2.startsWith(input.sourceRoot + sep6) || input.sourceRoot.startsWith(root2 + sep6)) && codexDiscovery.sources.some((source) => source.path === join26(input.sourceRoot, ".codex-plugin/plugin.json") && source.sha256 !== null && source.format === undefined && source.fields === undefined));
44834
+ const codexPluginSourceInputs = codexPluginControls.sourceInputs.filter((input) => codexDiscovery?.method === "reviewed" && codexDiscovery.roots.some((root2) => root2 === input.sourceRoot || root2.startsWith(input.sourceRoot + sep7) || input.sourceRoot.startsWith(root2 + sep7)) && codexDiscovery.sources.some((source) => source.path === join27(input.sourceRoot, ".codex-plugin/plugin.json") && source.sha256 !== null && source.format === undefined && source.fields === undefined));
44622
44835
  assertCodexInstallationInputs(home, [options.projectDir ?? home], codexPluginSourceInputs.map((input) => input.sourceRoot));
44623
44836
  const changes = [];
44624
44837
  let observedSettings;
@@ -44627,19 +44840,19 @@ function planAgentIntegration(options) {
44627
44840
  throw new Error(`Unsupported agent: ${agent}`);
44628
44841
  const { command, profileId: profileId2 } = bindings.get(agent);
44629
44842
  const adapter = AGENT_ADAPTERS[agent];
44630
- const bridgePath = canonicalAgentPath(join26(agent === "sumi" ? sumiBridgeRoot(home) : join26(home, adapter.root), CLI_BRIDGE_NAME), aliases);
44843
+ const bridgePath = canonicalAgentPath(join27(agent === "sumi" ? sumiBridgeRoot(home) : join27(home, adapter.root), CLI_BRIDGE_NAME), aliases);
44631
44844
  assertSafePath(bridgePath);
44632
44845
  if (existsSync7(bridgePath) && !isOwnedCliBridge(bridgePath, [bridgePath]))
44633
44846
  throw new Error(`Refusing to overwrite an unrecognized or modified Skills bridge: ${bridgePath}`);
44634
44847
  for (const [name, after2] of Object.entries(CLI_BRIDGE_FILES)) {
44635
- const path2 = join26(bridgePath, name), before2 = readOptional(path2);
44848
+ const path2 = join27(bridgePath, name), before2 = readOptional(path2);
44636
44849
  if (before2 !== after2)
44637
44850
  changes.push({ path: path2, before: before2, after: after2 });
44638
44851
  }
44639
- const path = canonicalAgentPath(agent === "sumi" ? sumiConfigPath(home) : join26(home, adapter.config), aliases);
44852
+ const path = canonicalAgentPath(agent === "sumi" ? sumiConfigPath(home) : join27(home, adapter.config), aliases);
44640
44853
  const before = readOptional(path);
44641
44854
  if (agent === "hermes") {
44642
- const supervisorPath = join26(dataDir2, "agent-hooks", "hermes.js"), supervisorBefore = readOptional(supervisorPath), supervisorAfter = renderHermesSupervisor(command, profileId2);
44855
+ const supervisorPath = join27(dataDir2, "agent-hooks", "hermes.js"), supervisorBefore = readOptional(supervisorPath), supervisorAfter = renderHermesSupervisor(command, profileId2);
44643
44856
  const priorCommand = policy.bridge?.commands?.hermes, priorProfile = policy.bridge?.profiles?.hermes ?? policy.profileId;
44644
44857
  const previous = policy.bridge?.supervisors?.hermes;
44645
44858
  if (supervisorBefore !== null && supervisorBefore !== supervisorAfter && !(previous?.path === supervisorPath && typeof priorCommand === "string" && typeof priorProfile === "string" && supervisorBefore === renderHermesSupervisor(priorCommand, priorProfile)))
@@ -44650,7 +44863,7 @@ function planAgentIntegration(options) {
44650
44863
  const after2 = configureHermesHooks(before, supervisor, previous);
44651
44864
  if (before !== after2)
44652
44865
  changes.push({ path, before, after: after2 });
44653
- const optOut = join26(home, ".hermes", HERMES_OPT_OUT), optOutBefore = readOptional(optOut);
44866
+ const optOut = join27(home, ".hermes", HERMES_OPT_OUT), optOutBefore = readOptional(optOut);
44654
44867
  if (optOutBefore === null)
44655
44868
  changes.push({ path: optOut, before: null, after: `Managed by @hasna/skills: bundled native skill reseeding is disabled.
44656
44869
  ` });
@@ -44661,7 +44874,7 @@ function planAgentIntegration(options) {
44661
44874
  if (config.permissions !== undefined && (!Array.isArray(config.permissions) || config.permissions.some((rule) => !rule || typeof rule.action !== "string" || typeof rule.resource !== "string" || !["allow", "deny", "ask"].includes(rule.effect))))
44662
44875
  throw new Error("Expected Sumi native permission rules");
44663
44876
  config.permissions = [...(config.permissions ?? []).filter((rule) => rule.action !== "skill"), ...SUMI_SKILL_PERMISSIONS];
44664
- const pluginPath = join26(sumiConfigDirectory(home), "plugins", "skills-cli.js"), pluginBefore = readOptional(pluginPath);
44877
+ const pluginPath = join27(sumiConfigDirectory(home), "plugins", "skills-cli.js"), pluginBefore = readOptional(pluginPath);
44665
44878
  const pluginAfter = renderSumiPlugin(command, profileId2);
44666
44879
  const priorCommand = policy.bridge?.commands?.sumi, priorProfile = policy.bridge?.profiles?.sumi ?? policy.profileId;
44667
44880
  if (pluginBefore !== null && pluginBefore !== pluginAfter && !(typeof priorCommand === "string" && typeof priorProfile === "string" && isManagedSumiPlugin(pluginBefore, priorCommand, priorProfile)))
@@ -44673,7 +44886,7 @@ function planAgentIntegration(options) {
44673
44886
  if (!permission || typeof permission !== "object" || Array.isArray(permission))
44674
44887
  throw new Error("Expected OpenCode permission object");
44675
44888
  config.permission = { ...permission, skill: { "*": "deny", [CLI_BRIDGE_NAME]: "allow" } };
44676
- const pluginPath = join26(home, ".config", "opencode", "plugins", "skills-cli.js"), pluginBefore = readOptional(pluginPath);
44889
+ const pluginPath = join27(home, ".config", "opencode", "plugins", "skills-cli.js"), pluginBefore = readOptional(pluginPath);
44677
44890
  const pluginAfter = renderOpenCodePlugin(command, profileId2);
44678
44891
  const priorCommand = policy.bridge?.commands?.opencode;
44679
44892
  const ownedPrevious = typeof priorCommand === "string" && typeof policy.profileId === "string" && pluginBefore === renderOpenCodePlugin(priorCommand, policy.bridge?.profiles?.opencode ?? policy.profileId);
@@ -44690,7 +44903,7 @@ function planAgentIntegration(options) {
44690
44903
  if (before !== after)
44691
44904
  changes.push({ path, before, after });
44692
44905
  if (agent === "codex") {
44693
- const configPath = canonicalAgentPath(join26(home, ".codex", "config.toml"), aliases), previous = readOptional(configPath);
44906
+ const configPath = canonicalAgentPath(join27(home, ".codex", "config.toml"), aliases), previous = readOptional(configPath);
44694
44907
  if (previous !== codexConfigBefore)
44695
44908
  throw new Error(`Configuration changed during planning: ${configPath}`);
44696
44909
  const next = disableReviewedCodexPluginNames(codexPathConfig, codexPluginSkills);
@@ -44702,16 +44915,16 @@ function planAgentIntegration(options) {
44702
44915
  }
44703
44916
  }
44704
44917
  }
44705
- const codexPluginSkillReview = options.codexNativeCatalog ? { version: options.codexNativeCatalog.version, cwd: options.codexNativeCatalog.cwd, catalogSha256: sha4(JSON.stringify({ version: options.codexNativeCatalog.version, cwd: options.codexNativeCatalog.cwd, skills: projectCodexNativeSkillCatalog({ data: [{ cwd: options.codexNativeCatalog.cwd, errors: [], skills: options.codexNativeCatalog.skills }] }, options.codexNativeCatalog.cwd), ...options.codexNativeCatalog.plugins === undefined ? {} : { plugins: projectCodexInstalledPluginEntries(options.codexNativeCatalog.plugins) } })), configSha256: changes.find((change) => change.path === canonicalAgentPath(join26(home, ".codex/config.toml"), aliases))?.before === null ? null : sha4(readOptional(canonicalAgentPath(join26(home, ".codex/config.toml"), aliases)) ?? "") } : policy.bridge?.codexPluginSkillReview;
44918
+ const codexPluginSkillReview = options.codexNativeCatalog ? { version: options.codexNativeCatalog.version, cwd: options.codexNativeCatalog.cwd, catalogSha256: sha4(JSON.stringify({ version: options.codexNativeCatalog.version, cwd: options.codexNativeCatalog.cwd, skills: projectCodexNativeSkillCatalog({ data: [{ cwd: options.codexNativeCatalog.cwd, errors: [], skills: options.codexNativeCatalog.skills }] }, options.codexNativeCatalog.cwd), ...options.codexNativeCatalog.plugins === undefined ? {} : { plugins: projectCodexInstalledPluginEntries(options.codexNativeCatalog.plugins) } })), configSha256: changes.find((change) => change.path === canonicalAgentPath(join27(home, ".codex/config.toml"), aliases))?.before === null ? null : sha4(readOptional(canonicalAgentPath(join27(home, ".codex/config.toml"), aliases)) ?? "") } : policy.bridge?.codexPluginSkillReview;
44706
44919
  const discoveryAfter = discoveries.map((binding) => {
44707
44920
  const rebound = rebindAgentDiscovery(binding, new Map(changes.map((change) => [change.path, change.after])));
44708
44921
  if (binding.agent !== "codex")
44709
44922
  return rebound;
44710
44923
  const { codexInstallationInputs: previousInputs, ...current } = rebound;
44711
44924
  const inputs = codexPluginSourceInputs.map((input) => input.sourceRoot);
44712
- const directories = options.codexNativeCatalog || !previousInputs ? captureDiscoveryDirectories((binding.directories ?? []).filter((directory) => inputs.some((root2) => root2.startsWith(directory.path + sep6))).map((directory) => directory.path), inputs) : previousInputs.directories;
44925
+ 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;
44713
44926
  const installed = codexPluginSourceInputs.length ? { ...current, codexInstallationInputs: { version: "codex-cli 0.160.0", catalogSha256: codexPluginSkillReview.catalogSha256, plugins: codexPluginSourceInputs, ...directories?.length ? { directories } : {} } } : current;
44714
- return captureRetiredCodexDiscovery(installed, codexPluginSkills, Bun.TOML.parse(changes.find((change) => change.path === canonicalAgentPath(join26(home, ".codex/config.toml"), aliases))?.after ?? codexConfigBefore ?? "").skills?.config ?? []);
44927
+ return captureRetiredCodexDiscovery(installed, codexPluginSkills, Bun.TOML.parse(changes.find((change) => change.path === canonicalAgentPath(join27(home, ".codex/config.toml"), aliases))?.after ?? codexConfigBefore ?? "").skills?.config ?? []);
44715
44928
  });
44716
44929
  const nextPolicy = { ...policy, version: 1, loading: "cli", profileId, bridge: {
44717
44930
  ...policy.bridge,
@@ -44720,10 +44933,10 @@ function planAgentIntegration(options) {
44720
44933
  agents: [...new Set([...priorAgents, ...options.agents])].sort(),
44721
44934
  home: resolve18(home),
44722
44935
  includeVendor: true,
44723
- ...options.agents.includes("hermes") ? { supervisors: { ...policy.bridge?.supervisors, hermes: { path: join26(dataDir2, "agent-hooks", "hermes.js"), runtime: process.execPath, sha256: sha4(renderHermesSupervisor(bindings.get("hermes").command, bindings.get("hermes").profileId)) } } } : {},
44936
+ ...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)) } } } : {},
44724
44937
  commands: { ...policy.bridge?.commands, ...Object.fromEntries([...bindings].map(([agent, binding]) => [agent, binding.command])) },
44725
44938
  profiles: Object.fromEntries([...new Set([...priorAgents, ...options.agents])].sort().map((agent) => [agent, bindings.get(agent)?.profileId ?? policy.bridge?.profiles?.[agent] ?? policy.profileId])),
44726
- disabledBuiltins: options.agents.includes("codex") ? nativeSkills.filter((entry) => entry.agent === "codex" && entry.vendor && entry.path.startsWith(canonicalAgentPath(join26(home, ".codex", "skills", ".system"), aliases) + sep6)).map((entry) => ({ path: entry.path, hash: entry.hash })) : policy.bridge?.disabledBuiltins ?? [],
44939
+ disabledBuiltins: options.agents.includes("codex") ? nativeSkills.filter((entry) => entry.agent === "codex" && entry.vendor && entry.path.startsWith(canonicalAgentPath(join27(home, ".codex", "skills", ".system"), aliases) + sep7)).map((entry) => ({ path: entry.path, hash: entry.hash })) : policy.bridge?.disabledBuiltins ?? [],
44727
44940
  rootAliases: aliases,
44728
44941
  ...options.codexNativeCatalog || codexPluginSkills.length || codexInactivePlugins.length || codexPluginSourceInputs.length ? { codexPluginSkills, codexInactivePlugins, codexPluginSkillReview } : {},
44729
44942
  discovery: { ...policy.bridge?.discovery, ...Object.fromEntries(discoveryAfter.map((binding) => [binding.agent, binding])) }
@@ -44775,10 +44988,10 @@ function projectedHookExecutable(command, expectedResolved) {
44775
44988
  if (expectedResolved !== undefined && resolved !== expectedResolved)
44776
44989
  hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
44777
44990
  const resolvedParentIdentity = parents3(resolved);
44778
- const manifest = snapshot(join26(dirname17(dirname17(resolved)), "package.json"), false, { readOnlyPackage: true });
44991
+ const manifest = snapshot(join27(dirname17(dirname17(resolved)), "package.json"), false, { readOnlyPackage: true });
44779
44992
  projectedHookAcl(manifest.file, manifest.stat);
44780
44993
  const pkg = JSON.parse(manifest.text);
44781
- if (pkg.name !== "@hasna/skills" || !/^\d+\.\d+\.\d+$/.test(pkg.version) || pkg.bin?.skills !== "bin/index.js" || resolved !== join26(dirname17(manifest.file), "bin/index.js"))
44994
+ 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"))
44782
44995
  hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
44783
44996
  const cli = snapshot(resolved, false, { readOnlyPackage: true });
44784
44997
  projectedHookAcl(cli.file, cli.stat);
@@ -44815,7 +45028,7 @@ function planClaudeManagedHookProjection(options) {
44815
45028
  hookProjectionRefusal("TARGET_INVALID");
44816
45029
  }
44817
45030
  const home = resolve18(options.home ?? homedir3()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
44818
- const policyPath = join26(dataDir2, "agent-policy.json");
45031
+ const policyPath = join27(dataDir2, "agent-policy.json");
44819
45032
  let policyBytes, settingsBytes, settingsPath, command, profile;
44820
45033
  try {
44821
45034
  policyBytes = readNativeBytes(policyPath, 1024 * 1024);
@@ -44823,7 +45036,7 @@ function planClaudeManagedHookProjection(options) {
44823
45036
  if (!snapshot2 || snapshot2.text !== policyBytes.toString("utf8"))
44824
45037
  hookProjectionRefusal("SOURCE_UNVERIFIED");
44825
45038
  const binding = snapshot2.value.bridge;
44826
- settingsPath = canonicalAgentPath(join26(home, AGENT_ADAPTERS.claude.config), binding?.rootAliases ?? []);
45039
+ settingsPath = canonicalAgentPath(join27(home, AGENT_ADAPTERS.claude.config), binding?.rootAliases ?? []);
44827
45040
  settingsBytes = readNativeBytes(settingsPath, 1024 * 1024);
44828
45041
  command = binding?.commands?.claude;
44829
45042
  profile = binding?.profiles?.claude;
@@ -44906,12 +45119,12 @@ function planClaudePreToolUseHookUpdate(options) {
44906
45119
  return planClaudeHookEventsUpdate({ ...options, events: ["PreToolUse"] });
44907
45120
  }
44908
45121
  function claudeSettingsConsumers(home, path, discoveries, aliases) {
44909
- const canonical6 = (value) => canonicalAgentPath(value, aliases);
45122
+ const canonical7 = (value) => canonicalAgentPath(value, aliases);
44910
45123
  const containsSettings = (root2) => {
44911
- const distance = relative5(canonical6(root2), path);
44912
- return distance === "" || distance !== ".." && !distance.startsWith(`..${sep6}`) && !isAbsolute19(distance);
45124
+ const distance = relative5(canonical7(root2), path);
45125
+ return distance === "" || distance !== ".." && !distance.startsWith(`..${sep7}`) && !isAbsolute19(distance);
44913
45126
  };
44914
- return discoveries.filter((binding) => binding.agent === "claude" || binding.agent === "opencode" || canonical6(join26(home, AGENT_ADAPTERS[binding.agent].config)) === path || binding.sources.some((source) => canonical6(source.path) === path) || binding.roots.some(containsSettings) || binding.directories?.some((directory) => containsSettings(directory.path))).map((binding) => binding.agent);
45127
+ 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);
44915
45128
  }
44916
45129
  function verifyCoordinatedDiscovery(binding, home, aliases) {
44917
45130
  try {
@@ -44929,7 +45142,7 @@ function verifyCoordinatedDiscovery(binding, home, aliases) {
44929
45142
  }
44930
45143
  function planClaudeHookEventsUpdate(options) {
44931
45144
  const home = resolve18(options.home ?? homedir3()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
44932
- const policyPath = join26(dataDir2, "agent-policy.json");
45145
+ const policyPath = join27(dataDir2, "agent-policy.json");
44933
45146
  assertSafePath(policyPath);
44934
45147
  const snapshot2 = readManagedSkillPolicySnapshot(dataDir2);
44935
45148
  if (!snapshot2)
@@ -44940,7 +45153,7 @@ function planClaudeHookEventsUpdate(options) {
44940
45153
  }
44941
45154
  const aliases = bridge.rootAliases ?? [];
44942
45155
  recheckRootAliases(aliases);
44943
- const path = canonicalAgentPath(join26(home, ".claude", "settings.json"), aliases);
45156
+ const path = canonicalAgentPath(join27(home, ".claude", "settings.json"), aliases);
44944
45157
  assertSafePath(path);
44945
45158
  const before = lstatSync22(path, { throwIfNoEntry: false }) ? new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(readNativeBytes(path, 1024 * 1024)) : null;
44946
45159
  if ((before === null ? "absent" : sha4(before)) !== options.expectedSettingsSha256)
@@ -45018,7 +45231,7 @@ function planAgentSettingsWitnessUpgrade(options) {
45018
45231
  const binding = policy.bridge?.discovery?.[options.agent];
45019
45232
  if (!binding || binding.agent !== options.agent || binding.method !== "reviewed")
45020
45233
  throw new Error("Settings witness upgrade requires an existing reviewed native binding");
45021
- const configPath = canonicalAgentPath(options.agent === "sumi" ? sumiConfigPath(home) : join26(home, options.agent === "claude" ? ".claude/settings.json" : ".codex/config.toml"), aliases);
45234
+ const configPath = canonicalAgentPath(options.agent === "sumi" ? sumiConfigPath(home) : join27(home, options.agent === "claude" ? ".claude/settings.json" : ".codex/config.toml"), aliases);
45022
45235
  const settings = readOptional(configPath);
45023
45236
  if (settings === null || sha4(settings) !== options.expectedSettingsSha256)
45024
45237
  throw new Error("Native settings preimage changed");
@@ -45069,7 +45282,7 @@ function planAgentSettingsWitnessUpgrade(options) {
45069
45282
  const replacement = { ...binding, sources: rebound };
45070
45283
  verifyAgentDiscovery(replacement);
45071
45284
  const after = serializeManagedSkillPolicy({ ...policy, bridge: { ...policy.bridge, discovery: { ...policy.bridge.discovery, [options.agent]: replacement } } });
45072
- return { dataDir: dataDir2, profileId: policy.profileId, changes: [{ path: join26(dataDir2, "agent-policy.json"), before: snapshot2.text, after }], nativeSkills: [], observedPolicy: { path: join26(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 })) } };
45285
+ 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 })) } };
45073
45286
  }
45074
45287
  function applyAgentIntegration(plan, options = {}) {
45075
45288
  const roots = plan.changes.flatMap((change) => {
@@ -45085,7 +45298,7 @@ function applyAgentIntegrationUnlocked(plan, options = {}, assertCurrent) {
45085
45298
  throw new Error("Native identity source changed after planning");
45086
45299
  if (plan.observedSettings && readOptional(plan.observedSettings.path) !== plan.observedSettings.before)
45087
45300
  throw new Error("Native settings changed after witness planning");
45088
- const policyPath = join26(plan.dataDir, "agent-policy.json");
45301
+ const policyPath = join27(plan.dataDir, "agent-policy.json");
45089
45302
  assertSafePath(policyPath);
45090
45303
  const currentText = (path) => resolve18(path) === resolve18(policyPath) ? readManagedSkillPolicySnapshot(plan.dataDir)?.text ?? null : readOptional(path);
45091
45304
  readManagedSkillPolicySnapshot(plan.dataDir);
@@ -45120,7 +45333,7 @@ function applyAgentIntegrationUnlocked(plan, options = {}, assertCurrent) {
45120
45333
  for (const change of plan.changes)
45121
45334
  if (currentText(change.path) !== change.before)
45122
45335
  throw new Error(`Configuration changed after planning: ${change.path}`);
45123
- const backupRoot = join26(plan.dataDir, "migration", randomUUID4()), backups = [], written = [], createdDirectories = new Set;
45336
+ const backupRoot = join27(plan.dataDir, "migration", randomUUID4()), backups = [], written = [], createdDirectories = new Set;
45124
45337
  if (!plan.changes.length) {
45125
45338
  assertCurrent();
45126
45339
  recheckRootAliases(aliases);
@@ -45131,7 +45344,7 @@ function applyAgentIntegrationUnlocked(plan, options = {}, assertCurrent) {
45131
45344
  chmodSync(backupRoot, 448);
45132
45345
  for (const [index, change] of plan.changes.entries())
45133
45346
  if (change.before !== null) {
45134
- const backup = join26(backupRoot, `${index}-${sha4(change.path).slice(0, 12)}.backup`);
45347
+ const backup = join27(backupRoot, `${index}-${sha4(change.path).slice(0, 12)}.backup`);
45135
45348
  writeFileSync5(backup, change.before, { mode: 384, flag: "wx" });
45136
45349
  if (readFileSync16(backup, "utf8") !== change.before)
45137
45350
  throw new Error("Native configuration preservation readback failed");
@@ -45164,7 +45377,7 @@ function applyAgentIntegrationUnlocked(plan, options = {}, assertCurrent) {
45164
45377
  }
45165
45378
  for (const agent of plan.managedAgentChecks?.agents ?? [])
45166
45379
  assertManagedAgentBridge(agent, { home: plan.managedAgentChecks.home, dataDir: plan.dataDir, projectDir: plan.managedAgentChecks.home });
45167
- atomicWrite2(join26(backupRoot, "receipt.json"), JSON.stringify({ version: 1, changes: written.map((change) => ({ path: change.path, beforeHash: change.before === null ? null : sha4(change.before), afterHash: sha4(change.after) })), backups, ...aliases.length ? { rootAliases: aliases } : {} }) + `
45380
+ atomicWrite2(join27(backupRoot, "receipt.json"), JSON.stringify({ version: 1, changes: written.map((change) => ({ path: change.path, beforeHash: change.before === null ? null : sha4(change.before), afterHash: sha4(change.after) })), backups, ...aliases.length ? { rootAliases: aliases } : {} }) + `
45168
45381
  `);
45169
45382
  } catch (error) {
45170
45383
  assertCurrent();
@@ -45227,7 +45440,7 @@ function archiveNativeSkills(inventory, options) {
45227
45440
  const selected = options.targetManifest ? selectNativeMigrationTargets(inventory, options.targetManifest) : inventory.filter((entry) => !entry.bridge && !entry.system && (entry.vendor ? options.includeVendor : entry.managed || options.includeUnmanaged));
45228
45441
  const roots = selected.flatMap((entry) => {
45229
45442
  const root2 = (entry.rootAlias?.agent === "codex" ? entry.rootAlias.alias : undefined) ?? codexCorpusRootForPath(entry.path);
45230
- const owner2 = entry.codexHome ?? (entry.agent === "codex" && entry.bridgeHome ? join26(entry.bridgeHome, ".codex") : undefined);
45443
+ const owner2 = entry.codexHome ?? (entry.agent === "codex" && entry.bridgeHome ? join27(entry.bridgeHome, ".codex") : undefined);
45231
45444
  if (!root2 && !owner2 && (entry.agent === "codex" || isCodexSkillDiscoveryInput(entry.path)))
45232
45445
  throw new Error("CODEX_CORPUS_ROOT_UNVERIFIED");
45233
45446
  return [...new Set([root2, owner2].filter((value) => value !== undefined))];
@@ -45242,7 +45455,7 @@ function archiveNativeSkillsUnlocked(inventory, options, assertCurrent) {
45242
45455
  recheckRootAliases(aliases);
45243
45456
  for (const entry of inventory.filter((entry2) => entry2.bridge)) {
45244
45457
  const adapter = AGENT_ADAPTERS[entry.agent];
45245
- const expected = adapter && entry.bridgeHome ? canonicalAgentPath(join26(entry.agent === "sumi" ? sumiBridgeRoot(entry.bridgeHome) : join26(entry.bridgeHome, adapter.root), CLI_BRIDGE_NAME), aliases) : undefined;
45458
+ const expected = adapter && entry.bridgeHome ? canonicalAgentPath(join27(entry.agent === "sumi" ? sumiBridgeRoot(entry.bridgeHome) : join27(entry.bridgeHome, adapter.root), CLI_BRIDGE_NAME), aliases) : undefined;
45246
45459
  if (!expected || treeHash(entry.path) !== entry.hash || !isOwnedCliBridge(entry.path, [expected]))
45247
45460
  throw new Error(`Skills bridge changed after planning: ${entry.path}`);
45248
45461
  }
@@ -45253,11 +45466,11 @@ function archiveNativeSkillsUnlocked(inventory, options, assertCurrent) {
45253
45466
  const targetManifest = options.targetManifest ? { schema: options.targetManifest.schema, digest: options.targetManifest.digest, targetCount: options.targetManifest.targets.length } : undefined;
45254
45467
  if (!selected.length)
45255
45468
  return { entries: [], ...targetManifest ? { targetManifest } : {}, ...aliases.length ? { rootAliases: aliases } : {} };
45256
- const operationId = randomUUID4(), archiveRoot = join26(options.dataDir ?? getDataDir(), "migration", operationId, "native"), receiptPath = join26(archiveRoot, "receipt.json");
45469
+ const operationId = randomUUID4(), archiveRoot = join27(options.dataDir ?? getDataDir(), "migration", operationId, "native"), receiptPath = join27(archiveRoot, "receipt.json");
45257
45470
  const entries = selected.map((entry, index) => ({
45258
- source: entry.vendor ? join26(entry.path, "SKILL.md") : entry.path,
45259
- archive: join26(archiveRoot, `${index}-${sha4(entry.path).slice(0, 12)}`),
45260
- hash: entry.vendor ? sha4(readNativeBytes(join26(entry.path, "SKILL.md"))) : entry.hash,
45471
+ source: entry.vendor ? join27(entry.path, "SKILL.md") : entry.path,
45472
+ archive: join27(archiveRoot, `${index}-${sha4(entry.path).slice(0, 12)}`),
45473
+ hash: entry.vendor ? sha4(readNativeBytes(join27(entry.path, "SKILL.md"))) : entry.hash,
45261
45474
  ...entry.vendor ? { discoveryOnly: true } : {},
45262
45475
  status: "planned"
45263
45476
  }));
@@ -45364,9 +45577,9 @@ function isInertCodexPluginCacheCopy(entry, cache, allowedHostPaths, read3) {
45364
45577
  try {
45365
45578
  if (entry.agent !== "codex" || !entry.vendor || entry.bridge || entry.system)
45366
45579
  return false;
45367
- const document2 = join26(entry.path, "SKILL.md");
45580
+ const document2 = join27(entry.path, "SKILL.md");
45368
45581
  const inside = relative5(cache, entry.path);
45369
- if (!inside || isAbsolute19(inside) || inside.split(sep6).some((segment) => segment === ".."))
45582
+ if (!inside || isAbsolute19(inside) || inside.split(sep7).some((segment) => segment === ".."))
45370
45583
  return false;
45371
45584
  assertSafePath(entry.path);
45372
45585
  if (!lstatSync22(cache).isDirectory() || !lstatSync22(entry.path).isDirectory() || !lstatSync22(document2).isFile())
@@ -45387,7 +45600,7 @@ function assertManagedAgentBridge(agent, options = {}) {
45387
45600
  }
45388
45601
  function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscovery) {
45389
45602
  const home = resolve18(options.home ?? homedir3()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
45390
- assertSafePath(join26(dataDir2, "agent-policy.json"));
45603
+ assertSafePath(join27(dataDir2, "agent-policy.json"));
45391
45604
  const snapshot2 = readManagedSkillPolicySnapshot(dataDir2);
45392
45605
  if (!snapshot2)
45393
45606
  throw new Error("NATIVE_SKILL_DRIFT: install the Skills bridge with skills hook install");
@@ -45398,14 +45611,14 @@ function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscov
45398
45611
  if (!Array.isArray(aliases))
45399
45612
  throw new Error("NATIVE_SKILL_DRIFT: invalid root alias binding");
45400
45613
  recheckRootAliases(aliases);
45401
- const expected = canonicalAgentPath(join26(agent === "sumi" ? sumiBridgeRoot(home) : join26(home, AGENT_ADAPTERS[agent].root), CLI_BRIDGE_NAME), aliases);
45614
+ const expected = canonicalAgentPath(join27(agent === "sumi" ? sumiBridgeRoot(home) : join27(home, AGENT_ADAPTERS[agent].root), CLI_BRIDGE_NAME), aliases);
45402
45615
  if (!isOwnedCliBridge(expected, [expected]))
45403
45616
  throw new Error("NATIVE_SKILL_DRIFT: the native Skills bridge is missing or modified; repair it before continuing");
45404
45617
  const roots = projectAncestorDirectories([options.projectDir ?? process.cwd(), ...options.projectDirs ?? [], ...agent === "hermes" && process.env.TERMINAL_CWD ? [process.cwd()] : []]);
45405
- const visible = (entry) => entry.agent === agent || ["codex", "gemini", "opencode", "hermes", "sumi"].includes(agent) && entry.path.includes(`${sep6}.agents${sep6}skills${sep6}`) || ["opencode", "sumi"].includes(agent) && entry.agent === "claude";
45618
+ const visible = (entry) => entry.agent === agent || ["codex", "gemini", "opencode", "hermes", "sumi"].includes(agent) && entry.path.includes(`${sep7}.agents${sep7}skills${sep7}`) || ["opencode", "sumi"].includes(agent) && entry.agent === "claude";
45406
45619
  const discovery = provenDiscovery ?? binding.discovery?.[agent];
45407
45620
  assertProjectDiscovery(agent, [...roots], home, (path) => canonicalAgentPath(path, aliases), discovery);
45408
- const configPath = canonicalAgentPath(agent === "sumi" ? sumiConfigPath(home) : join26(home, AGENT_ADAPTERS[agent].config), aliases), config = agent === "hermes" ? parseHermesConfig(readOptional(configPath)) : jsonObject(readOptional(configPath), configPath);
45621
+ const configPath = canonicalAgentPath(agent === "sumi" ? sumiConfigPath(home) : join27(home, AGENT_ADAPTERS[agent].config), aliases), config = agent === "hermes" ? parseHermesConfig(readOptional(configPath)) : jsonObject(readOptional(configPath), configPath);
45409
45622
  const command = binding.commands?.[agent], profile = binding.profiles?.[agent];
45410
45623
  if (typeof command !== "string" || typeof profile !== "string")
45411
45624
  throw new Error("NATIVE_SKILL_DRIFT: the native hook command/profile binding is missing");
@@ -45413,14 +45626,14 @@ function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscov
45413
45626
  throw new Error("NATIVE_SKILL_DRIFT: the hook selection profile differs from its managed binding; restart the native client after reviewing skills hook install");
45414
45627
  if (agent === "hermes") {
45415
45628
  const supervisor = binding.supervisors?.hermes;
45416
- if (supervisor?.path !== join26(dataDir2, "agent-hooks", "hermes.js") || supervisor?.sha256 !== sha4(renderHermesSupervisor(command, profile)))
45629
+ if (supervisor?.path !== join27(dataDir2, "agent-hooks", "hermes.js") || supervisor?.sha256 !== sha4(renderHermesSupervisor(command, profile)))
45417
45630
  throw new Error("NATIVE_SKILL_DRIFT: Hermes supervisor binding changed; run skills hook install");
45418
45631
  assertHermesProtection(home, config, command, profile, supervisor);
45419
45632
  } else if (agent === "sumi") {
45420
- if (JSON.stringify(config.permissions?.filter((rule) => rule.action === "skill")) !== JSON.stringify(SUMI_SKILL_PERMISSIONS) || !isManagedSumiPlugin(readOptional(join26(sumiConfigDirectory(home), "plugins", "skills-cli.js")), command, profile))
45633
+ if (JSON.stringify(config.permissions?.filter((rule) => rule.action === "skill")) !== JSON.stringify(SUMI_SKILL_PERMISSIONS) || !isManagedSumiPlugin(readOptional(join27(sumiConfigDirectory(home), "plugins", "skills-cli.js")), command, profile))
45421
45634
  throw new Error("NATIVE_SKILL_DRIFT: Sumi bridge protection changed; run skills hook install");
45422
45635
  } else if (agent === "opencode") {
45423
- if (JSON.stringify(config.permission?.skill) !== JSON.stringify({ "*": "deny", [CLI_BRIDGE_NAME]: "allow" }) || readOptional(join26(home, ".config", "opencode", "plugins", "skills-cli.js")) !== renderOpenCodePlugin(command, profile))
45636
+ if (JSON.stringify(config.permission?.skill) !== JSON.stringify({ "*": "deny", [CLI_BRIDGE_NAME]: "allow" }) || readOptional(join27(home, ".config", "opencode", "plugins", "skills-cli.js")) !== renderOpenCodePlugin(command, profile))
45424
45637
  throw new Error("NATIVE_SKILL_DRIFT: OpenCode bridge protection changed; run skills hook install");
45425
45638
  } else {
45426
45639
  const required = {};
@@ -45437,42 +45650,42 @@ function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscov
45437
45650
  if (agent === "gemini" && (config.hooksConfig?.enabled === false || config.skills?.enabled !== true || !["antigravity-support", "skill-creator"].every((name) => config.skills?.disabled?.includes(name)) || config.skills?.disabled?.includes(CLI_BRIDGE_NAME)))
45438
45651
  throw new Error("NATIVE_SKILL_DRIFT: Gemini bridge or bundled-skill protection changed; run skills hook install");
45439
45652
  }
45440
- const codexPath = canonicalAgentPath(join26(home, ".codex", "config.toml"), aliases);
45653
+ const codexPath = canonicalAgentPath(join27(home, ".codex", "config.toml"), aliases);
45441
45654
  if (options.codexDiscoveryRecovery && (agent !== "codex" || options.codexDiscoveryRecovery.configPath !== codexPath))
45442
45655
  throw new Error("NATIVE_SKILL_DRIFT: Codex trust recovery names a different configuration root");
45443
45656
  const codexConfig = agent === "codex" ? Bun.TOML.parse(readOptional(codexPath) ?? "") : {};
45444
45657
  if (agent === "codex" && codexConfig.skills?.bundled?.enabled !== false)
45445
45658
  throw new Error("NATIVE_SKILL_DRIFT: Codex bundled skill reseeding is not disabled (skills.bundled.enabled); run skills hook install");
45446
- const setting = (path) => (codexConfig.skills?.config ?? []).filter((entry) => typeof entry.path === "string" && [path, join26(path, "SKILL.md")].includes(canonicalAgentPath(entry.path, aliases)));
45659
+ const setting = (path) => (codexConfig.skills?.config ?? []).filter((entry) => typeof entry.path === "string" && [path, join27(path, "SKILL.md")].includes(canonicalAgentPath(entry.path, aliases)));
45447
45660
  if (agent === "codex" && [...setting(expected), ...(codexConfig.skills?.config ?? []).filter((entry) => typeof entry.name === "string" && entry.name.trim() === CLI_BRIDGE_NAME)].some((entry) => entry.enabled === false))
45448
45661
  throw new Error("NATIVE_SKILL_DRIFT: the Codex CLI bridge is disabled; run skills hook install");
45449
- if (agent === "codex" && !reviewedCodexPluginCapabilitiesUnchanged(canonicalAgentPath(join26(home, ".codex/plugins/cache"), aliases), binding.codexPluginSkills ?? [], (path) => new TextDecoder("utf-8", { fatal: true }).decode(readNativeBytes(path, 1024 * 1024)), codexConfig.skills?.config ?? []))
45662
+ if (agent === "codex" && !reviewedCodexPluginCapabilitiesUnchanged(canonicalAgentPath(join27(home, ".codex/plugins/cache"), aliases), binding.codexPluginSkills ?? [], (path) => new TextDecoder("utf-8", { fatal: true }).decode(readNativeBytes(path, 1024 * 1024)), codexConfig.skills?.config ?? []))
45450
45663
  throw new Error("NATIVE_SKILL_DRIFT: reviewed native plugin capability controls changed; run skills hook install with a fresh discovery review");
45451
45664
  const disabledPlugin = (entry) => {
45452
45665
  if (agent !== "codex" || !entry.vendor)
45453
45666
  return false;
45454
- const document2 = join26(entry.path, "SKILL.md"), cache = canonicalAgentPath(join26(home, ".codex/plugins/cache"), aliases), read3 = (path) => new TextDecoder("utf-8", { fatal: true }).decode(readNativeBytes(path, 1024 * 1024));
45667
+ const document2 = join27(entry.path, "SKILL.md"), cache = canonicalAgentPath(join27(home, ".codex/plugins/cache"), aliases), read3 = (path) => new TextDecoder("utf-8", { fatal: true }).decode(readNativeBytes(path, 1024 * 1024));
45455
45668
  return isReviewedCodexPluginInactive(document2, cache, binding.codexInactivePlugins ?? [], codexConfig.plugins, codexConfig.skills?.config ?? [], read3) || isReviewedCodexPluginSkillDisabled(document2, cache, binding.codexPluginSkills ?? [], codexConfig.skills?.config, read3);
45456
45669
  };
45457
45670
  const disabledPaths = new Set(disabledCodexSkillPaths(codexConfig, aliases));
45458
45671
  const disabledVendorSkill = (entry) => {
45459
45672
  if (agent !== "codex" || !entry.vendor)
45460
45673
  return false;
45461
- if ((binding.codexPluginSkills ?? []).some((control) => entry.path.startsWith(control.pluginParent + sep6)))
45674
+ if ((binding.codexPluginSkills ?? []).some((control) => entry.path.startsWith(control.pluginParent + sep7)))
45462
45675
  return disabledPlugin(entry);
45463
45676
  if (disabledPlugin(entry))
45464
45677
  return true;
45465
45678
  if (!disabledPaths.has(entry.path))
45466
45679
  return false;
45467
- if (entry.path.startsWith(canonicalAgentPath(join26(home, ".codex", "plugins", "cache"), aliases) + sep6))
45680
+ if (entry.path.startsWith(canonicalAgentPath(join27(home, ".codex", "plugins", "cache"), aliases) + sep7))
45468
45681
  return true;
45469
- const runtimeCache = canonicalAgentPath(join26(home, ".cache", "codex-runtimes"), aliases);
45470
- if (entry.path.startsWith(runtimeCache + sep6) && discovery?.method === "automatic" && discovery.roots.some((root2) => entry.path.startsWith(root2 + sep6)))
45682
+ const runtimeCache = canonicalAgentPath(join27(home, ".cache", "codex-runtimes"), aliases);
45683
+ if (entry.path.startsWith(runtimeCache + sep7) && discovery?.method === "automatic" && discovery.roots.some((root2) => entry.path.startsWith(root2 + sep7)))
45471
45684
  return true;
45472
- const bundledMarketplaces = canonicalAgentPath(join26(home, ".codex", ".tmp", "bundled-marketplaces"), aliases);
45473
- if (entry.path.startsWith(bundledMarketplaces + sep6) && discovery?.method === "automatic" && discovery.roots.some((root2) => entry.path.startsWith(root2 + sep6)))
45685
+ const bundledMarketplaces = canonicalAgentPath(join27(home, ".codex", ".tmp", "bundled-marketplaces"), aliases);
45686
+ if (entry.path.startsWith(bundledMarketplaces + sep7) && discovery?.method === "automatic" && discovery.roots.some((root2) => entry.path.startsWith(root2 + sep7)))
45474
45687
  return true;
45475
- if (!entry.path.startsWith(canonicalAgentPath(join26(home, ".codex", "skills", ".system"), aliases) + sep6))
45688
+ if (!entry.path.startsWith(canonicalAgentPath(join27(home, ".codex", "skills", ".system"), aliases) + sep7))
45476
45689
  return false;
45477
45690
  return Array.isArray(binding.disabledBuiltins) && binding.disabledBuiltins.some((item) => item.path === entry.path && item.hash === entry.hash);
45478
45691
  };
@@ -45495,7 +45708,7 @@ function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscov
45495
45708
  let installationInputRoots = [];
45496
45709
  if (agent === "codex") {
45497
45710
  try {
45498
- installationInputRoots = reviewedCodexPluginSourceRoots(canonicalAgentPath(join26(home, ".codex/plugins/cache"), aliases), discovery.codexInstallationInputs?.plugins ?? [], (path) => new TextDecoder("utf-8", { fatal: true }).decode(readNativeBytes(path, 1024 * 1024)));
45711
+ installationInputRoots = reviewedCodexPluginSourceRoots(canonicalAgentPath(join27(home, ".codex/plugins/cache"), aliases), discovery.codexInstallationInputs?.plugins ?? [], (path) => new TextDecoder("utf-8", { fatal: true }).decode(readNativeBytes(path, 1024 * 1024)));
45499
45712
  } catch {
45500
45713
  throw new Error("NATIVE_SKILL_DRIFT: native installation input identity changed; review discovery and catalog");
45501
45714
  }
@@ -45505,7 +45718,7 @@ function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscov
45505
45718
  let adapterRefusal, inert = [];
45506
45719
  if (agent === "codex" && unexpected.length && options.codexNativePolicy) {
45507
45720
  const { inspector, helperRunner, deadlineMs, ...envelope } = options.codexNativePolicy;
45508
- const cache = canonicalAgentPath(join26(home, ".codex", "plugins", "cache"), aliases), read3 = (path) => new TextDecoder("utf-8", { fatal: true }).decode(readNativeBytes(path, 1024 * 1024)), bridgeDocument = join26(expected, "SKILL.md");
45721
+ const cache = canonicalAgentPath(join27(home, ".codex", "plugins", "cache"), aliases), read3 = (path) => new TextDecoder("utf-8", { fatal: true }).decode(readNativeBytes(path, 1024 * 1024)), bridgeDocument = join27(expected, "SKILL.md");
45509
45722
  try {
45510
45723
  const claimed = parseCodexNativeHookEnvelope(envelope, bridgeDocument).policy;
45511
45724
  inert = unexpected.filter((entry) => isInertCodexPluginCacheCopy(entry, cache, claimed.allowedHostPaths, read3));
@@ -45545,15 +45758,15 @@ import {
45545
45758
  statSync as statSync10,
45546
45759
  writeFileSync as writeFileSync7
45547
45760
  } from "fs";
45548
- import { basename as basename11, dirname as dirname20, isAbsolute as isAbsolute20, join as join30, normalize as normalize4, relative as relative7, resolve as resolve20, sep as sep9 } from "path";
45761
+ import { basename as basename11, dirname as dirname20, isAbsolute as isAbsolute20, join as join31, normalize as normalize4, relative as relative7, resolve as resolve20, sep as sep10 } from "path";
45549
45762
 
45550
45763
  // src/lib/registry-data/index.ts
45551
45764
  var SKILLS = [];
45552
45765
 
45553
45766
  // src/lib/skill-hash.ts
45554
- import { createHash as createHash23 } from "crypto";
45767
+ import { createHash as createHash24 } from "crypto";
45555
45768
  import { existsSync as existsSync8, readdirSync as readdirSync9, readFileSync as readFileSync17, statSync as statSync8 } from "fs";
45556
- import { join as join27, sep as sep7 } from "path";
45769
+ import { join as join28, sep as sep8 } from "path";
45557
45770
  var CONTENT_HASH_ALGORITHM = "sha256";
45558
45771
  var HASH_EXCLUDE_DIRS = new Set([".git", "node_modules", "dist", "build", ".turbo"]);
45559
45772
  function excludedHashEntry(name, directory) {
@@ -45615,7 +45828,7 @@ function collectBundleFiles(skillPath) {
45615
45828
  if (seen.has(entry))
45616
45829
  continue;
45617
45830
  seen.add(entry);
45618
- const absolute = join27(skillPath, entry);
45831
+ const absolute = join28(skillPath, entry);
45619
45832
  if (!existsSync8(absolute))
45620
45833
  continue;
45621
45834
  if (statSync8(absolute).isDirectory())
@@ -45629,7 +45842,7 @@ function collectDirectory(files, dir, rel) {
45629
45842
  for (const entry of readdirSync9(dir).sort()) {
45630
45843
  if (entry.startsWith("."))
45631
45844
  continue;
45632
- const absolute = join27(dir, entry);
45845
+ const absolute = join28(dir, entry);
45633
45846
  const childRel = `${rel}/${entry}`;
45634
45847
  let stats;
45635
45848
  try {
@@ -45650,7 +45863,7 @@ function collectDirectory(files, dir, rel) {
45650
45863
  }
45651
45864
  function collectFile(files, absolute, rel) {
45652
45865
  const buffer = readFileSync17(absolute);
45653
- files.push(normalizeBundleFile(rel.split(sep7).join("/"), buffer));
45866
+ files.push(normalizeBundleFile(rel.split(sep8).join("/"), buffer));
45654
45867
  }
45655
45868
  function normalizeBundleFile(rel, buffer) {
45656
45869
  if (rel === "skill.json") {
@@ -45675,13 +45888,13 @@ function* bundleHashParts(files) {
45675
45888
  yield new TextEncoder().encode("\x00");
45676
45889
  }
45677
45890
  function hashBundleFiles(files) {
45678
- const hash2 = createHash23(CONTENT_HASH_ALGORITHM);
45891
+ const hash2 = createHash24(CONTENT_HASH_ALGORITHM);
45679
45892
  for (const part of bundleHashParts(files))
45680
45893
  hash2.update(part);
45681
45894
  return hash2.digest("hex");
45682
45895
  }
45683
45896
  async function hashBundleFilesCooperatively(files, check) {
45684
- const hash2 = createHash23(CONTENT_HASH_ALGORITHM);
45897
+ const hash2 = createHash24(CONTENT_HASH_ALGORITHM);
45685
45898
  let bytesSinceYield = 0;
45686
45899
  for (const part of bundleHashParts(files)) {
45687
45900
  for (let offset = 0;offset < part.byteLength; offset += 64 * 1024) {
@@ -46070,7 +46283,7 @@ import {
46070
46283
  realpathSync as realpathSync11,
46071
46284
  writeFileSync as writeFileSync6
46072
46285
  } from "fs";
46073
- import { basename as basename9, dirname as dirname18, join as join28, relative as relative6 } from "path";
46286
+ import { basename as basename9, dirname as dirname18, join as join29, relative as relative6 } from "path";
46074
46287
  var ANY_SEGMENT_COPY_EXCLUDES = new Set([
46075
46288
  ".git",
46076
46289
  ".DS_Store",
@@ -46127,9 +46340,9 @@ function readPortableSkillManifestForImport(skillPath) {
46127
46340
  return readManifest(skillPath, basename9(skillPath), normalizeNewPortableSkillName);
46128
46341
  }
46129
46342
  function readManifest(skillPath, fallbackName, normalizeName) {
46130
- const skillJsonPath = join28(skillPath, "skill.json");
46131
- const skillMdPath = join28(skillPath, "SKILL.md");
46132
- const pkgPath = join28(skillPath, "package.json");
46343
+ const skillJsonPath = join29(skillPath, "skill.json");
46344
+ const skillMdPath = join29(skillPath, "SKILL.md");
46345
+ const pkgPath = join29(skillPath, "package.json");
46133
46346
  const jsonManifest = existsSync9(skillJsonPath) ? readJsonObject(skillJsonPath) : undefined;
46134
46347
  const frontmatter = existsSync9(skillMdPath) ? parseSkillFrontmatter(readFileSync18(skillMdPath, "utf-8")) ?? undefined : undefined;
46135
46348
  const pkg = existsSync9(pkgPath) ? readJsonObject(pkgPath) : undefined;
@@ -46161,9 +46374,9 @@ function parseSkillKind(value) {
46161
46374
  return;
46162
46375
  }
46163
46376
  function readDeclaredSkillVersion(skillPath) {
46164
- const skillJsonPath = join28(skillPath, "skill.json");
46165
- const skillMdPath = join28(skillPath, "SKILL.md");
46166
- const pkgPath = join28(skillPath, "package.json");
46377
+ const skillJsonPath = join29(skillPath, "skill.json");
46378
+ const skillMdPath = join29(skillPath, "SKILL.md");
46379
+ const pkgPath = join29(skillPath, "package.json");
46167
46380
  const jsonManifest = existsSync9(skillJsonPath) ? readJsonObject(skillJsonPath) : undefined;
46168
46381
  const frontmatter = existsSync9(skillMdPath) ? parseSkillFrontmatter(readFileSync18(skillMdPath, "utf-8")) ?? undefined : undefined;
46169
46382
  const pkg = existsSync9(pkgPath) ? readJsonObject(pkgPath) : undefined;
@@ -46187,7 +46400,7 @@ function createInstructionManifest(name, options) {
46187
46400
  }
46188
46401
  function writeInstructionSkillTemplate(skillPath, manifest) {
46189
46402
  mkdirSync7(skillPath, { recursive: true });
46190
- writeFileSync6(join28(skillPath, "SKILL.md"), renderInstructionSkillMd(manifest));
46403
+ writeFileSync6(join29(skillPath, "SKILL.md"), renderInstructionSkillMd(manifest));
46191
46404
  writeSkillJsonWithHash(skillPath, manifest);
46192
46405
  }
46193
46406
  function renderInstructionSkillMd(manifest) {
@@ -46237,12 +46450,12 @@ function createPortableManifest(name, options) {
46237
46450
  };
46238
46451
  }
46239
46452
  function writePortableSkillTemplate(skillPath, manifest) {
46240
- mkdirSync7(join28(skillPath, "src"), { recursive: true });
46241
- writeFileSync6(join28(skillPath, "SKILL.md"), renderSkillMd(manifest));
46242
- writeFileSync6(join28(skillPath, "AGENTS.md"), renderAgentsMd(manifest));
46243
- writeFileSync6(join28(skillPath, "package.json"), renderPackageJson(manifest));
46244
- writeFileSync6(join28(skillPath, "tsconfig.json"), renderTsconfig());
46245
- writeFileSync6(join28(skillPath, "src", "index.ts"), renderEntrypoint(manifest));
46453
+ mkdirSync7(join29(skillPath, "src"), { recursive: true });
46454
+ writeFileSync6(join29(skillPath, "SKILL.md"), renderSkillMd(manifest));
46455
+ writeFileSync6(join29(skillPath, "AGENTS.md"), renderAgentsMd(manifest));
46456
+ writeFileSync6(join29(skillPath, "package.json"), renderPackageJson(manifest));
46457
+ writeFileSync6(join29(skillPath, "tsconfig.json"), renderTsconfig());
46458
+ writeFileSync6(join29(skillPath, "src", "index.ts"), renderEntrypoint(manifest));
46246
46459
  writeSkillJsonWithHash(skillPath, manifest);
46247
46460
  }
46248
46461
  function fillContractDefaults(manifest, entrypoint) {
@@ -46267,7 +46480,7 @@ function writeSkillJsonWithHash(skillPath, manifest) {
46267
46480
  content_hash: undefined
46268
46481
  }
46269
46482
  };
46270
- writeFileSync6(join28(skillPath, "skill.json"), `${JSON.stringify({ ...existing, ...renderSkillJsonObject(withoutHash) }, null, 2)}
46483
+ writeFileSync6(join29(skillPath, "skill.json"), `${JSON.stringify({ ...existing, ...renderSkillJsonObject(withoutHash) }, null, 2)}
46271
46484
  `);
46272
46485
  const hash2 = computeContentHash(skillPath);
46273
46486
  const withHash = {
@@ -46277,12 +46490,12 @@ function writeSkillJsonWithHash(skillPath, manifest) {
46277
46490
  content_hash: hash2
46278
46491
  }
46279
46492
  };
46280
- writeFileSync6(join28(skillPath, "skill.json"), `${JSON.stringify({ ...existing, ...renderSkillJsonObject(withHash) }, null, 2)}
46493
+ writeFileSync6(join29(skillPath, "skill.json"), `${JSON.stringify({ ...existing, ...renderSkillJsonObject(withHash) }, null, 2)}
46281
46494
  `);
46282
46495
  return withHash;
46283
46496
  }
46284
46497
  function readExistingSkillJson(skillPath) {
46285
- const path = join28(skillPath, "skill.json");
46498
+ const path = join29(skillPath, "skill.json");
46286
46499
  if (!existsSync9(path))
46287
46500
  return {};
46288
46501
  try {
@@ -46316,24 +46529,24 @@ function ensurePortableSkillFiles(skillPath, manifest) {
46316
46529
  tags: next.tags?.length ? next.tags : ["custom", next.name]
46317
46530
  };
46318
46531
  const entry = next.commands[0]?.entry ?? "src/index.ts";
46319
- if (entry && !existsSync9(join28(skillPath, entry))) {
46320
- mkdirSync7(dirname18(join28(skillPath, entry)), { recursive: true });
46321
- writeFileSync6(join28(skillPath, entry), renderEntrypoint(next));
46532
+ if (entry && !existsSync9(join29(skillPath, entry))) {
46533
+ mkdirSync7(dirname18(join29(skillPath, entry)), { recursive: true });
46534
+ writeFileSync6(join29(skillPath, entry), renderEntrypoint(next));
46322
46535
  }
46323
- if (!existsSync9(join28(skillPath, "SKILL.md")))
46324
- writeFileSync6(join28(skillPath, "SKILL.md"), renderSkillMd(next));
46536
+ if (!existsSync9(join29(skillPath, "SKILL.md")))
46537
+ writeFileSync6(join29(skillPath, "SKILL.md"), renderSkillMd(next));
46325
46538
  else
46326
- writeFileSync6(join28(skillPath, "SKILL.md"), ensureSkillMdFrontmatter(readFileSync18(join28(skillPath, "SKILL.md"), "utf-8"), next));
46327
- if (!existsSync9(join28(skillPath, "AGENTS.md")))
46328
- writeFileSync6(join28(skillPath, "AGENTS.md"), renderAgentsMd(next));
46539
+ writeFileSync6(join29(skillPath, "SKILL.md"), ensureSkillMdFrontmatter(readFileSync18(join29(skillPath, "SKILL.md"), "utf-8"), next));
46540
+ if (!existsSync9(join29(skillPath, "AGENTS.md")))
46541
+ writeFileSync6(join29(skillPath, "AGENTS.md"), renderAgentsMd(next));
46329
46542
  ensurePackageJson(skillPath, next);
46330
- if (!existsSync9(join28(skillPath, "tsconfig.json")))
46331
- writeFileSync6(join28(skillPath, "tsconfig.json"), renderTsconfig());
46543
+ if (!existsSync9(join29(skillPath, "tsconfig.json")))
46544
+ writeFileSync6(join29(skillPath, "tsconfig.json"), renderTsconfig());
46332
46545
  writeSkillJsonWithHash(skillPath, next);
46333
46546
  return readPortableSkillManifest(skillPath, next.name);
46334
46547
  }
46335
46548
  function ensurePackageJson(skillPath, manifest) {
46336
- const pkgPath = join28(skillPath, "package.json");
46549
+ const pkgPath = join29(skillPath, "package.json");
46337
46550
  const first = manifest.commands[0] ?? { name: manifest.name, entry: "src/index.ts" };
46338
46551
  const commandName = normalizePortableSkillName(first.name || manifest.name);
46339
46552
  const entry = (first.entry ?? "src/index.ts").replace(/^\.\//, "");
@@ -46380,17 +46593,17 @@ function ensureInstructionSkillFiles(skillPath, manifest) {
46380
46593
  inputs: [],
46381
46594
  commands: []
46382
46595
  };
46383
- if (!existsSync9(join28(skillPath, "SKILL.md"))) {
46384
- writeFileSync6(join28(skillPath, "SKILL.md"), renderSkillMd(next));
46596
+ if (!existsSync9(join29(skillPath, "SKILL.md"))) {
46597
+ writeFileSync6(join29(skillPath, "SKILL.md"), renderSkillMd(next));
46385
46598
  } else {
46386
- const path = join28(skillPath, "SKILL.md");
46599
+ const path = join29(skillPath, "SKILL.md");
46387
46600
  const content = readFileSync18(path, "utf8");
46388
46601
  const declaredName = parseSkillFrontmatter(content)?.name;
46389
46602
  if (declaredName && declaredName !== next.name) {
46390
46603
  writeFileSync6(path, renameInstructionFrontmatter(content, next.name));
46391
46604
  }
46392
46605
  }
46393
- const packagePath = join28(skillPath, "package.json");
46606
+ const packagePath = join29(skillPath, "package.json");
46394
46607
  if (existsSync9(packagePath)) {
46395
46608
  const pkg = readJsonObject(packagePath);
46396
46609
  if (typeof pkg.name === "string" && pkg.name !== next.name) {
@@ -46716,10 +46929,10 @@ function escapeJsString(value) {
46716
46929
  // src/lib/authoring-path.ts
46717
46930
  import { lstatSync as lstatSync24, realpathSync as realpathSync12 } from "fs";
46718
46931
  import { homedir as homedir4 } from "os";
46719
- import { basename as basename10, dirname as dirname19, join as join29, resolve as resolve19, sep as sep8 } from "path";
46932
+ import { basename as basename10, dirname as dirname19, join as join30, resolve as resolve19, sep as sep9 } from "path";
46720
46933
  var NATIVE_DISCOVERY_ROOTS = NATIVE_SKILL_ROOTS.map(([, path]) => path.split("/"));
46721
46934
  function pathParts(path) {
46722
- return resolve19(path).split(sep8).filter(Boolean);
46935
+ return resolve19(path).split(sep9).filter(Boolean);
46723
46936
  }
46724
46937
  function nativeRootMatch(path) {
46725
46938
  const parts = pathParts(path);
@@ -46745,10 +46958,10 @@ function physicalPath(path) {
46745
46958
  return resolve19(realpathSync12(cursor), ...suffix);
46746
46959
  }
46747
46960
  function contains(root2, path) {
46748
- return path === root2 || path.startsWith(root2 + sep8);
46961
+ return path === root2 || path.startsWith(root2 + sep9);
46749
46962
  }
46750
46963
  function configuredRoots(home, explicitHome) {
46751
- const homeData = join29(home, ".hasna", "skills");
46964
+ const homeData = join30(home, ".hasna", "skills");
46752
46965
  const homePolicy = readManagedSkillPolicySnapshot(homeData);
46753
46966
  const configuredPolicy = !explicitHome && resolve19(getDataDirReadOnly()) !== resolve19(homeData) ? readManagedSkillPolicySnapshot(getDataDirReadOnly()) : null;
46754
46967
  const policy = homePolicy ?? configuredPolicy;
@@ -46779,7 +46992,7 @@ function configuredRoots(home, explicitHome) {
46779
46992
  admitBinding(binding);
46780
46993
  continue;
46781
46994
  }
46782
- const nativeHome = join29(home, agent === "opencode" ? ".config/opencode" : `.${agent}`);
46995
+ const nativeHome = join30(home, agent === "opencode" ? ".config/opencode" : `.${agent}`);
46783
46996
  if (!lstatSync24(nativeHome, { throwIfNoEntry: false }))
46784
46997
  continue;
46785
46998
  roots.push(...resolveAgentDiscovery({ home, agent, canonical: physicalPath }).roots);
@@ -46794,8 +47007,8 @@ function assertPortableAuthoringPath(path, options = {}) {
46794
47007
  const candidates = [lexical, physical];
46795
47008
  let native = candidates.map(nativeRootMatch).find(Boolean);
46796
47009
  const home = resolve19(options.homeDir ?? homedir4());
46797
- const defaults = NATIVE_DISCOVERY_ROOTS.map((parts) => join29(home, ...parts));
46798
- defaults.push(join29(home, ".codex/plugins/cache"), join29(home, ".claude/plugins/cache"), join29(home, ".claude/plugins/synced"), join29(home, ".gemini/extensions"));
47010
+ const defaults = NATIVE_DISCOVERY_ROOTS.map((parts) => join30(home, ...parts));
47011
+ defaults.push(join30(home, ".codex/plugins/cache"), join30(home, ".claude/plugins/cache"), join30(home, ".claude/plugins/synced"), join30(home, ".gemini/extensions"));
46799
47012
  for (const root2 of defaults) {
46800
47013
  if (candidates.some((candidate2) => contains(resolve19(root2), candidate2) || contains(physicalPath(root2), candidate2)))
46801
47014
  native ??= root2;
@@ -46816,15 +47029,15 @@ function getPortableSkillsRoot(options = {}) {
46816
47029
  function resolvePortableSkillsRoot(options, migrate) {
46817
47030
  if (options.rootDir)
46818
47031
  return options.rootDir;
46819
- const appDir = options.homeDir ? join30(options.homeDir, ".hasna", "skills") : migrate ? getDataDir() : getDataDirReadOnly();
46820
- const cache = join30(appDir, SKILLS_CACHE_DIRNAME);
47032
+ const appDir = options.homeDir ? join31(options.homeDir, ".hasna", "skills") : migrate ? getDataDir() : getDataDirReadOnly();
47033
+ const cache = join31(appDir, SKILLS_CACHE_DIRNAME);
46821
47034
  if (isOwnerLayoutMigrated(appDir) && safeIsDirectory(cache))
46822
47035
  return cache;
46823
- const installed = join30(appDir, INSTALLED_SKILLS_DIRNAME);
47036
+ const installed = join31(appDir, INSTALLED_SKILLS_DIRNAME);
46824
47037
  return installed;
46825
47038
  }
46826
47039
  function getPortableSkillPath(name, options = {}) {
46827
- return join30(getPortableSkillsRoot(options), normalizePortableSkillName(name));
47040
+ return join31(getPortableSkillsRoot(options), normalizePortableSkillName(name));
46828
47041
  }
46829
47042
  function findPortableSkill(name, options = {}) {
46830
47043
  let normalized;
@@ -46850,7 +47063,7 @@ function listPortableSkills(options = {}) {
46850
47063
  for (const entry of readdirSync10(root2).sort()) {
46851
47064
  if (entry.startsWith("."))
46852
47065
  continue;
46853
- const path = join30(root2, entry);
47066
+ const path = join31(root2, entry);
46854
47067
  if (!safeIsDirectory(path))
46855
47068
  continue;
46856
47069
  try {
@@ -46884,9 +47097,9 @@ function isOfficialSkillName(name) {
46884
47097
  function scaffoldPortableSkill(name, options = {}) {
46885
47098
  const skillName = normalizeNewPortableSkillName(name);
46886
47099
  const readOnlyRoot = resolvePortableSkillsRoot(options, false);
46887
- assertPortableAuthoringPath(join30(readOnlyRoot, skillName), options);
47100
+ assertPortableAuthoringPath(join31(readOnlyRoot, skillName), options);
46888
47101
  const root2 = getPortableSkillsRoot(options);
46889
- const skillPath = join30(root2, skillName);
47102
+ const skillPath = join31(root2, skillName);
46890
47103
  assertPortableAuthoringPath(skillPath, options);
46891
47104
  if (existsSync10(skillPath)) {
46892
47105
  if (!options.overwrite)
@@ -46920,7 +47133,7 @@ function portPortableSkillDirectory(sourceDir, options = {}) {
46920
47133
  const skipped = [];
46921
47134
  const entries = readdirSync10(absoluteSource, { withFileTypes: true }).map((entry) => entry.name).filter((entryName) => !entryName.startsWith(".")).sort();
46922
47135
  for (const entryName of entries) {
46923
- const childPath = join30(absoluteSource, entryName);
47136
+ const childPath = join31(absoluteSource, entryName);
46924
47137
  if (!safeIsDirectory(childPath))
46925
47138
  continue;
46926
47139
  if (!isSkillCandidate(childPath)) {
@@ -46949,7 +47162,7 @@ function portPortableSkillDirectory(sourceDir, options = {}) {
46949
47162
  };
46950
47163
  }
46951
47164
  function isSkillCandidate(dir) {
46952
- return existsSync10(join30(dir, "SKILL.md")) || existsSync10(join30(dir, "skill.json")) || existsSync10(join30(dir, "package.json"));
47165
+ return existsSync10(join31(dir, "SKILL.md")) || existsSync10(join31(dir, "skill.json")) || existsSync10(join31(dir, "package.json"));
46953
47166
  }
46954
47167
  function physicalImportPath(path) {
46955
47168
  let ancestor = resolve20(path);
@@ -46958,14 +47171,14 @@ function physicalImportPath(path) {
46958
47171
  suffix.unshift(basename11(ancestor));
46959
47172
  ancestor = dirname20(ancestor);
46960
47173
  }
46961
- return join30(realpathSync13(ancestor), ...suffix);
47174
+ return join31(realpathSync13(ancestor), ...suffix);
46962
47175
  }
46963
47176
  function assertDisjointImportPaths(source, destination) {
46964
47177
  const sourcePath = realpathSync13(source);
46965
47178
  const destinationPath = physicalImportPath(destination);
46966
47179
  const contains2 = (parent, child) => {
46967
47180
  const path = relative7(parent, child);
46968
- return path === "" || !isAbsolute20(path) && path !== ".." && !path.startsWith(`..${sep9}`);
47181
+ return path === "" || !isAbsolute20(path) && path !== ".." && !path.startsWith(`..${sep10}`);
46969
47182
  };
46970
47183
  if (contains2(sourcePath, destinationPath) || contains2(destinationPath, sourcePath)) {
46971
47184
  throw new Error("Source and destination skill directories must not overlap");
@@ -46984,11 +47197,11 @@ function portPortableSkill(sourcePath, options = {}) {
46984
47197
  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.`;
46985
47198
  throw new Error(`${via} Importing it would shadow the official '${skillName}'. ` + `Pass --name to choose a different name, or --allow-shadow to override deliberately.`);
46986
47199
  }
46987
- const readOnlyDestination = join30(resolvePortableSkillsRoot(options, false), skillName);
47200
+ const readOnlyDestination = join31(resolvePortableSkillsRoot(options, false), skillName);
46988
47201
  assertPortableAuthoringPath(readOnlyDestination, options);
46989
47202
  assertDisjointImportPaths(absoluteSource, readOnlyDestination);
46990
47203
  const root2 = getPortableSkillsRoot(options);
46991
- const destination = join30(root2, skillName);
47204
+ const destination = join31(root2, skillName);
46992
47205
  assertPortableAuthoringPath(destination, options);
46993
47206
  assertDisjointImportPaths(absoluteSource, destination);
46994
47207
  if (existsSync10(destination)) {
@@ -47033,13 +47246,13 @@ function buildCorpusManifest(input, name) {
47033
47246
  function writeCorpusSkill(input, options = {}) {
47034
47247
  const name = normalizePortableSkillName(input.name);
47035
47248
  const readOnlyRoot = resolvePortableSkillsRoot(options, false);
47036
- assertPortableAuthoringPath(join30(readOnlyRoot, name), options);
47249
+ assertPortableAuthoringPath(join31(readOnlyRoot, name), options);
47037
47250
  const root2 = getPortableSkillsRoot(options);
47038
- const skillPath = join30(root2, name);
47251
+ const skillPath = join31(root2, name);
47039
47252
  assertPortableAuthoringPath(skillPath, options);
47040
47253
  const created = !existsSync10(skillPath);
47041
47254
  mkdirSync8(skillPath, { recursive: true });
47042
- writeFileSync7(join30(skillPath, "SKILL.md"), input.skillMd);
47255
+ writeFileSync7(join31(skillPath, "SKILL.md"), input.skillMd);
47043
47256
  const manifest = buildCorpusManifest(input, name);
47044
47257
  writeSkillJsonWithHash(skillPath, manifest);
47045
47258
  return { name, path: skillPath, manifest, created };
@@ -47047,22 +47260,22 @@ function writeCorpusSkill(input, options = {}) {
47047
47260
  function installCorpusSkillAtomically(input, options = {}) {
47048
47261
  const name = normalizePortableSkillName(input.name);
47049
47262
  const readOnlyRoot = resolvePortableSkillsRoot(options, false);
47050
- assertPortableAuthoringPath(join30(readOnlyRoot, name), options);
47263
+ assertPortableAuthoringPath(join31(readOnlyRoot, name), options);
47051
47264
  const root2 = getPortableSkillsRoot(options);
47052
- const target = join30(root2, name);
47265
+ const target = join31(root2, name);
47053
47266
  assertPortableAuthoringPath(target, options);
47054
47267
  const created = !existsSync10(target);
47055
47268
  mkdirSync8(root2, { recursive: true });
47056
- const staging = mkdtempSync(join30(root2, `.pull-${name}-`));
47269
+ const staging = mkdtempSync(join31(root2, `.pull-${name}-`));
47057
47270
  let moved = false;
47058
47271
  let backup = null;
47059
47272
  try {
47060
- writeFileSync7(join30(staging, "SKILL.md"), input.skillMd);
47273
+ writeFileSync7(join31(staging, "SKILL.md"), input.skillMd);
47061
47274
  const manifest = buildCorpusManifest(input, name);
47062
47275
  writeSkillJsonWithHash(staging, manifest);
47063
47276
  if (existsSync10(target)) {
47064
- backup = mkdtempSync(join30(root2, `.pull-backup-${name}-`));
47065
- renameSync5(target, join30(backup, name));
47277
+ backup = mkdtempSync(join31(root2, `.pull-backup-${name}-`));
47278
+ renameSync5(target, join31(backup, name));
47066
47279
  moved = true;
47067
47280
  }
47068
47281
  renameSync5(staging, target);
@@ -47071,9 +47284,9 @@ function installCorpusSkillAtomically(input, options = {}) {
47071
47284
  return { name, path: target, manifest, created };
47072
47285
  } catch (error) {
47073
47286
  rmSync2(staging, { recursive: true, force: true });
47074
- if (moved && backup && existsSync10(join30(backup, name))) {
47287
+ if (moved && backup && existsSync10(join31(backup, name))) {
47075
47288
  try {
47076
- renameSync5(join30(backup, name), target);
47289
+ renameSync5(join31(backup, name), target);
47077
47290
  } catch {}
47078
47291
  }
47079
47292
  throw error;
@@ -47086,8 +47299,8 @@ function validatePortableSkillDirectory(name, skillPath) {
47086
47299
  const warnings = [...base.warnings];
47087
47300
  let manifest;
47088
47301
  if (existsSync10(skillPath)) {
47089
- const skillJsonPath = join30(skillPath, "skill.json");
47090
- const skillMdPath = join30(skillPath, "SKILL.md");
47302
+ const skillJsonPath = join31(skillPath, "skill.json");
47303
+ const skillMdPath = join31(skillPath, "SKILL.md");
47091
47304
  if (!existsSync10(skillJsonPath) && !existsSync10(skillMdPath)) {
47092
47305
  add3(issues, "portable.manifest_missing", "Missing portable manifest: expected SKILL.md frontmatter and/or skill.json");
47093
47306
  }
@@ -47107,7 +47320,7 @@ function validatePortableSkillDirectory(name, skillPath) {
47107
47320
  add3(issues, "portable.version_missing", "Portable manifest missing version");
47108
47321
  }
47109
47322
  const contractIssues = validatePortableManifestContract(manifest, {
47110
- strict: existsSync10(join30(skillPath, "skill.json")),
47323
+ strict: existsSync10(join31(skillPath, "skill.json")),
47111
47324
  skillPath
47112
47325
  });
47113
47326
  for (const issue of contractIssues)
@@ -47147,7 +47360,7 @@ function validatePortableSkillDirectory(name, skillPath) {
47147
47360
  add3(issues, "portable.command_entry_unsafe", `Command '${command.name}' entry '${command.entry}' must stay inside the skill directory`);
47148
47361
  continue;
47149
47362
  }
47150
- const entryPath = join30(skillPath, command.entry);
47363
+ const entryPath = join31(skillPath, command.entry);
47151
47364
  if (!existsSync10(entryPath))
47152
47365
  add3(issues, "portable.command_entry_missing", `Command '${command.name}' entry '${command.entry}' is missing`);
47153
47366
  else if (statSync10(entryPath).isDirectory())
@@ -47158,7 +47371,7 @@ function validatePortableSkillDirectory(name, skillPath) {
47158
47371
  } catch (error) {
47159
47372
  add3(issues, "portable.manifest_invalid", error.message);
47160
47373
  }
47161
- if (manifest?.kind !== "instruction" && !existsSync10(join30(skillPath, "AGENTS.md"))) {
47374
+ if (manifest?.kind !== "instruction" && !existsSync10(join31(skillPath, "AGENTS.md"))) {
47162
47375
  add3(issues, "portable.agents_missing", "Missing AGENTS.md with build-out instructions for coding agents");
47163
47376
  }
47164
47377
  }
@@ -47194,12 +47407,12 @@ async function runPortableSkill(name, args, options = {}) {
47194
47407
  if (!isSafeRelativePath2(command.entry)) {
47195
47408
  return { exitCode: 1, error: `Portable skill '${name}' command entry is unsafe` };
47196
47409
  }
47197
- const entryPath = join30(skill.path, command.entry);
47410
+ const entryPath = join31(skill.path, command.entry);
47198
47411
  if (!existsSync10(entryPath)) {
47199
47412
  return { exitCode: 1, error: `Entry point '${command.entry}' not found in portable skill '${name}'` };
47200
47413
  }
47201
- const pkgPath = join30(skill.path, "package.json");
47202
- const nodeModules = join30(skill.path, "node_modules");
47414
+ const pkgPath = join31(skill.path, "package.json");
47415
+ const nodeModules = join31(skill.path, "node_modules");
47203
47416
  if (existsSync10(pkgPath) && !existsSync10(nodeModules) && hasPackageDependencies(pkgPath)) {
47204
47417
  const install = Bun.spawn(["bun", "install", "--no-save"], {
47205
47418
  cwd: skill.path,
@@ -47271,7 +47484,7 @@ function isSkillsOwnershipMarker(marker) {
47271
47484
  return typeof marker === "object" && marker !== null && Object.hasOwn(marker, "managedBy") && marker.managedBy === SYNC_MARKER_MANAGED_BY;
47272
47485
  }
47273
47486
  function hasSkillsOwnershipMarker(dir) {
47274
- const path = join31(dir, SYNC_MARKER_FILE);
47487
+ const path = join32(dir, SYNC_MARKER_FILE);
47275
47488
  try {
47276
47489
  if (!lstatSync25(path).isFile())
47277
47490
  return false;
@@ -47295,9 +47508,9 @@ function resolveSyncAgents(arg) {
47295
47508
  function agentGlobalSkillsDir(agent, homeDir3 = homedir5()) {
47296
47509
  switch (agent) {
47297
47510
  case "opencode":
47298
- return join31(homeDir3, ".config", "opencode", "skills");
47511
+ return join32(homeDir3, ".config", "opencode", "skills");
47299
47512
  default:
47300
- return join31(homeDir3, `.${agent}`, "skills");
47513
+ return join32(homeDir3, `.${agent}`, "skills");
47301
47514
  }
47302
47515
  }
47303
47516
  function adaptSkillMdForAgent(skillMd, agent) {
@@ -47356,7 +47569,7 @@ function resolveSyncCorpus(options = {}) {
47356
47569
  function packageSourceRoots(source) {
47357
47570
  const roots = [];
47358
47571
  for (const sub of ["skills"]) {
47359
- const candidate2 = join31(source, sub);
47572
+ const candidate2 = join32(source, sub);
47360
47573
  if (existsSync11(candidate2) && isDirectory(candidate2))
47361
47574
  roots.push(candidate2);
47362
47575
  }
@@ -47372,10 +47585,10 @@ function containsSkillDirectories(path) {
47372
47585
  return false;
47373
47586
  }
47374
47587
  return entries.some((entry) => {
47375
- const candidate2 = join31(path, entry);
47588
+ const candidate2 = join32(path, entry);
47376
47589
  if (!isDirectory(candidate2))
47377
47590
  return false;
47378
- return existsSync11(join31(candidate2, "SKILL.md")) || existsSync11(join31(candidate2, "skill.json")) || existsSync11(join31(candidate2, "package.json"));
47591
+ return existsSync11(join32(candidate2, "SKILL.md")) || existsSync11(join32(candidate2, "skill.json")) || existsSync11(join32(candidate2, "package.json"));
47379
47592
  });
47380
47593
  }
47381
47594
  function isDirectory(path) {
@@ -47415,7 +47628,7 @@ function syncSkillsToAgents(options = {}) {
47415
47628
  actions.push({
47416
47629
  skill: name,
47417
47630
  agent,
47418
- path: join31(agentGlobalSkillsDir(agent, homeDir3), name, "SKILL.md"),
47631
+ path: join32(agentGlobalSkillsDir(agent, homeDir3), name, "SKILL.md"),
47419
47632
  action: "skip",
47420
47633
  reason: "not found in this machine's corpus"
47421
47634
  });
@@ -47447,7 +47660,7 @@ function syncSkillsToAgents(options = {}) {
47447
47660
  }
47448
47661
  function writeManagedAgentSkill(params) {
47449
47662
  const homeDir3 = params.homeDir ?? homedir5();
47450
- const dir = join31(agentGlobalSkillsDir(params.agent, homeDir3), params.skill);
47663
+ const dir = join32(agentGlobalSkillsDir(params.agent, homeDir3), params.skill);
47451
47664
  const result = writeManagedSkillDir(dir, params.skillMd, {
47452
47665
  skill: params.skill,
47453
47666
  source: params.source,
@@ -47470,8 +47683,8 @@ function writeManagedSkillDir(dir, skillMd, options) {
47470
47683
  return withCodexCorpusWrite(root2 ? [root2] : [], (assertCurrent) => writeManagedSkillDirUnlocked(dir, skillMd, options, assertCurrent), options);
47471
47684
  }
47472
47685
  function writeManagedSkillDirUnlocked(dir, skillMd, options, assertCurrent) {
47473
- const skillMdPath = join31(dir, "SKILL.md");
47474
- const markerPath = join31(dir, SYNC_MARKER_FILE);
47686
+ const skillMdPath = join32(dir, "SKILL.md");
47687
+ const markerPath = join32(dir, SYNC_MARKER_FILE);
47475
47688
  const dirExists = existsSync11(dir);
47476
47689
  const managed = hasSkillsOwnershipMarker(dir);
47477
47690
  const hasSkillMd = existsSync11(skillMdPath);
@@ -47509,11 +47722,11 @@ function writeManagedSkillDirUnlocked(dir, skillMd, options, assertCurrent) {
47509
47722
  return { action, path: skillMdPath };
47510
47723
  const parentDir = dirname21(dir);
47511
47724
  mkdirSync9(parentDir, { recursive: true });
47512
- const transactionDir = mkdtempSync2(join31(parentDir, `.hasna-skills-write-${basename12(dir)}-`));
47513
- const candidateDir = join31(transactionDir, "candidate");
47514
- const backupDir = join31(transactionDir, "backup");
47515
- const candidateSkillMdPath = join31(candidateDir, "SKILL.md");
47516
- const candidateMarkerPath = join31(candidateDir, SYNC_MARKER_FILE);
47725
+ const transactionDir = mkdtempSync2(join32(parentDir, `.hasna-skills-write-${basename12(dir)}-`));
47726
+ const candidateDir = join32(transactionDir, "candidate");
47727
+ const backupDir = join32(transactionDir, "backup");
47728
+ const candidateSkillMdPath = join32(candidateDir, "SKILL.md");
47729
+ const candidateMarkerPath = join32(candidateDir, SYNC_MARKER_FILE);
47517
47730
  const marker = {
47518
47731
  managedBy: SYNC_MARKER_MANAGED_BY,
47519
47732
  skill: options.skill,
@@ -47571,12 +47784,12 @@ function writeManagedSkillDirUnlocked(dir, skillMd, options, assertCurrent) {
47571
47784
  return { action, path: skillMdPath };
47572
47785
  }
47573
47786
  function removeManagedAgentSkill(skill, agent, homeDir3 = homedir5(), options = {}) {
47574
- const dir = join31(agentGlobalSkillsDir(agent, homeDir3), skill);
47787
+ const dir = join32(agentGlobalSkillsDir(agent, homeDir3), skill);
47575
47788
  const root2 = codexCorpusRootForPath(dir);
47576
47789
  return withCodexCorpusWrite(root2 ? [root2] : [], () => removeManagedAgentSkillUnlocked(skill, agent, homeDir3, options), options);
47577
47790
  }
47578
47791
  function removeManagedAgentSkillUnlocked(skill, agent, homeDir3 = homedir5(), options = {}) {
47579
- const dir = join31(agentGlobalSkillsDir(agent, homeDir3), skill);
47792
+ const dir = join32(agentGlobalSkillsDir(agent, homeDir3), skill);
47580
47793
  if (!hasSkillsOwnershipMarker(dir))
47581
47794
  return false;
47582
47795
  rmSync3(dir, { recursive: true, force: true });
@@ -47584,7 +47797,7 @@ function removeManagedAgentSkillUnlocked(skill, agent, homeDir3 = homedir5(), op
47584
47797
  }
47585
47798
  function sourceSkillMd(skillPath, name, description, kind, preferBundledDocs = false) {
47586
47799
  if (kind === undefined || kind === "instruction" || preferBundledDocs) {
47587
- const skillMdPath = join31(skillPath, "SKILL.md");
47800
+ const skillMdPath = join32(skillPath, "SKILL.md");
47588
47801
  if (existsSync11(skillMdPath))
47589
47802
  return readFileSync19(skillMdPath, "utf-8");
47590
47803
  }
@@ -47617,7 +47830,7 @@ function normalizeSkillName(name) {
47617
47830
 
47618
47831
  // src/lib/registry.ts
47619
47832
  import { existsSync as existsSync12, readFileSync as readFileSync20, readdirSync as readdirSync12 } from "fs";
47620
- import { join as join32 } from "path";
47833
+ import { join as join33 } from "path";
47621
47834
 
47622
47835
  // src/lib/registry-merge.ts
47623
47836
  var SKILL_SOURCE_PRECEDENCE = {
@@ -47827,7 +48040,7 @@ function discoverSkillsInDir(dir, source = "custom") {
47827
48040
  for (const entry of entries) {
47828
48041
  if (!entry.isDirectory())
47829
48042
  continue;
47830
- const skillMdPath = join32(dir, entry.name, "SKILL.md");
48043
+ const skillMdPath = join33(dir, entry.name, "SKILL.md");
47831
48044
  if (!existsSync12(skillMdPath))
47832
48045
  continue;
47833
48046
  let content;
@@ -47847,7 +48060,7 @@ function discoverSkillsInDir(dir, source = "custom") {
47847
48060
  category: fm.category || "Development Tools",
47848
48061
  tags: fm.tags || [],
47849
48062
  ...fm.kind ? { kind: fm.kind } : {},
47850
- ...isHostedMetadataSkillDir(join32(dir, entry.name)) ? { serverOwned: true } : {},
48063
+ ...isHostedMetadataSkillDir(join33(dir, entry.name)) ? { serverOwned: true } : {},
47851
48064
  source
47852
48065
  });
47853
48066
  }
@@ -47863,8 +48076,8 @@ function findExtensionSkillPath(name) {
47863
48076
  for (const entry of entries) {
47864
48077
  if (!entry.isDirectory())
47865
48078
  continue;
47866
- const skillDir = join32(config.extensionsDir, entry.name);
47867
- const skillMdPath = join32(skillDir, "SKILL.md");
48079
+ const skillDir = join33(config.extensionsDir, entry.name);
48080
+ const skillMdPath = join33(skillDir, "SKILL.md");
47868
48081
  if (!existsSync12(skillMdPath))
47869
48082
  continue;
47870
48083
  let content;
@@ -47935,7 +48148,7 @@ function getAllTags(catalog) {
47935
48148
 
47936
48149
  // src/lib/project-state.ts
47937
48150
  import { existsSync as existsSync13, mkdirSync as mkdirSync10, readFileSync as readFileSync21, writeFileSync as writeFileSync9 } from "fs";
47938
- import { join as join33 } from "path";
48151
+ import { join as join34 } from "path";
47939
48152
  var VALID_PIN_SOURCES = [
47940
48153
  "official",
47941
48154
  "custom",
@@ -47950,10 +48163,10 @@ var SKILLS_PROJECT_DIR = ".skills";
47950
48163
  var PROJECT_CONFIG_FILE = "project.json";
47951
48164
  var DEFAULT_EXPORT_DIR = ".skills/exports";
47952
48165
  function getProjectStateDir(targetDir = process.cwd()) {
47953
- return join33(targetDir, SKILLS_PROJECT_DIR);
48166
+ return join34(targetDir, SKILLS_PROJECT_DIR);
47954
48167
  }
47955
48168
  function getProjectConfigPath(targetDir = process.cwd()) {
47956
- return join33(getProjectStateDir(targetDir), PROJECT_CONFIG_FILE);
48169
+ return join34(getProjectStateDir(targetDir), PROJECT_CONFIG_FILE);
47957
48170
  }
47958
48171
  function loadProjectConfig(targetDir = process.cwd()) {
47959
48172
  const path = getProjectConfigPath(targetDir);
@@ -48082,7 +48295,7 @@ function getSkillPath(name) {
48082
48295
  const extensionPath = findExtensionSkillPath(skillName);
48083
48296
  if (extensionPath)
48084
48297
  return extensionPath;
48085
- return join34(getPortableSkillsRoot(), skillName);
48298
+ return join35(getPortableSkillsRoot(), skillName);
48086
48299
  }
48087
48300
  function getCanonicalSkillName(name) {
48088
48301
  return getSkill(name)?.name ?? resolveSkillAlias(normalizeSkillSlug(name));
@@ -48145,7 +48358,7 @@ function createLocalSkillManifest(name, generateSkillMd) {
48145
48358
  if (!existsSync14(sourcePath))
48146
48359
  return null;
48147
48360
  let skillMd = "";
48148
- const skillMdPath = join34(sourcePath, "SKILL.md");
48361
+ const skillMdPath = join35(sourcePath, "SKILL.md");
48149
48362
  if (existsSync14(skillMdPath)) {
48150
48363
  skillMd = readFileSync22(skillMdPath, "utf-8");
48151
48364
  } else if (generateSkillMd) {
@@ -48219,16 +48432,16 @@ function getAgentSkillsDir(agent, scope = "global", projectDir) {
48219
48432
  const base = projectDir || process.cwd();
48220
48433
  switch (agent) {
48221
48434
  case "pi":
48222
- return scope === "project" ? join34(base, ".pi", "skills") : join34(homedir6(), ".pi", "agent", "skills");
48435
+ return scope === "project" ? join35(base, ".pi", "skills") : join35(homedir6(), ".pi", "agent", "skills");
48223
48436
  case "opencode":
48224
- return scope === "project" ? join34(base, ".opencode", "skills") : join34(homedir6(), ".config", "opencode", "skills");
48437
+ return scope === "project" ? join35(base, ".opencode", "skills") : join35(homedir6(), ".config", "opencode", "skills");
48225
48438
  default:
48226
- return scope === "project" ? join34(base, `.${agent}`, "skills") : join34(homedir6(), `.${agent}`, "skills");
48439
+ return scope === "project" ? join35(base, `.${agent}`, "skills") : join35(homedir6(), `.${agent}`, "skills");
48227
48440
  }
48228
48441
  }
48229
48442
  function getAgentSkillPath(name, agent, scope = "global", projectDir) {
48230
48443
  const skillName = normalizeSkillName(getCanonicalSkillName(name));
48231
- return join34(getAgentSkillsDir(agent, scope, projectDir), skillName);
48444
+ return join35(getAgentSkillsDir(agent, scope, projectDir), skillName);
48232
48445
  }
48233
48446
  function installSkillForAgent(name, options, generateSkillMd) {
48234
48447
  assertNativeExportAllowed();
@@ -48271,7 +48484,7 @@ function removeSkillForAgentUnlocked(name, options) {
48271
48484
  }
48272
48485
  function resolveAgentSkillMd(name, generateSkillMd) {
48273
48486
  const sourcePath = getSkillPath(name);
48274
- const skillMdPath = join34(sourcePath, "SKILL.md");
48487
+ const skillMdPath = join35(sourcePath, "SKILL.md");
48275
48488
  if (existsSync14(skillMdPath))
48276
48489
  return readFileSync22(skillMdPath, "utf-8");
48277
48490
  if (generateSkillMd)
@@ -48306,7 +48519,7 @@ function generateMinimalSkillMd(name) {
48306
48519
  "---",
48307
48520
  ""
48308
48521
  ].filter(Boolean);
48309
- const fallbackDoc = readFileIfExists(join34(sourcePath, "README.md")) || readFileIfExists(join34(sourcePath, "CLAUDE.md"));
48522
+ const fallbackDoc = readFileIfExists(join35(sourcePath, "README.md")) || readFileIfExists(join35(sourcePath, "CLAUDE.md"));
48310
48523
  if (fallbackDoc)
48311
48524
  return `${frontmatter.join(`
48312
48525
  `)}${fallbackDoc.trim()}
@@ -48325,7 +48538,7 @@ skills run ${canonicalName}
48325
48538
  `;
48326
48539
  }
48327
48540
  function readBundledSkillVersion(name) {
48328
- const pkgPath = join34(getSkillPath(name), "package.json");
48541
+ const pkgPath = join35(getSkillPath(name), "package.json");
48329
48542
  if (!existsSync14(pkgPath))
48330
48543
  return "unknown";
48331
48544
  try {
@@ -48380,7 +48593,7 @@ function selectSkillDoc(docs, file) {
48380
48593
  function isInstructionSkillDir(skillPath, meta) {
48381
48594
  if (meta?.kind === "instruction")
48382
48595
  return true;
48383
- const skillMdPath = join35(skillPath, "SKILL.md");
48596
+ const skillMdPath = join36(skillPath, "SKILL.md");
48384
48597
  if (!existsSync15(skillMdPath))
48385
48598
  return false;
48386
48599
  try {
@@ -48410,9 +48623,9 @@ function getSkillDocs(name) {
48410
48623
  if (!existsSync15(skillPath))
48411
48624
  return null;
48412
48625
  return {
48413
- skillMd: readIfExists(join35(skillPath, "SKILL.md")),
48414
- readme: readIfExists(join35(skillPath, "README.md")),
48415
- claudeMd: readIfExists(join35(skillPath, "CLAUDE.md"))
48626
+ skillMd: readIfExists(join36(skillPath, "SKILL.md")),
48627
+ readme: readIfExists(join36(skillPath, "README.md")),
48628
+ claudeMd: readIfExists(join36(skillPath, "CLAUDE.md"))
48416
48629
  };
48417
48630
  }
48418
48631
  function getSkillBestDoc(name, file) {
@@ -48428,14 +48641,14 @@ function getSkillRequirements(name) {
48428
48641
  return null;
48429
48642
  const texts = [];
48430
48643
  for (const file of ["SKILL.md", "README.md", "CLAUDE.md", ".env.example", ".env.local.example"]) {
48431
- const content = readIfExists(join35(skillPath, file));
48644
+ const content = readIfExists(join36(skillPath, file));
48432
48645
  if (content)
48433
48646
  texts.push(content);
48434
48647
  }
48435
48648
  const meta = getSkill(name);
48436
48649
  let dependencies = {};
48437
48650
  try {
48438
- dependencies = JSON.parse(readFileSync23(join35(skillPath, "package.json"), "utf8")).dependencies || {};
48651
+ dependencies = JSON.parse(readFileSync23(join36(skillPath, "package.json"), "utf8")).dependencies || {};
48439
48652
  } catch {}
48440
48653
  return getSkillRequirementsFromContent(name, texts, dependencies, meta);
48441
48654
  }
@@ -48497,7 +48710,7 @@ async function runSkill(name, args, options = {}) {
48497
48710
  error: `Skill '${name}' is an instruction skill (kind: instruction) and is not runnable. Instruction skills are consumed by coding agents via SKILL.md, not executed with 'skills run'.`
48498
48711
  };
48499
48712
  }
48500
- const pkgPath = join35(skillPath, "package.json");
48713
+ const pkgPath = join36(skillPath, "package.json");
48501
48714
  if (!existsSync15(pkgPath)) {
48502
48715
  return { exitCode: 1, error: `No package.json in skill '${name}'` };
48503
48716
  }
@@ -48517,12 +48730,12 @@ async function runSkill(name, args, options = {}) {
48517
48730
  } catch {
48518
48731
  return { exitCode: 1, error: `Failed to parse package.json for skill '${name}'` };
48519
48732
  }
48520
- const entryPath = join35(skillPath, entryPoint2);
48733
+ const entryPath = join36(skillPath, entryPoint2);
48521
48734
  if (!existsSync15(entryPath)) {
48522
48735
  return { exitCode: 1, error: `Entry point '${entryPoint2}' not found in skill '${name}'` };
48523
48736
  }
48524
48737
  const env = { ...process.env, ...options.env };
48525
- if (!existsSync15(join35(skillPath, "node_modules")) || hasDependencyPreparationMarker(skillPath)) {
48738
+ if (!existsSync15(join36(skillPath, "node_modules")) || hasDependencyPreparationMarker(skillPath)) {
48526
48739
  const failure = await prepareSkillDependencies(skillPath, env, options.preparationTimeoutMs);
48527
48740
  if (failure)
48528
48741
  return failure;
@@ -48600,10 +48813,10 @@ function generateSkillMd(name) {
48600
48813
  "---"
48601
48814
  ].join(`
48602
48815
  `);
48603
- const readme = readIfExists(join35(skillPath, "README.md"));
48604
- const claudeMd = readIfExists(join35(skillPath, "CLAUDE.md"));
48816
+ const readme = readIfExists(join36(skillPath, "README.md"));
48817
+ const claudeMd = readIfExists(join36(skillPath, "CLAUDE.md"));
48605
48818
  let cliCommand = null;
48606
- const pkgPath = join35(skillPath, "package.json");
48819
+ const pkgPath = join36(skillPath, "package.json");
48607
48820
  if (existsSync15(pkgPath)) {
48608
48821
  try {
48609
48822
  const pkg = JSON.parse(readFileSync23(pkgPath, "utf-8"));
@@ -48887,7 +49100,7 @@ async function executeSelectedLocal(selected, options = {}) {
48887
49100
  throw new SkillSelectionError("INVALID_SECRET_BINDINGS", "Explicit environment values must be bounded strings without NUL bytes.");
48888
49101
  secretEnv[name] = value;
48889
49102
  }
48890
- const runDirectory = mkdtempSync3(join36(tmpdir(), "skills-execution-"));
49103
+ const runDirectory = mkdtempSync3(join37(tmpdir(), "skills-execution-"));
48891
49104
  const paths = new SkillEntryPaths;
48892
49105
  for (const entry of entries) {
48893
49106
  paths.add(entry.path, 100, () => {
@@ -48895,7 +49108,7 @@ async function executeSelectedLocal(selected, options = {}) {
48895
49108
  }, () => {
48896
49109
  throw new SkillSelectionError("INVALID_BUNDLE_PATH", "The execution bundle path exceeds its limit.");
48897
49110
  });
48898
- const destination = join36(runDirectory, entry.path);
49111
+ const destination = join37(runDirectory, entry.path);
48899
49112
  mkdirSync11(dirname22(destination), { recursive: true, mode: 448 });
48900
49113
  writeFileSync10(destination, entry.bytes, { flag: "wx", mode: entry.mode & 511 });
48901
49114
  }
@@ -48923,20 +49136,20 @@ async function executeSelectedLocal(selected, options = {}) {
48923
49136
  }
48924
49137
  if (bindings)
48925
49138
  secretEnv = await resolveSelectedSecrets(bindings, options.createSecretsClient);
48926
- const result = await subprocess([executable2, ...runtimeName === "bun" ? ["--no-env-file"] : [], join36(runDirectory, declaredEntry), ...args], runDirectory, { ...env, ...secretEnv }, input, timeoutMs);
49139
+ const result = await subprocess([executable2, ...runtimeName === "bun" ? ["--no-env-file"] : [], join37(runDirectory, declaredEntry), ...args], runDirectory, { ...env, ...secretEnv }, input, timeoutMs);
48927
49140
  result.stdout = redactExecutionSecrets(result.stdout, secretEnv);
48928
49141
  result.stderr = redactExecutionSecrets(result.stderr, secretEnv);
48929
49142
  const receipt = {
48930
49143
  selection: selection2,
48931
49144
  target: "local",
48932
49145
  runtime: runtimeName,
48933
- inputDigest: `sha256:${createHash24("sha256").update(input).digest("hex")}`,
49146
+ inputDigest: `sha256:${createHash25("sha256").update(input).digest("hex")}`,
48934
49147
  runDirectory,
48935
49148
  ...executionGrant ? { executionGrant } : {},
48936
49149
  ...bindings ? { secretBinding: { schema: bindings.schema, selection: bindings.selection, consumer: bindings.consumer, secretsAuthority: bindings.secretsAuthority, bindings: bindings.bindings } } : {},
48937
49150
  ...result
48938
49151
  };
48939
- writeFileSync10(join36(runDirectory, ".execution-receipt.json"), JSON.stringify({ ...receipt, stdout: undefined, stderr: undefined }), { mode: 384 });
49152
+ writeFileSync10(join37(runDirectory, ".execution-receipt.json"), JSON.stringify({ ...receipt, stdout: undefined, stderr: undefined }), { mode: 384 });
48940
49153
  return receipt;
48941
49154
  }
48942
49155
  async function subprocess(command, cwd, env, input, timeoutMs) {
@@ -49456,7 +49669,7 @@ var { booleanSelector, SelectorType: SelectorType2 } = require_config();
49456
49669
  var { setFeature: setFeature2 } = require_client2();
49457
49670
  var { httpSigningMiddlewareOptions } = require_dist_cjs2();
49458
49671
  var { Readable } = __require("stream");
49459
- var { validate, parse: parse7 } = require_util();
49672
+ var { validate, parse: parse8 } = require_util();
49460
49673
  var { AwsRestXmlProtocol } = require_protocols2();
49461
49674
  var { NormalizedSchema } = require_schema4();
49462
49675
  var CONTENT_LENGTH_HEADER = "content-length";
@@ -58220,7 +58433,7 @@ var import_node_http_handler2 = __toESM(require_dist_cjs6(), 1);
58220
58433
 
58221
58434
  // node_modules/@aws-sdk/checksums/dist-cjs/submodules/sha/index.js
58222
58435
  var { toUint8Array: toUint8Array2, concatBytes } = require_serde();
58223
- var { createHmac: createHmac2, createHash: createHash26 } = __require("crypto");
58436
+ var { createHmac: createHmac2, createHash: createHash27 } = __require("crypto");
58224
58437
  var { Sha256: Sha2562, Sha256Js, Sha256Node } = require_checksum();
58225
58438
  var BLOCK2 = 64;
58226
58439
  var DIGEST_LENGTH = 20;
@@ -58389,7 +58602,7 @@ class Sha1Js {
58389
58602
  }
58390
58603
  var hasNativeCrypto = (() => {
58391
58604
  try {
58392
- createHash26("sha1");
58605
+ createHash27("sha1");
58393
58606
  return true;
58394
58607
  } catch {
58395
58608
  return false;
@@ -58429,7 +58642,7 @@ function buildNativeClass() {
58429
58642
  this.finished = false;
58430
58643
  }
58431
58644
  createHash() {
58432
- return this.secret ? createHmac2("sha1", toBuffer(this.secret)) : createHash26("sha1");
58645
+ return this.secret ? createHmac2("sha1", toBuffer(this.secret)) : createHash27("sha1");
58433
58646
  }
58434
58647
  };
58435
58648
  }
@@ -59001,7 +59214,7 @@ import { mkdirSync as mkdirSync13 } from "fs";
59001
59214
  import { dirname as dirname26 } from "path";
59002
59215
 
59003
59216
  // src/server/database-url.ts
59004
- import { isAbsolute as isAbsolute21, join as join38 } from "path";
59217
+ import { isAbsolute as isAbsolute21, join as join39 } from "path";
59005
59218
  import { fileURLToPath as fileURLToPath3 } from "url";
59006
59219
  var DEFAULT_SQLITE_FILENAME2 = "server.db";
59007
59220
  var SQLITE_MEMORY_PATH = ":memory:";
@@ -59010,7 +59223,7 @@ var SQLITE_SCHEMES = new Set(["sqlite", "sqlite3", "file"]);
59010
59223
  var MEMORY_SCHEMES = new Set(["memory"]);
59011
59224
  var SQLITE_EXTENSIONS = [".db", ".sqlite", ".sqlite3", ".db3"];
59012
59225
  function defaultSqlitePath() {
59013
- return join38(getDataDir(), DEFAULT_SQLITE_FILENAME2);
59226
+ return join39(getDataDir(), DEFAULT_SQLITE_FILENAME2);
59014
59227
  }
59015
59228
  function resolveDatabaseTarget(raw) {
59016
59229
  const value = raw?.trim();
@@ -59037,7 +59250,7 @@ function resolveDatabaseTarget(raw) {
59037
59250
  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()}.`);
59038
59251
  }
59039
59252
  if (looksLikeSqlitePath(value)) {
59040
- const path = isAbsolute21(value) ? value : join38(process.cwd(), value);
59253
+ const path = isAbsolute21(value) ? value : join39(process.cwd(), value);
59041
59254
  return { kind: "sqlite", path, durable: true, label: `sqlite (${path})` };
59042
59255
  }
59043
59256
  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()}.`);
@@ -59061,7 +59274,7 @@ function sqlitePathFromUrl(value, scheme) {
59061
59274
  }
59062
59275
  return rest.slice(2).replace(/^\/\/+/, "/");
59063
59276
  }
59064
- return isAbsolute21(rest) ? rest : join38(process.cwd(), rest);
59277
+ return isAbsolute21(rest) ? rest : join39(process.cwd(), rest);
59065
59278
  }
59066
59279
  function looksLikeSqlitePath(value) {
59067
59280
  if (value.includes("/"))
@@ -59294,12 +59507,12 @@ class PostgresSkillSelectionStore {
59294
59507
  // src/server/sqlite-store.ts
59295
59508
  import { randomUUID as randomUUID8 } from "crypto";
59296
59509
  import { mkdirSync as mkdirSync12, readFileSync as readFileSync25, readdirSync as readdirSync13 } from "fs";
59297
- import { dirname as dirname25, join as join40 } from "path";
59510
+ import { dirname as dirname25, join as join41 } from "path";
59298
59511
 
59299
59512
  // src/server/auth.ts
59300
- import { createHash as createHash27 } from "crypto";
59513
+ import { createHash as createHash28 } from "crypto";
59301
59514
  function hashApiKey(token) {
59302
- return createHash27("sha256").update(token).digest("hex");
59515
+ return createHash28("sha256").update(token).digest("hex");
59303
59516
  }
59304
59517
  function bearerToken(request2) {
59305
59518
  const header = request2.headers.get("authorization") || "";
@@ -59353,15 +59566,15 @@ function permitsSkillsRoute(principal, method, resource) {
59353
59566
 
59354
59567
  // src/server/migrations-dir.ts
59355
59568
  import { existsSync as existsSync16 } from "fs";
59356
- import { dirname as dirname24, join as join39 } from "path";
59569
+ import { dirname as dirname24, join as join40 } from "path";
59357
59570
  var MIGRATION_DIALECTS = ["postgres", "sqlite"];
59358
59571
  var MAX_WALK_UP = 6;
59359
59572
  function findMigrationsRoot(startDirs = defaultStartDirs()) {
59360
59573
  for (const start of startDirs) {
59361
59574
  let dir = start;
59362
59575
  for (let level = 0;level < MAX_WALK_UP; level += 1) {
59363
- const candidate2 = join39(dir, "migrations");
59364
- if (MIGRATION_DIALECTS.some((dialect) => existsSync16(join39(candidate2, dialect))))
59576
+ const candidate2 = join40(dir, "migrations");
59577
+ if (MIGRATION_DIALECTS.some((dialect) => existsSync16(join40(candidate2, dialect))))
59365
59578
  return candidate2;
59366
59579
  const parent = dirname24(dir);
59367
59580
  if (parent === dir)
@@ -59375,7 +59588,7 @@ function resolveMigrationsDir(dialect, root4 = findMigrationsRoot()) {
59375
59588
  if (!root4) {
59376
59589
  throw new Error(`could not locate the migrations directory for dialect "${dialect}". ` + `Expected a migrations/${dialect}/ folder alongside the package root.`);
59377
59590
  }
59378
- const dir = join39(root4, dialect);
59591
+ const dir = join40(root4, dialect);
59379
59592
  if (!existsSync16(dir)) {
59380
59593
  throw new Error(`migrations directory not found: ${dir}`);
59381
59594
  }
@@ -59471,6 +59684,7 @@ function rowToSkill(row) {
59471
59684
  revisionNumber: Number(row.revision_number ?? 0),
59472
59685
  ...row.tombstoned_at ? { tombstonedAt: dateString(row.tombstoned_at) } : {},
59473
59686
  ...row.tombstone_purge_after ? { tombstonePurgeAfter: dateString(row.tombstone_purge_after) } : {},
59687
+ ...typeof row.authorization_epoch === "string" ? { authorizationEpoch: row.authorization_epoch } : {},
59474
59688
  lifecycle: row.lifecycle === "archived" ? "archived" : "active",
59475
59689
  ...row.archived_at ? { archivedAt: dateString(row.archived_at) } : {},
59476
59690
  ...row.archive_reason ? { archiveReason: String(row.archive_reason) } : {},
@@ -59482,6 +59696,7 @@ function rowToPublishedSelectionState(row) {
59482
59696
  slug: String(row.slug),
59483
59697
  version: String(row.version),
59484
59698
  current: row.skill_exists ? {
59699
+ ...typeof row.authorization_epoch === "string" ? { authorizationEpoch: row.authorization_epoch } : {},
59485
59700
  lifecycle: row.lifecycle === "archived" ? "archived" : "active",
59486
59701
  ...row.tombstoned_at ? { tombstonedAt: dateString(row.tombstoned_at) } : {}
59487
59702
  } : null,
@@ -59621,7 +59836,7 @@ function validOperatorScopeEnrollmentInput(input) {
59621
59836
  }
59622
59837
 
59623
59838
  // src/lib/revision.ts
59624
- import { createHash as createHash28 } from "crypto";
59839
+ import { createHash as createHash29 } from "crypto";
59625
59840
  var REVISION_ID_PATTERN = /^[0-9a-f]{64}$/;
59626
59841
  function revisionIdOf(content) {
59627
59842
  const canonicalContent = {
@@ -59642,8 +59857,8 @@ function revisionIdOf(content) {
59642
59857
  canonicalContent.archiveReason = content.archiveReason ?? null;
59643
59858
  canonicalContent.replacementSlug = content.replacementSlug ?? null;
59644
59859
  }
59645
- const canonical6 = JSON.stringify(canonicalContent);
59646
- return createHash28("sha256").update(canonical6).digest("hex");
59860
+ const canonical7 = JSON.stringify(canonicalContent);
59861
+ return createHash29("sha256").update(canonical7).digest("hex");
59647
59862
  }
59648
59863
  function revisionIdOfRecord(record4) {
59649
59864
  return revisionIdOf(record4);
@@ -60125,7 +60340,7 @@ class SqliteSkillsStore {
60125
60340
  continue;
60126
60341
  insertTag.run(orgId, input.slug, tag);
60127
60342
  }
60128
- return rowToSkill(row);
60343
+ return this.getSkillSync(input.principal, input.slug);
60129
60344
  })();
60130
60345
  }
60131
60346
  async listSkills(principal) {
@@ -60162,7 +60377,7 @@ class SqliteSkillsStore {
60162
60377
  const row = this.get("UPDATE skills_registry SET lifecycle=?, archived_at=?, archive_reason=?, replacement_slug=?, revision_id=?, revision_number=revision_number+1, updated_at=? WHERE org_id=? AND slug=? AND tombstoned_at IS NULL AND revision_id=? RETURNING *", [next2.lifecycle, next2.archivedAt ?? null, next2.archiveReason ?? null, next2.replacementSlug ?? null, revisionIdOfRecord(next2), next2.updatedAt, principal.orgId, slug, current.revisionId]);
60163
60378
  if (!row)
60164
60379
  throw new SkillRevisionConflictError(slug, expectedRevisionId, this.getSkillSync(principal, slug)?.revisionId ?? null);
60165
- return rowToSkill(row);
60380
+ return this.getSkillSync(principal, slug);
60166
60381
  }).immediate();
60167
60382
  }
60168
60383
  getSkillSync(principal, slug) {
@@ -60233,7 +60448,7 @@ class SqliteSkillsStore {
60233
60448
  SET tombstoned_at = ?, tombstone_purge_after = ?, updated_at = ?
60234
60449
  WHERE org_id = ? AND slug = ?
60235
60450
  RETURNING *`, [tombstonedAt, purgeAfter, tombstonedAt, principal.orgId, slug]);
60236
- return rowToSkill(row);
60451
+ return this.getSkillSync(principal, slug);
60237
60452
  })();
60238
60453
  }
60239
60454
  async purgeExpiredTombstones(principal) {
@@ -60270,7 +60485,7 @@ class SqliteSkillsStore {
60270
60485
  return [];
60271
60486
  const requested = JSON.stringify(selections2.map(({ slug, version: version2 }) => ({ slug, version: version2 })));
60272
60487
  return this.all(`SELECT json_extract(q.value, '$.slug') AS slug, json_extract(q.value, '$.version') AS version,
60273
- r.slug IS NOT NULL AS skill_exists, r.lifecycle, r.tombstoned_at,
60488
+ r.slug IS NOT NULL AS skill_exists, r.lifecycle, r.tombstoned_at, r.authorization_epoch,
60274
60489
  v.bundle_sha256, b.sha256 IS NOT NULL AS bundle_available
60275
60490
  FROM json_each(?) q
60276
60491
  LEFT JOIN skills_registry r ON r.org_id = ? AND r.slug = json_extract(q.value, '$.slug')
@@ -60347,7 +60562,7 @@ function applySqliteMigrations(db, migrationsDir = resolveMigrationsDir("sqlite"
60347
60562
  const appliedNow = [];
60348
60563
  for (const file of files) {
60349
60564
  const version2 = file.replace(/\.sql$/, "");
60350
- const text2 = readFileSync25(join40(migrationsDir, file), "utf8");
60565
+ const text2 = readFileSync25(join41(migrationsDir, file), "utf8");
60351
60566
  const apply = db.transaction(() => {
60352
60567
  const already = db.query("SELECT 1 AS present FROM schema_migrations WHERE version = ? LIMIT 1").get(version2);
60353
60568
  if (already)
@@ -60727,7 +60942,7 @@ function nextMonthPrefix(monthPrefix) {
60727
60942
  }
60728
60943
 
60729
60944
  // src/server/skills-api.ts
60730
- import { createHash as createHash29 } from "crypto";
60945
+ import { createHash as createHash30 } from "crypto";
60731
60946
  var SLUG_PATTERN = /^[a-z0-9][a-z0-9._-]*$/;
60732
60947
  var SHA256_HEX2 = /^[0-9a-f]{64}$/;
60733
60948
  var MAX_SLUG_LENGTH = 128;
@@ -60917,7 +61132,7 @@ async function parsePublishRequest(request2, config) {
60917
61132
  if (bundleBytes.byteLength === 0) {
60918
61133
  throw new SkillRequestError(400, "BUNDLE_EMPTY", "the uploaded bundle is empty");
60919
61134
  }
60920
- const sha2562 = createHash29("sha256").update(bundleBytes).digest("hex");
61135
+ const sha2562 = createHash30("sha256").update(bundleBytes).digest("hex");
60921
61136
  const claimed = optionalString(manifest.bundleSha256);
60922
61137
  if (claimed)
60923
61138
  assertSha2562(claimed);
@@ -61032,7 +61247,7 @@ async function readPublishedBundle(store, artifactStorage, principal, slug) {
61032
61247
  if (!bytes) {
61033
61248
  throw new SkillRequestError(503, "BUNDLE_BACKEND_UNAVAILABLE", "bundle storage backend unavailable");
61034
61249
  }
61035
- const actual = createHash29("sha256").update(bytes).digest("hex");
61250
+ const actual = createHash30("sha256").update(bytes).digest("hex");
61036
61251
  if (actual !== record4.bundleSha256) {
61037
61252
  throw new SkillRequestError(500, "BUNDLE_DIGEST_DRIFT", `stored bundle for '${slug}' hashes to ${actual} but was published as ${record4.bundleSha256}`);
61038
61253
  }
@@ -61180,11 +61395,11 @@ async function readSkillVersionBundle(store, artifactStorage, principal, slug, v
61180
61395
  const bytes = await artifactStorage.readBundle(bundle2);
61181
61396
  if (!bytes)
61182
61397
  throw new SkillRequestError(503, "BUNDLE_BACKEND_UNAVAILABLE", "bundle storage backend unavailable");
61183
- const actual = createHash29("sha256").update(bytes).digest("hex");
61398
+ const actual = createHash30("sha256").update(bytes).digest("hex");
61184
61399
  if (actual !== found.bundleSha256) {
61185
61400
  throw new SkillRequestError(500, "BUNDLE_DIGEST_DRIFT", `stored bundle for '${slug}@${version2}' hashes to ${actual} but was published as ${found.bundleSha256}`);
61186
61401
  }
61187
- return { version: found, bytes };
61402
+ return { version: found, bytes, authorizationEpoch: resolved.record.authorizationEpoch };
61188
61403
  }
61189
61404
  function publishVersionOf(manifest) {
61190
61405
  const version2 = optionalString(manifest.version);
@@ -61424,6 +61639,7 @@ async function validatePublished(store, principal, selections2) {
61424
61639
  if (!state2.bundleAvailable)
61425
61640
  throw new SkillRequestError(503, "SELECTION_BUNDLE_UNAVAILABLE", "Selected bundle is unavailable");
61426
61641
  }
61642
+ return states;
61427
61643
  }
61428
61644
  async function body2(request2, limit) {
61429
61645
  if (!request2.body)
@@ -61484,6 +61700,7 @@ async function handleProfileApi(store, principal, request2, parts, config) {
61484
61700
  capabilities: [
61485
61701
  "skills.registry",
61486
61702
  "skills.versions",
61703
+ "skills.session-pin-renewal",
61487
61704
  ...store.selectionStore && store.executionGrantStore ? ["skills.execution-grants"] : [],
61488
61705
  ...store.selectionStore ? ["skills.profiles", "skills.station-state"] : []
61489
61706
  ],
@@ -61529,6 +61746,7 @@ async function handleProfileApi(store, principal, request2, parts, config) {
61529
61746
  const authority2 = skillsApiRequestUrl(normalizeSkillsApiOrigin(config.publicBaseUrl), "/api/v1/").replace(/\/+$/, "");
61530
61747
  const revision = "x".repeat(128);
61531
61748
  const projected2 = resolvedProfileSnapshot({ id: id2, workspaceId: principal.orgId, revision, selections: selections2 }, authority2);
61749
+ projected2.selections = projected2.selections.map((selection2) => ({ ...selection2, authorizationEpoch: "0".repeat(32) }));
61532
61750
  if (profileDocumentBytes(projected2) > MAX_RESOLVED_PROFILE_BYTES || profileDocumentBytes({ profileId: id2, profileRevision: revision, selections: selections2 }) > Math.min(config.requestBodyLimitBytes, MAX_PROFILE_DOCUMENT_BYTES)) {
61533
61751
  throw new SkillRequestError(413, "PROFILE_TOO_LARGE", "The complete resolved profile and station/session receipts must fit the advertised profile limits");
61534
61752
  }
@@ -61550,7 +61768,17 @@ async function handleProfileApi(store, principal, request2, parts, config) {
61550
61768
  const result = resolvedProfileSnapshot(profile2, authority2);
61551
61769
  if (result.selections.length > MAX_PROFILE_SELECTIONS || profileDocumentBytes(result) > MAX_RESOLVED_PROFILE_BYTES)
61552
61770
  throw new SkillRequestError(413, "PROFILE_TOO_LARGE", "Resolved profile exceeds the advertised profile limits");
61553
- await validatePublished(store, principal, profile2.selections);
61771
+ const states = await validatePublished(store, principal, profile2.selections);
61772
+ if (new URL(request2.url).searchParams.get("pinAuthorization") === "epoch-v1") {
61773
+ result.selections = result.selections.map((selection2, index) => {
61774
+ const epoch = states[index].current?.authorizationEpoch;
61775
+ if (!epoch || !/^[a-f0-9]{32}$/.test(epoch))
61776
+ throw new SkillRequestError(503, "PIN_AUTHORIZATION_UNAVAILABLE", "The selection lifecycle fence is unavailable");
61777
+ return { ...selection2, authorizationEpoch: epoch };
61778
+ });
61779
+ }
61780
+ if (profileDocumentBytes(result) > MAX_RESOLVED_PROFILE_BYTES)
61781
+ throw new SkillRequestError(413, "PROFILE_TOO_LARGE", "Resolved profile exceeds the advertised profile limits");
61554
61782
  return json2(result, 200, profile2.revision);
61555
61783
  }
61556
61784
  if (resource === "stations" && parts.length === 3 && child === "state") {
@@ -61883,7 +62111,7 @@ class RuntimeExecutionStore {
61883
62111
  }
61884
62112
 
61885
62113
  // src/sdk/execution/admission.ts
61886
- import { createHash as createHash31 } from "crypto";
62114
+ import { createHash as createHash32 } from "crypto";
61887
62115
 
61888
62116
  // src/sdk/execution/image-profile.ts
61889
62117
  class ImageProfileResolutionError extends Error {
@@ -62495,11 +62723,11 @@ function ownedAdmission(admission) {
62495
62723
  };
62496
62724
  }
62497
62725
  function digestInput(input) {
62498
- return createHash31("sha256").update(canonicalJson2(input)).digest("hex");
62726
+ return createHash32("sha256").update(canonicalJson2(input)).digest("hex");
62499
62727
  }
62500
62728
 
62501
62729
  // src/sdk/execution/dispatchers/ecs.ts
62502
- import { createHash as createHash32 } from "crypto";
62730
+ import { createHash as createHash33 } from "crypto";
62503
62731
 
62504
62732
  // src/sdk/execution/state-machine.ts
62505
62733
  var LEGAL_TRANSITIONS = {
@@ -65899,13 +66127,13 @@ function observedTask(states, taskArn) {
65899
66127
  return state2.lastStatus === "STOPPED" || LIVE_TASK_STATUSES.has(state2.lastStatus) ? state2 : undefined;
65900
66128
  }
65901
66129
  function clientTokenFor(runId3, attemptId) {
65902
- return createHash32("sha256").update(`${runId3}\x00${attemptId}`).digest("hex").slice(0, CLIENT_TOKEN_BYTES * 2);
66130
+ return createHash33("sha256").update(`${runId3}\x00${attemptId}`).digest("hex").slice(0, CLIENT_TOKEN_BYTES * 2);
65903
66131
  }
65904
66132
  function startedByFor(runId3, attemptNumber) {
65905
66133
  return `skills-exec/${runId3}/a${attemptNumber}`;
65906
66134
  }
65907
66135
  function requestDigestFor(admission, attemptId) {
65908
- return createHash32("sha256").update(canonicalJson2({ admission, attemptId })).digest("hex");
66136
+ return createHash33("sha256").update(canonicalJson2({ admission, attemptId })).digest("hex");
65909
66137
  }
65910
66138
 
65911
66139
  class EcsDispatcher {
@@ -66201,10 +66429,10 @@ function validText(value) {
66201
66429
  }
66202
66430
 
66203
66431
  // src/server/runtime-policy.ts
66204
- import { createHash as createHash34, createHmac as createHmac3, timingSafeEqual as timingSafeEqual2 } from "crypto";
66432
+ import { createHash as createHash35, createHmac as createHmac3, timingSafeEqual as timingSafeEqual2 } from "crypto";
66205
66433
 
66206
66434
  // src/server/runtime-pure-contract.ts
66207
- import { createHash as createHash33 } from "crypto";
66435
+ import { createHash as createHash34 } from "crypto";
66208
66436
  var PURE_DESCRIPTOR = Object.freeze({
66209
66437
  id: "regex-test.v1",
66210
66438
  runtime: "bun",
@@ -66228,7 +66456,7 @@ var PURE_LIMITS = Object.freeze({
66228
66456
  maxArtifactsBytes: 0,
66229
66457
  maxConcurrency: 1
66230
66458
  });
66231
- var hash2 = (bytes) => createHash33("sha256").update(bytes).digest("hex");
66459
+ var hash2 = (bytes) => createHash34("sha256").update(bytes).digest("hex");
66232
66460
  var object7 = (v2) => {
66233
66461
  if (!v2 || typeof v2 !== "object" || Array.isArray(v2))
66234
66462
  throw Error("Pure contract requires an object");
@@ -66457,7 +66685,7 @@ function verifyRuntimeToken(token, key, admission, attempt, now = Date.now()) {
66457
66685
  const actual = Buffer.from(token);
66458
66686
  return actual.length === expected.length && timingSafeEqual2(actual, expected);
66459
66687
  }
66460
- var hashBytes = (bytes) => createHash34("sha256").update(bytes).digest("hex");
66688
+ var hashBytes = (bytes) => createHash35("sha256").update(bytes).digest("hex");
66461
66689
 
66462
66690
  // src/server/runtime-api.ts
66463
66691
  async function createRuntimeService(options) {
@@ -67274,6 +67502,7 @@ class MemorySkillsStore {
67274
67502
  updatedAt: now,
67275
67503
  revisionId: revisionIdOfRecord(recordFieldsOf(input, carriedBundle, carriedSkillMd)),
67276
67504
  revisionNumber: (previous?.revisionNumber ?? 0) + 1,
67505
+ authorizationEpoch: previous?.authorizationEpoch ?? randomUUID10().replaceAll("-", ""),
67277
67506
  lifecycle: previous?.lifecycle ?? "active",
67278
67507
  ...previous?.archivedAt ? { archivedAt: previous.archivedAt } : {},
67279
67508
  ...previous?.archiveReason ? { archiveReason: previous.archiveReason } : {},
@@ -67317,6 +67546,7 @@ class MemorySkillsStore {
67317
67546
  slug,
67318
67547
  version: version2,
67319
67548
  current: current?.orgId === principal.orgId ? {
67549
+ authorizationEpoch: current.authorizationEpoch,
67320
67550
  lifecycle: current.lifecycle,
67321
67551
  ...current.tombstonedAt ? { tombstonedAt: current.tombstonedAt } : {}
67322
67552
  } : null,
@@ -67345,6 +67575,7 @@ class MemorySkillsStore {
67345
67575
  }
67346
67576
  const next2 = {
67347
67577
  ...current,
67578
+ authorizationEpoch: current.lifecycle === patch.lifecycle ? current.authorizationEpoch : randomUUID10().replaceAll("-", ""),
67348
67579
  lifecycle: patch.lifecycle,
67349
67580
  updatedAt: nowIso(),
67350
67581
  revisionId: revisionIdOfRecord({ ...current, lifecycle: patch.lifecycle, archiveReason: patch.reason, replacementSlug: patch.replacementSlug }),
@@ -67389,7 +67620,7 @@ class MemorySkillsStore {
67389
67620
  if (!current.tombstonedAt) {
67390
67621
  const tombstoned = nowIso();
67391
67622
  const purgeAfter = new Date(Date.now() + tombstoneWindowMs).toISOString();
67392
- const next2 = { ...current, tombstonedAt: tombstoned, tombstonePurgeAfter: purgeAfter, updatedAt: tombstoned };
67623
+ const next2 = { ...current, authorizationEpoch: randomUUID10().replaceAll("-", ""), tombstonedAt: tombstoned, tombstonePurgeAfter: purgeAfter, updatedAt: tombstoned };
67393
67624
  this.skills.set(skillKey(principal.orgId, slug), next2);
67394
67625
  return next2;
67395
67626
  }
@@ -68143,7 +68374,7 @@ class PostgresSkillsStore {
68143
68374
  const requested = JSON.stringify(selections2.map(({ slug, version: version2 }) => ({ slug, version: version2 })));
68144
68375
  const rows = await this.sql`
68145
68376
  SELECT q.value->>'slug' AS slug, q.value->>'version' AS version,
68146
- r.slug IS NOT NULL AS skill_exists, r.lifecycle, r.tombstoned_at,
68377
+ r.slug IS NOT NULL AS skill_exists, r.lifecycle, r.tombstoned_at, r.authorization_epoch,
68147
68378
  v.bundle_sha256, b.sha256 IS NOT NULL AS bundle_available
68148
68379
  FROM jsonb_array_elements(${requested}::text::jsonb) WITH ORDINALITY AS q(value, ordinal)
68149
68380
  LEFT JOIN skills_registry r ON r.org_id = ${principal.orgId} AND r.slug = q.value->>'slug'
@@ -68439,13 +68670,14 @@ async function handleApiV1(store, governanceStore, principal, request2, parts, c
68439
68670
  return json4(skillVersionPayload(version2, current));
68440
68671
  }
68441
68672
  if (request2.method === "GET" && id2 && subresource === "versions" && childId && parts[4] === "bundle" && !parts[5]) {
68442
- const { version: version2, bytes } = await readSkillVersionBundle(store, artifactStorage, principal, id2, childId);
68673
+ const { version: version2, bytes, authorizationEpoch } = await readSkillVersionBundle(store, artifactStorage, principal, id2, childId);
68443
68674
  const headers = {
68444
68675
  "Content-Type": "application/gzip",
68445
68676
  "Content-Length": String(bytes.byteLength),
68446
68677
  "Content-Disposition": `attachment; filename="${version2.slug}-${version2.version}.tar.gz"`,
68447
68678
  "X-Skill-Bundle-Sha256": version2.bundleSha256,
68448
68679
  "X-Skill-Version": version2.version,
68680
+ ...authorizationEpoch ? { "X-Skill-Authorization-Epoch": authorizationEpoch } : {},
68449
68681
  ETag: `"${version2.bundleSha256}"`,
68450
68682
  "Cache-Control": "no-store"
68451
68683
  };
@@ -72829,7 +73061,7 @@ var localRunExecutor = {
72829
73061
  // src/sdk/storage.ts
72830
73062
  var artifactStorageSeam = ArtifactStorage;
72831
73063
  // src/sdk/outputs.ts
72832
- import { createHash as createHash35 } from "crypto";
73064
+ import { createHash as createHash36 } from "crypto";
72833
73065
  class DatabaseOnlyObjectStore {
72834
73066
  usesS3 = false;
72835
73067
  async materialize(run, artifact, body4) {
@@ -72876,7 +73108,7 @@ function createGovernedArtifactWriter(options) {
72876
73108
  const stamped = {
72877
73109
  ...meta,
72878
73110
  byteSize: outputBytes,
72879
- sha256: createHash35("sha256").update(persistedBytes).digest("hex"),
73111
+ sha256: createHash36("sha256").update(persistedBytes).digest("hex"),
72880
73112
  visibility: options.visibility ?? config.defaultVisibility,
72881
73113
  ...config.artifactTtlSeconds !== undefined ? { expiresAt: expiresAtFor(createdAt, config.artifactTtlSeconds) } : {}
72882
73114
  };
@@ -73117,7 +73349,7 @@ __export(exports_external2, {
73117
73349
  pipe: () => pipe,
73118
73350
  partialRecord: () => partialRecord,
73119
73351
  parseAsync: () => parseAsync2,
73120
- parse: () => parse10,
73352
+ parse: () => parse11,
73121
73353
  overwrite: () => _overwrite,
73122
73354
  output: () => output,
73123
73355
  optional: () => optional,
@@ -73337,7 +73569,7 @@ __export(exports_core2, {
73337
73569
  prettifyError: () => prettifyError,
73338
73570
  parseURLObject: () => parseURLObject,
73339
73571
  parseAsync: () => parseAsync,
73340
- parse: () => parse8,
73572
+ parse: () => parse9,
73341
73573
  meta: () => meta,
73342
73574
  mergeValues: () => mergeValues2,
73343
73575
  memoizer: () => memoizer,
@@ -74791,7 +75023,7 @@ var _parse = (_Err) => {
74791
75023
  };
74792
75024
  return fn;
74793
75025
  };
74794
- var parse8 = /* @__PURE__ */ _parse($ZodRealError);
75026
+ var parse9 = /* @__PURE__ */ _parse($ZodRealError);
74795
75027
  var _parseAsync = (_Err) => {
74796
75028
  const fn = async (schema, value, _ctx, params) => {
74797
75029
  const ctx = _ctx ? { ..._ctx, async: true } : { async: true };
@@ -74862,18 +75094,18 @@ var validateAsync = async (schema, value, _ctx) => {
74862
75094
  return result.issues.length === 0;
74863
75095
  };
74864
75096
  var _encode = (_Err) => {
74865
- const parse9 = _parse(_Err);
75097
+ const parse10 = _parse(_Err);
74866
75098
  const fn = (schema, value, _ctx, _params) => {
74867
75099
  const ctx = _ctx ? { ..._ctx, direction: "backward" } : { direction: "backward" };
74868
- return parse9(schema, value, ctx, finalizeParams(fn, _params));
75100
+ return parse10(schema, value, ctx, finalizeParams(fn, _params));
74869
75101
  };
74870
75102
  return fn;
74871
75103
  };
74872
75104
  var encode = /* @__PURE__ */ _encode($ZodRealError);
74873
75105
  var _decode = (_Err) => {
74874
- const parse9 = _parse(_Err);
75106
+ const parse10 = _parse(_Err);
74875
75107
  const fn = (schema, value, _ctx, _params) => {
74876
- return parse9(schema, value, _ctx, finalizeParams(fn, _params));
75108
+ return parse10(schema, value, _ctx, finalizeParams(fn, _params));
74877
75109
  };
74878
75110
  return fn;
74879
75111
  };
@@ -77796,10 +78028,10 @@ var $ZodFunction = /* @__PURE__ */ $constructor("$ZodFunction", (inst, def) => {
77796
78028
  throw new Error("implement() must be called with a function");
77797
78029
  }
77798
78030
  return Object.defineProperty(function(...args) {
77799
- const parsedArgs = inst._def.input ? parse8(inst._def.input, args) : args;
78031
+ const parsedArgs = inst._def.input ? parse9(inst._def.input, args) : args;
77800
78032
  const result = Reflect.apply(func, this, parsedArgs);
77801
78033
  if (inst._def.output) {
77802
- return parse8(inst._def.output, result);
78034
+ return parse9(inst._def.output, result);
77803
78035
  }
77804
78036
  return result;
77805
78037
  }, "_zod", { value: inst._zod, enumerable: false });
@@ -89437,7 +89669,7 @@ var ZodRealError = /* @__PURE__ */ $constructor("ZodError", initializer2, undefi
89437
89669
  });
89438
89670
 
89439
89671
  // node_modules/zod/v4/classic/parse.js
89440
- var parse10 = /* @__PURE__ */ _parse(ZodRealError);
89672
+ var parse11 = /* @__PURE__ */ _parse(ZodRealError);
89441
89673
  var parseAsync2 = /* @__PURE__ */ _parseAsync(ZodRealError);
89442
89674
  var safeParse3 = /* @__PURE__ */ _safeParse(ZodRealError);
89443
89675
  var safeParseAsync2 = /* @__PURE__ */ _safeParseAsync(ZodRealError);
@@ -89573,7 +89805,7 @@ var ZodType2 = /* @__PURE__ */ $constructor("ZodType", (inst, def) => {
89573
89805
  exports_util.own(this, "~standard", value);
89574
89806
  },
89575
89807
  parse: function _parse2(data, params) {
89576
- return parse10(this, data, params, { callee: _parse2 });
89808
+ return parse11(this, data, params, { callee: _parse2 });
89577
89809
  },
89578
89810
  parseAsync: async function _parseAsync2(data, params) {
89579
89811
  return await parseAsync2(this, data, params, { callee: _parseAsync2 });
@@ -91643,7 +91875,7 @@ function date4(params) {
91643
91875
  return _coercedDate(ZodDate2, params);
91644
91876
  }
91645
91877
  // src/lib/canonical-json.ts
91646
- import { createHash as createHash36 } from "crypto";
91878
+ import { createHash as createHash37 } from "crypto";
91647
91879
  function canonicalJson3(value, maximumBytes = 2 * 1024 * 1024) {
91648
91880
  return canonicalJsonAtDepth(value, maximumBytes, 64);
91649
91881
  }
@@ -91687,7 +91919,7 @@ function canonicalJsonAtDepth(value, maximumBytes, maximumDepth) {
91687
91919
  return visit3(value, 0);
91688
91920
  }
91689
91921
  function canonicalJsonSha256(value, maximumBytes) {
91690
- return createHash36("sha256").update(canonicalJson3(value, maximumBytes)).digest("hex");
91922
+ return createHash37("sha256").update(canonicalJson3(value, maximumBytes)).digest("hex");
91691
91923
  }
91692
91924
 
91693
91925
  // src/lib/remote-recurring-contract.ts
@@ -93801,7 +94033,7 @@ async function requestInvitationEmail(origin, action, input2) {
93801
94033
  }
93802
94034
 
93803
94035
  // src/lib/remote-private-publications.ts
93804
- import { createHash as createHash37 } from "crypto";
94036
+ import { createHash as createHash38 } from "crypto";
93805
94037
  var PRIVATE_PUBLICATION_MAX_BYTES = 16 * 1024 * 1024;
93806
94038
  var failures2 = {
93807
94039
  INVALID_REQUEST: [400, "The publication request is invalid."],
@@ -93848,7 +94080,7 @@ var hash4 = (v2) => typeof v2 === "string" && /^[a-f0-9]{64}$/.test(v2);
93848
94080
  var record10 = (v2) => !!v2 && typeof v2 === "object" && !Array.isArray(v2);
93849
94081
  var exact = (v2, keys3) => record10(v2) && Object.keys(v2).sort().join(",") === keys3.sort().join(",");
93850
94082
  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));
93851
- var publicationSha256 = (bytes) => createHash37("sha256").update(bytes).digest("hex");
94083
+ var publicationSha256 = (bytes) => createHash38("sha256").update(bytes).digest("hex");
93852
94084
  function checkedPublicationDeclaration(value) {
93853
94085
  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)
93854
94086
  return bad();
@@ -94331,7 +94563,7 @@ class RemoteSkillsAuthClient {
94331
94563
  }
94332
94564
  // src/lib/private-publication-recovery.ts
94333
94565
  import { constants as constants15, closeSync as closeSync18, fsyncSync as fsyncSync6, fstatSync as fstatSync18, lstatSync as lstatSync26, mkdirSync as mkdirSync15, openSync as openSync18, readSync as readSync13, realpathSync as realpathSync15, renameSync as renameSync7, unlinkSync as unlinkSync6, writeFileSync as writeFileSync11 } from "fs";
94334
- import { dirname as dirname28, isAbsolute as isAbsolute22, join as join42, resolve as resolve23 } from "path";
94566
+ import { dirname as dirname28, isAbsolute as isAbsolute22, join as join43, resolve as resolve23 } from "path";
94335
94567
  import { randomUUID as randomUUID12 } from "crypto";
94336
94568
  var fail2 = () => {
94337
94569
  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.");
@@ -94357,7 +94589,7 @@ function unchangedDirectory(directory, identity5) {
94357
94589
  return fail2();
94358
94590
  }
94359
94591
  function readOwned(directory, name, max) {
94360
- const identity5 = safeDirectory(directory), file2 = join42(directory, name);
94592
+ const identity5 = safeDirectory(directory), file2 = join43(directory, name);
94361
94593
  const fd = openSync18(file2, constants15.O_RDONLY | constants15.O_NOFOLLOW);
94362
94594
  try {
94363
94595
  const stat2 = fstatSync18(fd);
@@ -94381,7 +94613,7 @@ function readOwned(directory, name, max) {
94381
94613
  }
94382
94614
  }
94383
94615
  function writeOwned(directory, name, bytes) {
94384
- const fd = openSync18(join42(directory, name), constants15.O_WRONLY | constants15.O_CREAT | constants15.O_EXCL | constants15.O_NOFOLLOW, 384);
94616
+ const fd = openSync18(join43(directory, name), constants15.O_WRONLY | constants15.O_CREAT | constants15.O_EXCL | constants15.O_NOFOLLOW, 384);
94385
94617
  try {
94386
94618
  writeFileSync11(fd, bytes);
94387
94619
  fsyncSync6(fd);
@@ -94394,7 +94626,7 @@ function save(directory, value) {
94394
94626
  writeOwned(directory, temporary, JSON.stringify(value) + `
94395
94627
  `);
94396
94628
  unchangedDirectory(directory, identity5);
94397
- renameSync7(join42(directory, temporary), join42(directory, "receipt.json"));
94629
+ renameSync7(join43(directory, temporary), join43(directory, "receipt.json"));
94398
94630
  const fd = openSync18(directory, constants15.O_RDONLY | constants15.O_NOFOLLOW);
94399
94631
  try {
94400
94632
  fsyncSync6(fd);
@@ -94407,7 +94639,7 @@ function bind(client2, receipt) {
94407
94639
  throw new PrivatePublicationError("PUBLICATION_IDENTITY_CHANGED", "The fresh session does not match the recovery directory's server, account and membership.");
94408
94640
  }
94409
94641
  async function locked(directory, action) {
94410
- const identity5 = safeDirectory(directory), file2 = join42(directory, "operation.lock");
94642
+ const identity5 = safeDirectory(directory), file2 = join43(directory, "operation.lock");
94411
94643
  let fd;
94412
94644
  try {
94413
94645
  fd = openSync18(file2, constants15.O_WRONLY | constants15.O_CREAT | constants15.O_EXCL | constants15.O_NOFOLLOW, 384);