@hasna/skills 0.10.28 → 0.10.30

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.30",
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) {
@@ -39072,6 +39072,8 @@ var NATIVE_SKILL_ROOTS = [
39072
39072
  ["codex", ".codex/skills"],
39073
39073
  ["codex", ".agents/skills"],
39074
39074
  ["gemini", ".gemini/skills"],
39075
+ ["sumi", ".sumi/skills"],
39076
+ ["sumi", ".sumi/skill"],
39075
39077
  ["codewith", ".codewith/skills"],
39076
39078
  ["opencode", ".config/opencode/skills"],
39077
39079
  ["opencode", ".opencode/skills"],
@@ -39088,8 +39090,8 @@ var NATIVE_SKILL_ROOTS = [
39088
39090
  // src/lib/agent-integration.ts
39089
39091
  import { createHash as createHash18, randomUUID as randomUUID3 } from "crypto";
39090
39092
  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";
39093
+ 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";
39094
+ import { dirname as dirname15, join as join23, resolve as resolve16, relative as relative4, isAbsolute as isAbsolute17, sep as sep5 } from "path";
39093
39095
  import { homedir as homedir3 } from "os";
39094
39096
 
39095
39097
  // src/lib/managed-policy.ts
@@ -39368,8 +39370,8 @@ function isOwnedCliBridge(path, expectedPaths) {
39368
39370
 
39369
39371
  // src/lib/agent-discovery.ts
39370
39372
  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";
39373
+ import { lstatSync as lstatSync19, readFileSync as readFileSync13, readdirSync as readdirSync7, realpathSync as realpathSync7 } from "fs";
39374
+ import { basename as basename7, dirname as dirname14, isAbsolute as isAbsolute16, join as join22, resolve as resolve15, sep as sep4 } from "path";
39373
39375
  import { isDeepStrictEqual as isDeepStrictEqual4 } from "util";
39374
39376
 
39375
39377
  // node_modules/yaml/dist/index.js
@@ -41680,6 +41682,114 @@ function verifiesCodexHookDiscoverySource(binding, source, currentDigest, witnes
41680
41682
  return true;
41681
41683
  }
41682
41684
 
41685
+ // src/lib/agent-sumi.ts
41686
+ import { existsSync as existsSync6, lstatSync as lstatSync18, realpathSync as realpathSync6 } from "fs";
41687
+ import { join as join21, resolve as resolve14 } from "path";
41688
+ function sumiConfigDirectory(home, env = process.env) {
41689
+ for (const key of ["SUMI_CONFIG", "SUMI_CONFIG_CONTENT"])
41690
+ if (env[key] !== undefined)
41691
+ throw new Error(`Sumi ${key} requires a dedicated discovery adapter; unset it before Skills integration`);
41692
+ const selected = (key) => env[key]?.trim() ? env[key] : undefined;
41693
+ const expand = (value) => resolve14(value === "~" ? home : value.startsWith("~/") ? join21(home, value.slice(2)) : value);
41694
+ const explicit = selected("SUMI_CONFIG_DIR");
41695
+ const xdg = selected("XDG_CONFIG_HOME");
41696
+ const custom = selected("SUMI_HOME");
41697
+ const canonical6 = explicit ? expand(explicit) : xdg ? join21(expand(xdg), "sumi") : join21(custom ? expand(custom) : join21(home, ".hasna-internal/sumi"), "config");
41698
+ if (explicit || xdg || custom)
41699
+ return canonical6;
41700
+ const legacy = join21(home, ".config/sumi");
41701
+ const a = lstatSync18(canonical6, { throwIfNoEntry: false }), b = lstatSync18(legacy, { throwIfNoEntry: false });
41702
+ if (a && b && realpathSync6(canonical6) !== realpathSync6(legacy))
41703
+ throw new Error("Sumi config roots conflict; complete native home adoption before Skills integration");
41704
+ const path = a ? canonical6 : b ? legacy : canonical6;
41705
+ if (!existsSync6(path))
41706
+ return path;
41707
+ const physical = realpathSync6(path);
41708
+ if ((a?.isSymbolicLink() || b?.isSymbolicLink()) && ![canonical6, legacy].includes(physical))
41709
+ throw new Error("Sumi config alias must resolve to its canonical or legacy root");
41710
+ return physical;
41711
+ }
41712
+ function sumiBridgeRoot(home) {
41713
+ return join21(sumiConfigDirectory(home), "skills");
41714
+ }
41715
+ function sumiConfigPath(home) {
41716
+ return join21(sumiConfigDirectory(home), "sumi.json");
41717
+ }
41718
+ function renderSumiPlugin(command, profile) {
41719
+ return `// Managed by @hasna/skills. Regenerate with skills hook install --agent sumi.
41720
+ import { spawn } from "node:child_process";
41721
+ const command = ${JSON.stringify(command)};
41722
+ const profile = ${JSON.stringify(profile)};
41723
+ function context(input) {
41724
+ return new Promise((resolve, reject) => {
41725
+ const child = spawn(command, ["hook", "user-prompt", "--agent", "sumi", "--selection-profile", profile], { cwd: input.cwd, stdio: ["pipe", "pipe", "pipe"] });
41726
+ const chunks = []; let bytes = 0, failure;
41727
+ const timer = setTimeout(() => { failure = new Error("Skills prompt hook timed out"); child.kill("SIGKILL"); }, 15000);
41728
+ 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); });
41729
+ child.stderr.on("data", () => {});
41730
+ child.stdin.on("error", () => {});
41731
+ child.on("error", error => { clearTimeout(timer); reject(error); });
41732
+ child.on("close", code => {
41733
+ clearTimeout(timer);
41734
+ if (failure || code !== 0) return reject(failure ?? new Error("Skills prompt hook failed"));
41735
+ try {
41736
+ const result = JSON.parse(Buffer.concat(chunks).toString("utf8"));
41737
+ if (!result || typeof result !== "object" || Array.isArray(result)) throw new Error("Invalid Skills hook response");
41738
+ if (result.decision === "block" || result.continue === false) throw new Error("Skills prompt hook refused");
41739
+ if (Object.keys(result).length && (!result.hookSpecificOutput || result.hookSpecificOutput.hookEventName !== input.hook_event_name)) throw new Error("Invalid Skills hook response");
41740
+ const text = result.hookSpecificOutput?.additionalContext ?? "";
41741
+ if (typeof text !== "string") throw new Error("Invalid Skills prompt context");
41742
+ resolve(text);
41743
+ } catch (error) { reject(error); }
41744
+ });
41745
+ child.stdin.end(JSON.stringify(input));
41746
+ });
41747
+ }
41748
+ export default {
41749
+ id: "local.hasna-skills-cli",
41750
+ async setup(ctx) {
41751
+ if (!ctx?.session?.hook || !ctx?.session?.get || !ctx?.skill?.transform || !ctx?.tool?.hook) throw new Error("Unsupported Sumi native Skills contract");
41752
+ const registrations = [];
41753
+ const sessions = new Set();
41754
+ async function input(sessionID, prompt, first) {
41755
+ // The Promise adapter unwraps single-data endpoint responses.
41756
+ const session = await ctx.session.get({ sessionID });
41757
+ 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");
41758
+ 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 };
41759
+ }
41760
+ registrations.push(await ctx.skill.transform(editor => {
41761
+ for (const skill of editor.list()) if (skill.id !== "skills-cli" || skill.name !== "skills-cli") editor.remove(skill.id);
41762
+ }));
41763
+ // Native config transforms may add skills after this transform. Guard
41764
+ // both direct tool calls and prompt attachments at the consumption edge.
41765
+ registrations.push(await ctx.tool.hook("execute.before", event => {
41766
+ if (event.tool === "skill" && event.input?.id !== "skills-cli") throw new Error("Native Sumi skill payload refused; use Skills CLI");
41767
+ }));
41768
+ registrations.push(await ctx.session.hook("prompt", async event => {
41769
+ if (typeof event.prompt?.text !== "string") throw new Error("Invalid Sumi prompt");
41770
+ 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");
41771
+ await context(await input(event.sessionID, event.prompt.text, !sessions.has(event.sessionID)));
41772
+ sessions.add(event.sessionID);
41773
+ }));
41774
+ registrations.push(await ctx.session.hook("context", async event => {
41775
+ const last = event.messages.findLast(message => message.role === "user");
41776
+ const prompt = (last?.content ?? []).filter(part => part.type === "text").map(part => part.text).join("\\n");
41777
+ // Recheck on every primary request, including resumed and synthetic
41778
+ // sessions. The CLI owns optional failures versus explicit refusals.
41779
+ const text = await context(await input(event.sessionID, prompt, !sessions.has(event.sessionID)));
41780
+ if (text) event.system.push({ type: "text", text });
41781
+ sessions.add(event.sessionID);
41782
+ }));
41783
+ return async () => { for (const registration of registrations) await registration.dispose(); };
41784
+ },
41785
+ };
41786
+ `;
41787
+ }
41788
+ var SUMI_SKILL_PERMISSIONS = [
41789
+ { action: "skill", resource: "*", effect: "deny" },
41790
+ { action: "skill", resource: "skills-cli", effect: "allow" }
41791
+ ];
41792
+
41683
41793
  // src/lib/agent-discovery.ts
41684
41794
  var digest2 = (text2) => createHash17("sha256").update(text2).digest("hex");
41685
41795
  function parseConfig(text2, path, toml = false) {
@@ -41696,7 +41806,7 @@ function safe4(path) {
41696
41806
  if (!isAbsolute16(path) || path.includes("\x00"))
41697
41807
  throw new Error("Expected an absolute native discovery path");
41698
41808
  for (let cursor = path;; cursor = dirname14(cursor)) {
41699
- if (lstatSync18(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
41809
+ if (lstatSync19(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
41700
41810
  throw new Error(`Refusing symlink native discovery input: ${cursor}`);
41701
41811
  if (dirname14(cursor) === cursor)
41702
41812
  break;
@@ -41706,7 +41816,7 @@ function read2(path, changes) {
41706
41816
  safe4(path);
41707
41817
  if (changes?.has(path))
41708
41818
  return changes.get(path);
41709
- const stat2 = lstatSync18(path, { throwIfNoEntry: false });
41819
+ const stat2 = lstatSync19(path, { throwIfNoEntry: false });
41710
41820
  if (!stat2)
41711
41821
  return null;
41712
41822
  if (!stat2.isFile() || stat2.size > 16 * 1024 * 1024)
@@ -41817,12 +41927,12 @@ function codexInstallationRoots(binding) {
41817
41927
  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
41928
  throw new Error("Invalid native installation input proof");
41819
41929
  const cache = dirname14(dirname14(proof.plugins[0].pluginParent));
41820
- const config = join21(dirname14(dirname14(cache)), "config.toml"), home = dirname14(dirname14(dirname14(cache)));
41930
+ const config = join22(dirname14(dirname14(cache)), "config.toml"), home = dirname14(dirname14(dirname14(cache)));
41821
41931
  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));
41932
+ const nativeRoots = NATIVE_SKILL_ROOTS.filter(([agent]) => agent === "codex").map(([, path]) => join22(home, path));
41823
41933
  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
41934
  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)))
41935
+ 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
41936
  throw new Error("Missing native installation input source witness");
41827
41937
  return reviewedCodexPluginSourceRoots(cache, proof.plugins, (path) => {
41828
41938
  const text2 = read2(path);
@@ -41864,19 +41974,19 @@ function captureDiscoveryPathSources(paths) {
41864
41974
  const budget = discoveryByteBudget();
41865
41975
  return paths.map((path) => ({ path, hashMode: "path-bytes", sha256: hashDiscoveryPathFile(path, budget) }));
41866
41976
  }
41867
- function assertProjectDiscovery(agent, directories, home, canonical6 = resolve14, reviewed) {
41977
+ function assertProjectDiscovery(agent, directories, home, canonical6 = resolve15, reviewed) {
41868
41978
  const homeConfigPath = canonical6(agentDiscoveryConfigPath(home, agent));
41869
41979
  for (const directory of directories) {
41870
- const isHome = resolve14(directory) === resolve14(home);
41980
+ const isHome = resolve15(directory) === resolve15(home);
41871
41981
  if (agent === "hermes") {
41872
41982
  assertHermesEnvironment(home);
41873
41983
  continue;
41874
41984
  }
41875
- if (isHome && agent !== "claude")
41985
+ if (isHome && agent !== "claude" && agent !== "sumi")
41876
41986
  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"];
41987
+ 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
41988
  for (const suffix of paths) {
41879
- const path = canonical6(join21(directory, suffix)), raw = read2(path);
41989
+ const path = canonical6(join22(directory, suffix)), raw = read2(path);
41880
41990
  if (raw === null)
41881
41991
  continue;
41882
41992
  const isRootAliasedHomeConfig = agent === "claude" && suffix === ".claude/settings.json" || agent === "codex" && suffix === ".codex/config.toml";
@@ -41885,7 +41995,7 @@ function assertProjectDiscovery(agent, directories, home, canonical6 = resolve14
41885
41995
  if (suffix.endsWith(".jsonc"))
41886
41996
  throw new Error(`NATIVE_SKILL_DRIFT: project JSONC discovery configuration requires review: ${path}`);
41887
41997
  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"];
41998
+ 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
41999
  let admittedPlugins = false;
41890
42000
  if (agent === "claude" && reviewed?.agent === agent && reviewed.method === "reviewed" && config.enabledPlugins && typeof config.enabledPlugins === "object" && !Array.isArray(config.enabledPlugins)) {
41891
42001
  const exact = reviewed.sources.find((source) => source.path === path && source.format === undefined && source.fields === undefined && (source.hashMode === undefined || source.hashMode === "bytes"));
@@ -41898,19 +42008,28 @@ function assertProjectDiscovery(agent, directories, home, canonical6 = resolve14
41898
42008
  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
42009
  throw new Error(`NATIVE_SKILL_DRIFT: higher-precedence project skill or hook configuration requires review: ${path}`);
41900
42010
  }
42011
+ if (agent === "sumi")
42012
+ for (const name of ["plugin", "plugins"]) {
42013
+ const path = canonical6(join22(directory, ".sumi", name));
42014
+ safe4(path);
42015
+ if (lstatSync19(path, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(path).length)
42016
+ throw new Error(`NATIVE_SKILL_DRIFT: project Sumi plugins require a dedicated discovery review: ${path}`);
42017
+ }
41901
42018
  if (agent === "claude") {
41902
- const commands = canonical6(join21(directory, ".claude/commands"));
42019
+ const commands = canonical6(join22(directory, ".claude/commands"));
41903
42020
  safe4(commands);
41904
- if (lstatSync18(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length)
42021
+ if (lstatSync19(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length)
41905
42022
  throw new Error("NATIVE_SKILL_DRIFT: legacy project command discovery requires a dedicated format adapter");
41906
42023
  }
41907
42024
  }
41908
42025
  }
41909
42026
  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"}`);
42027
+ if (agent === "sumi")
42028
+ return sumiConfigPath(home);
42029
+ 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
42030
  }
41912
42031
  function resolveAgentDiscovery(options) {
41913
- const canonical6 = options.canonical ?? resolve14, home = resolve14(options.home), agent = options.agent;
42032
+ const canonical6 = options.canonical ?? resolve15, home = resolve15(options.home), agent = options.agent;
41914
42033
  const sources = [], roots = new Set, builtinNames = [];
41915
42034
  const witness = (path, format, fields2) => {
41916
42035
  const source = { path: canonical6(path), sha256: null, ...format ? { format, fields: fields2 } : {} };
@@ -41921,13 +42040,49 @@ function resolveAgentDiscovery(options) {
41921
42040
  if (agent === "hermes")
41922
42041
  assertHermesEnvironment(home);
41923
42042
  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"]);
42043
+ 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
42044
  const config = configText === null ? {} : agent === "hermes" ? parseHermesConfig(configText) : parseConfig(configText, configPath, agent === "codex");
41926
42045
  const unresolved = (detail) => {
41927
42046
  throw new Error(`Native discovery is unresolved (${agent}: ${detail}); provide a reviewed --discovery-inputs file`);
41928
42047
  };
42048
+ if (agent === "sumi") {
42049
+ const directory = sumiConfigDirectory(home);
42050
+ if (witness(join22(directory, "sumi.jsonc")) !== null)
42051
+ unresolved("JSONC configuration requires a supported format adapter");
42052
+ for (const root2 of [directory, join22(home, ".claude"), join22(home, ".agents")])
42053
+ for (const name of ["skill", "skills"])
42054
+ roots.add(join22(root2, name));
42055
+ if (config.skills !== undefined && (!Array.isArray(config.skills) || config.skills.some((path) => typeof path !== "string")))
42056
+ unresolved("skills must be a string array");
42057
+ for (const value of config.skills ?? []) {
42058
+ if (typeof value !== "string" || /[\0$]/.test(value) || !value || !(isAbsolute16(value) || value.startsWith("~/")))
42059
+ unresolved("remote or relative skill sources need a dedicated discovery adapter");
42060
+ roots.add(value.startsWith("~/") ? join22(home, value.slice(2)) : value);
42061
+ }
42062
+ for (const key of ["plugin", "plugins"])
42063
+ if (config[key] !== undefined && !Array.isArray(config[key]))
42064
+ unresolved(`${key} must be an array`);
42065
+ const plugins = [join22(directory, "plugin"), join22(directory, "plugins")];
42066
+ for (const path of plugins) {
42067
+ safe4(path);
42068
+ if (lstatSync19(path, { throwIfNoEntry: false })?.isDirectory())
42069
+ for (const name of readdirSync7(path).sort()) {
42070
+ if (name === "skills-cli.js" && path === plugins[1])
42071
+ continue;
42072
+ const target = join22(path, name);
42073
+ if (!lstatSync19(target).isFile())
42074
+ unresolved("local plugin packages need a dedicated discovery adapter");
42075
+ witness(target);
42076
+ }
42077
+ }
42078
+ for (const root2 of roots) {
42079
+ safe4(root2);
42080
+ if (lstatSync19(root2, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(root2).some((name) => name.endsWith(".md")))
42081
+ unresolved("flat markdown skills require a dedicated native migration adapter");
42082
+ }
42083
+ }
41929
42084
  if (agent === "hermes") {
41930
- const profile = witness(join21(home, ".hermes/active_profile"));
42085
+ const profile = witness(join22(home, ".hermes/active_profile"));
41931
42086
  if (profile?.trim() && profile.trim() !== "default")
41932
42087
  unresolved("a non-default profile is active");
41933
42088
  const declared = config.skills?.external_dirs ?? [], paths = typeof declared === "string" ? [declared] : declared;
@@ -41941,7 +42096,7 @@ function resolveAgentDiscovery(options) {
41941
42096
  continue;
41942
42097
  if (normalized.startsWith("~") && normalized !== "~" && !normalized.startsWith("~/"))
41943
42098
  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);
42099
+ const path = normalized === "~" ? home : normalized.startsWith("~/") ? join22(home, normalized.slice(2)) : resolve15(home, ".hermes", normalized);
41945
42100
  safe4(path);
41946
42101
  roots.add(path);
41947
42102
  }
@@ -41950,8 +42105,8 @@ function resolveAgentDiscovery(options) {
41950
42105
  const executable = Bun.which("gemini");
41951
42106
  if (executable) {
41952
42107
  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);
42108
+ for (let directory = dirname14(realpathSync7(executable)), depth = 0;depth < 8; directory = dirname14(directory), depth++) {
42109
+ const path = join22(directory, "package.json"), raw = read2(path);
41955
42110
  if (raw !== null && parseConfig(raw, path).name === "@google/gemini-cli") {
41956
42111
  packageRoot = directory;
41957
42112
  witness(path);
@@ -41962,12 +42117,12 @@ function resolveAgentDiscovery(options) {
41962
42117
  }
41963
42118
  if (!packageRoot)
41964
42119
  unresolved("installed Gemini package layout is not recognized");
41965
- const builtinRoot = join21(packageRoot, "bundle/builtin");
42120
+ const builtinRoot = join22(packageRoot, "bundle/builtin");
41966
42121
  safe4(builtinRoot);
41967
- if (!lstatSync18(builtinRoot, { throwIfNoEntry: false })?.isDirectory())
42122
+ if (!lstatSync19(builtinRoot, { throwIfNoEntry: false })?.isDirectory())
41968
42123
  unresolved("installed Gemini builtin root is missing");
41969
42124
  for (const name of readdirSync7(builtinRoot).sort()) {
41970
- const text2 = witness(join21(builtinRoot, name, "SKILL.md"));
42125
+ const text2 = witness(join22(builtinRoot, name, "SKILL.md"));
41971
42126
  const match = text2?.match(/^---\r?\n[\s\S]*?^name:\s*([a-z0-9][a-z0-9-]*)\s*$/m);
41972
42127
  if (!match?.[1] || builtinNames.includes(match[1]))
41973
42128
  unresolved("installed Gemini builtin name is missing or ambiguous");
@@ -42009,39 +42164,39 @@ function resolveAgentDiscovery(options) {
42009
42164
  function plugin(root2) {
42010
42165
  root2 = canonical6(root2);
42011
42166
  safe4(root2);
42012
- const manifestPath = join21(root2, agent === "claude" ? ".claude-plugin/plugin.json" : ".codex-plugin/plugin.json");
42167
+ const manifestPath = join22(root2, agent === "claude" ? ".claude-plugin/plugin.json" : ".codex-plugin/plugin.json");
42013
42168
  const raw = witness(manifestPath);
42014
42169
  if (raw === null)
42015
42170
  unresolved("plugin manifest missing");
42016
42171
  const manifest = parseConfig(raw, manifestPath);
42017
- const hooks = witness(join21(root2, "hooks/hooks.json"));
42172
+ const hooks = witness(join22(root2, "hooks/hooks.json"));
42018
42173
  if (manifest.hooks !== undefined || hooks !== null)
42019
42174
  unresolved("plugin hooks require a separate no-skill-injection review");
42020
- const commands = join21(root2, "commands");
42175
+ const commands = join22(root2, "commands");
42021
42176
  safe4(commands);
42022
- if (agent === "claude" && (manifest.commands !== undefined || lstatSync18(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length))
42177
+ if (agent === "claude" && (manifest.commands !== undefined || lstatSync19(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length))
42023
42178
  unresolved("legacy command discovery requires retirement or a dedicated format adapter");
42024
- const rootSkill = witness(join21(root2, "SKILL.md"));
42179
+ const rootSkill = witness(join22(root2, "SKILL.md"));
42025
42180
  if (rootSkill !== null)
42026
42181
  roots.add(root2);
42027
42182
  const declared = manifest.skills === undefined ? ["./skills"] : typeof manifest.skills === "string" ? [manifest.skills] : manifest.skills;
42028
42183
  if (!Array.isArray(declared) || declared.some((path) => typeof path !== "string"))
42029
42184
  unresolved("unsupported plugin skill paths");
42030
42185
  if (agent === "claude")
42031
- roots.add(join21(root2, "skills"));
42186
+ roots.add(join22(root2, "skills"));
42032
42187
  for (const value of declared) {
42033
- const path = resolve14(root2, value);
42188
+ const path = resolve15(root2, value);
42034
42189
  if (path !== root2 && !path.startsWith(root2 + sep4))
42035
42190
  unresolved("plugin skill path escapes its root");
42036
42191
  roots.add(path.endsWith(`${sep4}SKILL.md`) ? dirname14(path) : path);
42037
42192
  }
42038
42193
  }
42039
42194
  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"));
42195
+ const registrations = witness(join22(home, ".claude/plugins/installed_plugins.json"));
42196
+ const installed = registrations === null ? {} : parseConfig(registrations, join22(home, ".claude/plugins/installed_plugins.json")).plugins;
42197
+ const commands = canonical6(join22(home, ".claude/commands"));
42043
42198
  safe4(commands);
42044
- if (lstatSync18(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length)
42199
+ if (lstatSync19(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length)
42045
42200
  unresolved("legacy home command discovery requires a dedicated format adapter");
42046
42201
  for (const [id2, enabled] of Object.entries(config.enabledPlugins ?? {})) {
42047
42202
  if (enabled === false)
@@ -42063,16 +42218,16 @@ function resolveAgentDiscovery(options) {
42063
42218
  const market = config.marketplaces?.[marketplace] ?? (marketplace === "personal" ? { source_type: "local", source: home } : undefined);
42064
42219
  if (split < 1 || market?.source_type !== "local" || typeof market.source !== "string" || !isAbsolute16(market.source))
42065
42220
  unresolved("enabled plugin marketplace is not an explicit local source");
42066
- const catalogText = witness(join21(market.source, ".agents/plugins/marketplace.json"));
42221
+ const catalogText = witness(join22(market.source, ".agents/plugins/marketplace.json"));
42067
42222
  if (catalogText === null)
42068
42223
  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) : [];
42224
+ const catalog = parseConfig(catalogText, join22(market.source, ".agents/plugins/marketplace.json")), matches = Array.isArray(catalog.plugins) ? catalog.plugins.filter((item) => item.name === name) : [];
42070
42225
  if (matches.length !== 1 || matches[0]?.source?.source !== "local" || typeof matches[0]?.source?.path !== "string")
42071
42226
  unresolved("plugin catalog source is missing or ambiguous");
42072
- plugin(resolve14(market.source, matches[0].source.path));
42227
+ plugin(resolve15(market.source, matches[0].source.path));
42073
42228
  }
42074
42229
  } else if (agent === "opencode") {
42075
- if (witness(join21(home, ".config/opencode/opencode.jsonc")) !== null || witness(join21(home, ".config/opencode/config.json")) !== null)
42230
+ if (witness(join22(home, ".config/opencode/opencode.jsonc")) !== null || witness(join22(home, ".config/opencode/config.json")) !== null)
42076
42231
  unresolved("additional config layers require review");
42077
42232
  if ((config.plugin?.length ?? 0) > 0 || config.skills?.urls?.length)
42078
42233
  unresolved("external plugin or remote skill source");
@@ -42081,14 +42236,17 @@ function resolveAgentDiscovery(options) {
42081
42236
  unresolved("relative or malformed added skill root");
42082
42237
  roots.add(path);
42083
42238
  }
42084
- const localPlugins = join21(home, ".config/opencode/plugins");
42239
+ const localPlugins = join22(home, ".config/opencode/plugins");
42085
42240
  safe4(localPlugins);
42086
- if (lstatSync18(localPlugins, { throwIfNoEntry: false }) && readdirSync7(localPlugins).some((name) => name !== "skills-cli.js"))
42241
+ if (lstatSync19(localPlugins, { throwIfNoEntry: false }) && readdirSync7(localPlugins).some((name) => name !== "skills-cli.js"))
42087
42242
  unresolved("additional local plugin hooks require review");
42243
+ } else if (agent === "sumi") {
42244
+ 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))
42245
+ unresolved("external or foreign local plugins require review");
42088
42246
  } else if (agent === "hermes") {
42089
- for (const directory of [join21(home, ".hermes/plugins"), join21(home, ".hermes/hermes-agent")]) {
42247
+ for (const directory of [join22(home, ".hermes/plugins"), join22(home, ".hermes/hermes-agent")]) {
42090
42248
  safe4(directory);
42091
- if (lstatSync18(directory, { throwIfNoEntry: false }))
42249
+ if (lstatSync19(directory, { throwIfNoEntry: false }))
42092
42250
  unresolved("installed runtime/plugin discovery requires reviewed source bindings");
42093
42251
  }
42094
42252
  if (Bun.which("hermes") || Object.keys(config.plugins ?? {}).length)
@@ -42096,28 +42254,28 @@ function resolveAgentDiscovery(options) {
42096
42254
  } else if (agent === "gemini") {
42097
42255
  if (Object.keys(config.extensions ?? {}).length || config.skills?.paths?.length)
42098
42256
  unresolved("custom extension or skill paths");
42099
- const directory = join21(home, ".gemini/extensions");
42257
+ const directory = join22(home, ".gemini/extensions");
42100
42258
  safe4(directory);
42101
- if (lstatSync18(directory, { throwIfNoEntry: false }))
42259
+ if (lstatSync19(directory, { throwIfNoEntry: false }))
42102
42260
  for (const name of readdirSync7(directory)) {
42103
- const root2 = join21(directory, name);
42261
+ const root2 = join22(directory, name);
42104
42262
  safe4(root2);
42105
- if (!lstatSync18(root2)?.isDirectory())
42263
+ if (!lstatSync19(root2)?.isDirectory())
42106
42264
  continue;
42107
- const raw = witness(join21(root2, "gemini-extension.json"));
42265
+ const raw = witness(join22(root2, "gemini-extension.json"));
42108
42266
  if (raw === null)
42109
42267
  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)
42268
+ const manifest = parseConfig(raw, join22(root2, "gemini-extension.json"));
42269
+ if (manifest.hooks !== undefined || witness(join22(root2, "hooks/hooks.json")) !== null || witness(join22(root2, ".gemini-extension-install.json")) !== null)
42112
42270
  unresolved("extension hooks or linked registration require review");
42113
- roots.add(join21(root2, "skills"));
42271
+ roots.add(join22(root2, "skills"));
42114
42272
  }
42115
42273
  }
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))) } : {} };
42274
+ 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
42275
  }
42118
42276
 
42119
42277
  // src/lib/agent-adapters.ts
42120
- var INTEGRATION_AGENTS = ["claude", "codex", "gemini", "opencode", "cursor", "hermes"];
42278
+ var INTEGRATION_AGENTS = ["claude", "codex", "gemini", "opencode", "cursor", "hermes", "sumi"];
42121
42279
  function renderAgentHookCommand(command, agent, profileId, event) {
42122
42280
  if (typeof profileId !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(profileId) || profileId.includes(".."))
42123
42281
  throw new Error("Invalid selection profile id");
@@ -42128,6 +42286,7 @@ var AGENT_ADAPTERS = {
42128
42286
  codex: { root: ".codex/skills", config: ".codex/hooks.json", events: ["UserPromptSubmit", "SessionStart", "SubagentStart"], promptContext: true },
42129
42287
  gemini: { root: ".gemini/skills", config: ".gemini/settings.json", events: ["BeforeAgent", "SessionStart"], promptContext: true },
42130
42288
  opencode: { root: ".config/opencode/skills", config: ".config/opencode/opencode.json", events: ["chat.message"], promptContext: true },
42289
+ sumi: { root: ".hasna-internal/sumi/config/skills", config: ".hasna-internal/sumi/config/sumi.json", events: ["prompt", "context"], promptContext: true },
42131
42290
  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
42291
  cursor: { root: ".cursor/skills", config: ".cursor/hooks.json", events: ["beforeSubmitPrompt", "sessionStart"], promptContext: false }
42133
42292
  };
@@ -42484,11 +42643,11 @@ function isSystemRootAlias(path) {
42484
42643
  const target = `/private${path}`, link = `private${path}`;
42485
42644
  const identity4 = (stat2) => `${stat2.dev}:${stat2.ino}:${stat2.ctimeNs}:${stat2.uid}:${stat2.mode}`;
42486
42645
  try {
42487
- const before = lstatSync19(path, { bigint: true });
42646
+ const before = lstatSync20(path, { bigint: true });
42488
42647
  if (!before.isSymbolicLink() || before.uid !== 0n || readlinkSync4(path) !== link)
42489
42648
  return false;
42490
42649
  const directories = ["/", "/private", target].map((directory) => {
42491
- const stat2 = lstatSync19(directory, { bigint: true });
42650
+ const stat2 = lstatSync20(directory, { bigint: true });
42492
42651
  if (!stat2.isDirectory() || stat2.uid !== 0n)
42493
42652
  throw new Error("Untrusted system alias directory");
42494
42653
  if (directory !== "/private/tmp") {
@@ -42505,23 +42664,23 @@ function isSystemRootAlias(path) {
42505
42664
  }
42506
42665
  return { directory, identity: identity4(stat2) };
42507
42666
  });
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);
42667
+ 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
42668
  } catch {
42510
42669
  return false;
42511
42670
  }
42512
42671
  }
42513
42672
  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())
42673
+ const absolute = resolve16(path), root2 = `/${absolute.split(sep5)[1]}`;
42674
+ if (process.platform !== "darwin" || !["/var", "/tmp", "/etc"].includes(root2) || !lstatSync20(root2, { throwIfNoEntry: false })?.isSymbolicLink())
42516
42675
  return absolute;
42517
42676
  if (!isSystemRootAlias(root2))
42518
42677
  throw new Error(`Refusing symlink path: ${root2}`);
42519
42678
  return `/private${absolute}`;
42520
42679
  }
42521
42680
  function assertSafePath(path) {
42522
- let cursor = resolve15(path);
42681
+ let cursor = resolve16(path);
42523
42682
  while (true) {
42524
- if (lstatSync19(cursor, { throwIfNoEntry: false })?.isSymbolicLink() && !isSystemRootAlias(cursor))
42683
+ if (lstatSync20(cursor, { throwIfNoEntry: false })?.isSymbolicLink() && !isSystemRootAlias(cursor))
42525
42684
  throw new Error(`Refusing symlink path: ${cursor}`);
42526
42685
  const parent = dirname15(cursor);
42527
42686
  if (parent === cursor)
@@ -42531,16 +42690,16 @@ function assertSafePath(path) {
42531
42690
  }
42532
42691
  function readRootAlias(home, agent) {
42533
42692
  assertSafePath(home);
42534
- const realHome = realpathSync7(home), alias = join22(realHome, `.${agent}`);
42535
- const stat2 = lstatSync19(alias, { throwIfNoEntry: false, bigint: true });
42693
+ const realHome = realpathSync8(home), alias = join23(realHome, `.${agent}`);
42694
+ const stat2 = lstatSync20(alias, { throwIfNoEntry: false, bigint: true });
42536
42695
  if (!stat2?.isSymbolicLink())
42537
42696
  throw new Error(`Agent root alias changed after planning: ${alias}`);
42538
- const link = readlinkSync4(alias), targetPath = resolve15(dirname15(alias), link);
42697
+ const link = readlinkSync4(alias), targetPath = resolve16(dirname15(alias), link);
42539
42698
  assertSafePath(targetPath);
42540
- const targetStat = lstatSync19(targetPath, { throwIfNoEntry: false });
42699
+ const targetStat = lstatSync20(targetPath, { throwIfNoEntry: false });
42541
42700
  if (!targetStat?.isDirectory())
42542
42701
  throw new Error(`Agent root alias must target an existing directory: ${alias}`);
42543
- const target = realpathSync7(targetPath), inside = relative4(realHome, target);
42702
+ const target = realpathSync8(targetPath), inside = relative4(realHome, target);
42544
42703
  if (!inside || inside === ".." || inside.startsWith(`..${sep5}`) || isAbsolute17(inside))
42545
42704
  throw new Error(`Agent root alias target must be inside the real home: ${alias}`);
42546
42705
  return { agent, home: realHome, alias, target, link, aliasIdentity: `${stat2.dev}:${stat2.ino}:${stat2.ctimeNs}`, targetIdentity: `${targetStat.dev}:${targetStat.ino}` };
@@ -42550,7 +42709,7 @@ function rootAliases(home, allowed = false) {
42550
42709
  return [];
42551
42710
  const result = [];
42552
42711
  for (const agent of ["claude", "codex"])
42553
- if (lstatSync19(join22(home, `.${agent}`), { throwIfNoEntry: false })?.isSymbolicLink())
42712
+ if (lstatSync20(join23(home, `.${agent}`), { throwIfNoEntry: false })?.isSymbolicLink())
42554
42713
  result.push(readRootAlias(home, agent));
42555
42714
  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
42715
  throw new Error("Agent root alias targets must not overlap");
@@ -42558,7 +42717,7 @@ function rootAliases(home, allowed = false) {
42558
42717
  }
42559
42718
  function canonicalAgentPath(path, aliases) {
42560
42719
  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;
42720
+ return binding ? join23(binding.target, relative4(binding.alias, absolute)) : absolute;
42562
42721
  }
42563
42722
  function disabledCodexSkillPaths(config, aliases) {
42564
42723
  const skills = config.skills;
@@ -42577,7 +42736,7 @@ function disabledCodexSkillPaths(config, aliases) {
42577
42736
  continue;
42578
42737
  let document2;
42579
42738
  try {
42580
- document2 = realpathSync7(canonicalAgentPath(entry.path, aliases));
42739
+ document2 = realpathSync8(canonicalAgentPath(entry.path, aliases));
42581
42740
  } catch {
42582
42741
  continue;
42583
42742
  }
@@ -42589,7 +42748,7 @@ function disabledCodexSkillPaths(config, aliases) {
42589
42748
  }
42590
42749
  function recheckRootAliases(aliases) {
42591
42750
  for (const binding of aliases) {
42592
- if (!["claude", "codex"].includes(binding.agent) || binding.alias !== join22(binding.home, `.${binding.agent}`))
42751
+ if (!["claude", "codex"].includes(binding.agent) || binding.alias !== join23(binding.home, `.${binding.agent}`))
42593
42752
  throw new Error("Invalid agent root alias binding");
42594
42753
  const current = readRootAlias(binding.home, binding.agent);
42595
42754
  if (JSON.stringify(current) !== JSON.stringify(binding))
@@ -42598,7 +42757,7 @@ function recheckRootAliases(aliases) {
42598
42757
  }
42599
42758
  function readNativeBytes(path, maximum = 64 * 1024 * 1024) {
42600
42759
  assertSafePath(path);
42601
- const before = lstatSync19(path);
42760
+ const before = lstatSync20(path);
42602
42761
  if (!before.isFile() || before.size > maximum)
42603
42762
  throw new Error("Unsupported or oversized native skill file");
42604
42763
  const descriptor = openSync16(path, constants12.O_RDONLY | constants12.O_NOFOLLOW | constants12.O_NONBLOCK);
@@ -42614,7 +42773,7 @@ function readNativeBytes(path, maximum = 64 * 1024 * 1024) {
42614
42773
  break;
42615
42774
  length += count;
42616
42775
  }
42617
- const after = fstatSync16(descriptor), current = lstatSync19(path);
42776
+ const after = fstatSync16(descriptor), current = lstatSync20(path);
42618
42777
  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
42778
  throw new Error("Native skill file changed while reading");
42620
42779
  return bytes.subarray(0, length);
@@ -42626,14 +42785,14 @@ function treeHash(root2) {
42626
42785
  const hash2 = createHash18("sha256");
42627
42786
  let bytes = 0, files = 0;
42628
42787
  function visit2(path) {
42629
- const stat2 = lstatSync19(path);
42788
+ const stat2 = lstatSync20(path);
42630
42789
  if (stat2.isSymbolicLink())
42631
42790
  throw new Error(`Refusing symlink in skill: ${path}`);
42632
42791
  const rel = relative4(root2, path);
42633
42792
  if (stat2.isDirectory()) {
42634
42793
  hash2.update(`d\x00${rel}\x00`);
42635
42794
  for (const name of readdirSync8(path).sort())
42636
- visit2(join22(path, name));
42795
+ visit2(join23(path, name));
42637
42796
  return;
42638
42797
  }
42639
42798
  if (!stat2.isFile())
@@ -42655,10 +42814,10 @@ function selectNativeMigrationTargets(inventory, manifest) {
42655
42814
  const identities = new Set;
42656
42815
  const selected = [];
42657
42816
  for (const target of manifest.targets) {
42658
- if (!isAbsolute17(target.projectRoot) || resolve15(target.projectRoot) !== target.projectRoot)
42817
+ if (!isAbsolute17(target.projectRoot) || resolve16(target.projectRoot) !== target.projectRoot)
42659
42818
  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())
42819
+ const projectRoot = canonicalSystemPath(target.projectRoot), normalized = relative4(projectRoot, resolve16(projectRoot, target.path));
42820
+ if (!existsSync7(projectRoot) || !lstatSync20(projectRoot).isDirectory())
42662
42821
  throw new Error(`Native migration target project root must be an existing absolute directory: ${target.projectRoot}`);
42663
42822
  assertSafePath(projectRoot);
42664
42823
  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 +42826,8 @@ function selectNativeMigrationTargets(inventory, manifest) {
42667
42826
  if (identities.has(identity4))
42668
42827
  throw new Error(`Duplicate native migration target: ${target.path}`);
42669
42828
  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);
42829
+ const expected = canonicalSystemPath(resolve16(target.projectRoot, target.path));
42830
+ const matches = inventory.filter((entry2) => entry2.agent === target.agent && resolve16(entry2.path) === expected);
42672
42831
  if (matches.length !== 1)
42673
42832
  throw new Error(`Native migration target was not found exactly once: ${target.agent} ${target.projectRoot}/${target.path}`);
42674
42833
  const entry = matches[0];
@@ -42697,9 +42856,9 @@ function projectAncestorDirectories(projects) {
42697
42856
  }
42698
42857
  function inventoryNativeSkills(home = homedir3(), options = {}) {
42699
42858
  home = canonicalSystemPath(home);
42700
- if (options.reviewedCacheAlias !== undefined && (!options.includeVendor || !isAbsolute17(options.reviewedCacheAlias) || resolve15(options.reviewedCacheAlias) !== options.reviewedCacheAlias))
42859
+ if (options.reviewedCacheAlias !== undefined && (!options.includeVendor || !isAbsolute17(options.reviewedCacheAlias) || resolve16(options.reviewedCacheAlias) !== options.reviewedCacheAlias))
42701
42860
  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))
42861
+ if (options.disabledVendorPaths?.some((path) => !isAbsolute17(path) || resolve16(path) !== path))
42703
42862
  throw new Error("Disabled vendor paths must be exact absolute paths");
42704
42863
  const reviewedCacheAlias = options.reviewedCacheAlias === undefined ? undefined : canonicalSystemPath(options.reviewedCacheAlias);
42705
42864
  const disabledVendorPaths = new Set((options.disabledVendorPaths ?? []).map(canonicalSystemPath));
@@ -42707,14 +42866,18 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
42707
42866
  const selectedAgents = options.agents ? new Set(options.agents) : undefined;
42708
42867
  const includesAgent = (agent) => !selectedAgents || selectedAgents.has(agent);
42709
42868
  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));
42869
+ const roots = rootDefinitions.map(([agent, path]) => [agent, canonicalAgentPath(join23(home, path), aliases)]);
42870
+ 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
42871
  for (const project of projectAncestorDirectories([...options.projectDirs ?? [], ...options.projectDir ? [options.projectDir] : []])) {
42713
42872
  for (const [agent, path] of rootDefinitions)
42714
- roots.push([agent, canonicalAgentPath(join22(project, path), aliases)]);
42873
+ roots.push([agent, canonicalAgentPath(join23(project, path), aliases)]);
42874
+ if (selectedAgents?.has("sumi"))
42875
+ for (const directory of [".claude", ".agents"])
42876
+ for (const name of ["skill", "skills"])
42877
+ roots.push(["sumi", canonicalAgentPath(join23(project, directory, name), aliases)]);
42715
42878
  }
42716
42879
  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)))))
42880
+ 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
42881
  throw new Error("Native installation input overlaps an unconditional skill-loading root");
42719
42882
  const entries = [], seen = new Set;
42720
42883
  const cacheScans = new Map, maxAliasProofEntries = 1e4;
@@ -42728,13 +42891,13 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
42728
42891
  }
42729
42892
  let reviewedCacheAliasFound = false;
42730
42893
  function verifiedSiblingCacheAlias(agent, path, parent) {
42731
- const link = readlinkSync4(path), lexicalTarget = resolve15(parent, link);
42894
+ const link = readlinkSync4(path), lexicalTarget = resolve16(parent, link);
42732
42895
  if (isAbsolute17(link) ? link !== lexicalTarget : dirname15(link) !== ".")
42733
42896
  return false;
42734
42897
  const target = canonicalSystemPath(lexicalTarget);
42735
42898
  if (dirname15(target) !== parent)
42736
42899
  return false;
42737
- if (!lstatSync19(target, { throwIfNoEntry: false })?.isDirectory())
42900
+ if (!lstatSync20(target, { throwIfNoEntry: false })?.isDirectory())
42738
42901
  return false;
42739
42902
  const scan = cacheScans.get(target);
42740
42903
  if (!scan?.complete || scan.entries > maxAliasProofEntries)
@@ -42757,37 +42920,40 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
42757
42920
  assertSafePath(path);
42758
42921
  if (configuredRoot && agent === "codex" && installationInputs.some((root2) => path === root2 || path.startsWith(`${root2}${sep5}`)))
42759
42922
  return scan;
42760
- if (!existsSync6(path))
42923
+ if (!existsSync7(path))
42761
42924
  return scan;
42762
- const stat2 = lstatSync19(path);
42763
- if (stat2.isFile())
42925
+ const stat2 = lstatSync20(path);
42926
+ if (stat2.isFile()) {
42927
+ if (agent === "sumi" && depth === 1 && path.endsWith(".md"))
42928
+ throw new Error("NATIVE_SKILL_DRIFT: flat Sumi skill documents require a dedicated migration adapter");
42764
42929
  return scan;
42930
+ }
42765
42931
  if (!stat2.isDirectory())
42766
42932
  throw new Error(`Unsupported native discovery entry: ${path}`);
42767
- if (existsSync6(join22(path, "SKILL.md"))) {
42933
+ if (existsSync7(join23(path, "SKILL.md"))) {
42768
42934
  scan.hasSkills = true;
42769
42935
  if (seen.has(path))
42770
42936
  return scan;
42771
42937
  seen.add(path);
42772
42938
  let managed = false;
42773
- const marker = join22(path, ".hasna-skills.json");
42774
- if (existsSync6(marker)) {
42939
+ const marker = join23(path, ".hasna-skills.json");
42940
+ if (existsSync7(marker)) {
42775
42941
  try {
42776
42942
  managed = JSON.parse(readFileSync14(marker, "utf8")).managedBy === "@hasna/skills";
42777
42943
  } catch {}
42778
42944
  }
42779
- const bridge = !vendor && isOwnedCliBridge(path, bridgePaths);
42945
+ const bridge = (!vendor || agent === "sumi") && isOwnedCliBridge(path, bridgePaths);
42780
42946
  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 } : {} });
42947
+ 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
42948
  return scan;
42783
42949
  }
42784
- if (depth > (vendor ? 32 : 3))
42950
+ if (depth > (agent === "sumi" ? 32 : vendor ? 32 : 3))
42785
42951
  return { ...scan, complete: false };
42786
42952
  const children = [], directory = opendirSync5(path);
42787
42953
  try {
42788
42954
  let child;
42789
42955
  while ((child = directory.readSync()) !== null) {
42790
- admit(join22(path, child.name));
42956
+ admit(join23(path, child.name));
42791
42957
  children.push(child);
42792
42958
  }
42793
42959
  } finally {
@@ -42799,13 +42965,13 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
42799
42965
  for (const { name } of children) {
42800
42966
  if (name === "node_modules")
42801
42967
  continue;
42802
- if (name.startsWith(".") && name !== ".system" && agent !== "hermes" && !(options.guardHermes && `${path}${sep5}`.includes(`${sep5}.agents${sep5}skills${sep5}`)))
42968
+ if (name.startsWith(".") && name !== ".system" && agent !== "hermes" && agent !== "sumi" && !(options.guardHermes && `${path}${sep5}`.includes(`${sep5}.agents${sep5}skills${sep5}`)))
42803
42969
  continue;
42804
42970
  const isVendor = vendor || name === ".system";
42805
42971
  if (isVendor && !options.includeVendor)
42806
42972
  continue;
42807
- const child = join22(path, name);
42808
- if (isVendor && lstatSync19(child, { throwIfNoEntry: false })?.isSymbolicLink()) {
42973
+ const child = join23(path, name);
42974
+ if (isVendor && lstatSync20(child, { throwIfNoEntry: false })?.isSymbolicLink()) {
42809
42975
  const target = statSync6(child, { throwIfNoEntry: false });
42810
42976
  if (target?.isFile() || pluginCache && target?.isDirectory() && verifiedSiblingCacheAlias(agent, child, path)) {
42811
42977
  scan.entries++;
@@ -42831,11 +42997,11 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
42831
42997
  scanRoot(agent, path);
42832
42998
  if (options.includeVendor) {
42833
42999
  for (const agent of ["codex", "claude"].filter(includesAgent))
42834
- scanRoot(agent, canonicalAgentPath(join22(home, `.${agent}`, "plugins", "cache"), aliases), true, true);
43000
+ scanRoot(agent, canonicalAgentPath(join23(home, `.${agent}`, "plugins", "cache"), aliases), true, true);
42835
43001
  if (includesAgent("claude"))
42836
- scanRoot("claude", canonicalAgentPath(join22(home, ".claude", "plugins", "synced"), aliases), true);
43002
+ scanRoot("claude", canonicalAgentPath(join23(home, ".claude", "plugins", "synced"), aliases), true);
42837
43003
  if (includesAgent("gemini"))
42838
- scanRoot("gemini", join22(home, ".gemini", "extensions"), true);
43004
+ scanRoot("gemini", join23(home, ".gemini", "extensions"), true);
42839
43005
  }
42840
43006
  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
43007
  for (const root2 of [...options.agentRoots ?? [], ...configured])
@@ -42848,7 +43014,7 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
42848
43014
  }
42849
43015
  function readOptional(path) {
42850
43016
  assertSafePath(path);
42851
- return existsSync6(path) ? readFileSync14(path, "utf8") : null;
43017
+ return existsSync7(path) ? readFileSync14(path, "utf8") : null;
42852
43018
  }
42853
43019
  function jsonObject(text2, path) {
42854
43020
  if (text2 === null)
@@ -42948,19 +43114,19 @@ function configureHooks(config, agent, command, profileId, nativeReady) {
42948
43114
  function disableCodexSkills(text2, skills, aliases, bridgePath) {
42949
43115
  const bundled = disableCodexBundledSkills(text2);
42950
43116
  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));
43117
+ 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
43118
  const previousConfig = Bun.TOML.parse(bundled).skills?.config;
42953
43119
  if (previousConfig !== undefined && (!Array.isArray(previousConfig) || previousConfig.some((entry) => !entry || typeof entry !== "object" || entry.path !== undefined && entry.name !== undefined)))
42954
43120
  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
43121
  const bridgeNeedsRepair = previousConfig?.some((entry) => entry.enabled === false && bridgeSelector(entry));
42956
43122
  const selections = [...skills.filter((entry) => entry.agent === "codex" && !entry.bridge).map((skill) => ({ path: skill.path, enabled: false })), { path: bridgePath, enabled: true }];
42957
43123
  for (const skill of selections) {
42958
- const path = join22(skill.path, "SKILL.md");
43124
+ const path = join23(skill.path, "SKILL.md");
42959
43125
  let found = false;
42960
43126
  result = result.replace(CODEX_SKILL_CONFIG_SECTIONS, (section) => {
42961
43127
  const parsed = Bun.TOML.parse(section);
42962
43128
  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))))
43129
+ if (!declared || !(skill.enabled && bridgeSelector(declared)) && !(typeof declared.path === "string" && [resolve16(path), resolve16(skill.path)].includes(canonicalAgentPath(declared.path, aliases))))
42964
43130
  return section;
42965
43131
  found = true;
42966
43132
  return /^\s*enabled\s*=/m.test(section) ? section.replace(/^\s*enabled\s*=.*$/m, `enabled = ${skill.enabled}`) : `${section.trimEnd()}
@@ -42981,14 +43147,14 @@ enabled = false
42981
43147
  return result;
42982
43148
  }
42983
43149
  function assertCodexInstallationInputs(home, projectDirs, inputs) {
42984
- const nativeRoots = [home, ...projectAncestorDirectories(projectDirs)].flatMap((directory) => ROOTS.filter(([agent]) => agent === "codex").map(([, path]) => resolve15(directory, path)));
43150
+ const nativeRoots = [home, ...projectAncestorDirectories(projectDirs)].flatMap((directory) => ROOTS.filter(([agent]) => agent === "codex").map(([, path]) => resolve16(directory, path)));
42985
43151
  if (inputs.some((input) => nativeRoots.some((root2) => root2 === input || root2.startsWith(input + sep5) || input.startsWith(root2 + sep5))))
42986
43152
  throw new Error("Native installation input overlaps an unconditional skill-loading root");
42987
43153
  }
42988
43154
  function planAgentIntegration(options) {
42989
43155
  const home = options.home ?? homedir3(), dataDir2 = options.dataDir ?? getDataDirReadOnly();
42990
43156
  const aliases = rootAliases(home, options.allowRootAliases);
42991
- const policyPath = join22(dataDir2, "agent-policy.json");
43157
+ const policyPath = join23(dataDir2, "agent-policy.json");
42992
43158
  assertSafePath(policyPath);
42993
43159
  const priorSnapshot = readManagedSkillPolicySnapshot(dataDir2), previousPolicy = priorSnapshot?.text ?? null, policy = priorSnapshot?.value ?? {};
42994
43160
  if (policy.bridge !== undefined && (!policy.bridge || typeof policy.bridge !== "object" || Array.isArray(policy.bridge)))
@@ -43020,10 +43186,10 @@ function planAgentIntegration(options) {
43020
43186
  }
43021
43187
  return resolveAgentDiscovery({ home, agent, reviewed: options.discoveryInputs, retainedReview, canonical: (path) => canonicalAgentPath(path, aliases) });
43022
43188
  });
43023
- const codexConfig = options.agents.includes("codex") ? Bun.TOML.parse(readOptional(canonicalAgentPath(join22(home, ".codex", "config.toml"), aliases)) ?? "") : {};
43189
+ const codexConfig = options.agents.includes("codex") ? Bun.TOML.parse(readOptional(canonicalAgentPath(join23(home, ".codex", "config.toml"), aliases)) ?? "") : {};
43024
43190
  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
43191
  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) => {
43192
+ 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
43193
  const bytes = readNativeBytes(path, 1024 * 1024);
43028
43194
  observedNativeSources.push({ path, sha256: sha4(bytes) });
43029
43195
  return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
@@ -43031,7 +43197,7 @@ function planAgentIntegration(options) {
43031
43197
  const codexPluginSkills = codexPluginControls.skills;
43032
43198
  const codexInactivePlugins = codexPluginControls.inactivePlugins;
43033
43199
  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));
43200
+ 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
43201
  assertCodexInstallationInputs(home, [options.projectDir ?? home], codexPluginSourceInputs.map((input) => input.sourceRoot));
43036
43202
  const changes = [];
43037
43203
  for (const agent of [...new Set(options.agents)]) {
@@ -43039,19 +43205,19 @@ function planAgentIntegration(options) {
43039
43205
  throw new Error(`Unsupported agent: ${agent}`);
43040
43206
  const { command, profileId: profileId2 } = bindings.get(agent);
43041
43207
  const adapter = AGENT_ADAPTERS[agent];
43042
- const bridgePath = canonicalAgentPath(join22(home, adapter.root, CLI_BRIDGE_NAME), aliases);
43208
+ const bridgePath = canonicalAgentPath(join23(agent === "sumi" ? sumiBridgeRoot(home) : join23(home, adapter.root), CLI_BRIDGE_NAME), aliases);
43043
43209
  assertSafePath(bridgePath);
43044
- if (existsSync6(bridgePath) && !isOwnedCliBridge(bridgePath, [bridgePath]))
43210
+ if (existsSync7(bridgePath) && !isOwnedCliBridge(bridgePath, [bridgePath]))
43045
43211
  throw new Error(`Refusing to overwrite an unrecognized or modified Skills bridge: ${bridgePath}`);
43046
43212
  for (const [name, after2] of Object.entries(CLI_BRIDGE_FILES)) {
43047
- const path2 = join22(bridgePath, name), before2 = readOptional(path2);
43213
+ const path2 = join23(bridgePath, name), before2 = readOptional(path2);
43048
43214
  if (before2 !== after2)
43049
43215
  changes.push({ path: path2, before: before2, after: after2 });
43050
43216
  }
43051
- const path = canonicalAgentPath(join22(home, adapter.config), aliases);
43217
+ const path = canonicalAgentPath(agent === "sumi" ? sumiConfigPath(home) : join23(home, adapter.config), aliases);
43052
43218
  const before = readOptional(path);
43053
43219
  if (agent === "hermes") {
43054
- const supervisorPath = join22(dataDir2, "agent-hooks", "hermes.js"), supervisorBefore = readOptional(supervisorPath), supervisorAfter = renderHermesSupervisor(command, profileId2);
43220
+ const supervisorPath = join23(dataDir2, "agent-hooks", "hermes.js"), supervisorBefore = readOptional(supervisorPath), supervisorAfter = renderHermesSupervisor(command, profileId2);
43055
43221
  const priorCommand = policy.bridge?.commands?.hermes, priorProfile = policy.bridge?.profiles?.hermes ?? policy.profileId;
43056
43222
  const previous = policy.bridge?.supervisors?.hermes;
43057
43223
  if (supervisorBefore !== null && supervisorBefore !== supervisorAfter && !(previous?.path === supervisorPath && typeof priorCommand === "string" && typeof priorProfile === "string" && supervisorBefore === renderHermesSupervisor(priorCommand, priorProfile)))
@@ -43062,19 +43228,30 @@ function planAgentIntegration(options) {
43062
43228
  const after2 = configureHermesHooks(before, supervisor, previous);
43063
43229
  if (before !== after2)
43064
43230
  changes.push({ path, before, after: after2 });
43065
- const optOut = join22(home, ".hermes", HERMES_OPT_OUT), optOutBefore = readOptional(optOut);
43231
+ const optOut = join23(home, ".hermes", HERMES_OPT_OUT), optOutBefore = readOptional(optOut);
43066
43232
  if (optOutBefore === null)
43067
43233
  changes.push({ path: optOut, before: null, after: `Managed by @hasna/skills: bundled native skill reseeding is disabled.
43068
43234
  ` });
43069
43235
  continue;
43070
43236
  }
43071
43237
  const config = jsonObject(before, path);
43072
- if (agent === "opencode") {
43238
+ if (agent === "sumi") {
43239
+ 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))))
43240
+ throw new Error("Expected Sumi native permission rules");
43241
+ config.permissions = [...(config.permissions ?? []).filter((rule) => rule.action !== "skill"), ...SUMI_SKILL_PERMISSIONS];
43242
+ const pluginPath = join23(sumiConfigDirectory(home), "plugins", "skills-cli.js"), pluginBefore = readOptional(pluginPath);
43243
+ const pluginAfter = renderSumiPlugin(command, profileId2);
43244
+ const priorCommand = policy.bridge?.commands?.sumi, priorProfile = policy.bridge?.profiles?.sumi ?? policy.profileId;
43245
+ if (pluginBefore !== null && pluginBefore !== pluginAfter && !(typeof priorCommand === "string" && typeof priorProfile === "string" && pluginBefore === renderSumiPlugin(priorCommand, priorProfile)))
43246
+ throw new Error("Refusing to overwrite a modified Sumi Skills plugin; preserve and review it first");
43247
+ if (pluginBefore !== pluginAfter)
43248
+ changes.push({ path: pluginPath, before: pluginBefore, after: pluginAfter });
43249
+ } else if (agent === "opencode") {
43073
43250
  const permission = config.permission ?? {};
43074
43251
  if (!permission || typeof permission !== "object" || Array.isArray(permission))
43075
43252
  throw new Error("Expected OpenCode permission object");
43076
43253
  config.permission = { ...permission, skill: { "*": "deny", [CLI_BRIDGE_NAME]: "allow" } };
43077
- const pluginPath = join22(home, ".config", "opencode", "plugins", "skills-cli.js"), pluginBefore = readOptional(pluginPath);
43254
+ const pluginPath = join23(home, ".config", "opencode", "plugins", "skills-cli.js"), pluginBefore = readOptional(pluginPath);
43078
43255
  const pluginAfter = renderOpenCodePlugin(command, profileId2);
43079
43256
  const priorCommand = policy.bridge?.commands?.opencode;
43080
43257
  const ownedPrevious = typeof priorCommand === "string" && typeof policy.profileId === "string" && pluginBefore === renderOpenCodePlugin(priorCommand, policy.bridge?.profiles?.opencode ?? policy.profileId);
@@ -43091,13 +43268,13 @@ function planAgentIntegration(options) {
43091
43268
  if (before !== after)
43092
43269
  changes.push({ path, before, after });
43093
43270
  if (agent === "codex") {
43094
- const configPath = canonicalAgentPath(join22(home, ".codex", "config.toml"), aliases), previous = readOptional(configPath);
43271
+ const configPath = canonicalAgentPath(join23(home, ".codex", "config.toml"), aliases), previous = readOptional(configPath);
43095
43272
  const next = disableReviewedCodexPluginNames(disableCodexSkills(previous ?? "", nativeSkills, aliases, bridgePath), codexPluginSkills);
43096
43273
  if (next !== (previous ?? ""))
43097
43274
  changes.push({ path: configPath, before: previous, after: next });
43098
43275
  }
43099
43276
  }
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;
43277
+ 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
43278
  const discoveryAfter = discoveries.map((binding) => {
43102
43279
  const rebound = rebindAgentDiscovery(binding, new Map(changes.map((change) => [change.path, change.after])));
43103
43280
  if (binding.agent !== "codex")
@@ -43112,12 +43289,12 @@ function planAgentIntegration(options) {
43112
43289
  version: CLI_BRIDGE_VERSION,
43113
43290
  digest: CLI_BRIDGE_DIGEST,
43114
43291
  agents: [...new Set([...priorAgents, ...options.agents])].sort(),
43115
- home: resolve15(home),
43292
+ home: resolve16(home),
43116
43293
  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)) } } } : {},
43294
+ ...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
43295
  commands: { ...policy.bridge?.commands, ...Object.fromEntries([...bindings].map(([agent, binding]) => [agent, binding.command])) },
43119
43296
  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 ?? [],
43297
+ 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
43298
  rootAliases: aliases,
43122
43299
  ...options.codexNativeCatalog || codexPluginSkills.length || codexInactivePlugins.length || codexPluginSourceInputs.length ? { codexPluginSkills, codexInactivePlugins, codexPluginSkillReview } : {},
43123
43300
  discovery: { ...policy.bridge?.discovery, ...Object.fromEntries(discoveryAfter.map((binding) => [binding.agent, binding])) }
@@ -43140,7 +43317,7 @@ function claudeSettingsConsumers(home, path, discoveries, aliases) {
43140
43317
  const distance = relative4(canonical6(root2), path);
43141
43318
  return distance === "" || distance !== ".." && !distance.startsWith(`..${sep5}`) && !isAbsolute17(distance);
43142
43319
  };
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);
43320
+ 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
43321
  }
43145
43322
  function verifyCoordinatedDiscovery(binding, home, aliases) {
43146
43323
  try {
@@ -43157,8 +43334,8 @@ function verifyCoordinatedDiscovery(binding, home, aliases) {
43157
43334
  }
43158
43335
  }
43159
43336
  function planClaudeHookEventsUpdate(options) {
43160
- const home = resolve15(options.home ?? homedir3()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
43161
- const policyPath = join22(dataDir2, "agent-policy.json");
43337
+ const home = resolve16(options.home ?? homedir3()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
43338
+ const policyPath = join23(dataDir2, "agent-policy.json");
43162
43339
  assertSafePath(policyPath);
43163
43340
  const snapshot2 = readManagedSkillPolicySnapshot(dataDir2);
43164
43341
  if (!snapshot2)
@@ -43169,9 +43346,9 @@ function planClaudeHookEventsUpdate(options) {
43169
43346
  }
43170
43347
  const aliases = bridge.rootAliases ?? [];
43171
43348
  recheckRootAliases(aliases);
43172
- const path = canonicalAgentPath(join22(home, ".claude", "settings.json"), aliases);
43349
+ const path = canonicalAgentPath(join23(home, ".claude", "settings.json"), aliases);
43173
43350
  assertSafePath(path);
43174
- const before = lstatSync19(path, { throwIfNoEntry: false }) ? new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(readNativeBytes(path, 1024 * 1024)) : null;
43351
+ const before = lstatSync20(path, { throwIfNoEntry: false }) ? new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(readNativeBytes(path, 1024 * 1024)) : null;
43175
43352
  if ((before === null ? "absent" : sha4(before)) !== options.expectedSettingsSha256)
43176
43353
  throw new Error("Claude settings preimage changed");
43177
43354
  assertClaudeHookEventsReplacement(before, options.replacement, options.events);
@@ -43231,14 +43408,14 @@ function atomicWrite2(path, content) {
43231
43408
  writeFileSync4(temporary, content, { mode: 384, flag: "wx" });
43232
43409
  renameSync3(temporary, path);
43233
43410
  } finally {
43234
- if (existsSync6(temporary))
43411
+ if (existsSync7(temporary))
43235
43412
  unlinkSync4(temporary);
43236
43413
  }
43237
43414
  }
43238
43415
  function planAgentSettingsWitnessUpgrade(options) {
43239
43416
  if (options.targetCodexVersion !== undefined && (options.agent !== "codex" || ![2, 3].includes(options.targetCodexVersion)))
43240
43417
  throw new Error("Invalid Codex witness target version");
43241
- const home = resolve15(options.home ?? homedir3()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
43418
+ const home = resolve16(options.home ?? homedir3()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
43242
43419
  const snapshot2 = readManagedSkillPolicySnapshot(dataDir2);
43243
43420
  if (!snapshot2 || sha4(snapshot2.text) !== options.expectedPolicySha256)
43244
43421
  throw new Error("Managed policy preimage changed");
@@ -43247,7 +43424,7 @@ function planAgentSettingsWitnessUpgrade(options) {
43247
43424
  const binding = policy.bridge?.discovery?.[options.agent];
43248
43425
  if (!binding || binding.agent !== options.agent || binding.method !== "reviewed")
43249
43426
  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);
43427
+ const configPath = canonicalAgentPath(join23(home, options.agent === "claude" ? ".claude/settings.json" : ".codex/config.toml"), aliases);
43251
43428
  const settings = readOptional(configPath);
43252
43429
  if (settings === null || sha4(settings) !== options.expectedSettingsSha256)
43253
43430
  throw new Error("Native settings preimage changed");
@@ -43286,7 +43463,7 @@ function planAgentSettingsWitnessUpgrade(options) {
43286
43463
  const replacement = { ...binding, sources: rebound };
43287
43464
  verifyAgentDiscovery(replacement);
43288
43465
  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 })) } };
43466
+ 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
43467
  }
43291
43468
  function applyAgentIntegration(plan) {
43292
43469
  for (const source of plan.observedNativeSources ?? [])
@@ -43294,12 +43471,12 @@ function applyAgentIntegration(plan) {
43294
43471
  throw new Error("Native identity source changed after planning");
43295
43472
  if (plan.observedSettings && readOptional(plan.observedSettings.path) !== plan.observedSettings.before)
43296
43473
  throw new Error("Native settings changed after witness planning");
43297
- const policyPath = join22(plan.dataDir, "agent-policy.json");
43474
+ const policyPath = join23(plan.dataDir, "agent-policy.json");
43298
43475
  assertSafePath(policyPath);
43299
- const currentText = (path) => resolve15(path) === resolve15(policyPath) ? readManagedSkillPolicySnapshot(plan.dataDir)?.text ?? null : readOptional(path);
43476
+ const currentText = (path) => resolve16(path) === resolve16(policyPath) ? readManagedSkillPolicySnapshot(plan.dataDir)?.text ?? null : readOptional(path);
43300
43477
  readManagedSkillPolicySnapshot(plan.dataDir);
43301
43478
  for (const change of plan.changes)
43302
- if (resolve15(change.path) === resolve15(policyPath))
43479
+ if (resolve16(change.path) === resolve16(policyPath))
43303
43480
  parseManagedSkillPolicy(change.after);
43304
43481
  const aliases = plan.rootAliases ?? [];
43305
43482
  recheckRootAliases(aliases);
@@ -43328,7 +43505,7 @@ function applyAgentIntegration(plan) {
43328
43505
  for (const change of plan.changes)
43329
43506
  if (currentText(change.path) !== change.before)
43330
43507
  throw new Error(`Configuration changed after planning: ${change.path}`);
43331
- const backupRoot = join22(plan.dataDir, "migration", randomUUID3()), backups = [], written = [], createdDirectories = new Set;
43508
+ const backupRoot = join23(plan.dataDir, "migration", randomUUID3()), backups = [], written = [], createdDirectories = new Set;
43332
43509
  if (!plan.changes.length) {
43333
43510
  recheckRootAliases(aliases);
43334
43511
  return { changed: [], backups, ...aliases.length ? { rootAliases: aliases } : {} };
@@ -43338,7 +43515,7 @@ function applyAgentIntegration(plan) {
43338
43515
  chmodSync(backupRoot, 448);
43339
43516
  for (const [index, change] of plan.changes.entries())
43340
43517
  if (change.before !== null) {
43341
- const backup = join22(backupRoot, `${index}-${sha4(change.path).slice(0, 12)}.backup`);
43518
+ const backup = join23(backupRoot, `${index}-${sha4(change.path).slice(0, 12)}.backup`);
43342
43519
  writeFileSync4(backup, change.before, { mode: 384, flag: "wx" });
43343
43520
  if (readFileSync14(backup, "utf8") !== change.before)
43344
43521
  throw new Error("Native configuration preservation readback failed");
@@ -43349,7 +43526,7 @@ function applyAgentIntegration(plan) {
43349
43526
  recheckRootAliases(aliases);
43350
43527
  if (currentText(change.path) !== change.before)
43351
43528
  throw new Error(`Configuration changed after planning: ${change.path}`);
43352
- for (let directory = dirname15(change.path);!existsSync6(directory); directory = dirname15(directory))
43529
+ for (let directory = dirname15(change.path);!existsSync7(directory); directory = dirname15(directory))
43353
43530
  createdDirectories.add(directory);
43354
43531
  const after = change.after;
43355
43532
  atomicWrite2(change.path, after);
@@ -43369,7 +43546,7 @@ function applyAgentIntegration(plan) {
43369
43546
  }
43370
43547
  for (const agent of plan.managedAgentChecks?.agents ?? [])
43371
43548
  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 } : {} }) + `
43549
+ 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
43550
  `);
43374
43551
  } catch (error) {
43375
43552
  for (const change of written.reverse()) {
@@ -43423,7 +43600,7 @@ function writeArchiveJournal(path, value) {
43423
43600
  } finally {
43424
43601
  if (descriptor !== undefined)
43425
43602
  closeSync16(descriptor);
43426
- if (lstatSync19(temporary, { throwIfNoEntry: false }))
43603
+ if (lstatSync20(temporary, { throwIfNoEntry: false }))
43427
43604
  unlinkSync4(temporary);
43428
43605
  }
43429
43606
  }
@@ -43434,7 +43611,7 @@ function archiveNativeSkills(inventory, options) {
43434
43611
  recheckRootAliases(aliases);
43435
43612
  for (const entry of inventory.filter((entry2) => entry2.bridge)) {
43436
43613
  const adapter = AGENT_ADAPTERS[entry.agent];
43437
- const expected = adapter && entry.bridgeHome ? canonicalAgentPath(join22(entry.bridgeHome, adapter.root, CLI_BRIDGE_NAME), aliases) : undefined;
43614
+ const expected = adapter && entry.bridgeHome ? canonicalAgentPath(join23(entry.agent === "sumi" ? sumiBridgeRoot(entry.bridgeHome) : join23(entry.bridgeHome, adapter.root), CLI_BRIDGE_NAME), aliases) : undefined;
43438
43615
  if (!expected || treeHash(entry.path) !== entry.hash || !isOwnedCliBridge(entry.path, [expected]))
43439
43616
  throw new Error(`Skills bridge changed after planning: ${entry.path}`);
43440
43617
  }
@@ -43445,11 +43622,11 @@ function archiveNativeSkills(inventory, options) {
43445
43622
  const targetManifest = options.targetManifest ? { schema: options.targetManifest.schema, digest: options.targetManifest.digest, targetCount: options.targetManifest.targets.length } : undefined;
43446
43623
  if (!selected.length)
43447
43624
  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");
43625
+ const operationId = randomUUID3(), archiveRoot = join23(options.dataDir ?? getDataDir(), "migration", operationId, "native"), receiptPath = join23(archiveRoot, "receipt.json");
43449
43626
  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,
43627
+ source: entry.vendor ? join23(entry.path, "SKILL.md") : entry.path,
43628
+ archive: join23(archiveRoot, `${index}-${sha4(entry.path).slice(0, 12)}`),
43629
+ hash: entry.vendor ? sha4(readNativeBytes(join23(entry.path, "SKILL.md"))) : entry.hash,
43453
43630
  ...entry.vendor ? { discoveryOnly: true } : {},
43454
43631
  status: "planned"
43455
43632
  }));
@@ -43457,7 +43634,7 @@ function archiveNativeSkills(inventory, options) {
43457
43634
  const moved = [];
43458
43635
  const verifyArchive = (entry) => {
43459
43636
  assertSafePath(entry.archive);
43460
- const stat2 = lstatSync19(entry.archive);
43637
+ const stat2 = lstatSync20(entry.archive);
43461
43638
  if (entry.discoveryOnly ? !stat2.isFile() : !stat2.isDirectory())
43462
43639
  throw new Error("Archive type changed");
43463
43640
  if ((entry.discoveryOnly ? sha4(readNativeBytes(entry.archive)) : treeHash(entry.archive)) !== entry.hash)
@@ -43465,7 +43642,7 @@ function archiveNativeSkills(inventory, options) {
43465
43642
  };
43466
43643
  assertSafePath(archiveRoot);
43467
43644
  const created = [];
43468
- for (let path = archiveRoot;!existsSync6(path); path = dirname15(path))
43645
+ for (let path = archiveRoot;!existsSync7(path); path = dirname15(path))
43469
43646
  created.push(path);
43470
43647
  mkdirSync5(archiveRoot, { recursive: true, mode: 448 });
43471
43648
  try {
@@ -43505,7 +43682,7 @@ function archiveNativeSkills(inventory, options) {
43505
43682
  recheckRootAliases(aliases);
43506
43683
  assertSafePath(entry.source);
43507
43684
  assertSafePath(entry.archive);
43508
- if (lstatSync19(entry.source, { throwIfNoEntry: false })) {
43685
+ if (lstatSync20(entry.source, { throwIfNoEntry: false })) {
43509
43686
  entry.status = "recovery-required";
43510
43687
  entry.conflict = "source-occupied";
43511
43688
  continue;
@@ -43522,7 +43699,7 @@ function archiveNativeSkills(inventory, options) {
43522
43699
  syncArchiveDirectory(dirname15(entry.source));
43523
43700
  unlinkSync4(entry.archive);
43524
43701
  } else {
43525
- if (lstatSync19(entry.source, { throwIfNoEntry: false })) {
43702
+ if (lstatSync20(entry.source, { throwIfNoEntry: false })) {
43526
43703
  entry.status = "recovery-required";
43527
43704
  entry.conflict = "source-occupied";
43528
43705
  continue;
@@ -43553,8 +43730,8 @@ function assertManagedAgentBridge(agent, options = {}) {
43553
43730
  assertManagedAgentBridgeWithDiscovery(agent, options);
43554
43731
  }
43555
43732
  function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscovery) {
43556
- const home = resolve15(options.home ?? homedir3()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
43557
- assertSafePath(join22(dataDir2, "agent-policy.json"));
43733
+ const home = resolve16(options.home ?? homedir3()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
43734
+ assertSafePath(join23(dataDir2, "agent-policy.json"));
43558
43735
  const snapshot2 = readManagedSkillPolicySnapshot(dataDir2);
43559
43736
  if (!snapshot2)
43560
43737
  throw new Error("NATIVE_SKILL_DRIFT: install the Skills bridge with skills hook install");
@@ -43565,14 +43742,14 @@ function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscov
43565
43742
  if (!Array.isArray(aliases))
43566
43743
  throw new Error("NATIVE_SKILL_DRIFT: invalid root alias binding");
43567
43744
  recheckRootAliases(aliases);
43568
- const expected = canonicalAgentPath(join22(home, AGENT_ADAPTERS[agent].root, CLI_BRIDGE_NAME), aliases);
43745
+ const expected = canonicalAgentPath(join23(agent === "sumi" ? sumiBridgeRoot(home) : join23(home, AGENT_ADAPTERS[agent].root), CLI_BRIDGE_NAME), aliases);
43569
43746
  if (!isOwnedCliBridge(expected, [expected]))
43570
43747
  throw new Error("NATIVE_SKILL_DRIFT: the native Skills bridge is missing or modified; repair it before continuing");
43571
43748
  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";
43749
+ 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
43750
  const discovery = provenDiscovery ?? binding.discovery?.[agent];
43574
43751
  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);
43752
+ 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
43753
  const command = binding.commands?.[agent], profile = binding.profiles?.[agent];
43577
43754
  if (typeof command !== "string" || typeof profile !== "string")
43578
43755
  throw new Error("NATIVE_SKILL_DRIFT: the native hook command/profile binding is missing");
@@ -43580,11 +43757,14 @@ function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscov
43580
43757
  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
43758
  if (agent === "hermes") {
43582
43759
  const supervisor = binding.supervisors?.hermes;
43583
- if (supervisor?.path !== join22(dataDir2, "agent-hooks", "hermes.js") || supervisor?.sha256 !== sha4(renderHermesSupervisor(command, profile)))
43760
+ if (supervisor?.path !== join23(dataDir2, "agent-hooks", "hermes.js") || supervisor?.sha256 !== sha4(renderHermesSupervisor(command, profile)))
43584
43761
  throw new Error("NATIVE_SKILL_DRIFT: Hermes supervisor binding changed; run skills hook install");
43585
43762
  assertHermesProtection(home, config, command, profile, supervisor);
43763
+ } else if (agent === "sumi") {
43764
+ 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))
43765
+ throw new Error("NATIVE_SKILL_DRIFT: Sumi bridge protection changed; run skills hook install");
43586
43766
  } 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))
43767
+ 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
43768
  throw new Error("NATIVE_SKILL_DRIFT: OpenCode bridge protection changed; run skills hook install");
43589
43769
  } else {
43590
43770
  const required = {};
@@ -43601,21 +43781,21 @@ function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscov
43601
43781
  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
43782
  throw new Error("NATIVE_SKILL_DRIFT: Gemini bridge or bundled-skill protection changed; run skills hook install");
43603
43783
  }
43604
- const codexPath = canonicalAgentPath(join22(home, ".codex", "config.toml"), aliases);
43784
+ const codexPath = canonicalAgentPath(join23(home, ".codex", "config.toml"), aliases);
43605
43785
  if (options.codexDiscoveryRecovery && (agent !== "codex" || options.codexDiscoveryRecovery.configPath !== codexPath))
43606
43786
  throw new Error("NATIVE_SKILL_DRIFT: Codex trust recovery names a different configuration root");
43607
43787
  const codexConfig = agent === "codex" ? Bun.TOML.parse(readOptional(codexPath) ?? "") : {};
43608
43788
  if (agent === "codex" && codexConfig.skills?.bundled?.enabled !== false)
43609
43789
  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)));
43790
+ const setting = (path) => (codexConfig.skills?.config ?? []).filter((entry) => typeof entry.path === "string" && [path, join23(path, "SKILL.md")].includes(canonicalAgentPath(entry.path, aliases)));
43611
43791
  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
43792
  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))))
43793
+ 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
43794
  throw new Error("NATIVE_SKILL_DRIFT: reviewed native plugin capability controls changed; run skills hook install with a fresh discovery review");
43615
43795
  const disabledPlugin = (entry) => {
43616
43796
  if (agent !== "codex" || !entry.vendor)
43617
43797
  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));
43798
+ 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
43799
  return isReviewedCodexPluginInactive(document2, cache, binding.codexInactivePlugins ?? [], codexConfig.plugins, codexConfig.skills?.config ?? [], read3) || isReviewedCodexPluginSkillDisabled(document2, cache, binding.codexPluginSkills ?? [], codexConfig.skills?.config, read3);
43620
43800
  };
43621
43801
  const disabledPaths = new Set(disabledCodexSkillPaths(codexConfig, aliases));
@@ -43628,15 +43808,15 @@ function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscov
43628
43808
  return true;
43629
43809
  if (!disabledPaths.has(entry.path))
43630
43810
  return false;
43631
- if (entry.path.startsWith(canonicalAgentPath(join22(home, ".codex", "plugins", "cache"), aliases) + sep5))
43811
+ if (entry.path.startsWith(canonicalAgentPath(join23(home, ".codex", "plugins", "cache"), aliases) + sep5))
43632
43812
  return true;
43633
- const runtimeCache = canonicalAgentPath(join22(home, ".cache", "codex-runtimes"), aliases);
43813
+ const runtimeCache = canonicalAgentPath(join23(home, ".cache", "codex-runtimes"), aliases);
43634
43814
  if (entry.path.startsWith(runtimeCache + sep5) && discovery?.method === "automatic" && discovery.roots.some((root2) => entry.path.startsWith(root2 + sep5)))
43635
43815
  return true;
43636
- const bundledMarketplaces = canonicalAgentPath(join22(home, ".codex", ".tmp", "bundled-marketplaces"), aliases);
43816
+ const bundledMarketplaces = canonicalAgentPath(join23(home, ".codex", ".tmp", "bundled-marketplaces"), aliases);
43637
43817
  if (entry.path.startsWith(bundledMarketplaces + sep5) && discovery?.method === "automatic" && discovery.roots.some((root2) => entry.path.startsWith(root2 + sep5)))
43638
43818
  return true;
43639
- if (!entry.path.startsWith(canonicalAgentPath(join22(home, ".codex", "skills", ".system"), aliases) + sep5))
43819
+ if (!entry.path.startsWith(canonicalAgentPath(join23(home, ".codex", "skills", ".system"), aliases) + sep5))
43640
43820
  return false;
43641
43821
  return Array.isArray(binding.disabledBuiltins) && binding.disabledBuiltins.some((item) => item.path === entry.path && item.hash === entry.hash);
43642
43822
  };
@@ -43646,6 +43826,8 @@ function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscov
43646
43826
  throw new Error("NATIVE_SKILL_DRIFT: an installed Gemini builtin is not disabled");
43647
43827
  try {
43648
43828
  verifyAgentDiscovery(discovery, options.codexDiscoveryRecovery);
43829
+ if (agent === "sumi" && discovery.method === "reviewed")
43830
+ resolveAgentDiscovery({ home, agent, retainedReview: discovery, canonical: (path) => canonicalAgentPath(path, aliases) });
43649
43831
  if (discovery.method === "automatic") {
43650
43832
  const current = resolveAgentDiscovery({ home, agent, canonical: (path) => canonicalAgentPath(path, aliases) });
43651
43833
  if (JSON.stringify(current) !== JSON.stringify(discovery))
@@ -43657,7 +43839,7 @@ function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscov
43657
43839
  let installationInputRoots = [];
43658
43840
  if (agent === "codex") {
43659
43841
  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)));
43842
+ 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
43843
  } catch {
43662
43844
  throw new Error("NATIVE_SKILL_DRIFT: native installation input identity changed; review discovery and catalog");
43663
43845
  }
@@ -43681,25 +43863,25 @@ function assertNativeExportAllowed(dataDir2 = getDataDirReadOnly()) {
43681
43863
 
43682
43864
  // src/lib/portable-skills.ts
43683
43865
  import {
43684
- existsSync as existsSync9,
43866
+ existsSync as existsSync10,
43685
43867
  mkdirSync as mkdirSync7,
43686
43868
  mkdtempSync,
43687
43869
  readdirSync as readdirSync10,
43688
- realpathSync as realpathSync10,
43870
+ realpathSync as realpathSync11,
43689
43871
  renameSync as renameSync4,
43690
43872
  rmSync as rmSync2,
43691
43873
  statSync as statSync9,
43692
43874
  writeFileSync as writeFileSync6
43693
43875
  } 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";
43876
+ 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
43877
 
43696
43878
  // src/lib/registry-data/index.ts
43697
43879
  var SKILLS = [];
43698
43880
 
43699
43881
  // src/lib/skill-hash.ts
43700
43882
  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";
43883
+ import { existsSync as existsSync8, readdirSync as readdirSync9, readFileSync as readFileSync15, statSync as statSync7 } from "fs";
43884
+ import { join as join24, sep as sep6 } from "path";
43703
43885
  var CONTENT_HASH_ALGORITHM = "sha256";
43704
43886
  var HASH_EXCLUDE_DIRS = new Set([".git", "node_modules", "dist", "build", ".turbo"]);
43705
43887
  function excludedHashEntry(name, directory) {
@@ -43761,8 +43943,8 @@ function collectBundleFiles(skillPath) {
43761
43943
  if (seen.has(entry))
43762
43944
  continue;
43763
43945
  seen.add(entry);
43764
- const absolute = join23(skillPath, entry);
43765
- if (!existsSync7(absolute))
43946
+ const absolute = join24(skillPath, entry);
43947
+ if (!existsSync8(absolute))
43766
43948
  continue;
43767
43949
  if (statSync7(absolute).isDirectory())
43768
43950
  collectDirectory(files, absolute, entry);
@@ -43775,7 +43957,7 @@ function collectDirectory(files, dir, rel) {
43775
43957
  for (const entry of readdirSync9(dir).sort()) {
43776
43958
  if (entry.startsWith("."))
43777
43959
  continue;
43778
- const absolute = join23(dir, entry);
43960
+ const absolute = join24(dir, entry);
43779
43961
  const childRel = `${rel}/${entry}`;
43780
43962
  let stats;
43781
43963
  try {
@@ -43836,7 +44018,7 @@ async function hashBundleFilesCooperatively(files, check) {
43836
44018
  hash2.update(chunk);
43837
44019
  bytesSinceYield += chunk.byteLength;
43838
44020
  if (bytesSinceYield >= 256 * 1024) {
43839
- await new Promise((resolve16) => setImmediate(resolve16));
44021
+ await new Promise((resolve17) => setImmediate(resolve17));
43840
44022
  bytesSinceYield = 0;
43841
44023
  }
43842
44024
  }
@@ -43989,7 +44171,7 @@ async function hashContentEntries(entries, options) {
43989
44171
  const normalized = [];
43990
44172
  let normalizedBytes = 0;
43991
44173
  let manifest;
43992
- await new Promise((resolve16) => setImmediate(resolve16));
44174
+ await new Promise((resolve17) => setImmediate(resolve17));
43993
44175
  for (const entry of snapshot2) {
43994
44176
  check();
43995
44177
  if (!coveredContentPath(entry.path))
@@ -44002,7 +44184,7 @@ async function hashContentEntries(entries, options) {
44002
44184
  contentLimit("Content hash normalized byte limit exceeded");
44003
44185
  normalizedBytes += file.content.byteLength;
44004
44186
  normalized.push(file);
44005
- await new Promise((resolve16) => setImmediate(resolve16));
44187
+ await new Promise((resolve17) => setImmediate(resolve17));
44006
44188
  }
44007
44189
  normalized.sort((a, b) => a.rel < b.rel ? -1 : a.rel > b.rel ? 1 : 0);
44008
44190
  check();
@@ -44209,14 +44391,14 @@ function validateRuntimeContract(manifest, issues, strict) {
44209
44391
  // src/lib/portable-skills-files.ts
44210
44392
  import {
44211
44393
  cpSync,
44212
- existsSync as existsSync8,
44213
- lstatSync as lstatSync20,
44394
+ existsSync as existsSync9,
44395
+ lstatSync as lstatSync21,
44214
44396
  mkdirSync as mkdirSync6,
44215
44397
  readFileSync as readFileSync16,
44216
- realpathSync as realpathSync8,
44398
+ realpathSync as realpathSync9,
44217
44399
  writeFileSync as writeFileSync5
44218
44400
  } from "fs";
44219
- import { basename as basename8, dirname as dirname16, join as join24, relative as relative5 } from "path";
44401
+ import { basename as basename8, dirname as dirname16, join as join25, relative as relative5 } from "path";
44220
44402
  var ANY_SEGMENT_COPY_EXCLUDES = new Set([
44221
44403
  ".git",
44222
44404
  ".DS_Store",
@@ -44273,12 +44455,12 @@ function readPortableSkillManifestForImport(skillPath) {
44273
44455
  return readManifest(skillPath, basename8(skillPath), normalizeNewPortableSkillName);
44274
44456
  }
44275
44457
  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;
44458
+ const skillJsonPath = join25(skillPath, "skill.json");
44459
+ const skillMdPath = join25(skillPath, "SKILL.md");
44460
+ const pkgPath = join25(skillPath, "package.json");
44461
+ const jsonManifest = existsSync9(skillJsonPath) ? readJsonObject(skillJsonPath) : undefined;
44462
+ const frontmatter = existsSync9(skillMdPath) ? parseSkillFrontmatter(readFileSync16(skillMdPath, "utf-8")) ?? undefined : undefined;
44463
+ const pkg = existsSync9(pkgPath) ? readJsonObject(pkgPath) : undefined;
44282
44464
  const name = normalizeName(stringField(jsonManifest, "name") ?? frontmatter?.name ?? stringValue(pkg?.name) ?? fallbackName);
44283
44465
  const description = stringField(jsonManifest, "description") ?? frontmatter?.description ?? stringValue(pkg?.description) ?? `${name} skill`;
44284
44466
  const version = readDeclaredSkillVersion(skillPath) ?? PORTABLE_SKILL_DEFAULT_VERSION;
@@ -44307,12 +44489,12 @@ function parseSkillKind(value) {
44307
44489
  return;
44308
44490
  }
44309
44491
  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;
44492
+ const skillJsonPath = join25(skillPath, "skill.json");
44493
+ const skillMdPath = join25(skillPath, "SKILL.md");
44494
+ const pkgPath = join25(skillPath, "package.json");
44495
+ const jsonManifest = existsSync9(skillJsonPath) ? readJsonObject(skillJsonPath) : undefined;
44496
+ const frontmatter = existsSync9(skillMdPath) ? parseSkillFrontmatter(readFileSync16(skillMdPath, "utf-8")) ?? undefined : undefined;
44497
+ const pkg = existsSync9(pkgPath) ? readJsonObject(pkgPath) : undefined;
44316
44498
  return stringField(jsonManifest, "version") ?? frontmatter?.version ?? stringValue(pkg?.version);
44317
44499
  }
44318
44500
  function createInstructionManifest(name, options) {
@@ -44333,7 +44515,7 @@ function createInstructionManifest(name, options) {
44333
44515
  }
44334
44516
  function writeInstructionSkillTemplate(skillPath, manifest) {
44335
44517
  mkdirSync6(skillPath, { recursive: true });
44336
- writeFileSync5(join24(skillPath, "SKILL.md"), renderInstructionSkillMd(manifest));
44518
+ writeFileSync5(join25(skillPath, "SKILL.md"), renderInstructionSkillMd(manifest));
44337
44519
  writeSkillJsonWithHash(skillPath, manifest);
44338
44520
  }
44339
44521
  function renderInstructionSkillMd(manifest) {
@@ -44383,12 +44565,12 @@ function createPortableManifest(name, options) {
44383
44565
  };
44384
44566
  }
44385
44567
  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));
44568
+ mkdirSync6(join25(skillPath, "src"), { recursive: true });
44569
+ writeFileSync5(join25(skillPath, "SKILL.md"), renderSkillMd(manifest));
44570
+ writeFileSync5(join25(skillPath, "AGENTS.md"), renderAgentsMd(manifest));
44571
+ writeFileSync5(join25(skillPath, "package.json"), renderPackageJson(manifest));
44572
+ writeFileSync5(join25(skillPath, "tsconfig.json"), renderTsconfig());
44573
+ writeFileSync5(join25(skillPath, "src", "index.ts"), renderEntrypoint(manifest));
44392
44574
  writeSkillJsonWithHash(skillPath, manifest);
44393
44575
  }
44394
44576
  function fillContractDefaults(manifest, entrypoint) {
@@ -44413,7 +44595,7 @@ function writeSkillJsonWithHash(skillPath, manifest) {
44413
44595
  content_hash: undefined
44414
44596
  }
44415
44597
  };
44416
- writeFileSync5(join24(skillPath, "skill.json"), `${JSON.stringify({ ...existing, ...renderSkillJsonObject(withoutHash) }, null, 2)}
44598
+ writeFileSync5(join25(skillPath, "skill.json"), `${JSON.stringify({ ...existing, ...renderSkillJsonObject(withoutHash) }, null, 2)}
44417
44599
  `);
44418
44600
  const hash2 = computeContentHash(skillPath);
44419
44601
  const withHash = {
@@ -44423,13 +44605,13 @@ function writeSkillJsonWithHash(skillPath, manifest) {
44423
44605
  content_hash: hash2
44424
44606
  }
44425
44607
  };
44426
- writeFileSync5(join24(skillPath, "skill.json"), `${JSON.stringify({ ...existing, ...renderSkillJsonObject(withHash) }, null, 2)}
44608
+ writeFileSync5(join25(skillPath, "skill.json"), `${JSON.stringify({ ...existing, ...renderSkillJsonObject(withHash) }, null, 2)}
44427
44609
  `);
44428
44610
  return withHash;
44429
44611
  }
44430
44612
  function readExistingSkillJson(skillPath) {
44431
- const path = join24(skillPath, "skill.json");
44432
- if (!existsSync8(path))
44613
+ const path = join25(skillPath, "skill.json");
44614
+ if (!existsSync9(path))
44433
44615
  return {};
44434
44616
  try {
44435
44617
  const parsed = JSON.parse(readFileSync16(path, "utf-8"));
@@ -44462,28 +44644,28 @@ function ensurePortableSkillFiles(skillPath, manifest) {
44462
44644
  tags: next.tags?.length ? next.tags : ["custom", next.name]
44463
44645
  };
44464
44646
  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));
44647
+ if (entry && !existsSync9(join25(skillPath, entry))) {
44648
+ mkdirSync6(dirname16(join25(skillPath, entry)), { recursive: true });
44649
+ writeFileSync5(join25(skillPath, entry), renderEntrypoint(next));
44468
44650
  }
44469
- if (!existsSync8(join24(skillPath, "SKILL.md")))
44470
- writeFileSync5(join24(skillPath, "SKILL.md"), renderSkillMd(next));
44651
+ if (!existsSync9(join25(skillPath, "SKILL.md")))
44652
+ writeFileSync5(join25(skillPath, "SKILL.md"), renderSkillMd(next));
44471
44653
  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));
44654
+ writeFileSync5(join25(skillPath, "SKILL.md"), ensureSkillMdFrontmatter(readFileSync16(join25(skillPath, "SKILL.md"), "utf-8"), next));
44655
+ if (!existsSync9(join25(skillPath, "AGENTS.md")))
44656
+ writeFileSync5(join25(skillPath, "AGENTS.md"), renderAgentsMd(next));
44475
44657
  ensurePackageJson(skillPath, next);
44476
- if (!existsSync8(join24(skillPath, "tsconfig.json")))
44477
- writeFileSync5(join24(skillPath, "tsconfig.json"), renderTsconfig());
44658
+ if (!existsSync9(join25(skillPath, "tsconfig.json")))
44659
+ writeFileSync5(join25(skillPath, "tsconfig.json"), renderTsconfig());
44478
44660
  writeSkillJsonWithHash(skillPath, next);
44479
44661
  return readPortableSkillManifest(skillPath, next.name);
44480
44662
  }
44481
44663
  function ensurePackageJson(skillPath, manifest) {
44482
- const pkgPath = join24(skillPath, "package.json");
44664
+ const pkgPath = join25(skillPath, "package.json");
44483
44665
  const first = manifest.commands[0] ?? { name: manifest.name, entry: "src/index.ts" };
44484
44666
  const commandName = normalizePortableSkillName(first.name || manifest.name);
44485
44667
  const entry = (first.entry ?? "src/index.ts").replace(/^\.\//, "");
44486
- if (!existsSync8(pkgPath)) {
44668
+ if (!existsSync9(pkgPath)) {
44487
44669
  writeFileSync5(pkgPath, renderPackageJson(manifest));
44488
44670
  return;
44489
44671
  }
@@ -44526,18 +44708,18 @@ function ensureInstructionSkillFiles(skillPath, manifest) {
44526
44708
  inputs: [],
44527
44709
  commands: []
44528
44710
  };
44529
- if (!existsSync8(join24(skillPath, "SKILL.md"))) {
44530
- writeFileSync5(join24(skillPath, "SKILL.md"), renderSkillMd(next));
44711
+ if (!existsSync9(join25(skillPath, "SKILL.md"))) {
44712
+ writeFileSync5(join25(skillPath, "SKILL.md"), renderSkillMd(next));
44531
44713
  } else {
44532
- const path = join24(skillPath, "SKILL.md");
44714
+ const path = join25(skillPath, "SKILL.md");
44533
44715
  const content = readFileSync16(path, "utf8");
44534
44716
  const declaredName = parseSkillFrontmatter(content)?.name;
44535
44717
  if (declaredName && declaredName !== next.name) {
44536
44718
  writeFileSync5(path, renameInstructionFrontmatter(content, next.name));
44537
44719
  }
44538
44720
  }
44539
- const packagePath = join24(skillPath, "package.json");
44540
- if (existsSync8(packagePath)) {
44721
+ const packagePath = join25(skillPath, "package.json");
44722
+ if (existsSync9(packagePath)) {
44541
44723
  const pkg = readJsonObject(packagePath);
44542
44724
  if (typeof pkg.name === "string" && pkg.name !== next.name) {
44543
44725
  writeFileSync5(packagePath, `${JSON.stringify({ ...pkg, name: next.name }, null, 2)}
@@ -44568,7 +44750,7 @@ function renameInstructionFrontmatter(content, name) {
44568
44750
  return renamed + content.slice(frontmatter[0].length);
44569
44751
  }
44570
44752
  function copySkillDirectory(source, destination) {
44571
- const resolvedSource = lstatSync20(source).isSymbolicLink() ? realpathSync8(source) : source;
44753
+ const resolvedSource = lstatSync21(source).isSymbolicLink() ? realpathSync9(source) : source;
44572
44754
  mkdirSync6(destination, { recursive: true });
44573
44755
  cpSync(resolvedSource, destination, {
44574
44756
  recursive: true,
@@ -44581,7 +44763,7 @@ function copySkillDirectory(source, destination) {
44581
44763
  if (isExcludedCopyEntry(segments[i], i === 0))
44582
44764
  return false;
44583
44765
  }
44584
- if (lstatSync20(src).isSymbolicLink())
44766
+ if (lstatSync21(src).isSymbolicLink())
44585
44767
  return false;
44586
44768
  return true;
44587
44769
  }
@@ -44860,12 +45042,12 @@ function escapeJsString(value) {
44860
45042
  }
44861
45043
 
44862
45044
  // src/lib/authoring-path.ts
44863
- import { lstatSync as lstatSync21, realpathSync as realpathSync9 } from "fs";
45045
+ import { lstatSync as lstatSync22, realpathSync as realpathSync10 } from "fs";
44864
45046
  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";
45047
+ import { basename as basename9, dirname as dirname17, join as join26, resolve as resolve17, sep as sep7 } from "path";
44866
45048
  var NATIVE_DISCOVERY_ROOTS = NATIVE_SKILL_ROOTS.map(([, path]) => path.split("/"));
44867
45049
  function pathParts(path) {
44868
- return resolve16(path).split(sep7).filter(Boolean);
45050
+ return resolve17(path).split(sep7).filter(Boolean);
44869
45051
  }
44870
45052
  function nativeRootMatch(path) {
44871
45053
  const parts = pathParts(path);
@@ -44879,24 +45061,24 @@ function nativeRootMatch(path) {
44879
45061
  return;
44880
45062
  }
44881
45063
  function physicalPath(path) {
44882
- let cursor = resolve16(path);
45064
+ let cursor = resolve17(path);
44883
45065
  const suffix = [];
44884
- while (!lstatSync21(cursor, { throwIfNoEntry: false })) {
45066
+ while (!lstatSync22(cursor, { throwIfNoEntry: false })) {
44885
45067
  suffix.unshift(basename9(cursor));
44886
45068
  const parent = dirname17(cursor);
44887
45069
  if (parent === cursor)
44888
- return resolve16(path);
45070
+ return resolve17(path);
44889
45071
  cursor = parent;
44890
45072
  }
44891
- return resolve16(realpathSync9(cursor), ...suffix);
45073
+ return resolve17(realpathSync10(cursor), ...suffix);
44892
45074
  }
44893
45075
  function contains(root2, path) {
44894
45076
  return path === root2 || path.startsWith(root2 + sep7);
44895
45077
  }
44896
45078
  function configuredRoots(home, explicitHome) {
44897
- const homeData = join25(home, ".hasna", "skills");
45079
+ const homeData = join26(home, ".hasna", "skills");
44898
45080
  const homePolicy = readManagedSkillPolicySnapshot(homeData);
44899
- const configuredPolicy = !explicitHome && resolve16(getDataDirReadOnly()) !== resolve16(homeData) ? readManagedSkillPolicySnapshot(getDataDirReadOnly()) : null;
45081
+ const configuredPolicy = !explicitHome && resolve17(getDataDirReadOnly()) !== resolve17(homeData) ? readManagedSkillPolicySnapshot(getDataDirReadOnly()) : null;
44900
45082
  const policy = homePolicy ?? configuredPolicy;
44901
45083
  const bridge = policy?.value.bridge;
44902
45084
  if (bridge && (typeof bridge.home !== "string" || physicalPath(bridge.home) !== physicalPath(home))) {
@@ -44925,8 +45107,8 @@ function configuredRoots(home, explicitHome) {
44925
45107
  admitBinding(binding);
44926
45108
  continue;
44927
45109
  }
44928
- const nativeHome = join25(home, agent === "opencode" ? ".config/opencode" : `.${agent}`);
44929
- if (!lstatSync21(nativeHome, { throwIfNoEntry: false }))
45110
+ const nativeHome = join26(home, agent === "opencode" ? ".config/opencode" : `.${agent}`);
45111
+ if (!lstatSync22(nativeHome, { throwIfNoEntry: false }))
44930
45112
  continue;
44931
45113
  roots.push(...resolveAgentDiscovery({ home, agent, canonical: physicalPath }).roots);
44932
45114
  }
@@ -44935,22 +45117,22 @@ function configuredRoots(home, explicitHome) {
44935
45117
  function assertPortableAuthoringPath(path, options = {}) {
44936
45118
  if (typeof path !== "string" || !path || path.includes("\x00"))
44937
45119
  throw new Error("Invalid portable authoring path");
44938
- const lexical = resolve16(path);
45120
+ const lexical = resolve17(path);
44939
45121
  const physical = physicalPath(lexical);
44940
45122
  const candidates = [lexical, physical];
44941
45123
  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"));
45124
+ const home = resolve17(options.homeDir ?? homedir4());
45125
+ const defaults = NATIVE_DISCOVERY_ROOTS.map((parts) => join26(home, ...parts));
45126
+ defaults.push(join26(home, ".codex/plugins/cache"), join26(home, ".claude/plugins/cache"), join26(home, ".claude/plugins/synced"), join26(home, ".gemini/extensions"));
44945
45127
  for (const root2 of defaults) {
44946
- if (candidates.some((candidate2) => contains(resolve16(root2), candidate2) || contains(physicalPath(root2), candidate2)))
45128
+ if (candidates.some((candidate2) => contains(resolve17(root2), candidate2) || contains(physicalPath(root2), candidate2)))
44947
45129
  native ??= root2;
44948
45130
  }
44949
45131
  if (native) {
44950
45132
  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
45133
  }
44952
45134
  for (const root2 of configuredRoots(home, options.homeDir !== undefined)) {
44953
- if (candidates.some((candidate2) => contains(resolve16(root2), candidate2) || contains(physicalPath(root2), candidate2))) {
45135
+ if (candidates.some((candidate2) => contains(resolve17(root2), candidate2) || contains(physicalPath(root2), candidate2))) {
44954
45136
  throw new Error(`Refusing portable Skills authoring below configured native discovery root: ${lexical}`);
44955
45137
  }
44956
45138
  }
@@ -44962,15 +45144,15 @@ function getPortableSkillsRoot(options = {}) {
44962
45144
  function resolvePortableSkillsRoot(options, migrate) {
44963
45145
  if (options.rootDir)
44964
45146
  return options.rootDir;
44965
- const appDir = options.homeDir ? join26(options.homeDir, ".hasna", "skills") : migrate ? getDataDir() : getDataDirReadOnly();
44966
- const cache = join26(appDir, SKILLS_CACHE_DIRNAME);
45147
+ const appDir = options.homeDir ? join27(options.homeDir, ".hasna", "skills") : migrate ? getDataDir() : getDataDirReadOnly();
45148
+ const cache = join27(appDir, SKILLS_CACHE_DIRNAME);
44967
45149
  if (isOwnerLayoutMigrated(appDir) && safeIsDirectory(cache))
44968
45150
  return cache;
44969
- const installed = join26(appDir, INSTALLED_SKILLS_DIRNAME);
45151
+ const installed = join27(appDir, INSTALLED_SKILLS_DIRNAME);
44970
45152
  return installed;
44971
45153
  }
44972
45154
  function getPortableSkillPath(name, options = {}) {
44973
- return join26(getPortableSkillsRoot(options), normalizePortableSkillName(name));
45155
+ return join27(getPortableSkillsRoot(options), normalizePortableSkillName(name));
44974
45156
  }
44975
45157
  function findPortableSkill(name, options = {}) {
44976
45158
  let normalized;
@@ -44980,7 +45162,7 @@ function findPortableSkill(name, options = {}) {
44980
45162
  return null;
44981
45163
  }
44982
45164
  const path = getPortableSkillPath(normalized, options);
44983
- if (!existsSync9(path) || !statSync9(path).isDirectory())
45165
+ if (!existsSync10(path) || !statSync9(path).isDirectory())
44984
45166
  return null;
44985
45167
  try {
44986
45168
  return summarizePortableSkill(path, normalized);
@@ -44996,7 +45178,7 @@ function listPortableSkills(options = {}) {
44996
45178
  for (const entry of readdirSync10(root2).sort()) {
44997
45179
  if (entry.startsWith("."))
44998
45180
  continue;
44999
- const path = join26(root2, entry);
45181
+ const path = join27(root2, entry);
45000
45182
  if (!safeIsDirectory(path))
45001
45183
  continue;
45002
45184
  try {
@@ -45030,11 +45212,11 @@ function isOfficialSkillName(name) {
45030
45212
  function scaffoldPortableSkill(name, options = {}) {
45031
45213
  const skillName = normalizeNewPortableSkillName(name);
45032
45214
  const readOnlyRoot = resolvePortableSkillsRoot(options, false);
45033
- assertPortableAuthoringPath(join26(readOnlyRoot, skillName), options);
45215
+ assertPortableAuthoringPath(join27(readOnlyRoot, skillName), options);
45034
45216
  const root2 = getPortableSkillsRoot(options);
45035
- const skillPath = join26(root2, skillName);
45217
+ const skillPath = join27(root2, skillName);
45036
45218
  assertPortableAuthoringPath(skillPath, options);
45037
- if (existsSync9(skillPath)) {
45219
+ if (existsSync10(skillPath)) {
45038
45220
  if (!options.overwrite)
45039
45221
  throw new Error(`Skill '${skillName}' already exists at ${skillPath}`);
45040
45222
  rmSync2(skillPath, { recursive: true, force: true });
@@ -45052,7 +45234,7 @@ function scaffoldPortableSkill(name, options = {}) {
45052
45234
  }
45053
45235
  function portPortableSkillDirectory(sourceDir, options = {}) {
45054
45236
  const absoluteSource = normalize4(sourceDir);
45055
- if (!existsSync9(absoluteSource) || !statSync9(absoluteSource).isDirectory()) {
45237
+ if (!existsSync10(absoluteSource) || !statSync9(absoluteSource).isDirectory()) {
45056
45238
  throw new Error(`Import directory not found: ${sourceDir}`);
45057
45239
  }
45058
45240
  const continueOnError = options.continueOnError ?? true;
@@ -45066,7 +45248,7 @@ function portPortableSkillDirectory(sourceDir, options = {}) {
45066
45248
  const skipped = [];
45067
45249
  const entries = readdirSync10(absoluteSource, { withFileTypes: true }).map((entry) => entry.name).filter((entryName) => !entryName.startsWith(".")).sort();
45068
45250
  for (const entryName of entries) {
45069
- const childPath = join26(absoluteSource, entryName);
45251
+ const childPath = join27(absoluteSource, entryName);
45070
45252
  if (!safeIsDirectory(childPath))
45071
45253
  continue;
45072
45254
  if (!isSkillCandidate(childPath)) {
@@ -45095,19 +45277,19 @@ function portPortableSkillDirectory(sourceDir, options = {}) {
45095
45277
  };
45096
45278
  }
45097
45279
  function isSkillCandidate(dir) {
45098
- return existsSync9(join26(dir, "SKILL.md")) || existsSync9(join26(dir, "skill.json")) || existsSync9(join26(dir, "package.json"));
45280
+ return existsSync10(join27(dir, "SKILL.md")) || existsSync10(join27(dir, "skill.json")) || existsSync10(join27(dir, "package.json"));
45099
45281
  }
45100
45282
  function physicalImportPath(path) {
45101
- let ancestor = resolve17(path);
45283
+ let ancestor = resolve18(path);
45102
45284
  const suffix = [];
45103
- while (!existsSync9(ancestor)) {
45285
+ while (!existsSync10(ancestor)) {
45104
45286
  suffix.unshift(basename10(ancestor));
45105
45287
  ancestor = dirname18(ancestor);
45106
45288
  }
45107
- return join26(realpathSync10(ancestor), ...suffix);
45289
+ return join27(realpathSync11(ancestor), ...suffix);
45108
45290
  }
45109
45291
  function assertDisjointImportPaths(source, destination) {
45110
- const sourcePath = realpathSync10(source);
45292
+ const sourcePath = realpathSync11(source);
45111
45293
  const destinationPath = physicalImportPath(destination);
45112
45294
  const contains2 = (parent, child) => {
45113
45295
  const path = relative6(parent, child);
@@ -45119,7 +45301,7 @@ function assertDisjointImportPaths(source, destination) {
45119
45301
  }
45120
45302
  function portPortableSkill(sourcePath, options = {}) {
45121
45303
  const absoluteSource = normalize4(sourcePath);
45122
- if (!existsSync9(absoluteSource) || !statSync9(absoluteSource).isDirectory()) {
45304
+ if (!existsSync10(absoluteSource) || !statSync9(absoluteSource).isDirectory()) {
45123
45305
  throw new Error(`Skill source directory not found: ${sourcePath}`);
45124
45306
  }
45125
45307
  const inferred = readPortableSkillManifestForImport(absoluteSource);
@@ -45130,14 +45312,14 @@ function portPortableSkill(sourcePath, options = {}) {
45130
45312
  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
45313
  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
45314
  }
45133
- const readOnlyDestination = join26(resolvePortableSkillsRoot(options, false), skillName);
45315
+ const readOnlyDestination = join27(resolvePortableSkillsRoot(options, false), skillName);
45134
45316
  assertPortableAuthoringPath(readOnlyDestination, options);
45135
45317
  assertDisjointImportPaths(absoluteSource, readOnlyDestination);
45136
45318
  const root2 = getPortableSkillsRoot(options);
45137
- const destination = join26(root2, skillName);
45319
+ const destination = join27(root2, skillName);
45138
45320
  assertPortableAuthoringPath(destination, options);
45139
45321
  assertDisjointImportPaths(absoluteSource, destination);
45140
- if (existsSync9(destination)) {
45322
+ if (existsSync10(destination)) {
45141
45323
  if (!options.overwrite)
45142
45324
  throw new Error(`Skill '${skillName}' already exists at ${destination}`);
45143
45325
  rmSync2(destination, { recursive: true, force: true });
@@ -45179,13 +45361,13 @@ function buildCorpusManifest(input, name) {
45179
45361
  function writeCorpusSkill(input, options = {}) {
45180
45362
  const name = normalizePortableSkillName(input.name);
45181
45363
  const readOnlyRoot = resolvePortableSkillsRoot(options, false);
45182
- assertPortableAuthoringPath(join26(readOnlyRoot, name), options);
45364
+ assertPortableAuthoringPath(join27(readOnlyRoot, name), options);
45183
45365
  const root2 = getPortableSkillsRoot(options);
45184
- const skillPath = join26(root2, name);
45366
+ const skillPath = join27(root2, name);
45185
45367
  assertPortableAuthoringPath(skillPath, options);
45186
- const created = !existsSync9(skillPath);
45368
+ const created = !existsSync10(skillPath);
45187
45369
  mkdirSync7(skillPath, { recursive: true });
45188
- writeFileSync6(join26(skillPath, "SKILL.md"), input.skillMd);
45370
+ writeFileSync6(join27(skillPath, "SKILL.md"), input.skillMd);
45189
45371
  const manifest = buildCorpusManifest(input, name);
45190
45372
  writeSkillJsonWithHash(skillPath, manifest);
45191
45373
  return { name, path: skillPath, manifest, created };
@@ -45193,22 +45375,22 @@ function writeCorpusSkill(input, options = {}) {
45193
45375
  function installCorpusSkillAtomically(input, options = {}) {
45194
45376
  const name = normalizePortableSkillName(input.name);
45195
45377
  const readOnlyRoot = resolvePortableSkillsRoot(options, false);
45196
- assertPortableAuthoringPath(join26(readOnlyRoot, name), options);
45378
+ assertPortableAuthoringPath(join27(readOnlyRoot, name), options);
45197
45379
  const root2 = getPortableSkillsRoot(options);
45198
- const target = join26(root2, name);
45380
+ const target = join27(root2, name);
45199
45381
  assertPortableAuthoringPath(target, options);
45200
- const created = !existsSync9(target);
45382
+ const created = !existsSync10(target);
45201
45383
  mkdirSync7(root2, { recursive: true });
45202
- const staging = mkdtempSync(join26(root2, `.pull-${name}-`));
45384
+ const staging = mkdtempSync(join27(root2, `.pull-${name}-`));
45203
45385
  let moved = false;
45204
45386
  let backup = null;
45205
45387
  try {
45206
- writeFileSync6(join26(staging, "SKILL.md"), input.skillMd);
45388
+ writeFileSync6(join27(staging, "SKILL.md"), input.skillMd);
45207
45389
  const manifest = buildCorpusManifest(input, name);
45208
45390
  writeSkillJsonWithHash(staging, manifest);
45209
- if (existsSync9(target)) {
45210
- backup = mkdtempSync(join26(root2, `.pull-backup-${name}-`));
45211
- renameSync4(target, join26(backup, name));
45391
+ if (existsSync10(target)) {
45392
+ backup = mkdtempSync(join27(root2, `.pull-backup-${name}-`));
45393
+ renameSync4(target, join27(backup, name));
45212
45394
  moved = true;
45213
45395
  }
45214
45396
  renameSync4(staging, target);
@@ -45217,9 +45399,9 @@ function installCorpusSkillAtomically(input, options = {}) {
45217
45399
  return { name, path: target, manifest, created };
45218
45400
  } catch (error) {
45219
45401
  rmSync2(staging, { recursive: true, force: true });
45220
- if (moved && backup && existsSync9(join26(backup, name))) {
45402
+ if (moved && backup && existsSync10(join27(backup, name))) {
45221
45403
  try {
45222
- renameSync4(join26(backup, name), target);
45404
+ renameSync4(join27(backup, name), target);
45223
45405
  } catch {}
45224
45406
  }
45225
45407
  throw error;
@@ -45231,10 +45413,10 @@ function validatePortableSkillDirectory(name, skillPath) {
45231
45413
  const issues = [...base.issues];
45232
45414
  const warnings = [...base.warnings];
45233
45415
  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)) {
45416
+ if (existsSync10(skillPath)) {
45417
+ const skillJsonPath = join27(skillPath, "skill.json");
45418
+ const skillMdPath = join27(skillPath, "SKILL.md");
45419
+ if (!existsSync10(skillJsonPath) && !existsSync10(skillMdPath)) {
45238
45420
  add3(issues, "portable.manifest_missing", "Missing portable manifest: expected SKILL.md frontmatter and/or skill.json");
45239
45421
  }
45240
45422
  try {
@@ -45253,7 +45435,7 @@ function validatePortableSkillDirectory(name, skillPath) {
45253
45435
  add3(issues, "portable.version_missing", "Portable manifest missing version");
45254
45436
  }
45255
45437
  const contractIssues = validatePortableManifestContract(manifest, {
45256
- strict: existsSync9(join26(skillPath, "skill.json")),
45438
+ strict: existsSync10(join27(skillPath, "skill.json")),
45257
45439
  skillPath
45258
45440
  });
45259
45441
  for (const issue of contractIssues)
@@ -45293,8 +45475,8 @@ function validatePortableSkillDirectory(name, skillPath) {
45293
45475
  add3(issues, "portable.command_entry_unsafe", `Command '${command.name}' entry '${command.entry}' must stay inside the skill directory`);
45294
45476
  continue;
45295
45477
  }
45296
- const entryPath = join26(skillPath, command.entry);
45297
- if (!existsSync9(entryPath))
45478
+ const entryPath = join27(skillPath, command.entry);
45479
+ if (!existsSync10(entryPath))
45298
45480
  add3(issues, "portable.command_entry_missing", `Command '${command.name}' entry '${command.entry}' is missing`);
45299
45481
  else if (statSync9(entryPath).isDirectory())
45300
45482
  add3(issues, "portable.command_entry_directory", `Command '${command.name}' entry '${command.entry}' must be a file`);
@@ -45304,7 +45486,7 @@ function validatePortableSkillDirectory(name, skillPath) {
45304
45486
  } catch (error) {
45305
45487
  add3(issues, "portable.manifest_invalid", error.message);
45306
45488
  }
45307
- if (manifest?.kind !== "instruction" && !existsSync9(join26(skillPath, "AGENTS.md"))) {
45489
+ if (manifest?.kind !== "instruction" && !existsSync10(join27(skillPath, "AGENTS.md"))) {
45308
45490
  add3(issues, "portable.agents_missing", "Missing AGENTS.md with build-out instructions for coding agents");
45309
45491
  }
45310
45492
  }
@@ -45340,13 +45522,13 @@ async function runPortableSkill(name, args, options = {}) {
45340
45522
  if (!isSafeRelativePath2(command.entry)) {
45341
45523
  return { exitCode: 1, error: `Portable skill '${name}' command entry is unsafe` };
45342
45524
  }
45343
- const entryPath = join26(skill.path, command.entry);
45344
- if (!existsSync9(entryPath)) {
45525
+ const entryPath = join27(skill.path, command.entry);
45526
+ if (!existsSync10(entryPath)) {
45345
45527
  return { exitCode: 1, error: `Entry point '${command.entry}' not found in portable skill '${name}'` };
45346
45528
  }
45347
- const pkgPath = join26(skill.path, "package.json");
45348
- const nodeModules = join26(skill.path, "node_modules");
45349
- if (existsSync9(pkgPath) && !existsSync9(nodeModules) && hasPackageDependencies(pkgPath)) {
45529
+ const pkgPath = join27(skill.path, "package.json");
45530
+ const nodeModules = join27(skill.path, "node_modules");
45531
+ if (existsSync10(pkgPath) && !existsSync10(nodeModules) && hasPackageDependencies(pkgPath)) {
45350
45532
  const install = Bun.spawn(["bun", "install", "--no-save"], {
45351
45533
  cwd: skill.path,
45352
45534
  stdout: "pipe",
@@ -45417,9 +45599,9 @@ function isSkillsOwnershipMarker(marker) {
45417
45599
  return typeof marker === "object" && marker !== null && Object.hasOwn(marker, "managedBy") && marker.managedBy === SYNC_MARKER_MANAGED_BY;
45418
45600
  }
45419
45601
  function hasSkillsOwnershipMarker(dir) {
45420
- const path = join27(dir, SYNC_MARKER_FILE);
45602
+ const path = join28(dir, SYNC_MARKER_FILE);
45421
45603
  try {
45422
- if (!lstatSync22(path).isFile())
45604
+ if (!lstatSync23(path).isFile())
45423
45605
  return false;
45424
45606
  const marker = JSON.parse(readFileSync17(path, "utf8"));
45425
45607
  return isSkillsOwnershipMarker(marker);
@@ -45441,9 +45623,9 @@ function resolveSyncAgents(arg) {
45441
45623
  function agentGlobalSkillsDir(agent, homeDir3 = homedir5()) {
45442
45624
  switch (agent) {
45443
45625
  case "opencode":
45444
- return join27(homeDir3, ".config", "opencode", "skills");
45626
+ return join28(homeDir3, ".config", "opencode", "skills");
45445
45627
  default:
45446
- return join27(homeDir3, `.${agent}`, "skills");
45628
+ return join28(homeDir3, `.${agent}`, "skills");
45447
45629
  }
45448
45630
  }
45449
45631
  function adaptSkillMdForAgent(skillMd, agent) {
@@ -45502,8 +45684,8 @@ function resolveSyncCorpus(options = {}) {
45502
45684
  function packageSourceRoots(source) {
45503
45685
  const roots = [];
45504
45686
  for (const sub of ["skills"]) {
45505
- const candidate2 = join27(source, sub);
45506
- if (existsSync10(candidate2) && isDirectory(candidate2))
45687
+ const candidate2 = join28(source, sub);
45688
+ if (existsSync11(candidate2) && isDirectory(candidate2))
45507
45689
  roots.push(candidate2);
45508
45690
  }
45509
45691
  if (roots.length > 0)
@@ -45518,10 +45700,10 @@ function containsSkillDirectories(path) {
45518
45700
  return false;
45519
45701
  }
45520
45702
  return entries.some((entry) => {
45521
- const candidate2 = join27(path, entry);
45703
+ const candidate2 = join28(path, entry);
45522
45704
  if (!isDirectory(candidate2))
45523
45705
  return false;
45524
- return existsSync10(join27(candidate2, "SKILL.md")) || existsSync10(join27(candidate2, "skill.json")) || existsSync10(join27(candidate2, "package.json"));
45706
+ return existsSync11(join28(candidate2, "SKILL.md")) || existsSync11(join28(candidate2, "skill.json")) || existsSync11(join28(candidate2, "package.json"));
45525
45707
  });
45526
45708
  }
45527
45709
  function isDirectory(path) {
@@ -45561,7 +45743,7 @@ function syncSkillsToAgents(options = {}) {
45561
45743
  actions.push({
45562
45744
  skill: name,
45563
45745
  agent,
45564
- path: join27(agentGlobalSkillsDir(agent, homeDir3), name, "SKILL.md"),
45746
+ path: join28(agentGlobalSkillsDir(agent, homeDir3), name, "SKILL.md"),
45565
45747
  action: "skip",
45566
45748
  reason: "not found in this machine's corpus"
45567
45749
  });
@@ -45591,7 +45773,7 @@ function syncSkillsToAgents(options = {}) {
45591
45773
  }
45592
45774
  function writeManagedAgentSkill(params) {
45593
45775
  const homeDir3 = params.homeDir ?? homedir5();
45594
- const dir = join27(agentGlobalSkillsDir(params.agent, homeDir3), params.skill);
45776
+ const dir = join28(agentGlobalSkillsDir(params.agent, homeDir3), params.skill);
45595
45777
  const result = writeManagedSkillDir(dir, params.skillMd, {
45596
45778
  skill: params.skill,
45597
45779
  source: params.source,
@@ -45608,11 +45790,11 @@ function writeManagedAgentSkill(params) {
45608
45790
  };
45609
45791
  }
45610
45792
  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);
45793
+ const skillMdPath = join28(dir, "SKILL.md");
45794
+ const markerPath = join28(dir, SYNC_MARKER_FILE);
45795
+ const dirExists = existsSync11(dir);
45614
45796
  const managed = hasSkillsOwnershipMarker(dir);
45615
- const hasSkillMd = existsSync10(skillMdPath);
45797
+ const hasSkillMd = existsSync11(skillMdPath);
45616
45798
  if (dirExists && !managed && !hasSkillMd) {
45617
45799
  return {
45618
45800
  action: "skip",
@@ -45624,7 +45806,7 @@ function writeManagedSkillDir(dir, skillMd, options) {
45624
45806
  return {
45625
45807
  action: "skip",
45626
45808
  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"
45809
+ 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
45810
  };
45629
45811
  }
45630
45812
  if (dirExists && managed && hasSkillMd && !options.force && isPointerSkillMd(skillMd)) {
@@ -45647,11 +45829,11 @@ function writeManagedSkillDir(dir, skillMd, options) {
45647
45829
  return { action, path: skillMdPath };
45648
45830
  const parentDir = dirname19(dir);
45649
45831
  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);
45832
+ const transactionDir = mkdtempSync2(join28(parentDir, `.hasna-skills-write-${basename11(dir)}-`));
45833
+ const candidateDir = join28(transactionDir, "candidate");
45834
+ const backupDir = join28(transactionDir, "backup");
45835
+ const candidateSkillMdPath = join28(candidateDir, "SKILL.md");
45836
+ const candidateMarkerPath = join28(candidateDir, SYNC_MARKER_FILE);
45655
45837
  const marker = {
45656
45838
  managedBy: SYNC_MARKER_MANAGED_BY,
45657
45839
  skill: options.skill,
@@ -45678,9 +45860,9 @@ function writeManagedSkillDir(dir, skillMd, options) {
45678
45860
  }
45679
45861
  renameDirectory(candidateDir, dir);
45680
45862
  } catch (error) {
45681
- if (originalMoved && existsSync10(backupDir)) {
45863
+ if (originalMoved && existsSync11(backupDir)) {
45682
45864
  try {
45683
- if (existsSync10(dir))
45865
+ if (existsSync11(dir))
45684
45866
  rmSync3(dir, { recursive: true, force: true });
45685
45867
  renameDirectory(backupDir, dir);
45686
45868
  originalMoved = false;
@@ -45700,7 +45882,7 @@ function writeManagedSkillDir(dir, skillMd, options) {
45700
45882
  return { action, path: skillMdPath };
45701
45883
  }
45702
45884
  function removeManagedAgentSkill(skill, agent, homeDir3 = homedir5()) {
45703
- const dir = join27(agentGlobalSkillsDir(agent, homeDir3), skill);
45885
+ const dir = join28(agentGlobalSkillsDir(agent, homeDir3), skill);
45704
45886
  if (!hasSkillsOwnershipMarker(dir))
45705
45887
  return false;
45706
45888
  rmSync3(dir, { recursive: true, force: true });
@@ -45708,8 +45890,8 @@ function removeManagedAgentSkill(skill, agent, homeDir3 = homedir5()) {
45708
45890
  }
45709
45891
  function sourceSkillMd(skillPath, name, description, kind, preferBundledDocs = false) {
45710
45892
  if (kind === undefined || kind === "instruction" || preferBundledDocs) {
45711
- const skillMdPath = join27(skillPath, "SKILL.md");
45712
- if (existsSync10(skillMdPath))
45893
+ const skillMdPath = join28(skillPath, "SKILL.md");
45894
+ if (existsSync11(skillMdPath))
45713
45895
  return readFileSync17(skillMdPath, "utf-8");
45714
45896
  }
45715
45897
  return pointerSkillMd(name, description);
@@ -45740,8 +45922,8 @@ function normalizeSkillName(name) {
45740
45922
  }
45741
45923
 
45742
45924
  // src/lib/registry.ts
45743
- import { existsSync as existsSync11, readFileSync as readFileSync18, readdirSync as readdirSync12 } from "fs";
45744
- import { join as join28 } from "path";
45925
+ import { existsSync as existsSync12, readFileSync as readFileSync18, readdirSync as readdirSync12 } from "fs";
45926
+ import { join as join29 } from "path";
45745
45927
 
45746
45928
  // src/lib/registry-merge.ts
45747
45929
  var SKILL_SOURCE_PRECEDENCE = {
@@ -45943,7 +46125,7 @@ function parseSkillMdFrontmatter(content) {
45943
46125
  return Object.keys(result).length > 0 ? result : null;
45944
46126
  }
45945
46127
  function discoverSkillsInDir(dir, source = "custom") {
45946
- if (!existsSync11(dir))
46128
+ if (!existsSync12(dir))
45947
46129
  return [];
45948
46130
  const result = [];
45949
46131
  try {
@@ -45951,8 +46133,8 @@ function discoverSkillsInDir(dir, source = "custom") {
45951
46133
  for (const entry of entries) {
45952
46134
  if (!entry.isDirectory())
45953
46135
  continue;
45954
- const skillMdPath = join28(dir, entry.name, "SKILL.md");
45955
- if (!existsSync11(skillMdPath))
46136
+ const skillMdPath = join29(dir, entry.name, "SKILL.md");
46137
+ if (!existsSync12(skillMdPath))
45956
46138
  continue;
45957
46139
  let content;
45958
46140
  try {
@@ -45971,7 +46153,7 @@ function discoverSkillsInDir(dir, source = "custom") {
45971
46153
  category: fm.category || "Development Tools",
45972
46154
  tags: fm.tags || [],
45973
46155
  ...fm.kind ? { kind: fm.kind } : {},
45974
- ...isHostedMetadataSkillDir(join28(dir, entry.name)) ? { serverOwned: true } : {},
46156
+ ...isHostedMetadataSkillDir(join29(dir, entry.name)) ? { serverOwned: true } : {},
45975
46157
  source
45976
46158
  });
45977
46159
  }
@@ -45980,16 +46162,16 @@ function discoverSkillsInDir(dir, source = "custom") {
45980
46162
  }
45981
46163
  function findExtensionSkillPath(name) {
45982
46164
  const config = loadConfig();
45983
- if (!config.extensionsDir || !existsSync11(config.extensionsDir))
46165
+ if (!config.extensionsDir || !existsSync12(config.extensionsDir))
45984
46166
  return null;
45985
46167
  try {
45986
46168
  const entries = readdirSync12(config.extensionsDir, { withFileTypes: true });
45987
46169
  for (const entry of entries) {
45988
46170
  if (!entry.isDirectory())
45989
46171
  continue;
45990
- const skillDir = join28(config.extensionsDir, entry.name);
45991
- const skillMdPath = join28(skillDir, "SKILL.md");
45992
- if (!existsSync11(skillMdPath))
46172
+ const skillDir = join29(config.extensionsDir, entry.name);
46173
+ const skillMdPath = join29(skillDir, "SKILL.md");
46174
+ if (!existsSync12(skillMdPath))
45993
46175
  continue;
45994
46176
  let content;
45995
46177
  try {
@@ -46036,21 +46218,21 @@ function clearRegistryCache() {
46036
46218
  registryCacheTime = 0;
46037
46219
  registryCacheKey = null;
46038
46220
  }
46039
- function getSkillsByCategory(category) {
46040
- return loadRegistry().filter((s) => s.category === category);
46221
+ function getSkillsByCategory(category, catalog) {
46222
+ return (catalog ?? loadRegistry()).filter((s) => s.category === category);
46041
46223
  }
46042
46224
  function getSkill(name) {
46043
46225
  const registry = loadRegistry();
46044
46226
  const slug = normalizeSkillSlug(name);
46045
46227
  return registry.find((s) => s.name === slug) ?? registry.find((s) => s.name === resolveSkillAlias(slug));
46046
46228
  }
46047
- function getSkillsByTag(tag) {
46229
+ function getSkillsByTag(tag, catalog) {
46048
46230
  const needle = tag.toLowerCase();
46049
- return loadRegistry().filter((s) => s.tags.some((t2) => t2.toLowerCase().includes(needle)));
46231
+ return (catalog ?? loadRegistry()).filter((s) => s.tags.some((t2) => t2.toLowerCase().includes(needle)));
46050
46232
  }
46051
- function getAllTags() {
46233
+ function getAllTags(catalog) {
46052
46234
  const tagSet = new Set;
46053
- for (const skill of loadRegistry()) {
46235
+ for (const skill of catalog ?? loadRegistry()) {
46054
46236
  for (const tag of skill.tags)
46055
46237
  tagSet.add(tag.toLowerCase());
46056
46238
  }
@@ -46058,8 +46240,8 @@ function getAllTags() {
46058
46240
  }
46059
46241
 
46060
46242
  // 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";
46243
+ import { existsSync as existsSync13, mkdirSync as mkdirSync9, readFileSync as readFileSync19, writeFileSync as writeFileSync8 } from "fs";
46244
+ import { join as join30 } from "path";
46063
46245
  var VALID_PIN_SOURCES = [
46064
46246
  "official",
46065
46247
  "custom",
@@ -46074,14 +46256,14 @@ var SKILLS_PROJECT_DIR = ".skills";
46074
46256
  var PROJECT_CONFIG_FILE = "project.json";
46075
46257
  var DEFAULT_EXPORT_DIR = ".skills/exports";
46076
46258
  function getProjectStateDir(targetDir = process.cwd()) {
46077
- return join29(targetDir, SKILLS_PROJECT_DIR);
46259
+ return join30(targetDir, SKILLS_PROJECT_DIR);
46078
46260
  }
46079
46261
  function getProjectConfigPath(targetDir = process.cwd()) {
46080
- return join29(getProjectStateDir(targetDir), PROJECT_CONFIG_FILE);
46262
+ return join30(getProjectStateDir(targetDir), PROJECT_CONFIG_FILE);
46081
46263
  }
46082
46264
  function loadProjectConfig(targetDir = process.cwd()) {
46083
46265
  const path = getProjectConfigPath(targetDir);
46084
- if (!existsSync12(path))
46266
+ if (!existsSync13(path))
46085
46267
  return null;
46086
46268
  try {
46087
46269
  return normalizeProjectConfig(JSON.parse(readFileSync19(path, "utf-8")));
@@ -46206,19 +46388,19 @@ function getSkillPath(name) {
46206
46388
  const extensionPath = findExtensionSkillPath(skillName);
46207
46389
  if (extensionPath)
46208
46390
  return extensionPath;
46209
- return join30(getPortableSkillsRoot(), skillName);
46391
+ return join31(getPortableSkillsRoot(), skillName);
46210
46392
  }
46211
46393
  function getCanonicalSkillName(name) {
46212
46394
  return getSkill(name)?.name ?? resolveSkillAlias(normalizeSkillSlug(name));
46213
46395
  }
46214
46396
  function skillExists(name) {
46215
- return existsSync13(getSkillPath(name));
46397
+ return existsSync14(getSkillPath(name));
46216
46398
  }
46217
46399
  function installSkill(name, options = {}) {
46218
46400
  const { targetDir = process.cwd(), overwrite = false } = options;
46219
46401
  const canonicalName = getCanonicalSkillName(name);
46220
46402
  const skillName = normalizeSkillName(canonicalName);
46221
- if (!existsSync13(getSkillPath(name))) {
46403
+ if (!existsSync14(getSkillPath(name))) {
46222
46404
  const knownOfficial = Boolean(getSkill(name));
46223
46405
  return {
46224
46406
  skill: canonicalName,
@@ -46245,7 +46427,7 @@ function installSkill(name, options = {}) {
46245
46427
  }
46246
46428
  function installSkillSource(name, _options = {}) {
46247
46429
  const canonicalName = getCanonicalSkillName(name);
46248
- if (!existsSync13(getSkillPath(name))) {
46430
+ if (!existsSync14(getSkillPath(name))) {
46249
46431
  return { skill: canonicalName, success: false, error: `Skill '${name}' not found`, mode: "source" };
46250
46432
  }
46251
46433
  return {
@@ -46266,11 +46448,11 @@ function installSkillManifest(manifest, _options = {}) {
46266
46448
  }
46267
46449
  function createLocalSkillManifest(name, generateSkillMd) {
46268
46450
  const sourcePath = getSkillPath(name);
46269
- if (!existsSync13(sourcePath))
46451
+ if (!existsSync14(sourcePath))
46270
46452
  return null;
46271
46453
  let skillMd = "";
46272
- const skillMdPath = join30(sourcePath, "SKILL.md");
46273
- if (existsSync13(skillMdPath)) {
46454
+ const skillMdPath = join31(sourcePath, "SKILL.md");
46455
+ if (existsSync14(skillMdPath)) {
46274
46456
  skillMd = readFileSync20(skillMdPath, "utf-8");
46275
46457
  } else if (generateSkillMd) {
46276
46458
  skillMd = generateSkillMd(name) ?? "";
@@ -46343,21 +46525,21 @@ function getAgentSkillsDir(agent, scope = "global", projectDir) {
46343
46525
  const base = projectDir || process.cwd();
46344
46526
  switch (agent) {
46345
46527
  case "pi":
46346
- return scope === "project" ? join30(base, ".pi", "skills") : join30(homedir6(), ".pi", "agent", "skills");
46528
+ return scope === "project" ? join31(base, ".pi", "skills") : join31(homedir6(), ".pi", "agent", "skills");
46347
46529
  case "opencode":
46348
- return scope === "project" ? join30(base, ".opencode", "skills") : join30(homedir6(), ".config", "opencode", "skills");
46530
+ return scope === "project" ? join31(base, ".opencode", "skills") : join31(homedir6(), ".config", "opencode", "skills");
46349
46531
  default:
46350
- return scope === "project" ? join30(base, `.${agent}`, "skills") : join30(homedir6(), `.${agent}`, "skills");
46532
+ return scope === "project" ? join31(base, `.${agent}`, "skills") : join31(homedir6(), `.${agent}`, "skills");
46351
46533
  }
46352
46534
  }
46353
46535
  function getAgentSkillPath(name, agent, scope = "global", projectDir) {
46354
46536
  const skillName = normalizeSkillName(getCanonicalSkillName(name));
46355
- return join30(getAgentSkillsDir(agent, scope, projectDir), skillName);
46537
+ return join31(getAgentSkillsDir(agent, scope, projectDir), skillName);
46356
46538
  }
46357
46539
  function installSkillForAgent(name, options, generateSkillMd) {
46358
46540
  assertNativeExportAllowed();
46359
46541
  const canonicalName = getCanonicalSkillName(name);
46360
- if (!existsSync13(getSkillPath(name))) {
46542
+ if (!existsSync14(getSkillPath(name))) {
46361
46543
  return { skill: canonicalName, success: false, error: `Skill '${name}' not found` };
46362
46544
  }
46363
46545
  const scope = options.scope ?? "global";
@@ -46388,8 +46570,8 @@ function removeSkillForAgent(name, options) {
46388
46570
  }
46389
46571
  function resolveAgentSkillMd(name, generateSkillMd) {
46390
46572
  const sourcePath = getSkillPath(name);
46391
- const skillMdPath = join30(sourcePath, "SKILL.md");
46392
- if (existsSync13(skillMdPath))
46573
+ const skillMdPath = join31(sourcePath, "SKILL.md");
46574
+ if (existsSync14(skillMdPath))
46393
46575
  return readFileSync20(skillMdPath, "utf-8");
46394
46576
  if (generateSkillMd)
46395
46577
  return generateSkillMd(name);
@@ -46408,7 +46590,7 @@ function warnMissingDependencies(name, targetDir) {
46408
46590
  }
46409
46591
  function generateMinimalSkillMd(name) {
46410
46592
  const sourcePath = getSkillPath(name);
46411
- if (!existsSync13(sourcePath))
46593
+ if (!existsSync14(sourcePath))
46412
46594
  return null;
46413
46595
  const canonicalName = getCanonicalSkillName(name);
46414
46596
  const meta = getSkill(canonicalName);
@@ -46423,7 +46605,7 @@ function generateMinimalSkillMd(name) {
46423
46605
  "---",
46424
46606
  ""
46425
46607
  ].filter(Boolean);
46426
- const fallbackDoc = readFileIfExists(join30(sourcePath, "README.md")) || readFileIfExists(join30(sourcePath, "CLAUDE.md"));
46608
+ const fallbackDoc = readFileIfExists(join31(sourcePath, "README.md")) || readFileIfExists(join31(sourcePath, "CLAUDE.md"));
46427
46609
  if (fallbackDoc)
46428
46610
  return `${frontmatter.join(`
46429
46611
  `)}${fallbackDoc.trim()}
@@ -46442,8 +46624,8 @@ skills run ${canonicalName}
46442
46624
  `;
46443
46625
  }
46444
46626
  function readBundledSkillVersion(name) {
46445
- const pkgPath = join30(getSkillPath(name), "package.json");
46446
- if (!existsSync13(pkgPath))
46627
+ const pkgPath = join31(getSkillPath(name), "package.json");
46628
+ if (!existsSync14(pkgPath))
46447
46629
  return "unknown";
46448
46630
  try {
46449
46631
  const pkg = JSON.parse(readFileSync20(pkgPath, "utf-8"));
@@ -46453,7 +46635,7 @@ function readBundledSkillVersion(name) {
46453
46635
  }
46454
46636
  }
46455
46637
  function readFileIfExists(path) {
46456
- return existsSync13(path) ? readFileSync20(path, "utf-8") : null;
46638
+ return existsSync14(path) ? readFileSync20(path, "utf-8") : null;
46457
46639
  }
46458
46640
  function loadProjectConfigCompat(targetDir) {
46459
46641
  return loadProjectConfig(targetDir);
@@ -46497,8 +46679,8 @@ function selectSkillDoc(docs, file) {
46497
46679
  function isInstructionSkillDir(skillPath, meta) {
46498
46680
  if (meta?.kind === "instruction")
46499
46681
  return true;
46500
- const skillMdPath = join31(skillPath, "SKILL.md");
46501
- if (!existsSync14(skillMdPath))
46682
+ const skillMdPath = join32(skillPath, "SKILL.md");
46683
+ if (!existsSync15(skillMdPath))
46502
46684
  return false;
46503
46685
  try {
46504
46686
  return parseSkillFrontmatter(readFileSync21(skillMdPath, "utf-8"))?.kind === "instruction";
@@ -46524,12 +46706,12 @@ var HOSTED_PROVIDER_ENV_PREFIXES = [
46524
46706
  ];
46525
46707
  function getSkillDocs(name) {
46526
46708
  const skillPath = getSkillPath(name);
46527
- if (!existsSync14(skillPath))
46709
+ if (!existsSync15(skillPath))
46528
46710
  return null;
46529
46711
  return {
46530
- skillMd: readIfExists(join31(skillPath, "SKILL.md")),
46531
- readme: readIfExists(join31(skillPath, "README.md")),
46532
- claudeMd: readIfExists(join31(skillPath, "CLAUDE.md"))
46712
+ skillMd: readIfExists(join32(skillPath, "SKILL.md")),
46713
+ readme: readIfExists(join32(skillPath, "README.md")),
46714
+ claudeMd: readIfExists(join32(skillPath, "CLAUDE.md"))
46533
46715
  };
46534
46716
  }
46535
46717
  function getSkillBestDoc(name, file) {
@@ -46541,18 +46723,18 @@ function getSkillBestDoc(name, file) {
46541
46723
  }
46542
46724
  function getSkillRequirements(name) {
46543
46725
  const skillPath = getSkillPath(name);
46544
- if (!existsSync14(skillPath))
46726
+ if (!existsSync15(skillPath))
46545
46727
  return null;
46546
46728
  const texts = [];
46547
46729
  for (const file of ["SKILL.md", "README.md", "CLAUDE.md", ".env.example", ".env.local.example"]) {
46548
- const content = readIfExists(join31(skillPath, file));
46730
+ const content = readIfExists(join32(skillPath, file));
46549
46731
  if (content)
46550
46732
  texts.push(content);
46551
46733
  }
46552
46734
  const meta = getSkill(name);
46553
46735
  let dependencies = {};
46554
46736
  try {
46555
- dependencies = JSON.parse(readFileSync21(join31(skillPath, "package.json"), "utf8")).dependencies || {};
46737
+ dependencies = JSON.parse(readFileSync21(join32(skillPath, "package.json"), "utf8")).dependencies || {};
46556
46738
  } catch {}
46557
46739
  return getSkillRequirementsFromContent(name, texts, dependencies, meta);
46558
46740
  }
@@ -46605,7 +46787,7 @@ async function runSkill(name, args, options = {}) {
46605
46787
  const meta = getSkill(name);
46606
46788
  const canonicalName = meta?.name ?? name;
46607
46789
  const skillPath = getSkillPath(canonicalName);
46608
- if (!existsSync14(skillPath)) {
46790
+ if (!existsSync15(skillPath)) {
46609
46791
  return { exitCode: 1, error: `Skill '${name}' not found` };
46610
46792
  }
46611
46793
  if (isInstructionSkillDir(skillPath, meta)) {
@@ -46614,8 +46796,8 @@ async function runSkill(name, args, options = {}) {
46614
46796
  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
46797
  };
46616
46798
  }
46617
- const pkgPath = join31(skillPath, "package.json");
46618
- if (!existsSync14(pkgPath)) {
46799
+ const pkgPath = join32(skillPath, "package.json");
46800
+ if (!existsSync15(pkgPath)) {
46619
46801
  return { exitCode: 1, error: `No package.json in skill '${name}'` };
46620
46802
  }
46621
46803
  let entryPoint2;
@@ -46634,12 +46816,12 @@ async function runSkill(name, args, options = {}) {
46634
46816
  } catch {
46635
46817
  return { exitCode: 1, error: `Failed to parse package.json for skill '${name}'` };
46636
46818
  }
46637
- const entryPath = join31(skillPath, entryPoint2);
46638
- if (!existsSync14(entryPath)) {
46819
+ const entryPath = join32(skillPath, entryPoint2);
46820
+ if (!existsSync15(entryPath)) {
46639
46821
  return { exitCode: 1, error: `Entry point '${entryPoint2}' not found in skill '${name}'` };
46640
46822
  }
46641
46823
  const env = { ...process.env, ...options.env };
46642
- if (!existsSync14(join31(skillPath, "node_modules")) || hasDependencyPreparationMarker(skillPath)) {
46824
+ if (!existsSync15(join32(skillPath, "node_modules")) || hasDependencyPreparationMarker(skillPath)) {
46643
46825
  const failure = await prepareSkillDependencies(skillPath, env, options.preparationTimeoutMs);
46644
46826
  if (failure)
46645
46827
  return failure;
@@ -46708,7 +46890,7 @@ function generateSkillMd(name) {
46708
46890
  if (!meta)
46709
46891
  return null;
46710
46892
  const skillPath = getSkillPath(name);
46711
- if (!existsSync14(skillPath))
46893
+ if (!existsSync15(skillPath))
46712
46894
  return null;
46713
46895
  const frontmatter = [
46714
46896
  "---",
@@ -46717,11 +46899,11 @@ function generateSkillMd(name) {
46717
46899
  "---"
46718
46900
  ].join(`
46719
46901
  `);
46720
- const readme = readIfExists(join31(skillPath, "README.md"));
46721
- const claudeMd = readIfExists(join31(skillPath, "CLAUDE.md"));
46902
+ const readme = readIfExists(join32(skillPath, "README.md"));
46903
+ const claudeMd = readIfExists(join32(skillPath, "CLAUDE.md"));
46722
46904
  let cliCommand = null;
46723
- const pkgPath = join31(skillPath, "package.json");
46724
- if (existsSync14(pkgPath)) {
46905
+ const pkgPath = join32(skillPath, "package.json");
46906
+ if (existsSync15(pkgPath)) {
46725
46907
  try {
46726
46908
  const pkg = JSON.parse(readFileSync21(pkgPath, "utf-8"));
46727
46909
  if (pkg.bin) {
@@ -46798,7 +46980,7 @@ function extractEnvVars(text2) {
46798
46980
  }
46799
46981
  function readIfExists(path) {
46800
46982
  try {
46801
- if (existsSync14(path)) {
46983
+ if (existsSync15(path)) {
46802
46984
  return readFileSync21(path, "utf-8");
46803
46985
  }
46804
46986
  } catch {}
@@ -46865,6 +47047,8 @@ async function syncSelectionProfile(profileId, options = {}) {
46865
47047
  async function resolveSelectionContext(profileId, options = {}) {
46866
47048
  const sessionState = options.sessionId ? readSkillSessionSnapshotIfExists(options.sessionId, options) : null;
46867
47049
  const session = sessionState?.receipt ?? null;
47050
+ if (options.nativeParentSessionId !== undefined && session && (session.parent?.sessionId ?? null) !== options.nativeParentSessionId)
47051
+ throw new SkillSelectionError("SESSION_PARENT_MISMATCH", "The native session id is already bound to different parent custody.");
46868
47052
  const parentState = !session && options.parentSessionId ? readSkillSessionSnapshotIfExists(options.parentSessionId, options) : null;
46869
47053
  if (!session && options.parentSessionId && !parentState) {
46870
47054
  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 +47186,7 @@ async function executeSelectedLocal(selected, options = {}) {
47002
47186
  throw new SkillSelectionError("INVALID_SECRET_BINDINGS", "Explicit environment values must be bounded strings without NUL bytes.");
47003
47187
  secretEnv[name] = value;
47004
47188
  }
47005
- const runDirectory = mkdtempSync3(join32(tmpdir(), "skills-execution-"));
47189
+ const runDirectory = mkdtempSync3(join33(tmpdir(), "skills-execution-"));
47006
47190
  const paths = new SkillEntryPaths;
47007
47191
  for (const entry of entries) {
47008
47192
  paths.add(entry.path, 100, () => {
@@ -47010,12 +47194,12 @@ async function executeSelectedLocal(selected, options = {}) {
47010
47194
  }, () => {
47011
47195
  throw new SkillSelectionError("INVALID_BUNDLE_PATH", "The execution bundle path exceeds its limit.");
47012
47196
  });
47013
- const destination = join32(runDirectory, entry.path);
47197
+ const destination = join33(runDirectory, entry.path);
47014
47198
  mkdirSync10(dirname20(destination), { recursive: true, mode: 448 });
47015
47199
  writeFileSync9(destination, entry.bytes, { flag: "wx", mode: entry.mode & 511 });
47016
47200
  }
47017
47201
  env.SKILLS_INPUT_JSON = input;
47018
- env.SKILLS_WORKSPACE_DIR = resolve18(options.cwd ?? process.cwd());
47202
+ env.SKILLS_WORKSPACE_DIR = resolve19(options.cwd ?? process.cwd());
47019
47203
  env.SKILLS_RUN_DIR = runDirectory;
47020
47204
  if (runtime.version) {
47021
47205
  const version = await subprocess([executable, ...runtimeName === "bun" ? ["--no-env-file"] : [], "--version"], runDirectory, env, "", Math.min(timeoutMs, 5000));
@@ -47028,7 +47212,7 @@ async function executeSelectedLocal(selected, options = {}) {
47028
47212
  const { authority: authority2, workspaceId, profileRevision, slug, version, bundleDigest } = selection2;
47029
47213
  const request2 = {
47030
47214
  selection: { authority: authority2, workspaceId, profileId, profileRevision, slug, version, bundleDigest },
47031
- consumer: { stationId: process.env.HASNA_STATION || stationHostname2(), workspaceDirectory: realpathSync11(options.cwd ?? process.cwd()) }
47215
+ consumer: { stationId: process.env.HASNA_STATION || stationHostname2(), workspaceDirectory: realpathSync12(options.cwd ?? process.cwd()) }
47032
47216
  };
47033
47217
  const grant = await (options.resolveExecutionGrant ?? resolveExecutionGrant)(request2);
47034
47218
  if (!grant || !grantIdentifier(grant.policyRevision) || !grantIdentifier(grant.grantId))
@@ -47038,7 +47222,7 @@ async function executeSelectedLocal(selected, options = {}) {
47038
47222
  }
47039
47223
  if (bindings)
47040
47224
  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);
47225
+ const result = await subprocess([executable, ...runtimeName === "bun" ? ["--no-env-file"] : [], join33(runDirectory, declaredEntry), ...args], runDirectory, { ...env, ...secretEnv }, input, timeoutMs);
47042
47226
  result.stdout = redactExecutionSecrets(result.stdout, secretEnv);
47043
47227
  result.stderr = redactExecutionSecrets(result.stderr, secretEnv);
47044
47228
  const receipt = {
@@ -47051,7 +47235,7 @@ async function executeSelectedLocal(selected, options = {}) {
47051
47235
  ...bindings ? { secretBinding: { schema: bindings.schema, selection: bindings.selection, consumer: bindings.consumer, secretsAuthority: bindings.secretsAuthority, bindings: bindings.bindings } } : {},
47052
47236
  ...result
47053
47237
  };
47054
- writeFileSync9(join32(runDirectory, ".execution-receipt.json"), JSON.stringify({ ...receipt, stdout: undefined, stderr: undefined }), { mode: 384 });
47238
+ writeFileSync9(join33(runDirectory, ".execution-receipt.json"), JSON.stringify({ ...receipt, stdout: undefined, stderr: undefined }), { mode: 384 });
47055
47239
  return receipt;
47056
47240
  }
47057
47241
  async function subprocess(command, cwd, env, input, timeoutMs) {
@@ -57116,7 +57300,7 @@ import { mkdirSync as mkdirSync12 } from "fs";
57116
57300
  import { dirname as dirname24 } from "path";
57117
57301
 
57118
57302
  // src/server/database-url.ts
57119
- import { isAbsolute as isAbsolute19, join as join34 } from "path";
57303
+ import { isAbsolute as isAbsolute19, join as join35 } from "path";
57120
57304
  import { fileURLToPath as fileURLToPath3 } from "url";
57121
57305
  var DEFAULT_SQLITE_FILENAME2 = "server.db";
57122
57306
  var SQLITE_MEMORY_PATH = ":memory:";
@@ -57125,7 +57309,7 @@ var SQLITE_SCHEMES = new Set(["sqlite", "sqlite3", "file"]);
57125
57309
  var MEMORY_SCHEMES = new Set(["memory"]);
57126
57310
  var SQLITE_EXTENSIONS = [".db", ".sqlite", ".sqlite3", ".db3"];
57127
57311
  function defaultSqlitePath() {
57128
- return join34(getDataDir(), DEFAULT_SQLITE_FILENAME2);
57312
+ return join35(getDataDir(), DEFAULT_SQLITE_FILENAME2);
57129
57313
  }
57130
57314
  function resolveDatabaseTarget(raw) {
57131
57315
  const value = raw?.trim();
@@ -57152,7 +57336,7 @@ function resolveDatabaseTarget(raw) {
57152
57336
  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
57337
  }
57154
57338
  if (looksLikeSqlitePath(value)) {
57155
- const path = isAbsolute19(value) ? value : join34(process.cwd(), value);
57339
+ const path = isAbsolute19(value) ? value : join35(process.cwd(), value);
57156
57340
  return { kind: "sqlite", path, durable: true, label: `sqlite (${path})` };
57157
57341
  }
57158
57342
  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 +57360,7 @@ function sqlitePathFromUrl(value, scheme) {
57176
57360
  }
57177
57361
  return rest.slice(2).replace(/^\/\/+/, "/");
57178
57362
  }
57179
- return isAbsolute19(rest) ? rest : join34(process.cwd(), rest);
57363
+ return isAbsolute19(rest) ? rest : join35(process.cwd(), rest);
57180
57364
  }
57181
57365
  function looksLikeSqlitePath(value) {
57182
57366
  if (value.includes("/"))
@@ -57409,7 +57593,7 @@ class PostgresSkillSelectionStore {
57409
57593
  // src/server/sqlite-store.ts
57410
57594
  import { randomUUID as randomUUID7 } from "crypto";
57411
57595
  import { mkdirSync as mkdirSync11, readFileSync as readFileSync23, readdirSync as readdirSync13 } from "fs";
57412
- import { dirname as dirname23, join as join36 } from "path";
57596
+ import { dirname as dirname23, join as join37 } from "path";
57413
57597
 
57414
57598
  // src/server/auth.ts
57415
57599
  import { createHash as createHash23 } from "crypto";
@@ -57467,16 +57651,16 @@ function permitsSkillsRoute(principal, method, resource) {
57467
57651
  }
57468
57652
 
57469
57653
  // src/server/migrations-dir.ts
57470
- import { existsSync as existsSync15 } from "fs";
57471
- import { dirname as dirname22, join as join35 } from "path";
57654
+ import { existsSync as existsSync16 } from "fs";
57655
+ import { dirname as dirname22, join as join36 } from "path";
57472
57656
  var MIGRATION_DIALECTS = ["postgres", "sqlite"];
57473
57657
  var MAX_WALK_UP = 6;
57474
57658
  function findMigrationsRoot(startDirs = defaultStartDirs()) {
57475
57659
  for (const start of startDirs) {
57476
57660
  let dir = start;
57477
57661
  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))))
57662
+ const candidate2 = join36(dir, "migrations");
57663
+ if (MIGRATION_DIALECTS.some((dialect) => existsSync16(join36(candidate2, dialect))))
57480
57664
  return candidate2;
57481
57665
  const parent = dirname22(dir);
57482
57666
  if (parent === dir)
@@ -57490,8 +57674,8 @@ function resolveMigrationsDir(dialect, root4 = findMigrationsRoot()) {
57490
57674
  if (!root4) {
57491
57675
  throw new Error(`could not locate the migrations directory for dialect "${dialect}". ` + `Expected a migrations/${dialect}/ folder alongside the package root.`);
57492
57676
  }
57493
- const dir = join35(root4, dialect);
57494
- if (!existsSync15(dir)) {
57677
+ const dir = join36(root4, dialect);
57678
+ if (!existsSync16(dir)) {
57495
57679
  throw new Error(`migrations directory not found: ${dir}`);
57496
57680
  }
57497
57681
  return dir;
@@ -58462,7 +58646,7 @@ function applySqliteMigrations(db, migrationsDir = resolveMigrationsDir("sqlite"
58462
58646
  const appliedNow = [];
58463
58647
  for (const file of files) {
58464
58648
  const version2 = file.replace(/\.sql$/, "");
58465
- const text2 = readFileSync23(join36(migrationsDir, file), "utf8");
58649
+ const text2 = readFileSync23(join37(migrationsDir, file), "utf8");
58466
58650
  const apply = db.transaction(() => {
58467
58651
  const already = db.query("SELECT 1 AS present FROM schema_migrations WHERE version = ? LIMIT 1").get(version2);
58468
58652
  if (already)
@@ -90719,10 +90903,10 @@ async function readQuoteUnavailableCode(response) {
90719
90903
  let timer;
90720
90904
  let deadlineExceeded = false;
90721
90905
  const expired = Symbol("quote body deadline");
90722
- const deadline = new Promise((resolve20) => {
90906
+ const deadline = new Promise((resolve21) => {
90723
90907
  timer = setTimeout(() => {
90724
90908
  deadlineExceeded = true;
90725
- resolve20(expired);
90909
+ resolve21(expired);
90726
90910
  reader.cancel().catch(() => {});
90727
90911
  }, 1500);
90728
90912
  });
@@ -92208,12 +92392,12 @@ class RemotePrivatePublicationsClient {
92208
92392
  previous = view;
92209
92393
  if (!["queued", "verifying"].includes(view.state) || Date.now() >= until)
92210
92394
  return view;
92211
- await new Promise((resolve20) => {
92395
+ await new Promise((resolve21) => {
92212
92396
  const timer = setTimeout(done, Math.min(1000, until - Date.now()));
92213
92397
  function done() {
92214
92398
  clearTimeout(timer);
92215
92399
  options.signal?.removeEventListener("abort", done);
92216
- resolve20();
92400
+ resolve21();
92217
92401
  }
92218
92402
  options.signal?.addEventListener("abort", done, { once: true });
92219
92403
  });
@@ -92445,23 +92629,23 @@ class RemoteSkillsAuthClient {
92445
92629
  }
92446
92630
  }
92447
92631
  // 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";
92632
+ 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";
92633
+ import { dirname as dirname26, isAbsolute as isAbsolute20, join as join39, resolve as resolve21 } from "path";
92450
92634
  import { randomUUID as randomUUID11 } from "crypto";
92451
92635
  var fail = () => {
92452
92636
  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
92637
  };
92454
92638
  function safeDirectory(directory) {
92455
- if (!isAbsolute20(directory) || directory !== resolve20(directory) || realpathSync12(directory) !== directory)
92639
+ if (!isAbsolute20(directory) || directory !== resolve21(directory) || realpathSync13(directory) !== directory)
92456
92640
  return fail();
92457
92641
  for (let path2 = directory;; path2 = dirname26(path2)) {
92458
- const stat2 = lstatSync23(path2);
92642
+ const stat2 = lstatSync24(path2);
92459
92643
  if (!stat2.isDirectory() || stat2.isSymbolicLink())
92460
92644
  return fail();
92461
92645
  if (path2 === dirname26(path2))
92462
92646
  break;
92463
92647
  }
92464
- const own2 = lstatSync23(directory);
92648
+ const own2 = lstatSync24(directory);
92465
92649
  if ((own2.mode & 63) !== 0 || process.getuid && own2.uid !== process.getuid())
92466
92650
  return fail();
92467
92651
  return { dev: own2.dev, ino: own2.ino };
@@ -92472,7 +92656,7 @@ function unchangedDirectory(directory, identity4) {
92472
92656
  return fail();
92473
92657
  }
92474
92658
  function readOwned(directory, name, max) {
92475
- const identity4 = safeDirectory(directory), file2 = join38(directory, name);
92659
+ const identity4 = safeDirectory(directory), file2 = join39(directory, name);
92476
92660
  const fd = openSync17(file2, constants13.O_RDONLY | constants13.O_NOFOLLOW);
92477
92661
  try {
92478
92662
  const stat2 = fstatSync17(fd);
@@ -92496,7 +92680,7 @@ function readOwned(directory, name, max) {
92496
92680
  }
92497
92681
  }
92498
92682
  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);
92683
+ const fd = openSync17(join39(directory, name), constants13.O_WRONLY | constants13.O_CREAT | constants13.O_EXCL | constants13.O_NOFOLLOW, 384);
92500
92684
  try {
92501
92685
  writeFileSync10(fd, bytes);
92502
92686
  fsyncSync5(fd);
@@ -92509,7 +92693,7 @@ function save(directory, value) {
92509
92693
  writeOwned(directory, temporary, JSON.stringify(value) + `
92510
92694
  `);
92511
92695
  unchangedDirectory(directory, identity4);
92512
- renameSync6(join38(directory, temporary), join38(directory, "receipt.json"));
92696
+ renameSync6(join39(directory, temporary), join39(directory, "receipt.json"));
92513
92697
  const fd = openSync17(directory, constants13.O_RDONLY | constants13.O_NOFOLLOW);
92514
92698
  try {
92515
92699
  fsyncSync5(fd);
@@ -92522,7 +92706,7 @@ function bind(client2, receipt) {
92522
92706
  throw new PrivatePublicationError("PUBLICATION_IDENTITY_CHANGED", "The fresh session does not match the recovery directory's server, account and membership.");
92523
92707
  }
92524
92708
  async function locked(directory, action) {
92525
- const identity4 = safeDirectory(directory), file2 = join38(directory, "operation.lock");
92709
+ const identity4 = safeDirectory(directory), file2 = join39(directory, "operation.lock");
92526
92710
  let fd;
92527
92711
  try {
92528
92712
  fd = openSync17(file2, constants13.O_WRONLY | constants13.O_CREAT | constants13.O_EXCL | constants13.O_NOFOLLOW, 384);
@@ -92538,7 +92722,7 @@ async function locked(directory, action) {
92538
92722
  } finally {
92539
92723
  closeSync17(fd);
92540
92724
  unchangedDirectory(directory, identity4);
92541
- const now2 = lstatSync23(file2);
92725
+ const now2 = lstatSync24(file2);
92542
92726
  if (now2.dev !== lock.dev || now2.ino !== lock.ino || !now2.isFile() || now2.isSymbolicLink())
92543
92727
  fail();
92544
92728
  unlinkSync5(file2);
@@ -92590,7 +92774,7 @@ async function preparePrivatePublication(client2, sourceDirectory, recoveryDirec
92590
92774
  phase: "prepared",
92591
92775
  intent: null
92592
92776
  };
92593
- if (!isAbsolute20(recoveryDirectory) || resolve20(recoveryDirectory) !== recoveryDirectory || realpathSync12(dirname26(recoveryDirectory)) !== dirname26(recoveryDirectory))
92777
+ if (!isAbsolute20(recoveryDirectory) || resolve21(recoveryDirectory) !== recoveryDirectory || realpathSync13(dirname26(recoveryDirectory)) !== dirname26(recoveryDirectory))
92594
92778
  return fail();
92595
92779
  mkdirSync14(recoveryDirectory, { mode: 448 });
92596
92780
  safeDirectory(recoveryDirectory);