skill-tree 0.1.2 → 0.1.3

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.js CHANGED
@@ -42,7 +42,6 @@ __export(index_exports, {
42
42
  BaseStorageAdapter: () => BaseStorageAdapter,
43
43
  BatchProcessor: () => BatchProcessor,
44
44
  ClaudeCodeAdapter: () => ClaudeCodeAdapter,
45
- CognitiveCoreProvider: () => CognitiveCoreProvider,
46
45
  ConflictStore: () => ConflictStore,
47
46
  DEFAULT_ACTIVATION_CONFIG: () => DEFAULT_ACTIVATION_CONFIG,
48
47
  DEFAULT_AGENTS_CONFIG: () => DEFAULT_AGENTS_CONFIG,
@@ -61,7 +60,6 @@ __export(index_exports, {
61
60
  MemoryMetricsStorage: () => MemoryMetricsStorage,
62
61
  MemoryStorageAdapter: () => MemoryStorageAdapter,
63
62
  MetricsTracker: () => MetricsTracker,
64
- NaiveLearningProvider: () => NaiveLearningProvider,
65
63
  OpenAIAdapter: () => OpenAIAdapter,
66
64
  OpenAIEmbedding: () => OpenAIEmbedding,
67
65
  ProjectDetector: () => ProjectDetector,
@@ -94,9 +92,7 @@ __export(index_exports, {
94
92
  createAgentsParser: () => createAgentsParser,
95
93
  createAgentsSync: () => createAgentsSync,
96
94
  createBackupHook: () => createBackupHook,
97
- createCognitiveCoreProvider: () => createCognitiveCoreProvider,
98
95
  createConflictStore: () => createConflictStore,
99
- createDefaultCognitiveCoreFactory: () => createDefaultCognitiveCoreFactory,
100
96
  createDefaultSyncConfig: () => createDefaultSyncConfig,
101
97
  createExtractionEnrichmentHook: () => createExtractionEnrichmentHook,
102
98
  createExtractionValidationHook: () => createExtractionValidationHook,
@@ -106,7 +102,6 @@ __export(index_exports, {
106
102
  createMcpServer: () => createMcpServer,
107
103
  createMetricsHook: () => createMetricsHook,
108
104
  createMetricsTracker: () => createMetricsTracker,
109
- createNaiveProvider: () => createNaiveProvider,
110
105
  createQualityBypassHook: () => createQualityBypassHook,
111
106
  createQualityLoggingHook: () => createQualityLoggingHook,
112
107
  createSaveValidationHook: () => createSaveValidationHook,
@@ -116,6 +111,7 @@ __export(index_exports, {
116
111
  createToolHandlers: () => createToolHandlers,
117
112
  debuggingProfile: () => debuggingProfile,
118
113
  devopsProfile: () => devopsProfile,
114
+ discoverSkills: () => discoverSkills,
119
115
  documentationProfile: () => documentationProfile,
120
116
  euclideanDistance: () => euclideanDistance,
121
117
  executeToolCall: () => executeToolCall,
@@ -126,6 +122,7 @@ __export(index_exports, {
126
122
  getLatestVersion: () => getLatestVersion,
127
123
  getToolDefinition: () => getToolDefinition,
128
124
  getToolNames: () => getToolNames,
125
+ hasSkilltreeDir: () => hasSkilltreeDir,
129
126
  hookRegistry: () => hookRegistry,
130
127
  implementationProfile: () => implementationProfile,
131
128
  importFromAgentsMd: () => importFromAgentsMd,
@@ -846,11 +843,76 @@ var LoadoutCompiler = class {
846
843
  // src/serving/project-detector.ts
847
844
  var import_fs = require("fs");
848
845
  var import_path = require("path");
849
- var _ProjectDetector = class _ProjectDetector {
846
+ var ProjectDetector = class _ProjectDetector {
850
847
  constructor() {
851
848
  /** Cache for project context */
852
849
  this.cache = /* @__PURE__ */ new Map();
853
850
  }
851
+ static {
852
+ /** Project type patterns */
853
+ this.PROJECT_TYPES = [
854
+ { manifestFile: "package.json", type: "nodejs", tags: ["nodejs", "javascript"], packageManager: "npm" },
855
+ { manifestFile: "pyproject.toml", type: "python", tags: ["python"], packageManager: "pip" },
856
+ { manifestFile: "requirements.txt", type: "python", tags: ["python"], packageManager: "pip" },
857
+ { manifestFile: "Cargo.toml", type: "rust", tags: ["rust"], packageManager: "cargo" },
858
+ { manifestFile: "go.mod", type: "go", tags: ["go", "golang"] },
859
+ { manifestFile: "pom.xml", type: "java", tags: ["java", "maven"], packageManager: "maven" },
860
+ { manifestFile: "build.gradle", type: "java", tags: ["java", "gradle"], packageManager: "gradle" },
861
+ { manifestFile: "build.gradle.kts", type: "kotlin", tags: ["kotlin", "gradle"], packageManager: "gradle" }
862
+ ];
863
+ }
864
+ static {
865
+ /** TypeScript detection */
866
+ this.TYPESCRIPT_FILES = ["tsconfig.json", "tsconfig.base.json"];
867
+ }
868
+ static {
869
+ /** Node.js framework patterns */
870
+ this.NODE_FRAMEWORKS = [
871
+ { name: "react", packageName: "react", tags: ["react", "frontend"] },
872
+ { name: "next", packageName: "next", tags: ["nextjs", "react", "fullstack"] },
873
+ { name: "vue", packageName: "vue", tags: ["vue", "frontend"] },
874
+ { name: "nuxt", packageName: "nuxt", tags: ["nuxt", "vue", "fullstack"] },
875
+ { name: "angular", packageName: "@angular/core", tags: ["angular", "frontend"] },
876
+ { name: "svelte", packageName: "svelte", tags: ["svelte", "frontend"] },
877
+ { name: "express", packageName: "express", tags: ["express", "backend", "api"] },
878
+ { name: "fastify", packageName: "fastify", tags: ["fastify", "backend", "api"] },
879
+ { name: "nestjs", packageName: "@nestjs/core", tags: ["nestjs", "backend", "api"] },
880
+ { name: "hono", packageName: "hono", tags: ["hono", "backend", "api"] },
881
+ { name: "prisma", packageName: "@prisma/client", tags: ["prisma", "database", "orm"] },
882
+ { name: "drizzle", packageName: "drizzle-orm", tags: ["drizzle", "database", "orm"] },
883
+ { name: "typeorm", packageName: "typeorm", tags: ["typeorm", "database", "orm"] },
884
+ { name: "jest", packageName: "jest", tags: ["testing", "jest"] },
885
+ { name: "vitest", packageName: "vitest", tags: ["testing", "vitest"] },
886
+ { name: "playwright", packageName: "@playwright/test", tags: ["testing", "e2e", "playwright"] },
887
+ { name: "cypress", packageName: "cypress", tags: ["testing", "e2e", "cypress"] }
888
+ ];
889
+ }
890
+ static {
891
+ /** Python framework patterns (from pyproject.toml or requirements.txt) */
892
+ this.PYTHON_FRAMEWORKS = [
893
+ { name: "fastapi", packageName: "fastapi", tags: ["fastapi", "backend", "api"] },
894
+ { name: "django", packageName: "django", tags: ["django", "backend", "fullstack"] },
895
+ { name: "flask", packageName: "flask", tags: ["flask", "backend", "api"] },
896
+ { name: "sqlalchemy", packageName: "sqlalchemy", tags: ["sqlalchemy", "database", "orm"] },
897
+ { name: "pytest", packageName: "pytest", tags: ["testing", "pytest"] },
898
+ { name: "pydantic", packageName: "pydantic", tags: ["pydantic", "validation"] }
899
+ ];
900
+ }
901
+ static {
902
+ /** Directory patterns */
903
+ this.DIRECTORY_PATTERNS = [
904
+ { pattern: ".github/workflows", feature: "github-actions", tags: ["ci", "github-actions"] },
905
+ { pattern: ".gitlab-ci.yml", feature: "gitlab-ci", tags: ["ci", "gitlab"] },
906
+ { pattern: "Dockerfile", feature: "docker", tags: ["docker", "containers"] },
907
+ { pattern: "docker-compose.yml", feature: "docker-compose", tags: ["docker", "containers"] },
908
+ { pattern: "docker-compose.yaml", feature: "docker-compose", tags: ["docker", "containers"] },
909
+ { pattern: "terraform", feature: "terraform", tags: ["terraform", "infrastructure"] },
910
+ { pattern: "kubernetes", feature: "kubernetes", tags: ["kubernetes", "infrastructure"] },
911
+ { pattern: "k8s", feature: "kubernetes", tags: ["kubernetes", "infrastructure"] },
912
+ { pattern: ".env.example", feature: "env-config", tags: ["configuration"] },
913
+ { pattern: "prisma/schema.prisma", feature: "prisma", tags: ["prisma", "database"] }
914
+ ];
915
+ }
854
916
  /**
855
917
  * Detect project context from a directory
856
918
  */
@@ -1012,62 +1074,6 @@ var _ProjectDetector = class _ProjectDetector {
1012
1074
  }
1013
1075
  }
1014
1076
  };
1015
- /** Project type patterns */
1016
- _ProjectDetector.PROJECT_TYPES = [
1017
- { manifestFile: "package.json", type: "nodejs", tags: ["nodejs", "javascript"], packageManager: "npm" },
1018
- { manifestFile: "pyproject.toml", type: "python", tags: ["python"], packageManager: "pip" },
1019
- { manifestFile: "requirements.txt", type: "python", tags: ["python"], packageManager: "pip" },
1020
- { manifestFile: "Cargo.toml", type: "rust", tags: ["rust"], packageManager: "cargo" },
1021
- { manifestFile: "go.mod", type: "go", tags: ["go", "golang"] },
1022
- { manifestFile: "pom.xml", type: "java", tags: ["java", "maven"], packageManager: "maven" },
1023
- { manifestFile: "build.gradle", type: "java", tags: ["java", "gradle"], packageManager: "gradle" },
1024
- { manifestFile: "build.gradle.kts", type: "kotlin", tags: ["kotlin", "gradle"], packageManager: "gradle" }
1025
- ];
1026
- /** TypeScript detection */
1027
- _ProjectDetector.TYPESCRIPT_FILES = ["tsconfig.json", "tsconfig.base.json"];
1028
- /** Node.js framework patterns */
1029
- _ProjectDetector.NODE_FRAMEWORKS = [
1030
- { name: "react", packageName: "react", tags: ["react", "frontend"] },
1031
- { name: "next", packageName: "next", tags: ["nextjs", "react", "fullstack"] },
1032
- { name: "vue", packageName: "vue", tags: ["vue", "frontend"] },
1033
- { name: "nuxt", packageName: "nuxt", tags: ["nuxt", "vue", "fullstack"] },
1034
- { name: "angular", packageName: "@angular/core", tags: ["angular", "frontend"] },
1035
- { name: "svelte", packageName: "svelte", tags: ["svelte", "frontend"] },
1036
- { name: "express", packageName: "express", tags: ["express", "backend", "api"] },
1037
- { name: "fastify", packageName: "fastify", tags: ["fastify", "backend", "api"] },
1038
- { name: "nestjs", packageName: "@nestjs/core", tags: ["nestjs", "backend", "api"] },
1039
- { name: "hono", packageName: "hono", tags: ["hono", "backend", "api"] },
1040
- { name: "prisma", packageName: "@prisma/client", tags: ["prisma", "database", "orm"] },
1041
- { name: "drizzle", packageName: "drizzle-orm", tags: ["drizzle", "database", "orm"] },
1042
- { name: "typeorm", packageName: "typeorm", tags: ["typeorm", "database", "orm"] },
1043
- { name: "jest", packageName: "jest", tags: ["testing", "jest"] },
1044
- { name: "vitest", packageName: "vitest", tags: ["testing", "vitest"] },
1045
- { name: "playwright", packageName: "@playwright/test", tags: ["testing", "e2e", "playwright"] },
1046
- { name: "cypress", packageName: "cypress", tags: ["testing", "e2e", "cypress"] }
1047
- ];
1048
- /** Python framework patterns (from pyproject.toml or requirements.txt) */
1049
- _ProjectDetector.PYTHON_FRAMEWORKS = [
1050
- { name: "fastapi", packageName: "fastapi", tags: ["fastapi", "backend", "api"] },
1051
- { name: "django", packageName: "django", tags: ["django", "backend", "fullstack"] },
1052
- { name: "flask", packageName: "flask", tags: ["flask", "backend", "api"] },
1053
- { name: "sqlalchemy", packageName: "sqlalchemy", tags: ["sqlalchemy", "database", "orm"] },
1054
- { name: "pytest", packageName: "pytest", tags: ["testing", "pytest"] },
1055
- { name: "pydantic", packageName: "pydantic", tags: ["pydantic", "validation"] }
1056
- ];
1057
- /** Directory patterns */
1058
- _ProjectDetector.DIRECTORY_PATTERNS = [
1059
- { pattern: ".github/workflows", feature: "github-actions", tags: ["ci", "github-actions"] },
1060
- { pattern: ".gitlab-ci.yml", feature: "gitlab-ci", tags: ["ci", "gitlab"] },
1061
- { pattern: "Dockerfile", feature: "docker", tags: ["docker", "containers"] },
1062
- { pattern: "docker-compose.yml", feature: "docker-compose", tags: ["docker", "containers"] },
1063
- { pattern: "docker-compose.yaml", feature: "docker-compose", tags: ["docker", "containers"] },
1064
- { pattern: "terraform", feature: "terraform", tags: ["terraform", "infrastructure"] },
1065
- { pattern: "kubernetes", feature: "kubernetes", tags: ["kubernetes", "infrastructure"] },
1066
- { pattern: "k8s", feature: "kubernetes", tags: ["kubernetes", "infrastructure"] },
1067
- { pattern: ".env.example", feature: "env-config", tags: ["configuration"] },
1068
- { pattern: "prisma/schema.prisma", feature: "prisma", tags: ["prisma", "database"] }
1069
- ];
1070
- var ProjectDetector = _ProjectDetector;
1071
1077
 
1072
1078
  // src/serving/view-renderer.ts
1073
1079
  var DEFAULT_CONFIG2 = {
@@ -6522,10 +6528,7 @@ var MemoryStorageAdapter = class extends BaseStorageAdapter {
6522
6528
  this.skills = /* @__PURE__ */ new Map();
6523
6529
  // skillId -> version -> skill
6524
6530
  this.lineages = /* @__PURE__ */ new Map();
6525
- this.candidates = /* @__PURE__ */ new Map();
6526
- this.antiPatterns = /* @__PURE__ */ new Map();
6527
6531
  }
6528
- // skillId -> patterns
6529
6532
  async initialize() {
6530
6533
  this.initialized = true;
6531
6534
  }
@@ -6656,78 +6659,6 @@ var MemoryStorageAdapter = class extends BaseStorageAdapter {
6656
6659
  clear() {
6657
6660
  this.skills.clear();
6658
6661
  this.lineages.clear();
6659
- this.candidates.clear();
6660
- this.antiPatterns.clear();
6661
- }
6662
- // ==========================================================================
6663
- // Learning Candidate Operations
6664
- // ==========================================================================
6665
- async saveCandidate(candidate) {
6666
- this.ensureInitialized();
6667
- this.candidates.set(candidate.id, { ...candidate });
6668
- }
6669
- async getCandidate(id) {
6670
- this.ensureInitialized();
6671
- return this.candidates.get(id) || null;
6672
- }
6673
- async listCandidates(filter) {
6674
- this.ensureInitialized();
6675
- let results = Array.from(this.candidates.values());
6676
- if (filter) {
6677
- if (filter.kind && filter.kind.length > 0) {
6678
- results = results.filter((c) => filter.kind.includes(c.kind));
6679
- }
6680
- if (filter.status && filter.status.length > 0) {
6681
- results = results.filter((c) => filter.status.includes(c.status));
6682
- }
6683
- if (filter.minConfidence !== void 0) {
6684
- results = results.filter((c) => c.confidence >= filter.minConfidence);
6685
- }
6686
- if (filter.createdAfter) {
6687
- results = results.filter((c) => c.createdAt >= filter.createdAfter);
6688
- }
6689
- if (filter.createdBefore) {
6690
- results = results.filter((c) => c.createdAt <= filter.createdBefore);
6691
- }
6692
- }
6693
- return results;
6694
- }
6695
- async updateCandidateStatus(id, status, details) {
6696
- this.ensureInitialized();
6697
- const candidate = this.candidates.get(id);
6698
- if (!candidate) return false;
6699
- candidate.status = status;
6700
- candidate.updatedAt = /* @__PURE__ */ new Date();
6701
- if (details?.promotedToSkillId) {
6702
- candidate.promotedToSkillId = details.promotedToSkillId;
6703
- }
6704
- if (details?.rejectionReason) {
6705
- candidate.rejectionReason = details.rejectionReason;
6706
- }
6707
- return true;
6708
- }
6709
- async deleteCandidate(id) {
6710
- this.ensureInitialized();
6711
- return this.candidates.delete(id);
6712
- }
6713
- // ==========================================================================
6714
- // Anti-Pattern Operations
6715
- // ==========================================================================
6716
- async saveAntiPatterns(skillId, patterns) {
6717
- this.ensureInitialized();
6718
- this.antiPatterns.set(skillId, [...patterns]);
6719
- }
6720
- async getAntiPatterns(skillId) {
6721
- this.ensureInitialized();
6722
- return this.antiPatterns.get(skillId) || [];
6723
- }
6724
- async listAntiPatterns() {
6725
- this.ensureInitialized();
6726
- const results = [];
6727
- for (const [skillId, patterns] of this.antiPatterns) {
6728
- results.push({ skillId, patterns });
6729
- }
6730
- return results;
6731
6662
  }
6732
6663
  // ==========================================================================
6733
6664
  // Fork Tracking
@@ -7278,152 +7209,6 @@ ${body}`;
7278
7209
  return Math.abs(hash).toString(16);
7279
7210
  }
7280
7211
  // ==========================================================================
7281
- // Learning Candidate Operations
7282
- // ==========================================================================
7283
- get candidatesDir() {
7284
- return path4.join(this.skilltreeDir, "candidates");
7285
- }
7286
- get antiPatternsDir() {
7287
- return path4.join(this.skilltreeDir, "anti-patterns");
7288
- }
7289
- async saveCandidate(candidate) {
7290
- this.ensureInitialized();
7291
- await fs4.mkdir(this.candidatesDir, { recursive: true });
7292
- const candidatePath = path4.join(this.candidatesDir, `${candidate.id}.json`);
7293
- await fs4.writeFile(candidatePath, JSON.stringify(candidate, null, 2), "utf-8");
7294
- }
7295
- async getCandidate(id) {
7296
- this.ensureInitialized();
7297
- const candidatePath = path4.join(this.candidatesDir, `${id}.json`);
7298
- try {
7299
- const content = await fs4.readFile(candidatePath, "utf-8");
7300
- const candidate = JSON.parse(content);
7301
- candidate.createdAt = new Date(candidate.createdAt);
7302
- candidate.updatedAt = new Date(candidate.updatedAt);
7303
- candidate.source.extractedAt = new Date(candidate.source.extractedAt);
7304
- return candidate;
7305
- } catch (error) {
7306
- if (error.code === "ENOENT") {
7307
- return null;
7308
- }
7309
- throw error;
7310
- }
7311
- }
7312
- async listCandidates(filter) {
7313
- this.ensureInitialized();
7314
- try {
7315
- const files = await fs4.readdir(this.candidatesDir);
7316
- const candidates = [];
7317
- for (const file of files) {
7318
- if (!file.endsWith(".json")) continue;
7319
- const id = file.replace(".json", "");
7320
- const candidate = await this.getCandidate(id);
7321
- if (candidate) {
7322
- candidates.push(candidate);
7323
- }
7324
- }
7325
- let results = candidates;
7326
- if (filter) {
7327
- if (filter.kind && filter.kind.length > 0) {
7328
- results = results.filter((c) => filter.kind.includes(c.kind));
7329
- }
7330
- if (filter.status && filter.status.length > 0) {
7331
- results = results.filter((c) => filter.status.includes(c.status));
7332
- }
7333
- if (filter.minConfidence !== void 0) {
7334
- results = results.filter((c) => c.confidence >= filter.minConfidence);
7335
- }
7336
- if (filter.createdAfter) {
7337
- results = results.filter((c) => c.createdAt >= filter.createdAfter);
7338
- }
7339
- if (filter.createdBefore) {
7340
- results = results.filter((c) => c.createdAt <= filter.createdBefore);
7341
- }
7342
- }
7343
- return results;
7344
- } catch (error) {
7345
- if (error.code === "ENOENT") {
7346
- return [];
7347
- }
7348
- throw error;
7349
- }
7350
- }
7351
- async updateCandidateStatus(id, status, details) {
7352
- this.ensureInitialized();
7353
- const candidate = await this.getCandidate(id);
7354
- if (!candidate) return false;
7355
- candidate.status = status;
7356
- candidate.updatedAt = /* @__PURE__ */ new Date();
7357
- if (details?.promotedToSkillId) {
7358
- candidate.promotedToSkillId = details.promotedToSkillId;
7359
- }
7360
- if (details?.rejectionReason) {
7361
- candidate.rejectionReason = details.rejectionReason;
7362
- }
7363
- await this.saveCandidate(candidate);
7364
- return true;
7365
- }
7366
- async deleteCandidate(id) {
7367
- this.ensureInitialized();
7368
- const candidatePath = path4.join(this.candidatesDir, `${id}.json`);
7369
- try {
7370
- await fs4.unlink(candidatePath);
7371
- return true;
7372
- } catch (error) {
7373
- if (error.code === "ENOENT") {
7374
- return false;
7375
- }
7376
- throw error;
7377
- }
7378
- }
7379
- // ==========================================================================
7380
- // Anti-Pattern Operations
7381
- // ==========================================================================
7382
- async saveAntiPatterns(skillId, patterns) {
7383
- this.ensureInitialized();
7384
- await fs4.mkdir(this.antiPatternsDir, { recursive: true });
7385
- const patternPath = path4.join(this.antiPatternsDir, `${skillId}.json`);
7386
- await fs4.writeFile(patternPath, JSON.stringify(patterns, null, 2), "utf-8");
7387
- }
7388
- async getAntiPatterns(skillId) {
7389
- this.ensureInitialized();
7390
- const patternPath = path4.join(this.antiPatternsDir, `${skillId}.json`);
7391
- try {
7392
- const content = await fs4.readFile(patternPath, "utf-8");
7393
- const patterns = JSON.parse(content);
7394
- for (const pattern of patterns) {
7395
- pattern.learnedAt = new Date(pattern.learnedAt);
7396
- }
7397
- return patterns;
7398
- } catch (error) {
7399
- if (error.code === "ENOENT") {
7400
- return [];
7401
- }
7402
- throw error;
7403
- }
7404
- }
7405
- async listAntiPatterns() {
7406
- this.ensureInitialized();
7407
- try {
7408
- const files = await fs4.readdir(this.antiPatternsDir);
7409
- const results = [];
7410
- for (const file of files) {
7411
- if (!file.endsWith(".json")) continue;
7412
- const skillId = file.replace(".json", "");
7413
- const patterns = await this.getAntiPatterns(skillId);
7414
- if (patterns.length > 0) {
7415
- results.push({ skillId, patterns });
7416
- }
7417
- }
7418
- return results;
7419
- } catch (error) {
7420
- if (error.code === "ENOENT") {
7421
- return [];
7422
- }
7423
- throw error;
7424
- }
7425
- }
7426
- // ==========================================================================
7427
7212
  // Fork Tracking
7428
7213
  // ==========================================================================
7429
7214
  async recordFork(sourceSkillId, fork) {
@@ -8226,8 +8011,6 @@ async function migrateStorage(source, target, options = {}) {
8226
8011
  const opts = {
8227
8012
  skills: options.skills ?? true,
8228
8013
  lineage: options.lineage ?? true,
8229
- candidates: options.candidates ?? true,
8230
- antiPatterns: options.antiPatterns ?? true,
8231
8014
  onProgress: options.onProgress ?? (() => {
8232
8015
  }),
8233
8016
  overwrite: options.overwrite ?? false
@@ -8239,9 +8022,7 @@ async function migrateStorage(source, target, options = {}) {
8239
8022
  errors: 0,
8240
8023
  details: {
8241
8024
  skills: { migrated: 0, skipped: 0, errors: 0 },
8242
- lineages: { migrated: 0, skipped: 0, errors: 0 },
8243
- candidates: { migrated: 0, skipped: 0, errors: 0 },
8244
- antiPatterns: { migrated: 0, skipped: 0, errors: 0 }
8025
+ lineages: { migrated: 0, skipped: 0, errors: 0 }
8245
8026
  }
8246
8027
  };
8247
8028
  if (opts.skills) {
@@ -8250,12 +8031,6 @@ async function migrateStorage(source, target, options = {}) {
8250
8031
  if (opts.lineage) {
8251
8032
  await migrateLineages(source, target, opts, result);
8252
8033
  }
8253
- if (opts.candidates) {
8254
- await migrateCandidates(source, target, opts, result);
8255
- }
8256
- if (opts.antiPatterns) {
8257
- await migrateAntiPatterns(source, target, opts, result);
8258
- }
8259
8034
  return result;
8260
8035
  }
8261
8036
  async function migrateSkills(source, target, opts, result) {
@@ -8321,65 +8096,6 @@ async function migrateLineages(source, target, opts, result) {
8321
8096
  }
8322
8097
  }
8323
8098
  }
8324
- async function migrateCandidates(source, target, opts, result) {
8325
- if (!source.listCandidates || !target.saveCandidate) {
8326
- return;
8327
- }
8328
- const candidates = await source.listCandidates();
8329
- for (const candidate of candidates) {
8330
- result.totalProcessed++;
8331
- try {
8332
- if (!opts.overwrite && target.getCandidate) {
8333
- const existing = await target.getCandidate(candidate.id);
8334
- if (existing) {
8335
- result.skipped++;
8336
- result.details.candidates.skipped++;
8337
- opts.onProgress({ type: "candidate", id: candidate.id, status: "skipped" });
8338
- continue;
8339
- }
8340
- }
8341
- await target.saveCandidate(candidate);
8342
- result.migrated++;
8343
- result.details.candidates.migrated++;
8344
- opts.onProgress({ type: "candidate", id: candidate.id, status: "migrated" });
8345
- } catch (error) {
8346
- result.errors++;
8347
- result.details.candidates.errors++;
8348
- opts.onProgress({
8349
- type: "candidate",
8350
- id: candidate.id,
8351
- status: "error",
8352
- error: error instanceof Error ? error.message : String(error)
8353
- });
8354
- }
8355
- }
8356
- }
8357
- async function migrateAntiPatterns(source, target, opts, result) {
8358
- if (!source.getAntiPatterns || !target.saveAntiPatterns) {
8359
- return;
8360
- }
8361
- const skills = await source.listSkills();
8362
- for (const skill of skills) {
8363
- try {
8364
- const patterns = await source.getAntiPatterns(skill.id);
8365
- if (!patterns || patterns.length === 0) continue;
8366
- result.totalProcessed++;
8367
- await target.saveAntiPatterns(skill.id, patterns);
8368
- result.migrated++;
8369
- result.details.antiPatterns.migrated++;
8370
- opts.onProgress({ type: "anti-pattern", id: skill.id, status: "migrated" });
8371
- } catch (error) {
8372
- result.errors++;
8373
- result.details.antiPatterns.errors++;
8374
- opts.onProgress({
8375
- type: "anti-pattern",
8376
- id: skill.id,
8377
- status: "error",
8378
- error: error instanceof Error ? error.message : String(error)
8379
- });
8380
- }
8381
- }
8382
- }
8383
8099
 
8384
8100
  // src/versioning/lineage.ts
8385
8101
  var LineageTracker = class {
@@ -9152,387 +8868,80 @@ function createSkillMerger(storage, config) {
9152
8868
  return new SkillMerger(storage, config);
9153
8869
  }
9154
8870
 
9155
- // src/learning/providers/naive.ts
9156
- var NaiveLearningProvider = class {
9157
- constructor(config) {
9158
- this.name = "naive";
9159
- this.description = "Built-in extraction using heuristics and optional LLM analysis";
9160
- this.capabilities = {
9161
- accumulating: false,
9162
- feedbackEnabled: false,
9163
- persistent: false,
9164
- supportedKinds: ["skill", "strategy", "pattern", "error-fix"]
9165
- };
9166
- this.config = {
9167
- llmProvider: config?.llmProvider ?? null,
9168
- minConfidence: config?.minConfidence ?? 0.6,
9169
- runQualityGates: config?.runQualityGates ?? true,
9170
- creditStrategy: config?.creditStrategy ?? "simple"
9171
- };
9172
- this.manualExtractor = new ManualExtractor();
9173
- this.automaticExtractor = new AutomaticExtractor({
9174
- llmProvider: this.config.llmProvider || void 0,
9175
- minConfidence: this.config.minConfidence
9176
- });
8871
+ // src/hooks/registry.ts
8872
+ var import_crypto = require("crypto");
8873
+ var PRIORITY_ORDER = {
8874
+ high: 0,
8875
+ normal: 1,
8876
+ low: 2
8877
+ };
8878
+ var HookRegistry = class {
8879
+ constructor() {
8880
+ this.hooks = /* @__PURE__ */ new Map();
8881
+ this.eventIndex = /* @__PURE__ */ new Map();
9177
8882
  }
9178
8883
  /**
9179
- * Set or update the LLM provider
8884
+ * Register a new hook
9180
8885
  */
9181
- setLLMProvider(provider) {
9182
- this.config.llmProvider = provider;
9183
- this.automaticExtractor.setLLMProvider(provider);
8886
+ register(options) {
8887
+ const id = (0, import_crypto.randomUUID)();
8888
+ const events = Array.isArray(options.events) ? options.events : [options.events];
8889
+ const hook = {
8890
+ id,
8891
+ name: options.name,
8892
+ events,
8893
+ handler: options.handler,
8894
+ priority: options.priority || "normal",
8895
+ enabled: options.enabled !== false,
8896
+ filter: options.filter
8897
+ };
8898
+ this.hooks.set(id, hook);
8899
+ for (const event of events) {
8900
+ if (!this.eventIndex.has(event)) {
8901
+ this.eventIndex.set(event, /* @__PURE__ */ new Set());
8902
+ }
8903
+ this.eventIndex.get(event).add(id);
8904
+ }
8905
+ return id;
9184
8906
  }
9185
8907
  /**
9186
- * Analyze a trajectory and extract learning candidates
8908
+ * Unregister a hook
9187
8909
  */
9188
- async analyze(trajectory, options) {
9189
- const startTime = Date.now();
9190
- const candidates = [];
9191
- const kinds = options?.kinds ?? ["skill"];
9192
- const useAutomatic = this.config.llmProvider != null;
9193
- let results;
9194
- if (useAutomatic) {
9195
- results = await this.automaticExtractor.extract(trajectory, {
9196
- turnRange: options?.turnRange,
9197
- minConfidence: options?.minConfidence ?? this.config.minConfidence,
9198
- skipValidation: options?.skipValidation ?? !this.config.runQualityGates,
9199
- context: options?.context
9200
- });
9201
- } else {
9202
- results = await this.manualExtractor.extract(trajectory, {
9203
- turnRange: options?.turnRange,
9204
- skipValidation: options?.skipValidation ?? !this.config.runQualityGates,
9205
- context: options?.context
9206
- });
9207
- }
9208
- for (const result of results) {
9209
- if (!result.success || !result.skill) continue;
9210
- const kind = this.inferKind(result.skill);
9211
- if (!kinds.includes(kind)) continue;
9212
- const candidate = this.extractionResultToCandidate(result, trajectory);
9213
- candidates.push(candidate);
8910
+ unregister(hookId) {
8911
+ const hook = this.hooks.get(hookId);
8912
+ if (!hook) return false;
8913
+ for (const event of hook.events) {
8914
+ this.eventIndex.get(event)?.delete(hookId);
9214
8915
  }
9215
- return {
9216
- candidates,
9217
- // Naive provider doesn't produce updates, demotions, or anti-patterns
9218
- metadata: {
9219
- trajectoriesAnalyzed: 1,
9220
- durationMs: Date.now() - startTime
9221
- }
9222
- };
8916
+ this.hooks.delete(hookId);
8917
+ return true;
9223
8918
  }
9224
8919
  /**
9225
- * Batch analysis - runs individual analysis on each trajectory.
9226
- * A more sophisticated provider could do cross-trajectory pattern detection.
8920
+ * Enable a hook
9227
8921
  */
9228
- async analyzeBatch(trajectories, options) {
9229
- const startTime = Date.now();
9230
- const allCandidates = [];
9231
- for (const trajectory of trajectories) {
9232
- const result = await this.analyze(trajectory, options);
9233
- allCandidates.push(...result.candidates);
9234
- }
9235
- const deduplicated = this.deduplicateCandidates(allCandidates);
9236
- return {
9237
- candidates: deduplicated,
9238
- metadata: {
9239
- trajectoriesAnalyzed: trajectories.length,
9240
- durationMs: Date.now() - startTime
9241
- }
9242
- };
8922
+ enable(hookId) {
8923
+ const hook = this.hooks.get(hookId);
8924
+ if (!hook) return false;
8925
+ hook.enabled = true;
8926
+ return true;
9243
8927
  }
9244
8928
  /**
9245
- * Check if a candidate is a duplicate based on name/content similarity
8929
+ * Disable a hook
9246
8930
  */
9247
- isDuplicate(candidate, existing) {
9248
- if (existing.some((e) => e.id === candidate.id)) {
9249
- return true;
9250
- }
9251
- const normalizedName = this.normalizeName(candidate.name);
9252
- for (const e of existing) {
9253
- if (this.normalizeName(e.name) === normalizedName) {
9254
- return true;
9255
- }
9256
- }
9257
- return false;
8931
+ disable(hookId) {
8932
+ const hook = this.hooks.get(hookId);
8933
+ if (!hook) return false;
8934
+ hook.enabled = false;
8935
+ return true;
9258
8936
  }
9259
8937
  /**
9260
- * Compute similarity between two candidates (basic implementation)
8938
+ * Get a hook by ID
9261
8939
  */
9262
- computeSimilarity(a, b) {
9263
- if (a.kind !== b.kind) return 0.1;
9264
- const nameA = this.normalizeName(a.name);
9265
- const nameB = this.normalizeName(b.name);
9266
- const nameSimilarity = this.jaccardSimilarity(
9267
- nameA.split("-"),
9268
- nameB.split("-")
9269
- );
9270
- let contentSimilarity = 0;
9271
- if (a.content.kind === "skill" && b.content.kind === "skill") {
9272
- const aWords = this.tokenize(a.content.problem + " " + a.content.solution);
9273
- const bWords = this.tokenize(b.content.problem + " " + b.content.solution);
9274
- contentSimilarity = this.jaccardSimilarity(aWords, bWords);
9275
- }
9276
- return nameSimilarity * 0.3 + contentSimilarity * 0.7;
8940
+ get(hookId) {
8941
+ return this.hooks.get(hookId);
9277
8942
  }
9278
- // ==========================================================================
9279
- // Private Methods
9280
- // ==========================================================================
9281
8943
  /**
9282
- * Convert an ExtractionResult to a LearningCandidate
9283
- */
9284
- extractionResultToCandidate(result, trajectory) {
9285
- const skill = result.skill;
9286
- const turnRange = result.sourceTrajectory.turnRange;
9287
- return {
9288
- kind: this.inferKind(skill),
9289
- id: skill.id,
9290
- name: skill.name,
9291
- content: this.skillToContent(skill),
9292
- confidence: result.confidence,
9293
- attribution: this.computeAttribution(trajectory, turnRange),
9294
- source: {
9295
- provider: this.name,
9296
- trajectoryId: trajectory.sessionId,
9297
- turnRange,
9298
- extractedAt: /* @__PURE__ */ new Date(),
9299
- metadata: {
9300
- gateResults: result.gateResults,
9301
- extractionMode: this.config.llmProvider ? "automatic" : "manual"
9302
- }
9303
- },
9304
- tags: skill.tags,
9305
- reasoning: result.failureReason
9306
- };
9307
- }
9308
- /**
9309
- * Convert a Skill to LearningContent
9310
- */
9311
- skillToContent(skill) {
9312
- return {
9313
- kind: "skill",
9314
- problem: skill.problem,
9315
- solution: skill.solution,
9316
- verification: skill.verification,
9317
- triggers: skill.triggerConditions.map(
9318
- (t) => ({
9319
- type: t.type,
9320
- value: t.value,
9321
- description: t.description
9322
- })
9323
- ),
9324
- examples: skill.examples.map(
9325
- (e) => ({
9326
- scenario: e.scenario,
9327
- before: e.before,
9328
- after: e.after
9329
- })
9330
- )
9331
- };
9332
- }
9333
- /**
9334
- * Infer the kind of learning from a skill
9335
- */
9336
- inferKind(skill) {
9337
- const hasErrorTriggers = skill.triggerConditions.some(
9338
- (t) => t.type === "error"
9339
- );
9340
- if (hasErrorTriggers && skill.problem.toLowerCase().includes("error")) {
9341
- return "error-fix";
9342
- }
9343
- if (skill.solution.toLowerCase().includes("approach") || skill.solution.toLowerCase().includes("strategy") || skill.solution.toLowerCase().includes("when you see")) {
9344
- return "strategy";
9345
- }
9346
- return "skill";
9347
- }
9348
- /**
9349
- * Compute step attribution using the configured strategy
9350
- */
9351
- computeAttribution(trajectory, turnRange) {
9352
- const [start, end] = turnRange;
9353
- const turns = trajectory.turns.slice(start, end + 1);
9354
- switch (this.config.creditStrategy) {
9355
- case "simple":
9356
- return this.simpleCredit(turns, start);
9357
- case "uniform":
9358
- return this.uniformCredit(turns, start);
9359
- case "llm":
9360
- return this.simpleCredit(turns, start);
9361
- default:
9362
- return this.simpleCredit(turns, start);
9363
- }
9364
- }
9365
- /**
9366
- * Simple credit assignment: exponential decay from end.
9367
- * Last step gets most credit, earlier steps get less.
9368
- */
9369
- simpleCredit(turns, startOffset) {
9370
- const attributions = [];
9371
- const n = turns.length;
9372
- for (let i = 0; i < n; i++) {
9373
- const turn = turns[i];
9374
- if (turn.role === "system") continue;
9375
- const distanceFromEnd = n - 1 - i;
9376
- const score = Math.pow(0.7, distanceFromEnd);
9377
- const hasToolCalls = turn.toolCalls && turn.toolCalls.length > 0;
9378
- const boostedScore = hasToolCalls ? Math.min(1, score * 1.3) : score;
9379
- attributions.push({
9380
- turnIndex: startOffset + i,
9381
- score: Math.round(boostedScore * 100) / 100,
9382
- reasoning: this.getAttributionReasoning(turn, boostedScore)
9383
- });
9384
- }
9385
- return attributions;
9386
- }
9387
- /**
9388
- * Uniform credit assignment: all steps get equal credit.
9389
- */
9390
- uniformCredit(turns, startOffset) {
9391
- const nonSystemTurns = turns.filter((t) => t.role !== "system");
9392
- const score = 1 / nonSystemTurns.length;
9393
- return turns.map((turn, i) => {
9394
- if (turn.role === "system") return null;
9395
- return {
9396
- turnIndex: startOffset + i,
9397
- score: Math.round(score * 100) / 100
9398
- };
9399
- }).filter((a) => a !== null);
9400
- }
9401
- /**
9402
- * Generate reasoning for attribution
9403
- */
9404
- getAttributionReasoning(turn, score) {
9405
- const reasons = [];
9406
- if (score >= 0.8) {
9407
- reasons.push("High impact (near end of solution)");
9408
- } else if (score >= 0.5) {
9409
- reasons.push("Medium impact");
9410
- } else {
9411
- reasons.push("Lower impact (early in trajectory)");
9412
- }
9413
- if (turn.toolCalls && turn.toolCalls.length > 0) {
9414
- const toolNames = turn.toolCalls.map((t) => t.name).join(", ");
9415
- reasons.push(`Used tools: ${toolNames}`);
9416
- }
9417
- if (turn.toolResults?.some((r) => !r.success)) {
9418
- reasons.push("Encountered and handled errors");
9419
- }
9420
- return reasons.join(". ");
9421
- }
9422
- /**
9423
- * Deduplicate candidates by ID
9424
- */
9425
- deduplicateCandidates(candidates) {
9426
- const seen = /* @__PURE__ */ new Map();
9427
- for (const candidate of candidates) {
9428
- const existing = seen.get(candidate.id);
9429
- if (!existing || candidate.confidence > existing.confidence) {
9430
- seen.set(candidate.id, candidate);
9431
- }
9432
- }
9433
- return Array.from(seen.values());
9434
- }
9435
- /**
9436
- * Normalize a name for comparison
9437
- */
9438
- normalizeName(name) {
9439
- return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
9440
- }
9441
- /**
9442
- * Tokenize text into words
9443
- */
9444
- tokenize(text) {
9445
- return text.toLowerCase().split(/\W+/).filter((w) => w.length > 2);
9446
- }
9447
- /**
9448
- * Compute Jaccard similarity between two arrays
9449
- */
9450
- jaccardSimilarity(a, b) {
9451
- const setA = new Set(a);
9452
- const setB = new Set(b);
9453
- const intersection = new Set([...setA].filter((x) => setB.has(x)));
9454
- const union = /* @__PURE__ */ new Set([...setA, ...setB]);
9455
- return union.size === 0 ? 0 : intersection.size / union.size;
9456
- }
9457
- };
9458
- function createNaiveProvider(config) {
9459
- return new NaiveLearningProvider(config);
9460
- }
9461
-
9462
- // src/hooks/registry.ts
9463
- var import_crypto = require("crypto");
9464
- var PRIORITY_ORDER = {
9465
- high: 0,
9466
- normal: 1,
9467
- low: 2
9468
- };
9469
- var HookRegistry = class {
9470
- constructor() {
9471
- this.hooks = /* @__PURE__ */ new Map();
9472
- this.eventIndex = /* @__PURE__ */ new Map();
9473
- }
9474
- /**
9475
- * Register a new hook
9476
- */
9477
- register(options) {
9478
- const id = (0, import_crypto.randomUUID)();
9479
- const events = Array.isArray(options.events) ? options.events : [options.events];
9480
- const hook = {
9481
- id,
9482
- name: options.name,
9483
- events,
9484
- handler: options.handler,
9485
- priority: options.priority || "normal",
9486
- enabled: options.enabled !== false,
9487
- filter: options.filter
9488
- };
9489
- this.hooks.set(id, hook);
9490
- for (const event of events) {
9491
- if (!this.eventIndex.has(event)) {
9492
- this.eventIndex.set(event, /* @__PURE__ */ new Set());
9493
- }
9494
- this.eventIndex.get(event).add(id);
9495
- }
9496
- return id;
9497
- }
9498
- /**
9499
- * Unregister a hook
9500
- */
9501
- unregister(hookId) {
9502
- const hook = this.hooks.get(hookId);
9503
- if (!hook) return false;
9504
- for (const event of hook.events) {
9505
- this.eventIndex.get(event)?.delete(hookId);
9506
- }
9507
- this.hooks.delete(hookId);
9508
- return true;
9509
- }
9510
- /**
9511
- * Enable a hook
9512
- */
9513
- enable(hookId) {
9514
- const hook = this.hooks.get(hookId);
9515
- if (!hook) return false;
9516
- hook.enabled = true;
9517
- return true;
9518
- }
9519
- /**
9520
- * Disable a hook
9521
- */
9522
- disable(hookId) {
9523
- const hook = this.hooks.get(hookId);
9524
- if (!hook) return false;
9525
- hook.enabled = false;
9526
- return true;
9527
- }
9528
- /**
9529
- * Get a hook by ID
9530
- */
9531
- get(hookId) {
9532
- return this.hooks.get(hookId);
9533
- }
9534
- /**
9535
- * List all registered hooks
8944
+ * List all registered hooks
9536
8945
  */
9537
8946
  list() {
9538
8947
  return Array.from(this.hooks.values());
@@ -9931,10 +9340,6 @@ var SkillBank = class {
9931
9340
  this.eventHandlers = [];
9932
9341
  this.initialized = false;
9933
9342
  this.autoIndexOnInit = false;
9934
- /** Learning providers for meta-learning integration */
9935
- this.learningProviders = /* @__PURE__ */ new Map();
9936
- /** Anti-patterns stored separately as metadata */
9937
- this.antiPatterns = /* @__PURE__ */ new Map();
9938
9343
  /** Validation mode: advisory (non-blocking) or blocking */
9939
9344
  this.validationMode = "advisory";
9940
9345
  /** Whether validation is enabled */
@@ -9972,11 +9377,6 @@ var SkillBank = class {
9972
9377
  similarityThreshold: config.matching?.similarityThreshold
9973
9378
  });
9974
9379
  this.autoIndexOnInit = config.matching?.autoIndex ?? false;
9975
- const naiveProvider = new NaiveLearningProvider({
9976
- llmProvider: config.llmProvider,
9977
- minConfidence: config.minExtractionConfidence
9978
- });
9979
- this.learningProviders.set(naiveProvider.name, naiveProvider);
9980
9380
  if (config.namespace) {
9981
9381
  this.namespaceConfig = {
9982
9382
  agentId: config.namespace.agentId,
@@ -10004,11 +9404,6 @@ var SkillBank = class {
10004
9404
  */
10005
9405
  async initialize() {
10006
9406
  await this.storage.initialize();
10007
- for (const provider of this.learningProviders.values()) {
10008
- if (provider.initialize) {
10009
- await provider.initialize();
10010
- }
10011
- }
10012
9407
  if (this.validator) {
10013
9408
  this.validator.setStorage(this.storage);
10014
9409
  }
@@ -10021,11 +9416,6 @@ var SkillBank = class {
10021
9416
  * Shutdown the skill bank cleanly
10022
9417
  */
10023
9418
  async shutdown() {
10024
- for (const provider of this.learningProviders.values()) {
10025
- if (provider.shutdown) {
10026
- await provider.shutdown();
10027
- }
10028
- }
10029
9419
  }
10030
9420
  /**
10031
9421
  * Ensure initialized before operations
@@ -10127,625 +9517,62 @@ var SkillBank = class {
10127
9517
  this.emit({ type: "extraction:started", sessionId: trajectory.sessionId });
10128
9518
  const results = await this.automaticExtractor.extract(trajectory, options);
10129
9519
  for (const result of results) {
10130
- if (result.success && result.skill) {
10131
- const duplicate = await this.findSemanticDuplicate(result.skill);
10132
- if (duplicate) {
10133
- result.success = false;
10134
- result.failureReason = `Duplicate of existing skill: ${duplicate.skill.id} (similarity: ${duplicate.similarity.toFixed(2)})`;
10135
- } else {
10136
- await this.storage.saveSkill(result.skill);
10137
- this.emit({ type: "skill:created", skill: result.skill });
10138
- }
10139
- }
10140
- this.emit({ type: "extraction:completed", result });
10141
- }
10142
- return results;
10143
- }
10144
- /**
10145
- * Unified extraction entry point.
10146
- *
10147
- * Supports both manual (targeted) and automatic (LLM-driven) extraction
10148
- * from a Trajectory. Use this instead of calling extractManual/extractAutomatic
10149
- * directly.
10150
- *
10151
- * @example
10152
- * ```typescript
10153
- * // Manual extraction with defaults
10154
- * const results = await bank.extract(trajectory);
10155
- *
10156
- * // Automatic extraction
10157
- * const results = await bank.extract(trajectory, { mode: 'automatic' });
10158
- *
10159
- * // Manual with specific turn range
10160
- * const results = await bank.extract(trajectory, {
10161
- * mode: 'manual',
10162
- * turnRange: [0, 5],
10163
- * suggestedName: 'fix-auth-error',
10164
- * });
10165
- * ```
10166
- */
10167
- async extract(trajectory, options) {
10168
- if (options?.mode === "automatic") {
10169
- return this.extractAutomatic(trajectory, options);
10170
- }
10171
- const result = await this.extractManual(trajectory, options);
10172
- return [result];
10173
- }
10174
- /**
10175
- * Extract from raw session content (convenience method)
10176
- */
10177
- async extractFromSession(content, options) {
10178
- const trajectory = await this.parseSession(content, options?.adapterName);
10179
- return this.extract(trajectory, options);
10180
- }
10181
- /**
10182
- * Set LLM provider for automatic extraction
10183
- */
10184
- setLLMProvider(provider) {
10185
- this.automaticExtractor.setLLMProvider(provider);
10186
- const naiveProvider = this.learningProviders.get("naive");
10187
- if (naiveProvider && "setLLMProvider" in naiveProvider) {
10188
- naiveProvider.setLLMProvider(provider);
10189
- }
10190
- }
10191
- // ==========================================================================
10192
- // Learning Providers (Meta-learning Integration)
10193
- // ==========================================================================
10194
- /**
10195
- * Register a learning provider.
10196
- * Learning providers analyze trajectories and produce learning candidates.
10197
- * Use this to integrate external learning engines like cognitive-core.
10198
- */
10199
- async registerLearningProvider(provider) {
10200
- if (provider.initialize) {
10201
- await provider.initialize();
10202
- }
10203
- this.learningProviders.set(provider.name, provider);
10204
- }
10205
- /**
10206
- * Get a registered learning provider by name
10207
- */
10208
- getLearningProvider(name) {
10209
- return this.learningProviders.get(name);
10210
- }
10211
- /**
10212
- * List all registered learning providers
10213
- */
10214
- listLearningProviders() {
10215
- return Array.from(this.learningProviders.values());
10216
- }
10217
- /**
10218
- * Learn from a trajectory using a learning provider.
10219
- * This is the primary integration point for meta-learning engines.
10220
- *
10221
- * For accumulating providers, this may not return immediate results.
10222
- * Use flushProviders() to force extraction from accumulated trajectories.
10223
- */
10224
- async learnFrom(trajectory, options) {
10225
- this.ensureInitialized();
10226
- const providerName = options?.provider ?? "naive";
10227
- const provider = this.learningProviders.get(providerName);
10228
- if (!provider) {
10229
- throw new Error(
10230
- `Learning provider not found: ${providerName}. Available: ${Array.from(this.learningProviders.keys()).join(", ")}`
10231
- );
10232
- }
10233
- const result = await provider.analyze(trajectory, options);
10234
- return this.processAnalyzeResult(result);
10235
- }
10236
- /**
10237
- * Learn from multiple trajectories.
10238
- * Providers that support batch analysis can find cross-trajectory patterns.
10239
- */
10240
- async learnFromBatch(trajectories, options) {
10241
- this.ensureInitialized();
10242
- const providerName = options?.provider ?? "naive";
10243
- const provider = this.learningProviders.get(providerName);
10244
- if (!provider) {
10245
- throw new Error(`Learning provider not found: ${providerName}`);
10246
- }
10247
- let result;
10248
- if (provider.analyzeBatch) {
10249
- result = await provider.analyzeBatch(trajectories, options);
10250
- } else {
10251
- const candidates = [];
10252
- const updates = [];
10253
- const demotions = [];
10254
- const antiPatterns = [];
10255
- let totalDuration = 0;
10256
- for (const trajectory of trajectories) {
10257
- const r = await provider.analyze(trajectory, options);
10258
- candidates.push(...r.candidates);
10259
- if (r.updates) updates.push(...r.updates);
10260
- if (r.demotions) demotions.push(...r.demotions);
10261
- if (r.antiPatterns) antiPatterns.push(...r.antiPatterns);
10262
- totalDuration += r.metadata.durationMs;
10263
- }
10264
- result = {
10265
- candidates,
10266
- updates: updates.length > 0 ? updates : void 0,
10267
- demotions: demotions.length > 0 ? demotions : void 0,
10268
- antiPatterns: antiPatterns.length > 0 ? antiPatterns : void 0,
10269
- metadata: {
10270
- trajectoriesAnalyzed: trajectories.length,
10271
- durationMs: totalDuration
10272
- }
10273
- };
10274
- }
10275
- return this.processAnalyzeResult(result);
10276
- }
10277
- /**
10278
- * Force extraction from all accumulating providers.
10279
- */
10280
- async flushProviders() {
10281
- this.ensureInitialized();
10282
- const mergedResult = {
10283
- skillsCreated: 0,
10284
- skillsUpdated: 0,
10285
- skillsDemoted: 0,
10286
- antiPatternsAdded: 0,
10287
- createdSkillIds: [],
10288
- updatedSkillIds: []
10289
- };
10290
- for (const provider of this.learningProviders.values()) {
10291
- if (provider.capabilities.accumulating && provider.flush) {
10292
- const result = await provider.flush();
10293
- const processed = await this.processAnalyzeResult(result);
10294
- mergedResult.skillsCreated += processed.skillsCreated;
10295
- mergedResult.skillsUpdated += processed.skillsUpdated;
10296
- mergedResult.skillsDemoted += processed.skillsDemoted;
10297
- mergedResult.antiPatternsAdded += processed.antiPatternsAdded;
10298
- mergedResult.createdSkillIds.push(...processed.createdSkillIds);
10299
- mergedResult.updatedSkillIds.push(...processed.updatedSkillIds);
10300
- }
10301
- }
10302
- return mergedResult;
10303
- }
10304
- /**
10305
- * Record outcome when a skill is applied.
10306
- * Provider updates internal state and returns updates for SkillBank.
10307
- */
10308
- async recordOutcome(feedback, providerName) {
10309
- this.ensureInitialized();
10310
- const skill = await this.storage.getSkill(feedback.candidateId);
10311
- if (skill) {
10312
- skill.metrics.usageCount++;
10313
- if (feedback.success) {
10314
- const totalUses = skill.metrics.usageCount;
10315
- const currentSuccesses = skill.metrics.successRate * (totalUses - 1);
10316
- skill.metrics.successRate = (currentSuccesses + 1) / totalUses;
10317
- } else {
10318
- const totalUses = skill.metrics.usageCount;
10319
- const currentSuccesses = skill.metrics.successRate * (totalUses - 1);
10320
- skill.metrics.successRate = currentSuccesses / totalUses;
10321
- }
10322
- skill.metrics.lastUsed = /* @__PURE__ */ new Date();
10323
- await this.storage.saveSkill(skill);
10324
- }
10325
- const providersToNotify = providerName ? [this.learningProviders.get(providerName)].filter(Boolean) : Array.from(this.learningProviders.values());
10326
- for (const provider of providersToNotify) {
10327
- if (provider.capabilities.feedbackEnabled && provider.recordOutcome) {
10328
- const result = await provider.recordOutcome(feedback);
10329
- if (result.updates) {
10330
- for (const update of result.updates) {
10331
- await this.applyUpdate(update);
10332
- }
10333
- }
10334
- if (result.antiPatterns) {
10335
- for (const ap of result.antiPatterns) {
10336
- await this.addAntiPattern(ap);
10337
- }
10338
- }
10339
- }
10340
- }
10341
- }
10342
- /**
10343
- * Process an AnalyzeResult: store candidates, apply updates, etc.
10344
- */
10345
- async processAnalyzeResult(result) {
10346
- const learnResult = {
10347
- skillsCreated: 0,
10348
- skillsUpdated: 0,
10349
- skillsDemoted: 0,
10350
- antiPatternsAdded: 0,
10351
- providerState: result.providerState,
10352
- createdSkillIds: [],
10353
- updatedSkillIds: []
10354
- };
10355
- for (const candidate of result.candidates) {
10356
- if (candidate.content.kind === "skill") {
10357
- const skill = await this.promoteToSkill(candidate);
10358
- learnResult.skillsCreated++;
10359
- learnResult.createdSkillIds.push(skill.id);
10360
- } else {
10361
- await this.storeCandidateForReview(candidate);
10362
- }
10363
- }
10364
- if (result.updates) {
10365
- for (const update of result.updates) {
10366
- const updated = await this.applyUpdate(update);
10367
- if (updated) {
10368
- learnResult.skillsUpdated++;
10369
- learnResult.updatedSkillIds.push(update.candidateId);
10370
- }
10371
- }
10372
- }
10373
- if (result.demotions) {
10374
- for (const demotion of result.demotions) {
10375
- await this.applyDemotion(demotion);
10376
- learnResult.skillsDemoted++;
10377
- }
10378
- }
10379
- if (result.antiPatterns) {
10380
- for (const ap of result.antiPatterns) {
10381
- await this.addAntiPattern(ap);
10382
- learnResult.antiPatternsAdded++;
10383
- }
10384
- }
10385
- return learnResult;
10386
- }
10387
- /**
10388
- * Store a non-skill candidate for later review
10389
- */
10390
- async storeCandidateForReview(candidate) {
10391
- if (!this.storage.saveCandidate) {
10392
- return;
10393
- }
10394
- const record = {
10395
- id: candidate.id,
10396
- kind: candidate.kind,
10397
- name: candidate.name,
10398
- content: candidate.content,
10399
- confidence: candidate.confidence,
10400
- source: {
10401
- trajectoryId: candidate.source.trajectoryId,
10402
- provider: candidate.source.provider,
10403
- extractedAt: candidate.source.extractedAt,
10404
- turnRange: candidate.source.turnRange
10405
- },
10406
- tags: candidate.tags,
10407
- reasoning: candidate.reasoning,
10408
- createdAt: /* @__PURE__ */ new Date(),
10409
- updatedAt: /* @__PURE__ */ new Date(),
10410
- status: "pending"
10411
- };
10412
- await this.storage.saveCandidate(record);
10413
- }
10414
- /**
10415
- * Apply an update to an existing skill
10416
- */
10417
- async applyUpdate(update) {
10418
- const skill = await this.storage.getSkill(update.candidateId);
10419
- if (!skill) return false;
10420
- let modified = false;
10421
- if (update.addTrigger) {
10422
- const exists = skill.triggerConditions.some(
10423
- (t) => t.type === update.addTrigger.type && t.value === update.addTrigger.value
10424
- );
10425
- if (!exists) {
10426
- skill.triggerConditions.push({
10427
- type: update.addTrigger.type,
10428
- value: update.addTrigger.value,
10429
- description: update.addTrigger.description
10430
- });
10431
- modified = true;
10432
- }
10433
- }
10434
- if (update.refinement) {
10435
- const refinementNote = `[${update.refinement.source}] ${update.refinement.context}: ${update.refinement.addition}`;
10436
- skill.notes = skill.notes ? `${skill.notes}
10437
- ${refinementNote}` : refinementNote;
10438
- modified = true;
10439
- }
10440
- if (update.confidenceAdjustment) {
10441
- skill.metrics.successRate = Math.max(
10442
- 0,
10443
- Math.min(1, skill.metrics.successRate + update.confidenceAdjustment)
10444
- );
10445
- modified = true;
10446
- }
10447
- if (update.incrementSuccess || update.incrementFailure) {
10448
- skill.metrics.usageCount++;
10449
- if (update.incrementSuccess) {
10450
- const total = skill.metrics.usageCount;
10451
- const currentSuccesses = skill.metrics.successRate * (total - 1);
10452
- skill.metrics.successRate = (currentSuccesses + 1) / total;
10453
- }
10454
- modified = true;
10455
- }
10456
- if (modified) {
10457
- skill.updatedAt = /* @__PURE__ */ new Date();
10458
- await this.storage.saveSkill(skill);
10459
- this.emit({ type: "skill:updated", skill, previousVersion: skill.version });
10460
- }
10461
- return modified;
10462
- }
10463
- /**
10464
- * Apply a demotion to an existing skill
10465
- */
10466
- async applyDemotion(demotion) {
10467
- const skill = await this.storage.getSkill(demotion.candidateId);
10468
- if (!skill) return;
10469
- skill.metrics.successRate = demotion.newConfidence;
10470
- if (demotion.deprecate) {
10471
- skill.status = "deprecated";
10472
- this.emit({ type: "skill:deprecated", skillId: skill.id });
10473
- }
10474
- skill.notes = skill.notes ? `${skill.notes}
10475
- [demotion] ${demotion.reason}` : `[demotion] ${demotion.reason}`;
10476
- skill.updatedAt = /* @__PURE__ */ new Date();
10477
- await this.storage.saveSkill(skill);
10478
- }
10479
- // ==========================================================================
10480
- // Anti-Pattern Management
10481
- // ==========================================================================
10482
- /**
10483
- * Get anti-patterns for a skill
10484
- */
10485
- async getAntiPatterns(skillId) {
10486
- return this.antiPatterns.get(skillId) ?? [];
10487
- }
10488
- /**
10489
- * Add an anti-pattern
10490
- */
10491
- async addAntiPattern(antiPattern) {
10492
- const existing = this.antiPatterns.get(antiPattern.candidateId) ?? [];
10493
- existing.push(antiPattern);
10494
- this.antiPatterns.set(antiPattern.candidateId, existing);
10495
- if (this.storage.saveAntiPatterns) {
10496
- const records = existing.map((ap) => ({
10497
- id: ap.id,
10498
- pattern: ap.pattern,
10499
- description: ap.reason,
10500
- context: ap.discoveredFrom,
10501
- severity: "warning",
10502
- learnedAt: ap.createdAt,
10503
- occurrences: 1
10504
- }));
10505
- await this.storage.saveAntiPatterns(antiPattern.candidateId, records);
10506
- }
10507
- }
10508
- /**
10509
- * Remove an anti-pattern by ID
10510
- */
10511
- async removeAntiPattern(antiPatternId) {
10512
- for (const [skillId, patterns] of this.antiPatterns.entries()) {
10513
- const index = patterns.findIndex((p) => p.id === antiPatternId);
10514
- if (index >= 0) {
10515
- patterns.splice(index, 1);
10516
- if (patterns.length === 0) {
10517
- this.antiPatterns.delete(skillId);
10518
- }
10519
- return true;
10520
- }
10521
- }
10522
- return false;
10523
- }
10524
- // ==========================================================================
10525
- // Candidate Lifecycle Management
10526
- // ==========================================================================
10527
- /**
10528
- * List pending learning candidates for review
10529
- */
10530
- async listCandidates(filter) {
10531
- this.ensureInitialized();
10532
- if (!this.storage.listCandidates) {
10533
- return [];
10534
- }
10535
- return this.storage.listCandidates(filter);
10536
- }
10537
- /**
10538
- * Get a specific candidate by ID
10539
- */
10540
- async getCandidate(id) {
10541
- this.ensureInitialized();
10542
- if (!this.storage.getCandidate) {
10543
- return null;
10544
- }
10545
- return this.storage.getCandidate(id);
10546
- }
10547
- /**
10548
- * Promote a candidate to a skill
10549
- * Works for strategy, pattern, and error-fix candidates that were stored for review
10550
- */
10551
- async promoteCandidate(candidateId) {
10552
- this.ensureInitialized();
10553
- if (!this.storage.getCandidate || !this.storage.updateCandidateStatus) {
10554
- throw new Error("Storage does not support candidate operations");
10555
- }
10556
- const record = await this.storage.getCandidate(candidateId);
10557
- if (!record) return null;
10558
- if (record.status !== "pending") {
10559
- throw new Error(`Cannot promote candidate with status: ${record.status}`);
10560
- }
10561
- const candidate = {
10562
- id: record.id,
10563
- kind: record.kind,
10564
- name: record.name,
10565
- content: record.content,
10566
- confidence: record.confidence,
10567
- source: {
10568
- provider: record.source.provider,
10569
- trajectoryId: record.source.trajectoryId,
10570
- extractedAt: record.source.extractedAt,
10571
- turnRange: record.source.turnRange ?? [0, 0]
10572
- },
10573
- tags: record.tags,
10574
- reasoning: record.reasoning
10575
- };
10576
- const skill = await this.promoteToSkill(candidate);
10577
- await this.storage.updateCandidateStatus(candidateId, "promoted", {
10578
- promotedToSkillId: skill.id
10579
- });
10580
- return skill;
10581
- }
10582
- /**
10583
- * Reject a candidate with a reason
10584
- */
10585
- async rejectCandidate(candidateId, reason) {
10586
- this.ensureInitialized();
10587
- if (!this.storage.updateCandidateStatus) {
10588
- throw new Error("Storage does not support candidate operations");
10589
- }
10590
- return this.storage.updateCandidateStatus(candidateId, "rejected", {
10591
- rejectionReason: reason
10592
- });
10593
- }
10594
- /**
10595
- * Delete a candidate
10596
- */
10597
- async deleteCandidate(candidateId) {
10598
- this.ensureInitialized();
10599
- if (!this.storage.deleteCandidate) {
10600
- return false;
10601
- }
10602
- return this.storage.deleteCandidate(candidateId);
10603
- }
10604
- /**
10605
- * Find skills with anti-pattern awareness
10606
- */
10607
- async findSkillsWithAntiPatterns(query, options) {
10608
- this.ensureInitialized();
10609
- const skills = await this.storage.listSkills({ status: ["active"] });
10610
- const matches = await this.semanticMatcher.findMatches(query, skills, {
10611
- threshold: options?.minSimilarity,
10612
- maxResults: options?.maxResults
10613
- });
10614
- const results = [];
10615
- for (const match of matches) {
10616
- const skillAntiPatterns = await this.getAntiPatterns(match.skill.id);
10617
- const warnings = [];
10618
- let relevantAntiPatterns;
10619
- if (options?.context && skillAntiPatterns.length > 0) {
10620
- relevantAntiPatterns = skillAntiPatterns.filter(
10621
- (ap) => options.context.toLowerCase().includes(ap.pattern.toLowerCase())
10622
- );
10623
- if (relevantAntiPatterns.length > 0) {
10624
- warnings.push(
10625
- `This skill has failed in similar contexts: ${relevantAntiPatterns.map((ap) => ap.reason).join("; ")}`
10626
- );
9520
+ if (result.success && result.skill) {
9521
+ const duplicate = await this.findSemanticDuplicate(result.skill);
9522
+ if (duplicate) {
9523
+ result.success = false;
9524
+ result.failureReason = `Duplicate of existing skill: ${duplicate.skill.id} (similarity: ${duplicate.similarity.toFixed(2)})`;
9525
+ } else {
9526
+ await this.storage.saveSkill(result.skill);
9527
+ this.emit({ type: "skill:created", skill: result.skill });
10627
9528
  }
10628
9529
  }
10629
- if (options?.excludeAntiPatternMatches && relevantAntiPatterns && relevantAntiPatterns.length > 0) {
10630
- continue;
10631
- }
10632
- if (match.skill.metrics.successRate < 0.5 && match.skill.metrics.usageCount > 2) {
10633
- warnings.push(`Low success rate: ${Math.round(match.skill.metrics.successRate * 100)}%`);
10634
- }
10635
- results.push({
10636
- ...match,
10637
- relevantAntiPatterns: relevantAntiPatterns && relevantAntiPatterns.length > 0 ? relevantAntiPatterns : void 0,
10638
- warnings: warnings.length > 0 ? warnings : void 0
10639
- });
9530
+ this.emit({ type: "extraction:completed", result });
10640
9531
  }
10641
9532
  return results;
10642
9533
  }
10643
- // ==========================================================================
10644
- // Legacy Learning Methods (backwards compatibility)
10645
- // ==========================================================================
10646
9534
  /**
10647
- * Extract learning candidates from a trajectory using a learning provider.
10648
- * @deprecated Use learnFrom() instead
9535
+ * Unified extraction entry point.
9536
+ *
9537
+ * Supports both manual (targeted) and automatic (LLM-driven) extraction
9538
+ * from a Trajectory. Use this instead of calling extractManual/extractAutomatic
9539
+ * directly.
9540
+ *
9541
+ * @example
9542
+ * ```typescript
9543
+ * // Manual extraction with defaults
9544
+ * const results = await bank.extract(trajectory);
9545
+ *
9546
+ * // Automatic extraction
9547
+ * const results = await bank.extract(trajectory, { mode: 'automatic' });
9548
+ *
9549
+ * // Manual with specific turn range
9550
+ * const results = await bank.extract(trajectory, {
9551
+ * mode: 'manual',
9552
+ * turnRange: [0, 5],
9553
+ * suggestedName: 'fix-auth-error',
9554
+ * });
9555
+ * ```
10649
9556
  */
10650
- async extractLearnings(trajectory, options) {
10651
- this.ensureInitialized();
10652
- const providerName = options?.provider ?? "naive";
10653
- const provider = this.learningProviders.get(providerName);
10654
- if (!provider) {
10655
- throw new Error(
10656
- `Learning provider not found: ${providerName}. Available: ${Array.from(this.learningProviders.keys()).join(", ")}`
10657
- );
9557
+ async extract(trajectory, options) {
9558
+ if (options?.mode === "automatic") {
9559
+ return this.extractAutomatic(trajectory, options);
10658
9560
  }
10659
- const result = await provider.analyze(trajectory, options);
10660
- return result.candidates;
9561
+ const result = await this.extractManual(trajectory, options);
9562
+ return [result];
10661
9563
  }
10662
9564
  /**
10663
- * Extract learning candidates from multiple trajectories.
10664
- * @deprecated Use learnFromBatch() instead
9565
+ * Extract from raw session content (convenience method)
10665
9566
  */
10666
- async extractLearningsBatch(trajectories, options) {
10667
- this.ensureInitialized();
10668
- const providerName = options?.provider ?? "naive";
10669
- const provider = this.learningProviders.get(providerName);
10670
- if (!provider) {
10671
- throw new Error(`Learning provider not found: ${providerName}`);
10672
- }
10673
- if (provider.analyzeBatch) {
10674
- const result = await provider.analyzeBatch(trajectories, options);
10675
- return result.candidates;
10676
- }
10677
- const allCandidates = [];
10678
- for (const trajectory of trajectories) {
10679
- const result = await provider.analyze(trajectory, options);
10680
- allCandidates.push(...result.candidates);
10681
- }
10682
- return allCandidates;
9567
+ async extractFromSession(content, options) {
9568
+ const trajectory = await this.parseSession(content, options?.adapterName);
9569
+ return this.extract(trajectory, options);
10683
9570
  }
10684
9571
  /**
10685
- * Promote a learning candidate to a versioned skill.
10686
- * This converts the raw learning into a curated, versioned skill.
9572
+ * Set LLM provider for automatic extraction
10687
9573
  */
10688
- async promoteToSkill(candidate, options) {
10689
- this.ensureInitialized();
10690
- if (candidate.content.kind !== "skill") {
10691
- throw new Error(
10692
- `Cannot promote ${candidate.content.kind} to skill directly. Only 'skill' kind is supported.`
10693
- );
10694
- }
10695
- const agentId = this.activationManager.getCurrentAgentId();
10696
- const agentMetadata = this.activationManager.getAgentMetadata();
10697
- const agentName = agentMetadata?.agentName;
10698
- const content = candidate.content;
10699
- const skill = {
10700
- id: candidate.id,
10701
- name: candidate.name,
10702
- version: "1.0.0",
10703
- description: content.problem.substring(0, 150),
10704
- problem: content.problem,
10705
- triggerConditions: (content.triggers ?? []).map((t) => ({
10706
- type: t.type,
10707
- value: t.value,
10708
- description: t.description
10709
- })),
10710
- solution: content.solution,
10711
- verification: content.verification,
10712
- examples: (content.examples ?? []).map((e) => ({
10713
- scenario: e.scenario,
10714
- before: e.before,
10715
- after: e.after
10716
- })),
10717
- author: options?.author ?? agentName ?? candidate.source.provider,
10718
- tags: options?.tags ?? candidate.tags ?? [],
10719
- createdAt: /* @__PURE__ */ new Date(),
10720
- updatedAt: /* @__PURE__ */ new Date(),
10721
- status: options?.status ?? "draft",
10722
- metrics: {
10723
- usageCount: 0,
10724
- successRate: candidate.confidence,
10725
- feedbackScores: []
10726
- },
10727
- source: {
10728
- type: "extracted",
10729
- sessionId: candidate.source.trajectoryId,
10730
- importedAt: candidate.source.extractedAt,
10731
- agentId,
10732
- agentName
10733
- }
10734
- };
10735
- skill.serving = computeServingMetadata(skill);
10736
- await this.storage.saveSkill(skill);
10737
- this.emit({ type: "skill:created", skill });
10738
- if (this.validationEnabled && this.validator) {
10739
- this.runValidationAsync(skill).catch((err) => {
10740
- console.error("Validation error:", err);
10741
- });
10742
- }
10743
- if (this.compositionEnabled && this.composer) {
10744
- this.runCompositionSuggestionsAsync(skill).catch((err) => {
10745
- console.error("Composition suggestion error:", err);
10746
- });
10747
- }
10748
- return skill;
9574
+ setLLMProvider(provider) {
9575
+ this.automaticExtractor.setLLMProvider(provider);
10749
9576
  }
10750
9577
  /**
10751
9578
  * Validate a skill and store the result
@@ -11204,7 +10031,6 @@ ${refinementNote}` : refinementNote;
11204
10031
  const deleted = await this.storage.deleteSkill(id, version);
11205
10032
  if (deleted) {
11206
10033
  this.emit({ type: "skill:deleted", skillId: id });
11207
- this.antiPatterns.delete(id);
11208
10034
  }
11209
10035
  return deleted;
11210
10036
  }
@@ -11678,8 +10504,7 @@ ${refinementNote}` : refinementNote;
11678
10504
  },
11679
10505
  byTag: {},
11680
10506
  avgSuccessRate: 0,
11681
- totalUsage: 0,
11682
- totalAntiPatterns: 0
10507
+ totalUsage: 0
11683
10508
  };
11684
10509
  if (this.namespaceConfig) {
11685
10510
  stats.byScope = { personal: 0, team: 0, global: 0 };
@@ -11697,10 +10522,6 @@ ${refinementNote}` : refinementNote;
11697
10522
  successRateSum += skill.metrics.successRate;
11698
10523
  successRateCount++;
11699
10524
  }
11700
- const ap = this.antiPatterns.get(skill.id);
11701
- if (ap) {
11702
- stats.totalAntiPatterns += ap.length;
11703
- }
11704
10525
  if (stats.byScope && stats.byVisibility) {
11705
10526
  const scope = skill.namespace?.scope || "personal";
11706
10527
  const visibility = skill.namespace?.visibility || "private";
@@ -13910,509 +12731,6 @@ function conditionalHook(filter, handler) {
13910
12731
  };
13911
12732
  }
13912
12733
 
13913
- // src/learning/providers/cognitive-core.ts
13914
- var CognitiveCoreProvider = class {
13915
- constructor(options) {
13916
- this.name = "cognitive-core";
13917
- this.description = "Advanced learning using cognitive-core with batch extraction and feedback";
13918
- this.capabilities = {
13919
- accumulating: true,
13920
- feedbackEnabled: true,
13921
- persistent: true,
13922
- minTrajectories: 5,
13923
- supportedKinds: ["skill", "strategy", "pattern", "error-fix"]
13924
- };
13925
- this.initialized = false;
13926
- // ID mapping: playbook.id <-> candidate.id
13927
- // For cognitive-core, we use playbook.id as the candidate.id directly
13928
- this.playbookIdCache = /* @__PURE__ */ new Map();
13929
- this.factory = options.factory;
13930
- this.config = {
13931
- storagePath: options.storagePath ?? "./.cognitive-core",
13932
- minTrajectories: options.minTrajectories ?? 5,
13933
- deduplicationThreshold: options.deduplicationThreshold ?? 0.85,
13934
- creditStrategy: options.creditStrategy ?? "simple",
13935
- convertToReAct: options.convertToReAct ?? true
13936
- };
13937
- this.memory = this.factory.createMemorySystem(this.config.storagePath);
13938
- this.pipeline = this.factory.createLearningPipeline(this.memory, {
13939
- creditStrategy: this.config.creditStrategy,
13940
- minTrajectories: this.config.minTrajectories,
13941
- deduplicationThreshold: this.config.deduplicationThreshold
13942
- });
13943
- }
13944
- /**
13945
- * Initialize the provider (load persisted state)
13946
- */
13947
- async initialize() {
13948
- if (this.initialized) return;
13949
- await this.memory.init();
13950
- this.initialized = true;
13951
- }
13952
- /**
13953
- * Shutdown cleanly (persist state, release resources)
13954
- */
13955
- async shutdown() {
13956
- await this.memory.close();
13957
- this.initialized = false;
13958
- }
13959
- /**
13960
- * Analyze a trajectory and accumulate for batch learning.
13961
- * Returns empty candidates until flush() or batch threshold.
13962
- */
13963
- async analyze(trajectory, options) {
13964
- await this.initialize();
13965
- const startTime = Date.now();
13966
- const ccTrajectory = this.convertTrajectory(trajectory, options);
13967
- await this.pipeline.processTrajectory(ccTrajectory);
13968
- let candidates = [];
13969
- let updates = [];
13970
- let demotions = [];
13971
- let antiPatterns = [];
13972
- if (options?.forceImmediate || this.pipeline.shouldRunBatch()) {
13973
- const batchResult = await this.runBatchExtraction(options);
13974
- candidates = batchResult.candidates;
13975
- updates = batchResult.updates ?? [];
13976
- demotions = batchResult.demotions ?? [];
13977
- antiPatterns = batchResult.antiPatterns ?? [];
13978
- }
13979
- return {
13980
- candidates,
13981
- updates: updates.length > 0 ? updates : void 0,
13982
- demotions: demotions.length > 0 ? demotions : void 0,
13983
- antiPatterns: antiPatterns.length > 0 ? antiPatterns : void 0,
13984
- providerState: {
13985
- pendingCount: this.pipeline.getAccumulatedCount(),
13986
- readyForFlush: this.pipeline.shouldRunBatch()
13987
- },
13988
- metadata: {
13989
- trajectoriesAnalyzed: 1,
13990
- durationMs: Date.now() - startTime
13991
- }
13992
- };
13993
- }
13994
- /**
13995
- * Analyze multiple trajectories together.
13996
- * Enables better cross-trajectory pattern detection.
13997
- */
13998
- async analyzeBatch(trajectories, options) {
13999
- await this.initialize();
14000
- const startTime = Date.now();
14001
- for (const trajectory of trajectories) {
14002
- const ccTrajectory = this.convertTrajectory(trajectory, options);
14003
- await this.pipeline.processTrajectory(ccTrajectory);
14004
- }
14005
- const batchResult = await this.runBatchExtraction(options);
14006
- return {
14007
- candidates: batchResult.candidates,
14008
- updates: batchResult.updates,
14009
- demotions: batchResult.demotions,
14010
- antiPatterns: batchResult.antiPatterns,
14011
- providerState: {
14012
- pendingCount: this.pipeline.getAccumulatedCount(),
14013
- readyForFlush: this.pipeline.shouldRunBatch()
14014
- },
14015
- metadata: {
14016
- trajectoriesAnalyzed: trajectories.length,
14017
- durationMs: Date.now() - startTime
14018
- }
14019
- };
14020
- }
14021
- /**
14022
- * Force extraction from accumulated trajectories.
14023
- */
14024
- async flush(options) {
14025
- await this.initialize();
14026
- const startTime = Date.now();
14027
- const pendingCount = this.pipeline.getAccumulatedCount();
14028
- const batchResult = await this.runBatchExtraction(options);
14029
- return {
14030
- ...batchResult,
14031
- metadata: {
14032
- trajectoriesAnalyzed: pendingCount,
14033
- durationMs: Date.now() - startTime
14034
- }
14035
- };
14036
- }
14037
- /**
14038
- * Record outcome when a candidate/playbook is applied.
14039
- * Updates playbook confidence and may generate refinements.
14040
- */
14041
- async recordOutcome(feedback) {
14042
- await this.initialize();
14043
- const playbookId = feedback.candidateId;
14044
- const playbook = await this.memory.playbooks.get(playbookId);
14045
- if (!playbook) {
14046
- return { recorded: false };
14047
- }
14048
- await this.memory.recordPlaybookUsage(
14049
- playbookId,
14050
- feedback.trajectoryId,
14051
- feedback.success,
14052
- feedback.context,
14053
- feedback.failureMode
14054
- );
14055
- const updates = [];
14056
- const antiPatterns = [];
14057
- if (feedback.success) {
14058
- updates.push({
14059
- candidateId: playbookId,
14060
- incrementSuccess: true,
14061
- confidenceAdjustment: 0.05
14062
- // Slight boost on success
14063
- });
14064
- } else {
14065
- updates.push({
14066
- candidateId: playbookId,
14067
- incrementFailure: true,
14068
- confidenceAdjustment: -0.1
14069
- // Decrease confidence on failure
14070
- });
14071
- if (feedback.context || feedback.failureMode) {
14072
- antiPatterns.push({
14073
- id: `anti-${playbookId}-${Date.now()}`,
14074
- candidateId: playbookId,
14075
- pattern: feedback.context ?? "Unknown context",
14076
- reason: feedback.failureMode ?? "Unknown failure mode",
14077
- discoveredFrom: feedback.trajectoryId,
14078
- createdAt: /* @__PURE__ */ new Date()
14079
- });
14080
- }
14081
- }
14082
- return {
14083
- recorded: true,
14084
- updates: updates.length > 0 ? updates : void 0,
14085
- antiPatterns: antiPatterns.length > 0 ? antiPatterns : void 0
14086
- };
14087
- }
14088
- /**
14089
- * Check if a candidate is a duplicate based on playbook similarity
14090
- */
14091
- isDuplicate(candidate, existing) {
14092
- if (existing.some((e) => e.id === candidate.id)) {
14093
- return true;
14094
- }
14095
- for (const e of existing) {
14096
- const similarity = this.computeSimilarity(candidate, e);
14097
- if (similarity > this.config.deduplicationThreshold) {
14098
- return true;
14099
- }
14100
- }
14101
- return false;
14102
- }
14103
- /**
14104
- * Compute similarity between two candidates
14105
- */
14106
- computeSimilarity(a, b) {
14107
- if (a.kind !== b.kind) return 0.1;
14108
- const nameA = this.tokenize(a.name);
14109
- const nameB = this.tokenize(b.name);
14110
- const nameSimilarity = this.jaccardSimilarity(nameA, nameB);
14111
- let contentSimilarity = 0;
14112
- if (a.content.kind === "skill" && b.content.kind === "skill") {
14113
- const aWords = this.tokenize(a.content.problem + " " + a.content.solution);
14114
- const bWords = this.tokenize(b.content.problem + " " + b.content.solution);
14115
- contentSimilarity = this.jaccardSimilarity(aWords, bWords);
14116
- }
14117
- return nameSimilarity * 0.3 + contentSimilarity * 0.7;
14118
- }
14119
- // ==========================================================================
14120
- // Private Methods
14121
- // ==========================================================================
14122
- /**
14123
- * Run batch extraction and convert results to LearningCandidates
14124
- */
14125
- async runBatchExtraction(options) {
14126
- await this.pipeline.runBatchLearning();
14127
- const allPlaybooks = await this.memory.playbooks.getAll();
14128
- const candidates = [];
14129
- const updates = [];
14130
- const demotions = [];
14131
- const antiPatterns = [];
14132
- const minConfidence = options?.minConfidence ?? 0;
14133
- const requestedKinds = options?.kinds;
14134
- for (const playbook of allPlaybooks) {
14135
- if (!this.playbookIdCache.has(playbook.id)) {
14136
- const candidate = this.playbookToCandidate(playbook);
14137
- if (candidate.confidence < minConfidence) {
14138
- continue;
14139
- }
14140
- if (requestedKinds && !requestedKinds.includes(candidate.kind)) {
14141
- continue;
14142
- }
14143
- candidates.push(candidate);
14144
- this.playbookIdCache.set(playbook.id, true);
14145
- }
14146
- const successRate = playbook.evolution.successCount + playbook.evolution.failureCount > 0 ? playbook.evolution.successCount / (playbook.evolution.successCount + playbook.evolution.failureCount) : 1;
14147
- if (successRate < 0.3 && playbook.evolution.successCount + playbook.evolution.failureCount >= 3) {
14148
- demotions.push({
14149
- candidateId: playbook.id,
14150
- reason: `Low success rate: ${Math.round(successRate * 100)}%`,
14151
- newConfidence: successRate,
14152
- deprecate: successRate < 0.1
14153
- });
14154
- }
14155
- for (const antiPattern of playbook.applicability.antiPatterns) {
14156
- antiPatterns.push({
14157
- id: `anti-${playbook.id}-${antiPattern.slice(0, 10)}`,
14158
- candidateId: playbook.id,
14159
- pattern: antiPattern,
14160
- reason: "Learned from playbook applicability",
14161
- discoveredFrom: playbook.evolution.createdFrom[0] ?? "unknown",
14162
- createdAt: playbook.createdAt
14163
- });
14164
- }
14165
- }
14166
- return {
14167
- candidates,
14168
- updates: updates.length > 0 ? updates : void 0,
14169
- demotions: demotions.length > 0 ? demotions : void 0,
14170
- antiPatterns: antiPatterns.length > 0 ? antiPatterns : void 0,
14171
- providerState: {
14172
- pendingCount: this.pipeline.getAccumulatedCount(),
14173
- readyForFlush: this.pipeline.shouldRunBatch()
14174
- }
14175
- };
14176
- }
14177
- /**
14178
- * Convert a skill-tree Trajectory to cognitive-core Trajectory format
14179
- */
14180
- convertTrajectory(trajectory, options) {
14181
- const firstUserTurn = trajectory.turns.find((t) => t.role === "user");
14182
- let taskDescription = firstUserTurn?.content ?? "Unknown task";
14183
- if (options?.context) {
14184
- taskDescription = `${taskDescription}
14185
-
14186
- Context: ${options.context}`;
14187
- }
14188
- const task = this.factory.createTask({
14189
- id: trajectory.sessionId,
14190
- domain: trajectory.metadata.projectName ?? "general",
14191
- description: taskDescription,
14192
- context: trajectory.metadata.custom ?? {}
14193
- });
14194
- const [startTurn, endTurn] = options?.turnRange ?? [0, trajectory.turns.length - 1];
14195
- const turnsToProcess = trajectory.turns.slice(startTurn, endTurn + 1);
14196
- const steps = [];
14197
- if (this.config.convertToReAct) {
14198
- for (let i = 0; i < turnsToProcess.length; i++) {
14199
- const turn = turnsToProcess[i];
14200
- if (turn.role === "assistant") {
14201
- const step = this.turnToStep(turn, turnsToProcess, i);
14202
- if (step) {
14203
- steps.push(step);
14204
- }
14205
- }
14206
- }
14207
- }
14208
- const outcome = {
14209
- success: trajectory.outcome?.success ?? false,
14210
- partialScore: trajectory.outcome?.success ? 1 : 0,
14211
- solution: trajectory.outcome?.summary ?? "",
14212
- errorInfo: trajectory.outcome?.errors?.join("; ")
14213
- };
14214
- return this.factory.createTrajectory({
14215
- id: trajectory.sessionId,
14216
- task,
14217
- steps,
14218
- outcome,
14219
- agentId: trajectory.metadata.agentType ?? "skill-tree",
14220
- metadata: trajectory.metadata.custom ?? {}
14221
- });
14222
- }
14223
- /**
14224
- * Convert an assistant turn to a cognitive-core Step
14225
- */
14226
- turnToStep(turn, allTurns, turnIndex) {
14227
- let observation = "";
14228
- const nextTurn = allTurns[turnIndex + 1];
14229
- if (nextTurn?.role === "tool" && nextTurn.toolResults?.length) {
14230
- observation = nextTurn.toolResults.map((r) => r.output).join("\n");
14231
- } else if (nextTurn?.role === "user") {
14232
- observation = nextTurn.content.slice(0, 500);
14233
- }
14234
- let action = "";
14235
- if (turn.toolCalls?.length) {
14236
- action = turn.toolCalls.map((tc) => `${tc.name}(${JSON.stringify(tc.input).slice(0, 200)})`).join("; ");
14237
- } else {
14238
- action = turn.content.slice(0, 300);
14239
- }
14240
- const thought = turn.toolCalls?.length ? turn.content.slice(0, 500) : void 0;
14241
- return this.factory.createStep({
14242
- thought,
14243
- action,
14244
- observation
14245
- });
14246
- }
14247
- /**
14248
- * Convert a cognitive-core Playbook to a LearningCandidate
14249
- */
14250
- playbookToCandidate(playbook) {
14251
- const kind = this.inferKind(playbook);
14252
- const content = this.createContentForKind(kind, playbook);
14253
- const attribution = playbook.evolution.createdFrom.map(
14254
- (trajectoryId, i) => ({
14255
- turnIndex: i,
14256
- score: 1 / Math.max(1, playbook.evolution.createdFrom.length),
14257
- reasoning: `Derived from trajectory ${trajectoryId}`
14258
- })
14259
- );
14260
- return {
14261
- kind,
14262
- id: playbook.id,
14263
- name: playbook.name,
14264
- content,
14265
- confidence: playbook.confidence,
14266
- attribution,
14267
- source: {
14268
- provider: this.name,
14269
- trajectoryId: playbook.evolution.createdFrom[0] ?? "unknown",
14270
- turnRange: [0, 0],
14271
- // Playbooks don't track specific turn ranges
14272
- extractedAt: playbook.createdAt,
14273
- metadata: {
14274
- version: playbook.evolution.version,
14275
- successCount: playbook.evolution.successCount,
14276
- failureCount: playbook.evolution.failureCount,
14277
- complexity: playbook.complexity
14278
- }
14279
- },
14280
- embedding: playbook.embedding,
14281
- // Pass through embedding if present
14282
- tags: playbook.applicability.domains,
14283
- reasoning: playbook.guidance.strategy
14284
- };
14285
- }
14286
- /**
14287
- * Create appropriate content type for the inferred kind
14288
- */
14289
- createContentForKind(kind, playbook) {
14290
- switch (kind) {
14291
- case "strategy":
14292
- return {
14293
- kind: "strategy",
14294
- situation: playbook.applicability.situations.join(". "),
14295
- suggestion: playbook.guidance.strategy,
14296
- parameters: playbook.guidance.codeExample ? { example: playbook.guidance.codeExample } : void 0
14297
- };
14298
- case "pattern":
14299
- return {
14300
- kind: "pattern",
14301
- pattern: playbook.applicability.triggers[0] ?? playbook.name,
14302
- description: playbook.guidance.strategy,
14303
- examples: playbook.applicability.situations
14304
- };
14305
- case "error-fix":
14306
- return {
14307
- kind: "error-fix",
14308
- errorPattern: playbook.applicability.triggers.join(" | "),
14309
- fix: playbook.guidance.strategy + (playbook.guidance.steps?.length ? "\n\nSteps:\n" + playbook.guidance.steps.map((s, i) => `${i + 1}. ${s}`).join("\n") : ""),
14310
- frequency: playbook.evolution.successCount + playbook.evolution.failureCount,
14311
- errorExamples: playbook.applicability.triggers
14312
- };
14313
- case "skill":
14314
- default:
14315
- return {
14316
- kind: "skill",
14317
- problem: playbook.applicability.situations.join(". "),
14318
- solution: playbook.guidance.strategy + (playbook.guidance.steps?.length ? "\n\nSteps:\n" + playbook.guidance.steps.map((s, i) => `${i + 1}. ${s}`).join("\n") : ""),
14319
- verification: playbook.verification.successIndicators.join(". "),
14320
- triggers: this.extractTriggers(playbook),
14321
- examples: []
14322
- // Playbooks don't have direct examples
14323
- };
14324
- }
14325
- }
14326
- /**
14327
- * Infer the kind of learning from a playbook
14328
- */
14329
- inferKind(playbook) {
14330
- const hasErrorTriggers = playbook.applicability.triggers.some(
14331
- (t) => t.toLowerCase().includes("error") || /^[A-Z]{2,}\d+/.test(t)
14332
- );
14333
- if (hasErrorTriggers) {
14334
- return "error-fix";
14335
- }
14336
- const strategy = playbook.guidance.strategy.toLowerCase();
14337
- if (strategy.includes("approach") || strategy.includes("strategy") || strategy.includes("when you see")) {
14338
- return "strategy";
14339
- }
14340
- if (playbook.applicability.situations.some((s) => s.includes("pattern"))) {
14341
- return "pattern";
14342
- }
14343
- return "skill";
14344
- }
14345
- /**
14346
- * Extract triggers from playbook applicability
14347
- */
14348
- extractTriggers(playbook) {
14349
- const triggers = [];
14350
- for (const situation of playbook.applicability.situations) {
14351
- triggers.push({
14352
- type: "context",
14353
- value: situation,
14354
- description: "Situation trigger"
14355
- });
14356
- }
14357
- for (const trigger of playbook.applicability.triggers) {
14358
- let type = "keyword";
14359
- if (trigger.toLowerCase().includes("error") || /^[A-Z]{2,}\d+/.test(trigger)) {
14360
- type = "error";
14361
- } else if (trigger.startsWith("/") || trigger.includes("*")) {
14362
- type = "pattern";
14363
- }
14364
- triggers.push({
14365
- type,
14366
- value: trigger,
14367
- description: "Explicit trigger"
14368
- });
14369
- }
14370
- return triggers;
14371
- }
14372
- /**
14373
- * Tokenize text into words
14374
- */
14375
- tokenize(text) {
14376
- return text.toLowerCase().split(/\W+/).filter((w) => w.length > 2);
14377
- }
14378
- /**
14379
- * Compute Jaccard similarity between two arrays
14380
- */
14381
- jaccardSimilarity(a, b) {
14382
- const setA = new Set(a);
14383
- const setB = new Set(b);
14384
- const intersection = new Set([...setA].filter((x) => setB.has(x)));
14385
- const union = /* @__PURE__ */ new Set([...setA, ...setB]);
14386
- return union.size === 0 ? 0 : intersection.size / union.size;
14387
- }
14388
- };
14389
- function createCognitiveCoreProvider(options) {
14390
- return new CognitiveCoreProvider(options);
14391
- }
14392
- async function createDefaultCognitiveCoreFactory() {
14393
- const cc = await import("cognitive-core");
14394
- return {
14395
- createMemorySystem(storagePath) {
14396
- return cc.createMemorySystem(storagePath);
14397
- },
14398
- createLearningPipeline(memory, config) {
14399
- return cc.createLearningPipeline(
14400
- memory,
14401
- config
14402
- );
14403
- },
14404
- createTrajectory(params) {
14405
- return cc.createTrajectory(params);
14406
- },
14407
- createTask(params) {
14408
- return cc.createTask(params);
14409
- },
14410
- createStep(params) {
14411
- return cc.createStep(params);
14412
- }
14413
- };
14414
- }
14415
-
14416
12734
  // src/sync/git-sync-adapter.ts
14417
12735
  var fs8 = __toESM(require("fs"));
14418
12736
  var path8 = __toESM(require("path"));
@@ -15942,7 +14260,6 @@ var VERSION = "0.1.0";
15942
14260
  BaseStorageAdapter,
15943
14261
  BatchProcessor,
15944
14262
  ClaudeCodeAdapter,
15945
- CognitiveCoreProvider,
15946
14263
  ConflictStore,
15947
14264
  DEFAULT_ACTIVATION_CONFIG,
15948
14265
  DEFAULT_AGENTS_CONFIG,
@@ -15961,7 +14278,6 @@ var VERSION = "0.1.0";
15961
14278
  MemoryMetricsStorage,
15962
14279
  MemoryStorageAdapter,
15963
14280
  MetricsTracker,
15964
- NaiveLearningProvider,
15965
14281
  OpenAIAdapter,
15966
14282
  OpenAIEmbedding,
15967
14283
  ProjectDetector,
@@ -15994,9 +14310,7 @@ var VERSION = "0.1.0";
15994
14310
  createAgentsParser,
15995
14311
  createAgentsSync,
15996
14312
  createBackupHook,
15997
- createCognitiveCoreProvider,
15998
14313
  createConflictStore,
15999
- createDefaultCognitiveCoreFactory,
16000
14314
  createDefaultSyncConfig,
16001
14315
  createExtractionEnrichmentHook,
16002
14316
  createExtractionValidationHook,
@@ -16006,7 +14320,6 @@ var VERSION = "0.1.0";
16006
14320
  createMcpServer,
16007
14321
  createMetricsHook,
16008
14322
  createMetricsTracker,
16009
- createNaiveProvider,
16010
14323
  createQualityBypassHook,
16011
14324
  createQualityLoggingHook,
16012
14325
  createSaveValidationHook,
@@ -16016,6 +14329,7 @@ var VERSION = "0.1.0";
16016
14329
  createToolHandlers,
16017
14330
  debuggingProfile,
16018
14331
  devopsProfile,
14332
+ discoverSkills,
16019
14333
  documentationProfile,
16020
14334
  euclideanDistance,
16021
14335
  executeToolCall,
@@ -16026,6 +14340,7 @@ var VERSION = "0.1.0";
16026
14340
  getLatestVersion,
16027
14341
  getToolDefinition,
16028
14342
  getToolNames,
14343
+ hasSkilltreeDir,
16029
14344
  hookRegistry,
16030
14345
  implementationProfile,
16031
14346
  importFromAgentsMd,
@@ -16055,3 +14370,4 @@ var VERSION = "0.1.0";
16055
14370
  testingProfile,
16056
14371
  writeAgentsMd
16057
14372
  });
14373
+ //# sourceMappingURL=index.js.map