@hasna/skills 0.10.28 → 0.10.31

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
@@ -8209,7 +8209,7 @@ var require_client = __commonJS((exports) => {
8209
8209
  };
8210
8210
  };
8211
8211
  var sleep = (seconds) => {
8212
- return new Promise((resolve19) => setTimeout(resolve19, seconds * 1000));
8212
+ return new Promise((resolve20) => setTimeout(resolve20, seconds * 1000));
8213
8213
  };
8214
8214
  var waiterServiceDefaults = {
8215
8215
  minDelay: 2,
@@ -8338,8 +8338,8 @@ var require_client = __commonJS((exports) => {
8338
8338
  };
8339
8339
  var abortTimeout = (abortSignal) => {
8340
8340
  let onAbort;
8341
- const promise = new Promise((resolve19) => {
8342
- onAbort = () => resolve19({ state: WaiterState.ABORTED });
8341
+ const promise = new Promise((resolve20) => {
8342
+ onAbort = () => resolve20({ state: WaiterState.ABORTED });
8343
8343
  if (typeof abortSignal.addEventListener === "function") {
8344
8344
  abortSignal.addEventListener("abort", onAbort);
8345
8345
  } else {
@@ -9477,7 +9477,7 @@ var require_config = __commonJS((exports) => {
9477
9477
  };
9478
9478
  var imdsRequest = async (options) => {
9479
9479
  const { request: request2 } = __require("http");
9480
- return new Promise((resolve19, reject) => {
9480
+ return new Promise((resolve20, reject) => {
9481
9481
  const req = request2({
9482
9482
  hostname: options.hostname,
9483
9483
  port: options.port,
@@ -9505,7 +9505,7 @@ var require_config = __commonJS((exports) => {
9505
9505
  const chunks = [];
9506
9506
  res.on("data", (chunk) => chunks.push(chunk));
9507
9507
  res.on("end", () => {
9508
- resolve19(Buffer.concat(chunks));
9508
+ resolve20(Buffer.concat(chunks));
9509
9509
  req.destroy();
9510
9510
  });
9511
9511
  });
@@ -10514,7 +10514,7 @@ var require_serde = __commonJS((exports) => {
10514
10514
  var { createHmac: createHmac2, createHash: createHash21, getRandomValues } = __require("crypto");
10515
10515
  var { hasOwn: hasOwn2, HttpResponse } = require_transport();
10516
10516
  exports.hasOwn = hasOwn2;
10517
- var { ReadStream, lstatSync: lstatSync23, fstatSync: fstatSync4 } = __require("fs");
10517
+ var { ReadStream, lstatSync: lstatSync24, fstatSync: fstatSync4 } = __require("fs");
10518
10518
  var { toEndpointV1 } = require_endpoints();
10519
10519
  var { Readable, Writable, PassThrough } = __require("stream");
10520
10520
  var isArrayBuffer = (arg) => typeof ArrayBuffer === "function" && arg instanceof ArrayBuffer || Object.prototype.toString.call(arg) === "[object ArrayBuffer]";
@@ -11280,7 +11280,7 @@ var require_serde = __commonJS((exports) => {
11280
11280
  return body.end + 1 - body.start;
11281
11281
  } else if (body instanceof ReadStream) {
11282
11282
  if (body.path != null) {
11283
- return lstatSync23(body.path).size;
11283
+ return lstatSync24(body.path).size;
11284
11284
  } else if (typeof body.fd === "number") {
11285
11285
  return fstatSync4(body.fd).size;
11286
11286
  }
@@ -11861,7 +11861,7 @@ ${value}\r
11861
11861
  if (isReadableStream(stream)) {
11862
11862
  return headStream$1(stream, bytes);
11863
11863
  }
11864
- return new Promise((resolve19, reject) => {
11864
+ return new Promise((resolve20, reject) => {
11865
11865
  const collector = new Collector$1;
11866
11866
  collector.limit = bytes;
11867
11867
  stream.pipe(collector);
@@ -11872,7 +11872,7 @@ ${value}\r
11872
11872
  collector.on("error", reject);
11873
11873
  collector.on("finish", function() {
11874
11874
  const bytes2 = concatBytes(this.buffers);
11875
- resolve19(bytes2);
11875
+ resolve20(bytes2);
11876
11876
  });
11877
11877
  });
11878
11878
  };
@@ -11986,7 +11986,7 @@ ${value}\r
11986
11986
  if (isReadableStream(stream)) {
11987
11987
  return collectReadableStream(stream);
11988
11988
  }
11989
- return new Promise((resolve19, reject) => {
11989
+ return new Promise((resolve20, reject) => {
11990
11990
  const collector = new Collector;
11991
11991
  const nodeStream = stream;
11992
11992
  nodeStream.pipe(collector);
@@ -11997,7 +11997,7 @@ ${value}\r
11997
11997
  collector.on("error", reject);
11998
11998
  collector.on("finish", function() {
11999
11999
  const bytes = concatBytes(this.bufferedBytes);
12000
- resolve19(bytes);
12000
+ resolve20(bytes);
12001
12001
  });
12002
12002
  });
12003
12003
  };
@@ -12189,7 +12189,7 @@ var require_checksum = __commonJS((exports) => {
12189
12189
  callback();
12190
12190
  }
12191
12191
  }
12192
- var fileStreamHasher = (hashCtor, fileStream) => new Promise((resolve19, reject) => {
12192
+ var fileStreamHasher = (hashCtor, fileStream) => new Promise((resolve20, reject) => {
12193
12193
  if (!isReadStream(fileStream)) {
12194
12194
  reject(new Error("Unable to calculate hash for non-file streams."));
12195
12195
  return;
@@ -12207,7 +12207,7 @@ var require_checksum = __commonJS((exports) => {
12207
12207
  });
12208
12208
  hashCalculator.on("error", reject);
12209
12209
  hashCalculator.on("finish", function() {
12210
- hash2.digest().then(resolve19).catch(reject);
12210
+ hash2.digest().then(resolve20).catch(reject);
12211
12211
  });
12212
12212
  });
12213
12213
  var isReadStream = (stream) => typeof stream.path === "string";
@@ -12218,14 +12218,14 @@ var require_checksum = __commonJS((exports) => {
12218
12218
  const hash2 = new hashCtor;
12219
12219
  const hashCalculator = new HashCalculator(hash2);
12220
12220
  readableStream.pipe(hashCalculator);
12221
- return new Promise((resolve19, reject) => {
12221
+ return new Promise((resolve20, reject) => {
12222
12222
  readableStream.on("error", (err) => {
12223
12223
  hashCalculator.end();
12224
12224
  reject(err);
12225
12225
  });
12226
12226
  hashCalculator.on("error", reject);
12227
12227
  hashCalculator.on("finish", () => {
12228
- hash2.digest().then(resolve19).catch(reject);
12228
+ hash2.digest().then(resolve20).catch(reject);
12229
12229
  });
12230
12230
  });
12231
12231
  };
@@ -13334,7 +13334,7 @@ var require_event_streams = __commonJS((exports) => {
13334
13334
  streamEnded = true;
13335
13335
  });
13336
13336
  while (!generationEnded) {
13337
- const value = await new Promise((resolve19) => setTimeout(() => resolve19(records.shift()), 0));
13337
+ const value = await new Promise((resolve20) => setTimeout(() => resolve20(records.shift()), 0));
13338
13338
  if (value) {
13339
13339
  yield value;
13340
13340
  }
@@ -14852,7 +14852,7 @@ var require_retry = __commonJS((exports) => {
14852
14852
  }
14853
14853
  };
14854
14854
  }
14855
- var cooldown = (ms) => new Promise((resolve19) => setTimeout(resolve19, ms));
14855
+ var cooldown = (ms) => new Promise((resolve20) => setTimeout(resolve20, ms));
14856
14856
  var isRetryStrategyV2 = (retryStrategy) => typeof retryStrategy.acquireInitialRetryToken !== "undefined" && typeof retryStrategy.refreshRetryTokenForRetry !== "undefined" && typeof retryStrategy.recordSuccess !== "undefined";
14857
14857
  var getRetryErrorInfo = (error, logger) => {
14858
14858
  const errorInfo = {
@@ -14951,7 +14951,7 @@ var require_retry = __commonJS((exports) => {
14951
14951
  this.refillTokenBucket();
14952
14952
  while (amount > this.availableTokens) {
14953
14953
  const delay = (amount - this.availableTokens) / this.fillRate * 1000;
14954
- await new Promise((resolve19) => DefaultRateLimiter.setTimeoutFn(resolve19, delay));
14954
+ await new Promise((resolve20) => DefaultRateLimiter.setTimeoutFn(resolve20, delay));
14955
14955
  this.refillTokenBucket();
14956
14956
  }
14957
14957
  this.availableTokens = this.availableTokens - amount;
@@ -15293,7 +15293,7 @@ var require_retry = __commonJS((exports) => {
15293
15293
  const delayFromResponse = getDelayFromRetryAfterHeader(err.$response);
15294
15294
  const delay = Math.max(delayFromResponse || 0, delayFromDecider);
15295
15295
  totalDelay += delay;
15296
- await new Promise((resolve19) => setTimeout(resolve19, delay));
15296
+ await new Promise((resolve20) => setTimeout(resolve20, delay));
15297
15297
  continue;
15298
15298
  }
15299
15299
  if (!err.$metadata) {
@@ -24646,7 +24646,7 @@ var init_node_http = () => {};
24646
24646
 
24647
24647
  // node_modules/@smithy/credential-provider-imds/dist-es/remoteProvider/httpRequest.js
24648
24648
  function httpRequest(options) {
24649
- return new Promise((resolve19, reject) => {
24649
+ return new Promise((resolve20, reject) => {
24650
24650
  const req = node_http.request({
24651
24651
  method: "GET",
24652
24652
  ...options,
@@ -24671,7 +24671,7 @@ function httpRequest(options) {
24671
24671
  chunks.push(chunk);
24672
24672
  });
24673
24673
  res.on("end", () => {
24674
- resolve19(Buffer.concat(chunks));
24674
+ resolve20(Buffer.concat(chunks));
24675
24675
  req.destroy();
24676
24676
  });
24677
24677
  });
@@ -25168,21 +25168,21 @@ var require_dist_cjs6 = __commonJS((exports) => {
25168
25168
  let sendBody = true;
25169
25169
  if (!externalAgent && expect === "100-continue") {
25170
25170
  sendBody = await Promise.race([
25171
- new Promise((resolve19) => {
25172
- timeoutId = Number(timing.setTimeout(() => resolve19(true), Math.max(MIN_WAIT_TIME, maxContinueTimeoutMs)));
25171
+ new Promise((resolve20) => {
25172
+ timeoutId = Number(timing.setTimeout(() => resolve20(true), Math.max(MIN_WAIT_TIME, maxContinueTimeoutMs)));
25173
25173
  }),
25174
- new Promise((resolve19) => {
25174
+ new Promise((resolve20) => {
25175
25175
  httpRequest2.on("continue", () => {
25176
25176
  timing.clearTimeout(timeoutId);
25177
- resolve19(true);
25177
+ resolve20(true);
25178
25178
  });
25179
25179
  httpRequest2.on("response", () => {
25180
25180
  timing.clearTimeout(timeoutId);
25181
- resolve19(false);
25181
+ resolve20(false);
25182
25182
  });
25183
25183
  httpRequest2.on("error", () => {
25184
25184
  timing.clearTimeout(timeoutId);
25185
- resolve19(false);
25185
+ resolve20(false);
25186
25186
  });
25187
25187
  })
25188
25188
  ]);
@@ -25259,13 +25259,13 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
25259
25259
  return socketWarningTimestamp;
25260
25260
  }
25261
25261
  constructor(options) {
25262
- this.configProvider = new Promise((resolve19, reject) => {
25262
+ this.configProvider = new Promise((resolve20, reject) => {
25263
25263
  if (typeof options === "function") {
25264
25264
  options().then((_options) => {
25265
- resolve19(this.resolveDefaultConfig(_options));
25265
+ resolve20(this.resolveDefaultConfig(_options));
25266
25266
  }).catch(reject);
25267
25267
  } else {
25268
- resolve19(this.resolveDefaultConfig(options));
25268
+ resolve20(this.resolveDefaultConfig(options));
25269
25269
  }
25270
25270
  });
25271
25271
  }
@@ -25297,7 +25297,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
25297
25297
  timing.clearTimeout(socketTimeoutId);
25298
25298
  timing.clearTimeout(keepAliveTimeoutId);
25299
25299
  };
25300
- const resolve19 = async (arg) => {
25300
+ const resolve20 = async (arg) => {
25301
25301
  await writeRequestBodyPromise;
25302
25302
  clearTimeouts();
25303
25303
  _resolve(arg);
@@ -25361,7 +25361,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
25361
25361
  headers: getTransformedHeaders(res.headers),
25362
25362
  body: res
25363
25363
  });
25364
- resolve19({ response: httpResponse });
25364
+ resolve20({ response: httpResponse });
25365
25365
  });
25366
25366
  req.on("error", (err) => {
25367
25367
  if (NODEJS_TIMEOUT_ERROR_CODES.includes(err.code)) {
@@ -25693,13 +25693,13 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
25693
25693
  return new NodeHttp2Handler(instanceOrOptions);
25694
25694
  }
25695
25695
  constructor(options) {
25696
- this.configProvider = new Promise((resolve19, reject) => {
25696
+ this.configProvider = new Promise((resolve20, reject) => {
25697
25697
  if (typeof options === "function") {
25698
25698
  options().then((opts) => {
25699
- resolve19(opts || {});
25699
+ resolve20(opts || {});
25700
25700
  }).catch(reject);
25701
25701
  } else {
25702
- resolve19(options || {});
25702
+ resolve20(options || {});
25703
25703
  }
25704
25704
  });
25705
25705
  }
@@ -25724,7 +25724,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
25724
25724
  return new Promise((_resolve, _reject) => {
25725
25725
  let fulfilled = false;
25726
25726
  let writeRequestBodyPromise = undefined;
25727
- const resolve19 = async (arg) => {
25727
+ const resolve20 = async (arg) => {
25728
25728
  await writeRequestBodyPromise;
25729
25729
  _resolve(arg);
25730
25730
  };
@@ -25809,7 +25809,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
25809
25809
  body: clientHttp2Stream
25810
25810
  });
25811
25811
  fulfilled = true;
25812
- resolve19({ response: httpResponse });
25812
+ resolve20({ response: httpResponse });
25813
25813
  if (useIsolatedSession) {
25814
25814
  session.close();
25815
25815
  clientHttp2Stream.on("end", () => {
@@ -25942,7 +25942,7 @@ var retryWrapper = (toRetry, maxRetries, delayMs) => {
25942
25942
  try {
25943
25943
  return await toRetry();
25944
25944
  } catch (e3) {
25945
- await new Promise((resolve19) => setTimeout(resolve19, delayMs));
25945
+ await new Promise((resolve20) => setTimeout(resolve20, delayMs));
25946
25946
  }
25947
25947
  }
25948
25948
  return await toRetry();
@@ -29446,7 +29446,7 @@ var require_signin = __commonJS((exports) => {
29446
29446
  import { createHash as createHash21, 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 dirname21, join as join33 } from "path";
29449
+ import { dirname as dirname21, join as join34 } 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 ?? join33(homedir7(), ".aws", "login", "cache");
29616
+ const directory = process.env.AWS_LOGIN_CACHE_DIRECTORY ?? join34(homedir7(), ".aws", "login", "cache");
29617
29617
  const loginSessionBytes = Buffer.from(this.loginSession, "utf8");
29618
29618
  const loginSessionSha256 = createHash21("sha256").update(loginSessionBytes).digest("hex");
29619
- return join33(directory, `${loginSessionSha256}.json`);
29619
+ return join34(directory, `${loginSessionSha256}.json`);
29620
29620
  }
29621
29621
  derToRawSignature(derSignature) {
29622
29622
  let offset = 2;
@@ -31065,9 +31065,9 @@ import { chmod, mkdir, readFile, rename, writeFile as writeFile2 } from "fs/prom
31065
31065
  import { Buffer as Buffer2 } from "buffer";
31066
31066
  import { existsSync as existsSync22 } from "fs";
31067
31067
  import { join as join210 } from "path";
31068
- import { existsSync as existsSync16 } from "fs";
31068
+ import { existsSync as existsSync17 } from "fs";
31069
31069
  import { homedir as homedir8 } from "os";
31070
- import { join as join37, resolve as resolve19 } from "path";
31070
+ import { join as join38, resolve as resolve20 } 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 join37(effectiveHome2(), ".hasna", "events");
31231
+ return join38(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 existsSync16(join37(resolved, EVENTS_STORE_SENTINEL_FILE));
31240
+ return existsSync17(join38(resolved, EVENTS_STORE_SENTINEL_FILE));
31241
31241
  }
31242
31242
  function exactEventsHome() {
31243
31243
  const dir = process.env[HASNA_EVENTS_DIR_ENV];
@@ -31251,9 +31251,9 @@ function exactEventsHome() {
31251
31251
  function getEventsHome() {
31252
31252
  const exact = exactEventsHome();
31253
31253
  if (exact)
31254
- return resolve19(exact);
31254
+ return resolve20(exact);
31255
31255
  const resolved = resolverHome();
31256
- return adoptResolverHome(resolved) ? resolve19(resolved) : resolve19(legacyHomeDir());
31256
+ return adoptResolverHome(resolved) ? resolve20(resolved) : resolve20(legacyHomeDir());
31257
31257
  }
31258
31258
  function getEventsDataDir(override) {
31259
31259
  return override || getEventsHome();
@@ -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.28",
32376
+ version: "0.10.31",
32377
32377
  description: "Skills library for AI coding agents",
32378
32378
  type: "module",
32379
32379
  bin: {
@@ -37457,8 +37457,8 @@ async function reconcileSkillSession(input, options = {}) {
37457
37457
  // src/lib/selected-run.ts
37458
37458
  import { createHash as createHash20 } from "crypto";
37459
37459
  import { spawn as spawn2 } from "child_process";
37460
- import { mkdirSync as mkdirSync10, mkdtempSync as mkdtempSync3, writeFileSync as writeFileSync9, realpathSync as realpathSync11 } from "fs";
37461
- import { dirname as dirname20, join as join32, resolve as resolve18 } from "path";
37460
+ import { mkdirSync as mkdirSync10, mkdtempSync as mkdtempSync3, writeFileSync as writeFileSync9, realpathSync as realpathSync12 } from "fs";
37461
+ import { dirname as dirname20, join as join33, resolve as resolve19 } from "path";
37462
37462
  import { tmpdir, hostname as stationHostname2 } from "os";
37463
37463
 
37464
37464
  // src/lib/dependency-preparation.ts
@@ -37669,19 +37669,19 @@ async function prepareSkillDependencies(skillPath, env, timeoutMs = DEFAULT_PREP
37669
37669
  }
37670
37670
 
37671
37671
  // src/lib/skillinfo.ts
37672
- import { existsSync as existsSync14, readFileSync as readFileSync21 } from "fs";
37673
- import { join as join31 } from "path";
37672
+ import { existsSync as existsSync15, readFileSync as readFileSync21 } from "fs";
37673
+ import { join as join32 } from "path";
37674
37674
 
37675
37675
  // src/lib/installer.ts
37676
- import { existsSync as existsSync13, readFileSync as readFileSync20, rmSync as rmSync4 } from "fs";
37677
- import { join as join30 } from "path";
37676
+ import { existsSync as existsSync14, readFileSync as readFileSync20, rmSync as rmSync4 } from "fs";
37677
+ import { join as join31 } from "path";
37678
37678
  import { homedir as homedir6 } from "os";
37679
37679
 
37680
37680
  // src/lib/agent-sync.ts
37681
37681
  import {
37682
37682
  cpSync as cpSync2,
37683
- existsSync as existsSync10,
37684
- lstatSync as lstatSync22,
37683
+ existsSync as existsSync11,
37684
+ lstatSync as lstatSync23,
37685
37685
  mkdirSync as mkdirSync8,
37686
37686
  mkdtempSync as mkdtempSync2,
37687
37687
  readFileSync as readFileSync17,
@@ -37692,7 +37692,7 @@ import {
37692
37692
  writeFileSync as writeFileSync7
37693
37693
  } from "fs";
37694
37694
  import { homedir as homedir5 } from "os";
37695
- import { basename as basename11, dirname as dirname19, join as join27 } from "path";
37695
+ import { basename as basename11, dirname as dirname19, join as join28 } from "path";
37696
37696
 
37697
37697
  // src/lib/codex-local-mcp-controls.ts
37698
37698
  function isCodexLocalStdioMcpServer(name, server) {
@@ -38451,6 +38451,29 @@ function mcpControls(path, read) {
38451
38451
  refuse3();
38452
38452
  return sha2562;
38453
38453
  }
38454
+ function isBundledCleanupHooks(root, namespace, value) {
38455
+ const object3 = (v) => Boolean(v && typeof v === "object" && !Array.isArray(v));
38456
+ const exactKeys2 = (v, keys2) => Object.keys(v).length === keys2.length && keys2.every((key) => Object.hasOwn(v, key));
38457
+ if (basename3(dirname5(root)) !== namespace || basename3(dirname5(dirname5(root))) !== "openai-bundled")
38458
+ return false;
38459
+ const server = namespace === "unified-computer-use" ? "cua_repl" : ["browser", "chrome", "chrome-dev", "chrome-internal", "computer-use"].includes(namespace) ? "node_repl" : undefined;
38460
+ if (!server || !object3(value) || !exactKeys2(value, ["hooks"]) || !object3(value.hooks))
38461
+ return false;
38462
+ const events = Object.entries(value.hooks);
38463
+ if (!events.length || events.length > 3)
38464
+ return false;
38465
+ for (const [event, groups] of events) {
38466
+ if (!["Interrupt", "SubagentStop", "Stop"].includes(event) || !Array.isArray(groups) || groups.length !== 1)
38467
+ return false;
38468
+ const group = groups[0];
38469
+ if (!object3(group) || !exactKeys2(group, ["hooks"]) || !Array.isArray(group.hooks) || group.hooks.length !== 1)
38470
+ return false;
38471
+ const handler = group.hooks[0];
38472
+ if (!object3(handler) || !exactKeys2(handler, ["type", "server", "tool", "input"]) || handler.type !== "mcp_tool" || handler.server !== server || handler.tool !== "turn_ended" || !object3(handler.input) || !exactKeys2(handler.input, ["hook_event_name", "session_id", "turn_id"]) || handler.input.hook_event_name !== "${hook_event_name}" || handler.input.turn_id !== "${turn_id}" || handler.input.session_id !== (event === "SubagentStop" ? "${agent_id}" : "${session_id}"))
38473
+ return false;
38474
+ }
38475
+ return true;
38476
+ }
38454
38477
  function rootControls(root, read) {
38455
38478
  const manifestPath = join10(root, ".codex-plugin/plugin.json"), manifestFile = lstatSync6(manifestPath, { throwIfNoEntry: false });
38456
38479
  if (!lstatSync6(join10(root, ".codex-plugin"), { throwIfNoEntry: false })?.isDirectory() || !manifestFile?.isFile() || manifestFile.size > 1024 * 1024)
@@ -38468,9 +38491,11 @@ function rootControls(root, read) {
38468
38491
  const cacheVersion = basename3(root), declaredVersion = manifest.version === undefined ? "" : typeof manifest.version === "string" ? manifest.version.trim() : null;
38469
38492
  if (declaredVersion === null || (declaredVersion ? declaredVersion !== cacheVersion : cacheVersion !== CODEX_DEFAULT_AGENT_PLUGIN_VERSION))
38470
38493
  refuse3();
38471
- if (manifest.hooks !== undefined || manifest.commands !== undefined || manifest.mcpServers !== undefined && manifest.mcpServers !== "./.mcp.json" || manifest.apps !== undefined && manifest.apps !== "./.app.json" || lstatSync6(join10(root, "hooks"), { throwIfNoEntry: false }))
38494
+ if (manifest.hooks !== undefined && !isBundledCleanupHooks(root, manifest.name, manifest.hooks) || manifest.commands !== undefined || manifest.mcpServers !== undefined && manifest.mcpServers !== "./.mcp.json" || manifest.apps !== undefined && manifest.apps !== "./.app.json" || lstatSync6(join10(root, "hooks"), { throwIfNoEntry: false }))
38472
38495
  refuse3();
38473
38496
  const mcp = join10(root, ".mcp.json"), mcpPresent = lstatSync6(mcp, { throwIfNoEntry: false });
38497
+ if (manifest.hooks !== undefined && (manifest.mcpServers !== undefined || mcpPresent))
38498
+ refuse3();
38474
38499
  if (mcpPresent && (!mcpPresent.isFile() || mcpPresent.isSymbolicLink() || mcpPresent.size > 1024 * 1024 || realpathSync5(mcp) !== mcp))
38475
38500
  refuse3();
38476
38501
  if (Boolean(mcpPresent) !== (manifest.mcpServers !== undefined))
@@ -39072,6 +39097,8 @@ var NATIVE_SKILL_ROOTS = [
39072
39097
  ["codex", ".codex/skills"],
39073
39098
  ["codex", ".agents/skills"],
39074
39099
  ["gemini", ".gemini/skills"],
39100
+ ["sumi", ".sumi/skills"],
39101
+ ["sumi", ".sumi/skill"],
39075
39102
  ["codewith", ".codewith/skills"],
39076
39103
  ["opencode", ".config/opencode/skills"],
39077
39104
  ["opencode", ".opencode/skills"],
@@ -39088,8 +39115,8 @@ var NATIVE_SKILL_ROOTS = [
39088
39115
  // src/lib/agent-integration.ts
39089
39116
  import { createHash as createHash18, randomUUID as randomUUID3 } from "crypto";
39090
39117
  import { isDeepStrictEqual as isDeepStrictEqual6 } from "util";
39091
- import { existsSync as existsSync6, lstatSync as lstatSync19, statSync as statSync6, mkdirSync as mkdirSync5, readFileSync as readFileSync14, readdirSync as readdirSync8, opendirSync as opendirSync5, readlinkSync as readlinkSync4, realpathSync as realpathSync7, renameSync as renameSync3, rmdirSync as rmdirSync3, writeFileSync as writeFileSync4, unlinkSync as unlinkSync4, chmodSync, openSync as openSync16, closeSync as closeSync16, fsyncSync as fsyncSync4, fstatSync as fstatSync16, readSync as readSync11, constants as constants12, linkSync as linkSync2 } from "fs";
39092
- import { dirname as dirname15, join as join22, resolve as resolve15, relative as relative4, isAbsolute as isAbsolute17, sep as sep5 } from "path";
39118
+ import { existsSync as existsSync7, lstatSync as lstatSync20, statSync as statSync6, mkdirSync as mkdirSync5, readFileSync as readFileSync14, readdirSync as readdirSync8, opendirSync as opendirSync5, readlinkSync as readlinkSync4, realpathSync as realpathSync8, renameSync as renameSync3, rmdirSync as rmdirSync3, writeFileSync as writeFileSync4, unlinkSync as unlinkSync4, chmodSync, openSync as openSync16, closeSync as closeSync16, fsyncSync as fsyncSync4, fstatSync as fstatSync16, readSync as readSync11, constants as constants12, linkSync as linkSync2 } from "fs";
39119
+ import { dirname as dirname15, join as join23, resolve as resolve16, relative as relative4, isAbsolute as isAbsolute17, sep as sep5 } from "path";
39093
39120
  import { homedir as homedir3 } from "os";
39094
39121
 
39095
39122
  // src/lib/managed-policy.ts
@@ -39368,8 +39395,8 @@ function isOwnedCliBridge(path, expectedPaths) {
39368
39395
 
39369
39396
  // src/lib/agent-discovery.ts
39370
39397
  import { createHash as createHash17 } from "crypto";
39371
- import { lstatSync as lstatSync18, readFileSync as readFileSync13, readdirSync as readdirSync7, realpathSync as realpathSync6 } from "fs";
39372
- import { basename as basename7, dirname as dirname14, isAbsolute as isAbsolute16, join as join21, resolve as resolve14, sep as sep4 } from "path";
39398
+ import { lstatSync as lstatSync19, readFileSync as readFileSync13, readdirSync as readdirSync7, realpathSync as realpathSync7 } from "fs";
39399
+ import { basename as basename7, dirname as dirname14, isAbsolute as isAbsolute16, join as join22, resolve as resolve15, sep as sep4 } from "path";
39373
39400
  import { isDeepStrictEqual as isDeepStrictEqual4 } from "util";
39374
39401
 
39375
39402
  // node_modules/yaml/dist/index.js
@@ -41680,6 +41707,114 @@ function verifiesCodexHookDiscoverySource(binding, source, currentDigest, witnes
41680
41707
  return true;
41681
41708
  }
41682
41709
 
41710
+ // src/lib/agent-sumi.ts
41711
+ import { existsSync as existsSync6, lstatSync as lstatSync18, realpathSync as realpathSync6 } from "fs";
41712
+ import { join as join21, resolve as resolve14 } from "path";
41713
+ function sumiConfigDirectory(home, env = process.env) {
41714
+ for (const key of ["SUMI_CONFIG", "SUMI_CONFIG_CONTENT"])
41715
+ if (env[key] !== undefined)
41716
+ throw new Error(`Sumi ${key} requires a dedicated discovery adapter; unset it before Skills integration`);
41717
+ const selected = (key) => env[key]?.trim() ? env[key] : undefined;
41718
+ const expand = (value) => resolve14(value === "~" ? home : value.startsWith("~/") ? join21(home, value.slice(2)) : value);
41719
+ const explicit = selected("SUMI_CONFIG_DIR");
41720
+ const xdg = selected("XDG_CONFIG_HOME");
41721
+ const custom = selected("SUMI_HOME");
41722
+ const canonical6 = explicit ? expand(explicit) : xdg ? join21(expand(xdg), "sumi") : join21(custom ? expand(custom) : join21(home, ".hasna-internal/sumi"), "config");
41723
+ if (explicit || xdg || custom)
41724
+ return canonical6;
41725
+ const legacy = join21(home, ".config/sumi");
41726
+ const a = lstatSync18(canonical6, { throwIfNoEntry: false }), b = lstatSync18(legacy, { throwIfNoEntry: false });
41727
+ if (a && b && realpathSync6(canonical6) !== realpathSync6(legacy))
41728
+ throw new Error("Sumi config roots conflict; complete native home adoption before Skills integration");
41729
+ const path = a ? canonical6 : b ? legacy : canonical6;
41730
+ if (!existsSync6(path))
41731
+ return path;
41732
+ const physical = realpathSync6(path);
41733
+ if ((a?.isSymbolicLink() || b?.isSymbolicLink()) && ![canonical6, legacy].includes(physical))
41734
+ throw new Error("Sumi config alias must resolve to its canonical or legacy root");
41735
+ return physical;
41736
+ }
41737
+ function sumiBridgeRoot(home) {
41738
+ return join21(sumiConfigDirectory(home), "skills");
41739
+ }
41740
+ function sumiConfigPath(home) {
41741
+ return join21(sumiConfigDirectory(home), "sumi.json");
41742
+ }
41743
+ function renderSumiPlugin(command, profile) {
41744
+ return `// Managed by @hasna/skills. Regenerate with skills hook install --agent sumi.
41745
+ import { spawn } from "node:child_process";
41746
+ const command = ${JSON.stringify(command)};
41747
+ const profile = ${JSON.stringify(profile)};
41748
+ function context(input) {
41749
+ return new Promise((resolve, reject) => {
41750
+ const child = spawn(command, ["hook", "user-prompt", "--agent", "sumi", "--selection-profile", profile], { cwd: input.cwd, stdio: ["pipe", "pipe", "pipe"] });
41751
+ const chunks = []; let bytes = 0, failure;
41752
+ const timer = setTimeout(() => { failure = new Error("Skills prompt hook timed out"); child.kill("SIGKILL"); }, 15000);
41753
+ child.stdout.on("data", chunk => { bytes += chunk.length; if (bytes > 1048576) { failure = new Error("Skills prompt hook output exceeded its limit"); child.kill("SIGKILL"); } else chunks.push(chunk); });
41754
+ child.stderr.on("data", () => {});
41755
+ child.stdin.on("error", () => {});
41756
+ child.on("error", error => { clearTimeout(timer); reject(error); });
41757
+ child.on("close", code => {
41758
+ clearTimeout(timer);
41759
+ if (failure || code !== 0) return reject(failure ?? new Error("Skills prompt hook failed"));
41760
+ try {
41761
+ const result = JSON.parse(Buffer.concat(chunks).toString("utf8"));
41762
+ if (!result || typeof result !== "object" || Array.isArray(result)) throw new Error("Invalid Skills hook response");
41763
+ if (result.decision === "block" || result.continue === false) throw new Error("Skills prompt hook refused");
41764
+ if (Object.keys(result).length && (!result.hookSpecificOutput || result.hookSpecificOutput.hookEventName !== input.hook_event_name)) throw new Error("Invalid Skills hook response");
41765
+ const text = result.hookSpecificOutput?.additionalContext ?? "";
41766
+ if (typeof text !== "string") throw new Error("Invalid Skills prompt context");
41767
+ resolve(text);
41768
+ } catch (error) { reject(error); }
41769
+ });
41770
+ child.stdin.end(JSON.stringify(input));
41771
+ });
41772
+ }
41773
+ export default {
41774
+ id: "local.hasna-skills-cli",
41775
+ async setup(ctx) {
41776
+ if (!ctx?.session?.hook || !ctx?.session?.get || !ctx?.skill?.transform || !ctx?.tool?.hook) throw new Error("Unsupported Sumi native Skills contract");
41777
+ const registrations = [];
41778
+ const sessions = new Set();
41779
+ async function input(sessionID, prompt, first) {
41780
+ // The Promise adapter unwraps single-data endpoint responses.
41781
+ const session = await ctx.session.get({ sessionID });
41782
+ if (!session || session.id !== sessionID || typeof session.location?.directory !== "string" || (session.parentID !== undefined && typeof session.parentID !== "string") || session.parentID === sessionID) throw new Error("Invalid Sumi session custody");
41783
+ return { hook_event_name: first ? session.parentID ? "SubagentStart" : "SessionStart" : "UserPromptSubmit", cwd: session.location.directory, session_id: sessionID, parent_session_id: session.parentID ?? null, prompt, restore: true };
41784
+ }
41785
+ registrations.push(await ctx.skill.transform(editor => {
41786
+ for (const skill of editor.list()) if (skill.id !== "skills-cli" || skill.name !== "skills-cli") editor.remove(skill.id);
41787
+ }));
41788
+ // Native config transforms may add skills after this transform. Guard
41789
+ // both direct tool calls and prompt attachments at the consumption edge.
41790
+ registrations.push(await ctx.tool.hook("execute.before", event => {
41791
+ if (event.tool === "skill" && event.input?.id !== "skills-cli") throw new Error("Native Sumi skill payload refused; use Skills CLI");
41792
+ }));
41793
+ registrations.push(await ctx.session.hook("prompt", async event => {
41794
+ if (typeof event.prompt?.text !== "string") throw new Error("Invalid Sumi prompt");
41795
+ if (event.prompt.skills !== undefined && (!Array.isArray(event.prompt.skills) || event.prompt.skills.some(skill => skill?.id !== "skills-cli"))) throw new Error("Native Sumi skill attachment refused; use Skills CLI");
41796
+ await context(await input(event.sessionID, event.prompt.text, !sessions.has(event.sessionID)));
41797
+ sessions.add(event.sessionID);
41798
+ }));
41799
+ registrations.push(await ctx.session.hook("context", async event => {
41800
+ const last = event.messages.findLast(message => message.role === "user");
41801
+ const prompt = (last?.content ?? []).filter(part => part.type === "text").map(part => part.text).join("\\n");
41802
+ // Recheck on every primary request, including resumed and synthetic
41803
+ // sessions. The CLI owns optional failures versus explicit refusals.
41804
+ const text = await context(await input(event.sessionID, prompt, !sessions.has(event.sessionID)));
41805
+ if (text) event.system.push({ type: "text", text });
41806
+ sessions.add(event.sessionID);
41807
+ }));
41808
+ return async () => { for (const registration of registrations) await registration.dispose(); };
41809
+ },
41810
+ };
41811
+ `;
41812
+ }
41813
+ var SUMI_SKILL_PERMISSIONS = [
41814
+ { action: "skill", resource: "*", effect: "deny" },
41815
+ { action: "skill", resource: "skills-cli", effect: "allow" }
41816
+ ];
41817
+
41683
41818
  // src/lib/agent-discovery.ts
41684
41819
  var digest2 = (text2) => createHash17("sha256").update(text2).digest("hex");
41685
41820
  function parseConfig(text2, path, toml = false) {
@@ -41696,7 +41831,7 @@ function safe4(path) {
41696
41831
  if (!isAbsolute16(path) || path.includes("\x00"))
41697
41832
  throw new Error("Expected an absolute native discovery path");
41698
41833
  for (let cursor = path;; cursor = dirname14(cursor)) {
41699
- if (lstatSync18(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
41834
+ if (lstatSync19(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
41700
41835
  throw new Error(`Refusing symlink native discovery input: ${cursor}`);
41701
41836
  if (dirname14(cursor) === cursor)
41702
41837
  break;
@@ -41706,7 +41841,7 @@ function read2(path, changes) {
41706
41841
  safe4(path);
41707
41842
  if (changes?.has(path))
41708
41843
  return changes.get(path);
41709
- const stat2 = lstatSync18(path, { throwIfNoEntry: false });
41844
+ const stat2 = lstatSync19(path, { throwIfNoEntry: false });
41710
41845
  if (!stat2)
41711
41846
  return null;
41712
41847
  if (!stat2.isFile() || stat2.size > 16 * 1024 * 1024)
@@ -41817,12 +41952,12 @@ function codexInstallationRoots(binding) {
41817
41952
  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)
41818
41953
  throw new Error("Invalid native installation input proof");
41819
41954
  const cache = dirname14(dirname14(proof.plugins[0].pluginParent));
41820
- const config = join21(dirname14(dirname14(cache)), "config.toml"), home = dirname14(dirname14(dirname14(cache)));
41955
+ const config = join22(dirname14(dirname14(cache)), "config.toml"), home = dirname14(dirname14(dirname14(cache)));
41821
41956
  const configSource = binding.sources.find((source) => source.path === config && source.sha256 !== null && (!source.format || source.format === "toml" && source.fields?.includes("plugins")));
41822
- const nativeRoots = NATIVE_SKILL_ROOTS.filter(([agent]) => agent === "codex").map(([, path]) => join21(home, path));
41957
+ const nativeRoots = NATIVE_SKILL_ROOTS.filter(([agent]) => agent === "codex").map(([, path]) => join22(home, path));
41823
41958
  if (!configSource || proof.plugins.some((input) => nativeRoots.some((root2) => root2 === input.sourceRoot || root2.startsWith(input.sourceRoot + sep4) || input.sourceRoot.startsWith(root2 + sep4)) || binding.sources.some((source) => basename7(source.path) === "config.toml" && (source.path === input.sourceRoot || source.path.startsWith(input.sourceRoot + sep4)))))
41824
41959
  throw new Error("Native installation input overlaps configuration or loading roots");
41825
- if (proof.plugins.some((input) => dirname14(dirname14(input.pluginParent)) !== cache || !binding.sources.some((source) => source.path === join21(input.sourceRoot, ".codex-plugin/plugin.json") && source.sha256 !== null && source.format === undefined && source.fields === undefined)))
41960
+ if (proof.plugins.some((input) => dirname14(dirname14(input.pluginParent)) !== cache || !binding.sources.some((source) => source.path === join22(input.sourceRoot, ".codex-plugin/plugin.json") && source.sha256 !== null && source.format === undefined && source.fields === undefined)))
41826
41961
  throw new Error("Missing native installation input source witness");
41827
41962
  return reviewedCodexPluginSourceRoots(cache, proof.plugins, (path) => {
41828
41963
  const text2 = read2(path);
@@ -41864,19 +41999,19 @@ function captureDiscoveryPathSources(paths) {
41864
41999
  const budget = discoveryByteBudget();
41865
42000
  return paths.map((path) => ({ path, hashMode: "path-bytes", sha256: hashDiscoveryPathFile(path, budget) }));
41866
42001
  }
41867
- function assertProjectDiscovery(agent, directories, home, canonical6 = resolve14, reviewed) {
42002
+ function assertProjectDiscovery(agent, directories, home, canonical6 = resolve15, reviewed) {
41868
42003
  const homeConfigPath = canonical6(agentDiscoveryConfigPath(home, agent));
41869
42004
  for (const directory of directories) {
41870
- const isHome = resolve14(directory) === resolve14(home);
42005
+ const isHome = resolve15(directory) === resolve15(home);
41871
42006
  if (agent === "hermes") {
41872
42007
  assertHermesEnvironment(home);
41873
42008
  continue;
41874
42009
  }
41875
- if (isHome && agent !== "claude")
42010
+ if (isHome && agent !== "claude" && agent !== "sumi")
41876
42011
  continue;
41877
- 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"] : [".cursor/hooks.json"];
42012
+ 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"];
41878
42013
  for (const suffix of paths) {
41879
- const path = canonical6(join21(directory, suffix)), raw = read2(path);
42014
+ const path = canonical6(join22(directory, suffix)), raw = read2(path);
41880
42015
  if (raw === null)
41881
42016
  continue;
41882
42017
  const isRootAliasedHomeConfig = agent === "claude" && suffix === ".claude/settings.json" || agent === "codex" && suffix === ".codex/config.toml";
@@ -41885,7 +42020,7 @@ function assertProjectDiscovery(agent, directories, home, canonical6 = resolve14
41885
42020
  if (suffix.endsWith(".jsonc"))
41886
42021
  throw new Error(`NATIVE_SKILL_DRIFT: project JSONC discovery configuration requires review: ${path}`);
41887
42022
  const config = parseConfig(raw, path, suffix.endsWith(".toml"));
41888
- const keys2 = agent === "claude" ? ["enabledPlugins", "extraKnownMarketplaces", "skillOverrides"] : agent === "codex" ? ["plugins", "marketplaces", "skills"] : agent === "gemini" ? ["skills", "extensions"] : agent === "opencode" ? ["plugin", "skills"] : ["hooks"];
42023
+ const keys2 = agent === "claude" ? ["enabledPlugins", "extraKnownMarketplaces", "skillOverrides"] : agent === "codex" ? ["plugins", "marketplaces", "skills"] : agent === "gemini" ? ["skills", "extensions"] : agent === "opencode" ? ["plugin", "skills"] : agent === "sumi" ? ["plugin", "plugins", "skills", "permissions"] : ["hooks"];
41889
42024
  let admittedPlugins = false;
41890
42025
  if (agent === "claude" && reviewed?.agent === agent && reviewed.method === "reviewed" && config.enabledPlugins && typeof config.enabledPlugins === "object" && !Array.isArray(config.enabledPlugins)) {
41891
42026
  const exact = reviewed.sources.find((source) => source.path === path && source.format === undefined && source.fields === undefined && (source.hashMode === undefined || source.hashMode === "bytes"));
@@ -41898,19 +42033,28 @@ function assertProjectDiscovery(agent, directories, home, canonical6 = resolve14
41898
42033
  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)))
41899
42034
  throw new Error(`NATIVE_SKILL_DRIFT: higher-precedence project skill or hook configuration requires review: ${path}`);
41900
42035
  }
42036
+ if (agent === "sumi")
42037
+ for (const name of ["plugin", "plugins"]) {
42038
+ const path = canonical6(join22(directory, ".sumi", name));
42039
+ safe4(path);
42040
+ if (lstatSync19(path, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(path).length)
42041
+ throw new Error(`NATIVE_SKILL_DRIFT: project Sumi plugins require a dedicated discovery review: ${path}`);
42042
+ }
41901
42043
  if (agent === "claude") {
41902
- const commands = canonical6(join21(directory, ".claude/commands"));
42044
+ const commands = canonical6(join22(directory, ".claude/commands"));
41903
42045
  safe4(commands);
41904
- if (lstatSync18(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length)
42046
+ if (lstatSync19(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length)
41905
42047
  throw new Error("NATIVE_SKILL_DRIFT: legacy project command discovery requires a dedicated format adapter");
41906
42048
  }
41907
42049
  }
41908
42050
  }
41909
42051
  function agentDiscoveryConfigPath(home, agent) {
41910
- return join21(home, agent === "hermes" ? ".hermes/config.yaml" : agent === "opencode" ? ".config/opencode/opencode.json" : `.${agent}/${agent === "codex" ? "config.toml" : agent === "cursor" ? "hooks.json" : "settings.json"}`);
42052
+ if (agent === "sumi")
42053
+ return sumiConfigPath(home);
42054
+ return join22(home, agent === "hermes" ? ".hermes/config.yaml" : agent === "opencode" ? ".config/opencode/opencode.json" : `.${agent}/${agent === "codex" ? "config.toml" : agent === "cursor" ? "hooks.json" : "settings.json"}`);
41911
42055
  }
41912
42056
  function resolveAgentDiscovery(options) {
41913
- const canonical6 = options.canonical ?? resolve14, home = resolve14(options.home), agent = options.agent;
42057
+ const canonical6 = options.canonical ?? resolve15, home = resolve15(options.home), agent = options.agent;
41914
42058
  const sources = [], roots = new Set, builtinNames = [];
41915
42059
  const witness = (path, format, fields2) => {
41916
42060
  const source = { path: canonical6(path), sha256: null, ...format ? { format, fields: fields2 } : {} };
@@ -41921,13 +42065,49 @@ function resolveAgentDiscovery(options) {
41921
42065
  if (agent === "hermes")
41922
42066
  assertHermesEnvironment(home);
41923
42067
  const configPath = agentDiscoveryConfigPath(home, agent);
41924
- const configText = witness(configPath, agent === "hermes" ? "yaml" : agent === "codex" ? "toml" : "json", agent === "hermes" ? ["skills", "plugins", "hooks"] : agent === "claude" ? ["enabledPlugins", "extraKnownMarketplaces"] : agent === "codex" ? [...CODEX_DISCOVERY_PROJECTION_FIELDS] : agent === "gemini" ? ["skills", "extensions", "security"] : agent === "opencode" ? ["plugin", "skills"] : ["version"]);
42068
+ const configText = witness(configPath, agent === "hermes" ? "yaml" : agent === "codex" ? "toml" : "json", agent === "hermes" ? ["skills", "plugins", "hooks"] : agent === "claude" ? ["enabledPlugins", "extraKnownMarketplaces"] : agent === "codex" ? [...CODEX_DISCOVERY_PROJECTION_FIELDS] : agent === "gemini" ? ["skills", "extensions", "security"] : agent === "opencode" ? ["plugin", "skills"] : agent === "sumi" ? ["skills", "plugin", "plugins", "permissions"] : ["version"]);
41925
42069
  const config = configText === null ? {} : agent === "hermes" ? parseHermesConfig(configText) : parseConfig(configText, configPath, agent === "codex");
41926
42070
  const unresolved = (detail) => {
41927
42071
  throw new Error(`Native discovery is unresolved (${agent}: ${detail}); provide a reviewed --discovery-inputs file`);
41928
42072
  };
42073
+ if (agent === "sumi") {
42074
+ const directory = sumiConfigDirectory(home);
42075
+ if (witness(join22(directory, "sumi.jsonc")) !== null)
42076
+ unresolved("JSONC configuration requires a supported format adapter");
42077
+ for (const root2 of [directory, join22(home, ".claude"), join22(home, ".agents")])
42078
+ for (const name of ["skill", "skills"])
42079
+ roots.add(join22(root2, name));
42080
+ if (config.skills !== undefined && (!Array.isArray(config.skills) || config.skills.some((path) => typeof path !== "string")))
42081
+ unresolved("skills must be a string array");
42082
+ for (const value of config.skills ?? []) {
42083
+ if (typeof value !== "string" || /[\0$]/.test(value) || !value || !(isAbsolute16(value) || value.startsWith("~/")))
42084
+ unresolved("remote or relative skill sources need a dedicated discovery adapter");
42085
+ roots.add(value.startsWith("~/") ? join22(home, value.slice(2)) : value);
42086
+ }
42087
+ for (const key of ["plugin", "plugins"])
42088
+ if (config[key] !== undefined && !Array.isArray(config[key]))
42089
+ unresolved(`${key} must be an array`);
42090
+ const plugins = [join22(directory, "plugin"), join22(directory, "plugins")];
42091
+ for (const path of plugins) {
42092
+ safe4(path);
42093
+ if (lstatSync19(path, { throwIfNoEntry: false })?.isDirectory())
42094
+ for (const name of readdirSync7(path).sort()) {
42095
+ if (name === "skills-cli.js" && path === plugins[1])
42096
+ continue;
42097
+ const target = join22(path, name);
42098
+ if (!lstatSync19(target).isFile())
42099
+ unresolved("local plugin packages need a dedicated discovery adapter");
42100
+ witness(target);
42101
+ }
42102
+ }
42103
+ for (const root2 of roots) {
42104
+ safe4(root2);
42105
+ if (lstatSync19(root2, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(root2).some((name) => name.endsWith(".md")))
42106
+ unresolved("flat markdown skills require a dedicated native migration adapter");
42107
+ }
42108
+ }
41929
42109
  if (agent === "hermes") {
41930
- const profile = witness(join21(home, ".hermes/active_profile"));
42110
+ const profile = witness(join22(home, ".hermes/active_profile"));
41931
42111
  if (profile?.trim() && profile.trim() !== "default")
41932
42112
  unresolved("a non-default profile is active");
41933
42113
  const declared = config.skills?.external_dirs ?? [], paths = typeof declared === "string" ? [declared] : declared;
@@ -41941,7 +42121,7 @@ function resolveAgentDiscovery(options) {
41941
42121
  continue;
41942
42122
  if (normalized.startsWith("~") && normalized !== "~" && !normalized.startsWith("~/"))
41943
42123
  unresolved("user-specific tilde expansion requires a separate discovery adapter");
41944
- const path = normalized === "~" ? home : normalized.startsWith("~/") ? join21(home, normalized.slice(2)) : resolve14(home, ".hermes", normalized);
42124
+ const path = normalized === "~" ? home : normalized.startsWith("~/") ? join22(home, normalized.slice(2)) : resolve15(home, ".hermes", normalized);
41945
42125
  safe4(path);
41946
42126
  roots.add(path);
41947
42127
  }
@@ -41950,8 +42130,8 @@ function resolveAgentDiscovery(options) {
41950
42130
  const executable = Bun.which("gemini");
41951
42131
  if (executable) {
41952
42132
  let packageRoot;
41953
- for (let directory = dirname14(realpathSync6(executable)), depth = 0;depth < 8; directory = dirname14(directory), depth++) {
41954
- const path = join21(directory, "package.json"), raw = read2(path);
42133
+ for (let directory = dirname14(realpathSync7(executable)), depth = 0;depth < 8; directory = dirname14(directory), depth++) {
42134
+ const path = join22(directory, "package.json"), raw = read2(path);
41955
42135
  if (raw !== null && parseConfig(raw, path).name === "@google/gemini-cli") {
41956
42136
  packageRoot = directory;
41957
42137
  witness(path);
@@ -41962,12 +42142,12 @@ function resolveAgentDiscovery(options) {
41962
42142
  }
41963
42143
  if (!packageRoot)
41964
42144
  unresolved("installed Gemini package layout is not recognized");
41965
- const builtinRoot = join21(packageRoot, "bundle/builtin");
42145
+ const builtinRoot = join22(packageRoot, "bundle/builtin");
41966
42146
  safe4(builtinRoot);
41967
- if (!lstatSync18(builtinRoot, { throwIfNoEntry: false })?.isDirectory())
42147
+ if (!lstatSync19(builtinRoot, { throwIfNoEntry: false })?.isDirectory())
41968
42148
  unresolved("installed Gemini builtin root is missing");
41969
42149
  for (const name of readdirSync7(builtinRoot).sort()) {
41970
- const text2 = witness(join21(builtinRoot, name, "SKILL.md"));
42150
+ const text2 = witness(join22(builtinRoot, name, "SKILL.md"));
41971
42151
  const match = text2?.match(/^---\r?\n[\s\S]*?^name:\s*([a-z0-9][a-z0-9-]*)\s*$/m);
41972
42152
  if (!match?.[1] || builtinNames.includes(match[1]))
41973
42153
  unresolved("installed Gemini builtin name is missing or ambiguous");
@@ -42009,39 +42189,39 @@ function resolveAgentDiscovery(options) {
42009
42189
  function plugin(root2) {
42010
42190
  root2 = canonical6(root2);
42011
42191
  safe4(root2);
42012
- const manifestPath = join21(root2, agent === "claude" ? ".claude-plugin/plugin.json" : ".codex-plugin/plugin.json");
42192
+ const manifestPath = join22(root2, agent === "claude" ? ".claude-plugin/plugin.json" : ".codex-plugin/plugin.json");
42013
42193
  const raw = witness(manifestPath);
42014
42194
  if (raw === null)
42015
42195
  unresolved("plugin manifest missing");
42016
42196
  const manifest = parseConfig(raw, manifestPath);
42017
- const hooks = witness(join21(root2, "hooks/hooks.json"));
42197
+ const hooks = witness(join22(root2, "hooks/hooks.json"));
42018
42198
  if (manifest.hooks !== undefined || hooks !== null)
42019
42199
  unresolved("plugin hooks require a separate no-skill-injection review");
42020
- const commands = join21(root2, "commands");
42200
+ const commands = join22(root2, "commands");
42021
42201
  safe4(commands);
42022
- if (agent === "claude" && (manifest.commands !== undefined || lstatSync18(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length))
42202
+ if (agent === "claude" && (manifest.commands !== undefined || lstatSync19(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length))
42023
42203
  unresolved("legacy command discovery requires retirement or a dedicated format adapter");
42024
- const rootSkill = witness(join21(root2, "SKILL.md"));
42204
+ const rootSkill = witness(join22(root2, "SKILL.md"));
42025
42205
  if (rootSkill !== null)
42026
42206
  roots.add(root2);
42027
42207
  const declared = manifest.skills === undefined ? ["./skills"] : typeof manifest.skills === "string" ? [manifest.skills] : manifest.skills;
42028
42208
  if (!Array.isArray(declared) || declared.some((path) => typeof path !== "string"))
42029
42209
  unresolved("unsupported plugin skill paths");
42030
42210
  if (agent === "claude")
42031
- roots.add(join21(root2, "skills"));
42211
+ roots.add(join22(root2, "skills"));
42032
42212
  for (const value of declared) {
42033
- const path = resolve14(root2, value);
42213
+ const path = resolve15(root2, value);
42034
42214
  if (path !== root2 && !path.startsWith(root2 + sep4))
42035
42215
  unresolved("plugin skill path escapes its root");
42036
42216
  roots.add(path.endsWith(`${sep4}SKILL.md`) ? dirname14(path) : path);
42037
42217
  }
42038
42218
  }
42039
42219
  if (agent === "claude") {
42040
- const registrations = witness(join21(home, ".claude/plugins/installed_plugins.json"));
42041
- const installed = registrations === null ? {} : parseConfig(registrations, join21(home, ".claude/plugins/installed_plugins.json")).plugins;
42042
- const commands = canonical6(join21(home, ".claude/commands"));
42220
+ const registrations = witness(join22(home, ".claude/plugins/installed_plugins.json"));
42221
+ const installed = registrations === null ? {} : parseConfig(registrations, join22(home, ".claude/plugins/installed_plugins.json")).plugins;
42222
+ const commands = canonical6(join22(home, ".claude/commands"));
42043
42223
  safe4(commands);
42044
- if (lstatSync18(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length)
42224
+ if (lstatSync19(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length)
42045
42225
  unresolved("legacy home command discovery requires a dedicated format adapter");
42046
42226
  for (const [id2, enabled] of Object.entries(config.enabledPlugins ?? {})) {
42047
42227
  if (enabled === false)
@@ -42063,16 +42243,16 @@ function resolveAgentDiscovery(options) {
42063
42243
  const market = config.marketplaces?.[marketplace] ?? (marketplace === "personal" ? { source_type: "local", source: home } : undefined);
42064
42244
  if (split < 1 || market?.source_type !== "local" || typeof market.source !== "string" || !isAbsolute16(market.source))
42065
42245
  unresolved("enabled plugin marketplace is not an explicit local source");
42066
- const catalogText = witness(join21(market.source, ".agents/plugins/marketplace.json"));
42246
+ const catalogText = witness(join22(market.source, ".agents/plugins/marketplace.json"));
42067
42247
  if (catalogText === null)
42068
42248
  unresolved("marketplace catalog missing");
42069
- const catalog = parseConfig(catalogText, join21(market.source, ".agents/plugins/marketplace.json")), matches = Array.isArray(catalog.plugins) ? catalog.plugins.filter((item) => item.name === name) : [];
42249
+ const catalog = parseConfig(catalogText, join22(market.source, ".agents/plugins/marketplace.json")), matches = Array.isArray(catalog.plugins) ? catalog.plugins.filter((item) => item.name === name) : [];
42070
42250
  if (matches.length !== 1 || matches[0]?.source?.source !== "local" || typeof matches[0]?.source?.path !== "string")
42071
42251
  unresolved("plugin catalog source is missing or ambiguous");
42072
- plugin(resolve14(market.source, matches[0].source.path));
42252
+ plugin(resolve15(market.source, matches[0].source.path));
42073
42253
  }
42074
42254
  } else if (agent === "opencode") {
42075
- if (witness(join21(home, ".config/opencode/opencode.jsonc")) !== null || witness(join21(home, ".config/opencode/config.json")) !== null)
42255
+ if (witness(join22(home, ".config/opencode/opencode.jsonc")) !== null || witness(join22(home, ".config/opencode/config.json")) !== null)
42076
42256
  unresolved("additional config layers require review");
42077
42257
  if ((config.plugin?.length ?? 0) > 0 || config.skills?.urls?.length)
42078
42258
  unresolved("external plugin or remote skill source");
@@ -42081,14 +42261,17 @@ function resolveAgentDiscovery(options) {
42081
42261
  unresolved("relative or malformed added skill root");
42082
42262
  roots.add(path);
42083
42263
  }
42084
- const localPlugins = join21(home, ".config/opencode/plugins");
42264
+ const localPlugins = join22(home, ".config/opencode/plugins");
42085
42265
  safe4(localPlugins);
42086
- if (lstatSync18(localPlugins, { throwIfNoEntry: false }) && readdirSync7(localPlugins).some((name) => name !== "skills-cli.js"))
42266
+ if (lstatSync19(localPlugins, { throwIfNoEntry: false }) && readdirSync7(localPlugins).some((name) => name !== "skills-cli.js"))
42087
42267
  unresolved("additional local plugin hooks require review");
42268
+ } else if (agent === "sumi") {
42269
+ if ((config.plugin?.length ?? 0) > 0 || (config.plugins?.length ?? 0) > 0 || sources.some((source) => source.path !== canonical6(configPath) && source.path !== canonical6(join22(sumiConfigDirectory(home), "sumi.jsonc")) && source.sha256 !== null))
42270
+ unresolved("external or foreign local plugins require review");
42088
42271
  } else if (agent === "hermes") {
42089
- for (const directory of [join21(home, ".hermes/plugins"), join21(home, ".hermes/hermes-agent")]) {
42272
+ for (const directory of [join22(home, ".hermes/plugins"), join22(home, ".hermes/hermes-agent")]) {
42090
42273
  safe4(directory);
42091
- if (lstatSync18(directory, { throwIfNoEntry: false }))
42274
+ if (lstatSync19(directory, { throwIfNoEntry: false }))
42092
42275
  unresolved("installed runtime/plugin discovery requires reviewed source bindings");
42093
42276
  }
42094
42277
  if (Bun.which("hermes") || Object.keys(config.plugins ?? {}).length)
@@ -42096,28 +42279,28 @@ function resolveAgentDiscovery(options) {
42096
42279
  } else if (agent === "gemini") {
42097
42280
  if (Object.keys(config.extensions ?? {}).length || config.skills?.paths?.length)
42098
42281
  unresolved("custom extension or skill paths");
42099
- const directory = join21(home, ".gemini/extensions");
42282
+ const directory = join22(home, ".gemini/extensions");
42100
42283
  safe4(directory);
42101
- if (lstatSync18(directory, { throwIfNoEntry: false }))
42284
+ if (lstatSync19(directory, { throwIfNoEntry: false }))
42102
42285
  for (const name of readdirSync7(directory)) {
42103
- const root2 = join21(directory, name);
42286
+ const root2 = join22(directory, name);
42104
42287
  safe4(root2);
42105
- if (!lstatSync18(root2)?.isDirectory())
42288
+ if (!lstatSync19(root2)?.isDirectory())
42106
42289
  continue;
42107
- const raw = witness(join21(root2, "gemini-extension.json"));
42290
+ const raw = witness(join22(root2, "gemini-extension.json"));
42108
42291
  if (raw === null)
42109
42292
  unresolved("extension registration missing");
42110
- const manifest = parseConfig(raw, join21(root2, "gemini-extension.json"));
42111
- if (manifest.hooks !== undefined || witness(join21(root2, "hooks/hooks.json")) !== null || witness(join21(root2, ".gemini-extension-install.json")) !== null)
42293
+ const manifest = parseConfig(raw, join22(root2, "gemini-extension.json"));
42294
+ if (manifest.hooks !== undefined || witness(join22(root2, "hooks/hooks.json")) !== null || witness(join22(root2, ".gemini-extension-install.json")) !== null)
42112
42295
  unresolved("extension hooks or linked registration require review");
42113
- roots.add(join21(root2, "skills"));
42296
+ roots.add(join22(root2, "skills"));
42114
42297
  }
42115
42298
  }
42116
- return { agent, roots: [...roots].sort(), sources, method: "automatic", ...agent === "gemini" ? { builtinNames } : {}, ...agent === "hermes" ? { directories: captureDiscoveryDirectories([join21(home, ".hermes/plugins"), join21(home, ".hermes/hermes-agent")].map((path) => canonical6(path))) } : {} };
42299
+ return { agent, roots: [...roots].sort(), sources, method: "automatic", ...agent === "gemini" ? { builtinNames } : {}, ...agent === "hermes" ? { directories: captureDiscoveryDirectories([join22(home, ".hermes/plugins"), join22(home, ".hermes/hermes-agent")].map((path) => canonical6(path))) } : {} };
42117
42300
  }
42118
42301
 
42119
42302
  // src/lib/agent-adapters.ts
42120
- var INTEGRATION_AGENTS = ["claude", "codex", "gemini", "opencode", "cursor", "hermes"];
42303
+ var INTEGRATION_AGENTS = ["claude", "codex", "gemini", "opencode", "cursor", "hermes", "sumi"];
42121
42304
  function renderAgentHookCommand(command, agent, profileId, event) {
42122
42305
  if (typeof profileId !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(profileId) || profileId.includes(".."))
42123
42306
  throw new Error("Invalid selection profile id");
@@ -42128,6 +42311,7 @@ var AGENT_ADAPTERS = {
42128
42311
  codex: { root: ".codex/skills", config: ".codex/hooks.json", events: ["UserPromptSubmit", "SessionStart", "SubagentStart"], promptContext: true },
42129
42312
  gemini: { root: ".gemini/skills", config: ".gemini/settings.json", events: ["BeforeAgent", "SessionStart"], promptContext: true },
42130
42313
  opencode: { root: ".config/opencode/skills", config: ".config/opencode/opencode.json", events: ["chat.message"], promptContext: true },
42314
+ sumi: { root: ".hasna-internal/sumi/config/skills", config: ".hasna-internal/sumi/config/sumi.json", events: ["prompt", "context"], promptContext: true },
42131
42315
  hermes: { root: ".hermes/skills", config: ".hermes/config.yaml", events: ["pre_llm_call", "pre_tool_call"], promptContext: true, promptFailureMode: "open", toolFailureMode: "supervised-child-errors-block", requiresNativeTrust: true },
42132
42316
  cursor: { root: ".cursor/skills", config: ".cursor/hooks.json", events: ["beforeSubmitPrompt", "sessionStart"], promptContext: false }
42133
42317
  };
@@ -42484,11 +42668,11 @@ function isSystemRootAlias(path) {
42484
42668
  const target = `/private${path}`, link = `private${path}`;
42485
42669
  const identity4 = (stat2) => `${stat2.dev}:${stat2.ino}:${stat2.ctimeNs}:${stat2.uid}:${stat2.mode}`;
42486
42670
  try {
42487
- const before = lstatSync19(path, { bigint: true });
42671
+ const before = lstatSync20(path, { bigint: true });
42488
42672
  if (!before.isSymbolicLink() || before.uid !== 0n || readlinkSync4(path) !== link)
42489
42673
  return false;
42490
42674
  const directories = ["/", "/private", target].map((directory) => {
42491
- const stat2 = lstatSync19(directory, { bigint: true });
42675
+ const stat2 = lstatSync20(directory, { bigint: true });
42492
42676
  if (!stat2.isDirectory() || stat2.uid !== 0n)
42493
42677
  throw new Error("Untrusted system alias directory");
42494
42678
  if (directory !== "/private/tmp") {
@@ -42505,23 +42689,23 @@ function isSystemRootAlias(path) {
42505
42689
  }
42506
42690
  return { directory, identity: identity4(stat2) };
42507
42691
  });
42508
- return realpathSync7(path) === target && readlinkSync4(path) === link && identity4(lstatSync19(path, { bigint: true })) === identity4(before) && directories.every((item) => identity4(lstatSync19(item.directory, { bigint: true })) === item.identity);
42692
+ return realpathSync8(path) === target && readlinkSync4(path) === link && identity4(lstatSync20(path, { bigint: true })) === identity4(before) && directories.every((item) => identity4(lstatSync20(item.directory, { bigint: true })) === item.identity);
42509
42693
  } catch {
42510
42694
  return false;
42511
42695
  }
42512
42696
  }
42513
42697
  function canonicalSystemPath(path) {
42514
- const absolute = resolve15(path), root2 = `/${absolute.split(sep5)[1]}`;
42515
- if (process.platform !== "darwin" || !["/var", "/tmp", "/etc"].includes(root2) || !lstatSync19(root2, { throwIfNoEntry: false })?.isSymbolicLink())
42698
+ const absolute = resolve16(path), root2 = `/${absolute.split(sep5)[1]}`;
42699
+ if (process.platform !== "darwin" || !["/var", "/tmp", "/etc"].includes(root2) || !lstatSync20(root2, { throwIfNoEntry: false })?.isSymbolicLink())
42516
42700
  return absolute;
42517
42701
  if (!isSystemRootAlias(root2))
42518
42702
  throw new Error(`Refusing symlink path: ${root2}`);
42519
42703
  return `/private${absolute}`;
42520
42704
  }
42521
42705
  function assertSafePath(path) {
42522
- let cursor = resolve15(path);
42706
+ let cursor = resolve16(path);
42523
42707
  while (true) {
42524
- if (lstatSync19(cursor, { throwIfNoEntry: false })?.isSymbolicLink() && !isSystemRootAlias(cursor))
42708
+ if (lstatSync20(cursor, { throwIfNoEntry: false })?.isSymbolicLink() && !isSystemRootAlias(cursor))
42525
42709
  throw new Error(`Refusing symlink path: ${cursor}`);
42526
42710
  const parent = dirname15(cursor);
42527
42711
  if (parent === cursor)
@@ -42531,16 +42715,16 @@ function assertSafePath(path) {
42531
42715
  }
42532
42716
  function readRootAlias(home, agent) {
42533
42717
  assertSafePath(home);
42534
- const realHome = realpathSync7(home), alias = join22(realHome, `.${agent}`);
42535
- const stat2 = lstatSync19(alias, { throwIfNoEntry: false, bigint: true });
42718
+ const realHome = realpathSync8(home), alias = join23(realHome, `.${agent}`);
42719
+ const stat2 = lstatSync20(alias, { throwIfNoEntry: false, bigint: true });
42536
42720
  if (!stat2?.isSymbolicLink())
42537
42721
  throw new Error(`Agent root alias changed after planning: ${alias}`);
42538
- const link = readlinkSync4(alias), targetPath = resolve15(dirname15(alias), link);
42722
+ const link = readlinkSync4(alias), targetPath = resolve16(dirname15(alias), link);
42539
42723
  assertSafePath(targetPath);
42540
- const targetStat = lstatSync19(targetPath, { throwIfNoEntry: false });
42724
+ const targetStat = lstatSync20(targetPath, { throwIfNoEntry: false });
42541
42725
  if (!targetStat?.isDirectory())
42542
42726
  throw new Error(`Agent root alias must target an existing directory: ${alias}`);
42543
- const target = realpathSync7(targetPath), inside = relative4(realHome, target);
42727
+ const target = realpathSync8(targetPath), inside = relative4(realHome, target);
42544
42728
  if (!inside || inside === ".." || inside.startsWith(`..${sep5}`) || isAbsolute17(inside))
42545
42729
  throw new Error(`Agent root alias target must be inside the real home: ${alias}`);
42546
42730
  return { agent, home: realHome, alias, target, link, aliasIdentity: `${stat2.dev}:${stat2.ino}:${stat2.ctimeNs}`, targetIdentity: `${targetStat.dev}:${targetStat.ino}` };
@@ -42550,7 +42734,7 @@ function rootAliases(home, allowed = false) {
42550
42734
  return [];
42551
42735
  const result = [];
42552
42736
  for (const agent of ["claude", "codex"])
42553
- if (lstatSync19(join22(home, `.${agent}`), { throwIfNoEntry: false })?.isSymbolicLink())
42737
+ if (lstatSync20(join23(home, `.${agent}`), { throwIfNoEntry: false })?.isSymbolicLink())
42554
42738
  result.push(readRootAlias(home, agent));
42555
42739
  if (result.some((item, index) => result.slice(index + 1).some((other) => item.target === other.target || item.target.startsWith(other.target + sep5) || other.target.startsWith(item.target + sep5))))
42556
42740
  throw new Error("Agent root alias targets must not overlap");
@@ -42558,7 +42742,7 @@ function rootAliases(home, allowed = false) {
42558
42742
  }
42559
42743
  function canonicalAgentPath(path, aliases) {
42560
42744
  const absolute = canonicalSystemPath(path), binding = aliases.find((item) => absolute === item.alias || absolute.startsWith(item.alias + sep5));
42561
- return binding ? join22(binding.target, relative4(binding.alias, absolute)) : absolute;
42745
+ return binding ? join23(binding.target, relative4(binding.alias, absolute)) : absolute;
42562
42746
  }
42563
42747
  function disabledCodexSkillPaths(config, aliases) {
42564
42748
  const skills = config.skills;
@@ -42577,7 +42761,7 @@ function disabledCodexSkillPaths(config, aliases) {
42577
42761
  continue;
42578
42762
  let document2;
42579
42763
  try {
42580
- document2 = realpathSync7(canonicalAgentPath(entry.path, aliases));
42764
+ document2 = realpathSync8(canonicalAgentPath(entry.path, aliases));
42581
42765
  } catch {
42582
42766
  continue;
42583
42767
  }
@@ -42589,7 +42773,7 @@ function disabledCodexSkillPaths(config, aliases) {
42589
42773
  }
42590
42774
  function recheckRootAliases(aliases) {
42591
42775
  for (const binding of aliases) {
42592
- if (!["claude", "codex"].includes(binding.agent) || binding.alias !== join22(binding.home, `.${binding.agent}`))
42776
+ if (!["claude", "codex"].includes(binding.agent) || binding.alias !== join23(binding.home, `.${binding.agent}`))
42593
42777
  throw new Error("Invalid agent root alias binding");
42594
42778
  const current = readRootAlias(binding.home, binding.agent);
42595
42779
  if (JSON.stringify(current) !== JSON.stringify(binding))
@@ -42598,7 +42782,7 @@ function recheckRootAliases(aliases) {
42598
42782
  }
42599
42783
  function readNativeBytes(path, maximum = 64 * 1024 * 1024) {
42600
42784
  assertSafePath(path);
42601
- const before = lstatSync19(path);
42785
+ const before = lstatSync20(path);
42602
42786
  if (!before.isFile() || before.size > maximum)
42603
42787
  throw new Error("Unsupported or oversized native skill file");
42604
42788
  const descriptor = openSync16(path, constants12.O_RDONLY | constants12.O_NOFOLLOW | constants12.O_NONBLOCK);
@@ -42614,7 +42798,7 @@ function readNativeBytes(path, maximum = 64 * 1024 * 1024) {
42614
42798
  break;
42615
42799
  length += count;
42616
42800
  }
42617
- const after = fstatSync16(descriptor), current = lstatSync19(path);
42801
+ const after = fstatSync16(descriptor), current = lstatSync20(path);
42618
42802
  if (current.dev !== opened.dev || current.ino !== opened.ino || current.size !== after.size || current.mtimeMs !== after.mtimeMs || current.ctimeMs !== after.ctimeMs || length !== before.size || after.size !== before.size || after.mtimeMs !== opened.mtimeMs || after.ctimeMs !== opened.ctimeMs)
42619
42803
  throw new Error("Native skill file changed while reading");
42620
42804
  return bytes.subarray(0, length);
@@ -42626,14 +42810,14 @@ function treeHash(root2) {
42626
42810
  const hash2 = createHash18("sha256");
42627
42811
  let bytes = 0, files = 0;
42628
42812
  function visit2(path) {
42629
- const stat2 = lstatSync19(path);
42813
+ const stat2 = lstatSync20(path);
42630
42814
  if (stat2.isSymbolicLink())
42631
42815
  throw new Error(`Refusing symlink in skill: ${path}`);
42632
42816
  const rel = relative4(root2, path);
42633
42817
  if (stat2.isDirectory()) {
42634
42818
  hash2.update(`d\x00${rel}\x00`);
42635
42819
  for (const name of readdirSync8(path).sort())
42636
- visit2(join22(path, name));
42820
+ visit2(join23(path, name));
42637
42821
  return;
42638
42822
  }
42639
42823
  if (!stat2.isFile())
@@ -42655,10 +42839,10 @@ function selectNativeMigrationTargets(inventory, manifest) {
42655
42839
  const identities = new Set;
42656
42840
  const selected = [];
42657
42841
  for (const target of manifest.targets) {
42658
- if (!isAbsolute17(target.projectRoot) || resolve15(target.projectRoot) !== target.projectRoot)
42842
+ if (!isAbsolute17(target.projectRoot) || resolve16(target.projectRoot) !== target.projectRoot)
42659
42843
  throw new Error(`Native migration target project root must be an existing absolute directory: ${target.projectRoot}`);
42660
- const projectRoot = canonicalSystemPath(target.projectRoot), normalized = relative4(projectRoot, resolve15(projectRoot, target.path));
42661
- if (!existsSync6(projectRoot) || !lstatSync19(projectRoot).isDirectory())
42844
+ const projectRoot = canonicalSystemPath(target.projectRoot), normalized = relative4(projectRoot, resolve16(projectRoot, target.path));
42845
+ if (!existsSync7(projectRoot) || !lstatSync20(projectRoot).isDirectory())
42662
42846
  throw new Error(`Native migration target project root must be an existing absolute directory: ${target.projectRoot}`);
42663
42847
  assertSafePath(projectRoot);
42664
42848
  if (isAbsolute17(target.path) || target.path.includes("\\") || target.path.includes("\x00") || !normalized || normalized === ".." || normalized.startsWith(`..${sep5}`) || normalized !== target.path || !/^[0-9a-f]{64}$/.test(target.treeSha256))
@@ -42667,8 +42851,8 @@ function selectNativeMigrationTargets(inventory, manifest) {
42667
42851
  if (identities.has(identity4))
42668
42852
  throw new Error(`Duplicate native migration target: ${target.path}`);
42669
42853
  identities.add(identity4);
42670
- const expected = canonicalSystemPath(resolve15(target.projectRoot, target.path));
42671
- const matches = inventory.filter((entry2) => entry2.agent === target.agent && resolve15(entry2.path) === expected);
42854
+ const expected = canonicalSystemPath(resolve16(target.projectRoot, target.path));
42855
+ const matches = inventory.filter((entry2) => entry2.agent === target.agent && resolve16(entry2.path) === expected);
42672
42856
  if (matches.length !== 1)
42673
42857
  throw new Error(`Native migration target was not found exactly once: ${target.agent} ${target.projectRoot}/${target.path}`);
42674
42858
  const entry = matches[0];
@@ -42697,9 +42881,9 @@ function projectAncestorDirectories(projects) {
42697
42881
  }
42698
42882
  function inventoryNativeSkills(home = homedir3(), options = {}) {
42699
42883
  home = canonicalSystemPath(home);
42700
- if (options.reviewedCacheAlias !== undefined && (!options.includeVendor || !isAbsolute17(options.reviewedCacheAlias) || resolve15(options.reviewedCacheAlias) !== options.reviewedCacheAlias))
42884
+ if (options.reviewedCacheAlias !== undefined && (!options.includeVendor || !isAbsolute17(options.reviewedCacheAlias) || resolve16(options.reviewedCacheAlias) !== options.reviewedCacheAlias))
42701
42885
  throw new Error("A reviewed cache alias requires vendor inventory and an exact absolute path");
42702
- if (options.disabledVendorPaths?.some((path) => !isAbsolute17(path) || resolve15(path) !== path))
42886
+ if (options.disabledVendorPaths?.some((path) => !isAbsolute17(path) || resolve16(path) !== path))
42703
42887
  throw new Error("Disabled vendor paths must be exact absolute paths");
42704
42888
  const reviewedCacheAlias = options.reviewedCacheAlias === undefined ? undefined : canonicalSystemPath(options.reviewedCacheAlias);
42705
42889
  const disabledVendorPaths = new Set((options.disabledVendorPaths ?? []).map(canonicalSystemPath));
@@ -42707,14 +42891,18 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
42707
42891
  const selectedAgents = options.agents ? new Set(options.agents) : undefined;
42708
42892
  const includesAgent = (agent) => !selectedAgents || selectedAgents.has(agent);
42709
42893
  const rootDefinitions = selectedAgents ? ROOTS.filter(([agent, path]) => selectedAgents.has(agent) || selectedAgents.has("hermes") && agent === "codex" && path === ".agents/skills") : ROOTS;
42710
- const roots = rootDefinitions.map(([agent, path]) => [agent, canonicalAgentPath(join22(home, path), aliases)]);
42711
- const bridgePaths = Object.values(AGENT_ADAPTERS).map((adapter) => canonicalAgentPath(join22(home, adapter.root, CLI_BRIDGE_NAME), aliases));
42894
+ const roots = rootDefinitions.map(([agent, path]) => [agent, canonicalAgentPath(join23(home, path), aliases)]);
42895
+ const bridgePaths = Object.entries(AGENT_ADAPTERS).filter(([agent]) => agent !== "sumi" || includesAgent("sumi")).map(([agent, adapter]) => canonicalAgentPath(join23(agent === "sumi" ? sumiBridgeRoot(home) : join23(home, adapter.root), CLI_BRIDGE_NAME), aliases));
42712
42896
  for (const project of projectAncestorDirectories([...options.projectDirs ?? [], ...options.projectDir ? [options.projectDir] : []])) {
42713
42897
  for (const [agent, path] of rootDefinitions)
42714
- roots.push([agent, canonicalAgentPath(join22(project, path), aliases)]);
42898
+ roots.push([agent, canonicalAgentPath(join23(project, path), aliases)]);
42899
+ if (selectedAgents?.has("sumi"))
42900
+ for (const directory of [".claude", ".agents"])
42901
+ for (const name of ["skill", "skills"])
42902
+ roots.push(["sumi", canonicalAgentPath(join23(project, directory, name), aliases)]);
42715
42903
  }
42716
42904
  const installationInputs = options.codexInstallationInputRoots ?? [];
42717
- if (installationInputs.some((input) => resolve15(input) !== input || realpathSync7(input) !== input || roots.some(([agent, path]) => agent === "codex" && (path === input || path.startsWith(input + sep5) || input.startsWith(path + sep5)))))
42905
+ if (installationInputs.some((input) => resolve16(input) !== input || realpathSync8(input) !== input || roots.some(([agent, path]) => agent === "codex" && (path === input || path.startsWith(input + sep5) || input.startsWith(path + sep5)))))
42718
42906
  throw new Error("Native installation input overlaps an unconditional skill-loading root");
42719
42907
  const entries = [], seen = new Set;
42720
42908
  const cacheScans = new Map, maxAliasProofEntries = 1e4;
@@ -42728,13 +42916,13 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
42728
42916
  }
42729
42917
  let reviewedCacheAliasFound = false;
42730
42918
  function verifiedSiblingCacheAlias(agent, path, parent) {
42731
- const link = readlinkSync4(path), lexicalTarget = resolve15(parent, link);
42919
+ const link = readlinkSync4(path), lexicalTarget = resolve16(parent, link);
42732
42920
  if (isAbsolute17(link) ? link !== lexicalTarget : dirname15(link) !== ".")
42733
42921
  return false;
42734
42922
  const target = canonicalSystemPath(lexicalTarget);
42735
42923
  if (dirname15(target) !== parent)
42736
42924
  return false;
42737
- if (!lstatSync19(target, { throwIfNoEntry: false })?.isDirectory())
42925
+ if (!lstatSync20(target, { throwIfNoEntry: false })?.isDirectory())
42738
42926
  return false;
42739
42927
  const scan = cacheScans.get(target);
42740
42928
  if (!scan?.complete || scan.entries > maxAliasProofEntries)
@@ -42757,37 +42945,40 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
42757
42945
  assertSafePath(path);
42758
42946
  if (configuredRoot && agent === "codex" && installationInputs.some((root2) => path === root2 || path.startsWith(`${root2}${sep5}`)))
42759
42947
  return scan;
42760
- if (!existsSync6(path))
42948
+ if (!existsSync7(path))
42761
42949
  return scan;
42762
- const stat2 = lstatSync19(path);
42763
- if (stat2.isFile())
42950
+ const stat2 = lstatSync20(path);
42951
+ if (stat2.isFile()) {
42952
+ if (agent === "sumi" && depth === 1 && path.endsWith(".md"))
42953
+ throw new Error("NATIVE_SKILL_DRIFT: flat Sumi skill documents require a dedicated migration adapter");
42764
42954
  return scan;
42955
+ }
42765
42956
  if (!stat2.isDirectory())
42766
42957
  throw new Error(`Unsupported native discovery entry: ${path}`);
42767
- if (existsSync6(join22(path, "SKILL.md"))) {
42958
+ if (existsSync7(join23(path, "SKILL.md"))) {
42768
42959
  scan.hasSkills = true;
42769
42960
  if (seen.has(path))
42770
42961
  return scan;
42771
42962
  seen.add(path);
42772
42963
  let managed = false;
42773
- const marker = join22(path, ".hasna-skills.json");
42774
- if (existsSync6(marker)) {
42964
+ const marker = join23(path, ".hasna-skills.json");
42965
+ if (existsSync7(marker)) {
42775
42966
  try {
42776
42967
  managed = JSON.parse(readFileSync14(marker, "utf8")).managedBy === "@hasna/skills";
42777
42968
  } catch {}
42778
42969
  }
42779
- const bridge = !vendor && isOwnedCliBridge(path, bridgePaths);
42970
+ const bridge = (!vendor || agent === "sumi") && isOwnedCliBridge(path, bridgePaths);
42780
42971
  const rootAlias = aliases.find((item) => path === item.target || path.startsWith(item.target + sep5));
42781
- entries.push({ agent, path, hash: treeHash(path), managed, vendor, ...agent === "codex" && path.startsWith(canonicalAgentPath(join22(home, ".codex", "skills", ".system"), aliases) + sep5) ? { system: true } : {}, ...bridge ? { bridge: true, bridgeHome: resolve15(home) } : {}, ...rootAlias ? { rootAlias } : {} });
42972
+ entries.push({ agent, path, hash: treeHash(path), managed, vendor, ...agent === "codex" && path.startsWith(canonicalAgentPath(join23(home, ".codex", "skills", ".system"), aliases) + sep5) ? { system: true } : {}, ...bridge ? { bridge: true, bridgeHome: resolve16(home) } : {}, ...rootAlias ? { rootAlias } : {} });
42782
42973
  return scan;
42783
42974
  }
42784
- if (depth > (vendor ? 32 : 3))
42975
+ if (depth > (agent === "sumi" ? 32 : vendor ? 32 : 3))
42785
42976
  return { ...scan, complete: false };
42786
42977
  const children = [], directory = opendirSync5(path);
42787
42978
  try {
42788
42979
  let child;
42789
42980
  while ((child = directory.readSync()) !== null) {
42790
- admit(join22(path, child.name));
42981
+ admit(join23(path, child.name));
42791
42982
  children.push(child);
42792
42983
  }
42793
42984
  } finally {
@@ -42799,13 +42990,13 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
42799
42990
  for (const { name } of children) {
42800
42991
  if (name === "node_modules")
42801
42992
  continue;
42802
- if (name.startsWith(".") && name !== ".system" && agent !== "hermes" && !(options.guardHermes && `${path}${sep5}`.includes(`${sep5}.agents${sep5}skills${sep5}`)))
42993
+ if (name.startsWith(".") && name !== ".system" && agent !== "hermes" && agent !== "sumi" && !(options.guardHermes && `${path}${sep5}`.includes(`${sep5}.agents${sep5}skills${sep5}`)))
42803
42994
  continue;
42804
42995
  const isVendor = vendor || name === ".system";
42805
42996
  if (isVendor && !options.includeVendor)
42806
42997
  continue;
42807
- const child = join22(path, name);
42808
- if (isVendor && lstatSync19(child, { throwIfNoEntry: false })?.isSymbolicLink()) {
42998
+ const child = join23(path, name);
42999
+ if (isVendor && lstatSync20(child, { throwIfNoEntry: false })?.isSymbolicLink()) {
42809
43000
  const target = statSync6(child, { throwIfNoEntry: false });
42810
43001
  if (target?.isFile() || pluginCache && target?.isDirectory() && verifiedSiblingCacheAlias(agent, child, path)) {
42811
43002
  scan.entries++;
@@ -42831,11 +43022,11 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
42831
43022
  scanRoot(agent, path);
42832
43023
  if (options.includeVendor) {
42833
43024
  for (const agent of ["codex", "claude"].filter(includesAgent))
42834
- scanRoot(agent, canonicalAgentPath(join22(home, `.${agent}`, "plugins", "cache"), aliases), true, true);
43025
+ scanRoot(agent, canonicalAgentPath(join23(home, `.${agent}`, "plugins", "cache"), aliases), true, true);
42835
43026
  if (includesAgent("claude"))
42836
- scanRoot("claude", canonicalAgentPath(join22(home, ".claude", "plugins", "synced"), aliases), true);
43027
+ scanRoot("claude", canonicalAgentPath(join23(home, ".claude", "plugins", "synced"), aliases), true);
42837
43028
  if (includesAgent("gemini"))
42838
- scanRoot("gemini", join22(home, ".gemini", "extensions"), true);
43029
+ scanRoot("gemini", join23(home, ".gemini", "extensions"), true);
42839
43030
  }
42840
43031
  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 }))) : [];
42841
43032
  for (const root2 of [...options.agentRoots ?? [], ...configured])
@@ -42848,7 +43039,7 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
42848
43039
  }
42849
43040
  function readOptional(path) {
42850
43041
  assertSafePath(path);
42851
- return existsSync6(path) ? readFileSync14(path, "utf8") : null;
43042
+ return existsSync7(path) ? readFileSync14(path, "utf8") : null;
42852
43043
  }
42853
43044
  function jsonObject(text2, path) {
42854
43045
  if (text2 === null)
@@ -42948,19 +43139,19 @@ function configureHooks(config, agent, command, profileId, nativeReady) {
42948
43139
  function disableCodexSkills(text2, skills, aliases, bridgePath) {
42949
43140
  const bundled = disableCodexBundledSkills(text2);
42950
43141
  let result = normalizeCodexInlinePathConfig(bundled);
42951
- const bridgeSelector = (entry) => typeof entry.name === "string" && entry.name.trim() === CLI_BRIDGE_NAME || typeof entry.path === "string" && [resolve15(bridgePath), resolve15(join22(bridgePath, "SKILL.md"))].includes(canonicalAgentPath(entry.path, aliases));
43142
+ const bridgeSelector = (entry) => typeof entry.name === "string" && entry.name.trim() === CLI_BRIDGE_NAME || typeof entry.path === "string" && [resolve16(bridgePath), resolve16(join23(bridgePath, "SKILL.md"))].includes(canonicalAgentPath(entry.path, aliases));
42952
43143
  const previousConfig = Bun.TOML.parse(bundled).skills?.config;
42953
43144
  if (previousConfig !== undefined && (!Array.isArray(previousConfig) || previousConfig.some((entry) => !entry || typeof entry !== "object" || entry.path !== undefined && entry.name !== undefined)))
42954
43145
  throw new Error("Codex skill controls require one path or name selector per [[skills.config]] entry; review ambiguous entries before running skills hook install");
42955
43146
  const bridgeNeedsRepair = previousConfig?.some((entry) => entry.enabled === false && bridgeSelector(entry));
42956
43147
  const selections = [...skills.filter((entry) => entry.agent === "codex" && !entry.bridge).map((skill) => ({ path: skill.path, enabled: false })), { path: bridgePath, enabled: true }];
42957
43148
  for (const skill of selections) {
42958
- const path = join22(skill.path, "SKILL.md");
43149
+ const path = join23(skill.path, "SKILL.md");
42959
43150
  let found = false;
42960
43151
  result = result.replace(CODEX_SKILL_CONFIG_SECTIONS, (section) => {
42961
43152
  const parsed = Bun.TOML.parse(section);
42962
43153
  const declared = parsed.skills?.config?.[0];
42963
- if (!declared || !(skill.enabled && bridgeSelector(declared)) && !(typeof declared.path === "string" && [resolve15(path), resolve15(skill.path)].includes(canonicalAgentPath(declared.path, aliases))))
43154
+ if (!declared || !(skill.enabled && bridgeSelector(declared)) && !(typeof declared.path === "string" && [resolve16(path), resolve16(skill.path)].includes(canonicalAgentPath(declared.path, aliases))))
42964
43155
  return section;
42965
43156
  found = true;
42966
43157
  return /^\s*enabled\s*=/m.test(section) ? section.replace(/^\s*enabled\s*=.*$/m, `enabled = ${skill.enabled}`) : `${section.trimEnd()}
@@ -42981,14 +43172,14 @@ enabled = false
42981
43172
  return result;
42982
43173
  }
42983
43174
  function assertCodexInstallationInputs(home, projectDirs, inputs) {
42984
- const nativeRoots = [home, ...projectAncestorDirectories(projectDirs)].flatMap((directory) => ROOTS.filter(([agent]) => agent === "codex").map(([, path]) => resolve15(directory, path)));
43175
+ const nativeRoots = [home, ...projectAncestorDirectories(projectDirs)].flatMap((directory) => ROOTS.filter(([agent]) => agent === "codex").map(([, path]) => resolve16(directory, path)));
42985
43176
  if (inputs.some((input) => nativeRoots.some((root2) => root2 === input || root2.startsWith(input + sep5) || input.startsWith(root2 + sep5))))
42986
43177
  throw new Error("Native installation input overlaps an unconditional skill-loading root");
42987
43178
  }
42988
43179
  function planAgentIntegration(options) {
42989
43180
  const home = options.home ?? homedir3(), dataDir2 = options.dataDir ?? getDataDirReadOnly();
42990
43181
  const aliases = rootAliases(home, options.allowRootAliases);
42991
- const policyPath = join22(dataDir2, "agent-policy.json");
43182
+ const policyPath = join23(dataDir2, "agent-policy.json");
42992
43183
  assertSafePath(policyPath);
42993
43184
  const priorSnapshot = readManagedSkillPolicySnapshot(dataDir2), previousPolicy = priorSnapshot?.text ?? null, policy = priorSnapshot?.value ?? {};
42994
43185
  if (policy.bridge !== undefined && (!policy.bridge || typeof policy.bridge !== "object" || Array.isArray(policy.bridge)))
@@ -43020,10 +43211,10 @@ function planAgentIntegration(options) {
43020
43211
  }
43021
43212
  return resolveAgentDiscovery({ home, agent, reviewed: options.discoveryInputs, retainedReview, canonical: (path) => canonicalAgentPath(path, aliases) });
43022
43213
  });
43023
- const codexConfig = options.agents.includes("codex") ? Bun.TOML.parse(readOptional(canonicalAgentPath(join22(home, ".codex", "config.toml"), aliases)) ?? "") : {};
43214
+ const codexConfig = options.agents.includes("codex") ? Bun.TOML.parse(readOptional(canonicalAgentPath(join23(home, ".codex", "config.toml"), aliases)) ?? "") : {};
43024
43215
  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) });
43025
43216
  const observedNativeSources = [];
43026
- const codexPluginControls = options.codexNativeCatalog ? reviewCodexPluginControls(options.codexNativeCatalog, nativeSkills.filter((entry) => entry.agent === "codex" && entry.vendor).map((entry) => join22(entry.path, "SKILL.md")), canonicalAgentPath(join22(home, ".codex/plugins/cache"), aliases), resolve15(options.projectDir ?? home), (path) => {
43217
+ const codexPluginControls = options.codexNativeCatalog ? reviewCodexPluginControls(options.codexNativeCatalog, nativeSkills.filter((entry) => entry.agent === "codex" && entry.vendor).map((entry) => join23(entry.path, "SKILL.md")), canonicalAgentPath(join23(home, ".codex/plugins/cache"), aliases), resolve16(options.projectDir ?? home), (path) => {
43027
43218
  const bytes = readNativeBytes(path, 1024 * 1024);
43028
43219
  observedNativeSources.push({ path, sha256: sha4(bytes) });
43029
43220
  return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
@@ -43031,7 +43222,7 @@ function planAgentIntegration(options) {
43031
43222
  const codexPluginSkills = codexPluginControls.skills;
43032
43223
  const codexInactivePlugins = codexPluginControls.inactivePlugins;
43033
43224
  const codexDiscovery = discoveries.find((binding) => binding.agent === "codex");
43034
- const codexPluginSourceInputs = codexPluginControls.sourceInputs.filter((input) => codexDiscovery?.method === "reviewed" && codexDiscovery.roots.some((root2) => root2 === input.sourceRoot || root2.startsWith(input.sourceRoot + sep5) || input.sourceRoot.startsWith(root2 + sep5)) && codexDiscovery.sources.some((source) => source.path === join22(input.sourceRoot, ".codex-plugin/plugin.json") && source.sha256 !== null && source.format === undefined && source.fields === undefined));
43225
+ const codexPluginSourceInputs = codexPluginControls.sourceInputs.filter((input) => codexDiscovery?.method === "reviewed" && codexDiscovery.roots.some((root2) => root2 === input.sourceRoot || root2.startsWith(input.sourceRoot + sep5) || input.sourceRoot.startsWith(root2 + sep5)) && codexDiscovery.sources.some((source) => source.path === join23(input.sourceRoot, ".codex-plugin/plugin.json") && source.sha256 !== null && source.format === undefined && source.fields === undefined));
43035
43226
  assertCodexInstallationInputs(home, [options.projectDir ?? home], codexPluginSourceInputs.map((input) => input.sourceRoot));
43036
43227
  const changes = [];
43037
43228
  for (const agent of [...new Set(options.agents)]) {
@@ -43039,19 +43230,19 @@ function planAgentIntegration(options) {
43039
43230
  throw new Error(`Unsupported agent: ${agent}`);
43040
43231
  const { command, profileId: profileId2 } = bindings.get(agent);
43041
43232
  const adapter = AGENT_ADAPTERS[agent];
43042
- const bridgePath = canonicalAgentPath(join22(home, adapter.root, CLI_BRIDGE_NAME), aliases);
43233
+ const bridgePath = canonicalAgentPath(join23(agent === "sumi" ? sumiBridgeRoot(home) : join23(home, adapter.root), CLI_BRIDGE_NAME), aliases);
43043
43234
  assertSafePath(bridgePath);
43044
- if (existsSync6(bridgePath) && !isOwnedCliBridge(bridgePath, [bridgePath]))
43235
+ if (existsSync7(bridgePath) && !isOwnedCliBridge(bridgePath, [bridgePath]))
43045
43236
  throw new Error(`Refusing to overwrite an unrecognized or modified Skills bridge: ${bridgePath}`);
43046
43237
  for (const [name, after2] of Object.entries(CLI_BRIDGE_FILES)) {
43047
- const path2 = join22(bridgePath, name), before2 = readOptional(path2);
43238
+ const path2 = join23(bridgePath, name), before2 = readOptional(path2);
43048
43239
  if (before2 !== after2)
43049
43240
  changes.push({ path: path2, before: before2, after: after2 });
43050
43241
  }
43051
- const path = canonicalAgentPath(join22(home, adapter.config), aliases);
43242
+ const path = canonicalAgentPath(agent === "sumi" ? sumiConfigPath(home) : join23(home, adapter.config), aliases);
43052
43243
  const before = readOptional(path);
43053
43244
  if (agent === "hermes") {
43054
- const supervisorPath = join22(dataDir2, "agent-hooks", "hermes.js"), supervisorBefore = readOptional(supervisorPath), supervisorAfter = renderHermesSupervisor(command, profileId2);
43245
+ const supervisorPath = join23(dataDir2, "agent-hooks", "hermes.js"), supervisorBefore = readOptional(supervisorPath), supervisorAfter = renderHermesSupervisor(command, profileId2);
43055
43246
  const priorCommand = policy.bridge?.commands?.hermes, priorProfile = policy.bridge?.profiles?.hermes ?? policy.profileId;
43056
43247
  const previous = policy.bridge?.supervisors?.hermes;
43057
43248
  if (supervisorBefore !== null && supervisorBefore !== supervisorAfter && !(previous?.path === supervisorPath && typeof priorCommand === "string" && typeof priorProfile === "string" && supervisorBefore === renderHermesSupervisor(priorCommand, priorProfile)))
@@ -43062,19 +43253,30 @@ function planAgentIntegration(options) {
43062
43253
  const after2 = configureHermesHooks(before, supervisor, previous);
43063
43254
  if (before !== after2)
43064
43255
  changes.push({ path, before, after: after2 });
43065
- const optOut = join22(home, ".hermes", HERMES_OPT_OUT), optOutBefore = readOptional(optOut);
43256
+ const optOut = join23(home, ".hermes", HERMES_OPT_OUT), optOutBefore = readOptional(optOut);
43066
43257
  if (optOutBefore === null)
43067
43258
  changes.push({ path: optOut, before: null, after: `Managed by @hasna/skills: bundled native skill reseeding is disabled.
43068
43259
  ` });
43069
43260
  continue;
43070
43261
  }
43071
43262
  const config = jsonObject(before, path);
43072
- if (agent === "opencode") {
43263
+ if (agent === "sumi") {
43264
+ 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))))
43265
+ throw new Error("Expected Sumi native permission rules");
43266
+ config.permissions = [...(config.permissions ?? []).filter((rule) => rule.action !== "skill"), ...SUMI_SKILL_PERMISSIONS];
43267
+ const pluginPath = join23(sumiConfigDirectory(home), "plugins", "skills-cli.js"), pluginBefore = readOptional(pluginPath);
43268
+ const pluginAfter = renderSumiPlugin(command, profileId2);
43269
+ const priorCommand = policy.bridge?.commands?.sumi, priorProfile = policy.bridge?.profiles?.sumi ?? policy.profileId;
43270
+ if (pluginBefore !== null && pluginBefore !== pluginAfter && !(typeof priorCommand === "string" && typeof priorProfile === "string" && pluginBefore === renderSumiPlugin(priorCommand, priorProfile)))
43271
+ throw new Error("Refusing to overwrite a modified Sumi Skills plugin; preserve and review it first");
43272
+ if (pluginBefore !== pluginAfter)
43273
+ changes.push({ path: pluginPath, before: pluginBefore, after: pluginAfter });
43274
+ } else if (agent === "opencode") {
43073
43275
  const permission = config.permission ?? {};
43074
43276
  if (!permission || typeof permission !== "object" || Array.isArray(permission))
43075
43277
  throw new Error("Expected OpenCode permission object");
43076
43278
  config.permission = { ...permission, skill: { "*": "deny", [CLI_BRIDGE_NAME]: "allow" } };
43077
- const pluginPath = join22(home, ".config", "opencode", "plugins", "skills-cli.js"), pluginBefore = readOptional(pluginPath);
43279
+ const pluginPath = join23(home, ".config", "opencode", "plugins", "skills-cli.js"), pluginBefore = readOptional(pluginPath);
43078
43280
  const pluginAfter = renderOpenCodePlugin(command, profileId2);
43079
43281
  const priorCommand = policy.bridge?.commands?.opencode;
43080
43282
  const ownedPrevious = typeof priorCommand === "string" && typeof policy.profileId === "string" && pluginBefore === renderOpenCodePlugin(priorCommand, policy.bridge?.profiles?.opencode ?? policy.profileId);
@@ -43091,13 +43293,13 @@ function planAgentIntegration(options) {
43091
43293
  if (before !== after)
43092
43294
  changes.push({ path, before, after });
43093
43295
  if (agent === "codex") {
43094
- const configPath = canonicalAgentPath(join22(home, ".codex", "config.toml"), aliases), previous = readOptional(configPath);
43296
+ const configPath = canonicalAgentPath(join23(home, ".codex", "config.toml"), aliases), previous = readOptional(configPath);
43095
43297
  const next = disableReviewedCodexPluginNames(disableCodexSkills(previous ?? "", nativeSkills, aliases, bridgePath), codexPluginSkills);
43096
43298
  if (next !== (previous ?? ""))
43097
43299
  changes.push({ path: configPath, before: previous, after: next });
43098
43300
  }
43099
43301
  }
43100
- 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(join22(home, ".codex/config.toml"), aliases))?.before === null ? null : sha4(readOptional(canonicalAgentPath(join22(home, ".codex/config.toml"), aliases)) ?? "") } : policy.bridge?.codexPluginSkillReview;
43302
+ 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(join23(home, ".codex/config.toml"), aliases))?.before === null ? null : sha4(readOptional(canonicalAgentPath(join23(home, ".codex/config.toml"), aliases)) ?? "") } : policy.bridge?.codexPluginSkillReview;
43101
43303
  const discoveryAfter = discoveries.map((binding) => {
43102
43304
  const rebound = rebindAgentDiscovery(binding, new Map(changes.map((change) => [change.path, change.after])));
43103
43305
  if (binding.agent !== "codex")
@@ -43112,12 +43314,12 @@ function planAgentIntegration(options) {
43112
43314
  version: CLI_BRIDGE_VERSION,
43113
43315
  digest: CLI_BRIDGE_DIGEST,
43114
43316
  agents: [...new Set([...priorAgents, ...options.agents])].sort(),
43115
- home: resolve15(home),
43317
+ home: resolve16(home),
43116
43318
  includeVendor: true,
43117
- ...options.agents.includes("hermes") ? { supervisors: { ...policy.bridge?.supervisors, hermes: { path: join22(dataDir2, "agent-hooks", "hermes.js"), runtime: process.execPath, sha256: sha4(renderHermesSupervisor(bindings.get("hermes").command, bindings.get("hermes").profileId)) } } } : {},
43319
+ ...options.agents.includes("hermes") ? { supervisors: { ...policy.bridge?.supervisors, hermes: { path: join23(dataDir2, "agent-hooks", "hermes.js"), runtime: process.execPath, sha256: sha4(renderHermesSupervisor(bindings.get("hermes").command, bindings.get("hermes").profileId)) } } } : {},
43118
43320
  commands: { ...policy.bridge?.commands, ...Object.fromEntries([...bindings].map(([agent, binding]) => [agent, binding.command])) },
43119
43321
  profiles: Object.fromEntries([...new Set([...priorAgents, ...options.agents])].sort().map((agent) => [agent, bindings.get(agent)?.profileId ?? policy.bridge?.profiles?.[agent] ?? policy.profileId])),
43120
- disabledBuiltins: options.agents.includes("codex") ? nativeSkills.filter((entry) => entry.agent === "codex" && entry.vendor && entry.path.startsWith(canonicalAgentPath(join22(home, ".codex", "skills", ".system"), aliases) + sep5)).map((entry) => ({ path: entry.path, hash: entry.hash })) : policy.bridge?.disabledBuiltins ?? [],
43322
+ disabledBuiltins: options.agents.includes("codex") ? nativeSkills.filter((entry) => entry.agent === "codex" && entry.vendor && entry.path.startsWith(canonicalAgentPath(join23(home, ".codex", "skills", ".system"), aliases) + sep5)).map((entry) => ({ path: entry.path, hash: entry.hash })) : policy.bridge?.disabledBuiltins ?? [],
43121
43323
  rootAliases: aliases,
43122
43324
  ...options.codexNativeCatalog || codexPluginSkills.length || codexInactivePlugins.length || codexPluginSourceInputs.length ? { codexPluginSkills, codexInactivePlugins, codexPluginSkillReview } : {},
43123
43325
  discovery: { ...policy.bridge?.discovery, ...Object.fromEntries(discoveryAfter.map((binding) => [binding.agent, binding])) }
@@ -43140,7 +43342,7 @@ function claudeSettingsConsumers(home, path, discoveries, aliases) {
43140
43342
  const distance = relative4(canonical6(root2), path);
43141
43343
  return distance === "" || distance !== ".." && !distance.startsWith(`..${sep5}`) && !isAbsolute17(distance);
43142
43344
  };
43143
- return discoveries.filter((binding) => binding.agent === "claude" || binding.agent === "opencode" || canonical6(join22(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);
43345
+ return discoveries.filter((binding) => binding.agent === "claude" || binding.agent === "opencode" || canonical6(join23(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);
43144
43346
  }
43145
43347
  function verifyCoordinatedDiscovery(binding, home, aliases) {
43146
43348
  try {
@@ -43157,8 +43359,8 @@ function verifyCoordinatedDiscovery(binding, home, aliases) {
43157
43359
  }
43158
43360
  }
43159
43361
  function planClaudeHookEventsUpdate(options) {
43160
- const home = resolve15(options.home ?? homedir3()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
43161
- const policyPath = join22(dataDir2, "agent-policy.json");
43362
+ const home = resolve16(options.home ?? homedir3()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
43363
+ const policyPath = join23(dataDir2, "agent-policy.json");
43162
43364
  assertSafePath(policyPath);
43163
43365
  const snapshot2 = readManagedSkillPolicySnapshot(dataDir2);
43164
43366
  if (!snapshot2)
@@ -43169,9 +43371,9 @@ function planClaudeHookEventsUpdate(options) {
43169
43371
  }
43170
43372
  const aliases = bridge.rootAliases ?? [];
43171
43373
  recheckRootAliases(aliases);
43172
- const path = canonicalAgentPath(join22(home, ".claude", "settings.json"), aliases);
43374
+ const path = canonicalAgentPath(join23(home, ".claude", "settings.json"), aliases);
43173
43375
  assertSafePath(path);
43174
- const before = lstatSync19(path, { throwIfNoEntry: false }) ? new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(readNativeBytes(path, 1024 * 1024)) : null;
43376
+ const before = lstatSync20(path, { throwIfNoEntry: false }) ? new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(readNativeBytes(path, 1024 * 1024)) : null;
43175
43377
  if ((before === null ? "absent" : sha4(before)) !== options.expectedSettingsSha256)
43176
43378
  throw new Error("Claude settings preimage changed");
43177
43379
  assertClaudeHookEventsReplacement(before, options.replacement, options.events);
@@ -43231,14 +43433,14 @@ function atomicWrite2(path, content) {
43231
43433
  writeFileSync4(temporary, content, { mode: 384, flag: "wx" });
43232
43434
  renameSync3(temporary, path);
43233
43435
  } finally {
43234
- if (existsSync6(temporary))
43436
+ if (existsSync7(temporary))
43235
43437
  unlinkSync4(temporary);
43236
43438
  }
43237
43439
  }
43238
43440
  function planAgentSettingsWitnessUpgrade(options) {
43239
43441
  if (options.targetCodexVersion !== undefined && (options.agent !== "codex" || ![2, 3].includes(options.targetCodexVersion)))
43240
43442
  throw new Error("Invalid Codex witness target version");
43241
- const home = resolve15(options.home ?? homedir3()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
43443
+ const home = resolve16(options.home ?? homedir3()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
43242
43444
  const snapshot2 = readManagedSkillPolicySnapshot(dataDir2);
43243
43445
  if (!snapshot2 || sha4(snapshot2.text) !== options.expectedPolicySha256)
43244
43446
  throw new Error("Managed policy preimage changed");
@@ -43247,7 +43449,7 @@ function planAgentSettingsWitnessUpgrade(options) {
43247
43449
  const binding = policy.bridge?.discovery?.[options.agent];
43248
43450
  if (!binding || binding.agent !== options.agent || binding.method !== "reviewed")
43249
43451
  throw new Error("Settings witness upgrade requires an existing reviewed native binding");
43250
- const configPath = canonicalAgentPath(join22(home, options.agent === "claude" ? ".claude/settings.json" : ".codex/config.toml"), aliases);
43452
+ const configPath = canonicalAgentPath(join23(home, options.agent === "claude" ? ".claude/settings.json" : ".codex/config.toml"), aliases);
43251
43453
  const settings = readOptional(configPath);
43252
43454
  if (settings === null || sha4(settings) !== options.expectedSettingsSha256)
43253
43455
  throw new Error("Native settings preimage changed");
@@ -43286,7 +43488,7 @@ function planAgentSettingsWitnessUpgrade(options) {
43286
43488
  const replacement = { ...binding, sources: rebound };
43287
43489
  verifyAgentDiscovery(replacement);
43288
43490
  const after = serializeManagedSkillPolicy({ ...policy, bridge: { ...policy.bridge, discovery: { ...policy.bridge.discovery, [options.agent]: replacement } } });
43289
- return { dataDir: dataDir2, profileId: policy.profileId, changes: [{ path: join22(dataDir2, "agent-policy.json"), before: snapshot2.text, after }], nativeSkills: [], observedPolicy: { path: join22(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 })) } };
43491
+ return { dataDir: dataDir2, profileId: policy.profileId, changes: [{ path: join23(dataDir2, "agent-policy.json"), before: snapshot2.text, after }], nativeSkills: [], observedPolicy: { path: join23(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 })) } };
43290
43492
  }
43291
43493
  function applyAgentIntegration(plan) {
43292
43494
  for (const source of plan.observedNativeSources ?? [])
@@ -43294,12 +43496,12 @@ function applyAgentIntegration(plan) {
43294
43496
  throw new Error("Native identity source changed after planning");
43295
43497
  if (plan.observedSettings && readOptional(plan.observedSettings.path) !== plan.observedSettings.before)
43296
43498
  throw new Error("Native settings changed after witness planning");
43297
- const policyPath = join22(plan.dataDir, "agent-policy.json");
43499
+ const policyPath = join23(plan.dataDir, "agent-policy.json");
43298
43500
  assertSafePath(policyPath);
43299
- const currentText = (path) => resolve15(path) === resolve15(policyPath) ? readManagedSkillPolicySnapshot(plan.dataDir)?.text ?? null : readOptional(path);
43501
+ const currentText = (path) => resolve16(path) === resolve16(policyPath) ? readManagedSkillPolicySnapshot(plan.dataDir)?.text ?? null : readOptional(path);
43300
43502
  readManagedSkillPolicySnapshot(plan.dataDir);
43301
43503
  for (const change of plan.changes)
43302
- if (resolve15(change.path) === resolve15(policyPath))
43504
+ if (resolve16(change.path) === resolve16(policyPath))
43303
43505
  parseManagedSkillPolicy(change.after);
43304
43506
  const aliases = plan.rootAliases ?? [];
43305
43507
  recheckRootAliases(aliases);
@@ -43328,7 +43530,7 @@ function applyAgentIntegration(plan) {
43328
43530
  for (const change of plan.changes)
43329
43531
  if (currentText(change.path) !== change.before)
43330
43532
  throw new Error(`Configuration changed after planning: ${change.path}`);
43331
- const backupRoot = join22(plan.dataDir, "migration", randomUUID3()), backups = [], written = [], createdDirectories = new Set;
43533
+ const backupRoot = join23(plan.dataDir, "migration", randomUUID3()), backups = [], written = [], createdDirectories = new Set;
43332
43534
  if (!plan.changes.length) {
43333
43535
  recheckRootAliases(aliases);
43334
43536
  return { changed: [], backups, ...aliases.length ? { rootAliases: aliases } : {} };
@@ -43338,7 +43540,7 @@ function applyAgentIntegration(plan) {
43338
43540
  chmodSync(backupRoot, 448);
43339
43541
  for (const [index, change] of plan.changes.entries())
43340
43542
  if (change.before !== null) {
43341
- const backup = join22(backupRoot, `${index}-${sha4(change.path).slice(0, 12)}.backup`);
43543
+ const backup = join23(backupRoot, `${index}-${sha4(change.path).slice(0, 12)}.backup`);
43342
43544
  writeFileSync4(backup, change.before, { mode: 384, flag: "wx" });
43343
43545
  if (readFileSync14(backup, "utf8") !== change.before)
43344
43546
  throw new Error("Native configuration preservation readback failed");
@@ -43349,7 +43551,7 @@ function applyAgentIntegration(plan) {
43349
43551
  recheckRootAliases(aliases);
43350
43552
  if (currentText(change.path) !== change.before)
43351
43553
  throw new Error(`Configuration changed after planning: ${change.path}`);
43352
- for (let directory = dirname15(change.path);!existsSync6(directory); directory = dirname15(directory))
43554
+ for (let directory = dirname15(change.path);!existsSync7(directory); directory = dirname15(directory))
43353
43555
  createdDirectories.add(directory);
43354
43556
  const after = change.after;
43355
43557
  atomicWrite2(change.path, after);
@@ -43369,7 +43571,7 @@ function applyAgentIntegration(plan) {
43369
43571
  }
43370
43572
  for (const agent of plan.managedAgentChecks?.agents ?? [])
43371
43573
  assertManagedAgentBridge(agent, { home: plan.managedAgentChecks.home, dataDir: plan.dataDir, projectDir: plan.managedAgentChecks.home });
43372
- atomicWrite2(join22(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 } : {} }) + `
43574
+ atomicWrite2(join23(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 } : {} }) + `
43373
43575
  `);
43374
43576
  } catch (error) {
43375
43577
  for (const change of written.reverse()) {
@@ -43423,7 +43625,7 @@ function writeArchiveJournal(path, value) {
43423
43625
  } finally {
43424
43626
  if (descriptor !== undefined)
43425
43627
  closeSync16(descriptor);
43426
- if (lstatSync19(temporary, { throwIfNoEntry: false }))
43628
+ if (lstatSync20(temporary, { throwIfNoEntry: false }))
43427
43629
  unlinkSync4(temporary);
43428
43630
  }
43429
43631
  }
@@ -43434,7 +43636,7 @@ function archiveNativeSkills(inventory, options) {
43434
43636
  recheckRootAliases(aliases);
43435
43637
  for (const entry of inventory.filter((entry2) => entry2.bridge)) {
43436
43638
  const adapter = AGENT_ADAPTERS[entry.agent];
43437
- const expected = adapter && entry.bridgeHome ? canonicalAgentPath(join22(entry.bridgeHome, adapter.root, CLI_BRIDGE_NAME), aliases) : undefined;
43639
+ const expected = adapter && entry.bridgeHome ? canonicalAgentPath(join23(entry.agent === "sumi" ? sumiBridgeRoot(entry.bridgeHome) : join23(entry.bridgeHome, adapter.root), CLI_BRIDGE_NAME), aliases) : undefined;
43438
43640
  if (!expected || treeHash(entry.path) !== entry.hash || !isOwnedCliBridge(entry.path, [expected]))
43439
43641
  throw new Error(`Skills bridge changed after planning: ${entry.path}`);
43440
43642
  }
@@ -43445,11 +43647,11 @@ function archiveNativeSkills(inventory, options) {
43445
43647
  const targetManifest = options.targetManifest ? { schema: options.targetManifest.schema, digest: options.targetManifest.digest, targetCount: options.targetManifest.targets.length } : undefined;
43446
43648
  if (!selected.length)
43447
43649
  return { entries: [], ...targetManifest ? { targetManifest } : {}, ...aliases.length ? { rootAliases: aliases } : {} };
43448
- const operationId = randomUUID3(), archiveRoot = join22(options.dataDir ?? getDataDir(), "migration", operationId, "native"), receiptPath = join22(archiveRoot, "receipt.json");
43650
+ const operationId = randomUUID3(), archiveRoot = join23(options.dataDir ?? getDataDir(), "migration", operationId, "native"), receiptPath = join23(archiveRoot, "receipt.json");
43449
43651
  const entries = selected.map((entry, index) => ({
43450
- source: entry.vendor ? join22(entry.path, "SKILL.md") : entry.path,
43451
- archive: join22(archiveRoot, `${index}-${sha4(entry.path).slice(0, 12)}`),
43452
- hash: entry.vendor ? sha4(readNativeBytes(join22(entry.path, "SKILL.md"))) : entry.hash,
43652
+ source: entry.vendor ? join23(entry.path, "SKILL.md") : entry.path,
43653
+ archive: join23(archiveRoot, `${index}-${sha4(entry.path).slice(0, 12)}`),
43654
+ hash: entry.vendor ? sha4(readNativeBytes(join23(entry.path, "SKILL.md"))) : entry.hash,
43453
43655
  ...entry.vendor ? { discoveryOnly: true } : {},
43454
43656
  status: "planned"
43455
43657
  }));
@@ -43457,7 +43659,7 @@ function archiveNativeSkills(inventory, options) {
43457
43659
  const moved = [];
43458
43660
  const verifyArchive = (entry) => {
43459
43661
  assertSafePath(entry.archive);
43460
- const stat2 = lstatSync19(entry.archive);
43662
+ const stat2 = lstatSync20(entry.archive);
43461
43663
  if (entry.discoveryOnly ? !stat2.isFile() : !stat2.isDirectory())
43462
43664
  throw new Error("Archive type changed");
43463
43665
  if ((entry.discoveryOnly ? sha4(readNativeBytes(entry.archive)) : treeHash(entry.archive)) !== entry.hash)
@@ -43465,7 +43667,7 @@ function archiveNativeSkills(inventory, options) {
43465
43667
  };
43466
43668
  assertSafePath(archiveRoot);
43467
43669
  const created = [];
43468
- for (let path = archiveRoot;!existsSync6(path); path = dirname15(path))
43670
+ for (let path = archiveRoot;!existsSync7(path); path = dirname15(path))
43469
43671
  created.push(path);
43470
43672
  mkdirSync5(archiveRoot, { recursive: true, mode: 448 });
43471
43673
  try {
@@ -43505,7 +43707,7 @@ function archiveNativeSkills(inventory, options) {
43505
43707
  recheckRootAliases(aliases);
43506
43708
  assertSafePath(entry.source);
43507
43709
  assertSafePath(entry.archive);
43508
- if (lstatSync19(entry.source, { throwIfNoEntry: false })) {
43710
+ if (lstatSync20(entry.source, { throwIfNoEntry: false })) {
43509
43711
  entry.status = "recovery-required";
43510
43712
  entry.conflict = "source-occupied";
43511
43713
  continue;
@@ -43522,7 +43724,7 @@ function archiveNativeSkills(inventory, options) {
43522
43724
  syncArchiveDirectory(dirname15(entry.source));
43523
43725
  unlinkSync4(entry.archive);
43524
43726
  } else {
43525
- if (lstatSync19(entry.source, { throwIfNoEntry: false })) {
43727
+ if (lstatSync20(entry.source, { throwIfNoEntry: false })) {
43526
43728
  entry.status = "recovery-required";
43527
43729
  entry.conflict = "source-occupied";
43528
43730
  continue;
@@ -43553,8 +43755,8 @@ function assertManagedAgentBridge(agent, options = {}) {
43553
43755
  assertManagedAgentBridgeWithDiscovery(agent, options);
43554
43756
  }
43555
43757
  function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscovery) {
43556
- const home = resolve15(options.home ?? homedir3()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
43557
- assertSafePath(join22(dataDir2, "agent-policy.json"));
43758
+ const home = resolve16(options.home ?? homedir3()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
43759
+ assertSafePath(join23(dataDir2, "agent-policy.json"));
43558
43760
  const snapshot2 = readManagedSkillPolicySnapshot(dataDir2);
43559
43761
  if (!snapshot2)
43560
43762
  throw new Error("NATIVE_SKILL_DRIFT: install the Skills bridge with skills hook install");
@@ -43565,14 +43767,14 @@ function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscov
43565
43767
  if (!Array.isArray(aliases))
43566
43768
  throw new Error("NATIVE_SKILL_DRIFT: invalid root alias binding");
43567
43769
  recheckRootAliases(aliases);
43568
- const expected = canonicalAgentPath(join22(home, AGENT_ADAPTERS[agent].root, CLI_BRIDGE_NAME), aliases);
43770
+ const expected = canonicalAgentPath(join23(agent === "sumi" ? sumiBridgeRoot(home) : join23(home, AGENT_ADAPTERS[agent].root), CLI_BRIDGE_NAME), aliases);
43569
43771
  if (!isOwnedCliBridge(expected, [expected]))
43570
43772
  throw new Error("NATIVE_SKILL_DRIFT: the native Skills bridge is missing or modified; repair it before continuing");
43571
43773
  const roots = projectAncestorDirectories([options.projectDir ?? process.cwd(), ...options.projectDirs ?? [], ...agent === "hermes" && process.env.TERMINAL_CWD ? [process.cwd()] : []]);
43572
- const visible = (entry) => entry.agent === agent || ["codex", "gemini", "opencode", "hermes"].includes(agent) && entry.path.includes(`${sep5}.agents${sep5}skills${sep5}`) || agent === "opencode" && entry.agent === "claude";
43774
+ const visible = (entry) => entry.agent === agent || ["codex", "gemini", "opencode", "hermes", "sumi"].includes(agent) && entry.path.includes(`${sep5}.agents${sep5}skills${sep5}`) || ["opencode", "sumi"].includes(agent) && entry.agent === "claude";
43573
43775
  const discovery = provenDiscovery ?? binding.discovery?.[agent];
43574
43776
  assertProjectDiscovery(agent, [...roots], home, (path) => canonicalAgentPath(path, aliases), discovery);
43575
- const configPath = canonicalAgentPath(join22(home, AGENT_ADAPTERS[agent].config), aliases), config = agent === "hermes" ? parseHermesConfig(readOptional(configPath)) : jsonObject(readOptional(configPath), configPath);
43777
+ const configPath = canonicalAgentPath(agent === "sumi" ? sumiConfigPath(home) : join23(home, AGENT_ADAPTERS[agent].config), aliases), config = agent === "hermes" ? parseHermesConfig(readOptional(configPath)) : jsonObject(readOptional(configPath), configPath);
43576
43778
  const command = binding.commands?.[agent], profile = binding.profiles?.[agent];
43577
43779
  if (typeof command !== "string" || typeof profile !== "string")
43578
43780
  throw new Error("NATIVE_SKILL_DRIFT: the native hook command/profile binding is missing");
@@ -43580,11 +43782,14 @@ function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscov
43580
43782
  throw new Error("NATIVE_SKILL_DRIFT: the hook selection profile differs from its managed binding; restart the native client after reviewing skills hook install");
43581
43783
  if (agent === "hermes") {
43582
43784
  const supervisor = binding.supervisors?.hermes;
43583
- if (supervisor?.path !== join22(dataDir2, "agent-hooks", "hermes.js") || supervisor?.sha256 !== sha4(renderHermesSupervisor(command, profile)))
43785
+ if (supervisor?.path !== join23(dataDir2, "agent-hooks", "hermes.js") || supervisor?.sha256 !== sha4(renderHermesSupervisor(command, profile)))
43584
43786
  throw new Error("NATIVE_SKILL_DRIFT: Hermes supervisor binding changed; run skills hook install");
43585
43787
  assertHermesProtection(home, config, command, profile, supervisor);
43788
+ } else if (agent === "sumi") {
43789
+ if (JSON.stringify(config.permissions?.filter((rule) => rule.action === "skill")) !== JSON.stringify(SUMI_SKILL_PERMISSIONS) || readOptional(join23(sumiConfigDirectory(home), "plugins", "skills-cli.js")) !== renderSumiPlugin(command, profile))
43790
+ throw new Error("NATIVE_SKILL_DRIFT: Sumi bridge protection changed; run skills hook install");
43586
43791
  } else if (agent === "opencode") {
43587
- if (JSON.stringify(config.permission?.skill) !== JSON.stringify({ "*": "deny", [CLI_BRIDGE_NAME]: "allow" }) || readOptional(join22(home, ".config", "opencode", "plugins", "skills-cli.js")) !== renderOpenCodePlugin(command, profile))
43792
+ if (JSON.stringify(config.permission?.skill) !== JSON.stringify({ "*": "deny", [CLI_BRIDGE_NAME]: "allow" }) || readOptional(join23(home, ".config", "opencode", "plugins", "skills-cli.js")) !== renderOpenCodePlugin(command, profile))
43588
43793
  throw new Error("NATIVE_SKILL_DRIFT: OpenCode bridge protection changed; run skills hook install");
43589
43794
  } else {
43590
43795
  const required = {};
@@ -43601,21 +43806,21 @@ function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscov
43601
43806
  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)))
43602
43807
  throw new Error("NATIVE_SKILL_DRIFT: Gemini bridge or bundled-skill protection changed; run skills hook install");
43603
43808
  }
43604
- const codexPath = canonicalAgentPath(join22(home, ".codex", "config.toml"), aliases);
43809
+ const codexPath = canonicalAgentPath(join23(home, ".codex", "config.toml"), aliases);
43605
43810
  if (options.codexDiscoveryRecovery && (agent !== "codex" || options.codexDiscoveryRecovery.configPath !== codexPath))
43606
43811
  throw new Error("NATIVE_SKILL_DRIFT: Codex trust recovery names a different configuration root");
43607
43812
  const codexConfig = agent === "codex" ? Bun.TOML.parse(readOptional(codexPath) ?? "") : {};
43608
43813
  if (agent === "codex" && codexConfig.skills?.bundled?.enabled !== false)
43609
43814
  throw new Error("NATIVE_SKILL_DRIFT: Codex bundled skill reseeding is not disabled (skills.bundled.enabled); run skills hook install");
43610
- const setting = (path) => (codexConfig.skills?.config ?? []).filter((entry) => typeof entry.path === "string" && [path, join22(path, "SKILL.md")].includes(canonicalAgentPath(entry.path, aliases)));
43815
+ const setting = (path) => (codexConfig.skills?.config ?? []).filter((entry) => typeof entry.path === "string" && [path, join23(path, "SKILL.md")].includes(canonicalAgentPath(entry.path, aliases)));
43611
43816
  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))
43612
43817
  throw new Error("NATIVE_SKILL_DRIFT: the Codex CLI bridge is disabled; run skills hook install");
43613
- if (agent === "codex" && !reviewedCodexPluginCapabilitiesUnchanged(canonicalAgentPath(join22(home, ".codex/plugins/cache"), aliases), binding.codexPluginSkills ?? [], (path) => new TextDecoder("utf-8", { fatal: true }).decode(readNativeBytes(path, 1024 * 1024))))
43818
+ if (agent === "codex" && !reviewedCodexPluginCapabilitiesUnchanged(canonicalAgentPath(join23(home, ".codex/plugins/cache"), aliases), binding.codexPluginSkills ?? [], (path) => new TextDecoder("utf-8", { fatal: true }).decode(readNativeBytes(path, 1024 * 1024))))
43614
43819
  throw new Error("NATIVE_SKILL_DRIFT: reviewed native plugin capability controls changed; run skills hook install with a fresh discovery review");
43615
43820
  const disabledPlugin = (entry) => {
43616
43821
  if (agent !== "codex" || !entry.vendor)
43617
43822
  return false;
43618
- const document2 = join22(entry.path, "SKILL.md"), cache = canonicalAgentPath(join22(home, ".codex/plugins/cache"), aliases), read3 = (path) => new TextDecoder("utf-8", { fatal: true }).decode(readNativeBytes(path, 1024 * 1024));
43823
+ const document2 = join23(entry.path, "SKILL.md"), cache = canonicalAgentPath(join23(home, ".codex/plugins/cache"), aliases), read3 = (path) => new TextDecoder("utf-8", { fatal: true }).decode(readNativeBytes(path, 1024 * 1024));
43619
43824
  return isReviewedCodexPluginInactive(document2, cache, binding.codexInactivePlugins ?? [], codexConfig.plugins, codexConfig.skills?.config ?? [], read3) || isReviewedCodexPluginSkillDisabled(document2, cache, binding.codexPluginSkills ?? [], codexConfig.skills?.config, read3);
43620
43825
  };
43621
43826
  const disabledPaths = new Set(disabledCodexSkillPaths(codexConfig, aliases));
@@ -43628,15 +43833,15 @@ function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscov
43628
43833
  return true;
43629
43834
  if (!disabledPaths.has(entry.path))
43630
43835
  return false;
43631
- if (entry.path.startsWith(canonicalAgentPath(join22(home, ".codex", "plugins", "cache"), aliases) + sep5))
43836
+ if (entry.path.startsWith(canonicalAgentPath(join23(home, ".codex", "plugins", "cache"), aliases) + sep5))
43632
43837
  return true;
43633
- const runtimeCache = canonicalAgentPath(join22(home, ".cache", "codex-runtimes"), aliases);
43838
+ const runtimeCache = canonicalAgentPath(join23(home, ".cache", "codex-runtimes"), aliases);
43634
43839
  if (entry.path.startsWith(runtimeCache + sep5) && discovery?.method === "automatic" && discovery.roots.some((root2) => entry.path.startsWith(root2 + sep5)))
43635
43840
  return true;
43636
- const bundledMarketplaces = canonicalAgentPath(join22(home, ".codex", ".tmp", "bundled-marketplaces"), aliases);
43841
+ const bundledMarketplaces = canonicalAgentPath(join23(home, ".codex", ".tmp", "bundled-marketplaces"), aliases);
43637
43842
  if (entry.path.startsWith(bundledMarketplaces + sep5) && discovery?.method === "automatic" && discovery.roots.some((root2) => entry.path.startsWith(root2 + sep5)))
43638
43843
  return true;
43639
- if (!entry.path.startsWith(canonicalAgentPath(join22(home, ".codex", "skills", ".system"), aliases) + sep5))
43844
+ if (!entry.path.startsWith(canonicalAgentPath(join23(home, ".codex", "skills", ".system"), aliases) + sep5))
43640
43845
  return false;
43641
43846
  return Array.isArray(binding.disabledBuiltins) && binding.disabledBuiltins.some((item) => item.path === entry.path && item.hash === entry.hash);
43642
43847
  };
@@ -43646,6 +43851,8 @@ function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscov
43646
43851
  throw new Error("NATIVE_SKILL_DRIFT: an installed Gemini builtin is not disabled");
43647
43852
  try {
43648
43853
  verifyAgentDiscovery(discovery, options.codexDiscoveryRecovery);
43854
+ if (agent === "sumi" && discovery.method === "reviewed")
43855
+ resolveAgentDiscovery({ home, agent, retainedReview: discovery, canonical: (path) => canonicalAgentPath(path, aliases) });
43649
43856
  if (discovery.method === "automatic") {
43650
43857
  const current = resolveAgentDiscovery({ home, agent, canonical: (path) => canonicalAgentPath(path, aliases) });
43651
43858
  if (JSON.stringify(current) !== JSON.stringify(discovery))
@@ -43657,7 +43864,7 @@ function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscov
43657
43864
  let installationInputRoots = [];
43658
43865
  if (agent === "codex") {
43659
43866
  try {
43660
- installationInputRoots = reviewedCodexPluginSourceRoots(canonicalAgentPath(join22(home, ".codex/plugins/cache"), aliases), discovery.codexInstallationInputs?.plugins ?? [], (path) => new TextDecoder("utf-8", { fatal: true }).decode(readNativeBytes(path, 1024 * 1024)));
43867
+ installationInputRoots = reviewedCodexPluginSourceRoots(canonicalAgentPath(join23(home, ".codex/plugins/cache"), aliases), discovery.codexInstallationInputs?.plugins ?? [], (path) => new TextDecoder("utf-8", { fatal: true }).decode(readNativeBytes(path, 1024 * 1024)));
43661
43868
  } catch {
43662
43869
  throw new Error("NATIVE_SKILL_DRIFT: native installation input identity changed; review discovery and catalog");
43663
43870
  }
@@ -43681,25 +43888,25 @@ function assertNativeExportAllowed(dataDir2 = getDataDirReadOnly()) {
43681
43888
 
43682
43889
  // src/lib/portable-skills.ts
43683
43890
  import {
43684
- existsSync as existsSync9,
43891
+ existsSync as existsSync10,
43685
43892
  mkdirSync as mkdirSync7,
43686
43893
  mkdtempSync,
43687
43894
  readdirSync as readdirSync10,
43688
- realpathSync as realpathSync10,
43895
+ realpathSync as realpathSync11,
43689
43896
  renameSync as renameSync4,
43690
43897
  rmSync as rmSync2,
43691
43898
  statSync as statSync9,
43692
43899
  writeFileSync as writeFileSync6
43693
43900
  } from "fs";
43694
- import { basename as basename10, dirname as dirname18, isAbsolute as isAbsolute18, join as join26, normalize as normalize4, relative as relative6, resolve as resolve17, sep as sep8 } from "path";
43901
+ import { basename as basename10, dirname as dirname18, isAbsolute as isAbsolute18, join as join27, normalize as normalize4, relative as relative6, resolve as resolve18, sep as sep8 } from "path";
43695
43902
 
43696
43903
  // src/lib/registry-data/index.ts
43697
43904
  var SKILLS = [];
43698
43905
 
43699
43906
  // src/lib/skill-hash.ts
43700
43907
  import { createHash as createHash19 } from "crypto";
43701
- import { existsSync as existsSync7, readdirSync as readdirSync9, readFileSync as readFileSync15, statSync as statSync7 } from "fs";
43702
- import { join as join23, sep as sep6 } from "path";
43908
+ import { existsSync as existsSync8, readdirSync as readdirSync9, readFileSync as readFileSync15, statSync as statSync7 } from "fs";
43909
+ import { join as join24, sep as sep6 } from "path";
43703
43910
  var CONTENT_HASH_ALGORITHM = "sha256";
43704
43911
  var HASH_EXCLUDE_DIRS = new Set([".git", "node_modules", "dist", "build", ".turbo"]);
43705
43912
  function excludedHashEntry(name, directory) {
@@ -43761,8 +43968,8 @@ function collectBundleFiles(skillPath) {
43761
43968
  if (seen.has(entry))
43762
43969
  continue;
43763
43970
  seen.add(entry);
43764
- const absolute = join23(skillPath, entry);
43765
- if (!existsSync7(absolute))
43971
+ const absolute = join24(skillPath, entry);
43972
+ if (!existsSync8(absolute))
43766
43973
  continue;
43767
43974
  if (statSync7(absolute).isDirectory())
43768
43975
  collectDirectory(files, absolute, entry);
@@ -43775,7 +43982,7 @@ function collectDirectory(files, dir, rel) {
43775
43982
  for (const entry of readdirSync9(dir).sort()) {
43776
43983
  if (entry.startsWith("."))
43777
43984
  continue;
43778
- const absolute = join23(dir, entry);
43985
+ const absolute = join24(dir, entry);
43779
43986
  const childRel = `${rel}/${entry}`;
43780
43987
  let stats;
43781
43988
  try {
@@ -43836,7 +44043,7 @@ async function hashBundleFilesCooperatively(files, check) {
43836
44043
  hash2.update(chunk);
43837
44044
  bytesSinceYield += chunk.byteLength;
43838
44045
  if (bytesSinceYield >= 256 * 1024) {
43839
- await new Promise((resolve16) => setImmediate(resolve16));
44046
+ await new Promise((resolve17) => setImmediate(resolve17));
43840
44047
  bytesSinceYield = 0;
43841
44048
  }
43842
44049
  }
@@ -43989,7 +44196,7 @@ async function hashContentEntries(entries, options) {
43989
44196
  const normalized = [];
43990
44197
  let normalizedBytes = 0;
43991
44198
  let manifest;
43992
- await new Promise((resolve16) => setImmediate(resolve16));
44199
+ await new Promise((resolve17) => setImmediate(resolve17));
43993
44200
  for (const entry of snapshot2) {
43994
44201
  check();
43995
44202
  if (!coveredContentPath(entry.path))
@@ -44002,7 +44209,7 @@ async function hashContentEntries(entries, options) {
44002
44209
  contentLimit("Content hash normalized byte limit exceeded");
44003
44210
  normalizedBytes += file.content.byteLength;
44004
44211
  normalized.push(file);
44005
- await new Promise((resolve16) => setImmediate(resolve16));
44212
+ await new Promise((resolve17) => setImmediate(resolve17));
44006
44213
  }
44007
44214
  normalized.sort((a, b) => a.rel < b.rel ? -1 : a.rel > b.rel ? 1 : 0);
44008
44215
  check();
@@ -44209,14 +44416,14 @@ function validateRuntimeContract(manifest, issues, strict) {
44209
44416
  // src/lib/portable-skills-files.ts
44210
44417
  import {
44211
44418
  cpSync,
44212
- existsSync as existsSync8,
44213
- lstatSync as lstatSync20,
44419
+ existsSync as existsSync9,
44420
+ lstatSync as lstatSync21,
44214
44421
  mkdirSync as mkdirSync6,
44215
44422
  readFileSync as readFileSync16,
44216
- realpathSync as realpathSync8,
44423
+ realpathSync as realpathSync9,
44217
44424
  writeFileSync as writeFileSync5
44218
44425
  } from "fs";
44219
- import { basename as basename8, dirname as dirname16, join as join24, relative as relative5 } from "path";
44426
+ import { basename as basename8, dirname as dirname16, join as join25, relative as relative5 } from "path";
44220
44427
  var ANY_SEGMENT_COPY_EXCLUDES = new Set([
44221
44428
  ".git",
44222
44429
  ".DS_Store",
@@ -44273,12 +44480,12 @@ function readPortableSkillManifestForImport(skillPath) {
44273
44480
  return readManifest(skillPath, basename8(skillPath), normalizeNewPortableSkillName);
44274
44481
  }
44275
44482
  function readManifest(skillPath, fallbackName, normalizeName) {
44276
- const skillJsonPath = join24(skillPath, "skill.json");
44277
- const skillMdPath = join24(skillPath, "SKILL.md");
44278
- const pkgPath = join24(skillPath, "package.json");
44279
- const jsonManifest = existsSync8(skillJsonPath) ? readJsonObject(skillJsonPath) : undefined;
44280
- const frontmatter = existsSync8(skillMdPath) ? parseSkillFrontmatter(readFileSync16(skillMdPath, "utf-8")) ?? undefined : undefined;
44281
- const pkg = existsSync8(pkgPath) ? readJsonObject(pkgPath) : undefined;
44483
+ const skillJsonPath = join25(skillPath, "skill.json");
44484
+ const skillMdPath = join25(skillPath, "SKILL.md");
44485
+ const pkgPath = join25(skillPath, "package.json");
44486
+ const jsonManifest = existsSync9(skillJsonPath) ? readJsonObject(skillJsonPath) : undefined;
44487
+ const frontmatter = existsSync9(skillMdPath) ? parseSkillFrontmatter(readFileSync16(skillMdPath, "utf-8")) ?? undefined : undefined;
44488
+ const pkg = existsSync9(pkgPath) ? readJsonObject(pkgPath) : undefined;
44282
44489
  const name = normalizeName(stringField(jsonManifest, "name") ?? frontmatter?.name ?? stringValue(pkg?.name) ?? fallbackName);
44283
44490
  const description = stringField(jsonManifest, "description") ?? frontmatter?.description ?? stringValue(pkg?.description) ?? `${name} skill`;
44284
44491
  const version = readDeclaredSkillVersion(skillPath) ?? PORTABLE_SKILL_DEFAULT_VERSION;
@@ -44307,12 +44514,12 @@ function parseSkillKind(value) {
44307
44514
  return;
44308
44515
  }
44309
44516
  function readDeclaredSkillVersion(skillPath) {
44310
- const skillJsonPath = join24(skillPath, "skill.json");
44311
- const skillMdPath = join24(skillPath, "SKILL.md");
44312
- const pkgPath = join24(skillPath, "package.json");
44313
- const jsonManifest = existsSync8(skillJsonPath) ? readJsonObject(skillJsonPath) : undefined;
44314
- const frontmatter = existsSync8(skillMdPath) ? parseSkillFrontmatter(readFileSync16(skillMdPath, "utf-8")) ?? undefined : undefined;
44315
- const pkg = existsSync8(pkgPath) ? readJsonObject(pkgPath) : undefined;
44517
+ const skillJsonPath = join25(skillPath, "skill.json");
44518
+ const skillMdPath = join25(skillPath, "SKILL.md");
44519
+ const pkgPath = join25(skillPath, "package.json");
44520
+ const jsonManifest = existsSync9(skillJsonPath) ? readJsonObject(skillJsonPath) : undefined;
44521
+ const frontmatter = existsSync9(skillMdPath) ? parseSkillFrontmatter(readFileSync16(skillMdPath, "utf-8")) ?? undefined : undefined;
44522
+ const pkg = existsSync9(pkgPath) ? readJsonObject(pkgPath) : undefined;
44316
44523
  return stringField(jsonManifest, "version") ?? frontmatter?.version ?? stringValue(pkg?.version);
44317
44524
  }
44318
44525
  function createInstructionManifest(name, options) {
@@ -44333,7 +44540,7 @@ function createInstructionManifest(name, options) {
44333
44540
  }
44334
44541
  function writeInstructionSkillTemplate(skillPath, manifest) {
44335
44542
  mkdirSync6(skillPath, { recursive: true });
44336
- writeFileSync5(join24(skillPath, "SKILL.md"), renderInstructionSkillMd(manifest));
44543
+ writeFileSync5(join25(skillPath, "SKILL.md"), renderInstructionSkillMd(manifest));
44337
44544
  writeSkillJsonWithHash(skillPath, manifest);
44338
44545
  }
44339
44546
  function renderInstructionSkillMd(manifest) {
@@ -44383,12 +44590,12 @@ function createPortableManifest(name, options) {
44383
44590
  };
44384
44591
  }
44385
44592
  function writePortableSkillTemplate(skillPath, manifest) {
44386
- mkdirSync6(join24(skillPath, "src"), { recursive: true });
44387
- writeFileSync5(join24(skillPath, "SKILL.md"), renderSkillMd(manifest));
44388
- writeFileSync5(join24(skillPath, "AGENTS.md"), renderAgentsMd(manifest));
44389
- writeFileSync5(join24(skillPath, "package.json"), renderPackageJson(manifest));
44390
- writeFileSync5(join24(skillPath, "tsconfig.json"), renderTsconfig());
44391
- writeFileSync5(join24(skillPath, "src", "index.ts"), renderEntrypoint(manifest));
44593
+ mkdirSync6(join25(skillPath, "src"), { recursive: true });
44594
+ writeFileSync5(join25(skillPath, "SKILL.md"), renderSkillMd(manifest));
44595
+ writeFileSync5(join25(skillPath, "AGENTS.md"), renderAgentsMd(manifest));
44596
+ writeFileSync5(join25(skillPath, "package.json"), renderPackageJson(manifest));
44597
+ writeFileSync5(join25(skillPath, "tsconfig.json"), renderTsconfig());
44598
+ writeFileSync5(join25(skillPath, "src", "index.ts"), renderEntrypoint(manifest));
44392
44599
  writeSkillJsonWithHash(skillPath, manifest);
44393
44600
  }
44394
44601
  function fillContractDefaults(manifest, entrypoint) {
@@ -44413,7 +44620,7 @@ function writeSkillJsonWithHash(skillPath, manifest) {
44413
44620
  content_hash: undefined
44414
44621
  }
44415
44622
  };
44416
- writeFileSync5(join24(skillPath, "skill.json"), `${JSON.stringify({ ...existing, ...renderSkillJsonObject(withoutHash) }, null, 2)}
44623
+ writeFileSync5(join25(skillPath, "skill.json"), `${JSON.stringify({ ...existing, ...renderSkillJsonObject(withoutHash) }, null, 2)}
44417
44624
  `);
44418
44625
  const hash2 = computeContentHash(skillPath);
44419
44626
  const withHash = {
@@ -44423,13 +44630,13 @@ function writeSkillJsonWithHash(skillPath, manifest) {
44423
44630
  content_hash: hash2
44424
44631
  }
44425
44632
  };
44426
- writeFileSync5(join24(skillPath, "skill.json"), `${JSON.stringify({ ...existing, ...renderSkillJsonObject(withHash) }, null, 2)}
44633
+ writeFileSync5(join25(skillPath, "skill.json"), `${JSON.stringify({ ...existing, ...renderSkillJsonObject(withHash) }, null, 2)}
44427
44634
  `);
44428
44635
  return withHash;
44429
44636
  }
44430
44637
  function readExistingSkillJson(skillPath) {
44431
- const path = join24(skillPath, "skill.json");
44432
- if (!existsSync8(path))
44638
+ const path = join25(skillPath, "skill.json");
44639
+ if (!existsSync9(path))
44433
44640
  return {};
44434
44641
  try {
44435
44642
  const parsed = JSON.parse(readFileSync16(path, "utf-8"));
@@ -44462,28 +44669,28 @@ function ensurePortableSkillFiles(skillPath, manifest) {
44462
44669
  tags: next.tags?.length ? next.tags : ["custom", next.name]
44463
44670
  };
44464
44671
  const entry = next.commands[0]?.entry ?? "src/index.ts";
44465
- if (entry && !existsSync8(join24(skillPath, entry))) {
44466
- mkdirSync6(dirname16(join24(skillPath, entry)), { recursive: true });
44467
- writeFileSync5(join24(skillPath, entry), renderEntrypoint(next));
44672
+ if (entry && !existsSync9(join25(skillPath, entry))) {
44673
+ mkdirSync6(dirname16(join25(skillPath, entry)), { recursive: true });
44674
+ writeFileSync5(join25(skillPath, entry), renderEntrypoint(next));
44468
44675
  }
44469
- if (!existsSync8(join24(skillPath, "SKILL.md")))
44470
- writeFileSync5(join24(skillPath, "SKILL.md"), renderSkillMd(next));
44676
+ if (!existsSync9(join25(skillPath, "SKILL.md")))
44677
+ writeFileSync5(join25(skillPath, "SKILL.md"), renderSkillMd(next));
44471
44678
  else
44472
- writeFileSync5(join24(skillPath, "SKILL.md"), ensureSkillMdFrontmatter(readFileSync16(join24(skillPath, "SKILL.md"), "utf-8"), next));
44473
- if (!existsSync8(join24(skillPath, "AGENTS.md")))
44474
- writeFileSync5(join24(skillPath, "AGENTS.md"), renderAgentsMd(next));
44679
+ writeFileSync5(join25(skillPath, "SKILL.md"), ensureSkillMdFrontmatter(readFileSync16(join25(skillPath, "SKILL.md"), "utf-8"), next));
44680
+ if (!existsSync9(join25(skillPath, "AGENTS.md")))
44681
+ writeFileSync5(join25(skillPath, "AGENTS.md"), renderAgentsMd(next));
44475
44682
  ensurePackageJson(skillPath, next);
44476
- if (!existsSync8(join24(skillPath, "tsconfig.json")))
44477
- writeFileSync5(join24(skillPath, "tsconfig.json"), renderTsconfig());
44683
+ if (!existsSync9(join25(skillPath, "tsconfig.json")))
44684
+ writeFileSync5(join25(skillPath, "tsconfig.json"), renderTsconfig());
44478
44685
  writeSkillJsonWithHash(skillPath, next);
44479
44686
  return readPortableSkillManifest(skillPath, next.name);
44480
44687
  }
44481
44688
  function ensurePackageJson(skillPath, manifest) {
44482
- const pkgPath = join24(skillPath, "package.json");
44689
+ const pkgPath = join25(skillPath, "package.json");
44483
44690
  const first = manifest.commands[0] ?? { name: manifest.name, entry: "src/index.ts" };
44484
44691
  const commandName = normalizePortableSkillName(first.name || manifest.name);
44485
44692
  const entry = (first.entry ?? "src/index.ts").replace(/^\.\//, "");
44486
- if (!existsSync8(pkgPath)) {
44693
+ if (!existsSync9(pkgPath)) {
44487
44694
  writeFileSync5(pkgPath, renderPackageJson(manifest));
44488
44695
  return;
44489
44696
  }
@@ -44526,18 +44733,18 @@ function ensureInstructionSkillFiles(skillPath, manifest) {
44526
44733
  inputs: [],
44527
44734
  commands: []
44528
44735
  };
44529
- if (!existsSync8(join24(skillPath, "SKILL.md"))) {
44530
- writeFileSync5(join24(skillPath, "SKILL.md"), renderSkillMd(next));
44736
+ if (!existsSync9(join25(skillPath, "SKILL.md"))) {
44737
+ writeFileSync5(join25(skillPath, "SKILL.md"), renderSkillMd(next));
44531
44738
  } else {
44532
- const path = join24(skillPath, "SKILL.md");
44739
+ const path = join25(skillPath, "SKILL.md");
44533
44740
  const content = readFileSync16(path, "utf8");
44534
44741
  const declaredName = parseSkillFrontmatter(content)?.name;
44535
44742
  if (declaredName && declaredName !== next.name) {
44536
44743
  writeFileSync5(path, renameInstructionFrontmatter(content, next.name));
44537
44744
  }
44538
44745
  }
44539
- const packagePath = join24(skillPath, "package.json");
44540
- if (existsSync8(packagePath)) {
44746
+ const packagePath = join25(skillPath, "package.json");
44747
+ if (existsSync9(packagePath)) {
44541
44748
  const pkg = readJsonObject(packagePath);
44542
44749
  if (typeof pkg.name === "string" && pkg.name !== next.name) {
44543
44750
  writeFileSync5(packagePath, `${JSON.stringify({ ...pkg, name: next.name }, null, 2)}
@@ -44568,7 +44775,7 @@ function renameInstructionFrontmatter(content, name) {
44568
44775
  return renamed + content.slice(frontmatter[0].length);
44569
44776
  }
44570
44777
  function copySkillDirectory(source, destination) {
44571
- const resolvedSource = lstatSync20(source).isSymbolicLink() ? realpathSync8(source) : source;
44778
+ const resolvedSource = lstatSync21(source).isSymbolicLink() ? realpathSync9(source) : source;
44572
44779
  mkdirSync6(destination, { recursive: true });
44573
44780
  cpSync(resolvedSource, destination, {
44574
44781
  recursive: true,
@@ -44581,7 +44788,7 @@ function copySkillDirectory(source, destination) {
44581
44788
  if (isExcludedCopyEntry(segments[i], i === 0))
44582
44789
  return false;
44583
44790
  }
44584
- if (lstatSync20(src).isSymbolicLink())
44791
+ if (lstatSync21(src).isSymbolicLink())
44585
44792
  return false;
44586
44793
  return true;
44587
44794
  }
@@ -44860,12 +45067,12 @@ function escapeJsString(value) {
44860
45067
  }
44861
45068
 
44862
45069
  // src/lib/authoring-path.ts
44863
- import { lstatSync as lstatSync21, realpathSync as realpathSync9 } from "fs";
45070
+ import { lstatSync as lstatSync22, realpathSync as realpathSync10 } from "fs";
44864
45071
  import { homedir as homedir4 } from "os";
44865
- import { basename as basename9, dirname as dirname17, join as join25, resolve as resolve16, sep as sep7 } from "path";
45072
+ import { basename as basename9, dirname as dirname17, join as join26, resolve as resolve17, sep as sep7 } from "path";
44866
45073
  var NATIVE_DISCOVERY_ROOTS = NATIVE_SKILL_ROOTS.map(([, path]) => path.split("/"));
44867
45074
  function pathParts(path) {
44868
- return resolve16(path).split(sep7).filter(Boolean);
45075
+ return resolve17(path).split(sep7).filter(Boolean);
44869
45076
  }
44870
45077
  function nativeRootMatch(path) {
44871
45078
  const parts = pathParts(path);
@@ -44879,24 +45086,24 @@ function nativeRootMatch(path) {
44879
45086
  return;
44880
45087
  }
44881
45088
  function physicalPath(path) {
44882
- let cursor = resolve16(path);
45089
+ let cursor = resolve17(path);
44883
45090
  const suffix = [];
44884
- while (!lstatSync21(cursor, { throwIfNoEntry: false })) {
45091
+ while (!lstatSync22(cursor, { throwIfNoEntry: false })) {
44885
45092
  suffix.unshift(basename9(cursor));
44886
45093
  const parent = dirname17(cursor);
44887
45094
  if (parent === cursor)
44888
- return resolve16(path);
45095
+ return resolve17(path);
44889
45096
  cursor = parent;
44890
45097
  }
44891
- return resolve16(realpathSync9(cursor), ...suffix);
45098
+ return resolve17(realpathSync10(cursor), ...suffix);
44892
45099
  }
44893
45100
  function contains(root2, path) {
44894
45101
  return path === root2 || path.startsWith(root2 + sep7);
44895
45102
  }
44896
45103
  function configuredRoots(home, explicitHome) {
44897
- const homeData = join25(home, ".hasna", "skills");
45104
+ const homeData = join26(home, ".hasna", "skills");
44898
45105
  const homePolicy = readManagedSkillPolicySnapshot(homeData);
44899
- const configuredPolicy = !explicitHome && resolve16(getDataDirReadOnly()) !== resolve16(homeData) ? readManagedSkillPolicySnapshot(getDataDirReadOnly()) : null;
45106
+ const configuredPolicy = !explicitHome && resolve17(getDataDirReadOnly()) !== resolve17(homeData) ? readManagedSkillPolicySnapshot(getDataDirReadOnly()) : null;
44900
45107
  const policy = homePolicy ?? configuredPolicy;
44901
45108
  const bridge = policy?.value.bridge;
44902
45109
  if (bridge && (typeof bridge.home !== "string" || physicalPath(bridge.home) !== physicalPath(home))) {
@@ -44925,8 +45132,8 @@ function configuredRoots(home, explicitHome) {
44925
45132
  admitBinding(binding);
44926
45133
  continue;
44927
45134
  }
44928
- const nativeHome = join25(home, agent === "opencode" ? ".config/opencode" : `.${agent}`);
44929
- if (!lstatSync21(nativeHome, { throwIfNoEntry: false }))
45135
+ const nativeHome = join26(home, agent === "opencode" ? ".config/opencode" : `.${agent}`);
45136
+ if (!lstatSync22(nativeHome, { throwIfNoEntry: false }))
44930
45137
  continue;
44931
45138
  roots.push(...resolveAgentDiscovery({ home, agent, canonical: physicalPath }).roots);
44932
45139
  }
@@ -44935,22 +45142,22 @@ function configuredRoots(home, explicitHome) {
44935
45142
  function assertPortableAuthoringPath(path, options = {}) {
44936
45143
  if (typeof path !== "string" || !path || path.includes("\x00"))
44937
45144
  throw new Error("Invalid portable authoring path");
44938
- const lexical = resolve16(path);
45145
+ const lexical = resolve17(path);
44939
45146
  const physical = physicalPath(lexical);
44940
45147
  const candidates = [lexical, physical];
44941
45148
  let native = candidates.map(nativeRootMatch).find(Boolean);
44942
- const home = resolve16(options.homeDir ?? homedir4());
44943
- const defaults = NATIVE_DISCOVERY_ROOTS.map((parts) => join25(home, ...parts));
44944
- defaults.push(join25(home, ".codex/plugins/cache"), join25(home, ".claude/plugins/cache"), join25(home, ".claude/plugins/synced"), join25(home, ".gemini/extensions"));
45149
+ const home = resolve17(options.homeDir ?? homedir4());
45150
+ const defaults = NATIVE_DISCOVERY_ROOTS.map((parts) => join26(home, ...parts));
45151
+ defaults.push(join26(home, ".codex/plugins/cache"), join26(home, ".claude/plugins/cache"), join26(home, ".claude/plugins/synced"), join26(home, ".gemini/extensions"));
44945
45152
  for (const root2 of defaults) {
44946
- if (candidates.some((candidate2) => contains(resolve16(root2), candidate2) || contains(physicalPath(root2), candidate2)))
45153
+ if (candidates.some((candidate2) => contains(resolve17(root2), candidate2) || contains(physicalPath(root2), candidate2)))
44947
45154
  native ??= root2;
44948
45155
  }
44949
45156
  if (native) {
44950
45157
  throw new Error(`Refusing portable Skills authoring below native discovery root '${native}': ${lexical}. Set HASNA_SKILLS_DIR to a private authoring corpus outside native roots.`);
44951
45158
  }
44952
45159
  for (const root2 of configuredRoots(home, options.homeDir !== undefined)) {
44953
- if (candidates.some((candidate2) => contains(resolve16(root2), candidate2) || contains(physicalPath(root2), candidate2))) {
45160
+ if (candidates.some((candidate2) => contains(resolve17(root2), candidate2) || contains(physicalPath(root2), candidate2))) {
44954
45161
  throw new Error(`Refusing portable Skills authoring below configured native discovery root: ${lexical}`);
44955
45162
  }
44956
45163
  }
@@ -44962,15 +45169,15 @@ function getPortableSkillsRoot(options = {}) {
44962
45169
  function resolvePortableSkillsRoot(options, migrate) {
44963
45170
  if (options.rootDir)
44964
45171
  return options.rootDir;
44965
- const appDir = options.homeDir ? join26(options.homeDir, ".hasna", "skills") : migrate ? getDataDir() : getDataDirReadOnly();
44966
- const cache = join26(appDir, SKILLS_CACHE_DIRNAME);
45172
+ const appDir = options.homeDir ? join27(options.homeDir, ".hasna", "skills") : migrate ? getDataDir() : getDataDirReadOnly();
45173
+ const cache = join27(appDir, SKILLS_CACHE_DIRNAME);
44967
45174
  if (isOwnerLayoutMigrated(appDir) && safeIsDirectory(cache))
44968
45175
  return cache;
44969
- const installed = join26(appDir, INSTALLED_SKILLS_DIRNAME);
45176
+ const installed = join27(appDir, INSTALLED_SKILLS_DIRNAME);
44970
45177
  return installed;
44971
45178
  }
44972
45179
  function getPortableSkillPath(name, options = {}) {
44973
- return join26(getPortableSkillsRoot(options), normalizePortableSkillName(name));
45180
+ return join27(getPortableSkillsRoot(options), normalizePortableSkillName(name));
44974
45181
  }
44975
45182
  function findPortableSkill(name, options = {}) {
44976
45183
  let normalized;
@@ -44980,7 +45187,7 @@ function findPortableSkill(name, options = {}) {
44980
45187
  return null;
44981
45188
  }
44982
45189
  const path = getPortableSkillPath(normalized, options);
44983
- if (!existsSync9(path) || !statSync9(path).isDirectory())
45190
+ if (!existsSync10(path) || !statSync9(path).isDirectory())
44984
45191
  return null;
44985
45192
  try {
44986
45193
  return summarizePortableSkill(path, normalized);
@@ -44996,7 +45203,7 @@ function listPortableSkills(options = {}) {
44996
45203
  for (const entry of readdirSync10(root2).sort()) {
44997
45204
  if (entry.startsWith("."))
44998
45205
  continue;
44999
- const path = join26(root2, entry);
45206
+ const path = join27(root2, entry);
45000
45207
  if (!safeIsDirectory(path))
45001
45208
  continue;
45002
45209
  try {
@@ -45030,11 +45237,11 @@ function isOfficialSkillName(name) {
45030
45237
  function scaffoldPortableSkill(name, options = {}) {
45031
45238
  const skillName = normalizeNewPortableSkillName(name);
45032
45239
  const readOnlyRoot = resolvePortableSkillsRoot(options, false);
45033
- assertPortableAuthoringPath(join26(readOnlyRoot, skillName), options);
45240
+ assertPortableAuthoringPath(join27(readOnlyRoot, skillName), options);
45034
45241
  const root2 = getPortableSkillsRoot(options);
45035
- const skillPath = join26(root2, skillName);
45242
+ const skillPath = join27(root2, skillName);
45036
45243
  assertPortableAuthoringPath(skillPath, options);
45037
- if (existsSync9(skillPath)) {
45244
+ if (existsSync10(skillPath)) {
45038
45245
  if (!options.overwrite)
45039
45246
  throw new Error(`Skill '${skillName}' already exists at ${skillPath}`);
45040
45247
  rmSync2(skillPath, { recursive: true, force: true });
@@ -45052,7 +45259,7 @@ function scaffoldPortableSkill(name, options = {}) {
45052
45259
  }
45053
45260
  function portPortableSkillDirectory(sourceDir, options = {}) {
45054
45261
  const absoluteSource = normalize4(sourceDir);
45055
- if (!existsSync9(absoluteSource) || !statSync9(absoluteSource).isDirectory()) {
45262
+ if (!existsSync10(absoluteSource) || !statSync9(absoluteSource).isDirectory()) {
45056
45263
  throw new Error(`Import directory not found: ${sourceDir}`);
45057
45264
  }
45058
45265
  const continueOnError = options.continueOnError ?? true;
@@ -45066,7 +45273,7 @@ function portPortableSkillDirectory(sourceDir, options = {}) {
45066
45273
  const skipped = [];
45067
45274
  const entries = readdirSync10(absoluteSource, { withFileTypes: true }).map((entry) => entry.name).filter((entryName) => !entryName.startsWith(".")).sort();
45068
45275
  for (const entryName of entries) {
45069
- const childPath = join26(absoluteSource, entryName);
45276
+ const childPath = join27(absoluteSource, entryName);
45070
45277
  if (!safeIsDirectory(childPath))
45071
45278
  continue;
45072
45279
  if (!isSkillCandidate(childPath)) {
@@ -45095,19 +45302,19 @@ function portPortableSkillDirectory(sourceDir, options = {}) {
45095
45302
  };
45096
45303
  }
45097
45304
  function isSkillCandidate(dir) {
45098
- return existsSync9(join26(dir, "SKILL.md")) || existsSync9(join26(dir, "skill.json")) || existsSync9(join26(dir, "package.json"));
45305
+ return existsSync10(join27(dir, "SKILL.md")) || existsSync10(join27(dir, "skill.json")) || existsSync10(join27(dir, "package.json"));
45099
45306
  }
45100
45307
  function physicalImportPath(path) {
45101
- let ancestor = resolve17(path);
45308
+ let ancestor = resolve18(path);
45102
45309
  const suffix = [];
45103
- while (!existsSync9(ancestor)) {
45310
+ while (!existsSync10(ancestor)) {
45104
45311
  suffix.unshift(basename10(ancestor));
45105
45312
  ancestor = dirname18(ancestor);
45106
45313
  }
45107
- return join26(realpathSync10(ancestor), ...suffix);
45314
+ return join27(realpathSync11(ancestor), ...suffix);
45108
45315
  }
45109
45316
  function assertDisjointImportPaths(source, destination) {
45110
- const sourcePath = realpathSync10(source);
45317
+ const sourcePath = realpathSync11(source);
45111
45318
  const destinationPath = physicalImportPath(destination);
45112
45319
  const contains2 = (parent, child) => {
45113
45320
  const path = relative6(parent, child);
@@ -45119,7 +45326,7 @@ function assertDisjointImportPaths(source, destination) {
45119
45326
  }
45120
45327
  function portPortableSkill(sourcePath, options = {}) {
45121
45328
  const absoluteSource = normalize4(sourcePath);
45122
- if (!existsSync9(absoluteSource) || !statSync9(absoluteSource).isDirectory()) {
45329
+ if (!existsSync10(absoluteSource) || !statSync9(absoluteSource).isDirectory()) {
45123
45330
  throw new Error(`Skill source directory not found: ${sourcePath}`);
45124
45331
  }
45125
45332
  const inferred = readPortableSkillManifestForImport(absoluteSource);
@@ -45130,14 +45337,14 @@ function portPortableSkill(sourcePath, options = {}) {
45130
45337
  const via = explicitName ? `Name '${skillName}' matches a bundled official skill.` : `Inferred name '${skillName}'${sourceSlug && sourceSlug !== skillName ? ` (from source folder '${basename10(absoluteSource)}')` : ""} matches a bundled official skill.`;
45131
45338
  throw new Error(`${via} Importing it would shadow the official '${skillName}'. ` + `Pass --name to choose a different name, or --allow-shadow to override deliberately.`);
45132
45339
  }
45133
- const readOnlyDestination = join26(resolvePortableSkillsRoot(options, false), skillName);
45340
+ const readOnlyDestination = join27(resolvePortableSkillsRoot(options, false), skillName);
45134
45341
  assertPortableAuthoringPath(readOnlyDestination, options);
45135
45342
  assertDisjointImportPaths(absoluteSource, readOnlyDestination);
45136
45343
  const root2 = getPortableSkillsRoot(options);
45137
- const destination = join26(root2, skillName);
45344
+ const destination = join27(root2, skillName);
45138
45345
  assertPortableAuthoringPath(destination, options);
45139
45346
  assertDisjointImportPaths(absoluteSource, destination);
45140
- if (existsSync9(destination)) {
45347
+ if (existsSync10(destination)) {
45141
45348
  if (!options.overwrite)
45142
45349
  throw new Error(`Skill '${skillName}' already exists at ${destination}`);
45143
45350
  rmSync2(destination, { recursive: true, force: true });
@@ -45179,13 +45386,13 @@ function buildCorpusManifest(input, name) {
45179
45386
  function writeCorpusSkill(input, options = {}) {
45180
45387
  const name = normalizePortableSkillName(input.name);
45181
45388
  const readOnlyRoot = resolvePortableSkillsRoot(options, false);
45182
- assertPortableAuthoringPath(join26(readOnlyRoot, name), options);
45389
+ assertPortableAuthoringPath(join27(readOnlyRoot, name), options);
45183
45390
  const root2 = getPortableSkillsRoot(options);
45184
- const skillPath = join26(root2, name);
45391
+ const skillPath = join27(root2, name);
45185
45392
  assertPortableAuthoringPath(skillPath, options);
45186
- const created = !existsSync9(skillPath);
45393
+ const created = !existsSync10(skillPath);
45187
45394
  mkdirSync7(skillPath, { recursive: true });
45188
- writeFileSync6(join26(skillPath, "SKILL.md"), input.skillMd);
45395
+ writeFileSync6(join27(skillPath, "SKILL.md"), input.skillMd);
45189
45396
  const manifest = buildCorpusManifest(input, name);
45190
45397
  writeSkillJsonWithHash(skillPath, manifest);
45191
45398
  return { name, path: skillPath, manifest, created };
@@ -45193,22 +45400,22 @@ function writeCorpusSkill(input, options = {}) {
45193
45400
  function installCorpusSkillAtomically(input, options = {}) {
45194
45401
  const name = normalizePortableSkillName(input.name);
45195
45402
  const readOnlyRoot = resolvePortableSkillsRoot(options, false);
45196
- assertPortableAuthoringPath(join26(readOnlyRoot, name), options);
45403
+ assertPortableAuthoringPath(join27(readOnlyRoot, name), options);
45197
45404
  const root2 = getPortableSkillsRoot(options);
45198
- const target = join26(root2, name);
45405
+ const target = join27(root2, name);
45199
45406
  assertPortableAuthoringPath(target, options);
45200
- const created = !existsSync9(target);
45407
+ const created = !existsSync10(target);
45201
45408
  mkdirSync7(root2, { recursive: true });
45202
- const staging = mkdtempSync(join26(root2, `.pull-${name}-`));
45409
+ const staging = mkdtempSync(join27(root2, `.pull-${name}-`));
45203
45410
  let moved = false;
45204
45411
  let backup = null;
45205
45412
  try {
45206
- writeFileSync6(join26(staging, "SKILL.md"), input.skillMd);
45413
+ writeFileSync6(join27(staging, "SKILL.md"), input.skillMd);
45207
45414
  const manifest = buildCorpusManifest(input, name);
45208
45415
  writeSkillJsonWithHash(staging, manifest);
45209
- if (existsSync9(target)) {
45210
- backup = mkdtempSync(join26(root2, `.pull-backup-${name}-`));
45211
- renameSync4(target, join26(backup, name));
45416
+ if (existsSync10(target)) {
45417
+ backup = mkdtempSync(join27(root2, `.pull-backup-${name}-`));
45418
+ renameSync4(target, join27(backup, name));
45212
45419
  moved = true;
45213
45420
  }
45214
45421
  renameSync4(staging, target);
@@ -45217,9 +45424,9 @@ function installCorpusSkillAtomically(input, options = {}) {
45217
45424
  return { name, path: target, manifest, created };
45218
45425
  } catch (error) {
45219
45426
  rmSync2(staging, { recursive: true, force: true });
45220
- if (moved && backup && existsSync9(join26(backup, name))) {
45427
+ if (moved && backup && existsSync10(join27(backup, name))) {
45221
45428
  try {
45222
- renameSync4(join26(backup, name), target);
45429
+ renameSync4(join27(backup, name), target);
45223
45430
  } catch {}
45224
45431
  }
45225
45432
  throw error;
@@ -45231,10 +45438,10 @@ function validatePortableSkillDirectory(name, skillPath) {
45231
45438
  const issues = [...base.issues];
45232
45439
  const warnings = [...base.warnings];
45233
45440
  let manifest;
45234
- if (existsSync9(skillPath)) {
45235
- const skillJsonPath = join26(skillPath, "skill.json");
45236
- const skillMdPath = join26(skillPath, "SKILL.md");
45237
- if (!existsSync9(skillJsonPath) && !existsSync9(skillMdPath)) {
45441
+ if (existsSync10(skillPath)) {
45442
+ const skillJsonPath = join27(skillPath, "skill.json");
45443
+ const skillMdPath = join27(skillPath, "SKILL.md");
45444
+ if (!existsSync10(skillJsonPath) && !existsSync10(skillMdPath)) {
45238
45445
  add3(issues, "portable.manifest_missing", "Missing portable manifest: expected SKILL.md frontmatter and/or skill.json");
45239
45446
  }
45240
45447
  try {
@@ -45253,7 +45460,7 @@ function validatePortableSkillDirectory(name, skillPath) {
45253
45460
  add3(issues, "portable.version_missing", "Portable manifest missing version");
45254
45461
  }
45255
45462
  const contractIssues = validatePortableManifestContract(manifest, {
45256
- strict: existsSync9(join26(skillPath, "skill.json")),
45463
+ strict: existsSync10(join27(skillPath, "skill.json")),
45257
45464
  skillPath
45258
45465
  });
45259
45466
  for (const issue of contractIssues)
@@ -45293,8 +45500,8 @@ function validatePortableSkillDirectory(name, skillPath) {
45293
45500
  add3(issues, "portable.command_entry_unsafe", `Command '${command.name}' entry '${command.entry}' must stay inside the skill directory`);
45294
45501
  continue;
45295
45502
  }
45296
- const entryPath = join26(skillPath, command.entry);
45297
- if (!existsSync9(entryPath))
45503
+ const entryPath = join27(skillPath, command.entry);
45504
+ if (!existsSync10(entryPath))
45298
45505
  add3(issues, "portable.command_entry_missing", `Command '${command.name}' entry '${command.entry}' is missing`);
45299
45506
  else if (statSync9(entryPath).isDirectory())
45300
45507
  add3(issues, "portable.command_entry_directory", `Command '${command.name}' entry '${command.entry}' must be a file`);
@@ -45304,7 +45511,7 @@ function validatePortableSkillDirectory(name, skillPath) {
45304
45511
  } catch (error) {
45305
45512
  add3(issues, "portable.manifest_invalid", error.message);
45306
45513
  }
45307
- if (manifest?.kind !== "instruction" && !existsSync9(join26(skillPath, "AGENTS.md"))) {
45514
+ if (manifest?.kind !== "instruction" && !existsSync10(join27(skillPath, "AGENTS.md"))) {
45308
45515
  add3(issues, "portable.agents_missing", "Missing AGENTS.md with build-out instructions for coding agents");
45309
45516
  }
45310
45517
  }
@@ -45340,13 +45547,13 @@ async function runPortableSkill(name, args, options = {}) {
45340
45547
  if (!isSafeRelativePath2(command.entry)) {
45341
45548
  return { exitCode: 1, error: `Portable skill '${name}' command entry is unsafe` };
45342
45549
  }
45343
- const entryPath = join26(skill.path, command.entry);
45344
- if (!existsSync9(entryPath)) {
45550
+ const entryPath = join27(skill.path, command.entry);
45551
+ if (!existsSync10(entryPath)) {
45345
45552
  return { exitCode: 1, error: `Entry point '${command.entry}' not found in portable skill '${name}'` };
45346
45553
  }
45347
- const pkgPath = join26(skill.path, "package.json");
45348
- const nodeModules = join26(skill.path, "node_modules");
45349
- if (existsSync9(pkgPath) && !existsSync9(nodeModules) && hasPackageDependencies(pkgPath)) {
45554
+ const pkgPath = join27(skill.path, "package.json");
45555
+ const nodeModules = join27(skill.path, "node_modules");
45556
+ if (existsSync10(pkgPath) && !existsSync10(nodeModules) && hasPackageDependencies(pkgPath)) {
45350
45557
  const install = Bun.spawn(["bun", "install", "--no-save"], {
45351
45558
  cwd: skill.path,
45352
45559
  stdout: "pipe",
@@ -45417,9 +45624,9 @@ function isSkillsOwnershipMarker(marker) {
45417
45624
  return typeof marker === "object" && marker !== null && Object.hasOwn(marker, "managedBy") && marker.managedBy === SYNC_MARKER_MANAGED_BY;
45418
45625
  }
45419
45626
  function hasSkillsOwnershipMarker(dir) {
45420
- const path = join27(dir, SYNC_MARKER_FILE);
45627
+ const path = join28(dir, SYNC_MARKER_FILE);
45421
45628
  try {
45422
- if (!lstatSync22(path).isFile())
45629
+ if (!lstatSync23(path).isFile())
45423
45630
  return false;
45424
45631
  const marker = JSON.parse(readFileSync17(path, "utf8"));
45425
45632
  return isSkillsOwnershipMarker(marker);
@@ -45441,9 +45648,9 @@ function resolveSyncAgents(arg) {
45441
45648
  function agentGlobalSkillsDir(agent, homeDir3 = homedir5()) {
45442
45649
  switch (agent) {
45443
45650
  case "opencode":
45444
- return join27(homeDir3, ".config", "opencode", "skills");
45651
+ return join28(homeDir3, ".config", "opencode", "skills");
45445
45652
  default:
45446
- return join27(homeDir3, `.${agent}`, "skills");
45653
+ return join28(homeDir3, `.${agent}`, "skills");
45447
45654
  }
45448
45655
  }
45449
45656
  function adaptSkillMdForAgent(skillMd, agent) {
@@ -45502,8 +45709,8 @@ function resolveSyncCorpus(options = {}) {
45502
45709
  function packageSourceRoots(source) {
45503
45710
  const roots = [];
45504
45711
  for (const sub of ["skills"]) {
45505
- const candidate2 = join27(source, sub);
45506
- if (existsSync10(candidate2) && isDirectory(candidate2))
45712
+ const candidate2 = join28(source, sub);
45713
+ if (existsSync11(candidate2) && isDirectory(candidate2))
45507
45714
  roots.push(candidate2);
45508
45715
  }
45509
45716
  if (roots.length > 0)
@@ -45518,10 +45725,10 @@ function containsSkillDirectories(path) {
45518
45725
  return false;
45519
45726
  }
45520
45727
  return entries.some((entry) => {
45521
- const candidate2 = join27(path, entry);
45728
+ const candidate2 = join28(path, entry);
45522
45729
  if (!isDirectory(candidate2))
45523
45730
  return false;
45524
- return existsSync10(join27(candidate2, "SKILL.md")) || existsSync10(join27(candidate2, "skill.json")) || existsSync10(join27(candidate2, "package.json"));
45731
+ return existsSync11(join28(candidate2, "SKILL.md")) || existsSync11(join28(candidate2, "skill.json")) || existsSync11(join28(candidate2, "package.json"));
45525
45732
  });
45526
45733
  }
45527
45734
  function isDirectory(path) {
@@ -45561,7 +45768,7 @@ function syncSkillsToAgents(options = {}) {
45561
45768
  actions.push({
45562
45769
  skill: name,
45563
45770
  agent,
45564
- path: join27(agentGlobalSkillsDir(agent, homeDir3), name, "SKILL.md"),
45771
+ path: join28(agentGlobalSkillsDir(agent, homeDir3), name, "SKILL.md"),
45565
45772
  action: "skip",
45566
45773
  reason: "not found in this machine's corpus"
45567
45774
  });
@@ -45591,7 +45798,7 @@ function syncSkillsToAgents(options = {}) {
45591
45798
  }
45592
45799
  function writeManagedAgentSkill(params) {
45593
45800
  const homeDir3 = params.homeDir ?? homedir5();
45594
- const dir = join27(agentGlobalSkillsDir(params.agent, homeDir3), params.skill);
45801
+ const dir = join28(agentGlobalSkillsDir(params.agent, homeDir3), params.skill);
45595
45802
  const result = writeManagedSkillDir(dir, params.skillMd, {
45596
45803
  skill: params.skill,
45597
45804
  source: params.source,
@@ -45608,11 +45815,11 @@ function writeManagedAgentSkill(params) {
45608
45815
  };
45609
45816
  }
45610
45817
  function writeManagedSkillDir(dir, skillMd, options) {
45611
- const skillMdPath = join27(dir, "SKILL.md");
45612
- const markerPath = join27(dir, SYNC_MARKER_FILE);
45613
- const dirExists = existsSync10(dir);
45818
+ const skillMdPath = join28(dir, "SKILL.md");
45819
+ const markerPath = join28(dir, SYNC_MARKER_FILE);
45820
+ const dirExists = existsSync11(dir);
45614
45821
  const managed = hasSkillsOwnershipMarker(dir);
45615
- const hasSkillMd = existsSync10(skillMdPath);
45822
+ const hasSkillMd = existsSync11(skillMdPath);
45616
45823
  if (dirExists && !managed && !hasSkillMd) {
45617
45824
  return {
45618
45825
  action: "skip",
@@ -45624,7 +45831,7 @@ function writeManagedSkillDir(dir, skillMd, options) {
45624
45831
  return {
45625
45832
  action: "skip",
45626
45833
  path: skillMdPath,
45627
- reason: existsSync10(markerPath) ? "an unmanaged SKILL.md already exists here (invalid or foreign ownership marker); pass --force to overwrite" : "an unmanaged SKILL.md already exists here (hand-authored); pass --force to overwrite"
45834
+ reason: existsSync11(markerPath) ? "an unmanaged SKILL.md already exists here (invalid or foreign ownership marker); pass --force to overwrite" : "an unmanaged SKILL.md already exists here (hand-authored); pass --force to overwrite"
45628
45835
  };
45629
45836
  }
45630
45837
  if (dirExists && managed && hasSkillMd && !options.force && isPointerSkillMd(skillMd)) {
@@ -45647,11 +45854,11 @@ function writeManagedSkillDir(dir, skillMd, options) {
45647
45854
  return { action, path: skillMdPath };
45648
45855
  const parentDir = dirname19(dir);
45649
45856
  mkdirSync8(parentDir, { recursive: true });
45650
- const transactionDir = mkdtempSync2(join27(parentDir, `.hasna-skills-write-${basename11(dir)}-`));
45651
- const candidateDir = join27(transactionDir, "candidate");
45652
- const backupDir = join27(transactionDir, "backup");
45653
- const candidateSkillMdPath = join27(candidateDir, "SKILL.md");
45654
- const candidateMarkerPath = join27(candidateDir, SYNC_MARKER_FILE);
45857
+ const transactionDir = mkdtempSync2(join28(parentDir, `.hasna-skills-write-${basename11(dir)}-`));
45858
+ const candidateDir = join28(transactionDir, "candidate");
45859
+ const backupDir = join28(transactionDir, "backup");
45860
+ const candidateSkillMdPath = join28(candidateDir, "SKILL.md");
45861
+ const candidateMarkerPath = join28(candidateDir, SYNC_MARKER_FILE);
45655
45862
  const marker = {
45656
45863
  managedBy: SYNC_MARKER_MANAGED_BY,
45657
45864
  skill: options.skill,
@@ -45678,9 +45885,9 @@ function writeManagedSkillDir(dir, skillMd, options) {
45678
45885
  }
45679
45886
  renameDirectory(candidateDir, dir);
45680
45887
  } catch (error) {
45681
- if (originalMoved && existsSync10(backupDir)) {
45888
+ if (originalMoved && existsSync11(backupDir)) {
45682
45889
  try {
45683
- if (existsSync10(dir))
45890
+ if (existsSync11(dir))
45684
45891
  rmSync3(dir, { recursive: true, force: true });
45685
45892
  renameDirectory(backupDir, dir);
45686
45893
  originalMoved = false;
@@ -45700,7 +45907,7 @@ function writeManagedSkillDir(dir, skillMd, options) {
45700
45907
  return { action, path: skillMdPath };
45701
45908
  }
45702
45909
  function removeManagedAgentSkill(skill, agent, homeDir3 = homedir5()) {
45703
- const dir = join27(agentGlobalSkillsDir(agent, homeDir3), skill);
45910
+ const dir = join28(agentGlobalSkillsDir(agent, homeDir3), skill);
45704
45911
  if (!hasSkillsOwnershipMarker(dir))
45705
45912
  return false;
45706
45913
  rmSync3(dir, { recursive: true, force: true });
@@ -45708,8 +45915,8 @@ function removeManagedAgentSkill(skill, agent, homeDir3 = homedir5()) {
45708
45915
  }
45709
45916
  function sourceSkillMd(skillPath, name, description, kind, preferBundledDocs = false) {
45710
45917
  if (kind === undefined || kind === "instruction" || preferBundledDocs) {
45711
- const skillMdPath = join27(skillPath, "SKILL.md");
45712
- if (existsSync10(skillMdPath))
45918
+ const skillMdPath = join28(skillPath, "SKILL.md");
45919
+ if (existsSync11(skillMdPath))
45713
45920
  return readFileSync17(skillMdPath, "utf-8");
45714
45921
  }
45715
45922
  return pointerSkillMd(name, description);
@@ -45740,8 +45947,8 @@ function normalizeSkillName(name) {
45740
45947
  }
45741
45948
 
45742
45949
  // src/lib/registry.ts
45743
- import { existsSync as existsSync11, readFileSync as readFileSync18, readdirSync as readdirSync12 } from "fs";
45744
- import { join as join28 } from "path";
45950
+ import { existsSync as existsSync12, readFileSync as readFileSync18, readdirSync as readdirSync12 } from "fs";
45951
+ import { join as join29 } from "path";
45745
45952
 
45746
45953
  // src/lib/registry-merge.ts
45747
45954
  var SKILL_SOURCE_PRECEDENCE = {
@@ -45943,7 +46150,7 @@ function parseSkillMdFrontmatter(content) {
45943
46150
  return Object.keys(result).length > 0 ? result : null;
45944
46151
  }
45945
46152
  function discoverSkillsInDir(dir, source = "custom") {
45946
- if (!existsSync11(dir))
46153
+ if (!existsSync12(dir))
45947
46154
  return [];
45948
46155
  const result = [];
45949
46156
  try {
@@ -45951,8 +46158,8 @@ function discoverSkillsInDir(dir, source = "custom") {
45951
46158
  for (const entry of entries) {
45952
46159
  if (!entry.isDirectory())
45953
46160
  continue;
45954
- const skillMdPath = join28(dir, entry.name, "SKILL.md");
45955
- if (!existsSync11(skillMdPath))
46161
+ const skillMdPath = join29(dir, entry.name, "SKILL.md");
46162
+ if (!existsSync12(skillMdPath))
45956
46163
  continue;
45957
46164
  let content;
45958
46165
  try {
@@ -45971,7 +46178,7 @@ function discoverSkillsInDir(dir, source = "custom") {
45971
46178
  category: fm.category || "Development Tools",
45972
46179
  tags: fm.tags || [],
45973
46180
  ...fm.kind ? { kind: fm.kind } : {},
45974
- ...isHostedMetadataSkillDir(join28(dir, entry.name)) ? { serverOwned: true } : {},
46181
+ ...isHostedMetadataSkillDir(join29(dir, entry.name)) ? { serverOwned: true } : {},
45975
46182
  source
45976
46183
  });
45977
46184
  }
@@ -45980,16 +46187,16 @@ function discoverSkillsInDir(dir, source = "custom") {
45980
46187
  }
45981
46188
  function findExtensionSkillPath(name) {
45982
46189
  const config = loadConfig();
45983
- if (!config.extensionsDir || !existsSync11(config.extensionsDir))
46190
+ if (!config.extensionsDir || !existsSync12(config.extensionsDir))
45984
46191
  return null;
45985
46192
  try {
45986
46193
  const entries = readdirSync12(config.extensionsDir, { withFileTypes: true });
45987
46194
  for (const entry of entries) {
45988
46195
  if (!entry.isDirectory())
45989
46196
  continue;
45990
- const skillDir = join28(config.extensionsDir, entry.name);
45991
- const skillMdPath = join28(skillDir, "SKILL.md");
45992
- if (!existsSync11(skillMdPath))
46197
+ const skillDir = join29(config.extensionsDir, entry.name);
46198
+ const skillMdPath = join29(skillDir, "SKILL.md");
46199
+ if (!existsSync12(skillMdPath))
45993
46200
  continue;
45994
46201
  let content;
45995
46202
  try {
@@ -46036,21 +46243,21 @@ function clearRegistryCache() {
46036
46243
  registryCacheTime = 0;
46037
46244
  registryCacheKey = null;
46038
46245
  }
46039
- function getSkillsByCategory(category) {
46040
- return loadRegistry().filter((s) => s.category === category);
46246
+ function getSkillsByCategory(category, catalog) {
46247
+ return (catalog ?? loadRegistry()).filter((s) => s.category === category);
46041
46248
  }
46042
46249
  function getSkill(name) {
46043
46250
  const registry = loadRegistry();
46044
46251
  const slug = normalizeSkillSlug(name);
46045
46252
  return registry.find((s) => s.name === slug) ?? registry.find((s) => s.name === resolveSkillAlias(slug));
46046
46253
  }
46047
- function getSkillsByTag(tag) {
46254
+ function getSkillsByTag(tag, catalog) {
46048
46255
  const needle = tag.toLowerCase();
46049
- return loadRegistry().filter((s) => s.tags.some((t2) => t2.toLowerCase().includes(needle)));
46256
+ return (catalog ?? loadRegistry()).filter((s) => s.tags.some((t2) => t2.toLowerCase().includes(needle)));
46050
46257
  }
46051
- function getAllTags() {
46258
+ function getAllTags(catalog) {
46052
46259
  const tagSet = new Set;
46053
- for (const skill of loadRegistry()) {
46260
+ for (const skill of catalog ?? loadRegistry()) {
46054
46261
  for (const tag of skill.tags)
46055
46262
  tagSet.add(tag.toLowerCase());
46056
46263
  }
@@ -46058,8 +46265,8 @@ function getAllTags() {
46058
46265
  }
46059
46266
 
46060
46267
  // src/lib/project-state.ts
46061
- import { existsSync as existsSync12, mkdirSync as mkdirSync9, readFileSync as readFileSync19, writeFileSync as writeFileSync8 } from "fs";
46062
- import { join as join29 } from "path";
46268
+ import { existsSync as existsSync13, mkdirSync as mkdirSync9, readFileSync as readFileSync19, writeFileSync as writeFileSync8 } from "fs";
46269
+ import { join as join30 } from "path";
46063
46270
  var VALID_PIN_SOURCES = [
46064
46271
  "official",
46065
46272
  "custom",
@@ -46074,14 +46281,14 @@ var SKILLS_PROJECT_DIR = ".skills";
46074
46281
  var PROJECT_CONFIG_FILE = "project.json";
46075
46282
  var DEFAULT_EXPORT_DIR = ".skills/exports";
46076
46283
  function getProjectStateDir(targetDir = process.cwd()) {
46077
- return join29(targetDir, SKILLS_PROJECT_DIR);
46284
+ return join30(targetDir, SKILLS_PROJECT_DIR);
46078
46285
  }
46079
46286
  function getProjectConfigPath(targetDir = process.cwd()) {
46080
- return join29(getProjectStateDir(targetDir), PROJECT_CONFIG_FILE);
46287
+ return join30(getProjectStateDir(targetDir), PROJECT_CONFIG_FILE);
46081
46288
  }
46082
46289
  function loadProjectConfig(targetDir = process.cwd()) {
46083
46290
  const path = getProjectConfigPath(targetDir);
46084
- if (!existsSync12(path))
46291
+ if (!existsSync13(path))
46085
46292
  return null;
46086
46293
  try {
46087
46294
  return normalizeProjectConfig(JSON.parse(readFileSync19(path, "utf-8")));
@@ -46206,19 +46413,19 @@ function getSkillPath(name) {
46206
46413
  const extensionPath = findExtensionSkillPath(skillName);
46207
46414
  if (extensionPath)
46208
46415
  return extensionPath;
46209
- return join30(getPortableSkillsRoot(), skillName);
46416
+ return join31(getPortableSkillsRoot(), skillName);
46210
46417
  }
46211
46418
  function getCanonicalSkillName(name) {
46212
46419
  return getSkill(name)?.name ?? resolveSkillAlias(normalizeSkillSlug(name));
46213
46420
  }
46214
46421
  function skillExists(name) {
46215
- return existsSync13(getSkillPath(name));
46422
+ return existsSync14(getSkillPath(name));
46216
46423
  }
46217
46424
  function installSkill(name, options = {}) {
46218
46425
  const { targetDir = process.cwd(), overwrite = false } = options;
46219
46426
  const canonicalName = getCanonicalSkillName(name);
46220
46427
  const skillName = normalizeSkillName(canonicalName);
46221
- if (!existsSync13(getSkillPath(name))) {
46428
+ if (!existsSync14(getSkillPath(name))) {
46222
46429
  const knownOfficial = Boolean(getSkill(name));
46223
46430
  return {
46224
46431
  skill: canonicalName,
@@ -46245,7 +46452,7 @@ function installSkill(name, options = {}) {
46245
46452
  }
46246
46453
  function installSkillSource(name, _options = {}) {
46247
46454
  const canonicalName = getCanonicalSkillName(name);
46248
- if (!existsSync13(getSkillPath(name))) {
46455
+ if (!existsSync14(getSkillPath(name))) {
46249
46456
  return { skill: canonicalName, success: false, error: `Skill '${name}' not found`, mode: "source" };
46250
46457
  }
46251
46458
  return {
@@ -46266,11 +46473,11 @@ function installSkillManifest(manifest, _options = {}) {
46266
46473
  }
46267
46474
  function createLocalSkillManifest(name, generateSkillMd) {
46268
46475
  const sourcePath = getSkillPath(name);
46269
- if (!existsSync13(sourcePath))
46476
+ if (!existsSync14(sourcePath))
46270
46477
  return null;
46271
46478
  let skillMd = "";
46272
- const skillMdPath = join30(sourcePath, "SKILL.md");
46273
- if (existsSync13(skillMdPath)) {
46479
+ const skillMdPath = join31(sourcePath, "SKILL.md");
46480
+ if (existsSync14(skillMdPath)) {
46274
46481
  skillMd = readFileSync20(skillMdPath, "utf-8");
46275
46482
  } else if (generateSkillMd) {
46276
46483
  skillMd = generateSkillMd(name) ?? "";
@@ -46343,21 +46550,21 @@ function getAgentSkillsDir(agent, scope = "global", projectDir) {
46343
46550
  const base = projectDir || process.cwd();
46344
46551
  switch (agent) {
46345
46552
  case "pi":
46346
- return scope === "project" ? join30(base, ".pi", "skills") : join30(homedir6(), ".pi", "agent", "skills");
46553
+ return scope === "project" ? join31(base, ".pi", "skills") : join31(homedir6(), ".pi", "agent", "skills");
46347
46554
  case "opencode":
46348
- return scope === "project" ? join30(base, ".opencode", "skills") : join30(homedir6(), ".config", "opencode", "skills");
46555
+ return scope === "project" ? join31(base, ".opencode", "skills") : join31(homedir6(), ".config", "opencode", "skills");
46349
46556
  default:
46350
- return scope === "project" ? join30(base, `.${agent}`, "skills") : join30(homedir6(), `.${agent}`, "skills");
46557
+ return scope === "project" ? join31(base, `.${agent}`, "skills") : join31(homedir6(), `.${agent}`, "skills");
46351
46558
  }
46352
46559
  }
46353
46560
  function getAgentSkillPath(name, agent, scope = "global", projectDir) {
46354
46561
  const skillName = normalizeSkillName(getCanonicalSkillName(name));
46355
- return join30(getAgentSkillsDir(agent, scope, projectDir), skillName);
46562
+ return join31(getAgentSkillsDir(agent, scope, projectDir), skillName);
46356
46563
  }
46357
46564
  function installSkillForAgent(name, options, generateSkillMd) {
46358
46565
  assertNativeExportAllowed();
46359
46566
  const canonicalName = getCanonicalSkillName(name);
46360
- if (!existsSync13(getSkillPath(name))) {
46567
+ if (!existsSync14(getSkillPath(name))) {
46361
46568
  return { skill: canonicalName, success: false, error: `Skill '${name}' not found` };
46362
46569
  }
46363
46570
  const scope = options.scope ?? "global";
@@ -46388,8 +46595,8 @@ function removeSkillForAgent(name, options) {
46388
46595
  }
46389
46596
  function resolveAgentSkillMd(name, generateSkillMd) {
46390
46597
  const sourcePath = getSkillPath(name);
46391
- const skillMdPath = join30(sourcePath, "SKILL.md");
46392
- if (existsSync13(skillMdPath))
46598
+ const skillMdPath = join31(sourcePath, "SKILL.md");
46599
+ if (existsSync14(skillMdPath))
46393
46600
  return readFileSync20(skillMdPath, "utf-8");
46394
46601
  if (generateSkillMd)
46395
46602
  return generateSkillMd(name);
@@ -46408,7 +46615,7 @@ function warnMissingDependencies(name, targetDir) {
46408
46615
  }
46409
46616
  function generateMinimalSkillMd(name) {
46410
46617
  const sourcePath = getSkillPath(name);
46411
- if (!existsSync13(sourcePath))
46618
+ if (!existsSync14(sourcePath))
46412
46619
  return null;
46413
46620
  const canonicalName = getCanonicalSkillName(name);
46414
46621
  const meta = getSkill(canonicalName);
@@ -46423,7 +46630,7 @@ function generateMinimalSkillMd(name) {
46423
46630
  "---",
46424
46631
  ""
46425
46632
  ].filter(Boolean);
46426
- const fallbackDoc = readFileIfExists(join30(sourcePath, "README.md")) || readFileIfExists(join30(sourcePath, "CLAUDE.md"));
46633
+ const fallbackDoc = readFileIfExists(join31(sourcePath, "README.md")) || readFileIfExists(join31(sourcePath, "CLAUDE.md"));
46427
46634
  if (fallbackDoc)
46428
46635
  return `${frontmatter.join(`
46429
46636
  `)}${fallbackDoc.trim()}
@@ -46442,8 +46649,8 @@ skills run ${canonicalName}
46442
46649
  `;
46443
46650
  }
46444
46651
  function readBundledSkillVersion(name) {
46445
- const pkgPath = join30(getSkillPath(name), "package.json");
46446
- if (!existsSync13(pkgPath))
46652
+ const pkgPath = join31(getSkillPath(name), "package.json");
46653
+ if (!existsSync14(pkgPath))
46447
46654
  return "unknown";
46448
46655
  try {
46449
46656
  const pkg = JSON.parse(readFileSync20(pkgPath, "utf-8"));
@@ -46453,7 +46660,7 @@ function readBundledSkillVersion(name) {
46453
46660
  }
46454
46661
  }
46455
46662
  function readFileIfExists(path) {
46456
- return existsSync13(path) ? readFileSync20(path, "utf-8") : null;
46663
+ return existsSync14(path) ? readFileSync20(path, "utf-8") : null;
46457
46664
  }
46458
46665
  function loadProjectConfigCompat(targetDir) {
46459
46666
  return loadProjectConfig(targetDir);
@@ -46497,8 +46704,8 @@ function selectSkillDoc(docs, file) {
46497
46704
  function isInstructionSkillDir(skillPath, meta) {
46498
46705
  if (meta?.kind === "instruction")
46499
46706
  return true;
46500
- const skillMdPath = join31(skillPath, "SKILL.md");
46501
- if (!existsSync14(skillMdPath))
46707
+ const skillMdPath = join32(skillPath, "SKILL.md");
46708
+ if (!existsSync15(skillMdPath))
46502
46709
  return false;
46503
46710
  try {
46504
46711
  return parseSkillFrontmatter(readFileSync21(skillMdPath, "utf-8"))?.kind === "instruction";
@@ -46524,12 +46731,12 @@ var HOSTED_PROVIDER_ENV_PREFIXES = [
46524
46731
  ];
46525
46732
  function getSkillDocs(name) {
46526
46733
  const skillPath = getSkillPath(name);
46527
- if (!existsSync14(skillPath))
46734
+ if (!existsSync15(skillPath))
46528
46735
  return null;
46529
46736
  return {
46530
- skillMd: readIfExists(join31(skillPath, "SKILL.md")),
46531
- readme: readIfExists(join31(skillPath, "README.md")),
46532
- claudeMd: readIfExists(join31(skillPath, "CLAUDE.md"))
46737
+ skillMd: readIfExists(join32(skillPath, "SKILL.md")),
46738
+ readme: readIfExists(join32(skillPath, "README.md")),
46739
+ claudeMd: readIfExists(join32(skillPath, "CLAUDE.md"))
46533
46740
  };
46534
46741
  }
46535
46742
  function getSkillBestDoc(name, file) {
@@ -46541,18 +46748,18 @@ function getSkillBestDoc(name, file) {
46541
46748
  }
46542
46749
  function getSkillRequirements(name) {
46543
46750
  const skillPath = getSkillPath(name);
46544
- if (!existsSync14(skillPath))
46751
+ if (!existsSync15(skillPath))
46545
46752
  return null;
46546
46753
  const texts = [];
46547
46754
  for (const file of ["SKILL.md", "README.md", "CLAUDE.md", ".env.example", ".env.local.example"]) {
46548
- const content = readIfExists(join31(skillPath, file));
46755
+ const content = readIfExists(join32(skillPath, file));
46549
46756
  if (content)
46550
46757
  texts.push(content);
46551
46758
  }
46552
46759
  const meta = getSkill(name);
46553
46760
  let dependencies = {};
46554
46761
  try {
46555
- dependencies = JSON.parse(readFileSync21(join31(skillPath, "package.json"), "utf8")).dependencies || {};
46762
+ dependencies = JSON.parse(readFileSync21(join32(skillPath, "package.json"), "utf8")).dependencies || {};
46556
46763
  } catch {}
46557
46764
  return getSkillRequirementsFromContent(name, texts, dependencies, meta);
46558
46765
  }
@@ -46605,7 +46812,7 @@ async function runSkill(name, args, options = {}) {
46605
46812
  const meta = getSkill(name);
46606
46813
  const canonicalName = meta?.name ?? name;
46607
46814
  const skillPath = getSkillPath(canonicalName);
46608
- if (!existsSync14(skillPath)) {
46815
+ if (!existsSync15(skillPath)) {
46609
46816
  return { exitCode: 1, error: `Skill '${name}' not found` };
46610
46817
  }
46611
46818
  if (isInstructionSkillDir(skillPath, meta)) {
@@ -46614,8 +46821,8 @@ async function runSkill(name, args, options = {}) {
46614
46821
  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'.`
46615
46822
  };
46616
46823
  }
46617
- const pkgPath = join31(skillPath, "package.json");
46618
- if (!existsSync14(pkgPath)) {
46824
+ const pkgPath = join32(skillPath, "package.json");
46825
+ if (!existsSync15(pkgPath)) {
46619
46826
  return { exitCode: 1, error: `No package.json in skill '${name}'` };
46620
46827
  }
46621
46828
  let entryPoint2;
@@ -46634,12 +46841,12 @@ async function runSkill(name, args, options = {}) {
46634
46841
  } catch {
46635
46842
  return { exitCode: 1, error: `Failed to parse package.json for skill '${name}'` };
46636
46843
  }
46637
- const entryPath = join31(skillPath, entryPoint2);
46638
- if (!existsSync14(entryPath)) {
46844
+ const entryPath = join32(skillPath, entryPoint2);
46845
+ if (!existsSync15(entryPath)) {
46639
46846
  return { exitCode: 1, error: `Entry point '${entryPoint2}' not found in skill '${name}'` };
46640
46847
  }
46641
46848
  const env = { ...process.env, ...options.env };
46642
- if (!existsSync14(join31(skillPath, "node_modules")) || hasDependencyPreparationMarker(skillPath)) {
46849
+ if (!existsSync15(join32(skillPath, "node_modules")) || hasDependencyPreparationMarker(skillPath)) {
46643
46850
  const failure = await prepareSkillDependencies(skillPath, env, options.preparationTimeoutMs);
46644
46851
  if (failure)
46645
46852
  return failure;
@@ -46708,7 +46915,7 @@ function generateSkillMd(name) {
46708
46915
  if (!meta)
46709
46916
  return null;
46710
46917
  const skillPath = getSkillPath(name);
46711
- if (!existsSync14(skillPath))
46918
+ if (!existsSync15(skillPath))
46712
46919
  return null;
46713
46920
  const frontmatter = [
46714
46921
  "---",
@@ -46717,11 +46924,11 @@ function generateSkillMd(name) {
46717
46924
  "---"
46718
46925
  ].join(`
46719
46926
  `);
46720
- const readme = readIfExists(join31(skillPath, "README.md"));
46721
- const claudeMd = readIfExists(join31(skillPath, "CLAUDE.md"));
46927
+ const readme = readIfExists(join32(skillPath, "README.md"));
46928
+ const claudeMd = readIfExists(join32(skillPath, "CLAUDE.md"));
46722
46929
  let cliCommand = null;
46723
- const pkgPath = join31(skillPath, "package.json");
46724
- if (existsSync14(pkgPath)) {
46930
+ const pkgPath = join32(skillPath, "package.json");
46931
+ if (existsSync15(pkgPath)) {
46725
46932
  try {
46726
46933
  const pkg = JSON.parse(readFileSync21(pkgPath, "utf-8"));
46727
46934
  if (pkg.bin) {
@@ -46798,7 +47005,7 @@ function extractEnvVars(text2) {
46798
47005
  }
46799
47006
  function readIfExists(path) {
46800
47007
  try {
46801
- if (existsSync14(path)) {
47008
+ if (existsSync15(path)) {
46802
47009
  return readFileSync21(path, "utf-8");
46803
47010
  }
46804
47011
  } catch {}
@@ -46865,6 +47072,8 @@ async function syncSelectionProfile(profileId, options = {}) {
46865
47072
  async function resolveSelectionContext(profileId, options = {}) {
46866
47073
  const sessionState = options.sessionId ? readSkillSessionSnapshotIfExists(options.sessionId, options) : null;
46867
47074
  const session = sessionState?.receipt ?? null;
47075
+ if (options.nativeParentSessionId !== undefined && session && (session.parent?.sessionId ?? null) !== options.nativeParentSessionId)
47076
+ throw new SkillSelectionError("SESSION_PARENT_MISMATCH", "The native session id is already bound to different parent custody.");
46868
47077
  const parentState = !session && options.parentSessionId ? readSkillSessionSnapshotIfExists(options.parentSessionId, options) : null;
46869
47078
  if (!session && options.parentSessionId && !parentState) {
46870
47079
  throw new SkillSelectionError("SESSION_PARENT_NOT_FOUND", "A child Skills session requires an existing parent receipt so its inherited pin can be bound exactly.");
@@ -47002,7 +47211,7 @@ async function executeSelectedLocal(selected, options = {}) {
47002
47211
  throw new SkillSelectionError("INVALID_SECRET_BINDINGS", "Explicit environment values must be bounded strings without NUL bytes.");
47003
47212
  secretEnv[name] = value;
47004
47213
  }
47005
- const runDirectory = mkdtempSync3(join32(tmpdir(), "skills-execution-"));
47214
+ const runDirectory = mkdtempSync3(join33(tmpdir(), "skills-execution-"));
47006
47215
  const paths = new SkillEntryPaths;
47007
47216
  for (const entry of entries) {
47008
47217
  paths.add(entry.path, 100, () => {
@@ -47010,12 +47219,12 @@ async function executeSelectedLocal(selected, options = {}) {
47010
47219
  }, () => {
47011
47220
  throw new SkillSelectionError("INVALID_BUNDLE_PATH", "The execution bundle path exceeds its limit.");
47012
47221
  });
47013
- const destination = join32(runDirectory, entry.path);
47222
+ const destination = join33(runDirectory, entry.path);
47014
47223
  mkdirSync10(dirname20(destination), { recursive: true, mode: 448 });
47015
47224
  writeFileSync9(destination, entry.bytes, { flag: "wx", mode: entry.mode & 511 });
47016
47225
  }
47017
47226
  env.SKILLS_INPUT_JSON = input;
47018
- env.SKILLS_WORKSPACE_DIR = resolve18(options.cwd ?? process.cwd());
47227
+ env.SKILLS_WORKSPACE_DIR = resolve19(options.cwd ?? process.cwd());
47019
47228
  env.SKILLS_RUN_DIR = runDirectory;
47020
47229
  if (runtime.version) {
47021
47230
  const version = await subprocess([executable, ...runtimeName === "bun" ? ["--no-env-file"] : [], "--version"], runDirectory, env, "", Math.min(timeoutMs, 5000));
@@ -47028,7 +47237,7 @@ async function executeSelectedLocal(selected, options = {}) {
47028
47237
  const { authority: authority2, workspaceId, profileRevision, slug, version, bundleDigest } = selection2;
47029
47238
  const request2 = {
47030
47239
  selection: { authority: authority2, workspaceId, profileId, profileRevision, slug, version, bundleDigest },
47031
- consumer: { stationId: process.env.HASNA_STATION || stationHostname2(), workspaceDirectory: realpathSync11(options.cwd ?? process.cwd()) }
47240
+ consumer: { stationId: process.env.HASNA_STATION || stationHostname2(), workspaceDirectory: realpathSync12(options.cwd ?? process.cwd()) }
47032
47241
  };
47033
47242
  const grant = await (options.resolveExecutionGrant ?? resolveExecutionGrant)(request2);
47034
47243
  if (!grant || !grantIdentifier(grant.policyRevision) || !grantIdentifier(grant.grantId))
@@ -47038,7 +47247,7 @@ async function executeSelectedLocal(selected, options = {}) {
47038
47247
  }
47039
47248
  if (bindings)
47040
47249
  secretEnv = await resolveSelectedSecrets(bindings, options.createSecretsClient);
47041
- const result = await subprocess([executable, ...runtimeName === "bun" ? ["--no-env-file"] : [], join32(runDirectory, declaredEntry), ...args], runDirectory, { ...env, ...secretEnv }, input, timeoutMs);
47250
+ const result = await subprocess([executable, ...runtimeName === "bun" ? ["--no-env-file"] : [], join33(runDirectory, declaredEntry), ...args], runDirectory, { ...env, ...secretEnv }, input, timeoutMs);
47042
47251
  result.stdout = redactExecutionSecrets(result.stdout, secretEnv);
47043
47252
  result.stderr = redactExecutionSecrets(result.stderr, secretEnv);
47044
47253
  const receipt = {
@@ -47051,7 +47260,7 @@ async function executeSelectedLocal(selected, options = {}) {
47051
47260
  ...bindings ? { secretBinding: { schema: bindings.schema, selection: bindings.selection, consumer: bindings.consumer, secretsAuthority: bindings.secretsAuthority, bindings: bindings.bindings } } : {},
47052
47261
  ...result
47053
47262
  };
47054
- writeFileSync9(join32(runDirectory, ".execution-receipt.json"), JSON.stringify({ ...receipt, stdout: undefined, stderr: undefined }), { mode: 384 });
47263
+ writeFileSync9(join33(runDirectory, ".execution-receipt.json"), JSON.stringify({ ...receipt, stdout: undefined, stderr: undefined }), { mode: 384 });
47055
47264
  return receipt;
47056
47265
  }
47057
47266
  async function subprocess(command, cwd, env, input, timeoutMs) {
@@ -57116,7 +57325,7 @@ import { mkdirSync as mkdirSync12 } from "fs";
57116
57325
  import { dirname as dirname24 } from "path";
57117
57326
 
57118
57327
  // src/server/database-url.ts
57119
- import { isAbsolute as isAbsolute19, join as join34 } from "path";
57328
+ import { isAbsolute as isAbsolute19, join as join35 } from "path";
57120
57329
  import { fileURLToPath as fileURLToPath3 } from "url";
57121
57330
  var DEFAULT_SQLITE_FILENAME2 = "server.db";
57122
57331
  var SQLITE_MEMORY_PATH = ":memory:";
@@ -57125,7 +57334,7 @@ var SQLITE_SCHEMES = new Set(["sqlite", "sqlite3", "file"]);
57125
57334
  var MEMORY_SCHEMES = new Set(["memory"]);
57126
57335
  var SQLITE_EXTENSIONS = [".db", ".sqlite", ".sqlite3", ".db3"];
57127
57336
  function defaultSqlitePath() {
57128
- return join34(getDataDir(), DEFAULT_SQLITE_FILENAME2);
57337
+ return join35(getDataDir(), DEFAULT_SQLITE_FILENAME2);
57129
57338
  }
57130
57339
  function resolveDatabaseTarget(raw) {
57131
57340
  const value = raw?.trim();
@@ -57152,7 +57361,7 @@ function resolveDatabaseTarget(raw) {
57152
57361
  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()}.`);
57153
57362
  }
57154
57363
  if (looksLikeSqlitePath(value)) {
57155
- const path = isAbsolute19(value) ? value : join34(process.cwd(), value);
57364
+ const path = isAbsolute19(value) ? value : join35(process.cwd(), value);
57156
57365
  return { kind: "sqlite", path, durable: true, label: `sqlite (${path})` };
57157
57366
  }
57158
57367
  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()}.`);
@@ -57176,7 +57385,7 @@ function sqlitePathFromUrl(value, scheme) {
57176
57385
  }
57177
57386
  return rest.slice(2).replace(/^\/\/+/, "/");
57178
57387
  }
57179
- return isAbsolute19(rest) ? rest : join34(process.cwd(), rest);
57388
+ return isAbsolute19(rest) ? rest : join35(process.cwd(), rest);
57180
57389
  }
57181
57390
  function looksLikeSqlitePath(value) {
57182
57391
  if (value.includes("/"))
@@ -57409,7 +57618,7 @@ class PostgresSkillSelectionStore {
57409
57618
  // src/server/sqlite-store.ts
57410
57619
  import { randomUUID as randomUUID7 } from "crypto";
57411
57620
  import { mkdirSync as mkdirSync11, readFileSync as readFileSync23, readdirSync as readdirSync13 } from "fs";
57412
- import { dirname as dirname23, join as join36 } from "path";
57621
+ import { dirname as dirname23, join as join37 } from "path";
57413
57622
 
57414
57623
  // src/server/auth.ts
57415
57624
  import { createHash as createHash23 } from "crypto";
@@ -57467,16 +57676,16 @@ function permitsSkillsRoute(principal, method, resource) {
57467
57676
  }
57468
57677
 
57469
57678
  // src/server/migrations-dir.ts
57470
- import { existsSync as existsSync15 } from "fs";
57471
- import { dirname as dirname22, join as join35 } from "path";
57679
+ import { existsSync as existsSync16 } from "fs";
57680
+ import { dirname as dirname22, join as join36 } from "path";
57472
57681
  var MIGRATION_DIALECTS = ["postgres", "sqlite"];
57473
57682
  var MAX_WALK_UP = 6;
57474
57683
  function findMigrationsRoot(startDirs = defaultStartDirs()) {
57475
57684
  for (const start of startDirs) {
57476
57685
  let dir = start;
57477
57686
  for (let level = 0;level < MAX_WALK_UP; level += 1) {
57478
- const candidate2 = join35(dir, "migrations");
57479
- if (MIGRATION_DIALECTS.some((dialect) => existsSync15(join35(candidate2, dialect))))
57687
+ const candidate2 = join36(dir, "migrations");
57688
+ if (MIGRATION_DIALECTS.some((dialect) => existsSync16(join36(candidate2, dialect))))
57480
57689
  return candidate2;
57481
57690
  const parent = dirname22(dir);
57482
57691
  if (parent === dir)
@@ -57490,8 +57699,8 @@ function resolveMigrationsDir(dialect, root4 = findMigrationsRoot()) {
57490
57699
  if (!root4) {
57491
57700
  throw new Error(`could not locate the migrations directory for dialect "${dialect}". ` + `Expected a migrations/${dialect}/ folder alongside the package root.`);
57492
57701
  }
57493
- const dir = join35(root4, dialect);
57494
- if (!existsSync15(dir)) {
57702
+ const dir = join36(root4, dialect);
57703
+ if (!existsSync16(dir)) {
57495
57704
  throw new Error(`migrations directory not found: ${dir}`);
57496
57705
  }
57497
57706
  return dir;
@@ -58462,7 +58671,7 @@ function applySqliteMigrations(db, migrationsDir = resolveMigrationsDir("sqlite"
58462
58671
  const appliedNow = [];
58463
58672
  for (const file of files) {
58464
58673
  const version2 = file.replace(/\.sql$/, "");
58465
- const text2 = readFileSync23(join36(migrationsDir, file), "utf8");
58674
+ const text2 = readFileSync23(join37(migrationsDir, file), "utf8");
58466
58675
  const apply = db.transaction(() => {
58467
58676
  const already = db.query("SELECT 1 AS present FROM schema_migrations WHERE version = ? LIMIT 1").get(version2);
58468
58677
  if (already)
@@ -90719,10 +90928,10 @@ async function readQuoteUnavailableCode(response) {
90719
90928
  let timer;
90720
90929
  let deadlineExceeded = false;
90721
90930
  const expired = Symbol("quote body deadline");
90722
- const deadline = new Promise((resolve20) => {
90931
+ const deadline = new Promise((resolve21) => {
90723
90932
  timer = setTimeout(() => {
90724
90933
  deadlineExceeded = true;
90725
- resolve20(expired);
90934
+ resolve21(expired);
90726
90935
  reader.cancel().catch(() => {});
90727
90936
  }, 1500);
90728
90937
  });
@@ -92208,12 +92417,12 @@ class RemotePrivatePublicationsClient {
92208
92417
  previous = view;
92209
92418
  if (!["queued", "verifying"].includes(view.state) || Date.now() >= until)
92210
92419
  return view;
92211
- await new Promise((resolve20) => {
92420
+ await new Promise((resolve21) => {
92212
92421
  const timer = setTimeout(done, Math.min(1000, until - Date.now()));
92213
92422
  function done() {
92214
92423
  clearTimeout(timer);
92215
92424
  options.signal?.removeEventListener("abort", done);
92216
- resolve20();
92425
+ resolve21();
92217
92426
  }
92218
92427
  options.signal?.addEventListener("abort", done, { once: true });
92219
92428
  });
@@ -92445,23 +92654,23 @@ class RemoteSkillsAuthClient {
92445
92654
  }
92446
92655
  }
92447
92656
  // src/lib/private-publication-recovery.ts
92448
- import { constants as constants13, closeSync as closeSync17, fsyncSync as fsyncSync5, fstatSync as fstatSync17, lstatSync as lstatSync23, mkdirSync as mkdirSync14, openSync as openSync17, readSync as readSync12, realpathSync as realpathSync12, renameSync as renameSync6, unlinkSync as unlinkSync5, writeFileSync as writeFileSync10 } from "fs";
92449
- import { dirname as dirname26, isAbsolute as isAbsolute20, join as join38, resolve as resolve20 } from "path";
92657
+ import { constants as constants13, closeSync as closeSync17, fsyncSync as fsyncSync5, fstatSync as fstatSync17, lstatSync as lstatSync24, mkdirSync as mkdirSync14, openSync as openSync17, readSync as readSync12, realpathSync as realpathSync13, renameSync as renameSync6, unlinkSync as unlinkSync5, writeFileSync as writeFileSync10 } from "fs";
92658
+ import { dirname as dirname26, isAbsolute as isAbsolute20, join as join39, resolve as resolve21 } from "path";
92450
92659
  import { randomUUID as randomUUID11 } from "crypto";
92451
92660
  var fail = () => {
92452
92661
  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.");
92453
92662
  };
92454
92663
  function safeDirectory(directory) {
92455
- if (!isAbsolute20(directory) || directory !== resolve20(directory) || realpathSync12(directory) !== directory)
92664
+ if (!isAbsolute20(directory) || directory !== resolve21(directory) || realpathSync13(directory) !== directory)
92456
92665
  return fail();
92457
92666
  for (let path2 = directory;; path2 = dirname26(path2)) {
92458
- const stat2 = lstatSync23(path2);
92667
+ const stat2 = lstatSync24(path2);
92459
92668
  if (!stat2.isDirectory() || stat2.isSymbolicLink())
92460
92669
  return fail();
92461
92670
  if (path2 === dirname26(path2))
92462
92671
  break;
92463
92672
  }
92464
- const own2 = lstatSync23(directory);
92673
+ const own2 = lstatSync24(directory);
92465
92674
  if ((own2.mode & 63) !== 0 || process.getuid && own2.uid !== process.getuid())
92466
92675
  return fail();
92467
92676
  return { dev: own2.dev, ino: own2.ino };
@@ -92472,7 +92681,7 @@ function unchangedDirectory(directory, identity4) {
92472
92681
  return fail();
92473
92682
  }
92474
92683
  function readOwned(directory, name, max) {
92475
- const identity4 = safeDirectory(directory), file2 = join38(directory, name);
92684
+ const identity4 = safeDirectory(directory), file2 = join39(directory, name);
92476
92685
  const fd = openSync17(file2, constants13.O_RDONLY | constants13.O_NOFOLLOW);
92477
92686
  try {
92478
92687
  const stat2 = fstatSync17(fd);
@@ -92496,7 +92705,7 @@ function readOwned(directory, name, max) {
92496
92705
  }
92497
92706
  }
92498
92707
  function writeOwned(directory, name, bytes) {
92499
- const fd = openSync17(join38(directory, name), constants13.O_WRONLY | constants13.O_CREAT | constants13.O_EXCL | constants13.O_NOFOLLOW, 384);
92708
+ const fd = openSync17(join39(directory, name), constants13.O_WRONLY | constants13.O_CREAT | constants13.O_EXCL | constants13.O_NOFOLLOW, 384);
92500
92709
  try {
92501
92710
  writeFileSync10(fd, bytes);
92502
92711
  fsyncSync5(fd);
@@ -92509,7 +92718,7 @@ function save(directory, value) {
92509
92718
  writeOwned(directory, temporary, JSON.stringify(value) + `
92510
92719
  `);
92511
92720
  unchangedDirectory(directory, identity4);
92512
- renameSync6(join38(directory, temporary), join38(directory, "receipt.json"));
92721
+ renameSync6(join39(directory, temporary), join39(directory, "receipt.json"));
92513
92722
  const fd = openSync17(directory, constants13.O_RDONLY | constants13.O_NOFOLLOW);
92514
92723
  try {
92515
92724
  fsyncSync5(fd);
@@ -92522,7 +92731,7 @@ function bind(client2, receipt) {
92522
92731
  throw new PrivatePublicationError("PUBLICATION_IDENTITY_CHANGED", "The fresh session does not match the recovery directory's server, account and membership.");
92523
92732
  }
92524
92733
  async function locked(directory, action) {
92525
- const identity4 = safeDirectory(directory), file2 = join38(directory, "operation.lock");
92734
+ const identity4 = safeDirectory(directory), file2 = join39(directory, "operation.lock");
92526
92735
  let fd;
92527
92736
  try {
92528
92737
  fd = openSync17(file2, constants13.O_WRONLY | constants13.O_CREAT | constants13.O_EXCL | constants13.O_NOFOLLOW, 384);
@@ -92538,7 +92747,7 @@ async function locked(directory, action) {
92538
92747
  } finally {
92539
92748
  closeSync17(fd);
92540
92749
  unchangedDirectory(directory, identity4);
92541
- const now2 = lstatSync23(file2);
92750
+ const now2 = lstatSync24(file2);
92542
92751
  if (now2.dev !== lock.dev || now2.ino !== lock.ino || !now2.isFile() || now2.isSymbolicLink())
92543
92752
  fail();
92544
92753
  unlinkSync5(file2);
@@ -92590,7 +92799,7 @@ async function preparePrivatePublication(client2, sourceDirectory, recoveryDirec
92590
92799
  phase: "prepared",
92591
92800
  intent: null
92592
92801
  };
92593
- if (!isAbsolute20(recoveryDirectory) || resolve20(recoveryDirectory) !== recoveryDirectory || realpathSync12(dirname26(recoveryDirectory)) !== dirname26(recoveryDirectory))
92802
+ if (!isAbsolute20(recoveryDirectory) || resolve21(recoveryDirectory) !== recoveryDirectory || realpathSync13(dirname26(recoveryDirectory)) !== dirname26(recoveryDirectory))
92594
92803
  return fail();
92595
92804
  mkdirSync14(recoveryDirectory, { mode: 448 });
92596
92805
  safeDirectory(recoveryDirectory);