skill-tree 0.1.7 → 0.2.0

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/index.mjs CHANGED
@@ -8,11 +8,25 @@ var __export = (target, all) => {
8
8
  __defProp(target, name, { get: all[name], enumerable: true });
9
9
  };
10
10
 
11
+ // node_modules/tsup/assets/esm_shims.js
12
+ import path from "path";
13
+ import { fileURLToPath } from "url";
14
+ var getFilename, getDirname, __dirname;
15
+ var init_esm_shims = __esm({
16
+ "node_modules/tsup/assets/esm_shims.js"() {
17
+ "use strict";
18
+ getFilename = () => fileURLToPath(import.meta.url);
19
+ getDirname = () => path.dirname(getFilename());
20
+ __dirname = /* @__PURE__ */ getDirname();
21
+ }
22
+ });
23
+
11
24
  // src/storage/base.ts
12
25
  var BaseStorageAdapter, MemoryStorageAdapter;
13
26
  var init_base = __esm({
14
27
  "src/storage/base.ts"() {
15
28
  "use strict";
29
+ init_esm_shims();
16
30
  BaseStorageAdapter = class {
17
31
  constructor() {
18
32
  this.initialized = false;
@@ -41,9 +55,6 @@ var init_base = __esm({
41
55
  if (filter.author && skill.author !== filter.author) {
42
56
  return false;
43
57
  }
44
- if (filter.minSuccessRate !== void 0 && skill.metrics.successRate < filter.minSuccessRate) {
45
- return false;
46
- }
47
58
  if (filter.createdAfter && skill.createdAt < filter.createdAfter) {
48
59
  return false;
49
60
  }
@@ -282,12 +293,13 @@ __export(sqlite_exports, {
282
293
  SQLiteStorageAdapter: () => SQLiteStorageAdapter
283
294
  });
284
295
  import Database from "better-sqlite3";
285
- import * as path7 from "path";
296
+ import * as path8 from "path";
286
297
  import * as fs7 from "fs";
287
298
  var SCHEMA_VERSION, SQLiteStorageAdapter;
288
299
  var init_sqlite = __esm({
289
300
  "src/storage/sqlite.ts"() {
290
301
  "use strict";
302
+ init_esm_shims();
291
303
  init_base();
292
304
  SCHEMA_VERSION = 3;
293
305
  SQLiteStorageAdapter = class extends BaseStorageAdapter {
@@ -301,7 +313,7 @@ var init_sqlite = __esm({
301
313
  };
302
314
  }
303
315
  async initialize() {
304
- const dir = path7.dirname(this.config.dbPath);
316
+ const dir = path8.dirname(this.config.dbPath);
305
317
  if (dir && !fs7.existsSync(dir)) {
306
318
  fs7.mkdirSync(dir, { recursive: true });
307
319
  }
@@ -336,12 +348,19 @@ var init_sqlite = __esm({
336
348
  status TEXT NOT NULL,
337
349
  parent_version TEXT,
338
350
  derived_from TEXT,
339
- metrics TEXT NOT NULL,
340
351
  source TEXT,
341
352
  taxonomy TEXT,
342
353
  external_source TEXT
343
354
  )
344
355
  `);
356
+ try {
357
+ db.exec("ALTER TABLE skills DROP COLUMN metrics");
358
+ } catch {
359
+ const cols = db.prepare("PRAGMA table_info(skills)").all();
360
+ if (cols.some((c) => c.name === "metrics")) {
361
+ this.rebuildSkillsTableWithoutMetrics(db, cols);
362
+ }
363
+ }
345
364
  db.exec(`
346
365
  CREATE TABLE IF NOT EXISTS skill_versions (
347
366
  id INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -505,6 +524,75 @@ var init_sqlite = __esm({
505
524
  db.prepare("UPDATE schema_version SET version = ?").run(SCHEMA_VERSION);
506
525
  }
507
526
  }
527
+ /**
528
+ * Rebuild the `skills` table without the legacy `metrics` column.
529
+ *
530
+ * Used as the fallback path on SQLite < 3.35 where ALTER TABLE DROP
531
+ * COLUMN isn't supported. Uses the standard "table dance" pattern:
532
+ * CREATE NEW → INSERT FROM OLD → DROP OLD → RENAME, inside a single
533
+ * transaction so a partial state can't outlive a crash.
534
+ *
535
+ * The `existingCols` arg is the full PRAGMA table_info output for the
536
+ * legacy table — we use it to figure out which columns to copy. Some
537
+ * legacy installs may have a subset of the current schema's columns
538
+ * (e.g., taxonomy/external_source were added in v2, related in v3),
539
+ * so we only copy columns that exist on both sides.
540
+ */
541
+ rebuildSkillsTableWithoutMetrics(db, existingCols) {
542
+ const NEW_SCHEMA_COLUMNS = [
543
+ "id",
544
+ "version",
545
+ "name",
546
+ "description",
547
+ "instructions",
548
+ "related",
549
+ "author",
550
+ "tags",
551
+ "created_at",
552
+ "updated_at",
553
+ "status",
554
+ "parent_version",
555
+ "derived_from",
556
+ "source",
557
+ "taxonomy",
558
+ "external_source"
559
+ ];
560
+ const sourceNames = new Set(existingCols.map((c) => c.name));
561
+ const copyable = NEW_SCHEMA_COLUMNS.filter((c) => sourceNames.has(c));
562
+ const copyList = copyable.join(", ");
563
+ db.exec("BEGIN");
564
+ try {
565
+ db.exec(`
566
+ CREATE TABLE skills_new (
567
+ id TEXT PRIMARY KEY,
568
+ version TEXT NOT NULL,
569
+ name TEXT NOT NULL,
570
+ description TEXT,
571
+ instructions TEXT NOT NULL DEFAULT '',
572
+ related TEXT,
573
+ author TEXT NOT NULL,
574
+ tags TEXT NOT NULL,
575
+ created_at TEXT NOT NULL,
576
+ updated_at TEXT NOT NULL,
577
+ status TEXT NOT NULL,
578
+ parent_version TEXT,
579
+ derived_from TEXT,
580
+ source TEXT,
581
+ taxonomy TEXT,
582
+ external_source TEXT
583
+ )
584
+ `);
585
+ db.exec(
586
+ `INSERT INTO skills_new (${copyList}) SELECT ${copyList} FROM skills`
587
+ );
588
+ db.exec("DROP TABLE skills");
589
+ db.exec("ALTER TABLE skills_new RENAME TO skills");
590
+ db.exec("COMMIT");
591
+ } catch (err) {
592
+ db.exec("ROLLBACK");
593
+ throw err;
594
+ }
595
+ }
508
596
  getDb() {
509
597
  if (!this.db) {
510
598
  throw new Error("Database not initialized. Call initialize() first.");
@@ -517,10 +605,10 @@ var init_sqlite = __esm({
517
605
  const stmt = db.prepare(`
518
606
  INSERT OR REPLACE INTO skills (
519
607
  id, version, name, description, instructions, related, author, tags,
520
- created_at, updated_at, status, parent_version, derived_from, metrics,
608
+ created_at, updated_at, status, parent_version, derived_from,
521
609
  source, taxonomy, external_source
522
610
  ) VALUES (
523
- ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
611
+ ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
524
612
  )
525
613
  `);
526
614
  stmt.run(
@@ -537,7 +625,6 @@ var init_sqlite = __esm({
537
625
  skill.status,
538
626
  skill.parentVersion || null,
539
627
  skill.derivedFrom ? JSON.stringify(skill.derivedFrom) : null,
540
- JSON.stringify(skill.metrics),
541
628
  skill.source ? JSON.stringify(skill.source) : null,
542
629
  skill.taxonomy ? JSON.stringify(skill.taxonomy) : null,
543
630
  skill.externalSource ? JSON.stringify({
@@ -632,10 +719,6 @@ var init_sqlite = __esm({
632
719
  sql += " AND author = ?";
633
720
  params.push(filter.author);
634
721
  }
635
- if (filter?.minSuccessRate !== void 0) {
636
- sql += " AND json_extract(metrics, '$.successRate') >= ?";
637
- params.push(filter.minSuccessRate);
638
- }
639
722
  if (filter?.createdAfter) {
640
723
  sql += " AND created_at >= ?";
641
724
  params.push(filter.createdAfter.toISOString());
@@ -831,15 +914,15 @@ var init_sqlite = __esm({
831
914
  /**
832
915
  * Get or create a taxonomy node
833
916
  */
834
- async ensureTaxonomyNode(path13) {
917
+ async ensureTaxonomyNode(path14) {
835
918
  this.ensureInitialized();
836
919
  const db = this.getDb();
837
- const pathStr = path13.join("/");
920
+ const pathStr = path14.join("/");
838
921
  const existing = db.prepare("SELECT id FROM taxonomy_nodes WHERE path = ?").get(pathStr);
839
922
  if (existing) return existing.id;
840
923
  const id = `node-${pathStr.replace(/\//g, "-").toLowerCase()}`;
841
- const name = path13[path13.length - 1] || "Root";
842
- const parentPath = path13.slice(0, -1);
924
+ const name = path14[path14.length - 1] || "Root";
925
+ const parentPath = path14.slice(0, -1);
843
926
  let parentId = null;
844
927
  if (parentPath.length > 0) {
845
928
  parentId = await this.ensureTaxonomyNode(parentPath);
@@ -1030,7 +1113,6 @@ var init_sqlite = __esm({
1030
1113
  status: row.status,
1031
1114
  parentVersion: row.parent_version || void 0,
1032
1115
  derivedFrom: row.derived_from ? JSON.parse(row.derived_from) : void 0,
1033
- metrics: JSON.parse(row.metrics),
1034
1116
  source: row.source ? JSON.parse(row.source) : void 0,
1035
1117
  taxonomy: row.taxonomy ? JSON.parse(row.taxonomy) : void 0,
1036
1118
  externalSource: externalSource ? {
@@ -1047,11 +1129,7 @@ var init_sqlite = __esm({
1047
1129
  source: skill.source ? {
1048
1130
  ...skill.source,
1049
1131
  importedAt: skill.source.importedAt.toISOString()
1050
- } : void 0,
1051
- metrics: {
1052
- ...skill.metrics,
1053
- lastUsed: skill.metrics.lastUsed?.toISOString()
1054
- }
1132
+ } : void 0
1055
1133
  };
1056
1134
  }
1057
1135
  deserializeSkill(data) {
@@ -1062,11 +1140,7 @@ var init_sqlite = __esm({
1062
1140
  source: data.source ? {
1063
1141
  ...data.source,
1064
1142
  importedAt: new Date(data.source.importedAt)
1065
- } : void 0,
1066
- metrics: {
1067
- ...data.metrics,
1068
- lastUsed: data.metrics.lastUsed ? new Date(data.metrics.lastUsed) : void 0
1069
- }
1143
+ } : void 0
1070
1144
  };
1071
1145
  }
1072
1146
  hashSkill(skill) {
@@ -1090,6 +1164,7 @@ var DEFAULT_AGENTS_CONFIG;
1090
1164
  var init_types = __esm({
1091
1165
  "src/agents/types.ts"() {
1092
1166
  "use strict";
1167
+ init_esm_shims();
1093
1168
  DEFAULT_AGENTS_CONFIG = {
1094
1169
  format: "xml",
1095
1170
  includeIds: true,
@@ -1107,6 +1182,7 @@ var AgentsGenerator;
1107
1182
  var init_generator = __esm({
1108
1183
  "src/agents/generator.ts"() {
1109
1184
  "use strict";
1185
+ init_esm_shims();
1110
1186
  init_types();
1111
1187
  AgentsGenerator = class {
1112
1188
  constructor(config) {
@@ -1275,9 +1351,6 @@ ${this.indentContent(skill.instructions, 4)}
1275
1351
  if (filter.tags && filter.tags.length > 0) {
1276
1352
  result = result.filter((s) => s.tags.some((t) => filter.tags.includes(t)));
1277
1353
  }
1278
- if (filter.minSuccessRate !== void 0) {
1279
- result = result.filter((s) => s.metrics.successRate >= filter.minSuccessRate);
1280
- }
1281
1354
  if (filter.limit) {
1282
1355
  result = result.slice(0, filter.limit);
1283
1356
  }
@@ -1324,6 +1397,7 @@ var AgentsParser;
1324
1397
  var init_parser = __esm({
1325
1398
  "src/agents/parser.ts"() {
1326
1399
  "use strict";
1400
+ init_esm_shims();
1327
1401
  AgentsParser = class {
1328
1402
  /**
1329
1403
  * Parse AGENTS.md content
@@ -1377,11 +1451,6 @@ var init_parser = __esm({
1377
1451
  createdAt: defaults?.createdAt || now,
1378
1452
  updatedAt: now,
1379
1453
  status: "active",
1380
- metrics: defaults?.metrics || {
1381
- usageCount: 0,
1382
- successRate: 0,
1383
- feedbackScores: []
1384
- },
1385
1454
  source: {
1386
1455
  type: "imported",
1387
1456
  location: "AGENTS.md",
@@ -1564,7 +1633,7 @@ __export(sync_exports, {
1564
1633
  writeAgentsMd: () => writeAgentsMd
1565
1634
  });
1566
1635
  import * as fs9 from "fs";
1567
- import * as path9 from "path";
1636
+ import * as path10 from "path";
1568
1637
  function createAgentsSync() {
1569
1638
  return new AgentsSync();
1570
1639
  }
@@ -1574,7 +1643,7 @@ async function generateAgentsMd(storage, config) {
1574
1643
  }
1575
1644
  async function writeAgentsMd(storage, filePath, config) {
1576
1645
  const content = await generateAgentsMd(storage, config);
1577
- const dir = path9.dirname(filePath);
1646
+ const dir = path10.dirname(filePath);
1578
1647
  if (dir && !fs9.existsSync(dir)) {
1579
1648
  fs9.mkdirSync(dir, { recursive: true });
1580
1649
  }
@@ -1592,6 +1661,7 @@ var AgentsSync;
1592
1661
  var init_sync = __esm({
1593
1662
  "src/agents/sync.ts"() {
1594
1663
  "use strict";
1664
+ init_esm_shims();
1595
1665
  init_generator();
1596
1666
  init_parser();
1597
1667
  AgentsSync = class {
@@ -1697,7 +1767,7 @@ var init_sync = __esm({
1697
1767
  }
1698
1768
  }
1699
1769
  if (!options.dryRun) {
1700
- const dir = path9.dirname(agentsPath);
1770
+ const dir = path10.dirname(agentsPath);
1701
1771
  if (!fs9.existsSync(dir)) {
1702
1772
  fs9.mkdirSync(dir, { recursive: true });
1703
1773
  }
@@ -1749,8 +1819,6 @@ var init_sync = __esm({
1749
1819
  // Keep existing ID
1750
1820
  createdAt: existing.createdAt,
1751
1821
  // Preserve creation date
1752
- metrics: existing.metrics,
1753
- // Preserve usage metrics
1754
1822
  source: incoming.source || existing.source,
1755
1823
  parentVersion: existing.version
1756
1824
  // Track update lineage
@@ -1760,7 +1828,14 @@ var init_sync = __esm({
1760
1828
  }
1761
1829
  });
1762
1830
 
1831
+ // src/index.ts
1832
+ init_esm_shims();
1833
+
1834
+ // src/skill-bank.ts
1835
+ init_esm_shims();
1836
+
1763
1837
  // src/types.ts
1838
+ init_esm_shims();
1764
1839
  function hasTaxonomySupport(storage) {
1765
1840
  return typeof storage.placeInTaxonomy === "function";
1766
1841
  }
@@ -1768,18 +1843,23 @@ function hasForkSupport(storage) {
1768
1843
  return typeof storage.recordFork === "function";
1769
1844
  }
1770
1845
 
1846
+ // src/sync/sync-manager.ts
1847
+ init_esm_shims();
1848
+
1771
1849
  // src/sync/git-sync-adapter.ts
1850
+ init_esm_shims();
1772
1851
  import * as fs2 from "fs";
1773
- import * as path2 from "path";
1852
+ import * as path3 from "path";
1774
1853
 
1775
1854
  // src/sync/conflict-store.ts
1855
+ init_esm_shims();
1776
1856
  import * as fs from "fs";
1777
- import * as path from "path";
1857
+ import * as path2 from "path";
1778
1858
  var ConflictStore = class {
1779
1859
  constructor(basePath) {
1780
- const skillbankDir = path.join(basePath, ".skillbank");
1781
- this.conflictsDir = path.join(skillbankDir, "conflicts");
1782
- this.stateFile = path.join(skillbankDir, "sync-state.json");
1860
+ const skillbankDir = path2.join(basePath, ".skillbank");
1861
+ this.conflictsDir = path2.join(skillbankDir, "conflicts");
1862
+ this.stateFile = path2.join(skillbankDir, "sync-state.json");
1783
1863
  }
1784
1864
  /**
1785
1865
  * Initialize the store (create directories if needed)
@@ -1796,7 +1876,7 @@ var ConflictStore = class {
1796
1876
  async saveConflict(conflict) {
1797
1877
  await this.initialize();
1798
1878
  const filename = this.getConflictFilename(conflict.skillId);
1799
- const filepath = path.join(this.conflictsDir, filename);
1879
+ const filepath = path2.join(this.conflictsDir, filename);
1800
1880
  const data = JSON.stringify(this.serializeConflict(conflict), null, 2);
1801
1881
  await fs.promises.writeFile(filepath, data, "utf-8");
1802
1882
  }
@@ -1805,7 +1885,7 @@ var ConflictStore = class {
1805
1885
  */
1806
1886
  async getConflict(skillId) {
1807
1887
  const filename = this.getConflictFilename(skillId);
1808
- const filepath = path.join(this.conflictsDir, filename);
1888
+ const filepath = path2.join(this.conflictsDir, filename);
1809
1889
  try {
1810
1890
  const data = await fs.promises.readFile(filepath, "utf-8");
1811
1891
  return this.deserializeConflict(JSON.parse(data));
@@ -1826,7 +1906,7 @@ var ConflictStore = class {
1826
1906
  const conflicts = [];
1827
1907
  for (const file of files) {
1828
1908
  if (file.endsWith(".json")) {
1829
- const filepath = path.join(this.conflictsDir, file);
1909
+ const filepath = path2.join(this.conflictsDir, file);
1830
1910
  try {
1831
1911
  const data = await fs.promises.readFile(filepath, "utf-8");
1832
1912
  conflicts.push(this.deserializeConflict(JSON.parse(data)));
@@ -1849,7 +1929,7 @@ var ConflictStore = class {
1849
1929
  */
1850
1930
  async removeConflict(skillId) {
1851
1931
  const filename = this.getConflictFilename(skillId);
1852
- const filepath = path.join(this.conflictsDir, filename);
1932
+ const filepath = path2.join(this.conflictsDir, filename);
1853
1933
  try {
1854
1934
  await fs.promises.unlink(filepath);
1855
1935
  return true;
@@ -1988,10 +2068,6 @@ var ConflictStore = class {
1988
2068
  ...skill,
1989
2069
  createdAt: skill.createdAt instanceof Date ? skill.createdAt.toISOString() : skill.createdAt,
1990
2070
  updatedAt: skill.updatedAt instanceof Date ? skill.updatedAt.toISOString() : skill.updatedAt,
1991
- metrics: {
1992
- ...skill.metrics,
1993
- lastUsed: skill.metrics?.lastUsed instanceof Date ? skill.metrics.lastUsed.toISOString() : skill.metrics?.lastUsed
1994
- },
1995
2071
  source: skill.source ? {
1996
2072
  ...skill.source,
1997
2073
  importedAt: skill.source.importedAt instanceof Date ? skill.source.importedAt.toISOString() : skill.source.importedAt
@@ -2003,10 +2079,6 @@ var ConflictStore = class {
2003
2079
  ...data,
2004
2080
  createdAt: new Date(data.createdAt),
2005
2081
  updatedAt: new Date(data.updatedAt),
2006
- metrics: {
2007
- ...data.metrics,
2008
- lastUsed: data.metrics?.lastUsed ? new Date(data.metrics.lastUsed) : void 0
2009
- },
2010
2082
  source: data.source ? {
2011
2083
  ...data.source,
2012
2084
  importedAt: new Date(data.source.importedAt)
@@ -2077,7 +2149,7 @@ var GitSyncAdapter = class {
2077
2149
  for (const file of changedFiles) {
2078
2150
  const skillId = this.extractSkillIdFromPath(file);
2079
2151
  if (!skillId) continue;
2080
- const localPath = path2.join(this.repoPath, file);
2152
+ const localPath = path3.join(this.repoPath, file);
2081
2153
  const existsLocally = fs2.existsSync(localPath);
2082
2154
  let existsRemotely = true;
2083
2155
  try {
@@ -2364,7 +2436,7 @@ var GitSyncAdapter = class {
2364
2436
  return this.config.remote.skillsPath || "skills/";
2365
2437
  }
2366
2438
  getSkillFilePath(skillId) {
2367
- return path2.join(this.getSkillsPath(), skillId, "SKILL.md");
2439
+ return path3.join(this.getSkillsPath(), skillId, "SKILL.md");
2368
2440
  }
2369
2441
  extractSkillIdFromPath(filePath) {
2370
2442
  const skillsPath = this.getSkillsPath();
@@ -2378,7 +2450,7 @@ var GitSyncAdapter = class {
2378
2450
  }
2379
2451
  async pullSkill(skillId, branch, syncState, options) {
2380
2452
  const skillPath = this.getSkillFilePath(skillId);
2381
- const fullPath = path2.join(this.repoPath, skillPath);
2453
+ const fullPath = path3.join(this.repoPath, skillPath);
2382
2454
  let remoteContent;
2383
2455
  try {
2384
2456
  remoteContent = await this.git.show([`origin/${branch}:${skillPath}`]);
@@ -2576,18 +2648,13 @@ ${remoteValue}`;
2576
2648
  tags: metadata.tags ? metadata.tags.split(",").map((t) => t.trim()) : [],
2577
2649
  createdAt: metadata.created ? new Date(metadata.created) : /* @__PURE__ */ new Date(),
2578
2650
  updatedAt: metadata.updated ? new Date(metadata.updated) : /* @__PURE__ */ new Date(),
2579
- status: isValidStatus(metadata.status) ? metadata.status : "active",
2580
- metrics: {
2581
- usageCount: 0,
2582
- successRate: 0,
2583
- feedbackScores: []
2584
- }
2651
+ status: isValidStatus(metadata.status) ? metadata.status : "active"
2585
2652
  };
2586
2653
  }
2587
2654
  async writeSkill(skill) {
2588
2655
  const skillPath = this.getSkillFilePath(skill.id);
2589
- const fullPath = path2.join(this.repoPath, skillPath);
2590
- await fs2.promises.mkdir(path2.dirname(fullPath), { recursive: true });
2656
+ const fullPath = path3.join(this.repoPath, skillPath);
2657
+ await fs2.promises.mkdir(path3.dirname(fullPath), { recursive: true });
2591
2658
  const content = this.buildSkillContent(skill);
2592
2659
  await fs2.promises.writeFile(fullPath, content, "utf-8");
2593
2660
  }
@@ -2638,11 +2705,11 @@ ${body.join("\n")}
2638
2705
  agent: this.config.agent,
2639
2706
  skills: {}
2640
2707
  };
2641
- const skillsPath = path2.join(this.repoPath, this.getSkillsPath());
2708
+ const skillsPath = path3.join(this.repoPath, this.getSkillsPath());
2642
2709
  if (fs2.existsSync(skillsPath)) {
2643
2710
  const dirs = await fs2.promises.readdir(skillsPath);
2644
2711
  for (const dir of dirs) {
2645
- const skillPath = path2.join(skillsPath, dir, "SKILL.md");
2712
+ const skillPath = path3.join(skillsPath, dir, "SKILL.md");
2646
2713
  if (fs2.existsSync(skillPath)) {
2647
2714
  try {
2648
2715
  const content = await fs2.promises.readFile(skillPath, "utf-8");
@@ -2842,7 +2909,14 @@ function createSyncManager(options) {
2842
2909
  return new SyncManager(options);
2843
2910
  }
2844
2911
 
2912
+ // src/serving/graph-server.ts
2913
+ init_esm_shims();
2914
+
2915
+ // src/serving/catalog-renderer.ts
2916
+ init_esm_shims();
2917
+
2845
2918
  // src/serving/xml-utils.ts
2919
+ init_esm_shims();
2846
2920
  function escapeXml(text) {
2847
2921
  return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
2848
2922
  }
@@ -2910,11 +2984,11 @@ var CatalogRenderer = class _CatalogRenderer {
2910
2984
  * Render a specific category path for browse drill-down.
2911
2985
  * Shows subcategories at intermediate nodes, or skill summaries at leaf nodes.
2912
2986
  */
2913
- async renderCategory(path13) {
2987
+ async renderCategory(path14) {
2914
2988
  if (hasCatalogSupport(this.storage)) {
2915
- return this.renderCategoryFromTaxonomy(this.storage, path13);
2989
+ return this.renderCategoryFromTaxonomy(this.storage, path14);
2916
2990
  }
2917
- return this.renderCategoryFromTags(path13);
2991
+ return this.renderCategoryFromTags(path14);
2918
2992
  }
2919
2993
  /**
2920
2994
  * Invalidate the overview cache (e.g., after skill changes).
@@ -2952,9 +3026,9 @@ var CatalogRenderer = class _CatalogRenderer {
2952
3026
  const categories = counted.sort((a, b) => b.count - a.count).slice(0, this.config.maxCategoriesPerLevel).map((c) => ({ name: c.node.name, count: c.count }));
2953
3027
  return this.renderOverviewXml(totalSkills, categories);
2954
3028
  }
2955
- async renderCategoryFromTaxonomy(storage, path13) {
2956
- const tree = await storage.getTaxonomyTree(path13);
2957
- const pathStr = path13.join("/");
3029
+ async renderCategoryFromTaxonomy(storage, path14) {
3030
+ const tree = await storage.getTaxonomyTree(path14);
3031
+ const pathStr = path14.join("/");
2958
3032
  if (tree.length > 0 && tree.some((n) => n.children.length > 0)) {
2959
3033
  const root = tree[0];
2960
3034
  const rootCount = this.countNodeSkills(root);
@@ -2964,7 +3038,7 @@ var CatalogRenderer = class _CatalogRenderer {
2964
3038
  lines.push(`<catalog_browse path="${escapeXml(pathStr)}" count="${rootCount}">`);
2965
3039
  lines.push(" <subcategories>");
2966
3040
  for (const { node: child, count } of children) {
2967
- const childPath = [...path13, child.name].join("/");
3041
+ const childPath = [...path14, child.name].join("/");
2968
3042
  lines.push(` <category path="${escapeXml(childPath)}" count="${count}" />`);
2969
3043
  }
2970
3044
  lines.push(" </subcategories>");
@@ -2988,13 +3062,13 @@ var CatalogRenderer = class _CatalogRenderer {
2988
3062
  const categories = Array.from(tagCounts.entries()).sort((a, b) => b[1] - a[1]).slice(0, this.config.maxCategoriesPerLevel).map(([name, count]) => ({ name, count }));
2989
3063
  return this.renderOverviewXml(skills.length, categories);
2990
3064
  }
2991
- async renderCategoryFromTags(path13) {
2992
- if (path13.length === 0) {
3065
+ async renderCategoryFromTags(path14) {
3066
+ if (path14.length === 0) {
2993
3067
  return this.renderOverviewFromTags();
2994
3068
  }
2995
- const tag = path13[0];
3069
+ const tag = path14[0];
2996
3070
  const matching = await this.storage.listSkills({ status: ["active"], tags: [tag] });
2997
- const pathStr = path13.join("/");
3071
+ const pathStr = path14.join("/");
2998
3072
  return this.renderLeafSkills(matching, pathStr, matching.length);
2999
3073
  }
3000
3074
  // ===========================================================================
@@ -3049,6 +3123,7 @@ var CatalogRenderer = class _CatalogRenderer {
3049
3123
  };
3050
3124
 
3051
3125
  // src/serving/loadout-compiler.ts
3126
+ init_esm_shims();
3052
3127
  var DEFAULT_CONFIG2 = {
3053
3128
  defaultMaxSkills: 15,
3054
3129
  defaultStatus: ["active"],
@@ -3063,7 +3138,24 @@ var LoadoutCompiler = class {
3063
3138
  };
3064
3139
  }
3065
3140
  /**
3066
- * Main entry point - compile skills from criteria
3141
+ * Main entry point - compile skills from criteria.
3142
+ *
3143
+ * Filter pipeline order:
3144
+ * 1. status (initial query)
3145
+ * 2. exclude (drop matching IDs)
3146
+ * 3. tags / tagsAll
3147
+ * 4. author
3148
+ * 5. semantic (currently no-op)
3149
+ * 6. relationships (rootSkills traversal)
3150
+ * 7. **include** — presence guarantee: ensures every ID in the
3151
+ * include list is in the result regardless of the filters above,
3152
+ * fetching missing ones from storage as needed. `exclude` still
3153
+ * wins (excluded IDs are removed from the include list before
3154
+ * this step).
3155
+ * 8. limits (maxSkills, maxTokens)
3156
+ *
3157
+ * For "restrict to exactly these skills" semantics, combine
3158
+ * `include: [...]` with `maxSkills: include.length`.
3067
3159
  */
3068
3160
  async compile(criteria) {
3069
3161
  const status = criteria.status ?? this.config.defaultStatus;
@@ -3073,6 +3165,7 @@ var LoadoutCompiler = class {
3073
3165
  candidates = this.applyQualityFilters(candidates, criteria);
3074
3166
  candidates = await this.applySemanticFilters(candidates, criteria);
3075
3167
  candidates = await this.applyRelationshipFilters(candidates, criteria);
3168
+ candidates = await this.ensureIncludedPresent(candidates, criteria);
3076
3169
  candidates = this.applyLimits(candidates, criteria);
3077
3170
  return candidates;
3078
3171
  }
@@ -3118,7 +3211,9 @@ var LoadoutCompiler = class {
3118
3211
  // Filter Methods
3119
3212
  // ===========================================================================
3120
3213
  /**
3121
- * Apply explicit include/exclude filters
3214
+ * Apply explicit exclude filter. Include is handled separately at the
3215
+ * compile level (see `ensureIncludedPresent`) so it can guarantee
3216
+ * presence regardless of the other filters in this method or below.
3122
3217
  */
3123
3218
  applyExplicitFilters(skills, criteria) {
3124
3219
  let result = skills;
@@ -3126,15 +3221,6 @@ var LoadoutCompiler = class {
3126
3221
  const excludeSet = new Set(criteria.exclude);
3127
3222
  result = result.filter((s) => !excludeSet.has(s.id));
3128
3223
  }
3129
- if (criteria.include && criteria.include.length > 0) {
3130
- const includeSet = new Set(criteria.include);
3131
- const currentIds = new Set(result.map((s) => s.id));
3132
- const includedSkills = result.filter((s) => includeSet.has(s.id));
3133
- const otherSkills = result.filter((s) => !includeSet.has(s.id));
3134
- if (includedSkills.length > 0) {
3135
- result = [...includedSkills, ...otherSkills];
3136
- }
3137
- }
3138
3224
  return result;
3139
3225
  }
3140
3226
  /**
@@ -3158,11 +3244,6 @@ var LoadoutCompiler = class {
3158
3244
  */
3159
3245
  applyQualityFilters(skills, criteria) {
3160
3246
  let result = skills;
3161
- if (criteria.minSuccessRate !== void 0) {
3162
- result = result.filter(
3163
- (s) => s.metrics.successRate >= criteria.minSuccessRate
3164
- );
3165
- }
3166
3247
  if (criteria.author) {
3167
3248
  result = result.filter((s) => s.author === criteria.author);
3168
3249
  }
@@ -3220,27 +3301,48 @@ var LoadoutCompiler = class {
3220
3301
  }
3221
3302
  return skills.filter((s) => result.has(s.id));
3222
3303
  }
3304
+ /**
3305
+ * Ensure every ID in `criteria.include` is present in the result,
3306
+ * regardless of which earlier filter would have dropped it. Missing
3307
+ * skills are fetched directly from storage.
3308
+ *
3309
+ * `criteria.exclude` still wins: an ID listed in both `include` and
3310
+ * `exclude` is treated as excluded (consistent with openteams' "deny
3311
+ * wins" inheritance rule on permissions).
3312
+ *
3313
+ * Included skills are placed at the front of the result, preserving
3314
+ * the order of `criteria.include`. Other skills retain their relative
3315
+ * order behind them.
3316
+ */
3317
+ async ensureIncludedPresent(current, criteria) {
3318
+ if (!criteria.include?.length) return current;
3319
+ const excludeSet = new Set(criteria.exclude ?? []);
3320
+ const effectiveInclude = criteria.include.filter(
3321
+ (id) => !excludeSet.has(id)
3322
+ );
3323
+ if (effectiveInclude.length === 0) return current;
3324
+ const currentById = new Map(current.map((s) => [s.id, s]));
3325
+ const ordered = [];
3326
+ for (const id of effectiveInclude) {
3327
+ const existing = currentById.get(id);
3328
+ if (existing) {
3329
+ ordered.push(existing);
3330
+ currentById.delete(id);
3331
+ continue;
3332
+ }
3333
+ const fetched = await this.storage.getSkill(id);
3334
+ if (fetched) {
3335
+ ordered.push(fetched);
3336
+ }
3337
+ }
3338
+ return [...ordered, ...currentById.values()];
3339
+ }
3223
3340
  /**
3224
3341
  * Apply limits and sorting
3225
3342
  */
3226
3343
  applyLimits(skills, criteria) {
3227
3344
  let result = skills;
3228
- if (criteria.priorityOrder) {
3229
- result = [...result].sort((a, b) => {
3230
- switch (criteria.priorityOrder) {
3231
- case "usage":
3232
- return b.metrics.usageCount - a.metrics.usageCount;
3233
- case "successRate":
3234
- return b.metrics.successRate - a.metrics.successRate;
3235
- case "recent":
3236
- const aDate = a.metrics.lastUsed?.getTime() ?? 0;
3237
- const bDate = b.metrics.lastUsed?.getTime() ?? 0;
3238
- return bDate - aDate;
3239
- case "relevance":
3240
- default:
3241
- return 0;
3242
- }
3243
- });
3345
+ if (criteria.priorityOrder === "relevance") {
3244
3346
  }
3245
3347
  const maxSkills = criteria.maxSkills ?? this.config.defaultMaxSkills;
3246
3348
  if (result.length > maxSkills) {
@@ -3277,6 +3379,7 @@ var LoadoutCompiler = class {
3277
3379
  };
3278
3380
 
3279
3381
  // src/serving/project-detector.ts
3382
+ init_esm_shims();
3280
3383
  import { existsSync as existsSync2, readFileSync } from "fs";
3281
3384
  import { join as join3 } from "path";
3282
3385
  var ProjectDetector = class _ProjectDetector {
@@ -3512,6 +3615,7 @@ var ProjectDetector = class _ProjectDetector {
3512
3615
  };
3513
3616
 
3514
3617
  // src/serving/view-renderer.ts
3618
+ init_esm_shims();
3515
3619
  var DEFAULT_CONFIG3 = {
3516
3620
  includeTokenEstimates: false,
3517
3621
  maxSummaryLength: 150
@@ -3707,6 +3811,7 @@ var ViewRenderer = class {
3707
3811
  };
3708
3812
 
3709
3813
  // src/serving/profiles/index.ts
3814
+ init_esm_shims();
3710
3815
  var codeReviewProfile = {
3711
3816
  tags: ["review", "quality", "security", "best-practices"],
3712
3817
  taskDescription: "review code for quality, security, and best practices",
@@ -3731,7 +3836,6 @@ var securityProfile = {
3731
3836
  tagsAll: ["security"],
3732
3837
  taskDescription: "security review, vulnerability detection, secure coding",
3733
3838
  maxSkills: 8,
3734
- minSuccessRate: 0.7,
3735
3839
  priorityOrder: "relevance"
3736
3840
  };
3737
3841
  var testingProfile = {
@@ -3985,16 +4089,6 @@ var SkillGraphServer = class {
3985
4089
  this.emit({ type: "skill:collapsed", skillId });
3986
4090
  return true;
3987
4091
  }
3988
- /**
3989
- * Record skill usage (for LRU tracking and auto-expansion)
3990
- */
3991
- recordUsage(skillId) {
3992
- if (!this.state.available.has(skillId)) return;
3993
- this.touchLru(skillId);
3994
- if (this.config.autoExpandOnUse && !this.state.expanded.has(skillId)) {
3995
- this.expandSkill(skillId);
3996
- }
3997
- }
3998
4092
  // ===========================================================================
3999
4093
  // AGENT API - Methods for agent-side modifications
4000
4094
  // ===========================================================================
@@ -4104,19 +4198,19 @@ var SkillGraphServer = class {
4104
4198
  * Returns rendered category view (subcategories or skill summaries at leaf).
4105
4199
  * Pass no path for the top-level overview.
4106
4200
  */
4107
- async agentBrowseCatalog(path13) {
4201
+ async agentBrowseCatalog(path14) {
4108
4202
  if (!this.catalogRenderer) {
4109
4203
  return "<error>Catalog browsing is not enabled</error>";
4110
4204
  }
4111
- if (!path13 || path13.length === 0) {
4205
+ if (!path14 || path14.length === 0) {
4112
4206
  const result2 = await this.catalogRenderer.renderOverview();
4113
4207
  if (result2) {
4114
4208
  this.emit({ type: "catalog:browsed", path: [] });
4115
4209
  }
4116
4210
  return result2;
4117
4211
  }
4118
- const result = await this.catalogRenderer.renderCategory(path13);
4119
- this.emit({ type: "catalog:browsed", path: path13 });
4212
+ const result = await this.catalogRenderer.renderCategory(path14);
4213
+ this.emit({ type: "catalog:browsed", path: path14 });
4120
4214
  return result;
4121
4215
  }
4122
4216
  /**
@@ -4283,6 +4377,7 @@ var SkillGraphServer = class {
4283
4377
  };
4284
4378
 
4285
4379
  // src/serving/interfaces.ts
4380
+ init_esm_shims();
4286
4381
  function createStorageView(storage) {
4287
4382
  return {
4288
4383
  getSkill: storage.getSkill.bind(storage),
@@ -4322,17 +4417,21 @@ function createServingEventBridge() {
4322
4417
  };
4323
4418
  }
4324
4419
 
4420
+ // src/federation/index.ts
4421
+ init_esm_shims();
4422
+
4325
4423
  // src/federation/remote-store.ts
4424
+ init_esm_shims();
4326
4425
  import * as fs3 from "fs";
4327
- import * as path3 from "path";
4426
+ import * as path4 from "path";
4328
4427
  var REMOTES_FILE = "remotes.json";
4329
4428
  var RemoteStore = class {
4330
4429
  constructor(options) {
4331
4430
  this.remotes = /* @__PURE__ */ new Map();
4332
4431
  this.initialized = false;
4333
4432
  this.basePath = options.basePath;
4334
- this.configDir = path3.join(this.basePath, ".skillbank");
4335
- this.configPath = path3.join(this.configDir, REMOTES_FILE);
4433
+ this.configDir = path4.join(this.basePath, ".skillbank");
4434
+ this.configPath = path4.join(this.configDir, REMOTES_FILE);
4336
4435
  }
4337
4436
  /**
4338
4437
  * Initialize the store, loading existing configuration
@@ -4404,7 +4503,7 @@ var RemoteStore = class {
4404
4503
  ...config,
4405
4504
  branch: config.branch || "main",
4406
4505
  skillsPath: config.skillsPath || "skills/",
4407
- localCache: config.localCache || path3.join(this.basePath, ".remotes", name)
4506
+ localCache: config.localCache || path4.join(this.basePath, ".remotes", name)
4408
4507
  };
4409
4508
  this.remotes.set(name, normalizedConfig);
4410
4509
  await this.save();
@@ -4478,7 +4577,7 @@ var RemoteStore = class {
4478
4577
  if (!config) {
4479
4578
  throw new Error(`Remote not found: ${name}`);
4480
4579
  }
4481
- return config.localCache || path3.join(this.basePath, ".remotes", name);
4580
+ return config.localCache || path4.join(this.basePath, ".remotes", name);
4482
4581
  }
4483
4582
  /**
4484
4583
  * Validate a remote name
@@ -4518,20 +4617,22 @@ var RemoteStore = class {
4518
4617
  };
4519
4618
 
4520
4619
  // src/federation/remote-manager.ts
4620
+ init_esm_shims();
4521
4621
  import * as fs5 from "fs";
4522
- import * as path5 from "path";
4622
+ import * as path6 from "path";
4523
4623
  import { exec } from "child_process";
4524
4624
  import { promisify } from "util";
4525
4625
 
4526
4626
  // src/federation/skilltree-config.ts
4627
+ init_esm_shims();
4527
4628
  import * as fs4 from "fs";
4528
- import * as path4 from "path";
4629
+ import * as path5 from "path";
4529
4630
  function resolveSkilltreeDir(repoRoot) {
4530
4631
  const envDir = process.env.SKILL_TREE_PROJECT_DIR;
4531
- if (envDir) return path4.join(repoRoot, envDir);
4532
- const swarmDir = path4.join(repoRoot, ".swarm", "skilltree");
4632
+ if (envDir) return path5.join(repoRoot, envDir);
4633
+ const swarmDir = path5.join(repoRoot, ".swarm", "skilltree");
4533
4634
  if (fs4.existsSync(swarmDir)) return swarmDir;
4534
- return path4.join(repoRoot, ".skilltree");
4635
+ return path5.join(repoRoot, ".skilltree");
4535
4636
  }
4536
4637
  var DEFAULT_CONFIG5 = {
4537
4638
  version: 1,
@@ -4562,7 +4663,7 @@ function getSkilltreeDir(repoRoot) {
4562
4663
  function getSkillsDir(repoRoot, config) {
4563
4664
  const skilltreeDir = getSkilltreeDir(repoRoot);
4564
4665
  const paths = config?.paths || DEFAULT_CONFIG5.paths;
4565
- return path4.join(skilltreeDir, paths[0]);
4666
+ return path5.join(skilltreeDir, paths[0]);
4566
4667
  }
4567
4668
  function parseSkilltreeConfig(content) {
4568
4669
  const parsed = JSON.parse(content);
@@ -4582,7 +4683,7 @@ function validateConfig(config) {
4582
4683
  };
4583
4684
  }
4584
4685
  async function loadSkilltreeConfig(repoRoot) {
4585
- const configPath = path4.join(getSkilltreeDir(repoRoot), "config.json");
4686
+ const configPath = path5.join(getSkilltreeDir(repoRoot), "config.json");
4586
4687
  try {
4587
4688
  const content = await fs4.promises.readFile(configPath, "utf-8");
4588
4689
  return parseSkilltreeConfig(content);
@@ -4599,9 +4700,9 @@ async function initSkilltreeDir(repoRoot, config) {
4599
4700
  await fs4.promises.mkdir(skilltreeDir, { recursive: true });
4600
4701
  const skillsDir = getSkillsDir(repoRoot, fullConfig);
4601
4702
  await fs4.promises.mkdir(skillsDir, { recursive: true });
4602
- const cacheDir = path4.join(skilltreeDir, ".cache");
4703
+ const cacheDir = path5.join(skilltreeDir, ".cache");
4603
4704
  await fs4.promises.mkdir(cacheDir, { recursive: true });
4604
- const gitignorePath = path4.join(skilltreeDir, ".gitignore");
4705
+ const gitignorePath = path5.join(skilltreeDir, ".gitignore");
4605
4706
  try {
4606
4707
  const existing = await fs4.promises.readFile(gitignorePath, "utf-8");
4607
4708
  if (!existing.includes(".cache")) {
@@ -4615,7 +4716,7 @@ async function initSkilltreeDir(repoRoot, config) {
4615
4716
  await fs4.promises.writeFile(gitignorePath, ".cache/\n", "utf-8");
4616
4717
  }
4617
4718
  if (config && Object.keys(config).length > 0) {
4618
- const configPath = path4.join(skilltreeDir, "config.json");
4719
+ const configPath = path5.join(skilltreeDir, "config.json");
4619
4720
  await fs4.promises.writeFile(
4620
4721
  configPath,
4621
4722
  JSON.stringify(fullConfig, null, 2),
@@ -4638,7 +4739,7 @@ function isSkillFile(filename, patterns = DEFAULT_CONFIG5.skillFilePatterns) {
4638
4739
  return false;
4639
4740
  }
4640
4741
  function shouldExclude(relativePath, excludePatterns) {
4641
- const parts = relativePath.split(path4.sep);
4742
+ const parts = relativePath.split(path5.sep);
4642
4743
  for (const part of parts) {
4643
4744
  if (excludePatterns.includes(part)) {
4644
4745
  return true;
@@ -4658,14 +4759,14 @@ async function discoverSkills(repoRoot) {
4658
4759
  } else {
4659
4760
  const paths = config.paths || DEFAULT_CONFIG5.paths;
4660
4761
  for (const searchPath of paths) {
4661
- const fullPath = path4.join(skilltreeDir, searchPath);
4762
+ const fullPath = path5.join(skilltreeDir, searchPath);
4662
4763
  await scanForSkills(skilltreeDir, fullPath, config, discovered);
4663
4764
  }
4664
4765
  }
4665
4766
  return discovered;
4666
4767
  }
4667
4768
  async function scanForSkills(skilltreeDir, dir, config, discovered) {
4668
- const relativePath = path4.relative(skilltreeDir, dir);
4769
+ const relativePath = path5.relative(skilltreeDir, dir);
4669
4770
  if (relativePath && shouldExclude(relativePath, config.exclude || [])) {
4670
4771
  return;
4671
4772
  }
@@ -4673,7 +4774,7 @@ async function scanForSkills(skilltreeDir, dir, config, discovered) {
4673
4774
  const entries = await fs4.promises.readdir(dir, { withFileTypes: true });
4674
4775
  for (const entry of entries) {
4675
4776
  if (entry.isFile() && isSkillFile(entry.name, config.skillFilePatterns)) {
4676
- const filePath = path4.join(dir, entry.name);
4777
+ const filePath = path5.join(dir, entry.name);
4677
4778
  const id = deriveSkillId(skilltreeDir, filePath);
4678
4779
  if (!discovered.some((d) => d.id === id)) {
4679
4780
  discovered.push({
@@ -4688,7 +4789,7 @@ async function scanForSkills(skilltreeDir, dir, config, discovered) {
4688
4789
  if (entry.isDirectory() && !entry.name.startsWith(".")) {
4689
4790
  await scanForSkills(
4690
4791
  skilltreeDir,
4691
- path4.join(dir, entry.name),
4792
+ path5.join(dir, entry.name),
4692
4793
  config,
4693
4794
  discovered
4694
4795
  );
@@ -4701,11 +4802,11 @@ async function scanForSkills(skilltreeDir, dir, config, discovered) {
4701
4802
  }
4702
4803
  }
4703
4804
  function deriveSkillId(skilltreeDir, filePath) {
4704
- const dir = path4.dirname(filePath);
4705
- const filename = path4.basename(filePath);
4706
- const dirName = path4.basename(dir);
4707
- const parentDir = path4.dirname(dir);
4708
- const parentDirName = path4.basename(parentDir);
4805
+ const dir = path5.dirname(filePath);
4806
+ const filename = path5.basename(filePath);
4807
+ const dirName = path5.basename(dir);
4808
+ const parentDir = path5.dirname(dir);
4809
+ const parentDirName = path5.basename(parentDir);
4709
4810
  if (dir !== skilltreeDir) {
4710
4811
  const skillMatch = filename.match(/^(.+)\.skill\.md$/i);
4711
4812
  if (skillMatch) {
@@ -4722,7 +4823,7 @@ function deriveSkillId(skilltreeDir, filePath) {
4722
4823
  return dirName;
4723
4824
  }
4724
4825
  }
4725
- const relativePath = path4.relative(skilltreeDir, filePath);
4826
+ const relativePath = path5.relative(skilltreeDir, filePath);
4726
4827
  const withoutExt = relativePath.replace(/\.(skill\.)?md$/i, "");
4727
4828
  return withoutExt.replace(/[\/\\]/g, "-");
4728
4829
  }
@@ -4739,7 +4840,7 @@ var RemoteManager = class {
4739
4840
  /** Cache of discovered skill locations per remote */
4740
4841
  this.discoveryCache = /* @__PURE__ */ new Map();
4741
4842
  this.basePath = options.basePath;
4742
- this.remotesDir = path5.join(this.basePath, ".remotes");
4843
+ this.remotesDir = path6.join(this.basePath, ".remotes");
4743
4844
  this.remoteStore = options.remoteStore;
4744
4845
  this.gitTimeout = options.gitTimeout || 6e4;
4745
4846
  }
@@ -4910,10 +5011,10 @@ var RemoteManager = class {
4910
5011
  throw new Error(`Remote ${remoteName} is read-only`);
4911
5012
  }
4912
5013
  const skillsPath = await this.getWritePath(remoteName);
4913
- const skillDir = path5.join(skillsPath, skill.id);
5014
+ const skillDir = path6.join(skillsPath, skill.id);
4914
5015
  await fs5.promises.mkdir(skillDir, { recursive: true });
4915
5016
  const content = this.serializeSkill(skill);
4916
- const skillPath = path5.join(skillDir, "SKILL.md");
5017
+ const skillPath = path6.join(skillDir, "SKILL.md");
4917
5018
  await fs5.promises.writeFile(skillPath, content, "utf-8");
4918
5019
  this.discoveryCache.delete(remoteName);
4919
5020
  return skillPath;
@@ -5032,7 +5133,7 @@ ${err.stderr || err.message}`
5032
5133
  * Get the cache path for a remote
5033
5134
  */
5034
5135
  getCachePath(name) {
5035
- return path5.join(this.remotesDir, name);
5136
+ return path6.join(this.remotesDir, name);
5036
5137
  }
5037
5138
  /**
5038
5139
  * Load and cache the .skilltree config for a remote
@@ -5112,12 +5213,7 @@ ${err.stderr || err.message}`
5112
5213
  tags: this.parseTags(metadata.tags),
5113
5214
  createdAt: metadata.created ? new Date(metadata.created) : /* @__PURE__ */ new Date(),
5114
5215
  updatedAt: metadata.updated ? new Date(metadata.updated) : /* @__PURE__ */ new Date(),
5115
- status: metadata.status || "active",
5116
- metrics: {
5117
- usageCount: parseInt(metadata.usageCount) || 0,
5118
- successRate: parseFloat(metadata.successRate) || 0,
5119
- feedbackScores: []
5120
- }
5216
+ status: metadata.status || "active"
5121
5217
  };
5122
5218
  }
5123
5219
  /**
@@ -5186,9 +5282,6 @@ ${body.join("\n")}
5186
5282
  if (filter.author && skill.author !== filter.author) {
5187
5283
  return false;
5188
5284
  }
5189
- if (filter.minSuccessRate !== void 0 && skill.metrics.successRate < filter.minSuccessRate) {
5190
- return false;
5191
- }
5192
5285
  if (filter.createdAfter && skill.createdAt < filter.createdAfter) {
5193
5286
  return false;
5194
5287
  }
@@ -5200,7 +5293,11 @@ ${body.join("\n")}
5200
5293
  }
5201
5294
  };
5202
5295
 
5296
+ // src/federation/federation-manager.ts
5297
+ init_esm_shims();
5298
+
5203
5299
  // src/versioning/semver.ts
5300
+ init_esm_shims();
5204
5301
  function parseVersion(version) {
5205
5302
  const match = version.match(
5206
5303
  /^(\d+)\.(\d+)\.(\d+)(?:-([a-zA-Z0-9.-]+))?(?:\+([a-zA-Z0-9.-]+))?$/
@@ -5814,14 +5911,16 @@ function createFederationManager(options) {
5814
5911
  init_base();
5815
5912
 
5816
5913
  // src/storage/cached.ts
5914
+ init_esm_shims();
5817
5915
  init_base();
5818
5916
  import * as fs8 from "fs";
5819
- import * as path8 from "path";
5917
+ import * as path9 from "path";
5820
5918
 
5821
5919
  // src/storage/filesystem.ts
5920
+ init_esm_shims();
5822
5921
  init_base();
5823
5922
  import * as fs6 from "fs/promises";
5824
- import * as path6 from "path";
5923
+ import * as path7 from "path";
5825
5924
  var FilesystemStorageAdapter = class extends BaseStorageAdapter {
5826
5925
  constructor(config) {
5827
5926
  super();
@@ -5832,7 +5931,7 @@ var FilesystemStorageAdapter = class extends BaseStorageAdapter {
5832
5931
  };
5833
5932
  this.skilltreeDir = getSkilltreeDir(this.config.basePath);
5834
5933
  this.skillsDir = getSkillsDir(this.config.basePath);
5835
- this.versionsDir = path6.join(this.skilltreeDir, ".versions");
5934
+ this.versionsDir = path7.join(this.skilltreeDir, ".versions");
5836
5935
  }
5837
5936
  async initialize() {
5838
5937
  await initSkilltreeDir(this.config.basePath);
@@ -5849,14 +5948,14 @@ var FilesystemStorageAdapter = class extends BaseStorageAdapter {
5849
5948
  }
5850
5949
  async saveSkill(skill) {
5851
5950
  this.ensureInitialized();
5852
- const skillDir = path6.join(this.skillsDir, skill.id);
5951
+ const skillDir = path7.join(this.skillsDir, skill.id);
5853
5952
  await fs6.mkdir(skillDir, { recursive: true });
5854
5953
  const skillContent = this.serializeSkill(skill);
5855
5954
  const skillFileName = this.config.openSkillsCompatible ? "SKILL.md" : "skill.md";
5856
- await fs6.writeFile(path6.join(skillDir, skillFileName), skillContent, "utf-8");
5955
+ await fs6.writeFile(path7.join(skillDir, skillFileName), skillContent, "utf-8");
5857
5956
  const metadata = this.createMetadata(skill);
5858
5957
  await fs6.writeFile(
5859
- path6.join(skillDir, ".skilltree.json"),
5958
+ path7.join(skillDir, ".skilltree.json"),
5860
5959
  JSON.stringify(metadata, null, 2),
5861
5960
  "utf-8"
5862
5961
  );
@@ -5914,7 +6013,7 @@ var FilesystemStorageAdapter = class extends BaseStorageAdapter {
5914
6013
  try {
5915
6014
  await fs6.rm(location.directory, { recursive: true });
5916
6015
  if (this.config.trackVersions) {
5917
- const versionDir = path6.join(this.versionsDir, id);
6016
+ const versionDir = path7.join(this.versionsDir, id);
5918
6017
  await fs6.rm(versionDir, { recursive: true }).catch(() => {
5919
6018
  });
5920
6019
  }
@@ -5942,13 +6041,13 @@ var FilesystemStorageAdapter = class extends BaseStorageAdapter {
5942
6041
  }
5943
6042
  ];
5944
6043
  }
5945
- const versionDir = path6.join(this.versionsDir, skillId);
6044
+ const versionDir = path7.join(this.versionsDir, skillId);
5946
6045
  const versions = [];
5947
6046
  try {
5948
6047
  const entries = await fs6.readdir(versionDir);
5949
6048
  for (const entry of entries) {
5950
6049
  if (!entry.endsWith(".json")) continue;
5951
- const versionPath = path6.join(versionDir, entry);
6050
+ const versionPath = path7.join(versionDir, entry);
5952
6051
  const content = await fs6.readFile(versionPath, "utf-8");
5953
6052
  const versionData = JSON.parse(content);
5954
6053
  versionData.createdAt = new Date(versionData.createdAt);
@@ -6071,11 +6170,6 @@ ${skill.instructions}
6071
6170
  status,
6072
6171
  parentVersion: parentVersion || void 0,
6073
6172
  derivedFrom: derivedFrom.length > 0 ? derivedFrom : void 0,
6074
- metrics: {
6075
- usageCount: 0,
6076
- successRate: 0,
6077
- feedbackScores: []
6078
- },
6079
6173
  source: metadata?.source,
6080
6174
  upstream,
6081
6175
  namespace: metadata?.namespace
@@ -6125,9 +6219,9 @@ ${skill.instructions}
6125
6219
  * Save a version snapshot
6126
6220
  */
6127
6221
  async saveVersionSnapshot(skill) {
6128
- const versionDir = path6.join(this.versionsDir, skill.id);
6222
+ const versionDir = path7.join(this.versionsDir, skill.id);
6129
6223
  await fs6.mkdir(versionDir, { recursive: true });
6130
- const versionFile = path6.join(versionDir, `${skill.version}.json`);
6224
+ const versionFile = path7.join(versionDir, `${skill.version}.json`);
6131
6225
  const versionData = {
6132
6226
  skillId: skill.id,
6133
6227
  version: skill.version,
@@ -6143,7 +6237,7 @@ ${skill.instructions}
6143
6237
  * Get a specific version of a skill
6144
6238
  */
6145
6239
  async getVersionedSkill(id, version) {
6146
- const versionFile = path6.join(this.versionsDir, id, `${version}.json`);
6240
+ const versionFile = path7.join(this.versionsDir, id, `${version}.json`);
6147
6241
  try {
6148
6242
  const content = await fs6.readFile(versionFile, "utf-8");
6149
6243
  const versionData = JSON.parse(content);
@@ -6162,7 +6256,7 @@ ${skill.instructions}
6162
6256
  * Delete a specific version
6163
6257
  */
6164
6258
  async deleteVersion(id, version) {
6165
- const versionFile = path6.join(this.versionsDir, id, `${version}.json`);
6259
+ const versionFile = path7.join(this.versionsDir, id, `${version}.json`);
6166
6260
  try {
6167
6261
  await fs6.unlink(versionFile);
6168
6262
  return true;
@@ -6196,7 +6290,7 @@ ${skill.instructions}
6196
6290
  * Load metadata for a skill directory
6197
6291
  */
6198
6292
  async loadMetadata(skillDir) {
6199
- const metadataPath = path6.join(skillDir, ".skilltree.json");
6293
+ const metadataPath = path7.join(skillDir, ".skilltree.json");
6200
6294
  try {
6201
6295
  const content = await fs6.readFile(metadataPath, "utf-8");
6202
6296
  return JSON.parse(content);
@@ -6208,7 +6302,7 @@ ${skill.instructions}
6208
6302
  * Save metadata for a skill directory
6209
6303
  */
6210
6304
  async saveMetadata(skillDir, metadata) {
6211
- const metadataPath = path6.join(skillDir, ".skilltree.json");
6305
+ const metadataPath = path7.join(skillDir, ".skilltree.json");
6212
6306
  await fs6.writeFile(metadataPath, JSON.stringify(metadata, null, 2), "utf-8");
6213
6307
  }
6214
6308
  // ==========================================================================
@@ -6274,9 +6368,9 @@ var CachedStorageAdapter = class extends BaseStorageAdapter {
6274
6368
  super();
6275
6369
  this.cache = null;
6276
6370
  this.basePath = config.basePath;
6277
- this.cacheDir = path8.join(config.basePath, ".skilltree", ".cache");
6278
- this.dbPath = path8.join(this.cacheDir, "index.db");
6279
- this.manifestPath = path8.join(this.cacheDir, "manifest.json");
6371
+ this.cacheDir = path9.join(config.basePath, ".skilltree", ".cache");
6372
+ this.dbPath = path9.join(this.cacheDir, "index.db");
6373
+ this.manifestPath = path9.join(this.cacheDir, "manifest.json");
6280
6374
  this.source = new FilesystemStorageAdapter({
6281
6375
  basePath: config.basePath,
6282
6376
  openSkillsCompatible: config.openSkillsCompatible ?? true,
@@ -6478,7 +6572,11 @@ var CachedStorageAdapter = class extends BaseStorageAdapter {
6478
6572
  }
6479
6573
  };
6480
6574
 
6575
+ // src/versioning/index.ts
6576
+ init_esm_shims();
6577
+
6481
6578
  // src/versioning/lineage.ts
6579
+ init_esm_shims();
6482
6580
  var LineageTracker = class {
6483
6581
  constructor(storage) {
6484
6582
  this.storage = storage;
@@ -6522,11 +6620,6 @@ var LineageTracker = class {
6522
6620
  createdAt: /* @__PURE__ */ new Date(),
6523
6621
  updatedAt: /* @__PURE__ */ new Date(),
6524
6622
  status: "draft",
6525
- metrics: {
6526
- usageCount: 0,
6527
- successRate: 0,
6528
- feedbackScores: []
6529
- },
6530
6623
  source: {
6531
6624
  type: "composed",
6532
6625
  importedAt: /* @__PURE__ */ new Date()
@@ -6727,11 +6820,12 @@ ${source}`;
6727
6820
  };
6728
6821
 
6729
6822
  // src/versioning/merge.ts
6823
+ init_esm_shims();
6730
6824
  var DEFAULT_MERGE_CONFIG = {
6731
6825
  textStrategy: "combine",
6732
6826
  tagStrategy: "union",
6733
6827
  includeFields: ["instructions", "tags"],
6734
- excludeFields: ["id", "version", "createdAt", "updatedAt", "metrics", "source"],
6828
+ excludeFields: ["id", "version", "createdAt", "updatedAt", "source"],
6735
6829
  bumpType: "minor"
6736
6830
  };
6737
6831
  var SkillMerger = class {
@@ -7140,6 +7234,7 @@ function createSkillMerger(storage, config) {
7140
7234
  }
7141
7235
 
7142
7236
  // src/hooks/registry.ts
7237
+ init_esm_shims();
7143
7238
  import { randomUUID } from "crypto";
7144
7239
  var PRIORITY_ORDER = {
7145
7240
  high: 0,
@@ -7324,8 +7419,9 @@ var HookRegistry = class {
7324
7419
  var hookRegistry = new HookRegistry();
7325
7420
 
7326
7421
  // src/materialization/materializer.ts
7422
+ init_esm_shims();
7327
7423
  import * as fs10 from "fs";
7328
- import * as path10 from "path";
7424
+ import * as path11 from "path";
7329
7425
  var SKILLTREE_MARKER_START = "<!-- SKILLTREE_START -->";
7330
7426
  var SKILLTREE_MARKER_END = "<!-- SKILLTREE_END -->";
7331
7427
  var Materializer = class {
@@ -7343,7 +7439,7 @@ var Materializer = class {
7343
7439
  return this.config.mode ?? "symlink";
7344
7440
  }
7345
7441
  get skillsSourceDir() {
7346
- return path10.join(this.basePath, ".skilltree", "skills");
7442
+ return path11.join(this.basePath, ".skilltree", "skills");
7347
7443
  }
7348
7444
  /**
7349
7445
  * Initial materialization: create all symlinks/copies + generate AGENTS.md
@@ -7386,11 +7482,11 @@ var Materializer = class {
7386
7482
  * Materialize a skill to all configured paths (symlink or copy)
7387
7483
  */
7388
7484
  async ensureMaterialized(skillId) {
7389
- const sourcePath = path10.join(this.skillsSourceDir, skillId);
7485
+ const sourcePath = path11.join(this.skillsSourceDir, skillId);
7390
7486
  if (!fs10.existsSync(sourcePath)) return;
7391
7487
  for (const targetBase of this.config.symlinkPaths ?? []) {
7392
7488
  const targetDir = this.resolvePath(targetBase);
7393
- const targetPath = path10.join(targetDir, skillId);
7489
+ const targetPath = path11.join(targetDir, skillId);
7394
7490
  if (this.mode === "copy") {
7395
7491
  this.copyDir(sourcePath, targetPath);
7396
7492
  } else {
@@ -7402,19 +7498,19 @@ var Materializer = class {
7402
7498
  * Remove a materialized skill from all configured paths
7403
7499
  */
7404
7500
  async removeMaterialized(skillId) {
7405
- const sourcePath = path10.resolve(path10.join(this.skillsSourceDir, skillId));
7501
+ const sourcePath = path11.resolve(path11.join(this.skillsSourceDir, skillId));
7406
7502
  for (const targetBase of this.config.symlinkPaths ?? []) {
7407
- const targetPath = path10.join(this.resolvePath(targetBase), skillId);
7503
+ const targetPath = path11.join(this.resolvePath(targetBase), skillId);
7408
7504
  if (!fs10.existsSync(targetPath)) continue;
7409
7505
  if (this.mode === "copy") {
7410
- const markerPath = path10.join(targetPath, ".skilltree-managed");
7506
+ const markerPath = path11.join(targetPath, ".skilltree-managed");
7411
7507
  if (fs10.existsSync(markerPath)) {
7412
7508
  fs10.rmSync(targetPath, { recursive: true, force: true });
7413
7509
  }
7414
7510
  } else {
7415
7511
  try {
7416
7512
  const linkTarget = fs10.readlinkSync(targetPath);
7417
- if (path10.resolve(linkTarget) === sourcePath) {
7513
+ if (path11.resolve(linkTarget) === sourcePath) {
7418
7514
  fs10.unlinkSync(targetPath);
7419
7515
  }
7420
7516
  } catch {
@@ -7429,7 +7525,7 @@ var Materializer = class {
7429
7525
  if (fs10.existsSync(targetPath)) {
7430
7526
  try {
7431
7527
  const existing = fs10.readlinkSync(targetPath);
7432
- if (path10.resolve(existing) === path10.resolve(sourcePath)) return;
7528
+ if (path11.resolve(existing) === path11.resolve(sourcePath)) return;
7433
7529
  fs10.unlinkSync(targetPath);
7434
7530
  } catch {
7435
7531
  return;
@@ -7451,7 +7547,7 @@ var Materializer = class {
7451
7547
  */
7452
7548
  copyDir(sourcePath, targetPath) {
7453
7549
  if (fs10.existsSync(targetPath)) {
7454
- const markerPath = path10.join(targetPath, ".skilltree-managed");
7550
+ const markerPath = path11.join(targetPath, ".skilltree-managed");
7455
7551
  if (fs10.existsSync(markerPath)) {
7456
7552
  fs10.rmSync(targetPath, { recursive: true, force: true });
7457
7553
  } else {
@@ -7460,7 +7556,7 @@ var Materializer = class {
7460
7556
  }
7461
7557
  fs10.cpSync(sourcePath, targetPath, { recursive: true });
7462
7558
  fs10.writeFileSync(
7463
- path10.join(targetPath, ".skilltree-managed"),
7559
+ path11.join(targetPath, ".skilltree-managed"),
7464
7560
  JSON.stringify({ source: sourcePath, copiedAt: (/* @__PURE__ */ new Date()).toISOString() })
7465
7561
  );
7466
7562
  }
@@ -7529,7 +7625,7 @@ ${SKILLTREE_MARKER_END}`;
7529
7625
  fs10.writeFileSync(resolvedPath, existing + "\n\n" + markedContent + "\n");
7530
7626
  return;
7531
7627
  }
7532
- const dir = path10.dirname(resolvedPath);
7628
+ const dir = path11.dirname(resolvedPath);
7533
7629
  if (!fs10.existsSync(dir)) {
7534
7630
  fs10.mkdirSync(dir, { recursive: true });
7535
7631
  }
@@ -7549,18 +7645,18 @@ ${SKILLTREE_MARKER_END}`;
7549
7645
  if (!fs10.existsSync(resolved)) continue;
7550
7646
  const entries = fs10.readdirSync(resolved);
7551
7647
  for (const entry of entries) {
7552
- const entryPath = path10.join(resolved, entry);
7648
+ const entryPath = path11.join(resolved, entry);
7553
7649
  if (skillIds.has(entry)) continue;
7554
7650
  if (this.mode === "copy") {
7555
- const markerPath = path10.join(entryPath, ".skilltree-managed");
7651
+ const markerPath = path11.join(entryPath, ".skilltree-managed");
7556
7652
  if (fs10.existsSync(markerPath)) {
7557
7653
  fs10.rmSync(entryPath, { recursive: true, force: true });
7558
7654
  }
7559
7655
  } else {
7560
7656
  try {
7561
7657
  const linkTarget = fs10.readlinkSync(entryPath);
7562
- const resolvedTarget = path10.resolve(linkTarget);
7563
- if (resolvedTarget.startsWith(this.skillsSourceDir + path10.sep) || resolvedTarget === this.skillsSourceDir) {
7658
+ const resolvedTarget = path11.resolve(linkTarget);
7659
+ if (resolvedTarget.startsWith(this.skillsSourceDir + path11.sep) || resolvedTarget === this.skillsSourceDir) {
7564
7660
  fs10.unlinkSync(entryPath);
7565
7661
  }
7566
7662
  } catch {
@@ -7647,10 +7743,10 @@ ${SKILLTREE_MARKER_END}`;
7647
7743
  */
7648
7744
  resolvePath(p) {
7649
7745
  if (p.startsWith("~")) {
7650
- return path10.join(process.env.HOME || process.env.USERPROFILE || "", p.slice(1));
7746
+ return path11.join(process.env.HOME || process.env.USERPROFILE || "", p.slice(1));
7651
7747
  }
7652
- if (path10.isAbsolute(p)) return p;
7653
- return path10.resolve(this.basePath, p);
7748
+ if (path11.isAbsolute(p)) return p;
7749
+ return path11.resolve(this.basePath, p);
7654
7750
  }
7655
7751
  };
7656
7752
 
@@ -8066,41 +8162,16 @@ var SkillBank = class {
8066
8162
  }
8067
8163
  }
8068
8164
  /**
8069
- * Handle events from serving layer
8165
+ * Handle events from serving layer.
8166
+ *
8167
+ * The `loadout:changed` event is currently the only one we react to.
8168
+ * Earlier versions also handled `skill:used` / `skill:feedback` to mutate
8169
+ * `Skill.metrics`, but skill-tree no longer tracks per-skill usage —
8170
+ * cognitive-core owns that signal via `playbook.evolution.*`. See
8171
+ * docs/SKILL_TREE_METRICS_DEPRECATION.md.
8070
8172
  */
8071
8173
  async handleServingEvent(event) {
8072
8174
  switch (event.type) {
8073
- case "skill:used":
8074
- const skill = await this.storage.getSkill(event.skillId);
8075
- if (skill) {
8076
- skill.metrics.usageCount++;
8077
- skill.metrics.lastUsed = /* @__PURE__ */ new Date();
8078
- if (event.success) {
8079
- const total = skill.metrics.usageCount;
8080
- const currentSuccesses = skill.metrics.successRate * (total - 1);
8081
- skill.metrics.successRate = (currentSuccesses + 1) / total;
8082
- } else {
8083
- const total = skill.metrics.usageCount;
8084
- const currentSuccesses = skill.metrics.successRate * (total - 1);
8085
- skill.metrics.successRate = currentSuccesses / total;
8086
- }
8087
- skill.updatedAt = /* @__PURE__ */ new Date();
8088
- await this.storage.saveSkill(skill);
8089
- }
8090
- break;
8091
- case "skill:feedback":
8092
- const feedbackSkill = await this.storage.getSkill(event.skillId);
8093
- if (feedbackSkill) {
8094
- feedbackSkill.metrics.feedbackScores.push(event.score);
8095
- if (feedbackSkill.metrics.feedbackScores.length > 50) {
8096
- feedbackSkill.metrics.feedbackScores = feedbackSkill.metrics.feedbackScores.slice(-50);
8097
- }
8098
- feedbackSkill.updatedAt = /* @__PURE__ */ new Date();
8099
- await this.storage.saveSkill(feedbackSkill);
8100
- }
8101
- break;
8102
- case "skill:requested":
8103
- break;
8104
8175
  case "loadout:changed":
8105
8176
  break;
8106
8177
  }
@@ -8122,26 +8193,17 @@ var SkillBank = class {
8122
8193
  deprecated: 0,
8123
8194
  experimental: 0
8124
8195
  },
8125
- byTag: {},
8126
- avgSuccessRate: 0,
8127
- totalUsage: 0
8196
+ byTag: {}
8128
8197
  };
8129
8198
  if (this.namespaceConfig) {
8130
8199
  stats.byScope = { personal: 0, team: 0, global: 0 };
8131
8200
  stats.byVisibility = { private: 0, "team-only": 0, public: 0 };
8132
8201
  }
8133
- let successRateSum = 0;
8134
- let successRateCount = 0;
8135
8202
  for (const skill of skills) {
8136
8203
  stats.byStatus[skill.status]++;
8137
8204
  for (const tag of skill.tags) {
8138
8205
  stats.byTag[tag] = (stats.byTag[tag] || 0) + 1;
8139
8206
  }
8140
- stats.totalUsage += skill.metrics.usageCount;
8141
- if (skill.metrics.successRate > 0) {
8142
- successRateSum += skill.metrics.successRate;
8143
- successRateCount++;
8144
- }
8145
8207
  if (stats.byScope && stats.byVisibility) {
8146
8208
  const scope = skill.namespace?.scope || "personal";
8147
8209
  const visibility = skill.namespace?.visibility || "private";
@@ -8149,7 +8211,6 @@ var SkillBank = class {
8149
8211
  stats.byVisibility[visibility]++;
8150
8212
  }
8151
8213
  }
8152
- stats.avgSuccessRate = successRateCount > 0 ? successRateSum / successRateCount : 0;
8153
8214
  return stats;
8154
8215
  }
8155
8216
  /**
@@ -8215,10 +8276,12 @@ function createSkillBank(config) {
8215
8276
  }
8216
8277
 
8217
8278
  // src/storage/index.ts
8279
+ init_esm_shims();
8218
8280
  init_base();
8219
8281
  init_sqlite();
8220
8282
 
8221
8283
  // src/storage/migration.ts
8284
+ init_esm_shims();
8222
8285
  async function migrateStorage(source, target, options = {}) {
8223
8286
  const opts = {
8224
8287
  skills: options.skills ?? true,
@@ -8310,12 +8373,17 @@ async function migrateLineages(source, target, opts, result) {
8310
8373
  }
8311
8374
 
8312
8375
  // src/agents/index.ts
8376
+ init_esm_shims();
8313
8377
  init_types();
8314
8378
  init_generator();
8315
8379
  init_parser();
8316
8380
  init_sync();
8317
8381
 
8382
+ // src/hooks/index.ts
8383
+ init_esm_shims();
8384
+
8318
8385
  // src/hooks/builtin.ts
8386
+ init_esm_shims();
8319
8387
  function createLoggingHook(logger = console.log) {
8320
8388
  return {
8321
8389
  name: "logging-hook",
@@ -8417,6 +8485,18 @@ function conditionalHook(filter, handler) {
8417
8485
  };
8418
8486
  }
8419
8487
 
8488
+ // src/serving/index.ts
8489
+ init_esm_shims();
8490
+
8491
+ // src/materialization/index.ts
8492
+ init_esm_shims();
8493
+
8494
+ // src/sync/index.ts
8495
+ init_esm_shims();
8496
+
8497
+ // src/sync/hierarchical-sync-adapter.ts
8498
+ init_esm_shims();
8499
+
8420
8500
  // src/sync/index.ts
8421
8501
  function createDefaultSyncConfig(remoteUrl, agentId, options) {
8422
8502
  return {
@@ -8446,10 +8526,15 @@ function createDefaultSyncConfig(remoteUrl, agentId, options) {
8446
8526
  }
8447
8527
 
8448
8528
  // src/services/indexer.ts
8449
- import * as path12 from "path";
8529
+ init_esm_shims();
8530
+ import * as path13 from "path";
8450
8531
  import * as fs12 from "fs";
8451
8532
 
8533
+ // src/config/index.ts
8534
+ init_esm_shims();
8535
+
8452
8536
  // src/config/types.ts
8537
+ init_esm_shims();
8453
8538
  var DEFAULT_CONFIG6 = {
8454
8539
  storage: {
8455
8540
  path: "~/.skill-tree"
@@ -8484,8 +8569,9 @@ var DEFAULT_CONFIG6 = {
8484
8569
  };
8485
8570
 
8486
8571
  // src/config/loader.ts
8572
+ init_esm_shims();
8487
8573
  import * as fs11 from "fs";
8488
- import * as path11 from "path";
8574
+ import * as path12 from "path";
8489
8575
  import * as os from "os";
8490
8576
  var ENV_MAPPINGS = {
8491
8577
  GITHUB_TOKEN: "indexer.github_token",
@@ -8496,17 +8582,17 @@ var ENV_MAPPINGS = {
8496
8582
  SKILL_TREE_NO_COLOR: "cli.color"
8497
8583
  };
8498
8584
  function getConfigDir() {
8499
- return path11.join(os.homedir(), ".skill-tree");
8585
+ return path12.join(os.homedir(), ".skill-tree");
8500
8586
  }
8501
8587
  function getConfigPath() {
8502
- return path11.join(getConfigDir(), "config.yaml");
8588
+ return path12.join(getConfigDir(), "config.yaml");
8503
8589
  }
8504
8590
  function expandPath(filePath) {
8505
8591
  if (filePath.startsWith("~/")) {
8506
- return path11.join(os.homedir(), filePath.slice(2));
8592
+ return path12.join(os.homedir(), filePath.slice(2));
8507
8593
  }
8508
8594
  if (filePath.startsWith("~")) {
8509
- return path11.join(os.homedir(), filePath.slice(1));
8595
+ return path12.join(os.homedir(), filePath.slice(1));
8510
8596
  }
8511
8597
  return filePath;
8512
8598
  }
@@ -8535,8 +8621,8 @@ function substituteEnvVarsInObject(obj) {
8535
8621
  }
8536
8622
  return obj;
8537
8623
  }
8538
- function setNestedProperty(obj, path13, value) {
8539
- const parts = path13.split(".");
8624
+ function setNestedProperty(obj, path14, value) {
8625
+ const parts = path14.split(".");
8540
8626
  let current = obj;
8541
8627
  for (let i = 0; i < parts.length - 1; i++) {
8542
8628
  const part = parts[i];
@@ -8695,8 +8781,8 @@ var ConfigLoader = class {
8695
8781
  /**
8696
8782
  * Get a specific config value by path
8697
8783
  */
8698
- get(path13) {
8699
- const parts = path13.split(".");
8784
+ get(path14) {
8785
+ const parts = path14.split(".");
8700
8786
  let current = this.getConfig();
8701
8787
  for (const part of parts) {
8702
8788
  if (current === null || typeof current !== "object") {
@@ -8716,7 +8802,7 @@ var ConfigLoader = class {
8716
8802
  * Create default config file
8717
8803
  */
8718
8804
  createDefaultConfigFile() {
8719
- const configDir = path11.dirname(expandPath(this.configPath));
8805
+ const configDir = path12.dirname(expandPath(this.configPath));
8720
8806
  if (!fs11.existsSync(configDir)) {
8721
8807
  fs11.mkdirSync(configDir, { recursive: true });
8722
8808
  }
@@ -8779,6 +8865,7 @@ function loadConfig(configPath) {
8779
8865
  }
8780
8866
 
8781
8867
  // src/import/converter.ts
8868
+ init_esm_shims();
8782
8869
  function convertIndexerSkill(indexerSkill) {
8783
8870
  const warnings = [];
8784
8871
  const instructions = indexerSkill.content || "";
@@ -8805,11 +8892,6 @@ function convertIndexerSkill(indexerSkill) {
8805
8892
  createdAt: new Date(indexerSkill.scrapedAt),
8806
8893
  updatedAt: new Date(indexerSkill.updatedAt),
8807
8894
  status,
8808
- metrics: {
8809
- usageCount: 0,
8810
- successRate: 0,
8811
- feedbackScores: []
8812
- },
8813
8895
  source: {
8814
8896
  type: "imported",
8815
8897
  location: indexerSkill.sourceUrl,
@@ -8869,8 +8951,8 @@ var IndexerService = class {
8869
8951
  const mod = this.serviceConfig.scraperModules;
8870
8952
  this.databaseModule = mod;
8871
8953
  if (mod.createDatabase) {
8872
- const dbPath = this.serviceConfig.databasePath || path12.join(process.cwd(), "scraper/data/skills.db");
8873
- const dbDir = path12.dirname(dbPath);
8954
+ const dbPath = this.serviceConfig.databasePath || path13.join(process.cwd(), "scraper/data/skills.db");
8955
+ const dbDir = path13.dirname(dbPath);
8874
8956
  if (!fs12.existsSync(dbDir)) fs12.mkdirSync(dbDir, { recursive: true });
8875
8957
  this.db = mod.createDatabase({ type: "sqlite", path: dbPath });
8876
8958
  if (this.db.connect) await this.db.connect();
@@ -8883,7 +8965,7 @@ var IndexerService = class {
8883
8965
  const scraperConfig = {
8884
8966
  githubToken: config.githubToken || "",
8885
8967
  cacheEnabled: true,
8886
- cacheDir: config.cacheDir || path12.join(process.cwd(), ".cache/scraper"),
8968
+ cacheDir: config.cacheDir || path13.join(process.cwd(), ".cache/scraper"),
8887
8969
  cacheTtlSeconds: config.cacheTtlSeconds || 3600,
8888
8970
  requestDelayMs: 100,
8889
8971
  maxRetries: 3
@@ -8936,15 +9018,15 @@ var IndexerService = class {
8936
9018
  }
8937
9019
  const possiblePaths = [
8938
9020
  // Relative to this file in dist
8939
- path12.resolve(__dirname, "../../scraper/dist"),
9021
+ path13.resolve(__dirname, "../../scraper/dist"),
8940
9022
  // Relative to project root
8941
- path12.resolve(process.cwd(), "scraper/dist"),
9023
+ path13.resolve(process.cwd(), "scraper/dist"),
8942
9024
  // Absolute paths from config
8943
- this.serviceConfig.cacheDir ? path12.resolve(this.serviceConfig.cacheDir, "../scraper/dist") : null
9025
+ this.serviceConfig.cacheDir ? path13.resolve(this.serviceConfig.cacheDir, "../scraper/dist") : null
8944
9026
  ].filter(Boolean);
8945
9027
  let scraperBasePath = null;
8946
9028
  for (const basePath of possiblePaths) {
8947
- const scraperIndex = path12.join(basePath, "scraper/index.js");
9029
+ const scraperIndex = path13.join(basePath, "scraper/index.js");
8948
9030
  if (fs12.existsSync(scraperIndex)) {
8949
9031
  scraperBasePath = basePath;
8950
9032
  break;
@@ -8955,9 +9037,9 @@ var IndexerService = class {
8955
9037
  "Scraper modules not found. Run `cd scraper && npm run build` first."
8956
9038
  );
8957
9039
  }
8958
- const scraperPath = path12.join(scraperBasePath, "scraper/index.js");
8959
- const indexerPath = path12.join(scraperBasePath, "indexer/index.js");
8960
- const databasePath = path12.join(scraperBasePath, "database/index.js");
9040
+ const scraperPath = path13.join(scraperBasePath, "scraper/index.js");
9041
+ const indexerPath = path13.join(scraperBasePath, "indexer/index.js");
9042
+ const databasePath = path13.join(scraperBasePath, "database/index.js");
8961
9043
  this.scraperModule = await import(
8962
9044
  /* webpackIgnore: true */
8963
9045
  scraperPath
@@ -8971,7 +9053,7 @@ var IndexerService = class {
8971
9053
  databasePath
8972
9054
  );
8973
9055
  if (this.databaseModule.createDatabase) {
8974
- const dbPath = this.serviceConfig.databasePath || path12.join(process.cwd(), "scraper/data/skills.db");
9056
+ const dbPath = this.serviceConfig.databasePath || path13.join(process.cwd(), "scraper/data/skills.db");
8975
9057
  this.db = this.databaseModule.createDatabase(dbPath);
8976
9058
  }
8977
9059
  this.initialized = true;
@@ -9608,7 +9690,7 @@ var IndexerService = class {
9608
9690
  };
9609
9691
 
9610
9692
  // src/index.ts
9611
- var VERSION = "0.1.0";
9693
+ var VERSION = "0.2.0";
9612
9694
  export {
9613
9695
  AgentsGenerator,
9614
9696
  AgentsParser,
@@ -9677,4 +9759,3 @@ export {
9677
9759
  testingProfile,
9678
9760
  writeAgentsMd
9679
9761
  };
9680
- //# sourceMappingURL=index.mjs.map