@hasna/skills 0.7.1 → 0.7.2

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
@@ -30042,10 +30042,10 @@ var require_public_api = __commonJS((exports) => {
30042
30042
  import { chmod, mkdir, readFile, rename, writeFile as writeFile2 } from "fs/promises";
30043
30043
  import { Buffer as Buffer2 } from "buffer";
30044
30044
  import { existsSync as existsSync22 } from "fs";
30045
- import { join as join27 } from "path";
30045
+ import { join as join28 } from "path";
30046
30046
  import { existsSync as existsSync18 } from "fs";
30047
30047
  import { homedir as homedir6 } from "os";
30048
- import { join as join28, resolve as resolve8 } from "path";
30048
+ import { join as join29, resolve as resolve10 } from "path";
30049
30049
  import { homedir as pathsResolverHomedir2 } from "os";
30050
30050
  import { join as pathsResolverJoin2 } from "path";
30051
30051
  import { createHmac as createHmac4, timingSafeEqual as timingSafeEqual3 } from "crypto";
@@ -30207,7 +30207,7 @@ function effectiveHome2() {
30207
30207
  return process.env["HOME"] || process.env["USERPROFILE"] || homedir6();
30208
30208
  }
30209
30209
  function legacyHomeDir() {
30210
- return join28(effectiveHome2(), ".hasna", "events");
30210
+ return join29(effectiveHome2(), ".hasna", "events");
30211
30211
  }
30212
30212
  function resolverHome() {
30213
30213
  return dataDir2({ app: "events", home: effectiveHome2() || undefined });
@@ -30216,7 +30216,7 @@ function adoptResolverHome(resolved, env = process.env) {
30216
30216
  const dataOverride = env.HASNA_DATA_HOME;
30217
30217
  if (typeof dataOverride === "string" && dataOverride.trim().length > 0)
30218
30218
  return true;
30219
- return existsSync18(join28(resolved, EVENTS_STORE_SENTINEL_FILE));
30219
+ return existsSync18(join29(resolved, EVENTS_STORE_SENTINEL_FILE));
30220
30220
  }
30221
30221
  function exactEventsHome() {
30222
30222
  const dir = process.env[HASNA_EVENTS_DIR_ENV];
@@ -30230,9 +30230,9 @@ function exactEventsHome() {
30230
30230
  function getEventsHome() {
30231
30231
  const exact = exactEventsHome();
30232
30232
  if (exact)
30233
- return resolve8(exact);
30233
+ return resolve10(exact);
30234
30234
  const resolved = resolverHome();
30235
- return adoptResolverHome(resolved) ? resolve8(resolved) : resolve8(legacyHomeDir());
30235
+ return adoptResolverHome(resolved) ? resolve10(resolved) : resolve10(legacyHomeDir());
30236
30236
  }
30237
30237
  function getEventsDataDir(override) {
30238
30238
  return override || getEventsHome();
@@ -30247,9 +30247,9 @@ class JsonEventsStore {
30247
30247
  constructor(dataDir22 = getEventsDataDir()) {
30248
30248
  this.dataDir = dataDir22;
30249
30249
  this.runtime = localJsonRuntime(dataDir22);
30250
- this.channelsPath = join27(dataDir22, "channels.json");
30251
- this.eventsPath = join27(dataDir22, "events.json");
30252
- this.deliveriesPath = join27(dataDir22, "deliveries.json");
30250
+ this.channelsPath = join28(dataDir22, "channels.json");
30251
+ this.eventsPath = join28(dataDir22, "events.json");
30252
+ this.deliveriesPath = join28(dataDir22, "deliveries.json");
30253
30253
  }
30254
30254
  async init() {
30255
30255
  await mkdir(this.dataDir, { recursive: true, mode: 448 });
@@ -31368,7 +31368,7 @@ var init_event_sink = __esm(() => {
31368
31368
  // package.json
31369
31369
  var package_default = {
31370
31370
  name: "@hasna/skills",
31371
- version: "0.7.1",
31371
+ version: "0.7.2",
31372
31372
  description: "Skills library for AI coding agents",
31373
31373
  type: "module",
31374
31374
  bin: {
@@ -45190,7 +45190,7 @@ import { existsSync as existsSync17 } from "fs";
45190
45190
 
45191
45191
  // src/lib/installer.ts
45192
45192
  import { existsSync as existsSync14, readFileSync as readFileSync17, rmSync as rmSync3 } from "fs";
45193
- import { dirname as dirname13, join as join23 } from "path";
45193
+ import { dirname as dirname15, join as join24 } from "path";
45194
45194
  import { homedir as homedir5 } from "os";
45195
45195
  import { fileURLToPath as fileURLToPath2 } from "url";
45196
45196
 
@@ -45198,7 +45198,7 @@ import { fileURLToPath as fileURLToPath2 } from "url";
45198
45198
  import {
45199
45199
  cpSync as cpSync3,
45200
45200
  existsSync as existsSync11,
45201
- lstatSync as lstatSync10,
45201
+ lstatSync as lstatSync12,
45202
45202
  mkdirSync as mkdirSync8,
45203
45203
  mkdtempSync as mkdtempSync2,
45204
45204
  readFileSync as readFileSync14,
@@ -45209,12 +45209,12 @@ import {
45209
45209
  writeFileSync as writeFileSync6
45210
45210
  } from "fs";
45211
45211
  import { homedir as homedir4 } from "os";
45212
- import { basename as basename3, dirname as dirname12, join as join20 } from "path";
45212
+ import { basename as basename3, dirname as dirname14, join as join21 } from "path";
45213
45213
 
45214
45214
  // src/lib/agent-integration.ts
45215
- import { createHash as createHash10, randomUUID as randomUUID6 } from "crypto";
45216
- import { existsSync as existsSync5, lstatSync as lstatSync7, statSync as statSync3, mkdirSync as mkdirSync5, readFileSync as readFileSync9, readdirSync as readdirSync6, readlinkSync, realpathSync as realpathSync2, renameSync as renameSync2, rmdirSync, writeFileSync as writeFileSync3, unlinkSync as unlinkSync2, chmodSync, openSync as openSync5, closeSync as closeSync5, fsyncSync, fstatSync as fstatSync5, readSync as readSync4, constants as constants4, linkSync } from "fs";
45217
- import { dirname as dirname9, join as join14, resolve as resolve5, relative as relative2, isAbsolute as isAbsolute5, sep as sep2 } from "path";
45215
+ import { createHash as createHash12, randomUUID as randomUUID6 } from "crypto";
45216
+ import { existsSync as existsSync5, lstatSync as lstatSync9, statSync as statSync3, mkdirSync as mkdirSync5, readFileSync as readFileSync9, readdirSync as readdirSync6, opendirSync as opendirSync3, readlinkSync, realpathSync as realpathSync2, renameSync as renameSync2, rmdirSync, writeFileSync as writeFileSync3, unlinkSync as unlinkSync2, chmodSync, openSync as openSync6, closeSync as closeSync6, fsyncSync, fstatSync as fstatSync6, readSync as readSync5, constants as constants5, linkSync } from "fs";
45217
+ import { dirname as dirname11, join as join15, resolve as resolve7, relative as relative2, isAbsolute as isAbsolute7, sep as sep2 } from "path";
45218
45218
  import { homedir as homedir3 } from "os";
45219
45219
 
45220
45220
  // src/lib/managed-policy.ts
@@ -45484,7 +45484,7 @@ function readSkillSession(sessionId, options = {}) {
45484
45484
  }
45485
45485
 
45486
45486
  // src/lib/agent-policy-limits.ts
45487
- var AGENT_POLICY_LIMITS = Object.freeze({ bytes: 1024 * 1024, agents: 16, discoverySources: 2048, discoveryRoots: 512, builtinNames: 2048, rootAliases: 2, fields: 64, pathCharacters: 4096 });
45487
+ var AGENT_POLICY_LIMITS = Object.freeze({ bytes: 1024 * 1024, agents: 16, discoverySources: 2048, discoveryRawSourceBytes: 64 * 1024 * 1024, discoveryRawTotalBytes: 256 * 1024 * 1024, discoveryRoots: 512, discoveryDirectories: 64, discoveryDirectoryEntries: 20000, discoveryDirectoryBytes: 8 * 1024 * 1024, builtinNames: 2048, rootAliases: 2, fields: 64, pathCharacters: 4096 });
45488
45488
  function object2(value) {
45489
45489
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
45490
45490
  }
@@ -45548,12 +45548,20 @@ function assertAgentPolicyCollections(policy) {
45548
45548
  requireBound(object2(source));
45549
45549
  text(source.path);
45550
45550
  requireBound(source.sha256 === null || typeof source.sha256 === "string" && /^[a-f0-9]{64}$/.test(source.sha256));
45551
+ if (source.hashMode !== undefined)
45552
+ requireBound(source.hashMode === "bytes" && source.format === undefined && source.fields === undefined);
45551
45553
  if (source.format !== undefined)
45552
45554
  requireBound(["json", "toml", "yaml"].includes(source.format));
45553
45555
  if (source.fields !== undefined)
45554
45556
  for (const field of array(source.fields, AGENT_POLICY_LIMITS.fields))
45555
45557
  text(field, 256);
45556
45558
  }
45559
+ if (value.directories !== undefined)
45560
+ for (const directory of array(value.directories, AGENT_POLICY_LIMITS.discoveryDirectories)) {
45561
+ requireBound(object2(directory));
45562
+ text(directory.path);
45563
+ requireBound(directory.sha256 === null || typeof directory.sha256 === "string" && /^[a-f0-9]{64}$/.test(directory.sha256));
45564
+ }
45557
45565
  if (value.builtinNames !== undefined)
45558
45566
  for (const name of array(value.builtinNames, AGENT_POLICY_LIMITS.builtinNames))
45559
45567
  text(name, 128);
@@ -45682,9 +45690,9 @@ function isOwnedCliBridge(path, expectedPaths) {
45682
45690
  }
45683
45691
 
45684
45692
  // src/lib/agent-discovery.ts
45685
- import { createHash as createHash9 } from "crypto";
45686
- import { lstatSync as lstatSync6, readFileSync as readFileSync8, readdirSync as readdirSync5, realpathSync } from "fs";
45687
- import { dirname as dirname8, isAbsolute as isAbsolute4, join as join13, resolve as resolve4, sep } from "path";
45693
+ import { createHash as createHash11 } from "crypto";
45694
+ import { lstatSync as lstatSync8, readFileSync as readFileSync8, readdirSync as readdirSync5, realpathSync } from "fs";
45695
+ import { dirname as dirname10, isAbsolute as isAbsolute6, join as join14, resolve as resolve6, sep } from "path";
45688
45696
 
45689
45697
  // ../../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/index.js
45690
45698
  var composer = require_composer();
@@ -45802,6 +45810,10 @@ function configureHermesHooks(text2, supervisor, previous) {
45802
45810
  function assertHermesEnvironment(home) {
45803
45811
  if (process.env.TERMINAL_CWD)
45804
45812
  throw new Error("NATIVE_SKILL_DRIFT: Hermes TERMINAL_CWD requires a separately reviewed effective project; unset it before using this adapter");
45813
+ for (const variable of ["HERMES_BUNDLED_PLUGINS", "HERMES_BUNDLED_SKILLS"]) {
45814
+ if (process.env[variable])
45815
+ throw new Error(`NATIVE_SKILL_DRIFT: Hermes ${variable} requires a dedicated discovery adapter; unset it before using this adapter`);
45816
+ }
45805
45817
  const selected = process.env.HERMES_HOME?.trim();
45806
45818
  if (selected && (!isAbsolute3(selected) || resolve3(selected) !== join12(resolve3(home), ".hermes")))
45807
45819
  throw new Error("NATIVE_SKILL_DRIFT: custom Hermes homes/profiles require their own reviewed bridge");
@@ -45893,8 +45905,147 @@ if (failed) process.exitCode = 2;
45893
45905
  `;
45894
45906
  }
45895
45907
 
45908
+ // src/lib/agent-discovery-directories.ts
45909
+ import { createHash as createHash9 } from "crypto";
45910
+ import { lstatSync as lstatSync6, opendirSync as opendirSync2 } from "fs";
45911
+ import { dirname as dirname8, isAbsolute as isAbsolute4, join as join13, resolve as resolve4 } from "path";
45912
+ function need(value, message) {
45913
+ if (!value)
45914
+ throw new Error(message);
45915
+ }
45916
+ function safe(path) {
45917
+ need(typeof path === "string" && path.length <= AGENT_POLICY_LIMITS.pathCharacters && isAbsolute4(path) && resolve4(path) === path && !path.includes("\x00"), "Expected a canonical absolute discovery directory path");
45918
+ for (let cursor = path;; cursor = dirname8(cursor)) {
45919
+ need(!lstatSync6(cursor, { throwIfNoEntry: false })?.isSymbolicLink(), "Refusing symlink native discovery directory");
45920
+ if (dirname8(cursor) === cursor)
45921
+ break;
45922
+ }
45923
+ }
45924
+ function same(before, after) {
45925
+ return Boolean(after && after.isDirectory() && before.dev === after.dev && before.ino === after.ino && before.mtimeMs === after.mtimeMs && before.ctimeMs === after.ctimeMs);
45926
+ }
45927
+ function capture(path, budget) {
45928
+ safe(path);
45929
+ const root3 = lstatSync6(path, { throwIfNoEntry: false });
45930
+ if (!root3)
45931
+ return { path, sha256: null };
45932
+ need(root3.isDirectory(), "Unsupported native discovery directory input");
45933
+ const hash2 = createHash9("sha256");
45934
+ function walk2(current, relative2, before, depth) {
45935
+ need(depth <= 64, "Native discovery directory depth limit exceeded");
45936
+ const names = [], directory = opendirSync2(current);
45937
+ try {
45938
+ for (let entry = directory.readSync();entry; entry = directory.readSync()) {
45939
+ need(++budget.entries <= AGENT_POLICY_LIMITS.discoveryDirectoryEntries, "Native discovery directory entry limit exceeded");
45940
+ names.push(entry.name);
45941
+ }
45942
+ } finally {
45943
+ directory.closeSync();
45944
+ }
45945
+ need(new Set(names).size === names.length, "Ambiguous native discovery directory names");
45946
+ for (const name of names.sort()) {
45947
+ const child = join13(current, name), childRelative = relative2 ? `${relative2}/${name}` : name;
45948
+ need(child.length <= AGENT_POLICY_LIMITS.pathCharacters, "Native discovery directory path limit exceeded");
45949
+ const stat = lstatSync6(child);
45950
+ need(stat.isFile() || stat.isDirectory(), "Refusing symlink or special native discovery directory member");
45951
+ const row = JSON.stringify([childRelative, stat.isDirectory() ? "directory" : "file"]) + `
45952
+ `;
45953
+ budget.bytes += Buffer.byteLength(row);
45954
+ need(budget.bytes <= AGENT_POLICY_LIMITS.discoveryDirectoryBytes, "Native discovery directory metadata limit exceeded");
45955
+ hash2.update(row);
45956
+ if (stat.isDirectory())
45957
+ walk2(child, childRelative, stat, depth + 1);
45958
+ }
45959
+ need(same(before, lstatSync6(current, { throwIfNoEntry: false })), "Native discovery directory changed while reading");
45960
+ }
45961
+ walk2(path, "", root3, 0);
45962
+ safe(path);
45963
+ return { path, sha256: hash2.digest("hex") };
45964
+ }
45965
+ function captureDiscoveryDirectories(paths) {
45966
+ need(Array.isArray(paths) && paths.length <= AGENT_POLICY_LIMITS.discoveryDirectories && new Set(paths).size === paths.length, "Invalid native discovery directory collection");
45967
+ const budget = { entries: 0, bytes: 0 };
45968
+ return paths.map((path) => capture(path, budget));
45969
+ }
45970
+ function verifyDiscoveryDirectories(directories) {
45971
+ need(Array.isArray(directories) && directories.length <= AGENT_POLICY_LIMITS.discoveryDirectories, "Invalid native discovery directory collection");
45972
+ for (const directory of directories)
45973
+ need(directory && typeof directory === "object" && (directory.sha256 === null || typeof directory.sha256 === "string" && /^[a-f0-9]{64}$/.test(directory.sha256)), "Invalid native discovery directory digest");
45974
+ const current = captureDiscoveryDirectories(directories.map((directory) => directory.path));
45975
+ for (let i3 = 0;i3 < directories.length; i3++)
45976
+ need(current[i3].sha256 === directories[i3].sha256, `Native discovery directory membership changed; run skills hook install with a fresh discovery review: ${directories[i3].path}`);
45977
+ }
45978
+
45979
+ // src/lib/agent-discovery-bytes.ts
45980
+ import { createHash as createHash10 } from "crypto";
45981
+ import { closeSync as closeSync5, constants as constants4, fstatSync as fstatSync5, lstatSync as lstatSync7, openSync as openSync5, readSync as readSync4 } from "fs";
45982
+ import { dirname as dirname9, isAbsolute as isAbsolute5, resolve as resolve5 } from "path";
45983
+ function discoveryByteBudget() {
45984
+ return { remaining: AGENT_POLICY_LIMITS.discoveryRawTotalBytes };
45985
+ }
45986
+ function safe2(path) {
45987
+ if (typeof path !== "string" || !isAbsolute5(path) || path !== resolve5(path) || path.length > AGENT_POLICY_LIMITS.pathCharacters || path.includes("\x00"))
45988
+ throw new Error("Expected a canonical absolute raw discovery path");
45989
+ for (let cursor = path;; cursor = dirname9(cursor)) {
45990
+ if (lstatSync7(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
45991
+ throw new Error("Refusing symlink raw discovery input");
45992
+ if (dirname9(cursor) === cursor)
45993
+ break;
45994
+ }
45995
+ }
45996
+ function same2(left, right) {
45997
+ return left.dev === right.dev && left.ino === right.ino && left.size === right.size && left.mtimeMs === right.mtimeMs && left.ctimeMs === right.ctimeMs;
45998
+ }
45999
+ function consume(budget, bytes) {
46000
+ if (bytes > budget.remaining)
46001
+ throw new Error("Raw discovery aggregate byte limit exceeded");
46002
+ budget.remaining -= bytes;
46003
+ }
46004
+ function hashRawDiscoveryFile(path, budget, changes) {
46005
+ safe2(path);
46006
+ if (changes?.has(path)) {
46007
+ const text2 = changes.get(path), bytes = Buffer.byteLength(text2);
46008
+ if (bytes > AGENT_POLICY_LIMITS.discoveryRawSourceBytes)
46009
+ throw new Error("Raw discovery file byte limit exceeded");
46010
+ consume(budget, bytes);
46011
+ return createHash10("sha256").update(text2).digest("hex");
46012
+ }
46013
+ const initial = lstatSync7(path, { throwIfNoEntry: false });
46014
+ if (!initial)
46015
+ return null;
46016
+ if (!initial.isFile() || initial.size > AGENT_POLICY_LIMITS.discoveryRawSourceBytes)
46017
+ throw new Error("Unsupported or oversized raw discovery input");
46018
+ if (initial.size > budget.remaining)
46019
+ throw new Error("Raw discovery aggregate byte limit exceeded");
46020
+ const fd = openSync5(path, constants4.O_RDONLY | constants4.O_NOFOLLOW | constants4.O_NONBLOCK);
46021
+ try {
46022
+ const opened = fstatSync5(fd);
46023
+ if (!opened.isFile() || !same2(initial, opened))
46024
+ throw new Error("Raw discovery input changed during open");
46025
+ const hash2 = createHash10("sha256"), buffer = Buffer.alloc(64 * 1024);
46026
+ let bytes = 0;
46027
+ while (true) {
46028
+ const count = readSync4(fd, buffer, 0, Math.min(buffer.length, AGENT_POLICY_LIMITS.discoveryRawSourceBytes - bytes + 1), null);
46029
+ if (!count)
46030
+ break;
46031
+ bytes += count;
46032
+ if (bytes > AGENT_POLICY_LIMITS.discoveryRawSourceBytes)
46033
+ throw new Error("Raw discovery file byte limit exceeded");
46034
+ consume(budget, count);
46035
+ hash2.update(buffer.subarray(0, count));
46036
+ }
46037
+ const final = fstatSync5(fd), current = lstatSync7(path, { throwIfNoEntry: false });
46038
+ safe2(path);
46039
+ if (!current?.isFile() || !same2(opened, final) || !same2(final, current) || bytes !== final.size)
46040
+ throw new Error("Raw discovery input changed during read");
46041
+ return hash2.digest("hex");
46042
+ } finally {
46043
+ closeSync5(fd);
46044
+ }
46045
+ }
46046
+
45896
46047
  // src/lib/agent-discovery.ts
45897
- var digest2 = (text2) => createHash9("sha256").update(text2).digest("hex");
46048
+ var digest2 = (text2) => createHash11("sha256").update(text2).digest("hex");
45898
46049
  function parseConfig(text2, path, toml = false) {
45899
46050
  try {
45900
46051
  const value = toml ? Bun.TOML.parse(text2) : JSON.parse(text2);
@@ -45905,28 +46056,35 @@ function parseConfig(text2, path, toml = false) {
45905
46056
  throw new Error(`Invalid native discovery configuration: ${path}`);
45906
46057
  }
45907
46058
  }
45908
- function safe(path) {
45909
- if (!isAbsolute4(path) || path.includes("\x00"))
46059
+ function safe3(path) {
46060
+ if (!isAbsolute6(path) || path.includes("\x00"))
45910
46061
  throw new Error("Expected an absolute native discovery path");
45911
- for (let cursor = path;; cursor = dirname8(cursor)) {
45912
- if (lstatSync6(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
46062
+ for (let cursor = path;; cursor = dirname10(cursor)) {
46063
+ if (lstatSync8(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
45913
46064
  throw new Error(`Refusing symlink native discovery input: ${cursor}`);
45914
- if (dirname8(cursor) === cursor)
46065
+ if (dirname10(cursor) === cursor)
45915
46066
  break;
45916
46067
  }
45917
46068
  }
45918
46069
  function read(path, changes) {
45919
- safe(path);
46070
+ safe3(path);
45920
46071
  if (changes?.has(path))
45921
46072
  return changes.get(path);
45922
- const stat = lstatSync6(path, { throwIfNoEntry: false });
46073
+ const stat = lstatSync8(path, { throwIfNoEntry: false });
45923
46074
  if (!stat)
45924
46075
  return null;
45925
46076
  if (!stat.isFile() || stat.size > 16 * 1024 * 1024)
45926
46077
  throw new Error(`Unsupported or oversized native discovery input: ${path}`);
45927
46078
  return readFileSync8(path, "utf8");
45928
46079
  }
45929
- function projected(source, changes) {
46080
+ function projected(source, changes, budget = discoveryByteBudget()) {
46081
+ if (source.hashMode !== undefined) {
46082
+ if (source.hashMode !== "bytes")
46083
+ throw new Error("Invalid native discovery hash mode");
46084
+ if (source.format !== undefined || source.fields !== undefined)
46085
+ throw new Error("Raw discovery witnesses cannot project configuration fields");
46086
+ return hashRawDiscoveryFile(source.path, budget, changes);
46087
+ }
45930
46088
  const text2 = read(source.path, changes);
45931
46089
  if (text2 === null)
45932
46090
  return null;
@@ -45940,22 +46098,34 @@ function projected(source, changes) {
45940
46098
  function verifyAgentDiscovery(binding) {
45941
46099
  if (!binding || !Array.isArray(binding.sources) || !Array.isArray(binding.roots) || binding.sources.length > AGENT_POLICY_LIMITS.discoverySources || binding.roots.length > AGENT_POLICY_LIMITS.discoveryRoots)
45942
46100
  throw new Error("Invalid native discovery binding");
46101
+ if (binding.agent === "hermes" && !binding.directories?.length)
46102
+ throw new Error("Hermes discovery requires directory membership coverage; run skills hook install with a fresh discovery review");
46103
+ if (binding.directories !== undefined)
46104
+ verifyDiscoveryDirectories(binding.directories);
46105
+ const budget = discoveryByteBudget();
45943
46106
  for (const source of binding.sources) {
45944
46107
  if (source.format !== undefined && (!["json", "toml", "yaml"].includes(source.format) || !Array.isArray(source.fields) || !source.fields.length || source.fields.length > 64 || source.fields.some((field) => typeof field !== "string" || !field)))
45945
46108
  throw new Error("Invalid native discovery projection");
45946
46109
  if (source.sha256 !== null && !/^[a-f0-9]{64}$/.test(source.sha256))
45947
46110
  throw new Error("Invalid native discovery digest");
45948
- if (projected(source) !== source.sha256)
46111
+ if (projected(source, undefined, budget) !== source.sha256)
45949
46112
  throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
45950
46113
  }
45951
46114
  for (const root3 of binding.roots)
45952
- safe(root3);
46115
+ safe3(root3);
45953
46116
  }
45954
46117
  function rebindAgentDiscovery(binding, changes) {
45955
- return { ...binding, sources: binding.sources.map((source) => ({ ...source, sha256: projected(source, changes) })) };
46118
+ const budget = discoveryByteBudget();
46119
+ return { ...binding, sources: binding.sources.map((source) => ({ ...source, sha256: projected(source, changes, budget) })) };
46120
+ }
46121
+ function captureDiscoveryByteSources(paths) {
46122
+ if (!Array.isArray(paths) || paths.length > AGENT_POLICY_LIMITS.discoverySources || new Set(paths).size !== paths.length)
46123
+ throw new Error("Invalid raw discovery source collection");
46124
+ const budget = discoveryByteBudget();
46125
+ return paths.map((path) => ({ path, hashMode: "bytes", sha256: hashRawDiscoveryFile(path, budget) }));
45956
46126
  }
45957
46127
  function resolveAgentDiscovery(options) {
45958
- const canonical = options.canonical ?? resolve4, home = resolve4(options.home), agent = options.agent;
46128
+ const canonical = options.canonical ?? resolve6, home = resolve6(options.home), agent = options.agent;
45959
46129
  const sources = [], roots = new Set, builtinNames = [];
45960
46130
  const witness = (path, format, fields) => {
45961
46131
  const source = { path: canonical(path), sha256: null, ...format ? { format, fields } : {} };
@@ -45965,14 +46135,14 @@ function resolveAgentDiscovery(options) {
45965
46135
  };
45966
46136
  if (agent === "hermes")
45967
46137
  assertHermesEnvironment(home);
45968
- const configPath = join13(home, agent === "hermes" ? ".hermes/config.yaml" : agent === "opencode" ? ".config/opencode/opencode.json" : `.${agent}/${agent === "codex" ? "config.toml" : agent === "cursor" ? "hooks.json" : "settings.json"}`);
46138
+ const configPath = join14(home, agent === "hermes" ? ".hermes/config.yaml" : agent === "opencode" ? ".config/opencode/opencode.json" : `.${agent}/${agent === "codex" ? "config.toml" : agent === "cursor" ? "hooks.json" : "settings.json"}`);
45969
46139
  const configText = witness(configPath, agent === "hermes" ? "yaml" : agent === "codex" ? "toml" : "json", agent === "hermes" ? ["skills", "plugins", "hooks"] : agent === "claude" ? ["enabledPlugins", "extraKnownMarketplaces"] : agent === "codex" ? ["plugins", "marketplaces", "skills"] : agent === "gemini" ? ["skills", "extensions", "security"] : agent === "opencode" ? ["plugin", "skills"] : ["version"]);
45970
46140
  const config = configText === null ? {} : agent === "hermes" ? parseHermesConfig(configText) : parseConfig(configText, configPath, agent === "codex");
45971
46141
  const unresolved = (detail) => {
45972
46142
  throw new Error(`Native discovery is unresolved (${agent}: ${detail}); provide a reviewed --discovery-inputs file`);
45973
46143
  };
45974
46144
  if (agent === "hermes") {
45975
- const profile2 = witness(join13(home, ".hermes/active_profile"));
46145
+ const profile2 = witness(join14(home, ".hermes/active_profile"));
45976
46146
  if (profile2?.trim() && profile2.trim() !== "default")
45977
46147
  unresolved("a non-default profile is active");
45978
46148
  const declared = config.skills?.external_dirs ?? [], paths = typeof declared === "string" ? [declared] : declared;
@@ -45986,8 +46156,8 @@ function resolveAgentDiscovery(options) {
45986
46156
  continue;
45987
46157
  if (normalized.startsWith("~") && normalized !== "~" && !normalized.startsWith("~/"))
45988
46158
  unresolved("user-specific tilde expansion requires a separate discovery adapter");
45989
- const path = normalized === "~" ? home : normalized.startsWith("~/") ? join13(home, normalized.slice(2)) : resolve4(home, ".hermes", normalized);
45990
- safe(path);
46159
+ const path = normalized === "~" ? home : normalized.startsWith("~/") ? join14(home, normalized.slice(2)) : resolve6(home, ".hermes", normalized);
46160
+ safe3(path);
45991
46161
  roots.add(path);
45992
46162
  }
45993
46163
  }
@@ -45995,24 +46165,24 @@ function resolveAgentDiscovery(options) {
45995
46165
  const executable = Bun.which("gemini");
45996
46166
  if (executable) {
45997
46167
  let packageRoot;
45998
- for (let directory = dirname8(realpathSync(executable)), depth = 0;depth < 8; directory = dirname8(directory), depth++) {
45999
- const path = join13(directory, "package.json"), raw = read(path);
46168
+ for (let directory = dirname10(realpathSync(executable)), depth = 0;depth < 8; directory = dirname10(directory), depth++) {
46169
+ const path = join14(directory, "package.json"), raw = read(path);
46000
46170
  if (raw !== null && parseConfig(raw, path).name === "@google/gemini-cli") {
46001
46171
  packageRoot = directory;
46002
46172
  witness(path);
46003
46173
  break;
46004
46174
  }
46005
- if (dirname8(directory) === directory)
46175
+ if (dirname10(directory) === directory)
46006
46176
  break;
46007
46177
  }
46008
46178
  if (!packageRoot)
46009
46179
  unresolved("installed Gemini package layout is not recognized");
46010
- const builtinRoot = join13(packageRoot, "bundle/builtin");
46011
- safe(builtinRoot);
46012
- if (!lstatSync6(builtinRoot, { throwIfNoEntry: false })?.isDirectory())
46180
+ const builtinRoot = join14(packageRoot, "bundle/builtin");
46181
+ safe3(builtinRoot);
46182
+ if (!lstatSync8(builtinRoot, { throwIfNoEntry: false })?.isDirectory())
46013
46183
  unresolved("installed Gemini builtin root is missing");
46014
46184
  for (const name of readdirSync5(builtinRoot).sort()) {
46015
- const text2 = witness(join13(builtinRoot, name, "SKILL.md"));
46185
+ const text2 = witness(join14(builtinRoot, name, "SKILL.md"));
46016
46186
  const match = text2?.match(/^---\r?\n[\s\S]*?^name:\s*([a-z0-9][a-z0-9-]*)\s*$/m);
46017
46187
  if (!match?.[1] || builtinNames.includes(match[1]))
46018
46188
  unresolved("installed Gemini builtin name is missing or ambiguous");
@@ -46026,7 +46196,7 @@ function resolveAgentDiscovery(options) {
46026
46196
  if (review) {
46027
46197
  if (review.pluginHooks !== "reviewed-no-skill-injection" || !Array.isArray(review.sources) || !review.sources.length || !Array.isArray(review.roots))
46028
46198
  throw new Error("Discovery review must bind sources and confirm plugin hooks do not inject retired skills");
46029
- const supplied = { agent, roots: review.roots, sources: review.sources, method: "reviewed" };
46199
+ const supplied = { agent, roots: review.roots, sources: review.sources, ...review.directories !== undefined ? { directories: review.directories } : {}, method: "reviewed" };
46030
46200
  if (review.sources.some((source) => source.format !== undefined || source.fields !== undefined))
46031
46201
  throw new Error("Explicit discovery reviews require full source-file hashes");
46032
46202
  verifyAgentDiscovery(supplied);
@@ -46036,40 +46206,40 @@ function resolveAgentDiscovery(options) {
46036
46206
  }
46037
46207
  function plugin(root3) {
46038
46208
  root3 = canonical(root3);
46039
- safe(root3);
46040
- const manifestPath = join13(root3, agent === "claude" ? ".claude-plugin/plugin.json" : ".codex-plugin/plugin.json");
46209
+ safe3(root3);
46210
+ const manifestPath = join14(root3, agent === "claude" ? ".claude-plugin/plugin.json" : ".codex-plugin/plugin.json");
46041
46211
  const raw = witness(manifestPath);
46042
46212
  if (raw === null)
46043
46213
  unresolved("plugin manifest missing");
46044
46214
  const manifest = parseConfig(raw, manifestPath);
46045
- const hooks = witness(join13(root3, "hooks/hooks.json"));
46215
+ const hooks = witness(join14(root3, "hooks/hooks.json"));
46046
46216
  if (manifest.hooks !== undefined || hooks !== null)
46047
46217
  unresolved("plugin hooks require a separate no-skill-injection review");
46048
- const commands2 = join13(root3, "commands");
46049
- safe(commands2);
46050
- if (agent === "claude" && (manifest.commands !== undefined || lstatSync6(commands2, { throwIfNoEntry: false })?.isDirectory() && readdirSync5(commands2).length))
46218
+ const commands2 = join14(root3, "commands");
46219
+ safe3(commands2);
46220
+ if (agent === "claude" && (manifest.commands !== undefined || lstatSync8(commands2, { throwIfNoEntry: false })?.isDirectory() && readdirSync5(commands2).length))
46051
46221
  unresolved("legacy command discovery requires retirement or a dedicated format adapter");
46052
- const rootSkill = witness(join13(root3, "SKILL.md"));
46222
+ const rootSkill = witness(join14(root3, "SKILL.md"));
46053
46223
  if (rootSkill !== null)
46054
46224
  roots.add(root3);
46055
46225
  const declared = manifest.skills === undefined ? ["./skills"] : typeof manifest.skills === "string" ? [manifest.skills] : manifest.skills;
46056
46226
  if (!Array.isArray(declared) || declared.some((path) => typeof path !== "string"))
46057
46227
  unresolved("unsupported plugin skill paths");
46058
46228
  if (agent === "claude")
46059
- roots.add(join13(root3, "skills"));
46229
+ roots.add(join14(root3, "skills"));
46060
46230
  for (const value of declared) {
46061
- const path = resolve4(root3, value);
46231
+ const path = resolve6(root3, value);
46062
46232
  if (path !== root3 && !path.startsWith(root3 + sep))
46063
46233
  unresolved("plugin skill path escapes its root");
46064
- roots.add(path.endsWith(`${sep}SKILL.md`) ? dirname8(path) : path);
46234
+ roots.add(path.endsWith(`${sep}SKILL.md`) ? dirname10(path) : path);
46065
46235
  }
46066
46236
  }
46067
46237
  if (agent === "claude") {
46068
- const registrations = witness(join13(home, ".claude/plugins/installed_plugins.json"));
46069
- const installed = registrations === null ? {} : parseConfig(registrations, join13(home, ".claude/plugins/installed_plugins.json")).plugins;
46070
- const commands2 = canonical(join13(home, ".claude/commands"));
46071
- safe(commands2);
46072
- if (lstatSync6(commands2, { throwIfNoEntry: false })?.isDirectory() && readdirSync5(commands2).length)
46238
+ const registrations = witness(join14(home, ".claude/plugins/installed_plugins.json"));
46239
+ const installed = registrations === null ? {} : parseConfig(registrations, join14(home, ".claude/plugins/installed_plugins.json")).plugins;
46240
+ const commands2 = canonical(join14(home, ".claude/commands"));
46241
+ safe3(commands2);
46242
+ if (lstatSync8(commands2, { throwIfNoEntry: false })?.isDirectory() && readdirSync5(commands2).length)
46073
46243
  unresolved("legacy home command discovery requires a dedicated format adapter");
46074
46244
  for (const [id, enabled] of Object.entries(config.enabledPlugins ?? {})) {
46075
46245
  if (enabled === false)
@@ -46089,34 +46259,34 @@ function resolveAgentDiscovery(options) {
46089
46259
  unresolved("unsupported plugin enablement");
46090
46260
  const split = id.lastIndexOf("@"), name = id.slice(0, split), marketplace = id.slice(split + 1);
46091
46261
  const market = config.marketplaces?.[marketplace] ?? (marketplace === "personal" ? { source_type: "local", source: home } : undefined);
46092
- if (split < 1 || market?.source_type !== "local" || typeof market.source !== "string" || !isAbsolute4(market.source))
46262
+ if (split < 1 || market?.source_type !== "local" || typeof market.source !== "string" || !isAbsolute6(market.source))
46093
46263
  unresolved("enabled plugin marketplace is not an explicit local source");
46094
- const catalogText = witness(join13(market.source, ".agents/plugins/marketplace.json"));
46264
+ const catalogText = witness(join14(market.source, ".agents/plugins/marketplace.json"));
46095
46265
  if (catalogText === null)
46096
46266
  unresolved("marketplace catalog missing");
46097
- const catalog = parseConfig(catalogText, join13(market.source, ".agents/plugins/marketplace.json")), matches = Array.isArray(catalog.plugins) ? catalog.plugins.filter((item) => item.name === name) : [];
46267
+ const catalog = parseConfig(catalogText, join14(market.source, ".agents/plugins/marketplace.json")), matches = Array.isArray(catalog.plugins) ? catalog.plugins.filter((item) => item.name === name) : [];
46098
46268
  if (matches.length !== 1 || matches[0]?.source?.source !== "local" || typeof matches[0]?.source?.path !== "string")
46099
46269
  unresolved("plugin catalog source is missing or ambiguous");
46100
- plugin(resolve4(market.source, matches[0].source.path));
46270
+ plugin(resolve6(market.source, matches[0].source.path));
46101
46271
  }
46102
46272
  } else if (agent === "opencode") {
46103
- if (witness(join13(home, ".config/opencode/opencode.jsonc")) !== null || witness(join13(home, ".config/opencode/config.json")) !== null)
46273
+ if (witness(join14(home, ".config/opencode/opencode.jsonc")) !== null || witness(join14(home, ".config/opencode/config.json")) !== null)
46104
46274
  unresolved("additional config layers require review");
46105
46275
  if ((config.plugin?.length ?? 0) > 0 || config.skills?.urls?.length)
46106
46276
  unresolved("external plugin or remote skill source");
46107
46277
  for (const path of config.skills?.paths ?? []) {
46108
- if (typeof path !== "string" || !isAbsolute4(path))
46278
+ if (typeof path !== "string" || !isAbsolute6(path))
46109
46279
  unresolved("relative or malformed added skill root");
46110
46280
  roots.add(path);
46111
46281
  }
46112
- const localPlugins = join13(home, ".config/opencode/plugins");
46113
- safe(localPlugins);
46114
- if (lstatSync6(localPlugins, { throwIfNoEntry: false }) && readdirSync5(localPlugins).some((name) => name !== "skills-cli.js"))
46282
+ const localPlugins = join14(home, ".config/opencode/plugins");
46283
+ safe3(localPlugins);
46284
+ if (lstatSync8(localPlugins, { throwIfNoEntry: false }) && readdirSync5(localPlugins).some((name) => name !== "skills-cli.js"))
46115
46285
  unresolved("additional local plugin hooks require review");
46116
46286
  } else if (agent === "hermes") {
46117
- for (const directory of [join13(home, ".hermes/plugins"), join13(home, ".hermes/hermes-agent")]) {
46118
- safe(directory);
46119
- if (lstatSync6(directory, { throwIfNoEntry: false }))
46287
+ for (const directory of [join14(home, ".hermes/plugins"), join14(home, ".hermes/hermes-agent")]) {
46288
+ safe3(directory);
46289
+ if (lstatSync8(directory, { throwIfNoEntry: false }))
46120
46290
  unresolved("installed runtime/plugin discovery requires reviewed source bindings");
46121
46291
  }
46122
46292
  if (Bun.which("hermes") || Object.keys(config.plugins ?? {}).length)
@@ -46124,24 +46294,24 @@ function resolveAgentDiscovery(options) {
46124
46294
  } else if (agent === "gemini") {
46125
46295
  if (Object.keys(config.extensions ?? {}).length || config.skills?.paths?.length)
46126
46296
  unresolved("custom extension or skill paths");
46127
- const directory = join13(home, ".gemini/extensions");
46128
- safe(directory);
46129
- if (lstatSync6(directory, { throwIfNoEntry: false }))
46297
+ const directory = join14(home, ".gemini/extensions");
46298
+ safe3(directory);
46299
+ if (lstatSync8(directory, { throwIfNoEntry: false }))
46130
46300
  for (const name of readdirSync5(directory)) {
46131
- const root3 = join13(directory, name);
46132
- safe(root3);
46133
- if (!lstatSync6(root3)?.isDirectory())
46301
+ const root3 = join14(directory, name);
46302
+ safe3(root3);
46303
+ if (!lstatSync8(root3)?.isDirectory())
46134
46304
  continue;
46135
- const raw = witness(join13(root3, "gemini-extension.json"));
46305
+ const raw = witness(join14(root3, "gemini-extension.json"));
46136
46306
  if (raw === null)
46137
46307
  unresolved("extension registration missing");
46138
- const manifest = parseConfig(raw, join13(root3, "gemini-extension.json"));
46139
- if (manifest.hooks !== undefined || witness(join13(root3, "hooks/hooks.json")) !== null || witness(join13(root3, ".gemini-extension-install.json")) !== null)
46308
+ const manifest = parseConfig(raw, join14(root3, "gemini-extension.json"));
46309
+ if (manifest.hooks !== undefined || witness(join14(root3, "hooks/hooks.json")) !== null || witness(join14(root3, ".gemini-extension-install.json")) !== null)
46140
46310
  unresolved("extension hooks or linked registration require review");
46141
- roots.add(join13(root3, "skills"));
46311
+ roots.add(join14(root3, "skills"));
46142
46312
  }
46143
46313
  }
46144
- return { agent, roots: [...roots].sort(), sources, method: "automatic", ...agent === "gemini" ? { builtinNames } : {} };
46314
+ return { agent, roots: [...roots].sort(), sources, method: "automatic", ...agent === "gemini" ? { builtinNames } : {}, ...agent === "hermes" ? { directories: captureDiscoveryDirectories([join14(home, ".hermes/plugins"), join14(home, ".hermes/hermes-agent")].map((path) => canonical(path))) } : {} };
46145
46315
  }
46146
46316
 
46147
46317
  // src/lib/agent-adapters.ts
@@ -46206,7 +46376,7 @@ export default async ({ directory }) => {
46206
46376
  }
46207
46377
 
46208
46378
  // src/lib/agent-integration.ts
46209
- var sha = (data) => createHash10("sha256").update(data).digest("hex");
46379
+ var sha = (data) => createHash12("sha256").update(data).digest("hex");
46210
46380
  var ROOTS = [
46211
46381
  ["claude", ".claude/skills"],
46212
46382
  ["codex", ".codex/skills"],
@@ -46225,11 +46395,11 @@ var ROOTS = [
46225
46395
  ["copilot", ".github/skills"]
46226
46396
  ];
46227
46397
  function assertSafePath(path) {
46228
- let cursor = resolve5(path);
46398
+ let cursor = resolve7(path);
46229
46399
  while (true) {
46230
- if (lstatSync7(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
46400
+ if (lstatSync9(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
46231
46401
  throw new Error(`Refusing symlink path: ${cursor}`);
46232
- const parent = dirname9(cursor);
46402
+ const parent = dirname11(cursor);
46233
46403
  if (parent === cursor)
46234
46404
  return;
46235
46405
  cursor = parent;
@@ -46237,17 +46407,17 @@ function assertSafePath(path) {
46237
46407
  }
46238
46408
  function readRootAlias(home, agent) {
46239
46409
  assertSafePath(home);
46240
- const realHome = realpathSync2(home), alias = join14(realHome, `.${agent}`);
46241
- const stat = lstatSync7(alias, { throwIfNoEntry: false, bigint: true });
46410
+ const realHome = realpathSync2(home), alias = join15(realHome, `.${agent}`);
46411
+ const stat = lstatSync9(alias, { throwIfNoEntry: false, bigint: true });
46242
46412
  if (!stat?.isSymbolicLink())
46243
46413
  throw new Error(`Agent root alias changed after planning: ${alias}`);
46244
- const link = readlinkSync(alias), targetPath = resolve5(dirname9(alias), link);
46414
+ const link = readlinkSync(alias), targetPath = resolve7(dirname11(alias), link);
46245
46415
  assertSafePath(targetPath);
46246
- const targetStat = lstatSync7(targetPath, { throwIfNoEntry: false });
46416
+ const targetStat = lstatSync9(targetPath, { throwIfNoEntry: false });
46247
46417
  if (!targetStat?.isDirectory())
46248
46418
  throw new Error(`Agent root alias must target an existing directory: ${alias}`);
46249
46419
  const target = realpathSync2(targetPath), inside = relative2(realHome, target);
46250
- if (!inside || inside === ".." || inside.startsWith(`..${sep2}`) || isAbsolute5(inside))
46420
+ if (!inside || inside === ".." || inside.startsWith(`..${sep2}`) || isAbsolute7(inside))
46251
46421
  throw new Error(`Agent root alias target must be inside the real home: ${alias}`);
46252
46422
  return { agent, home: realHome, alias, target, link, aliasIdentity: `${stat.dev}:${stat.ino}:${stat.ctimeNs}`, targetIdentity: `${targetStat.dev}:${targetStat.ino}` };
46253
46423
  }
@@ -46256,19 +46426,19 @@ function rootAliases(home, allowed = false) {
46256
46426
  return [];
46257
46427
  const result = [];
46258
46428
  for (const agent of ["claude", "codex"])
46259
- if (lstatSync7(join14(home, `.${agent}`), { throwIfNoEntry: false })?.isSymbolicLink())
46429
+ if (lstatSync9(join15(home, `.${agent}`), { throwIfNoEntry: false })?.isSymbolicLink())
46260
46430
  result.push(readRootAlias(home, agent));
46261
46431
  if (result.some((item, index) => result.slice(index + 1).some((other) => item.target === other.target || item.target.startsWith(other.target + sep2) || other.target.startsWith(item.target + sep2))))
46262
46432
  throw new Error("Agent root alias targets must not overlap");
46263
46433
  return result;
46264
46434
  }
46265
46435
  function canonicalAgentPath(path, aliases) {
46266
- const absolute = resolve5(path), binding = aliases.find((item) => absolute === item.alias || absolute.startsWith(item.alias + sep2));
46267
- return binding ? join14(binding.target, relative2(binding.alias, absolute)) : absolute;
46436
+ const absolute = resolve7(path), binding = aliases.find((item) => absolute === item.alias || absolute.startsWith(item.alias + sep2));
46437
+ return binding ? join15(binding.target, relative2(binding.alias, absolute)) : absolute;
46268
46438
  }
46269
46439
  function recheckRootAliases(aliases) {
46270
46440
  for (const binding of aliases) {
46271
- if (!["claude", "codex"].includes(binding.agent) || binding.alias !== join14(binding.home, `.${binding.agent}`))
46441
+ if (!["claude", "codex"].includes(binding.agent) || binding.alias !== join15(binding.home, `.${binding.agent}`))
46272
46442
  throw new Error("Invalid agent root alias binding");
46273
46443
  const current = readRootAlias(binding.home, binding.agent);
46274
46444
  if (JSON.stringify(current) !== JSON.stringify(binding))
@@ -46277,42 +46447,42 @@ function recheckRootAliases(aliases) {
46277
46447
  }
46278
46448
  function readNativeBytes(path, maximum = 64 * 1024 * 1024) {
46279
46449
  assertSafePath(path);
46280
- const before = lstatSync7(path);
46450
+ const before = lstatSync9(path);
46281
46451
  if (!before.isFile() || before.size > maximum)
46282
46452
  throw new Error("Unsupported or oversized native skill file");
46283
- const descriptor = openSync5(path, constants4.O_RDONLY | constants4.O_NOFOLLOW | constants4.O_NONBLOCK);
46453
+ const descriptor = openSync6(path, constants5.O_RDONLY | constants5.O_NOFOLLOW | constants5.O_NONBLOCK);
46284
46454
  try {
46285
- const opened = fstatSync5(descriptor);
46455
+ const opened = fstatSync6(descriptor);
46286
46456
  if (!opened.isFile() || opened.dev !== before.dev || opened.ino !== before.ino || opened.size !== before.size)
46287
46457
  throw new Error("Native skill file changed while reading");
46288
46458
  const bytes = Buffer.allocUnsafe(before.size + 1);
46289
46459
  let length = 0;
46290
46460
  while (length < bytes.length) {
46291
- const count = readSync4(descriptor, bytes, length, bytes.length - length, null);
46461
+ const count = readSync5(descriptor, bytes, length, bytes.length - length, null);
46292
46462
  if (!count)
46293
46463
  break;
46294
46464
  length += count;
46295
46465
  }
46296
- const after = fstatSync5(descriptor);
46466
+ const after = fstatSync6(descriptor);
46297
46467
  if (length !== before.size || after.size !== before.size || after.mtimeMs !== opened.mtimeMs || after.ctimeMs !== opened.ctimeMs)
46298
46468
  throw new Error("Native skill file changed while reading");
46299
46469
  return bytes.subarray(0, length);
46300
46470
  } finally {
46301
- closeSync5(descriptor);
46471
+ closeSync6(descriptor);
46302
46472
  }
46303
46473
  }
46304
46474
  function treeHash(root3) {
46305
- const hash2 = createHash10("sha256");
46475
+ const hash2 = createHash12("sha256");
46306
46476
  let bytes = 0, files = 0;
46307
46477
  function visit2(path) {
46308
- const stat = lstatSync7(path);
46478
+ const stat = lstatSync9(path);
46309
46479
  if (stat.isSymbolicLink())
46310
46480
  throw new Error(`Refusing symlink in skill: ${path}`);
46311
46481
  const rel = relative2(root3, path);
46312
46482
  if (stat.isDirectory()) {
46313
46483
  hash2.update(`d\x00${rel}\x00`);
46314
46484
  for (const name of readdirSync6(path).sort())
46315
- visit2(join14(path, name));
46485
+ visit2(join15(path, name));
46316
46486
  return;
46317
46487
  }
46318
46488
  if (!stat.isFile())
@@ -46330,37 +46500,50 @@ function treeHash(root3) {
46330
46500
  }
46331
46501
  function inventoryNativeSkills(home = homedir3(), options = {}) {
46332
46502
  const aliases = rootAliases(home, options.allowRootAliases);
46333
- const roots = ROOTS.map(([agent, path]) => [agent, canonicalAgentPath(join14(home, path), aliases)]);
46334
- const bridgePaths = Object.values(AGENT_ADAPTERS).map((adapter) => canonicalAgentPath(join14(home, adapter.root, CLI_BRIDGE_NAME), aliases));
46335
- for (const project of new Set([...options.projectDirs ?? [], ...options.projectDir ? [options.projectDir] : []].map((path) => resolve5(path)))) {
46503
+ const roots = ROOTS.map(([agent, path]) => [agent, canonicalAgentPath(join15(home, path), aliases)]);
46504
+ const bridgePaths = Object.values(AGENT_ADAPTERS).map((adapter) => canonicalAgentPath(join15(home, adapter.root, CLI_BRIDGE_NAME), aliases));
46505
+ for (const project of new Set([...options.projectDirs ?? [], ...options.projectDir ? [options.projectDir] : []].map((path) => resolve7(path)))) {
46336
46506
  for (const [agent, path] of ROOTS)
46337
- roots.push([agent, canonicalAgentPath(join14(project, path), aliases)]);
46507
+ roots.push([agent, canonicalAgentPath(join15(project, path), aliases)]);
46338
46508
  }
46339
46509
  const entries = [], seen = new Set;
46340
46510
  const cacheScans = new Map, maxAliasProofEntries = 1e4;
46511
+ let discoveryEntries = 0, discoveryPathBytes = 0;
46512
+ function admit(path) {
46513
+ if (++discoveryEntries > 20000)
46514
+ throw new Error("Native skill discovery entry limit exceeded");
46515
+ discoveryPathBytes += Buffer.byteLength(path, "utf8");
46516
+ if (discoveryPathBytes > 4 * 1024 * 1024)
46517
+ throw new Error("Native skill discovery metadata limit exceeded");
46518
+ }
46341
46519
  function emptySiblingCacheAlias(path, parent) {
46342
- const link = readlinkSync(path), target = resolve5(parent, link);
46343
- if (dirname9(target) !== parent || (isAbsolute5(link) ? link !== target : dirname9(link) !== "."))
46520
+ const link = readlinkSync(path), target = resolve7(parent, link);
46521
+ if (dirname11(target) !== parent || (isAbsolute7(link) ? link !== target : dirname11(link) !== "."))
46344
46522
  return false;
46345
- if (!lstatSync7(target, { throwIfNoEntry: false })?.isDirectory())
46523
+ if (!lstatSync9(target, { throwIfNoEntry: false })?.isDirectory())
46346
46524
  return false;
46347
46525
  const scan = cacheScans.get(target);
46348
46526
  return Boolean(scan?.complete && !scan.hasSkills && scan.entries <= maxAliasProofEntries);
46349
46527
  }
46350
- function visit2(agent, path, vendor = false, depth = 0, pluginCache = false) {
46528
+ function visit2(agent, path, vendor = false, depth = 0, pluginCache = false, admitted = false) {
46529
+ if (!admitted)
46530
+ admit(path);
46351
46531
  const scan = { complete: true, hasSkills: false, entries: 1 };
46352
46532
  assertSafePath(path);
46353
46533
  if (!existsSync5(path))
46354
46534
  return scan;
46355
- if (!lstatSync7(path).isDirectory())
46535
+ const stat = lstatSync9(path);
46536
+ if (stat.isFile())
46356
46537
  return scan;
46357
- if (existsSync5(join14(path, "SKILL.md"))) {
46538
+ if (!stat.isDirectory())
46539
+ throw new Error(`Unsupported native discovery entry: ${path}`);
46540
+ if (existsSync5(join15(path, "SKILL.md"))) {
46358
46541
  scan.hasSkills = true;
46359
46542
  if (seen.has(path))
46360
46543
  return scan;
46361
46544
  seen.add(path);
46362
46545
  let managed = false;
46363
- const marker = join14(path, ".hasna-skills.json");
46546
+ const marker = join15(path, ".hasna-skills.json");
46364
46547
  if (existsSync5(marker)) {
46365
46548
  try {
46366
46549
  managed = JSON.parse(readFileSync9(marker, "utf8")).managedBy === "@hasna/skills";
@@ -46368,12 +46551,22 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
46368
46551
  }
46369
46552
  const bridge = !vendor && isOwnedCliBridge(path, bridgePaths);
46370
46553
  const rootAlias = aliases.find((item) => path === item.target || path.startsWith(item.target + sep2));
46371
- entries.push({ agent, path, hash: treeHash(path), managed, vendor, ...agent === "codex" && path.startsWith(canonicalAgentPath(join14(home, ".codex", "skills", ".system"), aliases) + sep2) ? { system: true } : {}, ...bridge ? { bridge: true, bridgeHome: resolve5(home) } : {}, ...rootAlias ? { rootAlias } : {} });
46554
+ entries.push({ agent, path, hash: treeHash(path), managed, vendor, ...agent === "codex" && path.startsWith(canonicalAgentPath(join15(home, ".codex", "skills", ".system"), aliases) + sep2) ? { system: true } : {}, ...bridge ? { bridge: true, bridgeHome: resolve7(home) } : {}, ...rootAlias ? { rootAlias } : {} });
46372
46555
  return scan;
46373
46556
  }
46374
- if (depth > (vendor ? 8 : 3))
46557
+ if (depth > (vendor ? 32 : 3))
46375
46558
  return { ...scan, complete: false };
46376
- const children = readdirSync6(path, { withFileTypes: true }).sort((a3, b3) => a3.name < b3.name ? -1 : a3.name > b3.name ? 1 : 0);
46559
+ const children = [], directory = opendirSync3(path);
46560
+ try {
46561
+ let child;
46562
+ while ((child = directory.readSync()) !== null) {
46563
+ admit(join15(path, child.name));
46564
+ children.push(child);
46565
+ }
46566
+ } finally {
46567
+ directory.closeSync();
46568
+ }
46569
+ children.sort((a3, b3) => a3.name < b3.name ? -1 : a3.name > b3.name ? 1 : 0);
46377
46570
  if (pluginCache)
46378
46571
  children.sort((a3, b3) => Number(a3.isSymbolicLink()) - Number(b3.isSymbolicLink()));
46379
46572
  for (const { name } of children) {
@@ -46384,15 +46577,15 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
46384
46577
  const isVendor = vendor || name === ".system";
46385
46578
  if (isVendor && !options.includeVendor)
46386
46579
  continue;
46387
- const child = join14(path, name);
46388
- if (isVendor && lstatSync7(child, { throwIfNoEntry: false })?.isSymbolicLink()) {
46580
+ const child = join15(path, name);
46581
+ if (isVendor && lstatSync9(child, { throwIfNoEntry: false })?.isSymbolicLink()) {
46389
46582
  const target = statSync3(child, { throwIfNoEntry: false });
46390
46583
  if (target?.isFile() || pluginCache && target?.isDirectory() && emptySiblingCacheAlias(child, path)) {
46391
46584
  scan.entries++;
46392
46585
  continue;
46393
46586
  }
46394
46587
  }
46395
- const childScan = visit2(agent, child, isVendor, depth + 1, pluginCache);
46588
+ const childScan = visit2(agent, child, isVendor, depth + 1, pluginCache, true);
46396
46589
  scan.complete &&= childScan.complete;
46397
46590
  scan.hasSkills ||= childScan.hasSkills;
46398
46591
  scan.entries += childScan.entries;
@@ -46411,8 +46604,8 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
46411
46604
  scanRoot(agent, path);
46412
46605
  if (options.includeVendor) {
46413
46606
  for (const agent of ["codex", "claude"])
46414
- scanRoot(agent, canonicalAgentPath(join14(home, `.${agent}`, "plugins", "cache"), aliases), true, true);
46415
- scanRoot("gemini", join14(home, ".gemini", "extensions"), true);
46607
+ scanRoot(agent, canonicalAgentPath(join15(home, `.${agent}`, "plugins", "cache"), aliases), true, true);
46608
+ scanRoot("gemini", join15(home, ".gemini", "extensions"), true);
46416
46609
  }
46417
46610
  const configured = options.configured ? INTEGRATION_AGENTS.flatMap((agent) => resolveAgentDiscovery({ home, agent, reviewed: options.discoveryInputs, canonical: (path) => canonicalAgentPath(path, aliases) }).roots.map((path) => ({ agent, path }))) : [];
46418
46611
  for (const root3 of [...options.agentRoots ?? [], ...configured])
@@ -46510,12 +46703,12 @@ function disableCodexSkills(text2, skills, aliases, bridgePath) {
46510
46703
  let result = text2;
46511
46704
  const selections2 = [...skills.filter((entry) => entry.agent === "codex" && !entry.bridge).map((skill) => ({ path: skill.path, enabled: false })), { path: bridgePath, enabled: true }];
46512
46705
  for (const skill of selections2) {
46513
- const path = join14(skill.path, "SKILL.md");
46706
+ const path = join15(skill.path, "SKILL.md");
46514
46707
  let found = false;
46515
46708
  result = result.replace(/^\[\[skills\.config\]\][^\n]*(?:\n(?!\s*\[)[^\n]*)*/gm, (section) => {
46516
46709
  const parsed = Bun.TOML.parse(section);
46517
46710
  const declared = parsed.skills?.config?.[0]?.path;
46518
- if (!declared || ![resolve5(path), resolve5(skill.path)].includes(canonicalAgentPath(declared, aliases)))
46711
+ if (!declared || ![resolve7(path), resolve7(skill.path)].includes(canonicalAgentPath(declared, aliases)))
46519
46712
  return section;
46520
46713
  found = true;
46521
46714
  return /^\s*enabled\s*=/m.test(section) ? section.replace(/^\s*enabled\s*=.*$/m, `enabled = ${skill.enabled}`) : `${section.trimEnd()}
@@ -46539,7 +46732,7 @@ function planAgentIntegration(options) {
46539
46732
  if (!/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(profileId) || profileId.includes(".."))
46540
46733
  throw new Error("Invalid selection profile id");
46541
46734
  const aliases = rootAliases(home, options.allowRootAliases);
46542
- const policyPath = join14(dataDir2, "agent-policy.json");
46735
+ const policyPath = join15(dataDir2, "agent-policy.json");
46543
46736
  assertSafePath(policyPath);
46544
46737
  const priorSnapshot = readManagedSkillPolicySnapshot(dataDir2), previousPolicy = priorSnapshot?.text ?? null, policy = priorSnapshot?.value ?? {};
46545
46738
  if (policy.bridge !== undefined && (!policy.bridge || typeof policy.bridge !== "object" || Array.isArray(policy.bridge)))
@@ -46556,19 +46749,19 @@ function planAgentIntegration(options) {
46556
46749
  if (!INTEGRATION_AGENTS.includes(agent))
46557
46750
  throw new Error(`Unsupported agent: ${agent}`);
46558
46751
  const adapter = AGENT_ADAPTERS[agent];
46559
- const bridgePath = canonicalAgentPath(join14(home, adapter.root, CLI_BRIDGE_NAME), aliases);
46752
+ const bridgePath = canonicalAgentPath(join15(home, adapter.root, CLI_BRIDGE_NAME), aliases);
46560
46753
  assertSafePath(bridgePath);
46561
46754
  if (existsSync5(bridgePath) && !isOwnedCliBridge(bridgePath, [bridgePath]))
46562
46755
  throw new Error(`Refusing to overwrite an unrecognized or modified Skills bridge: ${bridgePath}`);
46563
46756
  for (const [name, after2] of Object.entries(CLI_BRIDGE_FILES)) {
46564
- const path2 = join14(bridgePath, name), before2 = readOptional(path2);
46757
+ const path2 = join15(bridgePath, name), before2 = readOptional(path2);
46565
46758
  if (before2 !== after2)
46566
46759
  changes.push({ path: path2, before: before2, after: after2 });
46567
46760
  }
46568
- const path = canonicalAgentPath(join14(home, adapter.config), aliases);
46761
+ const path = canonicalAgentPath(join15(home, adapter.config), aliases);
46569
46762
  const before = readOptional(path);
46570
46763
  if (agent === "hermes") {
46571
- const supervisorPath = join14(dataDir2, "agent-hooks", "hermes.js"), supervisorBefore = readOptional(supervisorPath), supervisorAfter = renderHermesSupervisor(options.command ?? "skills", profileId);
46764
+ const supervisorPath = join15(dataDir2, "agent-hooks", "hermes.js"), supervisorBefore = readOptional(supervisorPath), supervisorAfter = renderHermesSupervisor(options.command ?? "skills", profileId);
46572
46765
  const priorCommand = policy.bridge?.commands?.hermes, priorProfile = policy.bridge?.profiles?.hermes ?? policy.profileId;
46573
46766
  const previous = policy.bridge?.supervisors?.hermes;
46574
46767
  if (supervisorBefore !== null && supervisorBefore !== supervisorAfter && !(previous?.path === supervisorPath && typeof priorCommand === "string" && typeof priorProfile === "string" && supervisorBefore === renderHermesSupervisor(priorCommand, priorProfile)))
@@ -46579,7 +46772,7 @@ function planAgentIntegration(options) {
46579
46772
  const after2 = configureHermesHooks(before, supervisor, previous);
46580
46773
  if (before !== after2)
46581
46774
  changes.push({ path, before, after: after2 });
46582
- const optOut = join14(home, ".hermes", HERMES_OPT_OUT), optOutBefore = readOptional(optOut);
46775
+ const optOut = join15(home, ".hermes", HERMES_OPT_OUT), optOutBefore = readOptional(optOut);
46583
46776
  if (optOutBefore === null)
46584
46777
  changes.push({ path: optOut, before: null, after: `Managed by @hasna/skills: bundled native skill reseeding is disabled.
46585
46778
  ` });
@@ -46591,7 +46784,7 @@ function planAgentIntegration(options) {
46591
46784
  if (!permission || typeof permission !== "object" || Array.isArray(permission))
46592
46785
  throw new Error("Expected OpenCode permission object");
46593
46786
  config.permission = { ...permission, skill: { "*": "deny", [CLI_BRIDGE_NAME]: "allow" } };
46594
- const pluginPath = join14(home, ".config", "opencode", "plugins", "skills-cli.js"), pluginBefore = readOptional(pluginPath);
46787
+ const pluginPath = join15(home, ".config", "opencode", "plugins", "skills-cli.js"), pluginBefore = readOptional(pluginPath);
46595
46788
  const pluginAfter = renderOpenCodePlugin(options.command ?? "skills", profileId);
46596
46789
  const priorCommand = policy.bridge?.commands?.opencode;
46597
46790
  const ownedPrevious = typeof priorCommand === "string" && typeof policy.profileId === "string" && pluginBefore === renderOpenCodePlugin(priorCommand, policy.bridge?.profiles?.opencode ?? policy.profileId);
@@ -46608,7 +46801,7 @@ function planAgentIntegration(options) {
46608
46801
  if (before !== after)
46609
46802
  changes.push({ path, before, after });
46610
46803
  if (agent === "codex") {
46611
- const configPath = canonicalAgentPath(join14(home, ".codex", "config.toml"), aliases), previous = readOptional(configPath);
46804
+ const configPath = canonicalAgentPath(join15(home, ".codex", "config.toml"), aliases), previous = readOptional(configPath);
46612
46805
  const next = disableCodexSkills(previous ?? "", nativeSkills, aliases, bridgePath);
46613
46806
  if (next !== (previous ?? ""))
46614
46807
  changes.push({ path: configPath, before: previous, after: next });
@@ -46621,12 +46814,12 @@ function planAgentIntegration(options) {
46621
46814
  version: CLI_BRIDGE_VERSION,
46622
46815
  digest: CLI_BRIDGE_DIGEST,
46623
46816
  agents: [...new Set([...priorAgents, ...options.agents])].sort(),
46624
- home: resolve5(home),
46817
+ home: resolve7(home),
46625
46818
  includeVendor: true,
46626
- ...options.agents.includes("hermes") ? { supervisors: { ...policy.bridge?.supervisors, hermes: { path: join14(dataDir2, "agent-hooks", "hermes.js"), runtime: process.execPath, sha256: sha(renderHermesSupervisor(options.command ?? "skills", profileId)) } } } : {},
46819
+ ...options.agents.includes("hermes") ? { supervisors: { ...policy.bridge?.supervisors, hermes: { path: join15(dataDir2, "agent-hooks", "hermes.js"), runtime: process.execPath, sha256: sha(renderHermesSupervisor(options.command ?? "skills", profileId)) } } } : {},
46627
46820
  commands: { ...policy.bridge?.commands, ...Object.fromEntries(options.agents.map((agent) => [agent, options.command ?? "skills"])) },
46628
46821
  profiles: Object.fromEntries([...new Set([...priorAgents, ...options.agents])].sort().map((agent) => [agent, options.agents.includes(agent) ? profileId : policy.bridge?.profiles?.[agent] ?? policy.profileId])),
46629
- disabledBuiltins: options.agents.includes("codex") ? nativeSkills.filter((entry) => entry.agent === "codex" && entry.vendor && entry.path.startsWith(canonicalAgentPath(join14(home, ".codex", "skills", ".system"), aliases) + sep2)).map((entry) => ({ path: entry.path, hash: entry.hash })) : policy.bridge?.disabledBuiltins ?? [],
46822
+ disabledBuiltins: options.agents.includes("codex") ? nativeSkills.filter((entry) => entry.agent === "codex" && entry.vendor && entry.path.startsWith(canonicalAgentPath(join15(home, ".codex", "skills", ".system"), aliases) + sep2)).map((entry) => ({ path: entry.path, hash: entry.hash })) : policy.bridge?.disabledBuiltins ?? [],
46630
46823
  rootAliases: aliases,
46631
46824
  discovery: { ...policy.bridge?.discovery, ...Object.fromEntries(discoveryAfter.map((binding) => [binding.agent, binding])) }
46632
46825
  } };
@@ -46638,7 +46831,7 @@ function planAgentIntegration(options) {
46638
46831
  }
46639
46832
  function atomicWrite2(path, content) {
46640
46833
  assertSafePath(path);
46641
- mkdirSync5(dirname9(path), { recursive: true, mode: 448 });
46834
+ mkdirSync5(dirname11(path), { recursive: true, mode: 448 });
46642
46835
  const temporary = `${path}.skills-${randomUUID6()}`;
46643
46836
  try {
46644
46837
  writeFileSync3(temporary, content, { mode: 384, flag: "wx" });
@@ -46649,12 +46842,12 @@ function atomicWrite2(path, content) {
46649
46842
  }
46650
46843
  }
46651
46844
  function applyAgentIntegration(plan) {
46652
- const policyPath = join14(plan.dataDir, "agent-policy.json");
46845
+ const policyPath = join15(plan.dataDir, "agent-policy.json");
46653
46846
  assertSafePath(policyPath);
46654
- const currentText = (path) => resolve5(path) === resolve5(policyPath) ? readManagedSkillPolicySnapshot(plan.dataDir)?.text ?? null : readOptional(path);
46847
+ const currentText = (path) => resolve7(path) === resolve7(policyPath) ? readManagedSkillPolicySnapshot(plan.dataDir)?.text ?? null : readOptional(path);
46655
46848
  readManagedSkillPolicySnapshot(plan.dataDir);
46656
46849
  for (const change of plan.changes)
46657
- if (resolve5(change.path) === resolve5(policyPath))
46850
+ if (resolve7(change.path) === resolve7(policyPath))
46658
46851
  parseManagedSkillPolicy(change.after);
46659
46852
  const aliases = plan.rootAliases ?? [];
46660
46853
  recheckRootAliases(aliases);
@@ -46665,7 +46858,7 @@ function applyAgentIntegration(plan) {
46665
46858
  for (const change of plan.changes)
46666
46859
  if (currentText(change.path) !== change.before)
46667
46860
  throw new Error(`Configuration changed after planning: ${change.path}`);
46668
- const backupRoot = join14(plan.dataDir, "migration", randomUUID6()), backups = [], written = [], createdDirectories = new Set;
46861
+ const backupRoot = join15(plan.dataDir, "migration", randomUUID6()), backups = [], written = [], createdDirectories = new Set;
46669
46862
  if (!plan.changes.length) {
46670
46863
  recheckRootAliases(aliases);
46671
46864
  return { changed: [], backups, ...aliases.length ? { rootAliases: aliases } : {} };
@@ -46675,7 +46868,7 @@ function applyAgentIntegration(plan) {
46675
46868
  chmodSync(backupRoot, 448);
46676
46869
  for (const [index, change] of plan.changes.entries())
46677
46870
  if (change.before !== null) {
46678
- const backup = join14(backupRoot, `${index}-${sha(change.path).slice(0, 12)}.backup`);
46871
+ const backup = join15(backupRoot, `${index}-${sha(change.path).slice(0, 12)}.backup`);
46679
46872
  writeFileSync3(backup, change.before, { mode: 384, flag: "wx" });
46680
46873
  backups.push(backup);
46681
46874
  }
@@ -46684,7 +46877,7 @@ function applyAgentIntegration(plan) {
46684
46877
  recheckRootAliases(aliases);
46685
46878
  if (currentText(change.path) !== change.before)
46686
46879
  throw new Error(`Configuration changed after planning: ${change.path}`);
46687
- for (let directory = dirname9(change.path);!existsSync5(directory); directory = dirname9(directory))
46880
+ for (let directory = dirname11(change.path);!existsSync5(directory); directory = dirname11(directory))
46688
46881
  createdDirectories.add(directory);
46689
46882
  const after = change.after;
46690
46883
  atomicWrite2(change.path, after);
@@ -46693,7 +46886,7 @@ function applyAgentIntegration(plan) {
46693
46886
  recheckRootAliases(aliases);
46694
46887
  for (const binding of plan.discoveryAfter ?? [])
46695
46888
  verifyAgentDiscovery(binding);
46696
- atomicWrite2(join14(backupRoot, "receipt.json"), JSON.stringify({ version: 1, changes: written.map((change) => ({ path: change.path, beforeHash: change.before === null ? null : sha(change.before), afterHash: sha(change.after) })), backups, ...aliases.length ? { rootAliases: aliases } : {} }) + `
46889
+ atomicWrite2(join15(backupRoot, "receipt.json"), JSON.stringify({ version: 1, changes: written.map((change) => ({ path: change.path, beforeHash: change.before === null ? null : sha(change.before), afterHash: sha(change.after) })), backups, ...aliases.length ? { rootAliases: aliases } : {} }) + `
46697
46890
  `);
46698
46891
  } catch (error) {
46699
46892
  for (const change of written.reverse()) {
@@ -46724,11 +46917,11 @@ function applyAgentIntegration(plan) {
46724
46917
  }
46725
46918
  function syncArchiveDirectory(path) {
46726
46919
  assertSafePath(path);
46727
- const descriptor = openSync5(path, constants4.O_RDONLY | constants4.O_DIRECTORY | constants4.O_NOFOLLOW | constants4.O_NONBLOCK);
46920
+ const descriptor = openSync6(path, constants5.O_RDONLY | constants5.O_DIRECTORY | constants5.O_NOFOLLOW | constants5.O_NONBLOCK);
46728
46921
  try {
46729
46922
  fsyncSync(descriptor);
46730
46923
  } finally {
46731
- closeSync5(descriptor);
46924
+ closeSync6(descriptor);
46732
46925
  }
46733
46926
  }
46734
46927
  function writeArchiveJournal(path, value) {
@@ -46736,18 +46929,18 @@ function writeArchiveJournal(path, value) {
46736
46929
  const temporary = `${path}.skills-${randomUUID6()}`;
46737
46930
  let descriptor;
46738
46931
  try {
46739
- descriptor = openSync5(temporary, constants4.O_WRONLY | constants4.O_CREAT | constants4.O_EXCL | constants4.O_NOFOLLOW, 384);
46932
+ descriptor = openSync6(temporary, constants5.O_WRONLY | constants5.O_CREAT | constants5.O_EXCL | constants5.O_NOFOLLOW, 384);
46740
46933
  writeFileSync3(descriptor, `${JSON.stringify(value)}
46741
46934
  `);
46742
46935
  fsyncSync(descriptor);
46743
- closeSync5(descriptor);
46936
+ closeSync6(descriptor);
46744
46937
  descriptor = undefined;
46745
46938
  renameSync2(temporary, path);
46746
- syncArchiveDirectory(dirname9(path));
46939
+ syncArchiveDirectory(dirname11(path));
46747
46940
  } finally {
46748
46941
  if (descriptor !== undefined)
46749
- closeSync5(descriptor);
46750
- if (lstatSync7(temporary, { throwIfNoEntry: false }))
46942
+ closeSync6(descriptor);
46943
+ if (lstatSync9(temporary, { throwIfNoEntry: false }))
46751
46944
  unlinkSync2(temporary);
46752
46945
  }
46753
46946
  }
@@ -46758,7 +46951,7 @@ function archiveNativeSkills(inventory, options) {
46758
46951
  recheckRootAliases(aliases);
46759
46952
  for (const entry of inventory.filter((entry2) => entry2.bridge)) {
46760
46953
  const adapter = AGENT_ADAPTERS[entry.agent];
46761
- const expected = adapter && entry.bridgeHome ? canonicalAgentPath(join14(entry.bridgeHome, adapter.root, CLI_BRIDGE_NAME), aliases) : undefined;
46954
+ const expected = adapter && entry.bridgeHome ? canonicalAgentPath(join15(entry.bridgeHome, adapter.root, CLI_BRIDGE_NAME), aliases) : undefined;
46762
46955
  if (!expected || treeHash(entry.path) !== entry.hash || !isOwnedCliBridge(entry.path, [expected]))
46763
46956
  throw new Error(`Skills bridge changed after planning: ${entry.path}`);
46764
46957
  }
@@ -46768,11 +46961,11 @@ function archiveNativeSkills(inventory, options) {
46768
46961
  throw new Error(`Native skill changed after planning: ${entry.path}`);
46769
46962
  if (!selected.length)
46770
46963
  return { entries: [], ...aliases.length ? { rootAliases: aliases } : {} };
46771
- const operationId = randomUUID6(), archiveRoot = join14(options.dataDir ?? getDataDir(), "migration", operationId, "native"), receiptPath = join14(archiveRoot, "receipt.json");
46964
+ const operationId = randomUUID6(), archiveRoot = join15(options.dataDir ?? getDataDir(), "migration", operationId, "native"), receiptPath = join15(archiveRoot, "receipt.json");
46772
46965
  const entries = selected.map((entry, index) => ({
46773
- source: entry.vendor ? join14(entry.path, "SKILL.md") : entry.path,
46774
- archive: join14(archiveRoot, `${index}-${sha(entry.path).slice(0, 12)}`),
46775
- hash: entry.vendor ? sha(readNativeBytes(join14(entry.path, "SKILL.md"))) : entry.hash,
46966
+ source: entry.vendor ? join15(entry.path, "SKILL.md") : entry.path,
46967
+ archive: join15(archiveRoot, `${index}-${sha(entry.path).slice(0, 12)}`),
46968
+ hash: entry.vendor ? sha(readNativeBytes(join15(entry.path, "SKILL.md"))) : entry.hash,
46776
46969
  ...entry.vendor ? { discoveryOnly: true } : {},
46777
46970
  status: "planned"
46778
46971
  }));
@@ -46780,7 +46973,7 @@ function archiveNativeSkills(inventory, options) {
46780
46973
  const moved = [];
46781
46974
  const verifyArchive = (entry) => {
46782
46975
  assertSafePath(entry.archive);
46783
- const stat = lstatSync7(entry.archive);
46976
+ const stat = lstatSync9(entry.archive);
46784
46977
  if (entry.discoveryOnly ? !stat.isFile() : !stat.isDirectory())
46785
46978
  throw new Error("Archive type changed");
46786
46979
  if ((entry.discoveryOnly ? sha(readNativeBytes(entry.archive)) : treeHash(entry.archive)) !== entry.hash)
@@ -46788,14 +46981,14 @@ function archiveNativeSkills(inventory, options) {
46788
46981
  };
46789
46982
  assertSafePath(archiveRoot);
46790
46983
  const created = [];
46791
- for (let path = archiveRoot;!existsSync5(path); path = dirname9(path))
46984
+ for (let path = archiveRoot;!existsSync5(path); path = dirname11(path))
46792
46985
  created.push(path);
46793
46986
  mkdirSync5(archiveRoot, { recursive: true, mode: 448 });
46794
46987
  try {
46795
46988
  for (const directory of created)
46796
46989
  syncArchiveDirectory(directory);
46797
46990
  if (created.length)
46798
- syncArchiveDirectory(dirname9(created.at(-1)));
46991
+ syncArchiveDirectory(dirname11(created.at(-1)));
46799
46992
  writeArchiveJournal(receiptPath, journal);
46800
46993
  for (const [index, entry] of selected.entries()) {
46801
46994
  recheckRootAliases(aliases);
@@ -46807,7 +47000,7 @@ function archiveNativeSkills(inventory, options) {
46807
47000
  writeArchiveJournal(receiptPath, journal);
46808
47001
  renameSync2(move.source, move.archive);
46809
47002
  moved.push(move);
46810
- syncArchiveDirectory(dirname9(move.source));
47003
+ syncArchiveDirectory(dirname11(move.source));
46811
47004
  syncArchiveDirectory(archiveRoot);
46812
47005
  verifyArchive(move);
46813
47006
  move.status = "archived";
@@ -46828,7 +47021,7 @@ function archiveNativeSkills(inventory, options) {
46828
47021
  recheckRootAliases(aliases);
46829
47022
  assertSafePath(entry.source);
46830
47023
  assertSafePath(entry.archive);
46831
- if (lstatSync7(entry.source, { throwIfNoEntry: false })) {
47024
+ if (lstatSync9(entry.source, { throwIfNoEntry: false })) {
46832
47025
  entry.status = "recovery-required";
46833
47026
  entry.conflict = "source-occupied";
46834
47027
  continue;
@@ -46842,10 +47035,10 @@ function archiveNativeSkills(inventory, options) {
46842
47035
  }
46843
47036
  if (entry.discoveryOnly) {
46844
47037
  linkSync(entry.archive, entry.source);
46845
- syncArchiveDirectory(dirname9(entry.source));
47038
+ syncArchiveDirectory(dirname11(entry.source));
46846
47039
  unlinkSync2(entry.archive);
46847
47040
  } else {
46848
- if (lstatSync7(entry.source, { throwIfNoEntry: false })) {
47041
+ if (lstatSync9(entry.source, { throwIfNoEntry: false })) {
46849
47042
  entry.status = "recovery-required";
46850
47043
  entry.conflict = "source-occupied";
46851
47044
  continue;
@@ -46853,7 +47046,7 @@ function archiveNativeSkills(inventory, options) {
46853
47046
  renameSync2(entry.archive, entry.source);
46854
47047
  }
46855
47048
  entry.status = "restored";
46856
- syncArchiveDirectory(dirname9(entry.source));
47049
+ syncArchiveDirectory(dirname11(entry.source));
46857
47050
  syncArchiveDirectory(archiveRoot);
46858
47051
  } catch {
46859
47052
  entry.status = "recovery-required";
@@ -46890,7 +47083,7 @@ import {
46890
47083
  statSync as statSync8,
46891
47084
  writeFileSync as writeFileSync5
46892
47085
  } from "fs";
46893
- import { basename as basename2, dirname as dirname11, isAbsolute as isAbsolute7, join as join19, normalize as normalize2, relative as relative4, resolve as resolve6, sep as sep4 } from "path";
47086
+ import { basename as basename2, dirname as dirname13, isAbsolute as isAbsolute9, join as join20, normalize as normalize2, relative as relative4, resolve as resolve8, sep as sep4 } from "path";
46894
47087
 
46895
47088
  // src/lib/registry-data/development-tools.ts
46896
47089
  var DEVELOPMENT_TOOLS_SKILLS = [
@@ -47603,7 +47796,7 @@ var SKILLS = [
47603
47796
 
47604
47797
  // src/lib/hosted-skill-set.ts
47605
47798
  import { existsSync as existsSync6, readFileSync as readFileSync10, readdirSync as readdirSync7, statSync as statSync4 } from "fs";
47606
- import { join as join15 } from "path";
47799
+ import { join as join16 } from "path";
47607
47800
  var HOSTED_RUNTIMES = new Set(["hosted"]);
47608
47801
  var HOSTED_SOURCES = new Set(["remote", "private-hosted"]);
47609
47802
  function normalizeMarker(value) {
@@ -47616,7 +47809,7 @@ function isHostedMetadataPackage(pkg) {
47616
47809
  return HOSTED_RUNTIMES.has(normalizeMarker(skills.runtime)) || HOSTED_SOURCES.has(normalizeMarker(skills.source));
47617
47810
  }
47618
47811
  function isHostedMetadataSkillDir(skillDir) {
47619
- const pkgPath = join15(skillDir, "package.json");
47812
+ const pkgPath = join16(skillDir, "package.json");
47620
47813
  if (!existsSync6(pkgPath))
47621
47814
  return false;
47622
47815
  try {
@@ -47641,8 +47834,8 @@ var BRACE_SOURCE_EXCLUSION = new RegExp(`^!skills/\\{(${SLUG}(?:,${SLUG})+)\\}/s
47641
47834
  var SINGLE_SOURCE_EXCLUSION = new RegExp(`^!skills/(${SLUG})/src$`);
47642
47835
 
47643
47836
  // src/lib/skill-validation.ts
47644
- import { existsSync as existsSync7, lstatSync as lstatSync8, readFileSync as readFileSync11, readdirSync as readdirSync8, statSync as statSync5 } from "fs";
47645
- import { isAbsolute as isAbsolute6, join as join16, normalize } from "path";
47837
+ import { existsSync as existsSync7, lstatSync as lstatSync10, readFileSync as readFileSync11, readdirSync as readdirSync8, statSync as statSync5 } from "fs";
47838
+ import { isAbsolute as isAbsolute8, join as join17, normalize } from "path";
47646
47839
  var VALID_SKILL_KINDS = ["executable", "instruction"];
47647
47840
  var DOC_FILES = ["SKILL.md", "README.md", "CLAUDE.md"];
47648
47841
  var RESERVED_SKILL_ENTRIES = new Set([
@@ -47705,7 +47898,7 @@ function sortMessages(messages) {
47705
47898
  return [...messages].sort((a3, b3) => a3.code.localeCompare(b3.code) || a3.message.localeCompare(b3.message));
47706
47899
  }
47707
47900
  function isSafeRelativePath(value) {
47708
- if (!value.trim() || isAbsolute6(value))
47901
+ if (!value.trim() || isAbsolute8(value))
47709
47902
  return false;
47710
47903
  const normalized = normalize(value).replace(/\\/g, "/");
47711
47904
  return normalized !== ".." && !normalized.startsWith("../") && !normalized.includes("/../");
@@ -47805,11 +47998,11 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
47805
47998
  add(issues, "skill.name_invalid", `Skill name '${bareName}' must use lowercase letters, numbers, dots, underscores, or hyphens`);
47806
47999
  }
47807
48000
  for (const entry of readdirSync8(skillPath).sort()) {
47808
- const entryPath = join16(skillPath, entry);
48001
+ const entryPath = join17(skillPath, entry);
47809
48002
  if (RESERVED_SKILL_ENTRIES.has(entry)) {
47810
48003
  add(issues, "skill.reserved_file", `Reserved file '${entry}' is not allowed in skill packages`);
47811
48004
  }
47812
- if (lstatSync8(entryPath).isSymbolicLink()) {
48005
+ if (lstatSync10(entryPath).isSymbolicLink()) {
47813
48006
  add(issues, "skill.symlink_forbidden", `Symlink '${entry}' is not allowed in skill packages`);
47814
48007
  }
47815
48008
  if (!KNOWN_TOP_LEVEL_ENTRIES.has(entry)) {
@@ -47817,13 +48010,13 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
47817
48010
  }
47818
48011
  }
47819
48012
  for (const docFile of DOC_FILES) {
47820
- if (existsSync7(join16(skillPath, docFile)))
48013
+ if (existsSync7(join17(skillPath, docFile)))
47821
48014
  metadata.docFiles.push(docFile);
47822
48015
  }
47823
48016
  if (metadata.docFiles.length === 0) {
47824
48017
  add(issues, "skill.docs_missing", "Missing documentation file: expected SKILL.md, README.md, or CLAUDE.md");
47825
48018
  }
47826
- const skillMdPath = join16(skillPath, "SKILL.md");
48019
+ const skillMdPath = join17(skillPath, "SKILL.md");
47827
48020
  if (existsSync7(skillMdPath)) {
47828
48021
  const frontmatter = parseSkillFrontmatter(readFileSync11(skillMdPath, "utf-8"));
47829
48022
  if (!frontmatter) {
@@ -47867,7 +48060,7 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
47867
48060
  }
47868
48061
  metadata.kind = resolvedKind;
47869
48062
  const isInstruction = resolvedKind === "instruction";
47870
- const pkgPath = join16(skillPath, "package.json");
48063
+ const pkgPath = join17(skillPath, "package.json");
47871
48064
  if (!existsSync7(pkgPath)) {
47872
48065
  if (!isInstruction)
47873
48066
  add(issues, "package.missing", "Missing package.json");
@@ -47926,7 +48119,7 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
47926
48119
  add(issues, "package.bin_target_unsafe", `package.json bin '${command3}' target '${target}' must stay inside the skill directory`);
47927
48120
  continue;
47928
48121
  }
47929
- const targetPath = join16(skillPath, target);
48122
+ const targetPath = join17(skillPath, target);
47930
48123
  if (!existsSync7(targetPath)) {
47931
48124
  add(warnings, "package.bin_target_missing", `package.json bin '${command3}' target '${target}' is not present before build`);
47932
48125
  } else if (statSync5(targetPath).isDirectory()) {
@@ -47944,17 +48137,17 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
47944
48137
  metadata.runtime = "none";
47945
48138
  } else {
47946
48139
  metadata.runtime = hostedMetadata ? "hosted" : "local";
47947
- const srcDir = join16(skillPath, "src");
48140
+ const srcDir = join17(skillPath, "src");
47948
48141
  if (hostedMetadata) {
47949
48142
  if (existsSync7(srcDir)) {
47950
48143
  add(issues, "skill.hosted_source_forbidden", "Hosted metadata skills must not include local implementation source");
47951
48144
  }
47952
48145
  } else if (!existsSync7(srcDir)) {
47953
48146
  add(issues, "skill.src_missing", "Missing src/ directory");
47954
- } else if (!existsSync7(join16(srcDir, "index.ts")) && !existsSync7(join16(srcDir, "index.js"))) {
48147
+ } else if (!existsSync7(join17(srcDir, "index.ts")) && !existsSync7(join17(srcDir, "index.js"))) {
47955
48148
  add(issues, "skill.src_index_missing", "Missing src/index.ts or src/index.js");
47956
48149
  } else {
47957
- const indexPath = existsSync7(join16(srcDir, "index.ts")) ? join16(srcDir, "index.ts") : join16(srcDir, "index.js");
48150
+ const indexPath = existsSync7(join17(srcDir, "index.ts")) ? join17(srcDir, "index.ts") : join17(srcDir, "index.js");
47958
48151
  const size = statSync5(indexPath).size;
47959
48152
  if (size < 50)
47960
48153
  add(warnings, "skill.src_index_minimal", `Source entry point is very small (${size}B)`);
@@ -47979,7 +48172,7 @@ function validateRegistryConsistency(registry, skillsDir) {
47979
48172
  return false;
47980
48173
  })));
47981
48174
  const skillDirs = existsSync7(skillsDir) ? readdirSync8(skillsDir).filter((entry) => {
47982
- const fullPath = join16(skillsDir, entry);
48175
+ const fullPath = join17(skillsDir, entry);
47983
48176
  return !entry.startsWith(".") && entry !== "_common" && statSync5(fullPath).isDirectory();
47984
48177
  }) : [];
47985
48178
  const directoryNames = new Set(skillDirs);
@@ -47995,9 +48188,9 @@ function validateRegistryConsistency(registry, skillsDir) {
47995
48188
  }
47996
48189
 
47997
48190
  // src/lib/skill-hash.ts
47998
- import { createHash as createHash11 } from "crypto";
48191
+ import { createHash as createHash13 } from "crypto";
47999
48192
  import { existsSync as existsSync8, readdirSync as readdirSync9, readFileSync as readFileSync12, statSync as statSync6 } from "fs";
48000
- import { join as join17, sep as sep3 } from "path";
48193
+ import { join as join18, sep as sep3 } from "path";
48001
48194
  var CONTENT_HASH_ALGORITHM = "sha256";
48002
48195
  var HASH_EXCLUDE_DIRS = new Set([".git", "node_modules", "dist", "build", ".turbo"]);
48003
48196
  function excludedHashEntry(name, directory) {
@@ -48059,7 +48252,7 @@ function collectBundleFiles(skillPath) {
48059
48252
  if (seen.has(entry))
48060
48253
  continue;
48061
48254
  seen.add(entry);
48062
- const absolute = join17(skillPath, entry);
48255
+ const absolute = join18(skillPath, entry);
48063
48256
  if (!existsSync8(absolute))
48064
48257
  continue;
48065
48258
  if (statSync6(absolute).isDirectory())
@@ -48073,7 +48266,7 @@ function collectDirectory(files, dir, rel) {
48073
48266
  for (const entry of readdirSync9(dir).sort()) {
48074
48267
  if (entry.startsWith("."))
48075
48268
  continue;
48076
- const absolute = join17(dir, entry);
48269
+ const absolute = join18(dir, entry);
48077
48270
  const childRel = `${rel}/${entry}`;
48078
48271
  let stats;
48079
48272
  try {
@@ -48119,13 +48312,13 @@ function* bundleHashParts(files) {
48119
48312
  yield new TextEncoder().encode("\x00");
48120
48313
  }
48121
48314
  function hashBundleFiles(files) {
48122
- const hash2 = createHash11(CONTENT_HASH_ALGORITHM);
48315
+ const hash2 = createHash13(CONTENT_HASH_ALGORITHM);
48123
48316
  for (const part of bundleHashParts(files))
48124
48317
  hash2.update(part);
48125
48318
  return hash2.digest("hex");
48126
48319
  }
48127
48320
  async function hashBundleFilesCooperatively(files, check) {
48128
- const hash2 = createHash11(CONTENT_HASH_ALGORITHM);
48321
+ const hash2 = createHash13(CONTENT_HASH_ALGORITHM);
48129
48322
  let bytesSinceYield = 0;
48130
48323
  for (const part of bundleHashParts(files)) {
48131
48324
  for (let offset = 0;offset < part.byteLength; offset += 64 * 1024) {
@@ -48134,7 +48327,7 @@ async function hashBundleFilesCooperatively(files, check) {
48134
48327
  hash2.update(chunk);
48135
48328
  bytesSinceYield += chunk.byteLength;
48136
48329
  if (bytesSinceYield >= 256 * 1024) {
48137
- await new Promise((resolve6) => setImmediate(resolve6));
48330
+ await new Promise((resolve8) => setImmediate(resolve8));
48138
48331
  bytesSinceYield = 0;
48139
48332
  }
48140
48333
  }
@@ -48287,7 +48480,7 @@ async function hashContentEntries(entries, options) {
48287
48480
  const normalized = [];
48288
48481
  let normalizedBytes = 0;
48289
48482
  let manifest;
48290
- await new Promise((resolve6) => setImmediate(resolve6));
48483
+ await new Promise((resolve8) => setImmediate(resolve8));
48291
48484
  for (const entry of snapshot) {
48292
48485
  check();
48293
48486
  if (!coveredContentPath(entry.path))
@@ -48300,7 +48493,7 @@ async function hashContentEntries(entries, options) {
48300
48493
  contentLimit("Content hash normalized byte limit exceeded");
48301
48494
  normalizedBytes += file.content.byteLength;
48302
48495
  normalized.push(file);
48303
- await new Promise((resolve6) => setImmediate(resolve6));
48496
+ await new Promise((resolve8) => setImmediate(resolve8));
48304
48497
  }
48305
48498
  normalized.sort((a3, b3) => a3.rel < b3.rel ? -1 : a3.rel > b3.rel ? 1 : 0);
48306
48499
  check();
@@ -48508,13 +48701,13 @@ function validateRuntimeContract(manifest, issues, strict) {
48508
48701
  import {
48509
48702
  cpSync,
48510
48703
  existsSync as existsSync9,
48511
- lstatSync as lstatSync9,
48704
+ lstatSync as lstatSync11,
48512
48705
  mkdirSync as mkdirSync6,
48513
48706
  readFileSync as readFileSync13,
48514
48707
  realpathSync as realpathSync3,
48515
48708
  writeFileSync as writeFileSync4
48516
48709
  } from "fs";
48517
- import { basename, dirname as dirname10, join as join18, relative as relative3 } from "path";
48710
+ import { basename, dirname as dirname12, join as join19, relative as relative3 } from "path";
48518
48711
  var ANY_SEGMENT_COPY_EXCLUDES = new Set([
48519
48712
  ".git",
48520
48713
  ".DS_Store",
@@ -48571,9 +48764,9 @@ function readPortableSkillManifestForImport(skillPath) {
48571
48764
  return readManifest(skillPath, basename(skillPath), normalizeNewPortableSkillName);
48572
48765
  }
48573
48766
  function readManifest(skillPath, fallbackName, normalizeName) {
48574
- const skillJsonPath = join18(skillPath, "skill.json");
48575
- const skillMdPath = join18(skillPath, "SKILL.md");
48576
- const pkgPath = join18(skillPath, "package.json");
48767
+ const skillJsonPath = join19(skillPath, "skill.json");
48768
+ const skillMdPath = join19(skillPath, "SKILL.md");
48769
+ const pkgPath = join19(skillPath, "package.json");
48577
48770
  const jsonManifest = existsSync9(skillJsonPath) ? readJsonObject(skillJsonPath) : undefined;
48578
48771
  const frontmatter = existsSync9(skillMdPath) ? parseSkillFrontmatter(readFileSync13(skillMdPath, "utf-8")) ?? undefined : undefined;
48579
48772
  const pkg = existsSync9(pkgPath) ? readJsonObject(pkgPath) : undefined;
@@ -48604,9 +48797,9 @@ function parseSkillKind(value) {
48604
48797
  return;
48605
48798
  }
48606
48799
  function readDeclaredSkillVersion(skillPath) {
48607
- const skillJsonPath = join18(skillPath, "skill.json");
48608
- const skillMdPath = join18(skillPath, "SKILL.md");
48609
- const pkgPath = join18(skillPath, "package.json");
48800
+ const skillJsonPath = join19(skillPath, "skill.json");
48801
+ const skillMdPath = join19(skillPath, "SKILL.md");
48802
+ const pkgPath = join19(skillPath, "package.json");
48610
48803
  const jsonManifest = existsSync9(skillJsonPath) ? readJsonObject(skillJsonPath) : undefined;
48611
48804
  const frontmatter = existsSync9(skillMdPath) ? parseSkillFrontmatter(readFileSync13(skillMdPath, "utf-8")) ?? undefined : undefined;
48612
48805
  const pkg = existsSync9(pkgPath) ? readJsonObject(pkgPath) : undefined;
@@ -48631,7 +48824,7 @@ function createInstructionManifest(name, options) {
48631
48824
  }
48632
48825
  function writeInstructionSkillTemplate(skillPath, manifest) {
48633
48826
  mkdirSync6(skillPath, { recursive: true });
48634
- writeFileSync4(join18(skillPath, "SKILL.md"), renderInstructionSkillMd(manifest));
48827
+ writeFileSync4(join19(skillPath, "SKILL.md"), renderInstructionSkillMd(manifest));
48635
48828
  writeSkillJsonWithHash(skillPath, manifest);
48636
48829
  }
48637
48830
  function renderInstructionSkillMd(manifest) {
@@ -48681,12 +48874,12 @@ function createPortableManifest(name, options) {
48681
48874
  };
48682
48875
  }
48683
48876
  function writePortableSkillTemplate(skillPath, manifest) {
48684
- mkdirSync6(join18(skillPath, "src"), { recursive: true });
48685
- writeFileSync4(join18(skillPath, "SKILL.md"), renderSkillMd(manifest));
48686
- writeFileSync4(join18(skillPath, "AGENTS.md"), renderAgentsMd(manifest));
48687
- writeFileSync4(join18(skillPath, "package.json"), renderPackageJson(manifest));
48688
- writeFileSync4(join18(skillPath, "tsconfig.json"), renderTsconfig());
48689
- writeFileSync4(join18(skillPath, "src", "index.ts"), renderEntrypoint(manifest));
48877
+ mkdirSync6(join19(skillPath, "src"), { recursive: true });
48878
+ writeFileSync4(join19(skillPath, "SKILL.md"), renderSkillMd(manifest));
48879
+ writeFileSync4(join19(skillPath, "AGENTS.md"), renderAgentsMd(manifest));
48880
+ writeFileSync4(join19(skillPath, "package.json"), renderPackageJson(manifest));
48881
+ writeFileSync4(join19(skillPath, "tsconfig.json"), renderTsconfig());
48882
+ writeFileSync4(join19(skillPath, "src", "index.ts"), renderEntrypoint(manifest));
48690
48883
  writeSkillJsonWithHash(skillPath, manifest);
48691
48884
  }
48692
48885
  function fillContractDefaults(manifest, entrypoint) {
@@ -48711,7 +48904,7 @@ function writeSkillJsonWithHash(skillPath, manifest) {
48711
48904
  content_hash: undefined
48712
48905
  }
48713
48906
  };
48714
- writeFileSync4(join18(skillPath, "skill.json"), `${JSON.stringify({ ...existing, ...renderSkillJsonObject(withoutHash) }, null, 2)}
48907
+ writeFileSync4(join19(skillPath, "skill.json"), `${JSON.stringify({ ...existing, ...renderSkillJsonObject(withoutHash) }, null, 2)}
48715
48908
  `);
48716
48909
  const hash2 = computeContentHash(skillPath);
48717
48910
  const withHash = {
@@ -48721,12 +48914,12 @@ function writeSkillJsonWithHash(skillPath, manifest) {
48721
48914
  content_hash: hash2
48722
48915
  }
48723
48916
  };
48724
- writeFileSync4(join18(skillPath, "skill.json"), `${JSON.stringify({ ...existing, ...renderSkillJsonObject(withHash) }, null, 2)}
48917
+ writeFileSync4(join19(skillPath, "skill.json"), `${JSON.stringify({ ...existing, ...renderSkillJsonObject(withHash) }, null, 2)}
48725
48918
  `);
48726
48919
  return withHash;
48727
48920
  }
48728
48921
  function readExistingSkillJson(skillPath) {
48729
- const path = join18(skillPath, "skill.json");
48922
+ const path = join19(skillPath, "skill.json");
48730
48923
  if (!existsSync9(path))
48731
48924
  return {};
48732
48925
  try {
@@ -48760,24 +48953,24 @@ function ensurePortableSkillFiles(skillPath, manifest) {
48760
48953
  tags: next.tags?.length ? next.tags : ["custom", next.name]
48761
48954
  };
48762
48955
  const entry = next.commands[0]?.entry ?? "src/index.ts";
48763
- if (entry && !existsSync9(join18(skillPath, entry))) {
48764
- mkdirSync6(dirname10(join18(skillPath, entry)), { recursive: true });
48765
- writeFileSync4(join18(skillPath, entry), renderEntrypoint(next));
48956
+ if (entry && !existsSync9(join19(skillPath, entry))) {
48957
+ mkdirSync6(dirname12(join19(skillPath, entry)), { recursive: true });
48958
+ writeFileSync4(join19(skillPath, entry), renderEntrypoint(next));
48766
48959
  }
48767
- if (!existsSync9(join18(skillPath, "SKILL.md")))
48768
- writeFileSync4(join18(skillPath, "SKILL.md"), renderSkillMd(next));
48960
+ if (!existsSync9(join19(skillPath, "SKILL.md")))
48961
+ writeFileSync4(join19(skillPath, "SKILL.md"), renderSkillMd(next));
48769
48962
  else
48770
- writeFileSync4(join18(skillPath, "SKILL.md"), ensureSkillMdFrontmatter(readFileSync13(join18(skillPath, "SKILL.md"), "utf-8"), next));
48771
- if (!existsSync9(join18(skillPath, "AGENTS.md")))
48772
- writeFileSync4(join18(skillPath, "AGENTS.md"), renderAgentsMd(next));
48963
+ writeFileSync4(join19(skillPath, "SKILL.md"), ensureSkillMdFrontmatter(readFileSync13(join19(skillPath, "SKILL.md"), "utf-8"), next));
48964
+ if (!existsSync9(join19(skillPath, "AGENTS.md")))
48965
+ writeFileSync4(join19(skillPath, "AGENTS.md"), renderAgentsMd(next));
48773
48966
  ensurePackageJson(skillPath, next);
48774
- if (!existsSync9(join18(skillPath, "tsconfig.json")))
48775
- writeFileSync4(join18(skillPath, "tsconfig.json"), renderTsconfig());
48967
+ if (!existsSync9(join19(skillPath, "tsconfig.json")))
48968
+ writeFileSync4(join19(skillPath, "tsconfig.json"), renderTsconfig());
48776
48969
  writeSkillJsonWithHash(skillPath, next);
48777
48970
  return readPortableSkillManifest(skillPath, next.name);
48778
48971
  }
48779
48972
  function ensurePackageJson(skillPath, manifest) {
48780
- const pkgPath = join18(skillPath, "package.json");
48973
+ const pkgPath = join19(skillPath, "package.json");
48781
48974
  const first = manifest.commands[0] ?? { name: manifest.name, entry: "src/index.ts" };
48782
48975
  const commandName = normalizePortableSkillName(first.name || manifest.name);
48783
48976
  const entry = (first.entry ?? "src/index.ts").replace(/^\.\//, "");
@@ -48824,17 +49017,17 @@ function ensureInstructionSkillFiles(skillPath, manifest) {
48824
49017
  inputs: [],
48825
49018
  commands: []
48826
49019
  };
48827
- if (!existsSync9(join18(skillPath, "SKILL.md"))) {
48828
- writeFileSync4(join18(skillPath, "SKILL.md"), renderSkillMd(next));
49020
+ if (!existsSync9(join19(skillPath, "SKILL.md"))) {
49021
+ writeFileSync4(join19(skillPath, "SKILL.md"), renderSkillMd(next));
48829
49022
  } else {
48830
- const path = join18(skillPath, "SKILL.md");
49023
+ const path = join19(skillPath, "SKILL.md");
48831
49024
  const content = readFileSync13(path, "utf8");
48832
49025
  const declaredName = parseSkillFrontmatter(content)?.name;
48833
49026
  if (declaredName && declaredName !== next.name) {
48834
49027
  writeFileSync4(path, renameInstructionFrontmatter(content, next.name));
48835
49028
  }
48836
49029
  }
48837
- const packagePath = join18(skillPath, "package.json");
49030
+ const packagePath = join19(skillPath, "package.json");
48838
49031
  if (existsSync9(packagePath)) {
48839
49032
  const pkg = readJsonObject(packagePath);
48840
49033
  if (typeof pkg.name === "string" && pkg.name !== next.name) {
@@ -48866,7 +49059,7 @@ function renameInstructionFrontmatter(content, name) {
48866
49059
  return renamed + content.slice(frontmatter[0].length);
48867
49060
  }
48868
49061
  function copySkillDirectory(source, destination) {
48869
- const resolvedSource = lstatSync9(source).isSymbolicLink() ? realpathSync3(source) : source;
49062
+ const resolvedSource = lstatSync11(source).isSymbolicLink() ? realpathSync3(source) : source;
48870
49063
  mkdirSync6(destination, { recursive: true });
48871
49064
  cpSync(resolvedSource, destination, {
48872
49065
  recursive: true,
@@ -48879,7 +49072,7 @@ function copySkillDirectory(source, destination) {
48879
49072
  if (isExcludedCopyEntry(segments[i3], i3 === 0))
48880
49073
  return false;
48881
49074
  }
48882
- if (lstatSync9(src).isSymbolicLink())
49075
+ if (lstatSync11(src).isSymbolicLink())
48883
49076
  return false;
48884
49077
  return true;
48885
49078
  }
@@ -49158,11 +49351,11 @@ function getPortableSkillsRoot(options = {}) {
49158
49351
  function resolvePortableSkillsRoot(options, migrate) {
49159
49352
  if (options.rootDir)
49160
49353
  return options.rootDir;
49161
- const appDir = options.homeDir ? join19(options.homeDir, ".hasna", "skills") : migrate ? getDataDir() : getDataDirReadOnly();
49162
- const cache3 = join19(appDir, SKILLS_CACHE_DIRNAME);
49354
+ const appDir = options.homeDir ? join20(options.homeDir, ".hasna", "skills") : migrate ? getDataDir() : getDataDirReadOnly();
49355
+ const cache3 = join20(appDir, SKILLS_CACHE_DIRNAME);
49163
49356
  if (isOwnerLayoutMigrated(appDir) && safeIsDirectory(cache3))
49164
49357
  return cache3;
49165
- const installed = join19(appDir, INSTALLED_SKILLS_DIRNAME);
49358
+ const installed = join20(appDir, INSTALLED_SKILLS_DIRNAME);
49166
49359
  if (migrate)
49167
49360
  migrateLegacySkillLayout(appDir, installed);
49168
49361
  return installed;
@@ -49170,7 +49363,7 @@ function resolvePortableSkillsRoot(options, migrate) {
49170
49363
  function looksLikeSkillDirectory(path) {
49171
49364
  if (!safeIsDirectory(path))
49172
49365
  return false;
49173
- return existsSync10(join19(path, "SKILL.md")) || existsSync10(join19(path, "skill.json")) || existsSync10(join19(path, "package.json"));
49366
+ return existsSync10(join20(path, "SKILL.md")) || existsSync10(join20(path, "skill.json")) || existsSync10(join20(path, "package.json"));
49174
49367
  }
49175
49368
  function migrateLegacySkillLayout(appDir, installed) {
49176
49369
  if (!safeIsDirectory(appDir))
@@ -49180,7 +49373,7 @@ function migrateLegacySkillLayout(appDir, installed) {
49180
49373
  for (const entry of readdirSync10(appDir)) {
49181
49374
  if (entry.startsWith(".") || entry === INSTALLED_SKILLS_DIRNAME)
49182
49375
  continue;
49183
- const path = join19(appDir, entry);
49376
+ const path = join20(appDir, entry);
49184
49377
  if (entry === LEGACY_CUSTOM_DIRNAME) {
49185
49378
  if (!safeIsDirectory(path))
49186
49379
  continue;
@@ -49188,7 +49381,7 @@ function migrateLegacySkillLayout(appDir, installed) {
49188
49381
  for (const nested of readdirSync10(path)) {
49189
49382
  if (nested.startsWith("."))
49190
49383
  continue;
49191
- const nestedPath = join19(path, nested);
49384
+ const nestedPath = join20(path, nested);
49192
49385
  if (looksLikeSkillDirectory(nestedPath))
49193
49386
  candidates.push({ from: nestedPath, name: nested });
49194
49387
  }
@@ -49202,10 +49395,10 @@ function migrateLegacySkillLayout(appDir, installed) {
49202
49395
  return;
49203
49396
  }
49204
49397
  for (const { from, name } of candidates) {
49205
- const target = join19(installed, name);
49398
+ const target = join20(installed, name);
49206
49399
  if (existsSync10(target))
49207
49400
  continue;
49208
- const staging = join19(installed, `.migrating-${name}-${process.pid}`);
49401
+ const staging = join20(installed, `.migrating-${name}-${process.pid}`);
49209
49402
  try {
49210
49403
  rmSync(staging, { recursive: true, force: true });
49211
49404
  cpSync2(from, staging, { recursive: true, errorOnExist: false });
@@ -49218,7 +49411,7 @@ function migrateLegacySkillLayout(appDir, installed) {
49218
49411
  }
49219
49412
  }
49220
49413
  function getPortableSkillPath(name, options = {}) {
49221
- return join19(getPortableSkillsRoot(options), normalizePortableSkillName(name));
49414
+ return join20(getPortableSkillsRoot(options), normalizePortableSkillName(name));
49222
49415
  }
49223
49416
  function findPortableSkill(name, options = {}) {
49224
49417
  let normalized;
@@ -49244,7 +49437,7 @@ function listPortableSkills(options = {}) {
49244
49437
  for (const entry of readdirSync10(root3).sort()) {
49245
49438
  if (entry.startsWith("."))
49246
49439
  continue;
49247
- const path = join19(root3, entry);
49440
+ const path = join20(root3, entry);
49248
49441
  if (!safeIsDirectory(path))
49249
49442
  continue;
49250
49443
  try {
@@ -49278,7 +49471,7 @@ function isOfficialSkillName(name) {
49278
49471
  function scaffoldPortableSkill(name, options = {}) {
49279
49472
  const skillName = normalizeNewPortableSkillName(name);
49280
49473
  const root3 = getPortableSkillsRoot(options);
49281
- const skillPath = join19(root3, skillName);
49474
+ const skillPath = join20(root3, skillName);
49282
49475
  if (existsSync10(skillPath)) {
49283
49476
  if (!options.overwrite)
49284
49477
  throw new Error(`Skill '${skillName}' already exists at ${skillPath}`);
@@ -49310,7 +49503,7 @@ function portPortableSkillDirectory(sourceDir, options = {}) {
49310
49503
  const skipped = [];
49311
49504
  const entries = readdirSync10(absoluteSource, { withFileTypes: true }).map((entry) => entry.name).filter((entryName) => !entryName.startsWith(".")).sort();
49312
49505
  for (const entryName of entries) {
49313
- const childPath = join19(absoluteSource, entryName);
49506
+ const childPath = join20(absoluteSource, entryName);
49314
49507
  if (!safeIsDirectory(childPath))
49315
49508
  continue;
49316
49509
  if (!isSkillCandidate(childPath)) {
@@ -49339,23 +49532,23 @@ function portPortableSkillDirectory(sourceDir, options = {}) {
49339
49532
  };
49340
49533
  }
49341
49534
  function isSkillCandidate(dir) {
49342
- return existsSync10(join19(dir, "SKILL.md")) || existsSync10(join19(dir, "skill.json")) || existsSync10(join19(dir, "package.json"));
49535
+ return existsSync10(join20(dir, "SKILL.md")) || existsSync10(join20(dir, "skill.json")) || existsSync10(join20(dir, "package.json"));
49343
49536
  }
49344
49537
  function physicalImportPath(path) {
49345
- let ancestor = resolve6(path);
49538
+ let ancestor = resolve8(path);
49346
49539
  const suffix = [];
49347
49540
  while (!existsSync10(ancestor)) {
49348
49541
  suffix.unshift(basename2(ancestor));
49349
- ancestor = dirname11(ancestor);
49542
+ ancestor = dirname13(ancestor);
49350
49543
  }
49351
- return join19(realpathSync4(ancestor), ...suffix);
49544
+ return join20(realpathSync4(ancestor), ...suffix);
49352
49545
  }
49353
49546
  function assertDisjointImportPaths(source, destination) {
49354
49547
  const sourcePath = realpathSync4(source);
49355
49548
  const destinationPath = physicalImportPath(destination);
49356
49549
  const contains = (parent, child) => {
49357
49550
  const path = relative4(parent, child);
49358
- return path === "" || !isAbsolute7(path) && path !== ".." && !path.startsWith(`..${sep4}`);
49551
+ return path === "" || !isAbsolute9(path) && path !== ".." && !path.startsWith(`..${sep4}`);
49359
49552
  };
49360
49553
  if (contains(sourcePath, destinationPath) || contains(destinationPath, sourcePath)) {
49361
49554
  throw new Error("Source and destination skill directories must not overlap");
@@ -49374,16 +49567,16 @@ function portPortableSkill(sourcePath, options = {}) {
49374
49567
  const via = explicitName ? `Name '${skillName}' matches a bundled official skill.` : `Inferred name '${skillName}'${sourceSlug && sourceSlug !== skillName ? ` (from source folder '${basename2(absoluteSource)}')` : ""} matches a bundled official skill.`;
49375
49568
  throw new Error(`${via} Importing it would shadow the official '${skillName}'. ` + `Pass --name to choose a different name, or --allow-shadow to override deliberately.`);
49376
49569
  }
49377
- assertDisjointImportPaths(absoluteSource, join19(resolvePortableSkillsRoot(options, false), skillName));
49570
+ assertDisjointImportPaths(absoluteSource, join20(resolvePortableSkillsRoot(options, false), skillName));
49378
49571
  const root3 = getPortableSkillsRoot(options);
49379
- const destination = join19(root3, skillName);
49572
+ const destination = join20(root3, skillName);
49380
49573
  assertDisjointImportPaths(absoluteSource, destination);
49381
49574
  if (existsSync10(destination)) {
49382
49575
  if (!options.overwrite)
49383
49576
  throw new Error(`Skill '${skillName}' already exists at ${destination}`);
49384
49577
  rmSync(destination, { recursive: true, force: true });
49385
49578
  }
49386
- mkdirSync7(dirname11(destination), { recursive: true });
49579
+ mkdirSync7(dirname13(destination), { recursive: true });
49387
49580
  copySkillDirectory(absoluteSource, destination);
49388
49581
  const base = {
49389
49582
  ...inferred,
@@ -49420,10 +49613,10 @@ function buildCorpusManifest(input, name) {
49420
49613
  function writeCorpusSkill(input, options = {}) {
49421
49614
  const name = normalizePortableSkillName(input.name);
49422
49615
  const root3 = getPortableSkillsRoot(options);
49423
- const skillPath = join19(root3, name);
49616
+ const skillPath = join20(root3, name);
49424
49617
  const created = !existsSync10(skillPath);
49425
49618
  mkdirSync7(skillPath, { recursive: true });
49426
- writeFileSync5(join19(skillPath, "SKILL.md"), input.skillMd);
49619
+ writeFileSync5(join20(skillPath, "SKILL.md"), input.skillMd);
49427
49620
  const manifest = buildCorpusManifest(input, name);
49428
49621
  writeSkillJsonWithHash(skillPath, manifest);
49429
49622
  return { name, path: skillPath, manifest, created };
@@ -49431,19 +49624,19 @@ function writeCorpusSkill(input, options = {}) {
49431
49624
  function installCorpusSkillAtomically(input, options = {}) {
49432
49625
  const name = normalizePortableSkillName(input.name);
49433
49626
  const root3 = getPortableSkillsRoot(options);
49434
- const target = join19(root3, name);
49627
+ const target = join20(root3, name);
49435
49628
  const created = !existsSync10(target);
49436
49629
  mkdirSync7(root3, { recursive: true });
49437
- const staging = mkdtempSync(join19(root3, `.pull-${name}-`));
49630
+ const staging = mkdtempSync(join20(root3, `.pull-${name}-`));
49438
49631
  let moved = false;
49439
49632
  let backup = null;
49440
49633
  try {
49441
- writeFileSync5(join19(staging, "SKILL.md"), input.skillMd);
49634
+ writeFileSync5(join20(staging, "SKILL.md"), input.skillMd);
49442
49635
  const manifest = buildCorpusManifest(input, name);
49443
49636
  writeSkillJsonWithHash(staging, manifest);
49444
49637
  if (existsSync10(target)) {
49445
- backup = mkdtempSync(join19(root3, `.pull-backup-${name}-`));
49446
- renameSync3(target, join19(backup, name));
49638
+ backup = mkdtempSync(join20(root3, `.pull-backup-${name}-`));
49639
+ renameSync3(target, join20(backup, name));
49447
49640
  moved = true;
49448
49641
  }
49449
49642
  renameSync3(staging, target);
@@ -49452,9 +49645,9 @@ function installCorpusSkillAtomically(input, options = {}) {
49452
49645
  return { name, path: target, manifest, created };
49453
49646
  } catch (error) {
49454
49647
  rmSync(staging, { recursive: true, force: true });
49455
- if (moved && backup && existsSync10(join19(backup, name))) {
49648
+ if (moved && backup && existsSync10(join20(backup, name))) {
49456
49649
  try {
49457
- renameSync3(join19(backup, name), target);
49650
+ renameSync3(join20(backup, name), target);
49458
49651
  } catch {}
49459
49652
  }
49460
49653
  throw error;
@@ -49467,8 +49660,8 @@ function validatePortableSkillDirectory(name, skillPath) {
49467
49660
  const warnings = [...base.warnings];
49468
49661
  let manifest;
49469
49662
  if (existsSync10(skillPath)) {
49470
- const skillJsonPath = join19(skillPath, "skill.json");
49471
- const skillMdPath = join19(skillPath, "SKILL.md");
49663
+ const skillJsonPath = join20(skillPath, "skill.json");
49664
+ const skillMdPath = join20(skillPath, "SKILL.md");
49472
49665
  if (!existsSync10(skillJsonPath) && !existsSync10(skillMdPath)) {
49473
49666
  add3(issues, "portable.manifest_missing", "Missing portable manifest: expected SKILL.md frontmatter and/or skill.json");
49474
49667
  }
@@ -49488,7 +49681,7 @@ function validatePortableSkillDirectory(name, skillPath) {
49488
49681
  add3(issues, "portable.version_missing", "Portable manifest missing version");
49489
49682
  }
49490
49683
  const contractIssues = validatePortableManifestContract(manifest, {
49491
- strict: existsSync10(join19(skillPath, "skill.json")),
49684
+ strict: existsSync10(join20(skillPath, "skill.json")),
49492
49685
  skillPath
49493
49686
  });
49494
49687
  for (const issue of contractIssues)
@@ -49524,7 +49717,7 @@ function validatePortableSkillDirectory(name, skillPath) {
49524
49717
  add3(issues, "portable.command_entry_unsafe", `Command '${command3.name}' entry '${command3.entry}' must stay inside the skill directory`);
49525
49718
  continue;
49526
49719
  }
49527
- const entryPath = join19(skillPath, command3.entry);
49720
+ const entryPath = join20(skillPath, command3.entry);
49528
49721
  if (!existsSync10(entryPath))
49529
49722
  add3(issues, "portable.command_entry_missing", `Command '${command3.name}' entry '${command3.entry}' is missing`);
49530
49723
  else if (statSync8(entryPath).isDirectory())
@@ -49535,7 +49728,7 @@ function validatePortableSkillDirectory(name, skillPath) {
49535
49728
  } catch (error) {
49536
49729
  add3(issues, "portable.manifest_invalid", error.message);
49537
49730
  }
49538
- if (manifest?.kind !== "instruction" && !existsSync10(join19(skillPath, "AGENTS.md"))) {
49731
+ if (manifest?.kind !== "instruction" && !existsSync10(join20(skillPath, "AGENTS.md"))) {
49539
49732
  add3(issues, "portable.agents_missing", "Missing AGENTS.md with build-out instructions for coding agents");
49540
49733
  }
49541
49734
  }
@@ -49571,12 +49764,12 @@ async function runPortableSkill(name, args, options = {}) {
49571
49764
  if (!isSafeRelativePath2(command3.entry)) {
49572
49765
  return { exitCode: 1, error: `Portable skill '${name}' command entry is unsafe` };
49573
49766
  }
49574
- const entryPath = join19(skill.path, command3.entry);
49767
+ const entryPath = join20(skill.path, command3.entry);
49575
49768
  if (!existsSync10(entryPath)) {
49576
49769
  return { exitCode: 1, error: `Entry point '${command3.entry}' not found in portable skill '${name}'` };
49577
49770
  }
49578
- const pkgPath = join19(skill.path, "package.json");
49579
- const nodeModules = join19(skill.path, "node_modules");
49771
+ const pkgPath = join20(skill.path, "package.json");
49772
+ const nodeModules = join20(skill.path, "node_modules");
49580
49773
  if (existsSync10(pkgPath) && !existsSync10(nodeModules) && hasPackageDependencies(pkgPath)) {
49581
49774
  const install = Bun.spawn(["bun", "install", "--no-save"], {
49582
49775
  cwd: skill.path,
@@ -49623,7 +49816,7 @@ function safeIsDirectory(path) {
49623
49816
  }
49624
49817
  }
49625
49818
  function isSafeRelativePath2(value) {
49626
- if (!value.trim() || isAbsolute7(value))
49819
+ if (!value.trim() || isAbsolute9(value))
49627
49820
  return false;
49628
49821
  const normalized = normalize2(value).replace(/\\/g, "/");
49629
49822
  return normalized !== ".." && !normalized.startsWith("../") && !normalized.includes("/../");
@@ -49648,9 +49841,9 @@ function isSkillsOwnershipMarker(marker) {
49648
49841
  return typeof marker === "object" && marker !== null && Object.hasOwn(marker, "managedBy") && marker.managedBy === SYNC_MARKER_MANAGED_BY;
49649
49842
  }
49650
49843
  function hasSkillsOwnershipMarker(dir) {
49651
- const path = join20(dir, SYNC_MARKER_FILE);
49844
+ const path = join21(dir, SYNC_MARKER_FILE);
49652
49845
  try {
49653
- if (!lstatSync10(path).isFile())
49846
+ if (!lstatSync12(path).isFile())
49654
49847
  return false;
49655
49848
  const marker = JSON.parse(readFileSync14(path, "utf8"));
49656
49849
  return isSkillsOwnershipMarker(marker);
@@ -49672,9 +49865,9 @@ function resolveSyncAgents(arg) {
49672
49865
  function agentGlobalSkillsDir(agent, homeDir2 = homedir4()) {
49673
49866
  switch (agent) {
49674
49867
  case "opencode":
49675
- return join20(homeDir2, ".config", "opencode", "skills");
49868
+ return join21(homeDir2, ".config", "opencode", "skills");
49676
49869
  default:
49677
- return join20(homeDir2, `.${agent}`, "skills");
49870
+ return join21(homeDir2, `.${agent}`, "skills");
49678
49871
  }
49679
49872
  }
49680
49873
  function adaptSkillMdForAgent(skillMd, agent) {
@@ -49733,7 +49926,7 @@ function resolveSyncCorpus(options = {}) {
49733
49926
  function packageSourceRoots(source) {
49734
49927
  const roots = [];
49735
49928
  for (const sub of ["skills"]) {
49736
- const candidate = join20(source, sub);
49929
+ const candidate = join21(source, sub);
49737
49930
  if (existsSync11(candidate) && isDirectory(candidate))
49738
49931
  roots.push(candidate);
49739
49932
  }
@@ -49749,10 +49942,10 @@ function containsSkillDirectories(path) {
49749
49942
  return false;
49750
49943
  }
49751
49944
  return entries.some((entry) => {
49752
- const candidate = join20(path, entry);
49945
+ const candidate = join21(path, entry);
49753
49946
  if (!isDirectory(candidate))
49754
49947
  return false;
49755
- return existsSync11(join20(candidate, "SKILL.md")) || existsSync11(join20(candidate, "skill.json")) || existsSync11(join20(candidate, "package.json"));
49948
+ return existsSync11(join21(candidate, "SKILL.md")) || existsSync11(join21(candidate, "skill.json")) || existsSync11(join21(candidate, "package.json"));
49756
49949
  });
49757
49950
  }
49758
49951
  function isDirectory(path) {
@@ -49792,7 +49985,7 @@ function syncSkillsToAgents(options = {}) {
49792
49985
  actions.push({
49793
49986
  skill: name,
49794
49987
  agent,
49795
- path: join20(agentGlobalSkillsDir(agent, homeDir2), name, "SKILL.md"),
49988
+ path: join21(agentGlobalSkillsDir(agent, homeDir2), name, "SKILL.md"),
49796
49989
  action: "skip",
49797
49990
  reason: "not found in this machine's corpus"
49798
49991
  });
@@ -49822,7 +50015,7 @@ function syncSkillsToAgents(options = {}) {
49822
50015
  }
49823
50016
  function writeManagedAgentSkill(params) {
49824
50017
  const homeDir2 = params.homeDir ?? homedir4();
49825
- const dir = join20(agentGlobalSkillsDir(params.agent, homeDir2), params.skill);
50018
+ const dir = join21(agentGlobalSkillsDir(params.agent, homeDir2), params.skill);
49826
50019
  const result = writeManagedSkillDir(dir, params.skillMd, {
49827
50020
  skill: params.skill,
49828
50021
  source: params.source,
@@ -49839,8 +50032,8 @@ function writeManagedAgentSkill(params) {
49839
50032
  };
49840
50033
  }
49841
50034
  function writeManagedSkillDir(dir, skillMd, options) {
49842
- const skillMdPath = join20(dir, "SKILL.md");
49843
- const markerPath = join20(dir, SYNC_MARKER_FILE);
50035
+ const skillMdPath = join21(dir, "SKILL.md");
50036
+ const markerPath = join21(dir, SYNC_MARKER_FILE);
49844
50037
  const dirExists = existsSync11(dir);
49845
50038
  const managed = hasSkillsOwnershipMarker(dir);
49846
50039
  const hasSkillMd = existsSync11(skillMdPath);
@@ -49876,13 +50069,13 @@ function writeManagedSkillDir(dir, skillMd, options) {
49876
50069
  const action = dirExists ? "update" : "create";
49877
50070
  if (options.dryRun)
49878
50071
  return { action, path: skillMdPath };
49879
- const parentDir = dirname12(dir);
50072
+ const parentDir = dirname14(dir);
49880
50073
  mkdirSync8(parentDir, { recursive: true });
49881
- const transactionDir = mkdtempSync2(join20(parentDir, `.hasna-skills-write-${basename3(dir)}-`));
49882
- const candidateDir = join20(transactionDir, "candidate");
49883
- const backupDir = join20(transactionDir, "backup");
49884
- const candidateSkillMdPath = join20(candidateDir, "SKILL.md");
49885
- const candidateMarkerPath = join20(candidateDir, SYNC_MARKER_FILE);
50074
+ const transactionDir = mkdtempSync2(join21(parentDir, `.hasna-skills-write-${basename3(dir)}-`));
50075
+ const candidateDir = join21(transactionDir, "candidate");
50076
+ const backupDir = join21(transactionDir, "backup");
50077
+ const candidateSkillMdPath = join21(candidateDir, "SKILL.md");
50078
+ const candidateMarkerPath = join21(candidateDir, SYNC_MARKER_FILE);
49886
50079
  const marker = {
49887
50080
  managedBy: SYNC_MARKER_MANAGED_BY,
49888
50081
  skill: options.skill,
@@ -49931,7 +50124,7 @@ function writeManagedSkillDir(dir, skillMd, options) {
49931
50124
  return { action, path: skillMdPath };
49932
50125
  }
49933
50126
  function removeManagedAgentSkill(skill, agent, homeDir2 = homedir4()) {
49934
- const dir = join20(agentGlobalSkillsDir(agent, homeDir2), skill);
50127
+ const dir = join21(agentGlobalSkillsDir(agent, homeDir2), skill);
49935
50128
  if (!hasSkillsOwnershipMarker(dir))
49936
50129
  return false;
49937
50130
  rmSync2(dir, { recursive: true, force: true });
@@ -49939,7 +50132,7 @@ function removeManagedAgentSkill(skill, agent, homeDir2 = homedir4()) {
49939
50132
  }
49940
50133
  function sourceSkillMd(skillPath, name, description, kind, preferBundledDocs = false) {
49941
50134
  if (kind === undefined || kind === "instruction" || preferBundledDocs) {
49942
- const skillMdPath = join20(skillPath, "SKILL.md");
50135
+ const skillMdPath = join21(skillPath, "SKILL.md");
49943
50136
  if (existsSync11(skillMdPath))
49944
50137
  return readFileSync14(skillMdPath, "utf-8");
49945
50138
  }
@@ -49972,7 +50165,7 @@ function normalizeSkillName(name) {
49972
50165
 
49973
50166
  // src/lib/registry.ts
49974
50167
  import { existsSync as existsSync12, readFileSync as readFileSync15, readdirSync as readdirSync12 } from "fs";
49975
- import { join as join21 } from "path";
50168
+ import { join as join22 } from "path";
49976
50169
 
49977
50170
  // src/lib/registry-merge.ts
49978
50171
  var SKILL_SOURCE_PRECEDENCE = {
@@ -50193,7 +50386,7 @@ function discoverSkillsInDir(dir, source = "custom") {
50193
50386
  for (const entry of entries) {
50194
50387
  if (!entry.isDirectory())
50195
50388
  continue;
50196
- const skillMdPath = join21(dir, entry.name, "SKILL.md");
50389
+ const skillMdPath = join22(dir, entry.name, "SKILL.md");
50197
50390
  if (!existsSync12(skillMdPath))
50198
50391
  continue;
50199
50392
  let content;
@@ -50213,7 +50406,7 @@ function discoverSkillsInDir(dir, source = "custom") {
50213
50406
  category: fm.category || "Development Tools",
50214
50407
  tags: fm.tags || [],
50215
50408
  ...fm.kind ? { kind: fm.kind } : {},
50216
- ...isHostedMetadataSkillDir(join21(dir, entry.name)) ? { serverOwned: true } : {},
50409
+ ...isHostedMetadataSkillDir(join22(dir, entry.name)) ? { serverOwned: true } : {},
50217
50410
  source
50218
50411
  });
50219
50412
  }
@@ -50229,8 +50422,8 @@ function findExtensionSkillPath(name) {
50229
50422
  for (const entry of entries) {
50230
50423
  if (!entry.isDirectory())
50231
50424
  continue;
50232
- const skillDir = join21(config.extensionsDir, entry.name);
50233
- const skillMdPath = join21(skillDir, "SKILL.md");
50425
+ const skillDir = join22(config.extensionsDir, entry.name);
50426
+ const skillMdPath = join22(skillDir, "SKILL.md");
50234
50427
  if (!existsSync12(skillMdPath))
50235
50428
  continue;
50236
50429
  let content;
@@ -50268,7 +50461,7 @@ function loadRegistry(cwd) {
50268
50461
  const official = SKILLS.map((s2) => ({ ...s2, source: "official" }));
50269
50462
  const extensions = config.extensionsDir ? discoverSkillsInDir(config.extensionsDir, "extension") : [];
50270
50463
  const portableCustom = listPortableSkillMetas();
50271
- const legacyCustom = discoverSkillsInDir(join21(dataDir2, "custom"));
50464
+ const legacyCustom = discoverSkillsInDir(join22(dataDir2, "custom"));
50272
50465
  const globalCustom = mergeCustomSkills([...legacyCustom, ...portableCustom]);
50273
50466
  registryCache = mergeSkillRegistryLists(official, extensions, globalCustom);
50274
50467
  registryCacheTime = now;
@@ -50317,7 +50510,7 @@ function getAllTags() {
50317
50510
 
50318
50511
  // src/lib/project-state.ts
50319
50512
  import { existsSync as existsSync13, mkdirSync as mkdirSync9, readFileSync as readFileSync16, writeFileSync as writeFileSync7 } from "fs";
50320
- import { join as join22 } from "path";
50513
+ import { join as join23 } from "path";
50321
50514
  var VALID_PIN_SOURCES = [
50322
50515
  "official",
50323
50516
  "custom",
@@ -50332,10 +50525,10 @@ var SKILLS_PROJECT_DIR = ".skills";
50332
50525
  var PROJECT_CONFIG_FILE = "project.json";
50333
50526
  var DEFAULT_EXPORT_DIR = ".skills/exports";
50334
50527
  function getProjectStateDir(targetDir = process.cwd()) {
50335
- return join22(targetDir, SKILLS_PROJECT_DIR);
50528
+ return join23(targetDir, SKILLS_PROJECT_DIR);
50336
50529
  }
50337
50530
  function getProjectConfigPath(targetDir = process.cwd()) {
50338
- return join22(getProjectStateDir(targetDir), PROJECT_CONFIG_FILE);
50531
+ return join23(getProjectStateDir(targetDir), PROJECT_CONFIG_FILE);
50339
50532
  }
50340
50533
  function loadProjectConfig(targetDir = process.cwd()) {
50341
50534
  const path = getProjectConfigPath(targetDir);
@@ -50456,16 +50649,16 @@ function isPinSource(value) {
50456
50649
  }
50457
50650
 
50458
50651
  // src/lib/installer.ts
50459
- var __dirname2 = dirname13(fileURLToPath2(import.meta.url));
50652
+ var __dirname2 = dirname15(fileURLToPath2(import.meta.url));
50460
50653
  function findSkillsDir() {
50461
50654
  let dir = __dirname2;
50462
50655
  for (let i3 = 0;i3 < 5; i3++) {
50463
- const candidate = join23(dir, "skills");
50656
+ const candidate = join24(dir, "skills");
50464
50657
  if (existsSync14(candidate) && !dir.includes(".skills"))
50465
50658
  return candidate;
50466
- dir = dirname13(dir);
50659
+ dir = dirname15(dir);
50467
50660
  }
50468
- return join23(__dirname2, "..", "skills");
50661
+ return join24(__dirname2, "..", "skills");
50469
50662
  }
50470
50663
  var SKILLS_DIR = findSkillsDir();
50471
50664
  function getSkillPath(name) {
@@ -50473,13 +50666,13 @@ function getSkillPath(name) {
50473
50666
  const portable = findPortableSkill(skillName);
50474
50667
  if (portable)
50475
50668
  return portable.path;
50476
- const legacyCustomPath = join23(getDataDir(), "custom", skillName);
50669
+ const legacyCustomPath = join24(getDataDir(), "custom", skillName);
50477
50670
  if (existsSync14(legacyCustomPath))
50478
50671
  return legacyCustomPath;
50479
50672
  const extensionPath = findExtensionSkillPath(skillName);
50480
50673
  if (extensionPath)
50481
50674
  return extensionPath;
50482
- return join23(SKILLS_DIR, skillName);
50675
+ return join24(SKILLS_DIR, skillName);
50483
50676
  }
50484
50677
  function getCanonicalSkillName(name) {
50485
50678
  return getSkill(name)?.name ?? resolveSkillAlias(normalizeSkillSlug(name));
@@ -50542,7 +50735,7 @@ function createLocalSkillManifest(name, generateSkillMd) {
50542
50735
  if (!existsSync14(sourcePath))
50543
50736
  return null;
50544
50737
  let skillMd = "";
50545
- const skillMdPath = join23(sourcePath, "SKILL.md");
50738
+ const skillMdPath = join24(sourcePath, "SKILL.md");
50546
50739
  if (existsSync14(skillMdPath)) {
50547
50740
  skillMd = readFileSync17(skillMdPath, "utf-8");
50548
50741
  } else if (generateSkillMd) {
@@ -50616,16 +50809,16 @@ function getAgentSkillsDir(agent, scope = "global", projectDir) {
50616
50809
  const base = projectDir || process.cwd();
50617
50810
  switch (agent) {
50618
50811
  case "pi":
50619
- return scope === "project" ? join23(base, ".pi", "skills") : join23(homedir5(), ".pi", "agent", "skills");
50812
+ return scope === "project" ? join24(base, ".pi", "skills") : join24(homedir5(), ".pi", "agent", "skills");
50620
50813
  case "opencode":
50621
- return scope === "project" ? join23(base, ".opencode", "skills") : join23(homedir5(), ".config", "opencode", "skills");
50814
+ return scope === "project" ? join24(base, ".opencode", "skills") : join24(homedir5(), ".config", "opencode", "skills");
50622
50815
  default:
50623
- return scope === "project" ? join23(base, `.${agent}`, "skills") : join23(homedir5(), `.${agent}`, "skills");
50816
+ return scope === "project" ? join24(base, `.${agent}`, "skills") : join24(homedir5(), `.${agent}`, "skills");
50624
50817
  }
50625
50818
  }
50626
50819
  function getAgentSkillPath(name, agent, scope = "global", projectDir) {
50627
50820
  const skillName = normalizeSkillName(getCanonicalSkillName(name));
50628
- return join23(getAgentSkillsDir(agent, scope, projectDir), skillName);
50821
+ return join24(getAgentSkillsDir(agent, scope, projectDir), skillName);
50629
50822
  }
50630
50823
  function installSkillForAgent(name, options, generateSkillMd) {
50631
50824
  assertNativeExportAllowed();
@@ -50661,7 +50854,7 @@ function removeSkillForAgent(name, options) {
50661
50854
  }
50662
50855
  function resolveAgentSkillMd(name, generateSkillMd) {
50663
50856
  const sourcePath = getSkillPath(name);
50664
- const skillMdPath = join23(sourcePath, "SKILL.md");
50857
+ const skillMdPath = join24(sourcePath, "SKILL.md");
50665
50858
  if (existsSync14(skillMdPath))
50666
50859
  return readFileSync17(skillMdPath, "utf-8");
50667
50860
  if (generateSkillMd)
@@ -50696,7 +50889,7 @@ function generateMinimalSkillMd(name) {
50696
50889
  "---",
50697
50890
  ""
50698
50891
  ].filter(Boolean);
50699
- const fallbackDoc = readFileIfExists(join23(sourcePath, "README.md")) || readFileIfExists(join23(sourcePath, "CLAUDE.md"));
50892
+ const fallbackDoc = readFileIfExists(join24(sourcePath, "README.md")) || readFileIfExists(join24(sourcePath, "CLAUDE.md"));
50700
50893
  if (fallbackDoc)
50701
50894
  return `${frontmatter.join(`
50702
50895
  `)}${fallbackDoc.trim()}
@@ -50715,7 +50908,7 @@ skills run ${canonicalName}
50715
50908
  `;
50716
50909
  }
50717
50910
  function readBundledSkillVersion(name) {
50718
- const pkgPath = join23(getSkillPath(name), "package.json");
50911
+ const pkgPath = join24(getSkillPath(name), "package.json");
50719
50912
  if (!existsSync14(pkgPath))
50720
50913
  return "unknown";
50721
50914
  try {
@@ -50734,15 +50927,15 @@ function loadProjectConfigCompat(targetDir) {
50734
50927
 
50735
50928
  // src/server/seed-bundled.ts
50736
50929
  import { readFileSync as readFileSync21 } from "fs";
50737
- import { join as join26 } from "path";
50930
+ import { join as join27 } from "path";
50738
50931
 
50739
50932
  // src/server/registry.ts
50740
50933
  import { existsSync as existsSync16, readFileSync as readFileSync20 } from "fs";
50741
- import { resolve as resolve7, sep as sep5 } from "path";
50934
+ import { resolve as resolve9, sep as sep5 } from "path";
50742
50935
 
50743
50936
  // src/lib/dependency-preparation.ts
50744
- import { constants as constants5, closeSync as closeSync6, fstatSync as fstatSync6, lstatSync as lstatSync11, mkdirSync as mkdirSync10, openSync as openSync6, readFileSync as readFileSync18, readdirSync as readdirSync13, rmdirSync as rmdirSync2, unlinkSync as unlinkSync3, ftruncateSync, writeSync } from "fs";
50745
- import { join as join24 } from "path";
50937
+ import { constants as constants6, closeSync as closeSync7, fstatSync as fstatSync7, lstatSync as lstatSync13, mkdirSync as mkdirSync10, openSync as openSync7, readFileSync as readFileSync18, readdirSync as readdirSync13, rmdirSync as rmdirSync2, unlinkSync as unlinkSync3, ftruncateSync, writeSync } from "fs";
50938
+ import { join as join25 } from "path";
50746
50939
 
50747
50940
  // src/lib/preparation-process.ts
50748
50941
  function capturePreparationProcess(child, platform = process.platform, signalGroup = (pid, signal) => process.kill(pid, signal)) {
@@ -50789,15 +50982,15 @@ var DEPENDENCY_PREPARATION_MARKER = ".skills-dependency-preparation";
50789
50982
  var RECOVERY = "Skill dependency preparation is incomplete. Confirm no installer is running, successfully run bun install --no-save in the skill directory, then remove only .skills-dependency-preparation. See docs/skill-standard.md#recovering-interrupted-dependency-preparation.";
50790
50983
  function hasDependencyPreparationMarker(skillPath) {
50791
50984
  try {
50792
- lstatSync11(join24(skillPath, DEPENDENCY_PREPARATION_MARKER));
50985
+ lstatSync13(join25(skillPath, DEPENDENCY_PREPARATION_MARKER));
50793
50986
  return true;
50794
50987
  } catch (error) {
50795
50988
  return error.code !== "ENOENT";
50796
50989
  }
50797
50990
  }
50798
50991
  function claimPreparation(skillPath) {
50799
- const marker = join24(skillPath, DEPENDENCY_PREPARATION_MARKER);
50800
- const state2 = join24(marker, "state.json"), active = join24(marker, "active");
50992
+ const marker = join25(skillPath, DEPENDENCY_PREPARATION_MARKER);
50993
+ const state2 = join25(marker, "state.json"), active = join25(marker, "active");
50801
50994
  let created = false;
50802
50995
  try {
50803
50996
  mkdirSync10(marker, { mode: 448 });
@@ -50808,21 +51001,21 @@ function claimPreparation(skillPath) {
50808
51001
  }
50809
51002
  let fd;
50810
51003
  try {
50811
- if (!lstatSync11(marker).isDirectory() || lstatSync11(marker).isSymbolicLink())
51004
+ if (!lstatSync13(marker).isDirectory() || lstatSync13(marker).isSymbolicLink())
50812
51005
  return;
50813
51006
  if (!created) {
50814
51007
  if (readdirSync13(marker).some((name) => name !== "state.json"))
50815
51008
  return;
50816
- if (!lstatSync11(state2).isFile() || lstatSync11(state2).isSymbolicLink() || lstatSync11(state2).size > 1024)
51009
+ if (!lstatSync13(state2).isFile() || lstatSync13(state2).isSymbolicLink() || lstatSync13(state2).size > 1024)
50817
51010
  return;
50818
51011
  const previous = JSON.parse(readFileSync18(state2, "utf8"));
50819
51012
  if (previous.version !== 1 || previous.status !== "failed" || Object.keys(previous).length !== 2)
50820
51013
  return;
50821
51014
  }
50822
51015
  mkdirSync10(active, { mode: 448 });
50823
- fd = openSync6(state2, constants5.O_RDWR | constants5.O_NOFOLLOW | (created ? constants5.O_CREAT | constants5.O_EXCL : 0), 384);
50824
- if (!fstatSync6(fd).isFile()) {
50825
- closeSync6(fd);
51016
+ fd = openSync7(state2, constants6.O_RDWR | constants6.O_NOFOLLOW | (created ? constants6.O_CREAT | constants6.O_EXCL : 0), 384);
51017
+ if (!fstatSync7(fd).isFile()) {
51018
+ closeSync7(fd);
50826
51019
  return;
50827
51020
  }
50828
51021
  const descriptor = fd;
@@ -50834,7 +51027,7 @@ function claimPreparation(skillPath) {
50834
51027
  record2("pending");
50835
51028
  return { abandon() {
50836
51029
  try {
50837
- closeSync6(descriptor);
51030
+ closeSync7(descriptor);
50838
51031
  } catch {}
50839
51032
  }, finish(success) {
50840
51033
  try {
@@ -50842,7 +51035,7 @@ function claimPreparation(skillPath) {
50842
51035
  unlinkSync3(state2);
50843
51036
  else
50844
51037
  record2("failed");
50845
- closeSync6(descriptor);
51038
+ closeSync7(descriptor);
50846
51039
  fd = undefined;
50847
51040
  rmdirSync2(active);
50848
51041
  if (success)
@@ -50850,7 +51043,7 @@ function claimPreparation(skillPath) {
50850
51043
  return true;
50851
51044
  } catch {
50852
51045
  try {
50853
- closeSync6(descriptor);
51046
+ closeSync7(descriptor);
50854
51047
  } catch {}
50855
51048
  return false;
50856
51049
  }
@@ -50858,7 +51051,7 @@ function claimPreparation(skillPath) {
50858
51051
  } catch {
50859
51052
  if (fd !== undefined)
50860
51053
  try {
50861
- closeSync6(fd);
51054
+ closeSync7(fd);
50862
51055
  } catch {}
50863
51056
  return;
50864
51057
  }
@@ -50949,11 +51142,11 @@ async function prepareSkillDependencies(skillPath, env, timeoutMs = DEFAULT_PREP
50949
51142
 
50950
51143
  // src/lib/skillinfo.ts
50951
51144
  import { existsSync as existsSync15, readFileSync as readFileSync19 } from "fs";
50952
- import { join as join25 } from "path";
51145
+ import { join as join26 } from "path";
50953
51146
  function isInstructionSkillDir(skillPath, meta) {
50954
51147
  if (meta?.kind === "instruction")
50955
51148
  return true;
50956
- const skillMdPath = join25(skillPath, "SKILL.md");
51149
+ const skillMdPath = join26(skillPath, "SKILL.md");
50957
51150
  if (!existsSync15(skillMdPath))
50958
51151
  return false;
50959
51152
  try {
@@ -50983,9 +51176,9 @@ function getSkillDocs(name) {
50983
51176
  if (!existsSync15(skillPath))
50984
51177
  return null;
50985
51178
  return {
50986
- skillMd: readIfExists(join25(skillPath, "SKILL.md")),
50987
- readme: readIfExists(join25(skillPath, "README.md")),
50988
- claudeMd: readIfExists(join25(skillPath, "CLAUDE.md"))
51179
+ skillMd: readIfExists(join26(skillPath, "SKILL.md")),
51180
+ readme: readIfExists(join26(skillPath, "README.md")),
51181
+ claudeMd: readIfExists(join26(skillPath, "CLAUDE.md"))
50989
51182
  };
50990
51183
  }
50991
51184
  function getSkillBestDoc(name) {
@@ -51000,14 +51193,14 @@ function getSkillRequirements(name) {
51000
51193
  return null;
51001
51194
  const texts = [];
51002
51195
  for (const file of ["SKILL.md", "README.md", "CLAUDE.md", ".env.example", ".env.local.example"]) {
51003
- const content = readIfExists(join25(skillPath, file));
51196
+ const content = readIfExists(join26(skillPath, file));
51004
51197
  if (content)
51005
51198
  texts.push(content);
51006
51199
  }
51007
51200
  const meta = getSkill(name);
51008
51201
  let dependencies = {};
51009
51202
  try {
51010
- dependencies = JSON.parse(readFileSync19(join25(skillPath, "package.json"), "utf8")).dependencies || {};
51203
+ dependencies = JSON.parse(readFileSync19(join26(skillPath, "package.json"), "utf8")).dependencies || {};
51011
51204
  } catch {}
51012
51205
  return getSkillRequirementsFromContent(name, texts, dependencies, meta);
51013
51206
  }
@@ -51069,7 +51262,7 @@ async function runSkill(name, args, options = {}) {
51069
51262
  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'.`
51070
51263
  };
51071
51264
  }
51072
- const pkgPath = join25(skillPath, "package.json");
51265
+ const pkgPath = join26(skillPath, "package.json");
51073
51266
  if (!existsSync15(pkgPath)) {
51074
51267
  return { exitCode: 1, error: `No package.json in skill '${name}'` };
51075
51268
  }
@@ -51089,12 +51282,12 @@ async function runSkill(name, args, options = {}) {
51089
51282
  } catch {
51090
51283
  return { exitCode: 1, error: `Failed to parse package.json for skill '${name}'` };
51091
51284
  }
51092
- const entryPath = join25(skillPath, entryPoint);
51285
+ const entryPath = join26(skillPath, entryPoint);
51093
51286
  if (!existsSync15(entryPath)) {
51094
51287
  return { exitCode: 1, error: `Entry point '${entryPoint}' not found in skill '${name}'` };
51095
51288
  }
51096
51289
  const env = { ...process.env, ...options.env };
51097
- if (!existsSync15(join25(skillPath, "node_modules")) || hasDependencyPreparationMarker(skillPath)) {
51290
+ if (!existsSync15(join26(skillPath, "node_modules")) || hasDependencyPreparationMarker(skillPath)) {
51098
51291
  const failure = await prepareSkillDependencies(skillPath, env, options.preparationTimeoutMs);
51099
51292
  if (failure)
51100
51293
  return failure;
@@ -51172,10 +51365,10 @@ function generateSkillMd(name) {
51172
51365
  "---"
51173
51366
  ].join(`
51174
51367
  `);
51175
- const readme = readIfExists(join25(skillPath, "README.md"));
51176
- const claudeMd = readIfExists(join25(skillPath, "CLAUDE.md"));
51368
+ const readme = readIfExists(join26(skillPath, "README.md"));
51369
+ const claudeMd = readIfExists(join26(skillPath, "CLAUDE.md"));
51177
51370
  let cliCommand = null;
51178
- const pkgPath = join25(skillPath, "package.json");
51371
+ const pkgPath = join26(skillPath, "package.json");
51179
51372
  if (existsSync15(pkgPath)) {
51180
51373
  try {
51181
51374
  const pkg = JSON.parse(readFileSync19(pkgPath, "utf-8"));
@@ -51291,15 +51484,15 @@ function getServerSkillMd(slug) {
51291
51484
  const docs = getSkillDocs(name);
51292
51485
  if (docs?.skillMd)
51293
51486
  return docs.skillMd;
51294
- const skillsDir = resolve7(process.cwd(), "skills");
51295
- const path = resolve7(skillsDir, name, "SKILL.md");
51487
+ const skillsDir = resolve9(process.cwd(), "skills");
51488
+ const path = resolve9(skillsDir, name, "SKILL.md");
51296
51489
  if (!isInsideDir(skillsDir, path))
51297
51490
  return null;
51298
51491
  return existsSync16(path) ? readFileSync20(path, "utf8") : null;
51299
51492
  }
51300
51493
 
51301
51494
  // src/server/skills-api.ts
51302
- import { createHash as createHash12 } from "crypto";
51495
+ import { createHash as createHash14 } from "crypto";
51303
51496
  var SLUG_PATTERN = /^[a-z0-9][a-z0-9._-]*$/;
51304
51497
  var SHA256_HEX2 = /^[0-9a-f]{64}$/;
51305
51498
  var MAX_SLUG_LENGTH = 128;
@@ -51511,7 +51704,7 @@ async function parsePublishRequest(request, config) {
51511
51704
  if (bundleBytes.byteLength === 0) {
51512
51705
  throw new SkillRequestError(400, "BUNDLE_EMPTY", "the uploaded bundle is empty");
51513
51706
  }
51514
- const sha2562 = createHash12("sha256").update(bundleBytes).digest("hex");
51707
+ const sha2562 = createHash14("sha256").update(bundleBytes).digest("hex");
51515
51708
  const claimed = optionalString(manifest.bundleSha256);
51516
51709
  if (claimed)
51517
51710
  assertSha2562(claimed);
@@ -51626,7 +51819,7 @@ async function readPublishedBundle(store, artifactStorage, principal, slug) {
51626
51819
  if (!bytes) {
51627
51820
  throw new SkillRequestError(503, "BUNDLE_BACKEND_UNAVAILABLE", "bundle storage backend unavailable");
51628
51821
  }
51629
- const actual = createHash12("sha256").update(bytes).digest("hex");
51822
+ const actual = createHash14("sha256").update(bytes).digest("hex");
51630
51823
  if (actual !== record2.bundleSha256) {
51631
51824
  throw new SkillRequestError(500, "BUNDLE_DIGEST_DRIFT", `stored bundle for '${slug}' hashes to ${actual} but was published as ${record2.bundleSha256}`);
51632
51825
  }
@@ -51774,7 +51967,7 @@ async function readSkillVersionBundle(store, artifactStorage, principal, slug, v
51774
51967
  const bytes = await artifactStorage.readBundle(bundle);
51775
51968
  if (!bytes)
51776
51969
  throw new SkillRequestError(503, "BUNDLE_BACKEND_UNAVAILABLE", "bundle storage backend unavailable");
51777
- const actual = createHash12("sha256").update(bytes).digest("hex");
51970
+ const actual = createHash14("sha256").update(bytes).digest("hex");
51778
51971
  if (actual !== found.bundleSha256) {
51779
51972
  throw new SkillRequestError(500, "BUNDLE_DIGEST_DRIFT", `stored bundle for '${slug}@${version2}' hashes to ${actual} but was published as ${found.bundleSha256}`);
51780
51973
  }
@@ -51818,7 +52011,7 @@ async function seedBundledCorpus(options) {
51818
52011
  }
51819
52012
  const manifest = readPortableSkillManifest(dir, slug);
51820
52013
  const packed = packSkillBundle(dir, { maxUnpackedBytes: 50000000 });
51821
- const skillMdPath = join26(dir, "SKILL.md");
52014
+ const skillMdPath = join27(dir, "SKILL.md");
51822
52015
  const skillMd = existsSync17(skillMdPath) ? readFileSync21(skillMdPath, "utf-8") : undefined;
51823
52016
  const content = {
51824
52017
  slug,
@@ -52086,7 +52279,7 @@ async function handleProfileApi(store, principal, request, parts, config) {
52086
52279
  // src/server/runtime-store.ts
52087
52280
  import { Database as Database3 } from "bun:sqlite";
52088
52281
  import { mkdirSync as mkdirSync11 } from "fs";
52089
- import { dirname as dirname14 } from "path";
52282
+ import { dirname as dirname16 } from "path";
52090
52283
 
52091
52284
  // src/sdk/execution/types.ts
52092
52285
  var EXECUTION_PROTOCOL_VERSION = REMOTE_SKILL_RUN_CONTRACT_VERSION;
@@ -52142,7 +52335,7 @@ class RuntimeExecutionStore {
52142
52335
  }
52143
52336
  const path = target.kind === "sqlite" ? target.path : ":memory:";
52144
52337
  if (path !== ":memory:")
52145
- mkdirSync11(dirname14(path), { recursive: true });
52338
+ mkdirSync11(dirname16(path), { recursive: true });
52146
52339
  const db = new Database3(path);
52147
52340
  db.run("PRAGMA busy_timeout=5000");
52148
52341
  db.run("PRAGMA journal_mode=WAL");
@@ -52382,7 +52575,7 @@ class RuntimeExecutionStore {
52382
52575
  }
52383
52576
 
52384
52577
  // src/sdk/execution/admission.ts
52385
- import { createHash as createHash14 } from "crypto";
52578
+ import { createHash as createHash16 } from "crypto";
52386
52579
 
52387
52580
  // src/sdk/execution/image-profile.ts
52388
52581
  class ImageProfileResolutionError extends Error {
@@ -52980,11 +53173,11 @@ function ownedAdmission(admission) {
52980
53173
  };
52981
53174
  }
52982
53175
  function digestInput(input) {
52983
- return createHash14("sha256").update(canonicalJson(input)).digest("hex");
53176
+ return createHash16("sha256").update(canonicalJson(input)).digest("hex");
52984
53177
  }
52985
53178
 
52986
53179
  // src/sdk/execution/dispatchers/ecs.ts
52987
- import { createHash as createHash15 } from "crypto";
53180
+ import { createHash as createHash17 } from "crypto";
52988
53181
 
52989
53182
  // src/sdk/execution/state-machine.ts
52990
53183
  var LEGAL_TRANSITIONS = {
@@ -56383,13 +56576,13 @@ function observedTask(states, taskArn) {
56383
56576
  return state2.lastStatus === "STOPPED" || LIVE_TASK_STATUSES.has(state2.lastStatus) ? state2 : undefined;
56384
56577
  }
56385
56578
  function clientTokenFor(runId2, attemptId) {
56386
- return createHash15("sha256").update(`${runId2}\x00${attemptId}`).digest("hex").slice(0, CLIENT_TOKEN_BYTES * 2);
56579
+ return createHash17("sha256").update(`${runId2}\x00${attemptId}`).digest("hex").slice(0, CLIENT_TOKEN_BYTES * 2);
56387
56580
  }
56388
56581
  function startedByFor(runId2, attemptNumber) {
56389
56582
  return `skills-exec/${runId2}/a${attemptNumber}`;
56390
56583
  }
56391
56584
  function requestDigestFor(admission, attemptId) {
56392
- return createHash15("sha256").update(canonicalJson({ admission, attemptId })).digest("hex");
56585
+ return createHash17("sha256").update(canonicalJson({ admission, attemptId })).digest("hex");
56393
56586
  }
56394
56587
 
56395
56588
  class EcsDispatcher {
@@ -56685,7 +56878,7 @@ function validText(value) {
56685
56878
  }
56686
56879
 
56687
56880
  // src/server/runtime-policy.ts
56688
- import { createHash as createHash16, createHmac as createHmac3, timingSafeEqual as timingSafeEqual2 } from "crypto";
56881
+ import { createHash as createHash18, createHmac as createHmac3, timingSafeEqual as timingSafeEqual2 } from "crypto";
56689
56882
  var RUNTIME_MAX_INPUT_BYTES = 1e5;
56690
56883
  var RUNTIME_MAX_BUNDLE_BYTES = 1e6;
56691
56884
  var RUNTIME_MAX_ARTIFACT_BYTES = 2000000;
@@ -56757,7 +56950,7 @@ function verifyRuntimeToken(token, key, admission, attempt, now = Date.now()) {
56757
56950
  const actual = Buffer.from(token);
56758
56951
  return actual.length === expected.length && timingSafeEqual2(actual, expected);
56759
56952
  }
56760
- var hashBytes = (bytes) => createHash16("sha256").update(bytes).digest("hex");
56953
+ var hashBytes = (bytes) => createHash18("sha256").update(bytes).digest("hex");
56761
56954
 
56762
56955
  // src/server/runtime-api.ts
56763
56956
  async function createRuntimeService(options) {
@@ -57206,7 +57399,7 @@ function normalizePrefix(value) {
57206
57399
  }
57207
57400
 
57208
57401
  // src/server/handlers.ts
57209
- import { createHash as createHash17 } from "crypto";
57402
+ import { createHash as createHash19 } from "crypto";
57210
57403
 
57211
57404
  // src/server/store.ts
57212
57405
  import { randomUUID as randomUUID7 } from "crypto";
@@ -58238,7 +58431,7 @@ function textArtifact(run, relativePath, bodyText, contentType = relativePath.en
58238
58431
  relativePath,
58239
58432
  contentType,
58240
58433
  byteSize: bytes.byteLength,
58241
- sha256: createHash17("sha256").update(bytes).digest("hex"),
58434
+ sha256: createHash19("sha256").update(bytes).digest("hex"),
58242
58435
  visibility: "private"
58243
58436
  },
58244
58437
  body: { relativePath, bodyText, contentType }
@@ -62836,7 +63029,7 @@ var localRunExecutor = {
62836
63029
  // src/sdk/storage.ts
62837
63030
  var artifactStorageSeam = ArtifactStorage;
62838
63031
  // src/sdk/outputs.ts
62839
- import { createHash as createHash18 } from "crypto";
63032
+ import { createHash as createHash20 } from "crypto";
62840
63033
  class DatabaseOnlyObjectStore {
62841
63034
  usesS3 = false;
62842
63035
  async materialize(run, artifact, body3) {
@@ -62883,7 +63076,7 @@ function createGovernedArtifactWriter(options) {
62883
63076
  const stamped = {
62884
63077
  ...meta,
62885
63078
  byteSize: outputBytes,
62886
- sha256: createHash18("sha256").update(persistedBytes).digest("hex"),
63079
+ sha256: createHash20("sha256").update(persistedBytes).digest("hex"),
62887
63080
  visibility: options.visibility ?? config.defaultVisibility,
62888
63081
  ...config.artifactTtlSeconds !== undefined ? { expiresAt: expiresAtFor(createdAt, config.artifactTtlSeconds) } : {}
62889
63082
  };
@@ -63621,10 +63814,10 @@ async function readQuoteUnavailableCode(response) {
63621
63814
  let timer;
63622
63815
  let deadlineExceeded = false;
63623
63816
  const expired = Symbol("quote body deadline");
63624
- const deadline = new Promise((resolve9) => {
63817
+ const deadline = new Promise((resolve11) => {
63625
63818
  timer = setTimeout(() => {
63626
63819
  deadlineExceeded = true;
63627
- resolve9(expired);
63820
+ resolve11(expired);
63628
63821
  reader.cancel().catch(() => {});
63629
63822
  }, 1500);
63630
63823
  });
@@ -64533,7 +64726,7 @@ async function requestInvitationEmail(origin, action, input) {
64533
64726
  }
64534
64727
 
64535
64728
  // src/lib/remote-private-publications.ts
64536
- import { createHash as createHash19 } from "crypto";
64729
+ import { createHash as createHash21 } from "crypto";
64537
64730
  var PRIVATE_PUBLICATION_MAX_BYTES = 16 * 1024 * 1024;
64538
64731
  var failures = {
64539
64732
  INVALID_REQUEST: [400, "The publication request is invalid."],
@@ -64580,7 +64773,7 @@ var hash2 = (v2) => typeof v2 === "string" && /^[a-f0-9]{64}$/.test(v2);
64580
64773
  var record6 = (v2) => !!v2 && typeof v2 === "object" && !Array.isArray(v2);
64581
64774
  var exact = (v2, keys) => record6(v2) && Object.keys(v2).sort().join(",") === keys.sort().join(",");
64582
64775
  var date = (v2) => typeof v2 === "string" && /^\d{4}-\d\d-\d\dT[0-9:.]+(?:Z|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/.test(v2) && Number.isFinite(Date.parse(v2));
64583
- var publicationSha256 = (bytes) => createHash19("sha256").update(bytes).digest("hex");
64776
+ var publicationSha256 = (bytes) => createHash21("sha256").update(bytes).digest("hex");
64584
64777
  function checkedPublicationDeclaration(value) {
64585
64778
  if (!exact(value, ["idempotencyKey", "version", "expectedCurrentVersionId", "manifestText", "archiveSha256", "archiveByteSize"]) || !publicationUuid(value.idempotencyKey) || !(value.expectedCurrentVersionId === null || publicationUuid(value.expectedCurrentVersionId)) || typeof value.version !== "string" || !value.version || value.version.length > 128 || /[\p{Cc}\p{Cs}]/u.test(value.version) || typeof value.manifestText !== "string" || Buffer.byteLength(value.manifestText) > 16384 || !hash2(value.archiveSha256) || !Number.isSafeInteger(value.archiveByteSize) || Number(value.archiveByteSize) < 1 || Number(value.archiveByteSize) > PRIVATE_PUBLICATION_MAX_BYTES)
64586
64779
  return bad();
@@ -64825,12 +65018,12 @@ class RemotePrivatePublicationsClient {
64825
65018
  previous = view;
64826
65019
  if (!["queued", "verifying"].includes(view.state) || Date.now() >= until)
64827
65020
  return view;
64828
- await new Promise((resolve9) => {
65021
+ await new Promise((resolve11) => {
64829
65022
  const timer = setTimeout(done, Math.min(1000, until - Date.now()));
64830
65023
  function done() {
64831
65024
  clearTimeout(timer);
64832
65025
  options.signal?.removeEventListener("abort", done);
64833
- resolve9();
65026
+ resolve11();
64834
65027
  }
64835
65028
  options.signal?.addEventListener("abort", done, { once: true });
64836
65029
  });
@@ -65062,23 +65255,23 @@ class RemoteSkillsAuthClient {
65062
65255
  }
65063
65256
  }
65064
65257
  // src/lib/private-publication-recovery.ts
65065
- import { constants as constants6, closeSync as closeSync7, fsyncSync as fsyncSync2, fstatSync as fstatSync7, lstatSync as lstatSync12, mkdirSync as mkdirSync12, openSync as openSync7, readSync as readSync5, realpathSync as realpathSync5, renameSync as renameSync5, unlinkSync as unlinkSync4, writeFileSync as writeFileSync8 } from "fs";
65066
- import { dirname as dirname15, isAbsolute as isAbsolute8, join as join30, resolve as resolve9 } from "path";
65258
+ import { constants as constants7, closeSync as closeSync8, fsyncSync as fsyncSync2, fstatSync as fstatSync8, lstatSync as lstatSync14, mkdirSync as mkdirSync12, openSync as openSync8, readSync as readSync6, realpathSync as realpathSync5, renameSync as renameSync5, unlinkSync as unlinkSync4, writeFileSync as writeFileSync8 } from "fs";
65259
+ import { dirname as dirname17, isAbsolute as isAbsolute10, join as join31, resolve as resolve11 } from "path";
65067
65260
  import { randomUUID as randomUUID9 } from "crypto";
65068
65261
  var fail = () => {
65069
65262
  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.");
65070
65263
  };
65071
65264
  function safeDirectory(directory) {
65072
- if (!isAbsolute8(directory) || directory !== resolve9(directory) || realpathSync5(directory) !== directory)
65265
+ if (!isAbsolute10(directory) || directory !== resolve11(directory) || realpathSync5(directory) !== directory)
65073
65266
  return fail();
65074
- for (let path2 = directory;; path2 = dirname15(path2)) {
65075
- const stat = lstatSync12(path2);
65267
+ for (let path2 = directory;; path2 = dirname17(path2)) {
65268
+ const stat = lstatSync14(path2);
65076
65269
  if (!stat.isDirectory() || stat.isSymbolicLink())
65077
65270
  return fail();
65078
- if (path2 === dirname15(path2))
65271
+ if (path2 === dirname17(path2))
65079
65272
  break;
65080
65273
  }
65081
- const own = lstatSync12(directory);
65274
+ const own = lstatSync14(directory);
65082
65275
  if ((own.mode & 63) !== 0 || process.getuid && own.uid !== process.getuid())
65083
65276
  return fail();
65084
65277
  return { dev: own.dev, ino: own.ino };
@@ -65089,36 +65282,36 @@ function unchangedDirectory(directory, identity2) {
65089
65282
  return fail();
65090
65283
  }
65091
65284
  function readOwned(directory, name, max) {
65092
- const identity2 = safeDirectory(directory), file = join30(directory, name);
65093
- const fd = openSync7(file, constants6.O_RDONLY | constants6.O_NOFOLLOW);
65285
+ const identity2 = safeDirectory(directory), file = join31(directory, name);
65286
+ const fd = openSync8(file, constants7.O_RDONLY | constants7.O_NOFOLLOW);
65094
65287
  try {
65095
- const stat = fstatSync7(fd);
65288
+ const stat = fstatSync8(fd);
65096
65289
  if (!stat.isFile() || stat.nlink !== 1 || stat.size > max || stat.size < 1 || (stat.mode & 63) !== 0 || process.getuid && stat.uid !== process.getuid())
65097
65290
  return fail();
65098
65291
  const buffer = Buffer.alloc(Math.min(max, stat.size) + 1);
65099
65292
  let length = 0;
65100
65293
  while (length < buffer.length) {
65101
- const count = readSync5(fd, buffer, length, buffer.length - length, length);
65294
+ const count = readSync6(fd, buffer, length, buffer.length - length, length);
65102
65295
  if (count === 0)
65103
65296
  break;
65104
65297
  length += count;
65105
65298
  }
65106
- const bytes = buffer.subarray(0, length), after = fstatSync7(fd);
65299
+ const bytes = buffer.subarray(0, length), after = fstatSync8(fd);
65107
65300
  unchangedDirectory(directory, identity2);
65108
65301
  if (bytes.length !== stat.size || stat.size !== after.size || stat.mtimeMs !== after.mtimeMs || stat.ctimeMs !== after.ctimeMs)
65109
65302
  return fail();
65110
65303
  return bytes;
65111
65304
  } finally {
65112
- closeSync7(fd);
65305
+ closeSync8(fd);
65113
65306
  }
65114
65307
  }
65115
65308
  function writeOwned(directory, name, bytes) {
65116
- const fd = openSync7(join30(directory, name), constants6.O_WRONLY | constants6.O_CREAT | constants6.O_EXCL | constants6.O_NOFOLLOW, 384);
65309
+ const fd = openSync8(join31(directory, name), constants7.O_WRONLY | constants7.O_CREAT | constants7.O_EXCL | constants7.O_NOFOLLOW, 384);
65117
65310
  try {
65118
65311
  writeFileSync8(fd, bytes);
65119
65312
  fsyncSync2(fd);
65120
65313
  } finally {
65121
- closeSync7(fd);
65314
+ closeSync8(fd);
65122
65315
  }
65123
65316
  }
65124
65317
  function save(directory, value) {
@@ -65126,12 +65319,12 @@ function save(directory, value) {
65126
65319
  writeOwned(directory, temporary, JSON.stringify(value) + `
65127
65320
  `);
65128
65321
  unchangedDirectory(directory, identity2);
65129
- renameSync5(join30(directory, temporary), join30(directory, "receipt.json"));
65130
- const fd = openSync7(directory, constants6.O_RDONLY | constants6.O_NOFOLLOW);
65322
+ renameSync5(join31(directory, temporary), join31(directory, "receipt.json"));
65323
+ const fd = openSync8(directory, constants7.O_RDONLY | constants7.O_NOFOLLOW);
65131
65324
  try {
65132
65325
  fsyncSync2(fd);
65133
65326
  } finally {
65134
- closeSync7(fd);
65327
+ closeSync8(fd);
65135
65328
  }
65136
65329
  }
65137
65330
  function bind(client, receipt) {
@@ -65139,23 +65332,23 @@ function bind(client, receipt) {
65139
65332
  throw new PrivatePublicationError("PUBLICATION_IDENTITY_CHANGED", "The fresh session does not match the recovery directory's server, account and membership.");
65140
65333
  }
65141
65334
  async function locked(directory, action) {
65142
- const identity2 = safeDirectory(directory), file = join30(directory, "operation.lock");
65335
+ const identity2 = safeDirectory(directory), file = join31(directory, "operation.lock");
65143
65336
  let fd;
65144
65337
  try {
65145
- fd = openSync7(file, constants6.O_WRONLY | constants6.O_CREAT | constants6.O_EXCL | constants6.O_NOFOLLOW, 384);
65338
+ fd = openSync8(file, constants7.O_WRONLY | constants7.O_CREAT | constants7.O_EXCL | constants7.O_NOFOLLOW, 384);
65146
65339
  } catch {
65147
65340
  throw new PrivatePublicationError("PUBLICATION_RECOVERY_BUSY", "Another operation holds this recovery directory. If it crashed, confirm that process has stopped before explicitly removing operation.lock and resuming.");
65148
65341
  }
65149
- const lock = fstatSync7(fd);
65342
+ const lock = fstatSync8(fd);
65150
65343
  try {
65151
65344
  writeFileSync8(fd, JSON.stringify({ pid: process.pid }) + `
65152
65345
  `);
65153
65346
  fsyncSync2(fd);
65154
65347
  return await action();
65155
65348
  } finally {
65156
- closeSync7(fd);
65349
+ closeSync8(fd);
65157
65350
  unchangedDirectory(directory, identity2);
65158
- const now2 = lstatSync12(file);
65351
+ const now2 = lstatSync14(file);
65159
65352
  if (now2.dev !== lock.dev || now2.ino !== lock.ino || !now2.isFile() || now2.isSymbolicLink())
65160
65353
  fail();
65161
65354
  unlinkSync4(file);
@@ -65207,15 +65400,15 @@ async function preparePrivatePublication(client, sourceDirectory, recoveryDirect
65207
65400
  phase: "prepared",
65208
65401
  intent: null
65209
65402
  };
65210
- if (!isAbsolute8(recoveryDirectory) || resolve9(recoveryDirectory) !== recoveryDirectory || realpathSync5(dirname15(recoveryDirectory)) !== dirname15(recoveryDirectory))
65403
+ if (!isAbsolute10(recoveryDirectory) || resolve11(recoveryDirectory) !== recoveryDirectory || realpathSync5(dirname17(recoveryDirectory)) !== dirname17(recoveryDirectory))
65211
65404
  return fail();
65212
65405
  mkdirSync12(recoveryDirectory, { mode: 448 });
65213
65406
  safeDirectory(recoveryDirectory);
65214
- const parent = openSync7(dirname15(recoveryDirectory), constants6.O_RDONLY | constants6.O_NOFOLLOW);
65407
+ const parent = openSync8(dirname17(recoveryDirectory), constants7.O_RDONLY | constants7.O_NOFOLLOW);
65215
65408
  try {
65216
65409
  fsyncSync2(parent);
65217
65410
  } finally {
65218
- closeSync7(parent);
65411
+ closeSync8(parent);
65219
65412
  }
65220
65413
  writeOwned(recoveryDirectory, "bundle.tgz", packed.bytes);
65221
65414
  save(recoveryDirectory, receipt);