@hasna/skills 0.6.1 → 0.6.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/bin/index.js CHANGED
@@ -36868,7 +36868,7 @@ var package_default;
36868
36868
  var init_package = __esm(() => {
36869
36869
  package_default = {
36870
36870
  name: "@hasna/skills",
36871
- version: "0.6.1",
36871
+ version: "0.6.2",
36872
36872
  description: "Skills library for AI coding agents",
36873
36873
  type: "module",
36874
36874
  bin: {
@@ -43006,7 +43006,7 @@ var require_cli_spinners = __commonJS((exports, module) => {
43006
43006
 
43007
43007
  // src/lib/agent-integration.ts
43008
43008
  import { createHash as createHash2, randomUUID as randomUUID3 } from "crypto";
43009
- import { existsSync as existsSync13, lstatSync as lstatSync3, mkdirSync as mkdirSync4, readFileSync as readFileSync8, readdirSync as readdirSync7, readlinkSync, realpathSync as realpathSync3, renameSync as renameSync2, writeFileSync as writeFileSync4, unlinkSync, chmodSync } from "fs";
43009
+ import { existsSync as existsSync13, lstatSync as lstatSync3, statSync as statSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync8, readdirSync as readdirSync7, readlinkSync, realpathSync as realpathSync3, renameSync as renameSync2, writeFileSync as writeFileSync4, unlinkSync, chmodSync } from "fs";
43010
43010
  import { dirname as dirname4, join as join13, resolve as resolve4, relative as relative3, isAbsolute as isAbsolute3, sep as sep3 } from "path";
43011
43011
  import { homedir as homedir3 } from "os";
43012
43012
  function assertSafePath(path) {
@@ -43094,15 +43094,27 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
43094
43094
  for (const [agent, path] of ROOTS)
43095
43095
  roots.push([agent, join13(resolve4(options.projectDir), path)]);
43096
43096
  const entries = [], seen = new Set;
43097
- function visit(agent, path, vendor = false, depth = 0) {
43097
+ const cacheScans = new Map, maxAliasProofEntries = 1e4;
43098
+ function emptySiblingCacheAlias(path, parent) {
43099
+ const link2 = readlinkSync(path), target = resolve4(parent, link2);
43100
+ if (dirname4(target) !== parent || (isAbsolute3(link2) ? link2 !== target : dirname4(link2) !== "."))
43101
+ return false;
43102
+ if (!lstatSync3(target, { throwIfNoEntry: false })?.isDirectory())
43103
+ return false;
43104
+ const scan = cacheScans.get(target);
43105
+ return Boolean(scan?.complete && !scan.hasSkills && scan.entries <= maxAliasProofEntries);
43106
+ }
43107
+ function visit(agent, path, vendor = false, depth = 0, pluginCache = false) {
43108
+ const scan = { complete: true, hasSkills: false, entries: 1 };
43098
43109
  assertSafePath(path);
43099
43110
  if (!existsSync13(path))
43100
- return;
43111
+ return scan;
43101
43112
  if (!lstatSync3(path).isDirectory())
43102
- return;
43113
+ return scan;
43103
43114
  if (existsSync13(join13(path, "SKILL.md"))) {
43115
+ scan.hasSkills = true;
43104
43116
  if (seen.has(path))
43105
- return;
43117
+ return scan;
43106
43118
  seen.add(path);
43107
43119
  let managed = false;
43108
43120
  const marker = join13(path, ".hasna-skills.json");
@@ -43113,11 +43125,14 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
43113
43125
  }
43114
43126
  const rootAlias = aliases.find((item) => path === item.target || path.startsWith(item.target + sep3));
43115
43127
  entries.push({ agent, path, hash: treeHash(path), managed, vendor, ...rootAlias ? { rootAlias } : {} });
43116
- return;
43128
+ return scan;
43117
43129
  }
43118
43130
  if (depth > (vendor ? 8 : 3))
43119
- return;
43120
- for (const name of readdirSync7(path).sort()) {
43131
+ return { ...scan, complete: false };
43132
+ const children = readdirSync7(path, { withFileTypes: true }).sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
43133
+ if (pluginCache)
43134
+ children.sort((a, b) => Number(a.isSymbolicLink()) - Number(b.isSymbolicLink()));
43135
+ for (const { name } of children) {
43121
43136
  if (name === "node_modules")
43122
43137
  continue;
43123
43138
  if (name.startsWith(".") && name !== ".system")
@@ -43125,14 +43140,28 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
43125
43140
  const isVendor = vendor || name === ".system";
43126
43141
  if (isVendor && !options.includeVendor)
43127
43142
  continue;
43128
- visit(agent, join13(path, name), isVendor, depth + 1);
43143
+ const child = join13(path, name);
43144
+ if (isVendor && lstatSync3(child, { throwIfNoEntry: false })?.isSymbolicLink()) {
43145
+ const target = statSync7(child, { throwIfNoEntry: false });
43146
+ if (target?.isFile() || pluginCache && target?.isDirectory() && emptySiblingCacheAlias(child, path)) {
43147
+ scan.entries++;
43148
+ continue;
43149
+ }
43150
+ }
43151
+ const childScan = visit(agent, child, isVendor, depth + 1, pluginCache);
43152
+ scan.complete &&= childScan.complete;
43153
+ scan.hasSkills ||= childScan.hasSkills;
43154
+ scan.entries += childScan.entries;
43129
43155
  }
43156
+ if (pluginCache)
43157
+ cacheScans.set(path, scan);
43158
+ return scan;
43130
43159
  }
43131
43160
  for (const [agent, path] of roots)
43132
43161
  visit(agent, path);
43133
43162
  if (options.includeVendor) {
43134
43163
  for (const agent of ["codex", "claude"])
43135
- visit(agent, canonicalAgentPath(join13(home, `.${agent}`, "plugins", "cache"), aliases), true);
43164
+ visit(agent, canonicalAgentPath(join13(home, `.${agent}`, "plugins", "cache"), aliases), true, 0, true);
43136
43165
  }
43137
43166
  recheckRootAliases(aliases);
43138
43167
  return entries;
@@ -43363,7 +43392,7 @@ var init_agent_integration = __esm(() => {
43363
43392
  });
43364
43393
 
43365
43394
  // src/lib/home-migration.ts
43366
- import { existsSync as existsSync14, mkdirSync as mkdirSync5, readdirSync as readdirSync8, renameSync as renameSync3, rmSync as rmSync2, statSync as statSync7, writeFileSync as writeFileSync5 } from "fs";
43395
+ import { existsSync as existsSync14, mkdirSync as mkdirSync5, readdirSync as readdirSync8, renameSync as renameSync3, rmSync as rmSync2, statSync as statSync8, writeFileSync as writeFileSync5 } from "fs";
43367
43396
  import { join as join14 } from "path";
43368
43397
  function layoutMigrationRecordPath(appDir) {
43369
43398
  return join14(appDir, SKILLS_CACHE_DIRNAME, LAYOUT_MIGRATION_RECORD);
@@ -43376,7 +43405,7 @@ function migrationAppDir(homeDir) {
43376
43405
  }
43377
43406
  function looksLikeSkillDirectory2(path) {
43378
43407
  try {
43379
- if (!statSync7(path).isDirectory())
43408
+ if (!statSync8(path).isDirectory())
43380
43409
  return false;
43381
43410
  } catch {
43382
43411
  return false;
@@ -43508,7 +43537,7 @@ import {
43508
43537
  readdirSync as readdirSync9,
43509
43538
  renameSync as renameSync4,
43510
43539
  rmSync as rmSync3,
43511
- statSync as statSync8,
43540
+ statSync as statSync9,
43512
43541
  writeFileSync as writeFileSync6
43513
43542
  } from "fs";
43514
43543
  import { homedir as homedir4 } from "os";
@@ -43625,7 +43654,7 @@ function containsSkillDirectories(path) {
43625
43654
  }
43626
43655
  function isDirectory(path) {
43627
43656
  try {
43628
- return statSync8(path).isDirectory();
43657
+ return statSync9(path).isDirectory();
43629
43658
  } catch {
43630
43659
  return false;
43631
43660
  }
@@ -50123,7 +50152,7 @@ var init_remote_workspace_leave = __esm(() => {
50123
50152
  });
50124
50153
 
50125
50154
  // src/lib/auth-store.ts
50126
- import { chmodSync as chmodSync2, existsSync as existsSync18, mkdirSync as mkdirSync8, readFileSync as readFileSync13, renameSync as renameSync5, statSync as statSync9, unlinkSync as unlinkSync2, writeFileSync as writeFileSync8 } from "fs";
50155
+ import { chmodSync as chmodSync2, existsSync as existsSync18, mkdirSync as mkdirSync8, readFileSync as readFileSync13, renameSync as renameSync5, statSync as statSync10, unlinkSync as unlinkSync2, writeFileSync as writeFileSync8 } from "fs";
50127
50156
  import { basename as basename4, dirname as dirname7, join as join19 } from "path";
50128
50157
  function getAuthFilePath(env3 = process.env) {
50129
50158
  return skillsCredentialFilePath(env3);
@@ -50281,7 +50310,7 @@ function getApiUrl(action, env3 = process.env, options = {}) {
50281
50310
  }
50282
50311
  function credentialFileMode(env3 = process.env) {
50283
50312
  try {
50284
- return statSync9(skillsCredentialFilePath(env3)).mode & 511;
50313
+ return statSync10(skillsCredentialFilePath(env3)).mode & 511;
50285
50314
  } catch {
50286
50315
  return null;
50287
50316
  }
@@ -51430,7 +51459,7 @@ var init_revision = __esm(() => {
51430
51459
 
51431
51460
  // src/lib/skill-bundle.ts
51432
51461
  import { createHash as createHash5 } from "crypto";
51433
- import { readFileSync as readFileSync14, readdirSync as readdirSync10, statSync as statSync10 } from "fs";
51462
+ import { readFileSync as readFileSync14, readdirSync as readdirSync10, statSync as statSync11 } from "fs";
51434
51463
  import { join as join20, relative as relative4 } from "path";
51435
51464
  import { createGunzip } from "zlib";
51436
51465
  function isDotenvFile(lower) {
@@ -51491,7 +51520,7 @@ function walk(root, current, out) {
51491
51520
  continue;
51492
51521
  if (isCredentialFile(entry.name))
51493
51522
  continue;
51494
- const stats = statSync10(absolute);
51523
+ const stats = statSync11(absolute);
51495
51524
  out.push({
51496
51525
  path: rel,
51497
51526
  bytes: ownBytes(readFileSync14(absolute)),
@@ -55435,7 +55464,7 @@ var init_init = __esm(() => {
55435
55464
  });
55436
55465
 
55437
55466
  // src/lib/home-adoption.ts
55438
- import { constants as constants4, closeSync as closeSync4, fstatSync as fstatSync4, lstatSync as lstatSync8, openSync as openSync4, readSync as readSync3, existsSync as existsSync24, mkdirSync as mkdirSync11, readdirSync as readdirSync11, readFileSync as readFileSync21, rmSync as rmSync6, statSync as statSync11, writeFileSync as writeFileSync12 } from "fs";
55467
+ import { constants as constants4, closeSync as closeSync4, fstatSync as fstatSync4, lstatSync as lstatSync8, openSync as openSync4, readSync as readSync3, existsSync as existsSync24, mkdirSync as mkdirSync11, readdirSync as readdirSync11, readFileSync as readFileSync21, rmSync as rmSync6, statSync as statSync12, writeFileSync as writeFileSync12 } from "fs";
55439
55468
  import { homedir as homedir6 } from "os";
55440
55469
  import { join as join27 } from "path";
55441
55470
  function indexCanonicalCorpus(corpusRoot) {
@@ -55471,7 +55500,7 @@ function selectedHomeNames(options, index, homeDir2, agents) {
55471
55500
  continue;
55472
55501
  const present = agents.some((agent) => {
55473
55502
  try {
55474
- return statSync11(join27(agentGlobalSkillsDir(agent, homeDir2), name)).isDirectory();
55503
+ return statSync12(join27(agentGlobalSkillsDir(agent, homeDir2), name)).isDirectory();
55475
55504
  } catch {
55476
55505
  return false;
55477
55506
  }
@@ -55505,7 +55534,7 @@ function scanUnmarkedHomes(options = {}) {
55505
55534
  continue;
55506
55535
  const dir = join27(home, skill);
55507
55536
  try {
55508
- if (!statSync11(dir).isDirectory())
55537
+ if (!statSync12(dir).isDirectory())
55509
55538
  continue;
55510
55539
  } catch {
55511
55540
  continue;
@@ -55518,7 +55547,7 @@ function scanUnmarkedHomes(options = {}) {
55518
55547
  if (!existsSync24(skillMdPath))
55519
55548
  continue;
55520
55549
  const hash2 = hashSkillMarkdownFile(skillMdPath);
55521
- const mtime = statSync11(skillMdPath).mtime.toISOString();
55550
+ const mtime = statSync12(skillMdPath).mtime.toISOString();
55522
55551
  const entry = { agent, skill, home, path: dir, hash: hash2, mtime };
55523
55552
  const canonicalHash = index.get(skill);
55524
55553
  if (canonicalHash === undefined) {
@@ -55647,7 +55676,7 @@ function pruneStrayHomes(options = {}) {
55647
55676
  continue;
55648
55677
  const dir = join27(home, skill);
55649
55678
  try {
55650
- if (!statSync11(dir).isDirectory())
55679
+ if (!statSync12(dir).isDirectory())
55651
55680
  continue;
55652
55681
  } catch {
55653
55682
  continue;
@@ -55688,7 +55717,7 @@ var init_home_adoption = __esm(() => {
55688
55717
  });
55689
55718
 
55690
55719
  // src/lib/home-census.ts
55691
- import { existsSync as existsSync25, readFileSync as readFileSync22, readdirSync as readdirSync12, statSync as statSync12 } from "fs";
55720
+ import { existsSync as existsSync25, readFileSync as readFileSync22, readdirSync as readdirSync12, statSync as statSync13 } from "fs";
55692
55721
  import { homedir as homedir7 } from "os";
55693
55722
  import { join as join28 } from "path";
55694
55723
  function sortEntries(entries) {
@@ -55733,7 +55762,7 @@ function censusHomeDrift(options = {}) {
55733
55762
  continue;
55734
55763
  const dir = join28(home, skill);
55735
55764
  try {
55736
- if (!statSync12(dir).isDirectory())
55765
+ if (!statSync13(dir).isDirectory())
55737
55766
  continue;
55738
55767
  } catch {
55739
55768
  continue;
@@ -55986,7 +56015,7 @@ var exports_diagnostic = {};
55986
56015
  __export(exports_diagnostic, {
55987
56016
  registerDiagnostic: () => registerDiagnostic
55988
56017
  });
55989
- import { existsSync as existsSync26, readFileSync as readFileSync24, readdirSync as readdirSync13, statSync as statSync13 } from "fs";
56018
+ import { existsSync as existsSync26, readFileSync as readFileSync24, readdirSync as readdirSync13, statSync as statSync14 } from "fs";
55990
56019
  import { join as join29 } from "path";
55991
56020
  import { execSync as execSync2 } from "child_process";
55992
56021
  function registerDiagnostic(parent) {
@@ -56179,7 +56208,7 @@ function handleWhoami(options) {
56179
56208
  let skillCount = 0;
56180
56209
  if (exists)
56181
56210
  try {
56182
- skillCount = readdirSync13(agentSkillsPath).filter((f) => !f.startsWith(".") && statSync13(join29(agentSkillsPath, f)).isDirectory()).length;
56211
+ skillCount = readdirSync13(agentSkillsPath).filter((f) => !f.startsWith(".") && statSync14(join29(agentSkillsPath, f)).isDirectory()).length;
56183
56212
  } catch {}
56184
56213
  agentConfigs.push({ agent, label: AGENT_LABELS[agent], path: agentSkillsPath, exists, skillCount });
56185
56214
  }
@@ -56766,7 +56795,7 @@ var init_runs = __esm(() => {
56766
56795
 
56767
56796
  // src/lib/run-state.ts
56768
56797
  import { createHash as createHash9, randomBytes } from "crypto";
56769
- import { existsSync as existsSync27, mkdirSync as mkdirSync13, readFileSync as readFileSync25, readdirSync as readdirSync14, statSync as statSync14, writeFileSync as writeFileSync14 } from "fs";
56798
+ import { existsSync as existsSync27, mkdirSync as mkdirSync13, readFileSync as readFileSync25, readdirSync as readdirSync14, statSync as statSync15, writeFileSync as writeFileSync14 } from "fs";
56770
56799
  import { extname, join as join31, relative as relative5 } from "path";
56771
56800
  function createSkillRun(params, targetDir = process.cwd()) {
56772
56801
  const now3 = new Date;
@@ -56848,7 +56877,7 @@ function listSkillRuns(targetDir = process.cwd(), limit = 50) {
56848
56877
  const records = [];
56849
56878
  for (const day of readdirSync14(runsRoot).sort().reverse()) {
56850
56879
  const dayDir = join31(runsRoot, day);
56851
- if (!statSync14(dayDir).isDirectory())
56880
+ if (!statSync15(dayDir).isDirectory())
56852
56881
  continue;
56853
56882
  for (const runId2 of readdirSync14(dayDir).sort().reverse()) {
56854
56883
  const record4 = readRunRecord(join31(dayDir, runId2));
@@ -56897,7 +56926,7 @@ function collectRunArtifacts(context) {
56897
56926
  return [];
56898
56927
  const artifacts = [];
56899
56928
  for (const path of walkFiles(context.exportDir)) {
56900
- const stat = statSync14(path);
56929
+ const stat = statSync15(path);
56901
56930
  const bytes = readFileSync25(path);
56902
56931
  artifacts.push({
56903
56932
  path: toProjectRelative(context.targetDir, path),
@@ -56922,7 +56951,7 @@ function walkFiles(dir) {
56922
56951
  const files = [];
56923
56952
  for (const entry of readdirSync14(dir)) {
56924
56953
  const full = join31(dir, entry);
56925
- if (statSync14(full).isDirectory())
56954
+ if (statSync15(full).isDirectory())
56926
56955
  files.push(...walkFiles(full));
56927
56956
  else
56928
56957
  files.push(full);
@@ -74831,7 +74860,7 @@ var init_run_routing = __esm(() => {
74831
74860
  });
74832
74861
 
74833
74862
  // src/mcp/operation-tools.ts
74834
- import { existsSync as existsSync28, readdirSync as readdirSync15, statSync as statSync15 } from "fs";
74863
+ import { existsSync as existsSync28, readdirSync as readdirSync15, statSync as statSync16 } from "fs";
74835
74864
  import { join as join32 } from "path";
74836
74865
  function registerOperationTools(server) {
74837
74866
  server.registerTool("scaffold_skill", {
@@ -75290,7 +75319,7 @@ function registerOperationTools(server) {
75290
75319
  try {
75291
75320
  skillCount = readdirSync15(agentSkillsPath).filter((f) => {
75292
75321
  const full = join32(agentSkillsPath, f);
75293
- return !f.startsWith(".") && statSync15(full).isDirectory();
75322
+ return !f.startsWith(".") && statSync16(full).isDirectory();
75294
75323
  }).length;
75295
75324
  } catch {}
75296
75325
  }
@@ -75877,7 +75906,7 @@ import {
75877
75906
  mkdirSync as mkdirSync16,
75878
75907
  readFileSync as readFileSync27,
75879
75908
  readdirSync as readdirSync16,
75880
- statSync as statSync16,
75909
+ statSync as statSync17,
75881
75910
  writeFileSync as writeFileSync16
75882
75911
  } from "fs";
75883
75912
  import { dirname as dirname12, join as join35, normalize as normalize3, relative as relative6, sep as sep4 } from "path";
@@ -76003,7 +76032,7 @@ function walkFiles2(dir) {
76003
76032
  const files = [];
76004
76033
  for (const entry of readdirSync16(dir)) {
76005
76034
  const full = join35(dir, entry);
76006
- const stats = statSync16(full);
76035
+ const stats = statSync17(full);
76007
76036
  if (stats.isDirectory())
76008
76037
  files.push(...walkFiles2(full));
76009
76038
  else
@@ -79118,7 +79147,7 @@ var init_completion = __esm(() => {
79118
79147
  });
79119
79148
 
79120
79149
  // src/lib/portable-snapshot-filter.ts
79121
- import { readdirSync as readdirSync17, statSync as statSync17 } from "fs";
79150
+ import { readdirSync as readdirSync17, statSync as statSync18 } from "fs";
79122
79151
  import { homedir as homedir9 } from "os";
79123
79152
  import { join as join40, sep as sep5 } from "path";
79124
79153
  function isExcludedSkillFileName(fileName) {
@@ -79186,7 +79215,7 @@ function walkEntries(absoluteRoot) {
79186
79215
  }
79187
79216
  function isRegularFile(filePath) {
79188
79217
  try {
79189
- return statSync17(filePath).isFile();
79218
+ return statSync18(filePath).isFile();
79190
79219
  } catch {
79191
79220
  return false;
79192
79221
  }
@@ -79272,7 +79301,7 @@ import {
79272
79301
  copyFileSync as copyFileSync2,
79273
79302
  mkdirSync as mkdirSync21,
79274
79303
  readFileSync as readFileSync31,
79275
- statSync as statSync18,
79304
+ statSync as statSync19,
79276
79305
  writeFileSync as writeFileSync21
79277
79306
  } from "fs";
79278
79307
  import { dirname as dirname17, isAbsolute as isAbsolute8, relative as relative7, resolve as resolve9, sep as sep6 } from "path";
@@ -79312,7 +79341,7 @@ function scanHome(definition, homesRoot) {
79312
79341
  skipped.push({ relativePath: entry.relativePath, reason: "not-regular-file" });
79313
79342
  continue;
79314
79343
  }
79315
- const info = statSync18(entry.fullPath);
79344
+ const info = statSync19(entry.fullPath);
79316
79345
  portable.push({
79317
79346
  relativePath: entry.relativePath,
79318
79347
  fullPath: entry.fullPath,
@@ -80055,7 +80084,7 @@ import {
80055
80084
  mkdirSync as mkdirSync22,
80056
80085
  readdirSync as readdirSync18,
80057
80086
  readFileSync as readFileSync34,
80058
- statSync as statSync19,
80087
+ statSync as statSync20,
80059
80088
  writeFileSync as writeFileSync23
80060
80089
  } from "fs";
80061
80090
  import { dirname as dirname18, join as join42, resolve as resolve10, sep as sep7 } from "path";
@@ -80152,7 +80181,7 @@ function planStationHydration(stationId, repoRoot) {
80152
80181
  });
80153
80182
  continue;
80154
80183
  }
80155
- const info = statSync19(entry.fullPath);
80184
+ const info = statSync20(entry.fullPath);
80156
80185
  const manifestHash = manifestHashes.get(`${agent}${MANIFEST_HASH_KEY_SEP}${homeRelative}`) ?? null;
80157
80186
  let verified = false;
80158
80187
  if (manifestHash !== null) {
@@ -82715,11 +82744,11 @@ var init_storage = __esm(() => {
82715
82744
  });
82716
82745
 
82717
82746
  // src/lib/registry-reconcile.ts
82718
- import { existsSync as existsSync35, readFileSync as readFileSync36, statSync as statSync20, writeFileSync as writeFileSync25 } from "fs";
82747
+ import { existsSync as existsSync35, readFileSync as readFileSync36, statSync as statSync21, writeFileSync as writeFileSync25 } from "fs";
82719
82748
  import { join as join44 } from "path";
82720
82749
  function isDirectory2(path) {
82721
82750
  try {
82722
- return statSync20(path).isDirectory();
82751
+ return statSync21(path).isDirectory();
82723
82752
  } catch {
82724
82753
  return false;
82725
82754
  }
package/bin/mcp.js CHANGED
@@ -5586,7 +5586,7 @@ var package_default;
5586
5586
  var init_package = __esm(() => {
5587
5587
  package_default = {
5588
5588
  name: "@hasna/skills",
5589
- version: "0.6.1",
5589
+ version: "0.6.2",
5590
5590
  description: "Skills library for AI coding agents",
5591
5591
  type: "module",
5592
5592
  bin: {
package/bin/migrate.js CHANGED
@@ -7,7 +7,7 @@ import { join as join6 } from "path";
7
7
  // package.json
8
8
  var package_default = {
9
9
  name: "@hasna/skills",
10
- version: "0.6.1",
10
+ version: "0.6.2",
11
11
  description: "Skills library for AI coding agents",
12
12
  type: "module",
13
13
  bin: {
package/bin/server.js CHANGED
@@ -23100,7 +23100,7 @@ var init_dist_es9 = __esm(() => {
23100
23100
  // package.json
23101
23101
  var package_default = {
23102
23102
  name: "@hasna/skills",
23103
- version: "0.6.1",
23103
+ version: "0.6.2",
23104
23104
  description: "Skills library for AI coding agents",
23105
23105
  type: "module",
23106
23106
  bin: {
package/bin/worker.js CHANGED
@@ -23103,7 +23103,7 @@ import { randomUUID as randomUUID5 } from "crypto";
23103
23103
  // package.json
23104
23104
  var package_default = {
23105
23105
  name: "@hasna/skills",
23106
- version: "0.6.1",
23106
+ version: "0.6.2",
23107
23107
  description: "Skills library for AI coding agents",
23108
23108
  type: "module",
23109
23109
  bin: {
package/dist/index.js CHANGED
@@ -3493,7 +3493,7 @@ import {
3493
3493
  readdirSync as readdirSync8,
3494
3494
  renameSync as renameSync3,
3495
3495
  rmSync as rmSync2,
3496
- statSync as statSync7,
3496
+ statSync as statSync8,
3497
3497
  writeFileSync as writeFileSync5
3498
3498
  } from "fs";
3499
3499
  import { homedir as homedir3 } from "os";
@@ -3501,7 +3501,7 @@ import { basename as basename3, dirname as dirname5, join as join10 } from "path
3501
3501
 
3502
3502
  // src/lib/agent-integration.ts
3503
3503
  import { createHash as createHash2, randomUUID } from "crypto";
3504
- import { existsSync as existsSync9, lstatSync as lstatSync3, mkdirSync as mkdirSync4, readFileSync as readFileSync7, readdirSync as readdirSync7, readlinkSync, realpathSync as realpathSync3, renameSync as renameSync2, writeFileSync as writeFileSync4, unlinkSync, chmodSync } from "fs";
3504
+ import { existsSync as existsSync9, lstatSync as lstatSync3, statSync as statSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync7, readdirSync as readdirSync7, readlinkSync, realpathSync as realpathSync3, renameSync as renameSync2, writeFileSync as writeFileSync4, unlinkSync, chmodSync } from "fs";
3505
3505
  import { dirname as dirname4, join as join9, resolve as resolve3, relative as relative3, isAbsolute as isAbsolute3, sep as sep3 } from "path";
3506
3506
  import { homedir as homedir2 } from "os";
3507
3507
  var sha = (data) => createHash2("sha256").update(data).digest("hex");
@@ -3600,15 +3600,27 @@ function inventoryNativeSkills(home = homedir2(), options = {}) {
3600
3600
  for (const [agent, path] of ROOTS)
3601
3601
  roots.push([agent, join9(resolve3(options.projectDir), path)]);
3602
3602
  const entries = [], seen = new Set;
3603
- function visit(agent, path, vendor = false, depth = 0) {
3603
+ const cacheScans = new Map, maxAliasProofEntries = 1e4;
3604
+ function emptySiblingCacheAlias(path, parent) {
3605
+ const link = readlinkSync(path), target = resolve3(parent, link);
3606
+ if (dirname4(target) !== parent || (isAbsolute3(link) ? link !== target : dirname4(link) !== "."))
3607
+ return false;
3608
+ if (!lstatSync3(target, { throwIfNoEntry: false })?.isDirectory())
3609
+ return false;
3610
+ const scan = cacheScans.get(target);
3611
+ return Boolean(scan?.complete && !scan.hasSkills && scan.entries <= maxAliasProofEntries);
3612
+ }
3613
+ function visit(agent, path, vendor = false, depth = 0, pluginCache = false) {
3614
+ const scan = { complete: true, hasSkills: false, entries: 1 };
3604
3615
  assertSafePath(path);
3605
3616
  if (!existsSync9(path))
3606
- return;
3617
+ return scan;
3607
3618
  if (!lstatSync3(path).isDirectory())
3608
- return;
3619
+ return scan;
3609
3620
  if (existsSync9(join9(path, "SKILL.md"))) {
3621
+ scan.hasSkills = true;
3610
3622
  if (seen.has(path))
3611
- return;
3623
+ return scan;
3612
3624
  seen.add(path);
3613
3625
  let managed = false;
3614
3626
  const marker = join9(path, ".hasna-skills.json");
@@ -3619,11 +3631,14 @@ function inventoryNativeSkills(home = homedir2(), options = {}) {
3619
3631
  }
3620
3632
  const rootAlias = aliases.find((item) => path === item.target || path.startsWith(item.target + sep3));
3621
3633
  entries.push({ agent, path, hash: treeHash(path), managed, vendor, ...rootAlias ? { rootAlias } : {} });
3622
- return;
3634
+ return scan;
3623
3635
  }
3624
3636
  if (depth > (vendor ? 8 : 3))
3625
- return;
3626
- for (const name of readdirSync7(path).sort()) {
3637
+ return { ...scan, complete: false };
3638
+ const children = readdirSync7(path, { withFileTypes: true }).sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
3639
+ if (pluginCache)
3640
+ children.sort((a, b) => Number(a.isSymbolicLink()) - Number(b.isSymbolicLink()));
3641
+ for (const { name } of children) {
3627
3642
  if (name === "node_modules")
3628
3643
  continue;
3629
3644
  if (name.startsWith(".") && name !== ".system")
@@ -3631,14 +3646,28 @@ function inventoryNativeSkills(home = homedir2(), options = {}) {
3631
3646
  const isVendor = vendor || name === ".system";
3632
3647
  if (isVendor && !options.includeVendor)
3633
3648
  continue;
3634
- visit(agent, join9(path, name), isVendor, depth + 1);
3649
+ const child = join9(path, name);
3650
+ if (isVendor && lstatSync3(child, { throwIfNoEntry: false })?.isSymbolicLink()) {
3651
+ const target = statSync7(child, { throwIfNoEntry: false });
3652
+ if (target?.isFile() || pluginCache && target?.isDirectory() && emptySiblingCacheAlias(child, path)) {
3653
+ scan.entries++;
3654
+ continue;
3655
+ }
3656
+ }
3657
+ const childScan = visit(agent, child, isVendor, depth + 1, pluginCache);
3658
+ scan.complete &&= childScan.complete;
3659
+ scan.hasSkills ||= childScan.hasSkills;
3660
+ scan.entries += childScan.entries;
3635
3661
  }
3662
+ if (pluginCache)
3663
+ cacheScans.set(path, scan);
3664
+ return scan;
3636
3665
  }
3637
3666
  for (const [agent, path] of roots)
3638
3667
  visit(agent, path);
3639
3668
  if (options.includeVendor) {
3640
3669
  for (const agent of ["codex", "claude"])
3641
- visit(agent, canonicalAgentPath(join9(home, `.${agent}`, "plugins", "cache"), aliases), true);
3670
+ visit(agent, canonicalAgentPath(join9(home, `.${agent}`, "plugins", "cache"), aliases), true, 0, true);
3642
3671
  }
3643
3672
  recheckRootAliases(aliases);
3644
3673
  return entries;
@@ -3963,7 +3992,7 @@ function containsSkillDirectories(path) {
3963
3992
  }
3964
3993
  function isDirectory(path) {
3965
3994
  try {
3966
- return statSync7(path).isDirectory();
3995
+ return statSync8(path).isDirectory();
3967
3996
  } catch {
3968
3997
  return false;
3969
3998
  }
@@ -4594,7 +4623,7 @@ function loadProjectConfigCompat(targetDir) {
4594
4623
  }
4595
4624
  // src/lib/run-state.ts
4596
4625
  import { createHash as createHash3, randomBytes } from "crypto";
4597
- import { existsSync as existsSync13, mkdirSync as mkdirSync7, readFileSync as readFileSync11, readdirSync as readdirSync9, statSync as statSync8, writeFileSync as writeFileSync7 } from "fs";
4626
+ import { existsSync as existsSync13, mkdirSync as mkdirSync7, readFileSync as readFileSync11, readdirSync as readdirSync9, statSync as statSync9, writeFileSync as writeFileSync7 } from "fs";
4598
4627
  import { extname, join as join13, relative as relative4 } from "path";
4599
4628
  function createSkillRun(params, targetDir = process.cwd()) {
4600
4629
  const now = new Date;
@@ -4676,7 +4705,7 @@ function listSkillRuns(targetDir = process.cwd(), limit = 50) {
4676
4705
  const records = [];
4677
4706
  for (const day of readdirSync9(runsRoot).sort().reverse()) {
4678
4707
  const dayDir = join13(runsRoot, day);
4679
- if (!statSync8(dayDir).isDirectory())
4708
+ if (!statSync9(dayDir).isDirectory())
4680
4709
  continue;
4681
4710
  for (const runId of readdirSync9(dayDir).sort().reverse()) {
4682
4711
  const record = readRunRecord(join13(dayDir, runId));
@@ -4715,7 +4744,7 @@ function collectRunArtifacts(context) {
4715
4744
  return [];
4716
4745
  const artifacts = [];
4717
4746
  for (const path of walkFiles(context.exportDir)) {
4718
- const stat = statSync8(path);
4747
+ const stat = statSync9(path);
4719
4748
  const bytes = readFileSync11(path);
4720
4749
  artifacts.push({
4721
4750
  path: toProjectRelative(context.targetDir, path),
@@ -4740,7 +4769,7 @@ function walkFiles(dir) {
4740
4769
  const files = [];
4741
4770
  for (const entry of readdirSync9(dir)) {
4742
4771
  const full = join13(dir, entry);
4743
- if (statSync8(full).isDirectory())
4772
+ if (statSync9(full).isDirectory())
4744
4773
  files.push(...walkFiles(full));
4745
4774
  else
4746
4775
  files.push(full);
@@ -12614,7 +12643,7 @@ import { dirname as dirname7, join as join18 } from "path";
12614
12643
 
12615
12644
  // src/lib/skill-bundle.ts
12616
12645
  import { createHash as createHash6 } from "crypto";
12617
- import { readFileSync as readFileSync15, readdirSync as readdirSync10, statSync as statSync9 } from "fs";
12646
+ import { readFileSync as readFileSync15, readdirSync as readdirSync10, statSync as statSync10 } from "fs";
12618
12647
  import { join as join17, relative as relative5 } from "path";
12619
12648
  import { createGunzip } from "zlib";
12620
12649
  var BLOCK = 512;
@@ -12798,7 +12827,7 @@ function walk(root, current, out) {
12798
12827
  continue;
12799
12828
  if (isCredentialFile(entry.name))
12800
12829
  continue;
12801
- const stats = statSync9(absolute);
12830
+ const stats = statSync10(absolute);
12802
12831
  out.push({
12803
12832
  path: rel,
12804
12833
  bytes: ownBytes(readFileSync15(absolute)),
@@ -13710,7 +13739,7 @@ import { dirname as dirname8, relative as relative6 } from "path";
13710
13739
  // package.json
13711
13740
  var package_default = {
13712
13741
  name: "@hasna/skills",
13713
- version: "0.6.1",
13742
+ version: "0.6.2",
13714
13743
  description: "Skills library for AI coding agents",
13715
13744
  type: "module",
13716
13745
  bin: {
@@ -15031,7 +15060,7 @@ import {
15031
15060
  mkdirSync as mkdirSync12,
15032
15061
  readFileSync as readFileSync17,
15033
15062
  readdirSync as readdirSync11,
15034
- statSync as statSync10,
15063
+ statSync as statSync11,
15035
15064
  writeFileSync as writeFileSync11
15036
15065
  } from "fs";
15037
15066
  import { dirname as dirname10, join as join20, normalize as normalize3, relative as relative7, sep as sep4 } from "path";
@@ -15529,7 +15558,7 @@ function walkFiles2(dir) {
15529
15558
  const files = [];
15530
15559
  for (const entry of readdirSync11(dir)) {
15531
15560
  const full = join20(dir, entry);
15532
- const stats = statSync10(full);
15561
+ const stats = statSync11(full);
15533
15562
  if (stats.isDirectory())
15534
15563
  files.push(...walkFiles2(full));
15535
15564
  else
@@ -15615,13 +15644,13 @@ import {
15615
15644
  copyFileSync as copyFileSync2,
15616
15645
  mkdirSync as mkdirSync13,
15617
15646
  readFileSync as readFileSync18,
15618
- statSync as statSync12,
15647
+ statSync as statSync13,
15619
15648
  writeFileSync as writeFileSync12
15620
15649
  } from "fs";
15621
15650
  import { dirname as dirname11, isAbsolute as isAbsolute5, relative as relative8, resolve as resolve4, sep as sep6 } from "path";
15622
15651
 
15623
15652
  // src/lib/portable-snapshot-filter.ts
15624
- import { readdirSync as readdirSync12, statSync as statSync11 } from "fs";
15653
+ import { readdirSync as readdirSync12, statSync as statSync12 } from "fs";
15625
15654
  import { homedir as homedir5 } from "os";
15626
15655
  import { join as join21, sep as sep5 } from "path";
15627
15656
  var SYNC_HOMES = [
@@ -15759,7 +15788,7 @@ function walkEntries(absoluteRoot) {
15759
15788
  }
15760
15789
  function isRegularFile(filePath) {
15761
15790
  try {
15762
- return statSync11(filePath).isFile();
15791
+ return statSync12(filePath).isFile();
15763
15792
  } catch {
15764
15793
  return false;
15765
15794
  }
@@ -15815,7 +15844,7 @@ function scanHome(definition, homesRoot) {
15815
15844
  skipped.push({ relativePath: entry.relativePath, reason: "not-regular-file" });
15816
15845
  continue;
15817
15846
  }
15818
- const info = statSync12(entry.fullPath);
15847
+ const info = statSync13(entry.fullPath);
15819
15848
  portable.push({
15820
15849
  relativePath: entry.relativePath,
15821
15850
  fullPath: entry.fullPath,
@@ -15942,7 +15971,7 @@ import {
15942
15971
  mkdirSync as mkdirSync14,
15943
15972
  readdirSync as readdirSync13,
15944
15973
  readFileSync as readFileSync19,
15945
- statSync as statSync13,
15974
+ statSync as statSync14,
15946
15975
  writeFileSync as writeFileSync13
15947
15976
  } from "fs";
15948
15977
  import { dirname as dirname12, join as join22, resolve as resolve5, sep as sep7 } from "path";
@@ -16042,7 +16071,7 @@ function planStationHydration(stationId, repoRoot) {
16042
16071
  });
16043
16072
  continue;
16044
16073
  }
16045
- const info = statSync13(entry.fullPath);
16074
+ const info = statSync14(entry.fullPath);
16046
16075
  const manifestHash = manifestHashes.get(`${agent}${MANIFEST_HASH_KEY_SEP}${homeRelative}`) ?? null;
16047
16076
  let verified = false;
16048
16077
  if (manifestHash !== null) {
package/dist/sdk/index.js CHANGED
@@ -24427,7 +24427,7 @@ var init_event_sink = __esm(() => {
24427
24427
  // package.json
24428
24428
  var package_default = {
24429
24429
  name: "@hasna/skills",
24430
- version: "0.6.1",
24430
+ version: "0.6.2",
24431
24431
  description: "Skills library for AI coding agents",
24432
24432
  type: "module",
24433
24433
  bin: {
@@ -38174,7 +38174,7 @@ import {
38174
38174
  readdirSync as readdirSync9,
38175
38175
  renameSync as renameSync3,
38176
38176
  rmSync as rmSync2,
38177
- statSync as statSync8,
38177
+ statSync as statSync9,
38178
38178
  writeFileSync as writeFileSync5
38179
38179
  } from "fs";
38180
38180
  import { homedir as homedir4 } from "os";
@@ -38182,7 +38182,7 @@ import { basename as basename3, dirname as dirname9, join as join15 } from "path
38182
38182
 
38183
38183
  // src/lib/agent-integration.ts
38184
38184
  import { createHash as createHash7, randomUUID as randomUUID5 } from "crypto";
38185
- import { existsSync as existsSync4, lstatSync as lstatSync2, mkdirSync as mkdirSync4, readFileSync as readFileSync6, readdirSync as readdirSync4, readlinkSync, realpathSync, renameSync, writeFileSync as writeFileSync2, unlinkSync, chmodSync } from "fs";
38185
+ import { existsSync as existsSync4, lstatSync as lstatSync2, statSync as statSync3, mkdirSync as mkdirSync4, readFileSync as readFileSync6, readdirSync as readdirSync4, readlinkSync, realpathSync, renameSync, writeFileSync as writeFileSync2, unlinkSync, chmodSync } from "fs";
38186
38186
  import { dirname as dirname6, join as join9, resolve as resolve2, relative as relative2, isAbsolute as isAbsolute3, sep } from "path";
38187
38187
  import { homedir as homedir3 } from "os";
38188
38188
  var sha = (data) => createHash7("sha256").update(data).digest("hex");
@@ -38281,15 +38281,27 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
38281
38281
  for (const [agent, path] of ROOTS)
38282
38282
  roots.push([agent, join9(resolve2(options.projectDir), path)]);
38283
38283
  const entries = [], seen = new Set;
38284
- function visit(agent, path, vendor = false, depth = 0) {
38284
+ const cacheScans = new Map, maxAliasProofEntries = 1e4;
38285
+ function emptySiblingCacheAlias(path, parent) {
38286
+ const link = readlinkSync(path), target = resolve2(parent, link);
38287
+ if (dirname6(target) !== parent || (isAbsolute3(link) ? link !== target : dirname6(link) !== "."))
38288
+ return false;
38289
+ if (!lstatSync2(target, { throwIfNoEntry: false })?.isDirectory())
38290
+ return false;
38291
+ const scan = cacheScans.get(target);
38292
+ return Boolean(scan?.complete && !scan.hasSkills && scan.entries <= maxAliasProofEntries);
38293
+ }
38294
+ function visit(agent, path, vendor = false, depth = 0, pluginCache = false) {
38295
+ const scan = { complete: true, hasSkills: false, entries: 1 };
38285
38296
  assertSafePath(path);
38286
38297
  if (!existsSync4(path))
38287
- return;
38298
+ return scan;
38288
38299
  if (!lstatSync2(path).isDirectory())
38289
- return;
38300
+ return scan;
38290
38301
  if (existsSync4(join9(path, "SKILL.md"))) {
38302
+ scan.hasSkills = true;
38291
38303
  if (seen.has(path))
38292
- return;
38304
+ return scan;
38293
38305
  seen.add(path);
38294
38306
  let managed = false;
38295
38307
  const marker = join9(path, ".hasna-skills.json");
@@ -38300,11 +38312,14 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
38300
38312
  }
38301
38313
  const rootAlias = aliases.find((item) => path === item.target || path.startsWith(item.target + sep));
38302
38314
  entries.push({ agent, path, hash: treeHash(path), managed, vendor, ...rootAlias ? { rootAlias } : {} });
38303
- return;
38315
+ return scan;
38304
38316
  }
38305
38317
  if (depth > (vendor ? 8 : 3))
38306
- return;
38307
- for (const name of readdirSync4(path).sort()) {
38318
+ return { ...scan, complete: false };
38319
+ const children = readdirSync4(path, { withFileTypes: true }).sort((a3, b3) => a3.name < b3.name ? -1 : a3.name > b3.name ? 1 : 0);
38320
+ if (pluginCache)
38321
+ children.sort((a3, b3) => Number(a3.isSymbolicLink()) - Number(b3.isSymbolicLink()));
38322
+ for (const { name } of children) {
38308
38323
  if (name === "node_modules")
38309
38324
  continue;
38310
38325
  if (name.startsWith(".") && name !== ".system")
@@ -38312,14 +38327,28 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
38312
38327
  const isVendor = vendor || name === ".system";
38313
38328
  if (isVendor && !options.includeVendor)
38314
38329
  continue;
38315
- visit(agent, join9(path, name), isVendor, depth + 1);
38330
+ const child = join9(path, name);
38331
+ if (isVendor && lstatSync2(child, { throwIfNoEntry: false })?.isSymbolicLink()) {
38332
+ const target = statSync3(child, { throwIfNoEntry: false });
38333
+ if (target?.isFile() || pluginCache && target?.isDirectory() && emptySiblingCacheAlias(child, path)) {
38334
+ scan.entries++;
38335
+ continue;
38336
+ }
38337
+ }
38338
+ const childScan = visit(agent, child, isVendor, depth + 1, pluginCache);
38339
+ scan.complete &&= childScan.complete;
38340
+ scan.hasSkills ||= childScan.hasSkills;
38341
+ scan.entries += childScan.entries;
38316
38342
  }
38343
+ if (pluginCache)
38344
+ cacheScans.set(path, scan);
38345
+ return scan;
38317
38346
  }
38318
38347
  for (const [agent, path] of roots)
38319
38348
  visit(agent, path);
38320
38349
  if (options.includeVendor) {
38321
38350
  for (const agent of ["codex", "claude"])
38322
- visit(agent, canonicalAgentPath(join9(home, `.${agent}`, "plugins", "cache"), aliases), true);
38351
+ visit(agent, canonicalAgentPath(join9(home, `.${agent}`, "plugins", "cache"), aliases), true, 0, true);
38323
38352
  }
38324
38353
  recheckRootAliases(aliases);
38325
38354
  return entries;
@@ -38532,7 +38561,7 @@ import {
38532
38561
  realpathSync as realpathSync3,
38533
38562
  renameSync as renameSync2,
38534
38563
  rmSync,
38535
- statSync as statSync7,
38564
+ statSync as statSync8,
38536
38565
  writeFileSync as writeFileSync4
38537
38566
  } from "fs";
38538
38567
  import { basename as basename2, dirname as dirname8, isAbsolute as isAbsolute5, join as join14, normalize as normalize2, relative as relative4, resolve as resolve3, sep as sep3 } from "path";
@@ -39247,7 +39276,7 @@ var SKILLS = [
39247
39276
  ];
39248
39277
 
39249
39278
  // src/lib/hosted-skill-set.ts
39250
- import { existsSync as existsSync5, readFileSync as readFileSync7, readdirSync as readdirSync5, statSync as statSync3 } from "fs";
39279
+ import { existsSync as existsSync5, readFileSync as readFileSync7, readdirSync as readdirSync5, statSync as statSync4 } from "fs";
39251
39280
  import { join as join10 } from "path";
39252
39281
  var HOSTED_RUNTIMES = new Set(["hosted"]);
39253
39282
  var HOSTED_SOURCES = new Set(["remote", "private-hosted"]);
@@ -39286,7 +39315,7 @@ var BRACE_SOURCE_EXCLUSION = new RegExp(`^!skills/\\{(${SLUG}(?:,${SLUG})+)\\}/s
39286
39315
  var SINGLE_SOURCE_EXCLUSION = new RegExp(`^!skills/(${SLUG})/src$`);
39287
39316
 
39288
39317
  // src/lib/skill-validation.ts
39289
- import { existsSync as existsSync6, lstatSync as lstatSync3, readFileSync as readFileSync8, readdirSync as readdirSync6, statSync as statSync4 } from "fs";
39318
+ import { existsSync as existsSync6, lstatSync as lstatSync3, readFileSync as readFileSync8, readdirSync as readdirSync6, statSync as statSync5 } from "fs";
39290
39319
  import { isAbsolute as isAbsolute4, join as join11, normalize } from "path";
39291
39320
  var VALID_SKILL_KINDS = ["executable", "instruction"];
39292
39321
  var DOC_FILES = ["SKILL.md", "README.md", "CLAUDE.md"];
@@ -39574,7 +39603,7 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
39574
39603
  const targetPath = join11(skillPath, target);
39575
39604
  if (!existsSync6(targetPath)) {
39576
39605
  add(warnings, "package.bin_target_missing", `package.json bin '${command3}' target '${target}' is not present before build`);
39577
- } else if (statSync4(targetPath).isDirectory()) {
39606
+ } else if (statSync5(targetPath).isDirectory()) {
39578
39607
  add(issues, "package.bin_target_directory", `package.json bin '${command3}' target '${target}' must point to a file, not a directory`);
39579
39608
  }
39580
39609
  }
@@ -39600,7 +39629,7 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
39600
39629
  add(issues, "skill.src_index_missing", "Missing src/index.ts or src/index.js");
39601
39630
  } else {
39602
39631
  const indexPath = existsSync6(join11(srcDir, "index.ts")) ? join11(srcDir, "index.ts") : join11(srcDir, "index.js");
39603
- const size = statSync4(indexPath).size;
39632
+ const size = statSync5(indexPath).size;
39604
39633
  if (size < 50)
39605
39634
  add(warnings, "skill.src_index_minimal", `Source entry point is very small (${size}B)`);
39606
39635
  }
@@ -39625,7 +39654,7 @@ function validateRegistryConsistency(registry, skillsDir) {
39625
39654
  })));
39626
39655
  const skillDirs = existsSync6(skillsDir) ? readdirSync6(skillsDir).filter((entry) => {
39627
39656
  const fullPath = join11(skillsDir, entry);
39628
- return !entry.startsWith(".") && entry !== "_common" && statSync4(fullPath).isDirectory();
39657
+ return !entry.startsWith(".") && entry !== "_common" && statSync5(fullPath).isDirectory();
39629
39658
  }) : [];
39630
39659
  const directoryNames = new Set(skillDirs);
39631
39660
  const registryNameSet = new Set(registryNames);
@@ -39641,7 +39670,7 @@ function validateRegistryConsistency(registry, skillsDir) {
39641
39670
 
39642
39671
  // src/lib/skill-hash.ts
39643
39672
  import { createHash as createHash8 } from "crypto";
39644
- import { existsSync as existsSync7, readdirSync as readdirSync7, readFileSync as readFileSync9, statSync as statSync5 } from "fs";
39673
+ import { existsSync as existsSync7, readdirSync as readdirSync7, readFileSync as readFileSync9, statSync as statSync6 } from "fs";
39645
39674
  import { join as join12, sep as sep2 } from "path";
39646
39675
  var CONTENT_HASH_ALGORITHM = "sha256";
39647
39676
  var HASH_EXCLUDE_DIRS = new Set([".git", "node_modules", "dist", "build", ".turbo"]);
@@ -39707,7 +39736,7 @@ function collectBundleFiles(skillPath) {
39707
39736
  const absolute = join12(skillPath, entry);
39708
39737
  if (!existsSync7(absolute))
39709
39738
  continue;
39710
- if (statSync5(absolute).isDirectory())
39739
+ if (statSync6(absolute).isDirectory())
39711
39740
  collectDirectory(files, absolute, entry);
39712
39741
  else
39713
39742
  collectFile(files, absolute, entry);
@@ -39722,7 +39751,7 @@ function collectDirectory(files, dir, rel) {
39722
39751
  const childRel = `${rel}/${entry}`;
39723
39752
  let stats;
39724
39753
  try {
39725
- stats = statSync5(absolute);
39754
+ stats = statSync6(absolute);
39726
39755
  } catch {
39727
39756
  continue;
39728
39757
  }
@@ -40871,7 +40900,7 @@ function findPortableSkill(name, options = {}) {
40871
40900
  return null;
40872
40901
  }
40873
40902
  const path = getPortableSkillPath(normalized, options);
40874
- if (!existsSync9(path) || !statSync7(path).isDirectory())
40903
+ if (!existsSync9(path) || !statSync8(path).isDirectory())
40875
40904
  return null;
40876
40905
  try {
40877
40906
  return summarizePortableSkill(path, normalized);
@@ -40940,7 +40969,7 @@ function scaffoldPortableSkill(name, options = {}) {
40940
40969
  }
40941
40970
  function portPortableSkillDirectory(sourceDir, options = {}) {
40942
40971
  const absoluteSource = normalize2(sourceDir);
40943
- if (!existsSync9(absoluteSource) || !statSync7(absoluteSource).isDirectory()) {
40972
+ if (!existsSync9(absoluteSource) || !statSync8(absoluteSource).isDirectory()) {
40944
40973
  throw new Error(`Import directory not found: ${sourceDir}`);
40945
40974
  }
40946
40975
  const continueOnError = options.continueOnError ?? true;
@@ -41006,7 +41035,7 @@ function assertDisjointImportPaths(source, destination) {
41006
41035
  }
41007
41036
  function portPortableSkill(sourcePath, options = {}) {
41008
41037
  const absoluteSource = normalize2(sourcePath);
41009
- if (!existsSync9(absoluteSource) || !statSync7(absoluteSource).isDirectory()) {
41038
+ if (!existsSync9(absoluteSource) || !statSync8(absoluteSource).isDirectory()) {
41010
41039
  throw new Error(`Skill source directory not found: ${sourcePath}`);
41011
41040
  }
41012
41041
  const inferred = readPortableSkillManifestForImport(absoluteSource);
@@ -41170,7 +41199,7 @@ function validatePortableSkillDirectory(name, skillPath) {
41170
41199
  const entryPath = join14(skillPath, command3.entry);
41171
41200
  if (!existsSync9(entryPath))
41172
41201
  add3(issues, "portable.command_entry_missing", `Command '${command3.name}' entry '${command3.entry}' is missing`);
41173
- else if (statSync7(entryPath).isDirectory())
41202
+ else if (statSync8(entryPath).isDirectory())
41174
41203
  add3(issues, "portable.command_entry_directory", `Command '${command3.name}' entry '${command3.entry}' must be a file`);
41175
41204
  }
41176
41205
  }
@@ -41260,7 +41289,7 @@ function summarizePortableSkill(skillPath, fallbackName) {
41260
41289
  }
41261
41290
  function safeIsDirectory(path) {
41262
41291
  try {
41263
- return statSync7(path).isDirectory();
41292
+ return statSync8(path).isDirectory();
41264
41293
  } catch {
41265
41294
  return false;
41266
41295
  }
@@ -41400,7 +41429,7 @@ function containsSkillDirectories(path) {
41400
41429
  }
41401
41430
  function isDirectory(path) {
41402
41431
  try {
41403
- return statSync8(path).isDirectory();
41432
+ return statSync9(path).isDirectory();
41404
41433
  } catch {
41405
41434
  return false;
41406
41435
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/skills",
3
- "version": "0.6.1",
3
+ "version": "0.6.2",
4
4
  "description": "Skills library for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {