@skillkit/core 1.11.0 → 1.13.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.js CHANGED
@@ -10420,11 +10420,20 @@ import { parse as parseYaml7, stringify as stringifyYaml5 } from "yaml";
10420
10420
  import { randomUUID as randomUUID8 } from "crypto";
10421
10421
  var ObservationStore = class {
10422
10422
  filePath;
10423
+ projectPath;
10423
10424
  data = null;
10424
10425
  sessionId;
10425
- constructor(projectPath, sessionId) {
10426
+ compressionThreshold;
10427
+ autoCompress;
10428
+ onThresholdReached;
10429
+ compressionInProgress = false;
10430
+ constructor(projectPath, sessionId, options = {}) {
10431
+ this.projectPath = projectPath;
10426
10432
  this.filePath = join21(projectPath, ".skillkit", "memory", "observations.yaml");
10427
10433
  this.sessionId = sessionId || randomUUID8();
10434
+ this.compressionThreshold = options.compressionThreshold ?? 50;
10435
+ this.autoCompress = options.autoCompress ?? true;
10436
+ this.onThresholdReached = options.onThresholdReached;
10428
10437
  }
10429
10438
  ensureDir() {
10430
10439
  const dir = dirname4(this.filePath);
@@ -10475,8 +10484,66 @@ var ObservationStore = class {
10475
10484
  };
10476
10485
  data.observations.push(observation);
10477
10486
  this.save();
10487
+ void this.checkAutoCompression().catch(() => {
10488
+ });
10478
10489
  return observation;
10479
10490
  }
10491
+ /**
10492
+ * Check if auto-compression should trigger
10493
+ */
10494
+ async checkAutoCompression() {
10495
+ if (!this.autoCompress || this.compressionInProgress) return;
10496
+ if (!this.onThresholdReached) return;
10497
+ const count = this.count();
10498
+ if (count >= this.compressionThreshold) {
10499
+ this.compressionInProgress = true;
10500
+ try {
10501
+ const observations = this.getAll();
10502
+ await this.onThresholdReached(observations);
10503
+ } finally {
10504
+ this.compressionInProgress = false;
10505
+ }
10506
+ }
10507
+ }
10508
+ /**
10509
+ * Set auto-compression callback
10510
+ */
10511
+ setAutoCompressCallback(callback) {
10512
+ this.onThresholdReached = callback;
10513
+ }
10514
+ /**
10515
+ * Enable/disable auto-compression
10516
+ */
10517
+ setAutoCompress(enabled) {
10518
+ this.autoCompress = enabled;
10519
+ }
10520
+ /**
10521
+ * Set compression threshold
10522
+ */
10523
+ setCompressionThreshold(threshold) {
10524
+ if (threshold < 1 || !Number.isInteger(threshold)) {
10525
+ throw new Error("Compression threshold must be a positive integer");
10526
+ }
10527
+ this.compressionThreshold = threshold;
10528
+ }
10529
+ /**
10530
+ * Get compression threshold
10531
+ */
10532
+ getCompressionThreshold() {
10533
+ return this.compressionThreshold;
10534
+ }
10535
+ /**
10536
+ * Check if threshold is reached
10537
+ */
10538
+ isThresholdReached() {
10539
+ return this.count() >= this.compressionThreshold;
10540
+ }
10541
+ /**
10542
+ * Get project path
10543
+ */
10544
+ getProjectPath() {
10545
+ return this.projectPath;
10546
+ }
10480
10547
  getAll() {
10481
10548
  return this.load().observations;
10482
10549
  }
@@ -11364,7 +11431,6 @@ var MemoryObserver = class {
11364
11431
  }
11365
11432
  let score = 50;
11366
11433
  switch (event.type) {
11367
- // High relevance events
11368
11434
  case "error_encountered":
11369
11435
  case "task_failed":
11370
11436
  score = 85;
@@ -11384,7 +11450,6 @@ var MemoryObserver = class {
11384
11450
  case "verification_failed":
11385
11451
  score = 80;
11386
11452
  break;
11387
- // Medium relevance events
11388
11453
  case "file_modified":
11389
11454
  score = 60;
11390
11455
  if (event.files && event.files.length > 3) {
@@ -11398,7 +11463,6 @@ var MemoryObserver = class {
11398
11463
  case "verification_passed":
11399
11464
  score = 50;
11400
11465
  break;
11401
- // Lower relevance events
11402
11466
  case "task_start":
11403
11467
  score = 30;
11404
11468
  break;
@@ -12169,7 +12233,6 @@ Generate up to ${opts.maxLearnings} learnings. Only include learnings with impor
12169
12233
  return typeof item === "object" && typeof item.title === "string" && typeof item.content === "string" && Array.isArray(item.tags) && typeof item.importance === "number";
12170
12234
  }).map((item) => ({
12171
12235
  ...item,
12172
- // Validate source observation IDs
12173
12236
  sourceObservationIds: (item.sourceObservationIds || []).filter(
12174
12237
  (id) => observationIds.has(id)
12175
12238
  ),
@@ -12284,7 +12347,6 @@ var LearningConsolidator = class {
12284
12347
  const base = this.getBetterLearning(learning1, learning2);
12285
12348
  const other = base === learning1 ? learning2 : learning1;
12286
12349
  return {
12287
- // Preserve the source from the base learning instead of hard-coding 'session'
12288
12350
  source: base.source,
12289
12351
  sourceObservations: [
12290
12352
  ...base.sourceObservations || [],
@@ -12876,9 +12938,1429 @@ function createMemoryInjector(projectPath, projectName, projectContext) {
12876
12938
  return new MemoryInjector(projectPath, projectName, projectContext);
12877
12939
  }
12878
12940
 
12941
+ // src/memory/hooks/types.ts
12942
+ var DEFAULT_MEMORY_HOOK_CONFIG = {
12943
+ enabled: true,
12944
+ autoInjectOnSessionStart: true,
12945
+ autoCaptureToolUse: true,
12946
+ autoCompressOnSessionEnd: true,
12947
+ minRelevanceForCapture: 30,
12948
+ maxTokensForInjection: 2e3,
12949
+ compressionThreshold: 50,
12950
+ capturePatterns: ["*"],
12951
+ excludeTools: ["Read", "Glob", "Grep"]
12952
+ };
12953
+
12954
+ // src/memory/hooks/session-start.ts
12955
+ import { basename as basename9 } from "path";
12956
+ var SessionStartHook = class {
12957
+ config;
12958
+ projectPath;
12959
+ agent;
12960
+ constructor(projectPath, agent = "claude-code", config = {}) {
12961
+ this.projectPath = projectPath;
12962
+ this.agent = agent;
12963
+ this.config = { ...DEFAULT_MEMORY_HOOK_CONFIG, ...config };
12964
+ }
12965
+ /**
12966
+ * Execute the session start hook
12967
+ */
12968
+ async execute(context) {
12969
+ if (!this.config.enabled || !this.config.autoInjectOnSessionStart) {
12970
+ return {
12971
+ injected: false,
12972
+ learnings: [],
12973
+ tokenCount: 0,
12974
+ formattedContent: ""
12975
+ };
12976
+ }
12977
+ const status = getMemoryStatus(this.projectPath);
12978
+ if (!status.projectMemoryExists && !status.globalMemoryExists) {
12979
+ return {
12980
+ injected: false,
12981
+ learnings: [],
12982
+ tokenCount: 0,
12983
+ formattedContent: ""
12984
+ };
12985
+ }
12986
+ const projectName = context.project_path ? basename9(context.project_path.replace(/\/+$/, "")) || void 0 : void 0;
12987
+ const injector = new MemoryInjector(this.projectPath, projectName);
12988
+ const result = await injector.injectForAgent(this.agent, {
12989
+ maxTokens: this.config.maxTokensForInjection,
12990
+ minRelevance: this.config.minRelevanceForCapture,
12991
+ maxLearnings: 10,
12992
+ includeGlobal: true,
12993
+ disclosureLevel: "preview"
12994
+ });
12995
+ const learnings = result.memories.map((m) => m.learning);
12996
+ return {
12997
+ injected: result.memories.length > 0,
12998
+ learnings,
12999
+ tokenCount: result.totalTokens,
13000
+ formattedContent: result.formattedContent
13001
+ };
13002
+ }
13003
+ /**
13004
+ * Generate Claude Code hook output format
13005
+ */
13006
+ async generateHookOutput(context) {
13007
+ const result = await this.execute(context);
13008
+ return this.generateHookOutputFromResult(result);
13009
+ }
13010
+ /**
13011
+ * Generate hook output from pre-computed result (avoids double execution)
13012
+ */
13013
+ generateHookOutputFromResult(result) {
13014
+ if (!result.injected || result.learnings.length === 0) {
13015
+ return { continue: true };
13016
+ }
13017
+ return {
13018
+ continue: true,
13019
+ inject: this.formatInjection(result)
13020
+ };
13021
+ }
13022
+ /**
13023
+ * Format learnings for injection into Claude Code context
13024
+ */
13025
+ formatInjection(result) {
13026
+ if (result.learnings.length === 0) {
13027
+ return "";
13028
+ }
13029
+ const lines = [
13030
+ "<skillkit-memories>",
13031
+ `<!-- ${result.learnings.length} relevant learnings from previous sessions (${result.tokenCount} tokens) -->`,
13032
+ ""
13033
+ ];
13034
+ for (const learning of result.learnings) {
13035
+ lines.push(`## ${learning.title}`);
13036
+ lines.push(`Tags: ${learning.tags.join(", ")}`);
13037
+ if (learning.frameworks && learning.frameworks.length > 0) {
13038
+ lines.push(`Frameworks: ${learning.frameworks.join(", ")}`);
13039
+ }
13040
+ lines.push("");
13041
+ const preview = learning.content.slice(0, 200);
13042
+ lines.push(preview + (learning.content.length > 200 ? "..." : ""));
13043
+ lines.push("");
13044
+ }
13045
+ lines.push("</skillkit-memories>");
13046
+ return lines.join("\n");
13047
+ }
13048
+ /**
13049
+ * Get configuration
13050
+ */
13051
+ getConfig() {
13052
+ return { ...this.config };
13053
+ }
13054
+ /**
13055
+ * Update configuration
13056
+ */
13057
+ setConfig(config) {
13058
+ this.config = { ...this.config, ...config };
13059
+ }
13060
+ };
13061
+ function createSessionStartHook(projectPath, agent = "claude-code", config = {}) {
13062
+ return new SessionStartHook(projectPath, agent, config);
13063
+ }
13064
+ async function executeSessionStartHook(projectPath, context, config = {}) {
13065
+ const hook = new SessionStartHook(projectPath, context.agent || "claude-code", config);
13066
+ return hook.execute(context);
13067
+ }
13068
+
13069
+ // src/memory/hooks/post-tool-use.ts
13070
+ var TOOL_CATEGORIES = {
13071
+ Read: "tool_use",
13072
+ Write: "file_change",
13073
+ Edit: "file_change",
13074
+ Bash: "tool_use",
13075
+ Glob: "tool_use",
13076
+ Grep: "tool_use",
13077
+ WebFetch: "tool_use",
13078
+ WebSearch: "tool_use",
13079
+ Task: "checkpoint",
13080
+ AskUserQuestion: "decision"
13081
+ };
13082
+ var TOOL_RELEVANCE = {
13083
+ Write: 70,
13084
+ Edit: 70,
13085
+ Bash: 60,
13086
+ Task: 65,
13087
+ AskUserQuestion: 75,
13088
+ WebFetch: 50,
13089
+ WebSearch: 50,
13090
+ Read: 30,
13091
+ Glob: 25,
13092
+ Grep: 30
13093
+ };
13094
+ var PostToolUseHook = class {
13095
+ config;
13096
+ agent;
13097
+ store;
13098
+ pendingErrors = /* @__PURE__ */ new Map();
13099
+ constructor(projectPath, agent = "claude-code", config = {}, sessionId) {
13100
+ this.agent = agent;
13101
+ this.config = { ...DEFAULT_MEMORY_HOOK_CONFIG, ...config };
13102
+ this.store = new ObservationStore(projectPath, sessionId);
13103
+ }
13104
+ /**
13105
+ * Execute the post tool use hook
13106
+ */
13107
+ async execute(event) {
13108
+ this.clearOldPendingErrors();
13109
+ if (!this.config.enabled || !this.config.autoCaptureToolUse) {
13110
+ return { captured: false, reason: "Hook disabled" };
13111
+ }
13112
+ if (this.shouldExcludeTool(event.tool_name)) {
13113
+ return { captured: false, reason: `Tool ${event.tool_name} is excluded` };
13114
+ }
13115
+ const relevance = this.calculateRelevance(event);
13116
+ if (relevance < this.config.minRelevanceForCapture) {
13117
+ return { captured: false, reason: `Relevance ${relevance} below threshold` };
13118
+ }
13119
+ const observationType = this.getObservationType(event);
13120
+ const content = this.extractContent(event);
13121
+ if (event.is_error) {
13122
+ const errorId = this.generateErrorId(content.error || content.action);
13123
+ this.pendingErrors.set(errorId, {
13124
+ error: content.error || content.action,
13125
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
13126
+ });
13127
+ }
13128
+ const matchingSolution = event.is_error ? void 0 : this.findMatchingSolution(content);
13129
+ if (matchingSolution) {
13130
+ content.solution = content.action;
13131
+ content.context = `Solution for: ${matchingSolution.error}`;
13132
+ }
13133
+ const observation = this.store.add(
13134
+ observationType,
13135
+ content,
13136
+ this.agent,
13137
+ matchingSolution ? 95 : relevance
13138
+ );
13139
+ return { captured: true, observation };
13140
+ }
13141
+ /**
13142
+ * Generate Claude Code hook output format
13143
+ */
13144
+ async generateHookOutput(event) {
13145
+ const result = await this.execute(event);
13146
+ return this.generateHookOutputFromResult(event, result);
13147
+ }
13148
+ /**
13149
+ * Generate hook output from pre-computed result (avoids double execution)
13150
+ */
13151
+ generateHookOutputFromResult(event, result) {
13152
+ return {
13153
+ continue: true,
13154
+ message: result.captured ? `Observation captured: ${event.tool_name}` : void 0
13155
+ };
13156
+ }
13157
+ /**
13158
+ * Get configuration
13159
+ */
13160
+ getConfig() {
13161
+ return { ...this.config };
13162
+ }
13163
+ /**
13164
+ * Update configuration
13165
+ */
13166
+ setConfig(config) {
13167
+ this.config = { ...this.config, ...config };
13168
+ }
13169
+ /**
13170
+ * Record an error explicitly
13171
+ */
13172
+ recordError(error, context) {
13173
+ const errorId = this.generateErrorId(error);
13174
+ this.pendingErrors.set(errorId, {
13175
+ error,
13176
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
13177
+ });
13178
+ return this.store.add(
13179
+ "error",
13180
+ {
13181
+ action: "Error encountered",
13182
+ context,
13183
+ error,
13184
+ tags: ["error"]
13185
+ },
13186
+ this.agent,
13187
+ 80
13188
+ );
13189
+ }
13190
+ /**
13191
+ * Record a solution explicitly
13192
+ */
13193
+ recordSolution(solution, context, relatedError) {
13194
+ let relevance = 70;
13195
+ let solutionContext = context;
13196
+ if (relatedError) {
13197
+ const errorId = this.generateErrorId(relatedError);
13198
+ if (this.pendingErrors.has(errorId)) {
13199
+ this.pendingErrors.delete(errorId);
13200
+ relevance = 95;
13201
+ solutionContext = `Solution for: ${relatedError}`;
13202
+ }
13203
+ }
13204
+ return this.store.add(
13205
+ "solution",
13206
+ {
13207
+ action: solution,
13208
+ context: solutionContext,
13209
+ solution,
13210
+ tags: ["solution"]
13211
+ },
13212
+ this.agent,
13213
+ relevance
13214
+ );
13215
+ }
13216
+ /**
13217
+ * Record a decision explicitly
13218
+ */
13219
+ recordDecision(decision, options, context) {
13220
+ return this.store.add(
13221
+ "decision",
13222
+ {
13223
+ action: decision,
13224
+ context: `Options: ${options.join(", ")}. Context: ${context}`,
13225
+ tags: ["decision", "architecture"]
13226
+ },
13227
+ this.agent,
13228
+ 75
13229
+ );
13230
+ }
13231
+ /**
13232
+ * Record file modifications
13233
+ */
13234
+ recordFileChange(files, action, context) {
13235
+ return this.store.add(
13236
+ "file_change",
13237
+ {
13238
+ action,
13239
+ context,
13240
+ files,
13241
+ tags: ["file-change"]
13242
+ },
13243
+ this.agent,
13244
+ files.length > 3 ? 75 : 60
13245
+ );
13246
+ }
13247
+ /**
13248
+ * Get pending errors that haven't been resolved
13249
+ */
13250
+ getPendingErrors() {
13251
+ return Array.from(this.pendingErrors.values());
13252
+ }
13253
+ /**
13254
+ * Clear old pending errors (older than 30 minutes)
13255
+ */
13256
+ clearOldPendingErrors() {
13257
+ const thirtyMinutesAgo = Date.now() - 30 * 60 * 1e3;
13258
+ let cleared = 0;
13259
+ for (const [id, { timestamp }] of this.pendingErrors) {
13260
+ if (new Date(timestamp).getTime() < thirtyMinutesAgo) {
13261
+ this.pendingErrors.delete(id);
13262
+ cleared++;
13263
+ }
13264
+ }
13265
+ return cleared;
13266
+ }
13267
+ /**
13268
+ * Get observation store
13269
+ */
13270
+ getStore() {
13271
+ return this.store;
13272
+ }
13273
+ /**
13274
+ * Get observation count
13275
+ */
13276
+ getObservationCount() {
13277
+ return this.store.count();
13278
+ }
13279
+ shouldExcludeTool(toolName) {
13280
+ return this.config.excludeTools?.includes(toolName) ?? false;
13281
+ }
13282
+ calculateRelevance(event) {
13283
+ let relevance = TOOL_RELEVANCE[event.tool_name] || 50;
13284
+ if (event.is_error) {
13285
+ relevance = Math.max(relevance, 80);
13286
+ }
13287
+ if (event.duration_ms && event.duration_ms > 1e4) {
13288
+ relevance = Math.min(relevance + 10, 100);
13289
+ }
13290
+ const result = event.tool_result || "";
13291
+ if (result.includes("error") || result.includes("Error") || result.includes("failed")) {
13292
+ relevance = Math.max(relevance, 75);
13293
+ }
13294
+ if (result.includes("success") || result.includes("created") || result.includes("updated")) {
13295
+ relevance = Math.min(relevance + 5, 100);
13296
+ }
13297
+ return relevance;
13298
+ }
13299
+ getObservationType(event) {
13300
+ if (event.is_error) {
13301
+ return "error";
13302
+ }
13303
+ return TOOL_CATEGORIES[event.tool_name] || "tool_use";
13304
+ }
13305
+ extractContent(event) {
13306
+ const content = {
13307
+ action: `${event.tool_name}: ${this.summarizeInput(event.tool_input)}`,
13308
+ context: this.extractContext(event),
13309
+ tags: [event.tool_name.toLowerCase()]
13310
+ };
13311
+ if (event.is_error && event.tool_result) {
13312
+ content.error = event.tool_result.slice(0, 500);
13313
+ }
13314
+ if (event.tool_result && !event.is_error) {
13315
+ content.result = event.tool_result.slice(0, 200);
13316
+ }
13317
+ const files = this.extractFiles(event);
13318
+ if (files.length > 0) {
13319
+ content.files = files;
13320
+ }
13321
+ return content;
13322
+ }
13323
+ summarizeInput(input) {
13324
+ if (input.file_path) return String(input.file_path);
13325
+ if (input.pattern) return String(input.pattern);
13326
+ if (input.command) {
13327
+ const cmd = String(input.command);
13328
+ return cmd.length > 100 ? cmd.slice(0, 100) + "..." : cmd;
13329
+ }
13330
+ if (input.query) return String(input.query).slice(0, 100);
13331
+ const keys = Object.keys(input);
13332
+ if (keys.length === 0) return "(no input)";
13333
+ return keys.slice(0, 3).join(", ");
13334
+ }
13335
+ extractContext(event) {
13336
+ const parts = [];
13337
+ if (event.duration_ms) {
13338
+ parts.push(`Duration: ${event.duration_ms}ms`);
13339
+ }
13340
+ if (event.is_error) {
13341
+ parts.push("Result: Error");
13342
+ } else if (event.tool_result) {
13343
+ const resultPreview = event.tool_result.slice(0, 100);
13344
+ parts.push(`Result: ${resultPreview}${event.tool_result.length > 100 ? "..." : ""}`);
13345
+ }
13346
+ return parts.join(". ") || "No additional context";
13347
+ }
13348
+ extractFiles(event) {
13349
+ const files = [];
13350
+ if (event.tool_input.file_path) {
13351
+ files.push(String(event.tool_input.file_path));
13352
+ }
13353
+ if (event.tool_input.path) {
13354
+ files.push(String(event.tool_input.path));
13355
+ }
13356
+ return files;
13357
+ }
13358
+ generateErrorId(error) {
13359
+ const normalized = error.toLowerCase().replace(/[0-9]+/g, "N").replace(/['"`]/g, "").replace(/\s+/g, " ").trim().slice(0, 100);
13360
+ return normalized;
13361
+ }
13362
+ findMatchingSolution(content) {
13363
+ const actionLower = content.action.toLowerCase();
13364
+ const contextLower = content.context.toLowerCase();
13365
+ for (const [errorId, errorData] of this.pendingErrors) {
13366
+ const hasKeywordMatch = actionLower.includes("fix") || actionLower.includes("resolve") || actionLower.includes("solution") || contextLower.includes("fix") || contextLower.includes("resolve");
13367
+ if (hasKeywordMatch) {
13368
+ const errorWords = errorId.split(" ").filter((w) => w.length > 3);
13369
+ const textWords = new Set((actionLower + " " + contextLower).split(/\s+/));
13370
+ const matchCount = errorWords.filter((w) => textWords.has(w)).length;
13371
+ if (matchCount >= 2 || matchCount >= 1 && hasKeywordMatch) {
13372
+ this.pendingErrors.delete(errorId);
13373
+ return errorData;
13374
+ }
13375
+ }
13376
+ }
13377
+ return void 0;
13378
+ }
13379
+ };
13380
+ function createPostToolUseHook(projectPath, agent = "claude-code", config = {}, sessionId) {
13381
+ return new PostToolUseHook(projectPath, agent, config, sessionId);
13382
+ }
13383
+ async function executePostToolUseHook(projectPath, event, config = {}, sessionId) {
13384
+ const hook = new PostToolUseHook(projectPath, "claude-code", config, sessionId);
13385
+ return hook.execute(event);
13386
+ }
13387
+
13388
+ // src/memory/hooks/session-end.ts
13389
+ import { basename as basename10 } from "path";
13390
+ var SessionEndHook = class {
13391
+ config;
13392
+ projectPath;
13393
+ agent;
13394
+ constructor(projectPath, agent = "claude-code", config = {}) {
13395
+ this.projectPath = projectPath;
13396
+ this.agent = agent;
13397
+ this.config = { ...DEFAULT_MEMORY_HOOK_CONFIG, ...config };
13398
+ }
13399
+ /**
13400
+ * Execute the session end hook
13401
+ */
13402
+ async execute(context) {
13403
+ if (!this.config.enabled || !this.config.autoCompressOnSessionEnd) {
13404
+ return {
13405
+ compressed: false,
13406
+ observationCount: 0,
13407
+ learningCount: 0,
13408
+ learnings: []
13409
+ };
13410
+ }
13411
+ const store = new ObservationStore(this.projectPath, context.session_id);
13412
+ const observations = store.getAll();
13413
+ if (observations.length < 3) {
13414
+ return {
13415
+ compressed: false,
13416
+ observationCount: observations.length,
13417
+ learningCount: 0,
13418
+ learnings: []
13419
+ };
13420
+ }
13421
+ const projectName = context.project_path ? basename10(context.project_path.replace(/\/+$/, "")) || void 0 : void 0;
13422
+ const compressor = new MemoryCompressor(this.projectPath, {
13423
+ scope: "project",
13424
+ projectName
13425
+ });
13426
+ const { learnings, result } = await compressor.compressAndStore(observations, {
13427
+ minObservations: 3,
13428
+ maxLearnings: 10,
13429
+ minImportance: 4,
13430
+ includeLowRelevance: false,
13431
+ additionalTags: ["session-end", this.agent]
13432
+ });
13433
+ if (result.processedObservationIds.length > 0) {
13434
+ store.deleteMany(result.processedObservationIds);
13435
+ }
13436
+ return {
13437
+ compressed: learnings.length > 0,
13438
+ observationCount: observations.length,
13439
+ learningCount: learnings.length,
13440
+ learnings
13441
+ };
13442
+ }
13443
+ /**
13444
+ * Generate Claude Code hook output format
13445
+ */
13446
+ async generateHookOutput(context) {
13447
+ const result = await this.execute(context);
13448
+ return this.generateHookOutputFromResult(result);
13449
+ }
13450
+ /**
13451
+ * Generate hook output from pre-computed result (avoids double execution)
13452
+ */
13453
+ generateHookOutputFromResult(result) {
13454
+ let message;
13455
+ if (result.compressed) {
13456
+ message = `Session memory: ${result.observationCount} observations \u2192 ${result.learningCount} learnings`;
13457
+ }
13458
+ return {
13459
+ continue: true,
13460
+ message
13461
+ };
13462
+ }
13463
+ /**
13464
+ * Force compression regardless of settings
13465
+ */
13466
+ async forceCompress(sessionId) {
13467
+ const store = new ObservationStore(this.projectPath, sessionId);
13468
+ const observations = store.getAll();
13469
+ if (observations.length === 0) {
13470
+ return {
13471
+ compressed: false,
13472
+ observationCount: 0,
13473
+ learningCount: 0,
13474
+ learnings: []
13475
+ };
13476
+ }
13477
+ const compressor = new MemoryCompressor(this.projectPath, {
13478
+ scope: "project"
13479
+ });
13480
+ const { learnings, result } = await compressor.compressAndStore(observations, {
13481
+ minObservations: 1,
13482
+ maxLearnings: 20,
13483
+ minImportance: 3,
13484
+ includeLowRelevance: true
13485
+ });
13486
+ if (result.processedObservationIds.length > 0) {
13487
+ store.deleteMany(result.processedObservationIds);
13488
+ }
13489
+ return {
13490
+ compressed: learnings.length > 0,
13491
+ observationCount: observations.length,
13492
+ learningCount: learnings.length,
13493
+ learnings
13494
+ };
13495
+ }
13496
+ /**
13497
+ * Preview what would be compressed (dry-run)
13498
+ */
13499
+ async preview(sessionId) {
13500
+ const store = new ObservationStore(this.projectPath, sessionId);
13501
+ const observations = store.getAll();
13502
+ const types = {};
13503
+ for (const obs of observations) {
13504
+ types[obs.type] = (types[obs.type] || 0) + 1;
13505
+ }
13506
+ const compressor = new MemoryCompressor(this.projectPath, {
13507
+ scope: "project"
13508
+ });
13509
+ const result = await compressor.compress(observations, {
13510
+ minObservations: 3,
13511
+ maxLearnings: 10,
13512
+ minImportance: 4
13513
+ });
13514
+ return {
13515
+ wouldCompress: result.learnings.length > 0,
13516
+ observationCount: observations.length,
13517
+ estimatedLearnings: result.learnings.length,
13518
+ observationTypes: types
13519
+ };
13520
+ }
13521
+ /**
13522
+ * Get configuration
13523
+ */
13524
+ getConfig() {
13525
+ return { ...this.config };
13526
+ }
13527
+ /**
13528
+ * Update configuration
13529
+ */
13530
+ setConfig(config) {
13531
+ this.config = { ...this.config, ...config };
13532
+ }
13533
+ };
13534
+ function createSessionEndHook(projectPath, agent = "claude-code", config = {}) {
13535
+ return new SessionEndHook(projectPath, agent, config);
13536
+ }
13537
+ async function executeSessionEndHook(projectPath, context, config = {}) {
13538
+ const hook = new SessionEndHook(projectPath, context.agent || "claude-code", config);
13539
+ return hook.execute(context);
13540
+ }
13541
+
13542
+ // src/memory/hooks/manager.ts
13543
+ import { randomUUID as randomUUID10 } from "crypto";
13544
+ var MemoryHookManager = class {
13545
+ config;
13546
+ projectPath;
13547
+ agent;
13548
+ sessionId;
13549
+ startedAt;
13550
+ sessionStartHook;
13551
+ postToolUseHook;
13552
+ sessionEndHook;
13553
+ stats;
13554
+ constructor(projectPath, agent = "claude-code", config = {}, sessionId) {
13555
+ this.projectPath = projectPath;
13556
+ this.agent = agent;
13557
+ this.config = { ...DEFAULT_MEMORY_HOOK_CONFIG, ...config };
13558
+ this.sessionId = sessionId || randomUUID10();
13559
+ this.startedAt = (/* @__PURE__ */ new Date()).toISOString();
13560
+ this.sessionStartHook = new SessionStartHook(projectPath, agent, this.config);
13561
+ this.postToolUseHook = new PostToolUseHook(projectPath, agent, this.config, this.sessionId);
13562
+ this.sessionEndHook = new SessionEndHook(projectPath, agent, this.config);
13563
+ this.stats = {
13564
+ sessionId: this.sessionId,
13565
+ startedAt: this.startedAt,
13566
+ observationsCaptured: 0,
13567
+ learningsInjected: 0,
13568
+ tokensUsed: 0,
13569
+ toolCallsCaptured: 0,
13570
+ errorsRecorded: 0,
13571
+ solutionsRecorded: 0
13572
+ };
13573
+ }
13574
+ /**
13575
+ * Handle session start
13576
+ */
13577
+ async onSessionStart(workingDirectory) {
13578
+ const context = {
13579
+ session_id: this.sessionId,
13580
+ project_path: this.projectPath,
13581
+ agent: this.agent,
13582
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
13583
+ working_directory: workingDirectory
13584
+ };
13585
+ const result = await this.sessionStartHook.execute(context);
13586
+ this.stats.learningsInjected = result.learnings.length;
13587
+ this.stats.tokensUsed = result.tokenCount;
13588
+ return this.sessionStartHook.generateHookOutputFromResult(result);
13589
+ }
13590
+ /**
13591
+ * Handle tool use
13592
+ */
13593
+ async onToolUse(event) {
13594
+ const result = await this.postToolUseHook.execute(event);
13595
+ if (result.captured) {
13596
+ this.stats.observationsCaptured++;
13597
+ this.stats.toolCallsCaptured++;
13598
+ if (result.observation?.type === "error") {
13599
+ this.stats.errorsRecorded++;
13600
+ } else if (result.observation?.type === "solution") {
13601
+ this.stats.solutionsRecorded++;
13602
+ }
13603
+ }
13604
+ await this.checkAutoCompression();
13605
+ return this.postToolUseHook.generateHookOutputFromResult(event, result);
13606
+ }
13607
+ /**
13608
+ * Handle session end
13609
+ */
13610
+ async onSessionEnd(toolCallsCount) {
13611
+ const context = {
13612
+ session_id: this.sessionId,
13613
+ project_path: this.projectPath,
13614
+ agent: this.agent,
13615
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
13616
+ duration_ms: Date.now() - new Date(this.startedAt).getTime(),
13617
+ tool_calls_count: toolCallsCount
13618
+ };
13619
+ const result = await this.sessionEndHook.execute(context);
13620
+ return this.sessionEndHook.generateHookOutputFromResult(result);
13621
+ }
13622
+ /**
13623
+ * Record an error manually
13624
+ */
13625
+ recordError(error, context) {
13626
+ const obs = this.postToolUseHook.recordError(error, context);
13627
+ this.stats.observationsCaptured++;
13628
+ this.stats.errorsRecorded++;
13629
+ return obs;
13630
+ }
13631
+ /**
13632
+ * Record a solution manually
13633
+ */
13634
+ recordSolution(solution, context, relatedError) {
13635
+ const obs = this.postToolUseHook.recordSolution(solution, context, relatedError);
13636
+ this.stats.observationsCaptured++;
13637
+ this.stats.solutionsRecorded++;
13638
+ return obs;
13639
+ }
13640
+ /**
13641
+ * Record a decision manually
13642
+ */
13643
+ recordDecision(decision, options, context) {
13644
+ const obs = this.postToolUseHook.recordDecision(decision, options, context);
13645
+ this.stats.observationsCaptured++;
13646
+ return obs;
13647
+ }
13648
+ /**
13649
+ * Record file changes manually
13650
+ */
13651
+ recordFileChange(files, action, context) {
13652
+ const obs = this.postToolUseHook.recordFileChange(files, action, context);
13653
+ this.stats.observationsCaptured++;
13654
+ return obs;
13655
+ }
13656
+ /**
13657
+ * Force compression (regardless of threshold)
13658
+ */
13659
+ async forceCompress() {
13660
+ const result = await this.sessionEndHook.forceCompress(this.sessionId);
13661
+ return result.learnings;
13662
+ }
13663
+ /**
13664
+ * Preview compression without executing
13665
+ */
13666
+ async previewCompression() {
13667
+ return this.sessionEndHook.preview(this.sessionId);
13668
+ }
13669
+ /**
13670
+ * Get current stats
13671
+ */
13672
+ getStats() {
13673
+ return { ...this.stats };
13674
+ }
13675
+ /**
13676
+ * Get session ID
13677
+ */
13678
+ getSessionId() {
13679
+ return this.sessionId;
13680
+ }
13681
+ /**
13682
+ * Get observation count
13683
+ */
13684
+ getObservationCount() {
13685
+ return this.postToolUseHook.getObservationCount();
13686
+ }
13687
+ /**
13688
+ * Get pending errors
13689
+ */
13690
+ getPendingErrors() {
13691
+ return this.postToolUseHook.getPendingErrors();
13692
+ }
13693
+ /**
13694
+ * Get configuration
13695
+ */
13696
+ getConfig() {
13697
+ return { ...this.config };
13698
+ }
13699
+ /**
13700
+ * Update configuration
13701
+ */
13702
+ setConfig(config) {
13703
+ this.config = { ...this.config, ...config };
13704
+ this.sessionStartHook.setConfig(this.config);
13705
+ this.postToolUseHook.setConfig(this.config);
13706
+ this.sessionEndHook.setConfig(this.config);
13707
+ }
13708
+ /**
13709
+ * Check if auto-compression should trigger
13710
+ */
13711
+ async checkAutoCompression() {
13712
+ if (!this.config.enabled) return;
13713
+ const count = this.postToolUseHook.getObservationCount();
13714
+ if (count >= this.config.compressionThreshold) {
13715
+ await this.sessionEndHook.forceCompress(this.sessionId);
13716
+ }
13717
+ }
13718
+ /**
13719
+ * Generate Claude Code hooks.json configuration
13720
+ */
13721
+ generateClaudeCodeHooksConfig() {
13722
+ return {
13723
+ hooks: [
13724
+ {
13725
+ matcher: ".*",
13726
+ hooks: [
13727
+ {
13728
+ type: "command",
13729
+ command: `npx skillkit memory hook session-start --project "${this.projectPath}"`,
13730
+ event: "SessionStart"
13731
+ },
13732
+ {
13733
+ type: "command",
13734
+ command: `npx skillkit memory hook post-tool-use --project "${this.projectPath}"`,
13735
+ event: "PostToolUse"
13736
+ },
13737
+ {
13738
+ type: "command",
13739
+ command: `npx skillkit memory hook session-end --project "${this.projectPath}"`,
13740
+ event: "SessionEnd"
13741
+ }
13742
+ ]
13743
+ }
13744
+ ]
13745
+ };
13746
+ }
13747
+ };
13748
+ function createMemoryHookManager(projectPath, agent = "claude-code", config = {}, sessionId) {
13749
+ return new MemoryHookManager(projectPath, agent, config, sessionId);
13750
+ }
13751
+
13752
+ // src/memory/claude-md-updater.ts
13753
+ import { existsSync as existsSync26, readFileSync as readFileSync16, writeFileSync as writeFileSync14, mkdirSync as mkdirSync15 } from "fs";
13754
+ import { join as join25, dirname as dirname7, basename as basename11 } from "path";
13755
+ import { homedir as homedir12 } from "os";
13756
+ var SKILLKIT_MARKER = "<!-- Auto-populated by SkillKit -->";
13757
+ var DEFAULT_UPDATE_OPTIONS = {
13758
+ minEffectiveness: 60,
13759
+ maxLearnings: 20,
13760
+ includeGlobal: false,
13761
+ preserveManualEntries: true,
13762
+ sectionTitle: "LEARNED",
13763
+ addTimestamp: true
13764
+ };
13765
+ var ClaudeMdUpdater = class {
13766
+ projectPath;
13767
+ claudeMdPath;
13768
+ constructor(projectPath, claudeMdPath) {
13769
+ this.projectPath = projectPath;
13770
+ this.claudeMdPath = claudeMdPath || join25(projectPath, "CLAUDE.md");
13771
+ }
13772
+ /**
13773
+ * Parse CLAUDE.md to extract structure
13774
+ */
13775
+ parse() {
13776
+ if (!existsSync26(this.claudeMdPath)) {
13777
+ return {
13778
+ content: "",
13779
+ sections: /* @__PURE__ */ new Map(),
13780
+ hasLearnedSection: false
13781
+ };
13782
+ }
13783
+ const content = readFileSync16(this.claudeMdPath, "utf-8");
13784
+ const sections = /* @__PURE__ */ new Map();
13785
+ const lines = content.split("\n");
13786
+ let currentSection = null;
13787
+ let sectionStart = 0;
13788
+ let sectionContent = [];
13789
+ for (let i = 0; i < lines.length; i++) {
13790
+ const line = lines[i];
13791
+ const headerMatch = line.match(/^(#{1,3})\s+(.+)$/);
13792
+ if (headerMatch) {
13793
+ if (currentSection) {
13794
+ sections.set(currentSection, {
13795
+ start: sectionStart,
13796
+ end: i - 1,
13797
+ content: sectionContent.join("\n")
13798
+ });
13799
+ }
13800
+ currentSection = headerMatch[2].trim();
13801
+ sectionStart = i;
13802
+ sectionContent = [line];
13803
+ } else if (currentSection) {
13804
+ sectionContent.push(line);
13805
+ }
13806
+ }
13807
+ if (currentSection) {
13808
+ sections.set(currentSection, {
13809
+ start: sectionStart,
13810
+ end: lines.length - 1,
13811
+ content: sectionContent.join("\n")
13812
+ });
13813
+ }
13814
+ const learnedSection = sections.get("LEARNED") || sections.get("Learned");
13815
+ const hasLearnedSection = !!learnedSection;
13816
+ return {
13817
+ content,
13818
+ sections,
13819
+ hasLearnedSection,
13820
+ learnedSectionContent: learnedSection?.content,
13821
+ learnedSectionRange: learnedSection ? { start: learnedSection.start, end: learnedSection.end } : void 0
13822
+ };
13823
+ }
13824
+ /**
13825
+ * Get learnings to add to CLAUDE.md
13826
+ */
13827
+ getLearningsForClaudeMd(options = {}) {
13828
+ const opts = { ...DEFAULT_UPDATE_OPTIONS, ...options };
13829
+ const projectStore = new LearningStore("project", this.projectPath);
13830
+ let learnings = projectStore.getAll();
13831
+ if (opts.includeGlobal) {
13832
+ const globalStore = new LearningStore("global");
13833
+ learnings = [...learnings, ...globalStore.getAll()];
13834
+ }
13835
+ return learnings.filter((l) => (l.effectiveness ?? 0) >= opts.minEffectiveness || l.useCount >= 3).sort((a, b) => {
13836
+ const scoreA = (a.effectiveness ?? 50) + a.useCount * 5;
13837
+ const scoreB = (b.effectiveness ?? 50) + b.useCount * 5;
13838
+ return scoreB - scoreA;
13839
+ }).slice(0, opts.maxLearnings);
13840
+ }
13841
+ /**
13842
+ * Format learnings as CLAUDE.md LEARNED section
13843
+ */
13844
+ formatLearnedSection(learnings, options = {}) {
13845
+ const opts = { ...DEFAULT_UPDATE_OPTIONS, ...options };
13846
+ const lines = [];
13847
+ lines.push(`## ${opts.sectionTitle}`);
13848
+ lines.push("");
13849
+ lines.push(SKILLKIT_MARKER);
13850
+ if (opts.addTimestamp) {
13851
+ lines.push(`<!-- Last updated: ${(/* @__PURE__ */ new Date()).toISOString()} -->`);
13852
+ }
13853
+ lines.push("");
13854
+ const byCategory = this.categorizeLearnings(learnings);
13855
+ for (const [category, categoryLearnings] of byCategory) {
13856
+ if (categoryLearnings.length > 0) {
13857
+ lines.push(`### ${category}`);
13858
+ for (const learning of categoryLearnings) {
13859
+ const title = this.formatLearningTitle(learning);
13860
+ const summary = this.extractSummary(learning.content);
13861
+ lines.push(`${title}`);
13862
+ lines.push(summary);
13863
+ lines.push("");
13864
+ }
13865
+ }
13866
+ }
13867
+ return lines.join("\n");
13868
+ }
13869
+ /**
13870
+ * Update CLAUDE.md with learnings
13871
+ */
13872
+ update(options = {}) {
13873
+ const opts = { ...DEFAULT_UPDATE_OPTIONS, ...options };
13874
+ const learnings = this.getLearningsForClaudeMd(opts);
13875
+ if (learnings.length === 0) {
13876
+ return {
13877
+ updated: false,
13878
+ path: this.claudeMdPath,
13879
+ learningsAdded: 0,
13880
+ learningSummaries: [],
13881
+ previousLearnings: 0
13882
+ };
13883
+ }
13884
+ const parsed = this.parse();
13885
+ const newSection = this.formatLearnedSection(learnings, opts);
13886
+ let newContent;
13887
+ let previousLearnings = 0;
13888
+ if (parsed.hasLearnedSection && parsed.learnedSectionRange) {
13889
+ if (opts.preserveManualEntries) {
13890
+ const existingContent = parsed.learnedSectionContent || "";
13891
+ const manualEntries = this.extractManualEntries(existingContent);
13892
+ previousLearnings = this.countLearnings(existingContent);
13893
+ const combinedSection = this.combineWithManualEntries(newSection, manualEntries);
13894
+ const lines = parsed.content.split("\n");
13895
+ const before = lines.slice(0, parsed.learnedSectionRange.start).join("\n");
13896
+ const after = lines.slice(parsed.learnedSectionRange.end + 1).join("\n");
13897
+ newContent = before + (before ? "\n" : "") + combinedSection + (after ? "\n" + after : "");
13898
+ } else {
13899
+ const lines = parsed.content.split("\n");
13900
+ const before = lines.slice(0, parsed.learnedSectionRange.start).join("\n");
13901
+ const after = lines.slice(parsed.learnedSectionRange.end + 1).join("\n");
13902
+ newContent = before + (before ? "\n" : "") + newSection + (after ? "\n" + after : "");
13903
+ }
13904
+ } else if (parsed.content) {
13905
+ newContent = parsed.content + "\n\n" + newSection;
13906
+ } else {
13907
+ newContent = this.createNewClaudeMd(newSection);
13908
+ }
13909
+ const dir = dirname7(this.claudeMdPath);
13910
+ if (!existsSync26(dir)) {
13911
+ mkdirSync15(dir, { recursive: true });
13912
+ }
13913
+ writeFileSync14(this.claudeMdPath, newContent, "utf-8");
13914
+ return {
13915
+ updated: true,
13916
+ path: this.claudeMdPath,
13917
+ learningsAdded: learnings.length,
13918
+ learningSummaries: learnings.map((l) => l.title),
13919
+ previousLearnings
13920
+ };
13921
+ }
13922
+ /**
13923
+ * Preview update without writing
13924
+ */
13925
+ preview(options = {}) {
13926
+ const learnings = this.getLearningsForClaudeMd(options);
13927
+ const formattedSection = this.formatLearnedSection(learnings, options);
13928
+ return {
13929
+ learnings,
13930
+ formattedSection,
13931
+ wouldUpdate: learnings.length > 0
13932
+ };
13933
+ }
13934
+ /**
13935
+ * Check if CLAUDE.md exists
13936
+ */
13937
+ exists() {
13938
+ return existsSync26(this.claudeMdPath);
13939
+ }
13940
+ /**
13941
+ * Get CLAUDE.md path
13942
+ */
13943
+ getPath() {
13944
+ return this.claudeMdPath;
13945
+ }
13946
+ categorizeLearnings(learnings) {
13947
+ const categories = /* @__PURE__ */ new Map();
13948
+ for (const learning of learnings) {
13949
+ let category = "General";
13950
+ if (learning.patterns?.includes("error-handling")) {
13951
+ category = "Error-Handling";
13952
+ } else if (learning.patterns?.includes("debugging")) {
13953
+ category = "Debugging";
13954
+ } else if (learning.patterns?.includes("architecture")) {
13955
+ category = "Architecture";
13956
+ } else if (learning.patterns?.includes("workflow")) {
13957
+ category = "Workflow";
13958
+ } else if (learning.tags.some((t) => t.includes("react") || t.includes("typescript"))) {
13959
+ category = "Code-Patterns";
13960
+ }
13961
+ const existing = categories.get(category) || [];
13962
+ existing.push(learning);
13963
+ categories.set(category, existing);
13964
+ }
13965
+ return categories;
13966
+ }
13967
+ formatLearningTitle(learning) {
13968
+ const tags = learning.tags.slice(0, 3).join(", ");
13969
+ return tags ? `**${tags}**: ${learning.title}` : `**${learning.title}**`;
13970
+ }
13971
+ extractSummary(content) {
13972
+ const lines = content.split("\n").filter((l) => l.trim());
13973
+ for (const line of lines) {
13974
+ const cleaned = line.replace(/^#+\s*/, "").replace(/^\*\*.*?\*\*:?\s*/, "");
13975
+ if (cleaned.length > 20 && !cleaned.startsWith("#")) {
13976
+ return cleaned.slice(0, 200) + (cleaned.length > 200 ? "..." : "");
13977
+ }
13978
+ }
13979
+ return content.slice(0, 200) + (content.length > 200 ? "..." : "");
13980
+ }
13981
+ extractManualEntries(sectionContent) {
13982
+ const lines = sectionContent.split("\n");
13983
+ const manualEntries = [];
13984
+ let inManualEntry = false;
13985
+ let currentEntry = [];
13986
+ for (const line of lines) {
13987
+ if (line.includes(SKILLKIT_MARKER)) {
13988
+ inManualEntry = false;
13989
+ continue;
13990
+ }
13991
+ if (line.startsWith("### ") && !line.includes("Auto-populated")) {
13992
+ if (currentEntry.length > 0) {
13993
+ manualEntries.push(currentEntry.join("\n"));
13994
+ }
13995
+ inManualEntry = true;
13996
+ currentEntry = [line];
13997
+ } else if (inManualEntry) {
13998
+ currentEntry.push(line);
13999
+ }
14000
+ }
14001
+ if (currentEntry.length > 0) {
14002
+ manualEntries.push(currentEntry.join("\n"));
14003
+ }
14004
+ return manualEntries.filter((e) => e.trim().length > 0);
14005
+ }
14006
+ combineWithManualEntries(autoSection, manualEntries) {
14007
+ if (manualEntries.length === 0) {
14008
+ return autoSection;
14009
+ }
14010
+ const lines = autoSection.split("\n");
14011
+ const combinedLines = [...lines];
14012
+ combinedLines.push("");
14013
+ combinedLines.push("### Manual Entries");
14014
+ combinedLines.push("<!-- Preserved from previous edits -->");
14015
+ combinedLines.push("");
14016
+ for (const entry of manualEntries) {
14017
+ combinedLines.push(entry);
14018
+ combinedLines.push("");
14019
+ }
14020
+ return combinedLines.join("\n");
14021
+ }
14022
+ countLearnings(content) {
14023
+ const matches = content.match(/^\*\*[^*]+\*\*/gm);
14024
+ return matches ? matches.length : 0;
14025
+ }
14026
+ createNewClaudeMd(learnedSection) {
14027
+ const projectName = basename11(this.projectPath) || "Project";
14028
+ return `# ${projectName}
14029
+
14030
+ ${learnedSection}
14031
+ `;
14032
+ }
14033
+ };
14034
+ function createClaudeMdUpdater(projectPath, claudeMdPath) {
14035
+ return new ClaudeMdUpdater(projectPath, claudeMdPath);
14036
+ }
14037
+ function updateClaudeMd(projectPath, options = {}) {
14038
+ const updater = new ClaudeMdUpdater(projectPath);
14039
+ return updater.update(options);
14040
+ }
14041
+ function syncGlobalClaudeMd(options = {}) {
14042
+ const globalClaudeMdPath = join25(homedir12(), ".claude", "CLAUDE.md");
14043
+ const updater = new ClaudeMdUpdater(homedir12(), globalClaudeMdPath);
14044
+ const globalOpts = {
14045
+ ...options,
14046
+ includeGlobal: true,
14047
+ sectionTitle: "Global Learnings"
14048
+ };
14049
+ return updater.update(globalOpts);
14050
+ }
14051
+
14052
+ // src/memory/progressive-disclosure.ts
14053
+ var TOKEN_ESTIMATES = {
14054
+ index: 50,
14055
+ timeline: 200,
14056
+ details: 600
14057
+ };
14058
+ var ProgressiveDisclosureManager = class {
14059
+ projectStore;
14060
+ globalStore;
14061
+ constructor(projectPath, projectName) {
14062
+ this.projectStore = new LearningStore("project", projectPath, projectName);
14063
+ this.globalStore = new LearningStore("global");
14064
+ }
14065
+ /**
14066
+ * Layer 1: Get index of all learnings
14067
+ * Minimal tokens (~50-100 per entry)
14068
+ */
14069
+ getIndex(options = {}) {
14070
+ const projectLearnings = this.projectStore.getAll();
14071
+ const globalLearnings = options.includeGlobal ? this.globalStore.getAll() : [];
14072
+ const allLearnings = [...projectLearnings, ...globalLearnings];
14073
+ return allLearnings.map((learning) => this.toIndexEntry(learning)).sort((a, b) => {
14074
+ const scoreA = (a.effectiveness ?? 50) + a.useCount * 5;
14075
+ const scoreB = (b.effectiveness ?? 50) + b.useCount * 5;
14076
+ return scoreB - scoreA;
14077
+ }).slice(0, options.maxResults ?? 50);
14078
+ }
14079
+ /**
14080
+ * Layer 2: Get timeline entries for specific IDs
14081
+ * Medium tokens (~200 per entry)
14082
+ */
14083
+ getTimeline(ids, options = {}) {
14084
+ const entries = [];
14085
+ for (const id of ids) {
14086
+ let learning = this.projectStore.getById(id);
14087
+ if (!learning && options.includeGlobal) {
14088
+ learning = this.globalStore.getById(id);
14089
+ }
14090
+ if (learning) {
14091
+ entries.push(this.toTimelineEntry(learning));
14092
+ }
14093
+ }
14094
+ return entries.slice(0, options.maxResults ?? 20);
14095
+ }
14096
+ /**
14097
+ * Layer 3: Get full details for specific IDs
14098
+ * High tokens (~500-1000 per entry)
14099
+ */
14100
+ getDetails(ids, options = {}) {
14101
+ const entries = [];
14102
+ for (const id of ids) {
14103
+ let learning = this.projectStore.getById(id);
14104
+ let store = this.projectStore;
14105
+ if (!learning && options.includeGlobal) {
14106
+ learning = this.globalStore.getById(id);
14107
+ store = this.globalStore;
14108
+ }
14109
+ if (learning) {
14110
+ store.incrementUseCount(id);
14111
+ entries.push(this.toDetailsEntry(learning));
14112
+ }
14113
+ }
14114
+ return entries.slice(0, options.maxResults ?? 10);
14115
+ }
14116
+ /**
14117
+ * Smart retrieval with automatic layer selection
14118
+ * Uses minimum tokens needed to satisfy the query.
14119
+ *
14120
+ * Note: tokensUsed reflects cumulative cost of the retrieval operation
14121
+ * (index lookup + any deeper layer fetches), not just the returned entries.
14122
+ * This is intentional since progressive disclosure requires scanning
14123
+ * the index first before fetching timeline/details.
14124
+ */
14125
+ smartRetrieve(query, tokenBudget = 2e3, options = {}) {
14126
+ if (tokenBudget <= 0) {
14127
+ return {
14128
+ layer: 1,
14129
+ entries: [],
14130
+ tokensUsed: 0,
14131
+ tokensRemaining: 0
14132
+ };
14133
+ }
14134
+ const index = this.getIndex(options);
14135
+ if (index.length === 0) {
14136
+ return {
14137
+ layer: 1,
14138
+ entries: [],
14139
+ tokensUsed: 0,
14140
+ tokensRemaining: tokenBudget
14141
+ };
14142
+ }
14143
+ const indexTokens = index.length * TOKEN_ESTIMATES.index;
14144
+ if (tokenBudget < indexTokens) {
14145
+ const maxEntries = Math.floor(tokenBudget / TOKEN_ESTIMATES.index);
14146
+ const limitedIndex = index.slice(0, maxEntries);
14147
+ return {
14148
+ layer: 1,
14149
+ entries: limitedIndex,
14150
+ tokensUsed: limitedIndex.length * TOKEN_ESTIMATES.index,
14151
+ tokensRemaining: tokenBudget - limitedIndex.length * TOKEN_ESTIMATES.index
14152
+ };
14153
+ }
14154
+ const relevantIds = this.findRelevantIds(index, query, options.minRelevance ?? 0);
14155
+ if (relevantIds.length === 0) {
14156
+ return {
14157
+ layer: 1,
14158
+ entries: index,
14159
+ tokensUsed: indexTokens,
14160
+ tokensRemaining: tokenBudget - indexTokens
14161
+ };
14162
+ }
14163
+ const remainingBudget = tokenBudget - indexTokens;
14164
+ const maxTimelineEntries = Math.floor(remainingBudget / TOKEN_ESTIMATES.timeline);
14165
+ if (maxTimelineEntries >= 1) {
14166
+ const timelineIds = relevantIds.slice(0, Math.min(maxTimelineEntries, 10));
14167
+ const timeline = this.getTimeline(timelineIds, options);
14168
+ const timelineTokens = timeline.length * TOKEN_ESTIMATES.timeline;
14169
+ const afterTimelineBudget = remainingBudget - timelineTokens;
14170
+ const maxDetailsEntries = Math.floor(afterTimelineBudget / TOKEN_ESTIMATES.details);
14171
+ if (maxDetailsEntries >= 1) {
14172
+ const detailsIds = timelineIds.slice(0, Math.min(maxDetailsEntries, 5));
14173
+ const details = this.getDetails(detailsIds, options);
14174
+ const detailsTokens = details.length * TOKEN_ESTIMATES.details;
14175
+ return {
14176
+ layer: 3,
14177
+ entries: details,
14178
+ tokensUsed: indexTokens + timelineTokens + detailsTokens,
14179
+ tokensRemaining: tokenBudget - (indexTokens + timelineTokens + detailsTokens)
14180
+ };
14181
+ }
14182
+ return {
14183
+ layer: 2,
14184
+ entries: timeline,
14185
+ tokensUsed: indexTokens + timelineTokens,
14186
+ tokensRemaining: tokenBudget - (indexTokens + timelineTokens)
14187
+ };
14188
+ }
14189
+ return {
14190
+ layer: 1,
14191
+ entries: index,
14192
+ tokensUsed: indexTokens,
14193
+ tokensRemaining: tokenBudget - indexTokens
14194
+ };
14195
+ }
14196
+ /**
14197
+ * Estimate tokens for a given layer and count
14198
+ */
14199
+ estimateTokens(layer, count) {
14200
+ const estimate = {
14201
+ 1: TOKEN_ESTIMATES.index,
14202
+ 2: TOKEN_ESTIMATES.timeline,
14203
+ 3: TOKEN_ESTIMATES.details
14204
+ };
14205
+ return estimate[layer] * count;
14206
+ }
14207
+ /**
14208
+ * Format entries for injection
14209
+ */
14210
+ formatForInjection(entries, layer) {
14211
+ if (entries.length === 0) return "";
14212
+ const lines = ["<skillkit-memories>"];
14213
+ switch (layer) {
14214
+ case 1:
14215
+ lines.push("<!-- Memory Index (summaries only) -->");
14216
+ for (const entry of entries) {
14217
+ lines.push(`- [${entry.id.slice(0, 8)}] ${entry.title} (${entry.tags.join(", ")})`);
14218
+ }
14219
+ break;
14220
+ case 2:
14221
+ lines.push("<!-- Memory Timeline (with context) -->");
14222
+ for (const entry of entries) {
14223
+ lines.push(`## ${entry.title}`);
14224
+ lines.push(`ID: ${entry.id.slice(0, 8)} | Tags: ${entry.tags.join(", ")}`);
14225
+ if (entry.frameworks && entry.frameworks.length > 0) {
14226
+ lines.push(`Frameworks: ${entry.frameworks.join(", ")}`);
14227
+ }
14228
+ lines.push("");
14229
+ lines.push(entry.excerpt);
14230
+ lines.push("");
14231
+ }
14232
+ break;
14233
+ case 3:
14234
+ lines.push("<!-- Memory Details (full content) -->");
14235
+ for (const entry of entries) {
14236
+ lines.push(`## ${entry.title}`);
14237
+ lines.push(`ID: ${entry.id.slice(0, 8)} | Tags: ${entry.tags.join(", ")}`);
14238
+ if (entry.frameworks && entry.frameworks.length > 0) {
14239
+ lines.push(`Frameworks: ${entry.frameworks.join(", ")}`);
14240
+ }
14241
+ if (entry.patterns && entry.patterns.length > 0) {
14242
+ lines.push(`Patterns: ${entry.patterns.join(", ")}`);
14243
+ }
14244
+ lines.push("");
14245
+ lines.push(entry.content);
14246
+ lines.push("");
14247
+ }
14248
+ break;
14249
+ }
14250
+ lines.push("</skillkit-memories>");
14251
+ return lines.join("\n");
14252
+ }
14253
+ toIndexEntry(learning) {
14254
+ return {
14255
+ id: learning.id,
14256
+ title: learning.title,
14257
+ timestamp: learning.updatedAt,
14258
+ tags: learning.tags,
14259
+ scope: learning.scope,
14260
+ effectiveness: learning.effectiveness,
14261
+ useCount: learning.useCount
14262
+ };
14263
+ }
14264
+ toTimelineEntry(learning) {
14265
+ const timeline = this.buildActivityTimeline(learning);
14266
+ return {
14267
+ id: learning.id,
14268
+ title: learning.title,
14269
+ timestamp: learning.updatedAt,
14270
+ tags: learning.tags,
14271
+ scope: learning.scope,
14272
+ effectiveness: learning.effectiveness,
14273
+ useCount: learning.useCount,
14274
+ excerpt: learning.content.slice(0, 200) + (learning.content.length > 200 ? "..." : ""),
14275
+ frameworks: learning.frameworks,
14276
+ patterns: learning.patterns,
14277
+ sourceCount: learning.sourceObservations?.length ?? 0,
14278
+ lastUsed: learning.lastUsed,
14279
+ activityTimeline: timeline
14280
+ };
14281
+ }
14282
+ toDetailsEntry(learning) {
14283
+ const timeline = this.buildActivityTimeline(learning);
14284
+ return {
14285
+ id: learning.id,
14286
+ title: learning.title,
14287
+ timestamp: learning.updatedAt,
14288
+ tags: learning.tags,
14289
+ scope: learning.scope,
14290
+ effectiveness: learning.effectiveness,
14291
+ useCount: learning.useCount,
14292
+ excerpt: learning.content.slice(0, 200) + (learning.content.length > 200 ? "..." : ""),
14293
+ frameworks: learning.frameworks,
14294
+ patterns: learning.patterns,
14295
+ sourceCount: learning.sourceObservations?.length ?? 0,
14296
+ lastUsed: learning.lastUsed,
14297
+ activityTimeline: timeline,
14298
+ content: learning.content,
14299
+ sourceObservations: learning.sourceObservations
14300
+ };
14301
+ }
14302
+ buildActivityTimeline(learning) {
14303
+ const timeline = [];
14304
+ timeline.push({
14305
+ timestamp: learning.createdAt,
14306
+ type: "created",
14307
+ description: `Learning created from ${learning.source}`
14308
+ });
14309
+ if (learning.updatedAt !== learning.createdAt) {
14310
+ timeline.push({
14311
+ timestamp: learning.updatedAt,
14312
+ type: "updated"
14313
+ });
14314
+ }
14315
+ if (learning.lastUsed) {
14316
+ timeline.push({
14317
+ timestamp: learning.lastUsed,
14318
+ type: "used",
14319
+ description: `Used ${learning.useCount} times`
14320
+ });
14321
+ }
14322
+ if (learning.effectiveness !== void 0) {
14323
+ timeline.push({
14324
+ timestamp: learning.updatedAt,
14325
+ type: "rated",
14326
+ description: `Effectiveness: ${learning.effectiveness}%`
14327
+ });
14328
+ }
14329
+ return timeline.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
14330
+ }
14331
+ findRelevantIds(index, query, minRelevance = 0) {
14332
+ const queryWords = query.toLowerCase().split(/\s+/).filter((w) => w.length > 2);
14333
+ const scored = [];
14334
+ for (const entry of index) {
14335
+ let score = 0;
14336
+ const titleWords = entry.title.toLowerCase().split(/\s+/);
14337
+ for (const qw of queryWords) {
14338
+ if (titleWords.some((tw) => tw.includes(qw))) {
14339
+ score += 10;
14340
+ }
14341
+ }
14342
+ const tags = entry.tags.map((t) => t.toLowerCase());
14343
+ for (const qw of queryWords) {
14344
+ if (tags.includes(qw)) {
14345
+ score += 20;
14346
+ }
14347
+ }
14348
+ score += (entry.effectiveness ?? 50) / 10;
14349
+ score += Math.min(entry.useCount * 2, 20);
14350
+ if (score >= minRelevance) {
14351
+ scored.push({ id: entry.id, score });
14352
+ }
14353
+ }
14354
+ return scored.sort((a, b) => b.score - a.score).map((s) => s.id);
14355
+ }
14356
+ };
14357
+ function createProgressiveDisclosureManager(projectPath, projectName) {
14358
+ return new ProgressiveDisclosureManager(projectPath, projectName);
14359
+ }
14360
+
12879
14361
  // src/team/manager.ts
12880
- import { existsSync as existsSync26, readFileSync as readFileSync16, writeFileSync as writeFileSync14, mkdirSync as mkdirSync15 } from "fs";
12881
- import { join as join25, dirname as dirname7 } from "path";
14362
+ import { existsSync as existsSync27, readFileSync as readFileSync17, writeFileSync as writeFileSync15, mkdirSync as mkdirSync16 } from "fs";
14363
+ import { join as join26, dirname as dirname8 } from "path";
12882
14364
  import { execSync as execSync6 } from "child_process";
12883
14365
  import { parse as yamlParse, stringify as yamlStringify } from "yaml";
12884
14366
  var TEAM_CONFIG_FILE = "team.yaml";
@@ -12899,9 +14381,9 @@ var TeamManager = class {
12899
14381
  ...config,
12900
14382
  teamId
12901
14383
  };
12902
- const teamDir = join25(this.projectPath, TEAM_DIR);
12903
- if (!existsSync26(teamDir)) {
12904
- mkdirSync15(teamDir, { recursive: true });
14384
+ const teamDir = join26(this.projectPath, TEAM_DIR);
14385
+ if (!existsSync27(teamDir)) {
14386
+ mkdirSync16(teamDir, { recursive: true });
12905
14387
  }
12906
14388
  this.saveConfig(fullConfig);
12907
14389
  this.config = fullConfig;
@@ -12921,12 +14403,12 @@ var TeamManager = class {
12921
14403
  * Load existing team configuration
12922
14404
  */
12923
14405
  load() {
12924
- const configPath = join25(this.projectPath, TEAM_DIR, TEAM_CONFIG_FILE);
12925
- if (!existsSync26(configPath)) {
14406
+ const configPath = join26(this.projectPath, TEAM_DIR, TEAM_CONFIG_FILE);
14407
+ if (!existsSync27(configPath)) {
12926
14408
  return null;
12927
14409
  }
12928
14410
  try {
12929
- const content = readFileSync16(configPath, "utf-8");
14411
+ const content = readFileSync17(configPath, "utf-8");
12930
14412
  this.config = this.parseYaml(content);
12931
14413
  this.loadRegistry();
12932
14414
  return this.config;
@@ -12957,8 +14439,8 @@ var TeamManager = class {
12957
14439
  if (!skillPath) {
12958
14440
  throw new Error(`Skill "${options.skillName}" not found locally.`);
12959
14441
  }
12960
- const skillMdPath = join25(skillPath, "SKILL.md");
12961
- const skillContent = existsSync26(skillMdPath) ? readFileSync16(skillMdPath, "utf-8") : "";
14442
+ const skillMdPath = join26(skillPath, "SKILL.md");
14443
+ const skillContent = existsSync27(skillMdPath) ? readFileSync17(skillMdPath, "utf-8") : "";
12962
14444
  const metadata = this.extractFrontmatter(skillContent);
12963
14445
  const shared = {
12964
14446
  name: options.skillName,
@@ -13023,7 +14505,7 @@ var TeamManager = class {
13023
14505
  if (options.dryRun) {
13024
14506
  return {
13025
14507
  success: true,
13026
- path: join25(this.projectPath, ".skillkit", "skills", skillName)
14508
+ path: join26(this.projectPath, ".skillkit", "skills", skillName)
13027
14509
  };
13028
14510
  }
13029
14511
  try {
@@ -13073,9 +14555,9 @@ var TeamManager = class {
13073
14555
  if (!fetchResult.success || !fetchResult.path) {
13074
14556
  throw new Error(fetchResult.error || "Failed to fetch remote registry");
13075
14557
  }
13076
- const remoteRegistryPath = join25(fetchResult.path, TEAM_DIR, "registry.yaml");
13077
- if (existsSync26(remoteRegistryPath)) {
13078
- const remoteContent = readFileSync16(remoteRegistryPath, "utf-8");
14558
+ const remoteRegistryPath = join26(fetchResult.path, TEAM_DIR, "registry.yaml");
14559
+ if (existsSync27(remoteRegistryPath)) {
14560
+ const remoteContent = readFileSync17(remoteRegistryPath, "utf-8");
13079
14561
  const remoteRegistry = this.parseYaml(remoteContent);
13080
14562
  const localSkillNames = new Set(this.registry?.skills.map((s) => s.name) || []);
13081
14563
  for (const skill of remoteRegistry.skills) {
@@ -13121,32 +14603,32 @@ var TeamManager = class {
13121
14603
  return `team-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
13122
14604
  }
13123
14605
  saveConfig(config) {
13124
- const configPath = join25(this.projectPath, TEAM_DIR, TEAM_CONFIG_FILE);
13125
- const dir = dirname7(configPath);
13126
- if (!existsSync26(dir)) {
13127
- mkdirSync15(dir, { recursive: true });
14606
+ const configPath = join26(this.projectPath, TEAM_DIR, TEAM_CONFIG_FILE);
14607
+ const dir = dirname8(configPath);
14608
+ if (!existsSync27(dir)) {
14609
+ mkdirSync16(dir, { recursive: true });
13128
14610
  }
13129
- writeFileSync14(configPath, this.toYaml(config), "utf-8");
14611
+ writeFileSync15(configPath, this.toYaml(config), "utf-8");
13130
14612
  }
13131
14613
  loadRegistry() {
13132
- const registryPath = join25(this.projectPath, TEAM_DIR, "registry.yaml");
13133
- if (existsSync26(registryPath)) {
13134
- const content = readFileSync16(registryPath, "utf-8");
14614
+ const registryPath = join26(this.projectPath, TEAM_DIR, "registry.yaml");
14615
+ if (existsSync27(registryPath)) {
14616
+ const content = readFileSync17(registryPath, "utf-8");
13135
14617
  this.registry = this.parseYaml(content);
13136
14618
  }
13137
14619
  }
13138
14620
  saveRegistry(registry) {
13139
- const registryPath = join25(this.projectPath, TEAM_DIR, "registry.yaml");
13140
- writeFileSync14(registryPath, this.toYaml(registry), "utf-8");
14621
+ const registryPath = join26(this.projectPath, TEAM_DIR, "registry.yaml");
14622
+ writeFileSync15(registryPath, this.toYaml(registry), "utf-8");
13141
14623
  }
13142
14624
  findLocalSkill(skillName) {
13143
14625
  const possiblePaths = [
13144
- join25(this.projectPath, ".skillkit", "skills", skillName),
13145
- join25(this.projectPath, "skills", skillName),
13146
- join25(this.projectPath, ".claude", "skills", skillName)
14626
+ join26(this.projectPath, ".skillkit", "skills", skillName),
14627
+ join26(this.projectPath, "skills", skillName),
14628
+ join26(this.projectPath, ".claude", "skills", skillName)
13147
14629
  ];
13148
14630
  for (const p of possiblePaths) {
13149
- if (existsSync26(p)) {
14631
+ if (existsSync27(p)) {
13150
14632
  return p;
13151
14633
  }
13152
14634
  }
@@ -13163,13 +14645,13 @@ var TeamManager = class {
13163
14645
  }
13164
14646
  detectCompatibleAgents(skillPath) {
13165
14647
  const agents = [];
13166
- if (existsSync26(join25(skillPath, "SKILL.md"))) {
14648
+ if (existsSync27(join26(skillPath, "SKILL.md"))) {
13167
14649
  agents.push("claude-code", "codex", "gemini-cli", "universal");
13168
14650
  }
13169
- if (existsSync26(join25(skillPath, "skill.mdc"))) {
14651
+ if (existsSync27(join26(skillPath, "skill.mdc"))) {
13170
14652
  agents.push("cursor");
13171
14653
  }
13172
- if (existsSync26(join25(skillPath, "rules.md"))) {
14654
+ if (existsSync27(join26(skillPath, "rules.md"))) {
13173
14655
  agents.push("windsurf");
13174
14656
  }
13175
14657
  return agents.length > 0 ? agents : ["universal"];
@@ -13195,8 +14677,8 @@ function createTeamManager(projectPath) {
13195
14677
  }
13196
14678
 
13197
14679
  // src/team/bundle.ts
13198
- import { existsSync as existsSync27, readFileSync as readFileSync17, writeFileSync as writeFileSync15, mkdirSync as mkdirSync16, readdirSync as readdirSync6, statSync as statSync3 } from "fs";
13199
- import { join as join26, basename as basename9, resolve as resolve4, relative, dirname as dirname8, sep as sep3 } from "path";
14680
+ import { existsSync as existsSync28, readFileSync as readFileSync18, writeFileSync as writeFileSync16, mkdirSync as mkdirSync17, readdirSync as readdirSync6, statSync as statSync3 } from "fs";
14681
+ import { join as join27, basename as basename12, resolve as resolve4, relative, dirname as dirname9, sep as sep3 } from "path";
13200
14682
  import { createHash } from "crypto";
13201
14683
  var BUNDLE_VERSION = 1;
13202
14684
  var SkillBundle = class {
@@ -13218,7 +14700,7 @@ var SkillBundle = class {
13218
14700
  * Add a skill to the bundle
13219
14701
  */
13220
14702
  addSkill(skillPath, agents) {
13221
- const skillName = basename9(skillPath);
14703
+ const skillName = basename12(skillPath);
13222
14704
  if (this.skills.has(skillName)) {
13223
14705
  throw new Error(`Skill "${skillName}" already exists in bundle`);
13224
14706
  }
@@ -13280,13 +14762,13 @@ var SkillBundle = class {
13280
14762
  const readDir = (dir, prefix = "") => {
13281
14763
  const entries = readdirSync6(dir);
13282
14764
  for (const entry of entries) {
13283
- const fullPath = join26(dir, entry);
14765
+ const fullPath = join27(dir, entry);
13284
14766
  const relativePath = prefix ? `${prefix}/${entry}` : entry;
13285
14767
  const stat = statSync3(fullPath);
13286
14768
  if (stat.isDirectory()) {
13287
14769
  readDir(fullPath, relativePath);
13288
14770
  } else if (stat.isFile()) {
13289
- const content = readFileSync17(fullPath, "utf-8");
14771
+ const content = readFileSync18(fullPath, "utf-8");
13290
14772
  contents.push(`--- ${relativePath} ---
13291
14773
  ${content}`);
13292
14774
  }
@@ -13295,14 +14777,14 @@ ${content}`);
13295
14777
  if (statSync3(skillPath).isDirectory()) {
13296
14778
  readDir(skillPath);
13297
14779
  } else {
13298
- contents.push(readFileSync17(skillPath, "utf-8"));
14780
+ contents.push(readFileSync18(skillPath, "utf-8"));
13299
14781
  }
13300
14782
  return contents.join("\n\n");
13301
14783
  }
13302
14784
  detectAgents(skillPath) {
13303
14785
  const agents = [];
13304
- if (existsSync27(skillPath) && statSync3(skillPath).isFile()) {
13305
- const fileName = basename9(skillPath).toLowerCase();
14786
+ if (existsSync28(skillPath) && statSync3(skillPath).isFile()) {
14787
+ const fileName = basename12(skillPath).toLowerCase();
13306
14788
  if (fileName === "skill.md") {
13307
14789
  return ["claude-code", "codex", "gemini-cli", "universal"];
13308
14790
  }
@@ -13314,13 +14796,13 @@ ${content}`);
13314
14796
  }
13315
14797
  return ["universal"];
13316
14798
  }
13317
- if (existsSync27(join26(skillPath, "SKILL.md"))) {
14799
+ if (existsSync28(join27(skillPath, "SKILL.md"))) {
13318
14800
  agents.push("claude-code", "codex", "gemini-cli", "universal");
13319
14801
  }
13320
- if (existsSync27(join26(skillPath, "skill.mdc"))) {
14802
+ if (existsSync28(join27(skillPath, "skill.mdc"))) {
13321
14803
  agents.push("cursor");
13322
14804
  }
13323
- if (existsSync27(join26(skillPath, "rules.md"))) {
14805
+ if (existsSync28(join27(skillPath, "rules.md"))) {
13324
14806
  agents.push("windsurf");
13325
14807
  }
13326
14808
  return agents.length > 0 ? agents : ["universal"];
@@ -13342,11 +14824,11 @@ function exportBundle(bundle, outputPath) {
13342
14824
  exportData.skills[skill.name] = content;
13343
14825
  }
13344
14826
  }
13345
- const dir = dirname8(outputPath);
13346
- if (dir && !existsSync27(dir)) {
13347
- mkdirSync16(dir, { recursive: true });
14827
+ const dir = dirname9(outputPath);
14828
+ if (dir && !existsSync28(dir)) {
14829
+ mkdirSync17(dir, { recursive: true });
13348
14830
  }
13349
- writeFileSync15(outputPath, JSON.stringify(exportData, null, 2), "utf-8");
14831
+ writeFileSync16(outputPath, JSON.stringify(exportData, null, 2), "utf-8");
13350
14832
  return { success: true, path: outputPath };
13351
14833
  } catch (err) {
13352
14834
  return {
@@ -13359,7 +14841,7 @@ function importBundle(bundlePath, targetDir, options = {}) {
13359
14841
  const imported = [];
13360
14842
  const errors = [];
13361
14843
  try {
13362
- const content = readFileSync17(bundlePath, "utf-8");
14844
+ const content = readFileSync18(bundlePath, "utf-8");
13363
14845
  const data = JSON.parse(content);
13364
14846
  const absoluteTargetDir = resolve4(targetDir);
13365
14847
  for (const skill of data.manifest.skills) {
@@ -13372,19 +14854,19 @@ function importBundle(bundlePath, targetDir, options = {}) {
13372
14854
  errors.push(`Skill "${skill.name}" has no content in bundle`);
13373
14855
  continue;
13374
14856
  }
13375
- const skillDir = join26(absoluteTargetDir, skill.name);
14857
+ const skillDir = join27(absoluteTargetDir, skill.name);
13376
14858
  const resolvedSkillDir = resolve4(skillDir);
13377
14859
  const relativeToTarget = relative(absoluteTargetDir, resolvedSkillDir);
13378
14860
  if (relativeToTarget.startsWith("..") || relativeToTarget.startsWith(sep3)) {
13379
14861
  errors.push(`Skill "${skill.name}" would escape target directory`);
13380
14862
  continue;
13381
14863
  }
13382
- if (existsSync27(skillDir) && !options.overwrite) {
14864
+ if (existsSync28(skillDir) && !options.overwrite) {
13383
14865
  errors.push(`Skill "${skill.name}" already exists (use --overwrite)`);
13384
14866
  continue;
13385
14867
  }
13386
- if (!existsSync27(skillDir)) {
13387
- mkdirSync16(skillDir, { recursive: true });
14868
+ if (!existsSync28(skillDir)) {
14869
+ mkdirSync17(skillDir, { recursive: true });
13388
14870
  }
13389
14871
  const files = parseSkillContent2(skillContent);
13390
14872
  for (const [filePath, fileContent] of Object.entries(files)) {
@@ -13394,11 +14876,11 @@ function importBundle(bundlePath, targetDir, options = {}) {
13394
14876
  errors.push(`Skill "${skill.name}" contains invalid file path: ${filePath}`);
13395
14877
  continue;
13396
14878
  }
13397
- const fileDir = dirname8(fullPath);
13398
- if (!existsSync27(fileDir)) {
13399
- mkdirSync16(fileDir, { recursive: true });
14879
+ const fileDir = dirname9(fullPath);
14880
+ if (!existsSync28(fileDir)) {
14881
+ mkdirSync17(fileDir, { recursive: true });
13400
14882
  }
13401
- writeFileSync15(fullPath, fileContent, "utf-8");
14883
+ writeFileSync16(fullPath, fileContent, "utf-8");
13402
14884
  }
13403
14885
  imported.push(skill.name);
13404
14886
  }
@@ -13427,8 +14909,8 @@ function parseSkillContent2(content) {
13427
14909
  }
13428
14910
 
13429
14911
  // src/plugins/manager.ts
13430
- import { existsSync as existsSync28, readFileSync as readFileSync18, writeFileSync as writeFileSync16, mkdirSync as mkdirSync17 } from "fs";
13431
- import { join as join27 } from "path";
14912
+ import { existsSync as existsSync29, readFileSync as readFileSync19, writeFileSync as writeFileSync17, mkdirSync as mkdirSync18 } from "fs";
14913
+ import { join as join28 } from "path";
13432
14914
  var PLUGINS_DIR = ".skillkit/plugins";
13433
14915
  var PLUGINS_CONFIG_FILE = "plugins.json";
13434
14916
  var PluginManager = class {
@@ -13669,22 +15151,22 @@ var PluginManager = class {
13669
15151
  }
13670
15152
  // Private helpers
13671
15153
  loadState() {
13672
- const statePath = join27(this.projectPath, PLUGINS_DIR, PLUGINS_CONFIG_FILE);
13673
- if (existsSync28(statePath)) {
15154
+ const statePath = join28(this.projectPath, PLUGINS_DIR, PLUGINS_CONFIG_FILE);
15155
+ if (existsSync29(statePath)) {
13674
15156
  try {
13675
- return JSON.parse(readFileSync18(statePath, "utf-8"));
15157
+ return JSON.parse(readFileSync19(statePath, "utf-8"));
13676
15158
  } catch {
13677
15159
  }
13678
15160
  }
13679
15161
  return { version: 1, plugins: {} };
13680
15162
  }
13681
15163
  saveState() {
13682
- const pluginsDir = join27(this.projectPath, PLUGINS_DIR);
13683
- if (!existsSync28(pluginsDir)) {
13684
- mkdirSync17(pluginsDir, { recursive: true });
15164
+ const pluginsDir = join28(this.projectPath, PLUGINS_DIR);
15165
+ if (!existsSync29(pluginsDir)) {
15166
+ mkdirSync18(pluginsDir, { recursive: true });
13685
15167
  }
13686
- const statePath = join27(pluginsDir, PLUGINS_CONFIG_FILE);
13687
- writeFileSync16(statePath, JSON.stringify(this.state, null, 2), "utf-8");
15168
+ const statePath = join28(pluginsDir, PLUGINS_CONFIG_FILE);
15169
+ writeFileSync17(statePath, JSON.stringify(this.state, null, 2), "utf-8");
13688
15170
  }
13689
15171
  createContext() {
13690
15172
  return {
@@ -13709,15 +15191,15 @@ function createPluginManager(projectPath) {
13709
15191
  }
13710
15192
 
13711
15193
  // src/plugins/loader.ts
13712
- import { existsSync as existsSync29, readFileSync as readFileSync19, readdirSync as readdirSync7, statSync as statSync4 } from "fs";
13713
- import { join as join28, extname, basename as basename10, isAbsolute } from "path";
15194
+ import { existsSync as existsSync30, readFileSync as readFileSync20, readdirSync as readdirSync7, statSync as statSync4 } from "fs";
15195
+ import { join as join29, extname, basename as basename13, isAbsolute } from "path";
13714
15196
  import { pathToFileURL } from "url";
13715
15197
  var PluginLoader = class {
13716
15198
  /**
13717
15199
  * Load a plugin from a file path
13718
15200
  */
13719
15201
  async loadFromFile(filePath) {
13720
- if (!existsSync29(filePath)) {
15202
+ if (!existsSync30(filePath)) {
13721
15203
  throw new Error(`Plugin file not found: ${filePath}`);
13722
15204
  }
13723
15205
  const ext = extname(filePath);
@@ -13759,11 +15241,11 @@ var PluginLoader = class {
13759
15241
  * Load a plugin from a JSON definition (for simple plugins)
13760
15242
  */
13761
15243
  loadFromJson(jsonPath) {
13762
- if (!existsSync29(jsonPath)) {
15244
+ if (!existsSync30(jsonPath)) {
13763
15245
  throw new Error(`Plugin JSON not found: ${jsonPath}`);
13764
15246
  }
13765
15247
  try {
13766
- const content = readFileSync19(jsonPath, "utf-8");
15248
+ const content = readFileSync20(jsonPath, "utf-8");
13767
15249
  const data = JSON.parse(content);
13768
15250
  if (!data.metadata) {
13769
15251
  throw new Error("Invalid plugin JSON: missing metadata");
@@ -13782,13 +15264,13 @@ var PluginLoader = class {
13782
15264
  * Scan a directory for plugins
13783
15265
  */
13784
15266
  async scanDirectory(dirPath) {
13785
- if (!existsSync29(dirPath)) {
15267
+ if (!existsSync30(dirPath)) {
13786
15268
  return [];
13787
15269
  }
13788
15270
  const plugins = [];
13789
15271
  const entries = readdirSync7(dirPath);
13790
15272
  for (const entry of entries) {
13791
- const fullPath = join28(dirPath, entry);
15273
+ const fullPath = join29(dirPath, entry);
13792
15274
  let stat;
13793
15275
  try {
13794
15276
  stat = statSync4(fullPath);
@@ -13796,11 +15278,11 @@ var PluginLoader = class {
13796
15278
  continue;
13797
15279
  }
13798
15280
  if (stat.isDirectory()) {
13799
- const pkgPath = join28(fullPath, "package.json");
13800
- const pluginPath = join28(fullPath, "plugin.json");
13801
- if (existsSync29(pkgPath)) {
15281
+ const pkgPath = join29(fullPath, "package.json");
15282
+ const pluginPath = join29(fullPath, "plugin.json");
15283
+ if (existsSync30(pkgPath)) {
13802
15284
  try {
13803
- const pkg = JSON.parse(readFileSync19(pkgPath, "utf-8"));
15285
+ const pkg = JSON.parse(readFileSync20(pkgPath, "utf-8"));
13804
15286
  if ((pkg.skillkitPlugin || pkg.keywords?.includes("skillkit-plugin")) && pkg.name && typeof pkg.name === "string" && pkg.version && typeof pkg.version === "string") {
13805
15287
  plugins.push({
13806
15288
  name: pkg.name,
@@ -13812,9 +15294,9 @@ var PluginLoader = class {
13812
15294
  }
13813
15295
  } catch {
13814
15296
  }
13815
- } else if (existsSync29(pluginPath)) {
15297
+ } else if (existsSync30(pluginPath)) {
13816
15298
  try {
13817
- const data = JSON.parse(readFileSync19(pluginPath, "utf-8"));
15299
+ const data = JSON.parse(readFileSync20(pluginPath, "utf-8"));
13818
15300
  if (data.metadata && data.metadata.name && typeof data.metadata.name === "string" && data.metadata.version && typeof data.metadata.version === "string") {
13819
15301
  plugins.push(data.metadata);
13820
15302
  }
@@ -13824,7 +15306,7 @@ var PluginLoader = class {
13824
15306
  } else if (stat.isFile()) {
13825
15307
  const ext = extname(entry);
13826
15308
  if (ext === ".js" || ext === ".mjs") {
13827
- const name = basename10(entry, ext);
15309
+ const name = basename13(entry, ext);
13828
15310
  if (name.includes("plugin") || name.startsWith("skillkit-")) {
13829
15311
  plugins.push({
13830
15312
  name,
@@ -13902,12 +15384,12 @@ async function loadPlugin(source) {
13902
15384
  async function loadPluginsFromDirectory(dirPath) {
13903
15385
  const loader = new PluginLoader();
13904
15386
  const plugins = [];
13905
- if (!existsSync29(dirPath)) {
15387
+ if (!existsSync30(dirPath)) {
13906
15388
  return plugins;
13907
15389
  }
13908
15390
  const entries = readdirSync7(dirPath);
13909
15391
  for (const entry of entries) {
13910
- const fullPath = join28(dirPath, entry);
15392
+ const fullPath = join29(dirPath, entry);
13911
15393
  let stat;
13912
15394
  try {
13913
15395
  stat = statSync4(fullPath);
@@ -13916,20 +15398,20 @@ async function loadPluginsFromDirectory(dirPath) {
13916
15398
  }
13917
15399
  try {
13918
15400
  if (stat.isDirectory()) {
13919
- const indexMjsPath = join28(fullPath, "index.mjs");
13920
- const indexPath = join28(fullPath, "index.js");
13921
- const mainMjsPath = join28(fullPath, "plugin.mjs");
13922
- const mainPath = join28(fullPath, "plugin.js");
13923
- const jsonPath = join28(fullPath, "plugin.json");
13924
- if (existsSync29(indexMjsPath)) {
15401
+ const indexMjsPath = join29(fullPath, "index.mjs");
15402
+ const indexPath = join29(fullPath, "index.js");
15403
+ const mainMjsPath = join29(fullPath, "plugin.mjs");
15404
+ const mainPath = join29(fullPath, "plugin.js");
15405
+ const jsonPath = join29(fullPath, "plugin.json");
15406
+ if (existsSync30(indexMjsPath)) {
13925
15407
  plugins.push(await loader.loadFromFile(indexMjsPath));
13926
- } else if (existsSync29(indexPath)) {
15408
+ } else if (existsSync30(indexPath)) {
13927
15409
  plugins.push(await loader.loadFromFile(indexPath));
13928
- } else if (existsSync29(mainMjsPath)) {
15410
+ } else if (existsSync30(mainMjsPath)) {
13929
15411
  plugins.push(await loader.loadFromFile(mainMjsPath));
13930
- } else if (existsSync29(mainPath)) {
15412
+ } else if (existsSync30(mainPath)) {
13931
15413
  plugins.push(await loader.loadFromFile(mainPath));
13932
- } else if (existsSync29(jsonPath)) {
15414
+ } else if (existsSync30(jsonPath)) {
13933
15415
  plugins.push(loader.loadFromJson(jsonPath));
13934
15416
  }
13935
15417
  } else if (stat.isFile()) {
@@ -13948,17 +15430,17 @@ async function loadPluginsFromDirectory(dirPath) {
13948
15430
  }
13949
15431
 
13950
15432
  // src/methodology/manager.ts
13951
- import { existsSync as existsSync32, readFileSync as readFileSync22, writeFileSync as writeFileSync17, mkdirSync as mkdirSync18 } from "fs";
13952
- import { join as join31, dirname as dirname10 } from "path";
15433
+ import { existsSync as existsSync33, readFileSync as readFileSync23, writeFileSync as writeFileSync18, mkdirSync as mkdirSync19 } from "fs";
15434
+ import { join as join32, dirname as dirname11 } from "path";
13953
15435
 
13954
15436
  // src/methodology/loader.ts
13955
- import { existsSync as existsSync31, readFileSync as readFileSync21, readdirSync as readdirSync9, statSync as statSync6 } from "fs";
13956
- import { join as join30, dirname as dirname9 } from "path";
15437
+ import { existsSync as existsSync32, readFileSync as readFileSync22, readdirSync as readdirSync9, statSync as statSync6 } from "fs";
15438
+ import { join as join31, dirname as dirname10 } from "path";
13957
15439
  import { fileURLToPath } from "url";
13958
15440
 
13959
15441
  // src/methodology/validator.ts
13960
- import { existsSync as existsSync30, readFileSync as readFileSync20, readdirSync as readdirSync8, statSync as statSync5 } from "fs";
13961
- import { join as join29 } from "path";
15442
+ import { existsSync as existsSync31, readFileSync as readFileSync21, readdirSync as readdirSync8, statSync as statSync5 } from "fs";
15443
+ import { join as join30 } from "path";
13962
15444
  function validatePackManifest(pack) {
13963
15445
  const errors = [];
13964
15446
  const warnings = [];
@@ -14108,15 +15590,15 @@ function validateSkillContent(content) {
14108
15590
  function validatePackDirectory(packPath) {
14109
15591
  const errors = [];
14110
15592
  const warnings = [];
14111
- if (!existsSync30(packPath)) {
15593
+ if (!existsSync31(packPath)) {
14112
15594
  errors.push({
14113
15595
  code: "DIR_NOT_FOUND",
14114
15596
  message: `Pack directory not found: ${packPath}`
14115
15597
  });
14116
15598
  return { valid: false, errors, warnings };
14117
15599
  }
14118
- const manifestPath = join29(packPath, "pack.json");
14119
- if (!existsSync30(manifestPath)) {
15600
+ const manifestPath = join30(packPath, "pack.json");
15601
+ if (!existsSync31(manifestPath)) {
14120
15602
  errors.push({
14121
15603
  code: "MANIFEST_NOT_FOUND",
14122
15604
  message: "Pack must have a pack.json manifest",
@@ -14126,7 +15608,7 @@ function validatePackDirectory(packPath) {
14126
15608
  }
14127
15609
  let manifest;
14128
15610
  try {
14129
- const raw = readFileSync20(manifestPath, "utf-8");
15611
+ const raw = readFileSync21(manifestPath, "utf-8");
14130
15612
  manifest = JSON.parse(raw);
14131
15613
  const manifestResult = validatePackManifest(manifest);
14132
15614
  errors.push(...manifestResult.errors);
@@ -14141,8 +15623,8 @@ function validatePackDirectory(packPath) {
14141
15623
  }
14142
15624
  if (manifest.skills) {
14143
15625
  for (const skillName of manifest.skills) {
14144
- const skillDir = join29(packPath, skillName);
14145
- if (!existsSync30(skillDir)) {
15626
+ const skillDir = join30(packPath, skillName);
15627
+ if (!existsSync31(skillDir)) {
14146
15628
  errors.push({
14147
15629
  code: "SKILL_DIR_NOT_FOUND",
14148
15630
  message: `Skill directory not found: ${skillName}`,
@@ -14158,8 +15640,8 @@ function validatePackDirectory(packPath) {
14158
15640
  });
14159
15641
  continue;
14160
15642
  }
14161
- const skillFile = join29(skillDir, "SKILL.md");
14162
- if (!existsSync30(skillFile)) {
15643
+ const skillFile = join30(skillDir, "SKILL.md");
15644
+ if (!existsSync31(skillFile)) {
14163
15645
  errors.push({
14164
15646
  code: "SKILL_FILE_NOT_FOUND",
14165
15647
  message: `Skill must have a SKILL.md file: ${skillName}`,
@@ -14167,7 +15649,7 @@ function validatePackDirectory(packPath) {
14167
15649
  });
14168
15650
  continue;
14169
15651
  }
14170
- const skillContent = readFileSync20(skillFile, "utf-8");
15652
+ const skillContent = readFileSync21(skillFile, "utf-8");
14171
15653
  const skillResult = validateSkillContent(skillContent);
14172
15654
  for (const err of skillResult.errors) {
14173
15655
  errors.push({
@@ -14191,15 +15673,15 @@ function validatePackDirectory(packPath) {
14191
15673
  }
14192
15674
  function validateBuiltinPacks(packsDir) {
14193
15675
  const results = /* @__PURE__ */ new Map();
14194
- if (!existsSync30(packsDir)) {
15676
+ if (!existsSync31(packsDir)) {
14195
15677
  return results;
14196
15678
  }
14197
15679
  const packDirs = readdirSync8(packsDir).filter((name) => {
14198
- const packPath = join29(packsDir, name);
15680
+ const packPath = join30(packsDir, name);
14199
15681
  return statSync5(packPath).isDirectory();
14200
15682
  });
14201
15683
  for (const packName of packDirs) {
14202
- const packPath = join29(packsDir, packName);
15684
+ const packPath = join30(packsDir, packName);
14203
15685
  results.set(packName, validatePackDirectory(packPath));
14204
15686
  }
14205
15687
  return results;
@@ -14257,8 +15739,8 @@ function extractSkillMetadata(content) {
14257
15739
 
14258
15740
  // src/methodology/loader.ts
14259
15741
  var __filename = fileURLToPath(import.meta.url);
14260
- var __dirname = dirname9(__filename);
14261
- var BUILTIN_PACKS_DIR = join30(__dirname, "packs");
15742
+ var __dirname = dirname10(__filename);
15743
+ var BUILTIN_PACKS_DIR = join31(__dirname, "packs");
14262
15744
  var MethodologyLoader = class {
14263
15745
  packsDir;
14264
15746
  loadedPacks = /* @__PURE__ */ new Map();
@@ -14271,11 +15753,11 @@ var MethodologyLoader = class {
14271
15753
  */
14272
15754
  async loadAllPacks() {
14273
15755
  const packs = [];
14274
- if (!existsSync31(this.packsDir)) {
15756
+ if (!existsSync32(this.packsDir)) {
14275
15757
  return packs;
14276
15758
  }
14277
15759
  const packDirs = readdirSync9(this.packsDir).filter((name) => {
14278
- const packPath = join30(this.packsDir, name);
15760
+ const packPath = join31(this.packsDir, name);
14279
15761
  return statSync6(packPath).isDirectory();
14280
15762
  });
14281
15763
  for (const packName of packDirs) {
@@ -14296,9 +15778,9 @@ var MethodologyLoader = class {
14296
15778
  if (this.loadedPacks.has(packName)) {
14297
15779
  return this.loadedPacks.get(packName);
14298
15780
  }
14299
- const packPath = join30(this.packsDir, packName);
14300
- const manifestPath = join30(packPath, "pack.json");
14301
- if (!existsSync31(manifestPath)) {
15781
+ const packPath = join31(this.packsDir, packName);
15782
+ const manifestPath = join31(packPath, "pack.json");
15783
+ if (!existsSync32(manifestPath)) {
14302
15784
  return null;
14303
15785
  }
14304
15786
  const validation = validatePackDirectory(packPath);
@@ -14308,7 +15790,7 @@ var MethodologyLoader = class {
14308
15790
  );
14309
15791
  }
14310
15792
  const manifest = JSON.parse(
14311
- readFileSync21(manifestPath, "utf-8")
15793
+ readFileSync22(manifestPath, "utf-8")
14312
15794
  );
14313
15795
  this.loadedPacks.set(packName, manifest);
14314
15796
  return manifest;
@@ -14338,11 +15820,11 @@ var MethodologyLoader = class {
14338
15820
  if (this.loadedSkills.has(skillId)) {
14339
15821
  return this.loadedSkills.get(skillId);
14340
15822
  }
14341
- const skillPath = join30(this.packsDir, packName, skillName, "SKILL.md");
14342
- if (!existsSync31(skillPath)) {
15823
+ const skillPath = join31(this.packsDir, packName, skillName, "SKILL.md");
15824
+ if (!existsSync32(skillPath)) {
14343
15825
  return null;
14344
15826
  }
14345
- const content = readFileSync21(skillPath, "utf-8");
15827
+ const content = readFileSync22(skillPath, "utf-8");
14346
15828
  const rawMetadata = extractSkillMetadata(content);
14347
15829
  const metadata = {
14348
15830
  triggers: rawMetadata.triggers,
@@ -14421,9 +15903,9 @@ var MethodologyLoader = class {
14421
15903
  * Check if a pack exists
14422
15904
  */
14423
15905
  packExists(packName) {
14424
- const packPath = join30(this.packsDir, packName);
14425
- const manifestPath = join30(packPath, "pack.json");
14426
- return existsSync31(manifestPath);
15906
+ const packPath = join31(this.packsDir, packName);
15907
+ const manifestPath = join31(packPath, "pack.json");
15908
+ return existsSync32(manifestPath);
14427
15909
  }
14428
15910
  /**
14429
15911
  * Clear cache
@@ -14789,10 +16271,10 @@ var MethodologyManager = class {
14789
16271
  }
14790
16272
  // Private helpers
14791
16273
  loadState() {
14792
- const statePath = join31(this.projectPath, METHODOLOGY_STATE_FILE);
14793
- if (existsSync32(statePath)) {
16274
+ const statePath = join32(this.projectPath, METHODOLOGY_STATE_FILE);
16275
+ if (existsSync33(statePath)) {
14794
16276
  try {
14795
- return JSON.parse(readFileSync22(statePath, "utf-8"));
16277
+ return JSON.parse(readFileSync23(statePath, "utf-8"));
14796
16278
  } catch {
14797
16279
  }
14798
16280
  }
@@ -14803,21 +16285,21 @@ var MethodologyManager = class {
14803
16285
  };
14804
16286
  }
14805
16287
  saveState() {
14806
- const statePath = join31(this.projectPath, METHODOLOGY_STATE_FILE);
14807
- const dir = dirname10(statePath);
14808
- if (!existsSync32(dir)) {
14809
- mkdirSync18(dir, { recursive: true });
16288
+ const statePath = join32(this.projectPath, METHODOLOGY_STATE_FILE);
16289
+ const dir = dirname11(statePath);
16290
+ if (!existsSync33(dir)) {
16291
+ mkdirSync19(dir, { recursive: true });
14810
16292
  }
14811
- writeFileSync17(statePath, JSON.stringify(this.state, null, 2), "utf-8");
16293
+ writeFileSync18(statePath, JSON.stringify(this.state, null, 2), "utf-8");
14812
16294
  }
14813
16295
  async installSkillLocally(skill) {
14814
- const skillsDir = join31(this.projectPath, ".skillkit", "methodology", "skills");
14815
- const skillDir = join31(skillsDir, skill.pack, skill.id.split("/")[1]);
14816
- if (!existsSync32(skillDir)) {
14817
- mkdirSync18(skillDir, { recursive: true });
16296
+ const skillsDir = join32(this.projectPath, ".skillkit", "methodology", "skills");
16297
+ const skillDir = join32(skillsDir, skill.pack, skill.id.split("/")[1]);
16298
+ if (!existsSync33(skillDir)) {
16299
+ mkdirSync19(skillDir, { recursive: true });
14818
16300
  }
14819
- const targetPath = join31(skillDir, "SKILL.md");
14820
- writeFileSync17(targetPath, skill.content, "utf-8");
16301
+ const targetPath = join32(skillDir, "SKILL.md");
16302
+ writeFileSync18(targetPath, skill.content, "utf-8");
14821
16303
  }
14822
16304
  async removeSkillLocally(_skillId) {
14823
16305
  }
@@ -14845,9 +16327,9 @@ var MethodologyManager = class {
14845
16327
  if (!agentDir) {
14846
16328
  throw new Error(`Unknown agent: ${agent}`);
14847
16329
  }
14848
- const skillsDir = join31(this.projectPath, agentDir);
14849
- if (!existsSync32(skillsDir)) {
14850
- mkdirSync18(skillsDir, { recursive: true });
16330
+ const skillsDir = join32(this.projectPath, agentDir);
16331
+ if (!existsSync33(skillsDir)) {
16332
+ mkdirSync19(skillsDir, { recursive: true });
14851
16333
  }
14852
16334
  const skillName = skillId.split("/")[1];
14853
16335
  let filename;
@@ -14858,8 +16340,8 @@ var MethodologyManager = class {
14858
16340
  } else {
14859
16341
  filename = `${skillName}.md`;
14860
16342
  }
14861
- const targetPath = join31(skillsDir, filename);
14862
- writeFileSync17(targetPath, content, "utf-8");
16343
+ const targetPath = join32(skillsDir, filename);
16344
+ writeFileSync18(targetPath, content, "utf-8");
14863
16345
  }
14864
16346
  detectAgents() {
14865
16347
  const agents = [];
@@ -14882,7 +16364,7 @@ var MethodologyManager = class {
14882
16364
  ["windsurf", ".windsurf"]
14883
16365
  ];
14884
16366
  for (const [agent, dir] of agentDirs) {
14885
- if (existsSync32(join31(this.projectPath, dir))) {
16367
+ if (existsSync33(join32(this.projectPath, dir))) {
14886
16368
  agents.push(agent);
14887
16369
  }
14888
16370
  }
@@ -14895,9 +16377,9 @@ function createMethodologyManager(options) {
14895
16377
  }
14896
16378
 
14897
16379
  // src/hooks/manager.ts
14898
- import { existsSync as existsSync33, readFileSync as readFileSync23, writeFileSync as writeFileSync18, mkdirSync as mkdirSync19 } from "fs";
14899
- import { join as join32, dirname as dirname11 } from "path";
14900
- import { randomUUID as randomUUID10 } from "crypto";
16380
+ import { existsSync as existsSync34, readFileSync as readFileSync24, writeFileSync as writeFileSync19, mkdirSync as mkdirSync20 } from "fs";
16381
+ import { join as join33, dirname as dirname12 } from "path";
16382
+ import { randomUUID as randomUUID11 } from "crypto";
14901
16383
  import { minimatch } from "minimatch";
14902
16384
  var DEFAULT_CONFIG_PATH = ".skillkit/hooks.json";
14903
16385
  var HookManager = class {
@@ -14907,7 +16389,7 @@ var HookManager = class {
14907
16389
  constructor(options) {
14908
16390
  this.options = {
14909
16391
  projectPath: options.projectPath,
14910
- configPath: options.configPath || join32(options.projectPath, DEFAULT_CONFIG_PATH),
16392
+ configPath: options.configPath || join33(options.projectPath, DEFAULT_CONFIG_PATH),
14911
16393
  autoLoad: options.autoLoad ?? true,
14912
16394
  defaultInjectionMode: options.defaultInjectionMode || "reference"
14913
16395
  };
@@ -14921,7 +16403,7 @@ var HookManager = class {
14921
16403
  registerHook(hook) {
14922
16404
  const fullHook = {
14923
16405
  ...hook,
14924
- id: hook.id || randomUUID10(),
16406
+ id: hook.id || randomUUID11(),
14925
16407
  inject: hook.inject || this.options.defaultInjectionMode,
14926
16408
  enabled: hook.enabled ?? true,
14927
16409
  priority: hook.priority ?? 0
@@ -15047,11 +16529,11 @@ var HookManager = class {
15047
16529
  * Load hooks from config file
15048
16530
  */
15049
16531
  load() {
15050
- if (!existsSync33(this.options.configPath)) {
16532
+ if (!existsSync34(this.options.configPath)) {
15051
16533
  return;
15052
16534
  }
15053
16535
  try {
15054
- const content = readFileSync23(this.options.configPath, "utf-8");
16536
+ const content = readFileSync24(this.options.configPath, "utf-8");
15055
16537
  const config = JSON.parse(content);
15056
16538
  this.hooks.clear();
15057
16539
  for (const hook of config.hooks) {
@@ -15078,11 +16560,11 @@ var HookManager = class {
15078
16560
  enabled: true
15079
16561
  }
15080
16562
  };
15081
- const dir = dirname11(this.options.configPath);
15082
- if (!existsSync33(dir)) {
15083
- mkdirSync19(dir, { recursive: true });
16563
+ const dir = dirname12(this.options.configPath);
16564
+ if (!existsSync34(dir)) {
16565
+ mkdirSync20(dir, { recursive: true });
15084
16566
  }
15085
- writeFileSync18(this.options.configPath, JSON.stringify(config, null, 2));
16567
+ writeFileSync19(this.options.configPath, JSON.stringify(config, null, 2));
15086
16568
  }
15087
16569
  /**
15088
16570
  * Generate agent-specific hook configuration
@@ -15324,7 +16806,7 @@ function createHookManager(options) {
15324
16806
 
15325
16807
  // src/hooks/triggers.ts
15326
16808
  import { watch } from "fs";
15327
- import { join as join33, relative as relative2 } from "path";
16809
+ import { join as join34, relative as relative2 } from "path";
15328
16810
  function debounce(fn, delay) {
15329
16811
  let timeoutId = null;
15330
16812
  return (...args) => {
@@ -15509,7 +16991,7 @@ var SkillTriggerEngine = class {
15509
16991
  { recursive: true },
15510
16992
  debounce((eventType, filename) => {
15511
16993
  if (!filename) return;
15512
- const relativePath = relative2(this.options.projectPath, join33(this.options.projectPath, filename));
16994
+ const relativePath = relative2(this.options.projectPath, join34(this.options.projectPath, filename));
15513
16995
  if (this.shouldIgnore(relativePath)) return;
15514
16996
  if (eventType === "rename") {
15515
16997
  this.triggerFileCreate(relativePath);
@@ -15553,10 +17035,10 @@ function createTriggerEngine(hookManager, options) {
15553
17035
  }
15554
17036
 
15555
17037
  // src/orchestrator/team.ts
15556
- import { randomUUID as randomUUID13 } from "crypto";
17038
+ import { randomUUID as randomUUID14 } from "crypto";
15557
17039
 
15558
17040
  // src/orchestrator/task.ts
15559
- import { randomUUID as randomUUID11 } from "crypto";
17041
+ import { randomUUID as randomUUID12 } from "crypto";
15560
17042
  var TaskManager = class {
15561
17043
  tasks = /* @__PURE__ */ new Map();
15562
17044
  listeners = /* @__PURE__ */ new Set();
@@ -15566,7 +17048,7 @@ var TaskManager = class {
15566
17048
  createTask(name, description, spec, options) {
15567
17049
  const now = /* @__PURE__ */ new Date();
15568
17050
  const task = {
15569
- id: randomUUID11(),
17051
+ id: randomUUID12(),
15570
17052
  name,
15571
17053
  description,
15572
17054
  spec,
@@ -15885,7 +17367,7 @@ function createTaskManager() {
15885
17367
  }
15886
17368
 
15887
17369
  // src/orchestrator/messages.ts
15888
- import { randomUUID as randomUUID12 } from "crypto";
17370
+ import { randomUUID as randomUUID13 } from "crypto";
15889
17371
  var TeamMessageBus = class {
15890
17372
  messages = [];
15891
17373
  handlers = /* @__PURE__ */ new Map();
@@ -15899,7 +17381,7 @@ var TeamMessageBus = class {
15899
17381
  */
15900
17382
  async send(from, to, content, options) {
15901
17383
  const message = {
15902
- id: randomUUID12(),
17384
+ id: randomUUID13(),
15903
17385
  type: options?.type || "direct",
15904
17386
  from,
15905
17387
  to,
@@ -15918,7 +17400,7 @@ var TeamMessageBus = class {
15918
17400
  */
15919
17401
  async broadcast(from, content, options) {
15920
17402
  const message = {
15921
- id: randomUUID12(),
17403
+ id: randomUUID13(),
15922
17404
  type: "broadcast",
15923
17405
  from,
15924
17406
  content,
@@ -16178,10 +17660,10 @@ var TeamOrchestrator = class {
16178
17660
  * Spawn a new team
16179
17661
  */
16180
17662
  async spawnTeam(config) {
16181
- const teamId = randomUUID13();
17663
+ const teamId = randomUUID14();
16182
17664
  const now = /* @__PURE__ */ new Date();
16183
17665
  const leader = {
16184
- id: randomUUID13(),
17666
+ id: randomUUID14(),
16185
17667
  role: "leader",
16186
17668
  agentType: config.leaderAgent,
16187
17669
  status: "idle",
@@ -16223,7 +17705,7 @@ var TeamOrchestrator = class {
16223
17705
  if (!team) throw new Error(`Team not found: ${teamId}`);
16224
17706
  const now = /* @__PURE__ */ new Date();
16225
17707
  const teammate = {
16226
- id: randomUUID13(),
17708
+ id: randomUUID14(),
16227
17709
  role: "teammate",
16228
17710
  agentType,
16229
17711
  status: "idle",
@@ -19610,8 +21092,8 @@ var CUSTOM_AGENT_FORMAT_MAP = {
19610
21092
  };
19611
21093
 
19612
21094
  // src/agents/parser.ts
19613
- import { existsSync as existsSync34, readFileSync as readFileSync24, statSync as statSync7 } from "fs";
19614
- import { join as join34, basename as basename11, extname as extname2 } from "path";
21095
+ import { existsSync as existsSync35, readFileSync as readFileSync25, statSync as statSync7 } from "fs";
21096
+ import { join as join35, basename as basename14, extname as extname2 } from "path";
19615
21097
  import { parse as parseYaml10 } from "yaml";
19616
21098
  function extractAgentFrontmatter(content) {
19617
21099
  const match = content.match(/^---\s*\n([\s\S]*?)\n---/);
@@ -19629,18 +21111,18 @@ function extractAgentContent(content) {
19629
21111
  return withoutFrontmatter.trim();
19630
21112
  }
19631
21113
  function parseAgentFile(filePath, location = "project") {
19632
- if (!existsSync34(filePath)) {
21114
+ if (!existsSync35(filePath)) {
19633
21115
  return null;
19634
21116
  }
19635
21117
  if (extname2(filePath) !== ".md") {
19636
21118
  return null;
19637
21119
  }
19638
21120
  try {
19639
- const content = readFileSync24(filePath, "utf-8");
21121
+ const content = readFileSync25(filePath, "utf-8");
19640
21122
  const rawFrontmatter = extractAgentFrontmatter(content);
19641
21123
  const agentContent = extractAgentContent(content);
19642
21124
  if (!rawFrontmatter) {
19643
- const name = basename11(filePath, ".md");
21125
+ const name = basename14(filePath, ".md");
19644
21126
  return {
19645
21127
  name,
19646
21128
  description: "No description available",
@@ -19656,7 +21138,7 @@ function parseAgentFile(filePath, location = "project") {
19656
21138
  }
19657
21139
  const parsed = AgentFrontmatter.safeParse(rawFrontmatter);
19658
21140
  if (!parsed.success) {
19659
- const name = rawFrontmatter.name || basename11(filePath, ".md");
21141
+ const name = rawFrontmatter.name || basename14(filePath, ".md");
19660
21142
  return {
19661
21143
  name,
19662
21144
  description: rawFrontmatter.description || "No description available",
@@ -19688,16 +21170,16 @@ function parseAgentFile(filePath, location = "project") {
19688
21170
  }
19689
21171
  }
19690
21172
  function parseAgentDir(dirPath, location = "project") {
19691
- const agentMdPath = join34(dirPath, "AGENT.md");
19692
- if (existsSync34(agentMdPath)) {
21173
+ const agentMdPath = join35(dirPath, "AGENT.md");
21174
+ if (existsSync35(agentMdPath)) {
19693
21175
  const agent = parseAgentFile(agentMdPath, location);
19694
21176
  if (agent) {
19695
21177
  agent.path = dirPath;
19696
21178
  }
19697
21179
  return agent;
19698
21180
  }
19699
- const indexMdPath = join34(dirPath, "index.md");
19700
- if (existsSync34(indexMdPath)) {
21181
+ const indexMdPath = join35(dirPath, "index.md");
21182
+ if (existsSync35(indexMdPath)) {
19701
21183
  const agent = parseAgentFile(indexMdPath, location);
19702
21184
  if (agent) {
19703
21185
  agent.path = dirPath;
@@ -19707,11 +21189,11 @@ function parseAgentDir(dirPath, location = "project") {
19707
21189
  return null;
19708
21190
  }
19709
21191
  function loadAgentMetadata(metadataPath) {
19710
- if (!existsSync34(metadataPath)) {
21192
+ if (!existsSync35(metadataPath)) {
19711
21193
  return null;
19712
21194
  }
19713
21195
  try {
19714
- const content = readFileSync24(metadataPath, "utf-8");
21196
+ const content = readFileSync25(metadataPath, "utf-8");
19715
21197
  const data = JSON.parse(content);
19716
21198
  const parsed = AgentMetadata.safeParse(data);
19717
21199
  return parsed.success ? parsed.data : null;
@@ -19812,25 +21294,25 @@ function fromCanonicalAgent(canonical, _targetFormat = "claude-agent") {
19812
21294
  return lines.join("\n");
19813
21295
  }
19814
21296
  function readAgentContent(agentPath) {
19815
- if (existsSync34(agentPath) && extname2(agentPath) === ".md") {
21297
+ if (existsSync35(agentPath) && extname2(agentPath) === ".md") {
19816
21298
  try {
19817
- return readFileSync24(agentPath, "utf-8");
21299
+ return readFileSync25(agentPath, "utf-8");
19818
21300
  } catch {
19819
21301
  return null;
19820
21302
  }
19821
21303
  }
19822
- const agentMdPath = join34(agentPath, "AGENT.md");
19823
- if (existsSync34(agentMdPath)) {
21304
+ const agentMdPath = join35(agentPath, "AGENT.md");
21305
+ if (existsSync35(agentMdPath)) {
19824
21306
  try {
19825
- return readFileSync24(agentMdPath, "utf-8");
21307
+ return readFileSync25(agentMdPath, "utf-8");
19826
21308
  } catch {
19827
21309
  return null;
19828
21310
  }
19829
21311
  }
19830
- const indexMdPath = join34(agentPath, "index.md");
19831
- if (existsSync34(indexMdPath)) {
21312
+ const indexMdPath = join35(agentPath, "index.md");
21313
+ if (existsSync35(indexMdPath)) {
19832
21314
  try {
19833
- return readFileSync24(indexMdPath, "utf-8");
21315
+ return readFileSync25(indexMdPath, "utf-8");
19834
21316
  } catch {
19835
21317
  return null;
19836
21318
  }
@@ -19841,17 +21323,17 @@ function validateAgent(agentPath) {
19841
21323
  const errors = [];
19842
21324
  const warnings = [];
19843
21325
  let filePath = agentPath;
19844
- if (!existsSync34(agentPath)) {
21326
+ if (!existsSync35(agentPath)) {
19845
21327
  errors.push(`Agent file not found: ${agentPath}`);
19846
21328
  return { valid: false, errors, warnings };
19847
21329
  }
19848
21330
  const stats = statSync7(agentPath);
19849
21331
  if (stats.isDirectory()) {
19850
- const agentMd = join34(agentPath, "AGENT.md");
19851
- const indexMd = join34(agentPath, "index.md");
19852
- if (existsSync34(agentMd)) {
21332
+ const agentMd = join35(agentPath, "AGENT.md");
21333
+ const indexMd = join35(agentPath, "index.md");
21334
+ if (existsSync35(agentMd)) {
19853
21335
  filePath = agentMd;
19854
- } else if (existsSync34(indexMd)) {
21336
+ } else if (existsSync35(indexMd)) {
19855
21337
  filePath = indexMd;
19856
21338
  } else {
19857
21339
  errors.push("Directory must contain AGENT.md or index.md");
@@ -19860,7 +21342,7 @@ function validateAgent(agentPath) {
19860
21342
  }
19861
21343
  let content;
19862
21344
  try {
19863
- content = readFileSync24(filePath, "utf-8");
21345
+ content = readFileSync25(filePath, "utf-8");
19864
21346
  } catch {
19865
21347
  errors.push(`Cannot read file: ${filePath}`);
19866
21348
  return { valid: false, errors, warnings };
@@ -19878,7 +21360,7 @@ function validateAgent(agentPath) {
19878
21360
  }
19879
21361
  if (parsed.success) {
19880
21362
  const data = parsed.data;
19881
- const fileName = basename11(filePath, ".md");
21363
+ const fileName = basename14(filePath, ".md");
19882
21364
  if (data.name !== fileName && fileName !== "AGENT" && fileName !== "index") {
19883
21365
  warnings.push(`name "${data.name}" does not match filename "${fileName}"`);
19884
21366
  }
@@ -19897,18 +21379,18 @@ function validateAgent(agentPath) {
19897
21379
  }
19898
21380
 
19899
21381
  // src/agents/discovery.ts
19900
- import { existsSync as existsSync35, readdirSync as readdirSync10, statSync as statSync8 } from "fs";
19901
- import { join as join35, extname as extname3 } from "path";
19902
- import { homedir as homedir12 } from "os";
21382
+ import { existsSync as existsSync36, readdirSync as readdirSync10, statSync as statSync8 } from "fs";
21383
+ import { join as join36, extname as extname3 } from "path";
21384
+ import { homedir as homedir13 } from "os";
19903
21385
  function discoverAgentsInDir(dir, location) {
19904
21386
  const agents = [];
19905
- if (!existsSync35(dir)) {
21387
+ if (!existsSync36(dir)) {
19906
21388
  return agents;
19907
21389
  }
19908
21390
  try {
19909
21391
  const entries = readdirSync10(dir, { withFileTypes: true });
19910
21392
  for (const entry of entries) {
19911
- const entryPath = join35(dir, entry.name);
21393
+ const entryPath = join36(dir, entry.name);
19912
21394
  if (entry.isFile() && extname3(entry.name) === ".md") {
19913
21395
  const agent = parseAgentFile(entryPath, location);
19914
21396
  if (agent) {
@@ -19929,8 +21411,8 @@ function discoverAgents(rootDir) {
19929
21411
  const agents = [];
19930
21412
  const seen = /* @__PURE__ */ new Set();
19931
21413
  for (const searchPath of ALL_AGENT_DISCOVERY_PATHS) {
19932
- const fullPath = join35(rootDir, searchPath);
19933
- if (existsSync35(fullPath)) {
21414
+ const fullPath = join36(rootDir, searchPath);
21415
+ if (existsSync36(fullPath)) {
19934
21416
  for (const agent of discoverAgentsInDir(fullPath, "project")) {
19935
21417
  if (!seen.has(agent.name)) {
19936
21418
  seen.add(agent.name);
@@ -19946,8 +21428,8 @@ function discoverAgentsForAgent(rootDir, agentType) {
19946
21428
  const seen = /* @__PURE__ */ new Set();
19947
21429
  const paths = AGENT_DISCOVERY_PATHS[agentType] || [];
19948
21430
  for (const searchPath of paths) {
19949
- const fullPath = join35(rootDir, searchPath);
19950
- if (existsSync35(fullPath)) {
21431
+ const fullPath = join36(rootDir, searchPath);
21432
+ if (existsSync36(fullPath)) {
19951
21433
  for (const agent of discoverAgentsInDir(fullPath, "project")) {
19952
21434
  if (!seen.has(agent.name)) {
19953
21435
  seen.add(agent.name);
@@ -19961,14 +21443,14 @@ function discoverAgentsForAgent(rootDir, agentType) {
19961
21443
  function discoverGlobalAgents() {
19962
21444
  const agents = [];
19963
21445
  const seen = /* @__PURE__ */ new Set();
19964
- const home = homedir12();
21446
+ const home = homedir13();
19965
21447
  const globalPaths = [
19966
- join35(home, ".claude", "agents"),
19967
- join35(home, ".skillkit", "agents"),
19968
- join35(home, ".config", "skillkit", "agents")
21448
+ join36(home, ".claude", "agents"),
21449
+ join36(home, ".skillkit", "agents"),
21450
+ join36(home, ".config", "skillkit", "agents")
19969
21451
  ];
19970
21452
  for (const searchPath of globalPaths) {
19971
- if (existsSync35(searchPath)) {
21453
+ if (existsSync36(searchPath)) {
19972
21454
  for (const agent of discoverAgentsInDir(searchPath, "global")) {
19973
21455
  if (!seen.has(agent.name)) {
19974
21456
  seen.add(agent.name);
@@ -19983,7 +21465,7 @@ function findAllAgents(searchDirs) {
19983
21465
  const agents = [];
19984
21466
  const seen = /* @__PURE__ */ new Set();
19985
21467
  for (const dir of searchDirs) {
19986
- if (!existsSync35(dir)) continue;
21468
+ if (!existsSync36(dir)) continue;
19987
21469
  const discovered = discoverAgents(dir);
19988
21470
  for (const agent of discovered) {
19989
21471
  if (!seen.has(agent.name)) {
@@ -20002,33 +21484,33 @@ function findAllAgents(searchDirs) {
20002
21484
  }
20003
21485
  function findAgent(name, searchDirs) {
20004
21486
  for (const dir of searchDirs) {
20005
- if (!existsSync35(dir)) continue;
21487
+ if (!existsSync36(dir)) continue;
20006
21488
  for (const searchPath of ALL_AGENT_DISCOVERY_PATHS) {
20007
- const agentsDir = join35(dir, searchPath);
20008
- if (!existsSync35(agentsDir)) continue;
20009
- const agentFile = join35(agentsDir, `${name}.md`);
20010
- if (existsSync35(agentFile)) {
21489
+ const agentsDir = join36(dir, searchPath);
21490
+ if (!existsSync36(agentsDir)) continue;
21491
+ const agentFile = join36(agentsDir, `${name}.md`);
21492
+ if (existsSync36(agentFile)) {
20011
21493
  return parseAgentFile(agentFile, "project");
20012
21494
  }
20013
- const agentDir = join35(agentsDir, name);
20014
- if (existsSync35(agentDir) && statSync8(agentDir).isDirectory()) {
21495
+ const agentDir = join36(agentsDir, name);
21496
+ if (existsSync36(agentDir) && statSync8(agentDir).isDirectory()) {
20015
21497
  return parseAgentDir(agentDir, "project");
20016
21498
  }
20017
21499
  }
20018
21500
  }
20019
- const home = homedir12();
21501
+ const home = homedir13();
20020
21502
  const globalPaths = [
20021
- join35(home, ".claude", "agents"),
20022
- join35(home, ".skillkit", "agents")
21503
+ join36(home, ".claude", "agents"),
21504
+ join36(home, ".skillkit", "agents")
20023
21505
  ];
20024
21506
  for (const agentsDir of globalPaths) {
20025
- if (!existsSync35(agentsDir)) continue;
20026
- const agentFile = join35(agentsDir, `${name}.md`);
20027
- if (existsSync35(agentFile)) {
21507
+ if (!existsSync36(agentsDir)) continue;
21508
+ const agentFile = join36(agentsDir, `${name}.md`);
21509
+ if (existsSync36(agentFile)) {
20028
21510
  return parseAgentFile(agentFile, "global");
20029
21511
  }
20030
- const agentDir = join35(agentsDir, name);
20031
- if (existsSync35(agentDir) && statSync8(agentDir).isDirectory()) {
21512
+ const agentDir = join36(agentsDir, name);
21513
+ if (existsSync36(agentDir) && statSync8(agentDir).isDirectory()) {
20032
21514
  return parseAgentDir(agentDir, "global");
20033
21515
  }
20034
21516
  }
@@ -20037,9 +21519,9 @@ function findAgent(name, searchDirs) {
20037
21519
  function getAgentsDirectory(rootDir, agentType) {
20038
21520
  const paths = AGENT_DISCOVERY_PATHS[agentType];
20039
21521
  if (paths && paths.length > 0) {
20040
- return join35(rootDir, paths[0]);
21522
+ return join36(rootDir, paths[0]);
20041
21523
  }
20042
- return join35(rootDir, "agents");
21524
+ return join36(rootDir, "agents");
20043
21525
  }
20044
21526
  function agentExists(name, searchDirs) {
20045
21527
  return findAgent(name, searchDirs) !== null;
@@ -20057,14 +21539,14 @@ function getAgentStats(searchDirs) {
20057
21539
  function discoverAgentsRecursive(rootDir, location = "project") {
20058
21540
  const agents = [];
20059
21541
  const seen = /* @__PURE__ */ new Set();
20060
- if (!existsSync35(rootDir)) {
21542
+ if (!existsSync36(rootDir)) {
20061
21543
  return agents;
20062
21544
  }
20063
21545
  function scanDirectory(dir) {
20064
21546
  try {
20065
21547
  const entries = readdirSync10(dir, { withFileTypes: true });
20066
21548
  for (const entry of entries) {
20067
- const entryPath = join35(dir, entry.name);
21549
+ const entryPath = join36(dir, entry.name);
20068
21550
  if (entry.isFile() && extname3(entry.name) === ".md") {
20069
21551
  const agent = parseAgentFile(entryPath, location);
20070
21552
  if (agent && !seen.has(agent.name)) {
@@ -20091,7 +21573,7 @@ function discoverAgentsRecursive(rootDir, location = "project") {
20091
21573
  return agents;
20092
21574
  }
20093
21575
  function discoverAgentsFromPath(sourcePath, recursive = false, location = "project") {
20094
- if (!existsSync35(sourcePath)) {
21576
+ if (!existsSync36(sourcePath)) {
20095
21577
  return [];
20096
21578
  }
20097
21579
  const stats = statSync8(sourcePath);
@@ -20114,7 +21596,7 @@ function discoverAgentsFromPath(sourcePath, recursive = false, location = "proje
20114
21596
  try {
20115
21597
  const entries = readdirSync10(sourcePath, { withFileTypes: true });
20116
21598
  for (const entry of entries) {
20117
- const entryPath = join35(sourcePath, entry.name);
21599
+ const entryPath = join36(sourcePath, entry.name);
20118
21600
  if (entry.isFile() && extname3(entry.name) === ".md") {
20119
21601
  const a = parseAgentFile(entryPath, location);
20120
21602
  if (a) agents.push(a);
@@ -20131,7 +21613,7 @@ function discoverAgentsFromPath(sourcePath, recursive = false, location = "proje
20131
21613
  }
20132
21614
 
20133
21615
  // src/agents/translator.ts
20134
- import { join as join36 } from "path";
21616
+ import { join as join37 } from "path";
20135
21617
  function translateAgent(agent, targetAgent, options) {
20136
21618
  const canonical = toCanonicalAgent(agent);
20137
21619
  return translateCanonicalAgent(canonical, targetAgent, options);
@@ -20352,9 +21834,9 @@ function getAgentFilename(agentName, targetAgent) {
20352
21834
  function getAgentTargetDirectory(rootDir, targetAgent) {
20353
21835
  const paths = AGENT_DISCOVERY_PATHS[targetAgent];
20354
21836
  if (paths && paths.length > 0) {
20355
- return join36(rootDir, paths[0]);
21837
+ return join37(rootDir, paths[0]);
20356
21838
  }
20357
- return join36(rootDir, "agents");
21839
+ return join37(rootDir, "agents");
20358
21840
  }
20359
21841
  function escapeYamlString(str) {
20360
21842
  if (/[:\{\}\[\],&*#?|\-<>=!%@`]/.test(str) || str.includes("\n")) {
@@ -20541,8 +22023,8 @@ function loadAndConvertSkill(skill, options) {
20541
22023
  }
20542
22024
 
20543
22025
  // src/skill-translator.ts
20544
- import { readFileSync as readFileSync25, existsSync as existsSync36, writeFileSync as writeFileSync19, mkdirSync as mkdirSync20 } from "fs";
20545
- import { join as join37, basename as basename12, dirname as dirname12, resolve as resolve5, relative as relative3, isAbsolute as isAbsolute2 } from "path";
22026
+ import { readFileSync as readFileSync26, existsSync as existsSync37, writeFileSync as writeFileSync20, mkdirSync as mkdirSync21 } from "fs";
22027
+ import { join as join38, basename as basename15, dirname as dirname13, resolve as resolve5, relative as relative3, isAbsolute as isAbsolute2 } from "path";
20546
22028
  import { parse as parseYaml11, stringify as stringifyYaml8 } from "yaml";
20547
22029
  var AGENT_SKILL_FORMATS = Object.fromEntries(
20548
22030
  Object.entries(AGENT_CONFIG).map(([agent, config]) => [
@@ -20551,12 +22033,12 @@ var AGENT_SKILL_FORMATS = Object.fromEntries(
20551
22033
  ])
20552
22034
  );
20553
22035
  function parseSkillToCanonical(skillPath, sourceAgent) {
20554
- const skillMdPath = skillPath.endsWith("SKILL.md") ? skillPath : join37(skillPath, "SKILL.md");
20555
- if (!existsSync36(skillMdPath)) {
22036
+ const skillMdPath = skillPath.endsWith("SKILL.md") ? skillPath : join38(skillPath, "SKILL.md");
22037
+ if (!existsSync37(skillMdPath)) {
20556
22038
  return null;
20557
22039
  }
20558
22040
  try {
20559
- const content = readFileSync25(skillMdPath, "utf-8");
22041
+ const content = readFileSync26(skillMdPath, "utf-8");
20560
22042
  return parseSkillContentToCanonical(content, skillPath, sourceAgent);
20561
22043
  } catch {
20562
22044
  return null;
@@ -20573,7 +22055,7 @@ function parseSkillContentToCanonical(content, sourcePath, sourceAgent) {
20573
22055
  } catch {
20574
22056
  }
20575
22057
  }
20576
- const name = frontmatter.name || basename12(sourcePath.endsWith(".md") ? dirname12(sourcePath) : sourcePath);
22058
+ const name = frontmatter.name || basename15(sourcePath.endsWith(".md") ? dirname13(sourcePath) : sourcePath);
20577
22059
  const description = frontmatter.description || extractDescriptionFromContent(bodyContent);
20578
22060
  return {
20579
22061
  name,
@@ -20644,7 +22126,7 @@ function translateSkillToAgent(canonical, targetAgent, options) {
20644
22126
  }
20645
22127
  const content = generateSkillContent(canonical, targetAgent, format, options);
20646
22128
  const filename = options?.outputFilename || "SKILL.md";
20647
- const targetDir = options?.outputDir || join37(format.skillsDir, canonical.name);
22129
+ const targetDir = options?.outputDir || join38(format.skillsDir, canonical.name);
20648
22130
  return {
20649
22131
  success: true,
20650
22132
  content,
@@ -20783,7 +22265,7 @@ function writeTranslatedSkill(result, rootDir, options) {
20783
22265
  try {
20784
22266
  const rootPath = resolve5(rootDir);
20785
22267
  const filePath = resolve5(rootDir, result.targetDir, result.filename);
20786
- const targetPath = dirname12(filePath);
22268
+ const targetPath = dirname13(filePath);
20787
22269
  const relPath = relative3(rootPath, filePath);
20788
22270
  if (relPath.startsWith("..") || isAbsolute2(relPath)) {
20789
22271
  return {
@@ -20792,7 +22274,7 @@ function writeTranslatedSkill(result, rootDir, options) {
20792
22274
  error: "Resolved output path escapes rootDir"
20793
22275
  };
20794
22276
  }
20795
- if (existsSync36(filePath) && options?.overwrite === false) {
22277
+ if (existsSync37(filePath) && options?.overwrite === false) {
20796
22278
  return {
20797
22279
  success: false,
20798
22280
  path: filePath,
@@ -20800,10 +22282,10 @@ function writeTranslatedSkill(result, rootDir, options) {
20800
22282
  skipped: true
20801
22283
  };
20802
22284
  }
20803
- if (!existsSync36(targetPath)) {
20804
- mkdirSync20(targetPath, { recursive: true });
22285
+ if (!existsSync37(targetPath)) {
22286
+ mkdirSync21(targetPath, { recursive: true });
20805
22287
  }
20806
- writeFileSync19(filePath, result.content, "utf-8");
22288
+ writeFileSync20(filePath, result.content, "utf-8");
20807
22289
  return { success: true, path: filePath };
20808
22290
  } catch (error) {
20809
22291
  return {
@@ -20986,30 +22468,30 @@ var getAgentSkillsDir = getSkillsDir;
20986
22468
  var getAgentConfigFile = getConfigFile;
20987
22469
 
20988
22470
  // src/manifest/index.ts
20989
- import { readFileSync as readFileSync26, writeFileSync as writeFileSync20, existsSync as existsSync37 } from "fs";
20990
- import { join as join38, dirname as dirname13 } from "path";
22471
+ import { readFileSync as readFileSync27, writeFileSync as writeFileSync21, existsSync as existsSync38 } from "fs";
22472
+ import { join as join39, dirname as dirname14 } from "path";
20991
22473
  import { parse as parseYaml12, stringify as stringifyYaml9 } from "yaml";
20992
22474
  var MANIFEST_FILENAMES = [".skills", ".skills.yaml", ".skills.yml", "skills.yaml"];
20993
22475
  function findManifestPath(startDir = process.cwd()) {
20994
22476
  let dir = startDir;
20995
- while (dir !== dirname13(dir)) {
22477
+ while (dir !== dirname14(dir)) {
20996
22478
  for (const filename of MANIFEST_FILENAMES) {
20997
- const manifestPath = join38(dir, filename);
20998
- if (existsSync37(manifestPath)) {
22479
+ const manifestPath = join39(dir, filename);
22480
+ if (existsSync38(manifestPath)) {
20999
22481
  return manifestPath;
21000
22482
  }
21001
22483
  }
21002
- dir = dirname13(dir);
22484
+ dir = dirname14(dir);
21003
22485
  }
21004
22486
  return null;
21005
22487
  }
21006
22488
  function loadManifest(manifestPath) {
21007
22489
  const path4 = manifestPath || findManifestPath();
21008
- if (!path4 || !existsSync37(path4)) {
22490
+ if (!path4 || !existsSync38(path4)) {
21009
22491
  return null;
21010
22492
  }
21011
22493
  try {
21012
- const content = readFileSync26(path4, "utf-8");
22494
+ const content = readFileSync27(path4, "utf-8");
21013
22495
  const parsed = parseYaml12(content);
21014
22496
  if (!parsed || typeof parsed !== "object") {
21015
22497
  return null;
@@ -21051,7 +22533,7 @@ function normalizeSkills(skills) {
21051
22533
  }).filter((s) => s.source);
21052
22534
  }
21053
22535
  function saveManifest(manifest, manifestPath) {
21054
- const path4 = manifestPath || join38(process.cwd(), ".skills");
22536
+ const path4 = manifestPath || join39(process.cwd(), ".skills");
21055
22537
  const content = stringifyYaml9({
21056
22538
  version: manifest.version || 1,
21057
22539
  skills: manifest.skills.map((s) => {
@@ -21064,7 +22546,7 @@ function saveManifest(manifest, manifestPath) {
21064
22546
  ...manifest.installMethod && { installMethod: manifest.installMethod },
21065
22547
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
21066
22548
  });
21067
- writeFileSync20(path4, content, "utf-8");
22549
+ writeFileSync21(path4, content, "utf-8");
21068
22550
  }
21069
22551
  function addToManifest(source, options, manifestPath) {
21070
22552
  const existing = loadManifest(manifestPath) || {
@@ -21141,8 +22623,8 @@ function generateManifestFromInstalled(installedSkills) {
21141
22623
  }
21142
22624
 
21143
22625
  // src/quality/index.ts
21144
- import { readFileSync as readFileSync27, existsSync as existsSync38 } from "fs";
21145
- import { join as join39, basename as basename13 } from "path";
22626
+ import { readFileSync as readFileSync28, existsSync as existsSync39 } from "fs";
22627
+ import { join as join40, basename as basename16 } from "path";
21146
22628
 
21147
22629
  // src/quality/benchmark.ts
21148
22630
  var CATEGORY_BENCHMARKS = {
@@ -21744,23 +23226,23 @@ function evaluateSkillContent(content) {
21744
23226
  };
21745
23227
  }
21746
23228
  function evaluateSkillFile(filePath) {
21747
- if (!existsSync38(filePath)) return null;
23229
+ if (!existsSync39(filePath)) return null;
21748
23230
  try {
21749
- const content = readFileSync27(filePath, "utf-8");
23231
+ const content = readFileSync28(filePath, "utf-8");
21750
23232
  return evaluateSkillContent(content);
21751
23233
  } catch {
21752
23234
  return null;
21753
23235
  }
21754
23236
  }
21755
23237
  function evaluateSkillDirectory(dirPath) {
21756
- const skillMdPath = join39(dirPath, "SKILL.md");
21757
- if (existsSync38(skillMdPath)) {
23238
+ const skillMdPath = join40(dirPath, "SKILL.md");
23239
+ if (existsSync39(skillMdPath)) {
21758
23240
  return evaluateSkillFile(skillMdPath);
21759
23241
  }
21760
- const mdcFiles = ["index.mdc", `${basename13(dirPath)}.mdc`];
23242
+ const mdcFiles = ["index.mdc", `${basename16(dirPath)}.mdc`];
21761
23243
  for (const file of mdcFiles) {
21762
- const mdcPath = join39(dirPath, file);
21763
- if (existsSync38(mdcPath)) {
23244
+ const mdcPath = join40(dirPath, file);
23245
+ if (existsSync39(mdcPath)) {
21764
23246
  return evaluateSkillFile(mdcPath);
21765
23247
  }
21766
23248
  }
@@ -21930,8 +23412,8 @@ var AGENT_INSTRUCTION_TEMPLATES = {
21930
23412
  };
21931
23413
 
21932
23414
  // src/primer/analyzer.ts
21933
- import { existsSync as existsSync39, readFileSync as readFileSync28, readdirSync as readdirSync11 } from "fs";
21934
- import { join as join40, basename as basename14, relative as relative4, sep as sep4 } from "path";
23415
+ import { existsSync as existsSync40, readFileSync as readFileSync29, readdirSync as readdirSync11 } from "fs";
23416
+ import { join as join41, basename as basename17, relative as relative4, sep as sep4 } from "path";
21935
23417
  var PACKAGE_MANAGER_FILES = {
21936
23418
  "package-lock.json": "npm",
21937
23419
  "pnpm-lock.yaml": "pnpm",
@@ -22019,10 +23501,10 @@ var PrimerAnalyzer = class {
22019
23501
  return analysis;
22020
23502
  }
22021
23503
  loadPackageJson() {
22022
- const packageJsonPath = join40(this.projectPath, "package.json");
22023
- if (existsSync39(packageJsonPath)) {
23504
+ const packageJsonPath = join41(this.projectPath, "package.json");
23505
+ if (existsSync40(packageJsonPath)) {
22024
23506
  try {
22025
- const content = readFileSync28(packageJsonPath, "utf-8");
23507
+ const content = readFileSync29(packageJsonPath, "utf-8");
22026
23508
  this.packageJson = JSON.parse(content);
22027
23509
  } catch {
22028
23510
  this.packageJson = null;
@@ -22035,7 +23517,7 @@ var PrimerAnalyzer = class {
22035
23517
  try {
22036
23518
  const entries = readdirSync11(dir, { withFileTypes: true });
22037
23519
  for (const entry of entries) {
22038
- const fullPath = join40(dir, entry.name);
23520
+ const fullPath = join41(dir, entry.name);
22039
23521
  const relativePath = relative4(this.projectPath, fullPath);
22040
23522
  if (entry.name.startsWith(".") && entry.name !== ".github" && entry.name !== ".env.example") {
22041
23523
  if (!entry.isDirectory()) {
@@ -22058,7 +23540,7 @@ var PrimerAnalyzer = class {
22058
23540
  }
22059
23541
  getProjectInfo() {
22060
23542
  const info = {
22061
- name: basename14(this.projectPath)
23543
+ name: basename17(this.projectPath)
22062
23544
  };
22063
23545
  if (this.packageJson) {
22064
23546
  if (typeof this.packageJson.name === "string") {
@@ -22080,10 +23562,10 @@ var PrimerAnalyzer = class {
22080
23562
  info.repository = String(repo.url);
22081
23563
  }
22082
23564
  }
22083
- const pyprojectPath = join40(this.projectPath, "pyproject.toml");
22084
- if (!this.packageJson && existsSync39(pyprojectPath)) {
23565
+ const pyprojectPath = join41(this.projectPath, "pyproject.toml");
23566
+ if (!this.packageJson && existsSync40(pyprojectPath)) {
22085
23567
  try {
22086
- const content = readFileSync28(pyprojectPath, "utf-8");
23568
+ const content = readFileSync29(pyprojectPath, "utf-8");
22087
23569
  const nameMatch = content.match(/name\s*=\s*["']([^"']+)["']/);
22088
23570
  const versionMatch = content.match(/version\s*=\s*["']([^"']+)["']/);
22089
23571
  const descMatch = content.match(/description\s*=\s*["']([^"']+)["']/);
@@ -22093,10 +23575,10 @@ var PrimerAnalyzer = class {
22093
23575
  } catch {
22094
23576
  }
22095
23577
  }
22096
- const cargoPath = join40(this.projectPath, "Cargo.toml");
22097
- if (!this.packageJson && existsSync39(cargoPath)) {
23578
+ const cargoPath = join41(this.projectPath, "Cargo.toml");
23579
+ if (!this.packageJson && existsSync40(cargoPath)) {
22098
23580
  try {
22099
- const content = readFileSync28(cargoPath, "utf-8");
23581
+ const content = readFileSync29(cargoPath, "utf-8");
22100
23582
  const nameMatch = content.match(/name\s*=\s*["']([^"']+)["']/);
22101
23583
  const versionMatch = content.match(/version\s*=\s*["']([^"']+)["']/);
22102
23584
  const descMatch = content.match(/description\s*=\s*["']([^"']+)["']/);
@@ -22276,8 +23758,8 @@ var PrimerAnalyzer = class {
22276
23758
  }
22277
23759
  if (this.hasFile("tsconfig.json")) {
22278
23760
  try {
22279
- const tsconfigPath = join40(this.projectPath, "tsconfig.json");
22280
- const content = readFileSync28(tsconfigPath, "utf-8");
23761
+ const tsconfigPath = join41(this.projectPath, "tsconfig.json");
23762
+ const content = readFileSync29(tsconfigPath, "utf-8");
22281
23763
  const tsconfig = JSON.parse(content.replace(/\/\/.*$/gm, "").replace(/,\s*}/g, "}"));
22282
23764
  const paths = tsconfig.compilerOptions?.paths;
22283
23765
  if (paths && Object.keys(paths).some((k) => k.startsWith("@"))) {
@@ -22306,7 +23788,7 @@ var PrimerAnalyzer = class {
22306
23788
  ci.provider = "github-actions";
22307
23789
  ci.configFile = ".github/workflows";
22308
23790
  try {
22309
- const workflowsDir = join40(this.projectPath, ".github/workflows");
23791
+ const workflowsDir = join41(this.projectPath, ".github/workflows");
22310
23792
  const workflows = readdirSync11(workflowsDir);
22311
23793
  const deployWorkflows = workflows.filter(
22312
23794
  (f) => f.includes("deploy") || f.includes("release") || f.includes("publish")
@@ -22327,12 +23809,12 @@ var PrimerAnalyzer = class {
22327
23809
  env.hasEnvFile = this.hasFile(".env");
22328
23810
  env.hasEnvExample = this.hasFile(".env.example") || this.hasFile(".env.template") || this.hasFile(".env.sample");
22329
23811
  if (env.hasEnvExample) {
22330
- const envExamplePath = join40(
23812
+ const envExamplePath = join41(
22331
23813
  this.projectPath,
22332
23814
  this.hasFile(".env.example") ? ".env.example" : this.hasFile(".env.template") ? ".env.template" : ".env.sample"
22333
23815
  );
22334
23816
  try {
22335
- const content = readFileSync28(envExamplePath, "utf-8");
23817
+ const content = readFileSync29(envExamplePath, "utf-8");
22336
23818
  const variables = content.split("\n").filter((line) => line.trim() && !line.startsWith("#")).map((line) => line.split("=")[0].trim()).filter((v) => v);
22337
23819
  env.envVariables = variables;
22338
23820
  } catch {
@@ -22349,8 +23831,8 @@ var PrimerAnalyzer = class {
22349
23831
  docker.hasCompose = this.hasFile("docker-compose.yml") || this.hasFile("docker-compose.yaml") || this.hasFile("compose.yml");
22350
23832
  if (docker.hasDockerfile) {
22351
23833
  try {
22352
- const dockerfilePath = join40(this.projectPath, "Dockerfile");
22353
- const content = readFileSync28(dockerfilePath, "utf-8");
23834
+ const dockerfilePath = join41(this.projectPath, "Dockerfile");
23835
+ const content = readFileSync29(dockerfilePath, "utf-8");
22354
23836
  const fromMatch = content.match(/^FROM\s+(\S+)/m);
22355
23837
  if (fromMatch) {
22356
23838
  docker.baseImage = fromMatch[1];
@@ -22439,7 +23921,7 @@ var PrimerAnalyzer = class {
22439
23921
  }
22440
23922
  return false;
22441
23923
  }
22442
- return this.files.has(name) || existsSync39(join40(this.projectPath, name));
23924
+ return this.files.has(name) || existsSync40(join41(this.projectPath, name));
22443
23925
  }
22444
23926
  getDepVersion(dep) {
22445
23927
  if (!this.packageJson) return void 0;
@@ -22461,10 +23943,10 @@ var PrimerAnalyzer = class {
22461
23943
  }
22462
23944
  readConfigFile(files) {
22463
23945
  for (const file of files) {
22464
- const filePath = join40(this.projectPath, file);
22465
- if (existsSync39(filePath)) {
23946
+ const filePath = join41(this.projectPath, file);
23947
+ if (existsSync40(filePath)) {
22466
23948
  try {
22467
- const content = readFileSync28(filePath, "utf-8");
23949
+ const content = readFileSync29(filePath, "utf-8");
22468
23950
  if (file.endsWith(".json")) {
22469
23951
  return JSON.parse(content);
22470
23952
  }
@@ -22482,8 +23964,8 @@ function analyzePrimer(projectPath) {
22482
23964
  }
22483
23965
 
22484
23966
  // src/primer/generator.ts
22485
- import { existsSync as existsSync40, mkdirSync as mkdirSync21, writeFileSync as writeFileSync21 } from "fs";
22486
- import { join as join41, dirname as dirname14 } from "path";
23967
+ import { existsSync as existsSync41, mkdirSync as mkdirSync22, writeFileSync as writeFileSync22 } from "fs";
23968
+ import { join as join42, dirname as dirname15 } from "path";
22487
23969
  var ALL_AGENTS = Object.keys(AGENT_CONFIG);
22488
23970
  var markdownRenderer = {
22489
23971
  h1: (text) => `# ${text}`,
@@ -22647,14 +24129,14 @@ var PrimerGenerator = class {
22647
24129
  detectInstalledAgents() {
22648
24130
  const detected = [];
22649
24131
  for (const [agent, config] of Object.entries(AGENT_CONFIG)) {
22650
- const configPath = join41(this.projectPath, config.configFile);
22651
- const skillsPath = join41(this.projectPath, config.skillsDir);
22652
- if (existsSync40(configPath) || existsSync40(skillsPath)) {
24132
+ const configPath = join42(this.projectPath, config.configFile);
24133
+ const skillsPath = join42(this.projectPath, config.skillsDir);
24134
+ if (existsSync41(configPath) || existsSync41(skillsPath)) {
22653
24135
  detected.push(agent);
22654
24136
  }
22655
24137
  if (config.altSkillsDirs) {
22656
24138
  for (const altDir of config.altSkillsDirs) {
22657
- if (existsSync40(join41(this.projectPath, altDir))) {
24139
+ if (existsSync41(join42(this.projectPath, altDir))) {
22658
24140
  if (!detected.includes(agent)) {
22659
24141
  detected.push(agent);
22660
24142
  }
@@ -22674,7 +24156,7 @@ var PrimerGenerator = class {
22674
24156
  const template = AGENT_INSTRUCTION_TEMPLATES[agent] || this.getDefaultTemplate(agent, config);
22675
24157
  const content = this.generateContent(template);
22676
24158
  const outputDir = this.options.outputDir || this.projectPath;
22677
- const filepath = join41(outputDir, template.filename);
24159
+ const filepath = join42(outputDir, template.filename);
22678
24160
  return {
22679
24161
  agent,
22680
24162
  filename: template.filename,
@@ -23046,11 +24528,11 @@ var PrimerGenerator = class {
23046
24528
  return lines.join("\n");
23047
24529
  }
23048
24530
  writeInstruction(instruction) {
23049
- const dir = dirname14(instruction.filepath);
23050
- if (!existsSync40(dir)) {
23051
- mkdirSync21(dir, { recursive: true });
24531
+ const dir = dirname15(instruction.filepath);
24532
+ if (!existsSync41(dir)) {
24533
+ mkdirSync22(dir, { recursive: true });
23052
24534
  }
23053
- writeFileSync21(instruction.filepath, instruction.content, "utf-8");
24535
+ writeFileSync22(instruction.filepath, instruction.content, "utf-8");
23054
24536
  }
23055
24537
  formatProjectType(type) {
23056
24538
  const typeMap = {
@@ -23092,23 +24574,23 @@ var DEFAULT_LEARNING_CONFIG = {
23092
24574
  };
23093
24575
 
23094
24576
  // src/learning/config.ts
23095
- import { existsSync as existsSync41, readFileSync as readFileSync29, writeFileSync as writeFileSync22, mkdirSync as mkdirSync22 } from "fs";
23096
- import { join as join42, dirname as dirname15 } from "path";
23097
- import { homedir as homedir13 } from "os";
24577
+ import { existsSync as existsSync42, readFileSync as readFileSync30, writeFileSync as writeFileSync23, mkdirSync as mkdirSync23 } from "fs";
24578
+ import { join as join43, dirname as dirname16 } from "path";
24579
+ import { homedir as homedir14 } from "os";
23098
24580
  import yaml from "yaml";
23099
24581
  function getDefaultConfigPath() {
23100
- return join42(homedir13(), ".skillkit", "learning.yaml");
24582
+ return join43(homedir14(), ".skillkit", "learning.yaml");
23101
24583
  }
23102
24584
  function getDefaultStorePath() {
23103
- return join42(homedir13(), ".skillkit", "learned", "patterns.json");
24585
+ return join43(homedir14(), ".skillkit", "learned", "patterns.json");
23104
24586
  }
23105
24587
  function loadLearningConfig(configPath) {
23106
24588
  const path4 = configPath || getDefaultConfigPath();
23107
- if (!existsSync41(path4)) {
24589
+ if (!existsSync42(path4)) {
23108
24590
  return DEFAULT_LEARNING_CONFIG;
23109
24591
  }
23110
24592
  try {
23111
- const content = readFileSync29(path4, "utf-8");
24593
+ const content = readFileSync30(path4, "utf-8");
23112
24594
  const config = yaml.parse(content);
23113
24595
  return { ...DEFAULT_LEARNING_CONFIG, ...config };
23114
24596
  } catch {
@@ -23117,16 +24599,16 @@ function loadLearningConfig(configPath) {
23117
24599
  }
23118
24600
  function saveLearningConfig(config, configPath) {
23119
24601
  const path4 = configPath || getDefaultConfigPath();
23120
- const dir = dirname15(path4);
23121
- if (!existsSync41(dir)) {
23122
- mkdirSync22(dir, { recursive: true });
24602
+ const dir = dirname16(path4);
24603
+ if (!existsSync42(dir)) {
24604
+ mkdirSync23(dir, { recursive: true });
23123
24605
  }
23124
24606
  const content = yaml.stringify(config);
23125
- writeFileSync22(path4, content);
24607
+ writeFileSync23(path4, content);
23126
24608
  }
23127
24609
  function loadPatternStore(storePath) {
23128
24610
  const path4 = storePath || getDefaultStorePath();
23129
- if (!existsSync41(path4)) {
24611
+ if (!existsSync42(path4)) {
23130
24612
  return {
23131
24613
  version: 1,
23132
24614
  updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -23135,7 +24617,7 @@ function loadPatternStore(storePath) {
23135
24617
  };
23136
24618
  }
23137
24619
  try {
23138
- const content = readFileSync29(path4, "utf-8");
24620
+ const content = readFileSync30(path4, "utf-8");
23139
24621
  return JSON.parse(content);
23140
24622
  } catch {
23141
24623
  return {
@@ -23148,13 +24630,13 @@ function loadPatternStore(storePath) {
23148
24630
  }
23149
24631
  function savePatternStore(store, storePath) {
23150
24632
  const path4 = storePath || getDefaultStorePath();
23151
- const dir = dirname15(path4);
23152
- if (!existsSync41(dir)) {
23153
- mkdirSync22(dir, { recursive: true });
24633
+ const dir = dirname16(path4);
24634
+ if (!existsSync42(dir)) {
24635
+ mkdirSync23(dir, { recursive: true });
23154
24636
  }
23155
24637
  store.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
23156
24638
  const content = JSON.stringify(store, null, 2);
23157
- writeFileSync22(path4, content);
24639
+ writeFileSync23(path4, content);
23158
24640
  }
23159
24641
  function addPattern(pattern, storePath) {
23160
24642
  const store = loadPatternStore(storePath);
@@ -23197,8 +24679,8 @@ function getApprovedPatterns(storePath) {
23197
24679
 
23198
24680
  // src/learning/git-analyzer.ts
23199
24681
  import { execSync as execSync7 } from "child_process";
23200
- import { existsSync as existsSync42 } from "fs";
23201
- import { join as join43 } from "path";
24682
+ import { existsSync as existsSync43 } from "fs";
24683
+ import { join as join44 } from "path";
23202
24684
  function runGitCommand(command, cwd) {
23203
24685
  try {
23204
24686
  return execSync7(command, { cwd, encoding: "utf-8", maxBuffer: 10 * 1024 * 1024 });
@@ -23207,7 +24689,7 @@ function runGitCommand(command, cwd) {
23207
24689
  }
23208
24690
  }
23209
24691
  function isGitRepository(path4) {
23210
- return existsSync42(join43(path4, ".git"));
24692
+ return existsSync43(join44(path4, ".git"));
23211
24693
  }
23212
24694
  function getGitCommits(repoPath, options = {}) {
23213
24695
  if (!isGitRepository(repoPath)) {
@@ -23712,9 +25194,9 @@ function mergePatterns(existing, newPatterns) {
23712
25194
  }
23713
25195
 
23714
25196
  // src/learning/generator.ts
23715
- import { writeFileSync as writeFileSync23, mkdirSync as mkdirSync23, existsSync as existsSync43 } from "fs";
23716
- import { join as join44 } from "path";
23717
- import { homedir as homedir14 } from "os";
25197
+ import { writeFileSync as writeFileSync24, mkdirSync as mkdirSync24, existsSync as existsSync44 } from "fs";
25198
+ import { join as join45 } from "path";
25199
+ import { homedir as homedir15 } from "os";
23718
25200
  function generateSkillFromPatterns(patterns, options = {}) {
23719
25201
  const minConfidence = options.minConfidence ?? 0.5;
23720
25202
  const minPatterns = options.minPatterns ?? 1;
@@ -23804,12 +25286,12 @@ function generateSkillContent2(name, patterns, category) {
23804
25286
  return lines.join("\n");
23805
25287
  }
23806
25288
  function saveGeneratedSkill(skill, outputDir) {
23807
- const dir = outputDir || join44(homedir14(), ".skillkit", "skills", "learned");
23808
- if (!existsSync43(dir)) {
23809
- mkdirSync23(dir, { recursive: true });
25289
+ const dir = outputDir || join45(homedir15(), ".skillkit", "skills", "learned");
25290
+ if (!existsSync44(dir)) {
25291
+ mkdirSync24(dir, { recursive: true });
23810
25292
  }
23811
- const filepath = join44(dir, skill.filename);
23812
- writeFileSync23(filepath, skill.content);
25293
+ const filepath = join45(dir, skill.filename);
25294
+ writeFileSync24(filepath, skill.content);
23813
25295
  return filepath;
23814
25296
  }
23815
25297
  function generatePatternReport(patterns) {
@@ -24039,9 +25521,9 @@ var DEFAULT_PROFILE_CONFIG = {
24039
25521
  };
24040
25522
 
24041
25523
  // src/profiles/manager.ts
24042
- import { existsSync as existsSync44, readFileSync as readFileSync30, writeFileSync as writeFileSync24, mkdirSync as mkdirSync24 } from "fs";
24043
- import { join as join45, dirname as dirname16 } from "path";
24044
- import { homedir as homedir15 } from "os";
25524
+ import { existsSync as existsSync45, readFileSync as readFileSync31, writeFileSync as writeFileSync25, mkdirSync as mkdirSync25 } from "fs";
25525
+ import { join as join46, dirname as dirname17 } from "path";
25526
+ import { homedir as homedir16 } from "os";
24045
25527
  import yaml2 from "yaml";
24046
25528
  var BUILTIN_PROFILES = [
24047
25529
  {
@@ -24121,15 +25603,15 @@ var BUILTIN_PROFILES = [
24121
25603
  }
24122
25604
  ];
24123
25605
  function getConfigPath() {
24124
- return join45(homedir15(), ".skillkit", "profiles.yaml");
25606
+ return join46(homedir16(), ".skillkit", "profiles.yaml");
24125
25607
  }
24126
25608
  function loadProfileConfig() {
24127
25609
  const path4 = getConfigPath();
24128
- if (!existsSync44(path4)) {
25610
+ if (!existsSync45(path4)) {
24129
25611
  return DEFAULT_PROFILE_CONFIG;
24130
25612
  }
24131
25613
  try {
24132
- const content = readFileSync30(path4, "utf-8");
25614
+ const content = readFileSync31(path4, "utf-8");
24133
25615
  return { ...DEFAULT_PROFILE_CONFIG, ...yaml2.parse(content) };
24134
25616
  } catch {
24135
25617
  return DEFAULT_PROFILE_CONFIG;
@@ -24137,11 +25619,11 @@ function loadProfileConfig() {
24137
25619
  }
24138
25620
  function saveProfileConfig(config) {
24139
25621
  const path4 = getConfigPath();
24140
- const dir = dirname16(path4);
24141
- if (!existsSync44(dir)) {
24142
- mkdirSync24(dir, { recursive: true });
25622
+ const dir = dirname17(path4);
25623
+ if (!existsSync45(dir)) {
25624
+ mkdirSync25(dir, { recursive: true });
24143
25625
  }
24144
- writeFileSync24(path4, yaml2.stringify(config));
25626
+ writeFileSync25(path4, yaml2.stringify(config));
24145
25627
  }
24146
25628
  function getActiveProfile() {
24147
25629
  const config = loadProfileConfig();
@@ -24208,9 +25690,9 @@ var DEFAULT_GUIDELINE_CONFIG = {
24208
25690
  };
24209
25691
 
24210
25692
  // src/guidelines/manager.ts
24211
- import { existsSync as existsSync45, readFileSync as readFileSync31, writeFileSync as writeFileSync25, mkdirSync as mkdirSync25 } from "fs";
24212
- import { join as join46, dirname as dirname17 } from "path";
24213
- import { homedir as homedir16 } from "os";
25693
+ import { existsSync as existsSync46, readFileSync as readFileSync32, writeFileSync as writeFileSync26, mkdirSync as mkdirSync26 } from "fs";
25694
+ import { join as join47, dirname as dirname18 } from "path";
25695
+ import { homedir as homedir17 } from "os";
24214
25696
  import yaml3 from "yaml";
24215
25697
  var BUILTIN_GUIDELINES = [
24216
25698
  {
@@ -24387,15 +25869,15 @@ Types: feat, fix, docs, style, refactor, test, chore`
24387
25869
  }
24388
25870
  ];
24389
25871
  function getConfigPath2() {
24390
- return join46(homedir16(), ".skillkit", "guidelines.yaml");
25872
+ return join47(homedir17(), ".skillkit", "guidelines.yaml");
24391
25873
  }
24392
25874
  function loadGuidelineConfig() {
24393
25875
  const path4 = getConfigPath2();
24394
- if (!existsSync45(path4)) {
25876
+ if (!existsSync46(path4)) {
24395
25877
  return DEFAULT_GUIDELINE_CONFIG;
24396
25878
  }
24397
25879
  try {
24398
- const content = readFileSync31(path4, "utf-8");
25880
+ const content = readFileSync32(path4, "utf-8");
24399
25881
  return { ...DEFAULT_GUIDELINE_CONFIG, ...yaml3.parse(content) };
24400
25882
  } catch {
24401
25883
  return DEFAULT_GUIDELINE_CONFIG;
@@ -24403,11 +25885,11 @@ function loadGuidelineConfig() {
24403
25885
  }
24404
25886
  function saveGuidelineConfig(config) {
24405
25887
  const path4 = getConfigPath2();
24406
- const dir = dirname17(path4);
24407
- if (!existsSync45(dir)) {
24408
- mkdirSync25(dir, { recursive: true });
25888
+ const dir = dirname18(path4);
25889
+ if (!existsSync46(dir)) {
25890
+ mkdirSync26(dir, { recursive: true });
24409
25891
  }
24410
- writeFileSync25(path4, yaml3.stringify(config));
25892
+ writeFileSync26(path4, yaml3.stringify(config));
24411
25893
  }
24412
25894
  function getGuideline(id) {
24413
25895
  const builtin = BUILTIN_GUIDELINES.find((g) => g.id === id);
@@ -24489,8 +25971,8 @@ init_generator();
24489
25971
 
24490
25972
  // src/tree/serializer.ts
24491
25973
  init_types3();
24492
- import { readFileSync as readFileSync32, writeFileSync as writeFileSync26, existsSync as existsSync46, mkdirSync as mkdirSync26 } from "fs";
24493
- import { dirname as dirname18 } from "path";
25974
+ import { readFileSync as readFileSync33, writeFileSync as writeFileSync27, existsSync as existsSync47, mkdirSync as mkdirSync27 } from "fs";
25975
+ import { dirname as dirname19 } from "path";
24494
25976
  var TREE_FILE_NAME = "skill-tree.json";
24495
25977
  function serializeTree(tree) {
24496
25978
  return JSON.stringify(tree, null, 2);
@@ -24500,19 +25982,19 @@ function deserializeTree(json) {
24500
25982
  return SkillTreeSchema.parse(parsed);
24501
25983
  }
24502
25984
  function saveTree(tree, path4) {
24503
- const dir = dirname18(path4);
24504
- if (!existsSync46(dir)) {
24505
- mkdirSync26(dir, { recursive: true });
25985
+ const dir = dirname19(path4);
25986
+ if (!existsSync47(dir)) {
25987
+ mkdirSync27(dir, { recursive: true });
24506
25988
  }
24507
25989
  const json = serializeTree(tree);
24508
- writeFileSync26(path4, json, "utf-8");
25990
+ writeFileSync27(path4, json, "utf-8");
24509
25991
  }
24510
25992
  function loadTree(path4) {
24511
- if (!existsSync46(path4)) {
25993
+ if (!existsSync47(path4)) {
24512
25994
  return null;
24513
25995
  }
24514
25996
  try {
24515
- const json = readFileSync32(path4, "utf-8");
25997
+ const json = readFileSync33(path4, "utf-8");
24516
25998
  return deserializeTree(json);
24517
25999
  } catch {
24518
26000
  return null;
@@ -25229,7 +26711,7 @@ var ExecutionFlowSchema = z11.object({
25229
26711
  });
25230
26712
 
25231
26713
  // src/execution/manager.ts
25232
- import { randomUUID as randomUUID14 } from "crypto";
26714
+ import { randomUUID as randomUUID15 } from "crypto";
25233
26715
  var DEFAULT_MAX_RETRIES = 3;
25234
26716
  var DEFAULT_RETRY_DELAY = 1e3;
25235
26717
  var DEFAULT_TIMEOUT2 = 3e4;
@@ -25249,7 +26731,7 @@ var ExecutionManager = class {
25249
26731
  };
25250
26732
  }
25251
26733
  createFlow(skillName, steps, options = {}) {
25252
- const flowId = randomUUID14();
26734
+ const flowId = randomUUID15();
25253
26735
  const executionSteps = steps.map((step, index) => ({
25254
26736
  id: `${flowId}-step-${index}`,
25255
26737
  name: step.name,
@@ -25467,12 +26949,12 @@ function createExecutionManager(config) {
25467
26949
  }
25468
26950
 
25469
26951
  // src/execution/mode.ts
25470
- import { existsSync as existsSync47, readFileSync as readFileSync33 } from "fs";
25471
- import { join as join47 } from "path";
25472
- import { homedir as homedir17 } from "os";
26952
+ import { existsSync as existsSync48, readFileSync as readFileSync34 } from "fs";
26953
+ import { join as join48 } from "path";
26954
+ import { homedir as homedir18 } from "os";
25473
26955
  var DEFAULT_MCP_CONFIG_PATHS = [
25474
- join47(homedir17(), ".mcp.json"),
25475
- join47(homedir17(), ".config", "claude", "mcp.json"),
26956
+ join48(homedir18(), ".mcp.json"),
26957
+ join48(homedir18(), ".config", "claude", "mcp.json"),
25476
26958
  ".mcp.json",
25477
26959
  "mcp.json"
25478
26960
  ];
@@ -25521,8 +27003,8 @@ function detectMcpServers(configPaths) {
25521
27003
  for (const configPath of configPaths) {
25522
27004
  try {
25523
27005
  const fullPath = configPath.startsWith("~") ? configPath.replace("~", process.env.HOME || "") : configPath;
25524
- if (existsSync47(fullPath)) {
25525
- const content = readFileSync33(fullPath, "utf-8");
27006
+ if (existsSync48(fullPath)) {
27007
+ const content = readFileSync34(fullPath, "utf-8");
25526
27008
  const config = JSON.parse(content);
25527
27009
  if (config.mcpServers) {
25528
27010
  servers.push(...Object.keys(config.mcpServers));
@@ -25659,6 +27141,80 @@ init_rrf();
25659
27141
  init_expansion();
25660
27142
  init_hybrid();
25661
27143
 
27144
+ // src/registry/community.ts
27145
+ import { readFileSync as readFileSync35, existsSync as existsSync49 } from "fs";
27146
+ import { join as join49, dirname as dirname20 } from "path";
27147
+ import { fileURLToPath as fileURLToPath2 } from "url";
27148
+ var CommunityRegistry = class {
27149
+ constructor(skillsMdPath) {
27150
+ this.skillsMdPath = skillsMdPath;
27151
+ }
27152
+ name = "community";
27153
+ entries = [];
27154
+ loaded = false;
27155
+ load() {
27156
+ if (this.loaded) return;
27157
+ this.loaded = true;
27158
+ const paths = this.skillsMdPath ? [this.skillsMdPath] : [
27159
+ join49(process.cwd(), "registry", "SKILLS.md"),
27160
+ join49(dirname20(fileURLToPath2(import.meta.url)), "..", "..", "..", "..", "registry", "SKILLS.md")
27161
+ ];
27162
+ for (const path4 of paths) {
27163
+ if (!existsSync49(path4)) continue;
27164
+ try {
27165
+ const content = readFileSync35(path4, "utf-8");
27166
+ this.entries = this.parse(content);
27167
+ return;
27168
+ } catch {
27169
+ continue;
27170
+ }
27171
+ }
27172
+ }
27173
+ parse(content) {
27174
+ const results = [];
27175
+ let currentCategory = "";
27176
+ for (const line of content.split("\n")) {
27177
+ const headerMatch = line.match(/^##\s+(.+)/);
27178
+ if (headerMatch) {
27179
+ currentCategory = headerMatch[1].trim();
27180
+ continue;
27181
+ }
27182
+ const entryMatch = line.match(/^-\s+\[([^\]]+)\]\(([^)]+)\)\s*-\s*(.+)/);
27183
+ if (entryMatch) {
27184
+ results.push({
27185
+ name: entryMatch[1].trim(),
27186
+ url: entryMatch[2].trim(),
27187
+ description: entryMatch[3].trim(),
27188
+ category: currentCategory
27189
+ });
27190
+ }
27191
+ }
27192
+ return results;
27193
+ }
27194
+ async search(query, options) {
27195
+ this.load();
27196
+ const limit = options?.limit ?? 20;
27197
+ const q = query.toLowerCase();
27198
+ const matched = this.entries.filter(
27199
+ (e) => e.name.toLowerCase().includes(q) || e.description.toLowerCase().includes(q) || e.category.toLowerCase().includes(q)
27200
+ );
27201
+ return matched.slice(0, limit).map((e) => ({
27202
+ name: e.name,
27203
+ description: e.description,
27204
+ source: e.url,
27205
+ registry: this.name
27206
+ }));
27207
+ }
27208
+ getAll() {
27209
+ this.load();
27210
+ return [...this.entries];
27211
+ }
27212
+ getCategories() {
27213
+ this.load();
27214
+ return [...new Set(this.entries.map((e) => e.category))];
27215
+ }
27216
+ };
27217
+
25662
27218
  // src/registry/index.ts
25663
27219
  var RateLimitError = class extends Error {
25664
27220
  constructor(registry) {
@@ -25765,6 +27321,296 @@ var FederatedSearch = class {
25765
27321
  };
25766
27322
  }
25767
27323
  };
27324
+
27325
+ // src/cache/memory.ts
27326
+ var DEFAULT_MAX_SIZE = 1e3;
27327
+ var DEFAULT_TTL_MS = 24 * 60 * 60 * 1e3;
27328
+ var MemoryCache = class {
27329
+ store = /* @__PURE__ */ new Map();
27330
+ maxSize;
27331
+ ttlMs;
27332
+ hitCount = 0;
27333
+ missCount = 0;
27334
+ constructor(options) {
27335
+ this.maxSize = options?.maxSize ?? DEFAULT_MAX_SIZE;
27336
+ this.ttlMs = options?.ttlMs ?? DEFAULT_TTL_MS;
27337
+ }
27338
+ get(key) {
27339
+ const entry = this.store.get(key);
27340
+ if (!entry) {
27341
+ this.missCount++;
27342
+ return void 0;
27343
+ }
27344
+ if (Date.now() > entry.expiresAt) {
27345
+ this.store.delete(key);
27346
+ this.missCount++;
27347
+ return void 0;
27348
+ }
27349
+ entry.lastAccessed = Date.now();
27350
+ this.hitCount++;
27351
+ return entry.value;
27352
+ }
27353
+ set(key, value) {
27354
+ if (this.store.size >= this.maxSize && !this.store.has(key)) {
27355
+ this.evictLRU();
27356
+ }
27357
+ const now = Date.now();
27358
+ this.store.set(key, {
27359
+ value,
27360
+ expiresAt: now + this.ttlMs,
27361
+ lastAccessed: now
27362
+ });
27363
+ }
27364
+ delete(key) {
27365
+ return this.store.delete(key);
27366
+ }
27367
+ has(key) {
27368
+ const entry = this.store.get(key);
27369
+ if (!entry) return false;
27370
+ if (Date.now() > entry.expiresAt) {
27371
+ this.store.delete(key);
27372
+ return false;
27373
+ }
27374
+ return true;
27375
+ }
27376
+ clear() {
27377
+ this.store.clear();
27378
+ this.hitCount = 0;
27379
+ this.missCount = 0;
27380
+ }
27381
+ stats() {
27382
+ const total = this.hitCount + this.missCount;
27383
+ return {
27384
+ hits: this.hitCount,
27385
+ misses: this.missCount,
27386
+ size: this.store.size,
27387
+ maxSize: this.maxSize,
27388
+ hitRate: total > 0 ? this.hitCount / total : 0
27389
+ };
27390
+ }
27391
+ evictLRU() {
27392
+ let oldestKey = null;
27393
+ let oldestTime = Infinity;
27394
+ for (const [key, entry] of this.store) {
27395
+ if (entry.lastAccessed < oldestTime) {
27396
+ oldestTime = entry.lastAccessed;
27397
+ oldestKey = key;
27398
+ }
27399
+ }
27400
+ if (oldestKey) {
27401
+ this.store.delete(oldestKey);
27402
+ }
27403
+ }
27404
+ };
27405
+
27406
+ // src/ranking/relevance.ts
27407
+ var WEIGHTS = {
27408
+ contentAvailability: 40,
27409
+ queryMatch: 30,
27410
+ popularity: 15,
27411
+ references: 15
27412
+ };
27413
+ var RelevanceRanker = class {
27414
+ rank(skills, query) {
27415
+ const results = skills.map((skill) => {
27416
+ const breakdown = this.score(skill, query);
27417
+ const score = breakdown.contentAvailability + breakdown.queryMatch + breakdown.popularity + breakdown.referenceScore;
27418
+ return { skill, score, breakdown };
27419
+ });
27420
+ results.sort((a, b) => b.score - a.score);
27421
+ return results;
27422
+ }
27423
+ score(skill, query) {
27424
+ return {
27425
+ contentAvailability: this.scoreContent(skill),
27426
+ queryMatch: query ? this.scoreQuery(skill, query) : 0,
27427
+ popularity: this.scorePopularity(skill),
27428
+ referenceScore: this.scoreReferences(skill)
27429
+ };
27430
+ }
27431
+ scoreContent(skill) {
27432
+ let score = 0;
27433
+ if (skill.description && skill.description.length > 0) score += 20;
27434
+ if (skill.content && skill.content.length > 0) score += 20;
27435
+ return score;
27436
+ }
27437
+ scoreQuery(skill, query) {
27438
+ const q = query.toLowerCase();
27439
+ const name = skill.name.toLowerCase();
27440
+ if (name === q) return WEIGHTS.queryMatch;
27441
+ if (name.includes(q) || q.includes(name)) {
27442
+ return WEIGHTS.queryMatch * 0.7;
27443
+ }
27444
+ const desc = (skill.description || "").toLowerCase();
27445
+ const content = (skill.content || "").toLowerCase();
27446
+ const searchable = `${name} ${desc} ${content}`;
27447
+ const words = q.split(/\s+/).filter(Boolean);
27448
+ const matched = words.filter((w) => searchable.includes(w)).length;
27449
+ if (words.length === 0) return 0;
27450
+ return Math.round(WEIGHTS.queryMatch * (matched / words.length) * 0.6);
27451
+ }
27452
+ scorePopularity(skill) {
27453
+ const count = (skill.stars ?? 0) + (skill.installs ?? 0);
27454
+ if (count <= 0) return 0;
27455
+ return Math.min(WEIGHTS.popularity, Math.round(Math.log10(count + 1) * 5));
27456
+ }
27457
+ scoreReferences(skill) {
27458
+ if (!skill.references || skill.references.length === 0) return 0;
27459
+ return Math.min(WEIGHTS.references, skill.references.length * 5);
27460
+ }
27461
+ };
27462
+
27463
+ // src/parser/references.ts
27464
+ import { readdirSync as readdirSync12, statSync as statSync9, existsSync as existsSync50 } from "fs";
27465
+ import { join as join50 } from "path";
27466
+ var REFERENCE_DIRS = ["references", "resources", "docs", "examples", "assets", "scripts"];
27467
+ var DIR_TYPE_MAP = {
27468
+ references: "resource",
27469
+ resources: "resource",
27470
+ docs: "doc",
27471
+ examples: "example",
27472
+ assets: "asset",
27473
+ scripts: "resource"
27474
+ };
27475
+ function discoverReferences(skillDir) {
27476
+ const refs = [];
27477
+ for (const dir of REFERENCE_DIRS) {
27478
+ const fullPath = join50(skillDir, dir);
27479
+ if (!existsSync50(fullPath)) continue;
27480
+ try {
27481
+ const stat = statSync9(fullPath);
27482
+ if (!stat.isDirectory()) continue;
27483
+ } catch {
27484
+ continue;
27485
+ }
27486
+ const type = DIR_TYPE_MAP[dir] || "resource";
27487
+ try {
27488
+ const entries = readdirSync12(fullPath);
27489
+ for (const entry of entries) {
27490
+ const entryPath = join50(fullPath, entry);
27491
+ try {
27492
+ const entryStat = statSync9(entryPath);
27493
+ if (entryStat.isFile()) {
27494
+ refs.push({
27495
+ path: join50(dir, entry),
27496
+ type,
27497
+ name: entry
27498
+ });
27499
+ }
27500
+ } catch {
27501
+ continue;
27502
+ }
27503
+ }
27504
+ } catch {
27505
+ continue;
27506
+ }
27507
+ }
27508
+ return refs;
27509
+ }
27510
+ function stripFrontmatter(raw) {
27511
+ const match = raw.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/);
27512
+ if (!match) {
27513
+ const emptyMatch = raw.match(/^---\r?\n---\r?\n?([\s\S]*)$/);
27514
+ if (emptyMatch) {
27515
+ return { frontmatter: {}, body: emptyMatch[1] };
27516
+ }
27517
+ return { frontmatter: {}, body: raw };
27518
+ }
27519
+ const fmBlock = match[1];
27520
+ const body = match[2];
27521
+ const frontmatter = {};
27522
+ for (const line of fmBlock.split("\n")) {
27523
+ const colonIdx = line.indexOf(":");
27524
+ if (colonIdx === -1) continue;
27525
+ const key = line.slice(0, colonIdx).trim();
27526
+ const value = line.slice(colonIdx + 1).trim();
27527
+ if (key) {
27528
+ frontmatter[key] = value;
27529
+ }
27530
+ }
27531
+ return { frontmatter, body };
27532
+ }
27533
+ function parseSkillMd(raw, skillDir) {
27534
+ const { frontmatter, body } = stripFrontmatter(raw);
27535
+ const references = skillDir ? discoverReferences(skillDir) : [];
27536
+ return {
27537
+ frontmatter,
27538
+ body,
27539
+ references,
27540
+ raw
27541
+ };
27542
+ }
27543
+
27544
+ // src/runtime/injector.ts
27545
+ function parseSource2(source) {
27546
+ const parts = source.replace(/^https?:\/\/github\.com\//, "").split("/");
27547
+ if (parts.length < 2) {
27548
+ throw new Error(`Invalid source format: "${source}". Expected "owner/repo".`);
27549
+ }
27550
+ return { owner: parts[0], repo: parts[1] };
27551
+ }
27552
+ var SkillInjector = class {
27553
+ cache;
27554
+ constructor(cacheTtlMs) {
27555
+ this.cache = new MemoryCache({
27556
+ maxSize: 200,
27557
+ ttlMs: cacheTtlMs ?? 24 * 60 * 60 * 1e3
27558
+ });
27559
+ }
27560
+ async fetch(source, skillId) {
27561
+ const cacheKey = `${source}:${skillId}`;
27562
+ const cached = this.cache.get(cacheKey);
27563
+ if (cached) return cached;
27564
+ const { owner, repo } = parseSource2(source);
27565
+ const raw = await this.fetchRawSkillMd(owner, repo, skillId);
27566
+ const parsed = parseSkillMd(raw);
27567
+ const result = {
27568
+ source: { owner, repo },
27569
+ skillId,
27570
+ parsed,
27571
+ fetchedAt: Date.now()
27572
+ };
27573
+ this.cache.set(cacheKey, result);
27574
+ return result;
27575
+ }
27576
+ async inject(source, skillId) {
27577
+ const fetched = await this.fetch(source, skillId);
27578
+ return fetched.parsed.body;
27579
+ }
27580
+ async fetchRawSkillMd(owner, repo, skillId) {
27581
+ const paths = [
27582
+ `${skillId}/SKILL.md`,
27583
+ `skills/${skillId}/SKILL.md`,
27584
+ `SKILL.md`
27585
+ ];
27586
+ const headers = {
27587
+ Accept: "application/vnd.github.v3.raw",
27588
+ "User-Agent": "skillkit-runtime"
27589
+ };
27590
+ const token = process.env.GITHUB_TOKEN || process.env.GH_TOKEN;
27591
+ if (token) {
27592
+ headers.Authorization = `Bearer ${token}`;
27593
+ }
27594
+ for (const path4 of paths) {
27595
+ const url = `https://api.github.com/repos/${owner}/${repo}/contents/${path4}`;
27596
+ try {
27597
+ const response = await fetch(url, { headers });
27598
+ if (response.ok) {
27599
+ return await response.text();
27600
+ }
27601
+ } catch {
27602
+ continue;
27603
+ }
27604
+ }
27605
+ throw new Error(`SKILL.md not found in ${owner}/${repo} for skill "${skillId}"`);
27606
+ }
27607
+ clearCache() {
27608
+ this.cache.clear();
27609
+ }
27610
+ cacheStats() {
27611
+ return this.cache.stats();
27612
+ }
27613
+ };
25768
27614
  export {
25769
27615
  AGENT_CLI_CONFIGS,
25770
27616
  AGENT_CONFIG,
@@ -25793,8 +27639,10 @@ export {
25793
27639
  CONTEXT_DIR,
25794
27640
  CONTEXT_FILE,
25795
27641
  CUSTOM_AGENT_FORMAT_MAP,
27642
+ ClaudeMdUpdater,
25796
27643
  CommandGenerator,
25797
27644
  CommandRegistry,
27645
+ CommunityRegistry,
25798
27646
  ConnectorCategorySchema,
25799
27647
  ConnectorConfigSchema,
25800
27648
  ConnectorMappingSchema,
@@ -25811,6 +27659,7 @@ export {
25811
27659
  DEFAULT_HYBRID_CONFIG,
25812
27660
  DEFAULT_LEARNING_CONFIG,
25813
27661
  DEFAULT_MEMORY_CONFIG,
27662
+ DEFAULT_MEMORY_HOOK_CONFIG,
25814
27663
  DEFAULT_PROFILE_CONFIG,
25815
27664
  DEFAULT_REASONING_CONFIG,
25816
27665
  DEFAULT_SCORING_WEIGHTS,
@@ -25841,8 +27690,10 @@ export {
25841
27690
  MARKETPLACE_CACHE_FILE,
25842
27691
  MODEL_REGISTRY,
25843
27692
  MarketplaceAggregator,
27693
+ MemoryCache,
25844
27694
  MemoryCompressor,
25845
27695
  MemoryEnabledEngine,
27696
+ MemoryHookManager,
25846
27697
  MemoryIndexStore,
25847
27698
  MemoryInjector,
25848
27699
  MemoryObserver,
@@ -25859,8 +27710,10 @@ export {
25859
27710
  PlanValidator,
25860
27711
  PluginLoader,
25861
27712
  PluginManager,
27713
+ PostToolUseHook,
25862
27714
  PrimerAnalyzer,
25863
27715
  PrimerGenerator,
27716
+ ProgressiveDisclosureManager,
25864
27717
  ProjectDetector,
25865
27718
  QueryExpander,
25866
27719
  RateLimitError,
@@ -25868,18 +27721,22 @@ export {
25868
27721
  ReasoningProviderSchema,
25869
27722
  ReasoningRecommendationEngine,
25870
27723
  RecommendationEngine,
27724
+ RelevanceRanker,
25871
27725
  RuleBasedCompressor,
25872
27726
  SEARCH_PLANNING_PROMPT,
25873
27727
  SESSION_FILE,
25874
27728
  SKILL_DISCOVERY_PATHS,
25875
27729
  SKILL_MATCH_PROMPT,
25876
27730
  STANDARD_PLACEHOLDERS,
27731
+ SessionEndHook,
25877
27732
  SessionManager,
27733
+ SessionStartHook,
25878
27734
  Skill,
25879
27735
  SkillBundle,
25880
27736
  SkillChunkSchema,
25881
27737
  SkillExecutionEngine,
25882
27738
  SkillFrontmatter,
27739
+ SkillInjector,
25883
27740
  SkillLocation,
25884
27741
  SkillMdTranslator,
25885
27742
  SkillMetadata,
@@ -25932,6 +27789,7 @@ export {
25932
27789
  computeRRFScore,
25933
27790
  copilotTranslator,
25934
27791
  createAPIBasedCompressor,
27792
+ createClaudeMdUpdater,
25935
27793
  createCommandGenerator,
25936
27794
  createCommandRegistry,
25937
27795
  createConnectorConfig,
@@ -25946,6 +27804,7 @@ export {
25946
27804
  createMarketplaceAggregator,
25947
27805
  createMemoryCompressor,
25948
27806
  createMemoryEnabledEngine,
27807
+ createMemoryHookManager,
25949
27808
  createMemoryInjector,
25950
27809
  createMemoryObserver,
25951
27810
  createMessageBus,
@@ -25957,13 +27816,17 @@ export {
25957
27816
  createPlanParser,
25958
27817
  createPlanValidator,
25959
27818
  createPluginManager,
27819
+ createPostToolUseHook,
27820
+ createProgressiveDisclosureManager,
25960
27821
  createQueryExpander,
25961
27822
  createReasoningEngine,
25962
27823
  createReasoningRecommendationEngine,
25963
27824
  createRecommendationEngine,
25964
27825
  createRuleBasedCompressor,
27826
+ createSessionEndHook,
25965
27827
  createSessionFile,
25966
27828
  createSessionManager,
27829
+ createSessionStartHook,
25967
27830
  createSimulatedSkillExecutor,
25968
27831
  createSkillBundle,
25969
27832
  createSkillExecutor,
@@ -25989,6 +27852,7 @@ export {
25989
27852
  discoverAgentsFromPath,
25990
27853
  discoverAgentsRecursive,
25991
27854
  discoverGlobalAgents,
27855
+ discoverReferences,
25992
27856
  discoverSkills,
25993
27857
  dryRunExecutor,
25994
27858
  enableGuideline,
@@ -25996,6 +27860,9 @@ export {
25996
27860
  evaluateSkillContent,
25997
27861
  evaluateSkillDirectory,
25998
27862
  evaluateSkillFile,
27863
+ executePostToolUseHook,
27864
+ executeSessionEndHook,
27865
+ executeSessionStartHook,
25999
27866
  executeWithAgent,
26000
27867
  expandQuerySimple,
26001
27868
  exportBundle,
@@ -26155,6 +28022,7 @@ export {
26155
28022
  parseSkill,
26156
28023
  parseSkillContent,
26157
28024
  parseSkillContentToCanonical,
28025
+ parseSkillMd,
26158
28026
  parseSkillToCanonical,
26159
28027
  parseSource,
26160
28028
  parseWorkflow,
@@ -26191,9 +28059,11 @@ export {
26191
28059
  shellExecutor,
26192
28060
  skillMdTranslator,
26193
28061
  skillToSubagent,
28062
+ stripFrontmatter,
26194
28063
  suggestMappingsFromMcp,
26195
28064
  supportsAutoDiscovery,
26196
28065
  supportsSlashCommands,
28066
+ syncGlobalClaudeMd,
26197
28067
  syncToAgent,
26198
28068
  syncToAllAgents,
26199
28069
  toCanonicalAgent,
@@ -26208,6 +28078,7 @@ export {
26208
28078
  translatorRegistry,
26209
28079
  treeToMarkdown,
26210
28080
  treeToText,
28081
+ updateClaudeMd,
26211
28082
  updateSessionFile,
26212
28083
  validateAgent,
26213
28084
  validateBuiltinPacks,