@skillkit/core 1.17.0 → 1.19.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
@@ -7955,6 +7955,837 @@ function getMostRecentSession() {
7955
7955
  return loadSessionFile(summaries[0].date);
7956
7956
  }
7957
7957
 
7958
+ // src/session/activity-log.ts
7959
+ import { existsSync as existsSync18, mkdirSync as mkdirSync9, readFileSync as readFileSync10, writeFileSync as writeFileSync9 } from "fs";
7960
+ import { join as join17 } from "path";
7961
+ import { parse as parse2, stringify as stringify2 } from "yaml";
7962
+ var ACTIVITY_FILE = "activity.yaml";
7963
+ var ActivityLog = class {
7964
+ filePath;
7965
+ projectPath;
7966
+ data = null;
7967
+ constructor(projectPath) {
7968
+ this.projectPath = projectPath;
7969
+ this.filePath = join17(projectPath, ".skillkit", ACTIVITY_FILE);
7970
+ }
7971
+ createEmpty() {
7972
+ return { version: 1, activities: [] };
7973
+ }
7974
+ load() {
7975
+ if (this.data) return this.data;
7976
+ if (!existsSync18(this.filePath)) {
7977
+ this.data = this.createEmpty();
7978
+ return this.data;
7979
+ }
7980
+ try {
7981
+ const content = readFileSync10(this.filePath, "utf-8");
7982
+ const parsed = parse2(content);
7983
+ if (parsed && Array.isArray(parsed.activities)) {
7984
+ this.data = parsed;
7985
+ } else {
7986
+ this.data = this.createEmpty();
7987
+ }
7988
+ } catch {
7989
+ this.data = this.createEmpty();
7990
+ }
7991
+ return this.data;
7992
+ }
7993
+ save() {
7994
+ const dir = join17(this.projectPath, ".skillkit");
7995
+ if (!existsSync18(dir)) {
7996
+ mkdirSync9(dir, { recursive: true });
7997
+ }
7998
+ writeFileSync9(this.filePath, stringify2(this.data));
7999
+ }
8000
+ record(entry) {
8001
+ const data = this.load();
8002
+ data.activities.unshift({
8003
+ commitSha: entry.commitSha,
8004
+ committedAt: (/* @__PURE__ */ new Date()).toISOString(),
8005
+ activeSkills: entry.activeSkills,
8006
+ filesChanged: entry.filesChanged,
8007
+ message: entry.message
8008
+ });
8009
+ if (data.activities.length > 500) {
8010
+ data.activities = data.activities.slice(0, 500);
8011
+ }
8012
+ this.save();
8013
+ }
8014
+ getByCommit(sha) {
8015
+ if (sha.length < 4) return void 0;
8016
+ const data = this.load();
8017
+ return data.activities.find(
8018
+ (a) => a.commitSha === sha || a.commitSha.startsWith(sha)
8019
+ );
8020
+ }
8021
+ getBySkill(skillName) {
8022
+ const data = this.load();
8023
+ return data.activities.filter((a) => a.activeSkills.includes(skillName));
8024
+ }
8025
+ getRecent(limit = 20) {
8026
+ const data = this.load();
8027
+ return data.activities.slice(0, limit);
8028
+ }
8029
+ getMostUsedSkills() {
8030
+ const data = this.load();
8031
+ const counts = /* @__PURE__ */ new Map();
8032
+ for (const activity of data.activities) {
8033
+ for (const skill of activity.activeSkills) {
8034
+ counts.set(skill, (counts.get(skill) ?? 0) + 1);
8035
+ }
8036
+ }
8037
+ return Array.from(counts.entries()).map(([skill, count]) => ({ skill, count })).sort((a, b) => b.count - a.count);
8038
+ }
8039
+ };
8040
+
8041
+ // src/session/snapshot-manager.ts
8042
+ import {
8043
+ existsSync as existsSync19,
8044
+ mkdirSync as mkdirSync10,
8045
+ readFileSync as readFileSync11,
8046
+ writeFileSync as writeFileSync10,
8047
+ readdirSync as readdirSync5,
8048
+ unlinkSync as unlinkSync2
8049
+ } from "fs";
8050
+ import { join as join18 } from "path";
8051
+ import { parse as parse3, stringify as stringify3 } from "yaml";
8052
+ var SAFE_NAME_RE = /^[a-zA-Z0-9_-]+$/;
8053
+ var SnapshotManager = class {
8054
+ snapshotsDir;
8055
+ constructor(projectPath) {
8056
+ this.snapshotsDir = join18(projectPath, ".skillkit", "snapshots");
8057
+ }
8058
+ ensureDir() {
8059
+ if (!existsSync19(this.snapshotsDir)) {
8060
+ mkdirSync10(this.snapshotsDir, { recursive: true });
8061
+ }
8062
+ }
8063
+ sanitizeName(name) {
8064
+ if (!name || !SAFE_NAME_RE.test(name)) {
8065
+ throw new Error(`Invalid snapshot name: "${name}". Use only letters, numbers, hyphens, and underscores.`);
8066
+ }
8067
+ return name;
8068
+ }
8069
+ getPath(name) {
8070
+ const safe = this.sanitizeName(name);
8071
+ return join18(this.snapshotsDir, `${safe}.yaml`);
8072
+ }
8073
+ save(name, sessionState, observations, description) {
8074
+ this.ensureDir();
8075
+ const snapshot = {
8076
+ version: 1,
8077
+ name,
8078
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
8079
+ description,
8080
+ sessionState,
8081
+ observations
8082
+ };
8083
+ writeFileSync10(this.getPath(name), stringify3(snapshot));
8084
+ }
8085
+ restore(name) {
8086
+ const filepath = this.getPath(name);
8087
+ if (!existsSync19(filepath)) {
8088
+ throw new Error(`Snapshot "${name}" not found`);
8089
+ }
8090
+ let snapshot;
8091
+ try {
8092
+ const content = readFileSync11(filepath, "utf-8");
8093
+ snapshot = parse3(content);
8094
+ } catch (err) {
8095
+ throw new Error(`Failed to read snapshot "${name}": ${err instanceof Error ? err.message : "unknown error"}`);
8096
+ }
8097
+ if (!snapshot.sessionState || !snapshot.observations) {
8098
+ throw new Error(`Snapshot "${name}" is corrupted or invalid`);
8099
+ }
8100
+ return {
8101
+ sessionState: snapshot.sessionState,
8102
+ observations: snapshot.observations
8103
+ };
8104
+ }
8105
+ list() {
8106
+ if (!existsSync19(this.snapshotsDir)) {
8107
+ return [];
8108
+ }
8109
+ const files = readdirSync5(this.snapshotsDir).filter(
8110
+ (f) => f.endsWith(".yaml")
8111
+ );
8112
+ return files.map((f) => {
8113
+ try {
8114
+ const content = readFileSync11(join18(this.snapshotsDir, f), "utf-8");
8115
+ const snapshot = parse3(content);
8116
+ if (!snapshot.createdAt) {
8117
+ return null;
8118
+ }
8119
+ const skillCount = snapshot.sessionState?.history?.length ?? 0;
8120
+ return {
8121
+ name: snapshot.name ?? f.replace(/\.yaml$/, ""),
8122
+ createdAt: snapshot.createdAt,
8123
+ description: snapshot.description,
8124
+ skillCount
8125
+ };
8126
+ } catch {
8127
+ return null;
8128
+ }
8129
+ }).filter((s) => s !== null).sort((a, b) => {
8130
+ const timeA = new Date(a.createdAt).getTime() || 0;
8131
+ const timeB = new Date(b.createdAt).getTime() || 0;
8132
+ return timeB - timeA;
8133
+ });
8134
+ }
8135
+ get(name) {
8136
+ const filepath = this.getPath(name);
8137
+ if (!existsSync19(filepath)) {
8138
+ return void 0;
8139
+ }
8140
+ try {
8141
+ const content = readFileSync11(filepath, "utf-8");
8142
+ return parse3(content);
8143
+ } catch {
8144
+ return void 0;
8145
+ }
8146
+ }
8147
+ delete(name) {
8148
+ const filepath = this.getPath(name);
8149
+ if (!existsSync19(filepath)) {
8150
+ return false;
8151
+ }
8152
+ unlinkSync2(filepath);
8153
+ return true;
8154
+ }
8155
+ exists(name) {
8156
+ return existsSync19(this.getPath(name));
8157
+ }
8158
+ };
8159
+
8160
+ // src/memory/observation-store.ts
8161
+ import { existsSync as existsSync20, mkdirSync as mkdirSync11, readFileSync as readFileSync12, writeFileSync as writeFileSync11 } from "fs";
8162
+ import { dirname as dirname4, join as join19 } from "path";
8163
+ import { parse as parseYaml6, stringify as stringifyYaml5 } from "yaml";
8164
+ import { randomUUID as randomUUID6 } from "crypto";
8165
+ var ObservationStore = class {
8166
+ filePath;
8167
+ projectPath;
8168
+ data = null;
8169
+ sessionId;
8170
+ compressionThreshold;
8171
+ autoCompress;
8172
+ onThresholdReached;
8173
+ compressionInProgress = false;
8174
+ constructor(projectPath, sessionId, options = {}) {
8175
+ this.projectPath = projectPath;
8176
+ this.filePath = join19(projectPath, ".skillkit", "memory", "observations.yaml");
8177
+ this.sessionId = sessionId || randomUUID6();
8178
+ this.compressionThreshold = options.compressionThreshold ?? 50;
8179
+ this.autoCompress = options.autoCompress ?? true;
8180
+ this.onThresholdReached = options.onThresholdReached;
8181
+ }
8182
+ ensureDir() {
8183
+ const dir = dirname4(this.filePath);
8184
+ if (!existsSync20(dir)) {
8185
+ mkdirSync11(dir, { recursive: true });
8186
+ }
8187
+ }
8188
+ load() {
8189
+ if (this.data) return this.data;
8190
+ if (existsSync20(this.filePath)) {
8191
+ try {
8192
+ const content = readFileSync12(this.filePath, "utf-8");
8193
+ this.data = parseYaml6(content);
8194
+ if (this.data.sessionId !== this.sessionId) {
8195
+ this.data.sessionId = this.sessionId;
8196
+ this.data.observations = [];
8197
+ }
8198
+ } catch {
8199
+ this.data = this.createEmpty();
8200
+ }
8201
+ } else {
8202
+ this.data = this.createEmpty();
8203
+ }
8204
+ return this.data;
8205
+ }
8206
+ createEmpty() {
8207
+ return {
8208
+ version: 1,
8209
+ sessionId: this.sessionId,
8210
+ observations: []
8211
+ };
8212
+ }
8213
+ save() {
8214
+ this.ensureDir();
8215
+ const content = stringifyYaml5(this.data, { lineWidth: 0 });
8216
+ writeFileSync11(this.filePath, content, "utf-8");
8217
+ }
8218
+ add(type, content, agent, relevance = 50) {
8219
+ const data = this.load();
8220
+ const observation = {
8221
+ id: randomUUID6(),
8222
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
8223
+ sessionId: this.sessionId,
8224
+ agent,
8225
+ type,
8226
+ content,
8227
+ relevance
8228
+ };
8229
+ data.observations.push(observation);
8230
+ this.save();
8231
+ void this.checkAutoCompression().catch(() => {
8232
+ });
8233
+ return observation;
8234
+ }
8235
+ /**
8236
+ * Check if auto-compression should trigger
8237
+ */
8238
+ async checkAutoCompression() {
8239
+ if (!this.autoCompress || this.compressionInProgress) return;
8240
+ if (!this.onThresholdReached) return;
8241
+ const count = this.count();
8242
+ if (count >= this.compressionThreshold) {
8243
+ this.compressionInProgress = true;
8244
+ try {
8245
+ const observations = this.getAll();
8246
+ await this.onThresholdReached(observations);
8247
+ } finally {
8248
+ this.compressionInProgress = false;
8249
+ }
8250
+ }
8251
+ }
8252
+ /**
8253
+ * Set auto-compression callback
8254
+ */
8255
+ setAutoCompressCallback(callback) {
8256
+ this.onThresholdReached = callback;
8257
+ }
8258
+ /**
8259
+ * Enable/disable auto-compression
8260
+ */
8261
+ setAutoCompress(enabled) {
8262
+ this.autoCompress = enabled;
8263
+ }
8264
+ /**
8265
+ * Set compression threshold
8266
+ */
8267
+ setCompressionThreshold(threshold) {
8268
+ if (threshold < 1 || !Number.isInteger(threshold)) {
8269
+ throw new Error("Compression threshold must be a positive integer");
8270
+ }
8271
+ this.compressionThreshold = threshold;
8272
+ }
8273
+ /**
8274
+ * Get compression threshold
8275
+ */
8276
+ getCompressionThreshold() {
8277
+ return this.compressionThreshold;
8278
+ }
8279
+ /**
8280
+ * Check if threshold is reached
8281
+ */
8282
+ isThresholdReached() {
8283
+ return this.count() >= this.compressionThreshold;
8284
+ }
8285
+ /**
8286
+ * Get project path
8287
+ */
8288
+ getProjectPath() {
8289
+ return this.projectPath;
8290
+ }
8291
+ getAll() {
8292
+ return this.load().observations;
8293
+ }
8294
+ static readAll(projectPath) {
8295
+ const filePath = join19(projectPath, ".skillkit", "memory", "observations.yaml");
8296
+ if (!existsSync20(filePath)) return [];
8297
+ try {
8298
+ const content = readFileSync12(filePath, "utf-8");
8299
+ const data = parseYaml6(content);
8300
+ return data?.observations ?? [];
8301
+ } catch {
8302
+ return [];
8303
+ }
8304
+ }
8305
+ getByType(type) {
8306
+ return this.load().observations.filter((o) => o.type === type);
8307
+ }
8308
+ getByRelevance(minRelevance) {
8309
+ return this.load().observations.filter((o) => o.relevance >= minRelevance);
8310
+ }
8311
+ getRecent(count) {
8312
+ const observations = this.load().observations;
8313
+ return observations.slice(-count);
8314
+ }
8315
+ getUncompressed(compressedIds) {
8316
+ const compressedSet = new Set(compressedIds);
8317
+ return this.load().observations.filter((o) => !compressedSet.has(o.id));
8318
+ }
8319
+ count() {
8320
+ return this.load().observations.length;
8321
+ }
8322
+ clear() {
8323
+ this.data = this.createEmpty();
8324
+ this.save();
8325
+ }
8326
+ getById(id) {
8327
+ return this.load().observations.find((o) => o.id === id);
8328
+ }
8329
+ getByIds(ids) {
8330
+ const idSet = new Set(ids);
8331
+ return this.load().observations.filter((o) => idSet.has(o.id));
8332
+ }
8333
+ getSessionId() {
8334
+ return this.sessionId;
8335
+ }
8336
+ setSessionId(sessionId) {
8337
+ this.sessionId = sessionId;
8338
+ if (this.data) {
8339
+ this.data.sessionId = sessionId;
8340
+ }
8341
+ }
8342
+ exists() {
8343
+ return existsSync20(this.filePath);
8344
+ }
8345
+ delete(id) {
8346
+ const data = this.load();
8347
+ const index = data.observations.findIndex((o) => o.id === id);
8348
+ if (index === -1) return false;
8349
+ data.observations.splice(index, 1);
8350
+ this.save();
8351
+ return true;
8352
+ }
8353
+ deleteMany(ids) {
8354
+ const idSet = new Set(ids);
8355
+ const data = this.load();
8356
+ const initialLength = data.observations.length;
8357
+ data.observations = data.observations.filter((o) => !idSet.has(o.id));
8358
+ if (data.observations.length !== initialLength) {
8359
+ this.save();
8360
+ }
8361
+ return initialLength - data.observations.length;
8362
+ }
8363
+ };
8364
+
8365
+ // src/learning/git-analyzer.ts
8366
+ import { execSync as execSync5 } from "child_process";
8367
+ import { existsSync as existsSync21 } from "fs";
8368
+ import { join as join20 } from "path";
8369
+ function runGitCommand(command, cwd) {
8370
+ try {
8371
+ return execSync5(command, { cwd, encoding: "utf-8", maxBuffer: 10 * 1024 * 1024 });
8372
+ } catch {
8373
+ return "";
8374
+ }
8375
+ }
8376
+ function isGitRepository(path4) {
8377
+ return existsSync21(join20(path4, ".git"));
8378
+ }
8379
+ function getGitCommits(repoPath, options = {}) {
8380
+ if (!isGitRepository(repoPath)) {
8381
+ return [];
8382
+ }
8383
+ const limit = options.commits || 100;
8384
+ const args = [
8385
+ "log",
8386
+ `--max-count=${limit}`,
8387
+ "--format=%H|||%h|||%an|||%aI|||%s|||%b|||END_COMMIT",
8388
+ "--name-status"
8389
+ ];
8390
+ if (options.since) {
8391
+ args.push(`--since="${options.since}"`);
8392
+ }
8393
+ if (options.until) {
8394
+ args.push(`--until="${options.until}"`);
8395
+ }
8396
+ if (options.branch) {
8397
+ args.push(options.branch);
8398
+ }
8399
+ if (options.author) {
8400
+ args.push(`--author="${options.author}"`);
8401
+ }
8402
+ const output = runGitCommand(`git ${args.join(" ")}`, repoPath);
8403
+ if (!output) return [];
8404
+ const commits = [];
8405
+ const commitBlocks = output.split("END_COMMIT").filter((b) => b.trim());
8406
+ for (const block of commitBlocks) {
8407
+ const lines = block.trim().split("\n");
8408
+ if (lines.length === 0) continue;
8409
+ const headerLine = lines[0];
8410
+ const parts = headerLine.split("|||");
8411
+ if (parts.length < 5) continue;
8412
+ const [hash, shortHash, author, date, message, body] = parts;
8413
+ const files = [];
8414
+ for (let i = 1; i < lines.length; i++) {
8415
+ const line = lines[i].trim();
8416
+ if (!line) continue;
8417
+ const match = line.match(/^([AMDRT])\d*\t(.+?)(?:\t(.+))?$/);
8418
+ if (match) {
8419
+ const [, status, path4, oldPath] = match;
8420
+ files.push({
8421
+ path: path4,
8422
+ status: parseFileStatus(status),
8423
+ additions: 0,
8424
+ deletions: 0,
8425
+ oldPath: oldPath || void 0
8426
+ });
8427
+ }
8428
+ }
8429
+ commits.push({
8430
+ hash,
8431
+ shortHash,
8432
+ author,
8433
+ date,
8434
+ message,
8435
+ body: body || void 0,
8436
+ files
8437
+ });
8438
+ }
8439
+ return commits;
8440
+ }
8441
+ function parseFileStatus(status) {
8442
+ switch (status) {
8443
+ case "A":
8444
+ return "added";
8445
+ case "D":
8446
+ return "deleted";
8447
+ case "R":
8448
+ return "renamed";
8449
+ default:
8450
+ return "modified";
8451
+ }
8452
+ }
8453
+ function categorizeCommit(message, body) {
8454
+ const text = `${message} ${body || ""}`.toLowerCase();
8455
+ if (text.includes("fix") || text.includes("bug") || text.includes("error") || text.includes("issue")) {
8456
+ return "error_fix";
8457
+ }
8458
+ if (text.includes("refactor") || text.includes("clean") || text.includes("simplify")) {
8459
+ return "refactor";
8460
+ }
8461
+ if (text.includes("workaround") || text.includes("hack") || text.includes("temporary")) {
8462
+ return "workaround";
8463
+ }
8464
+ if (text.includes("debug") || text.includes("log") || text.includes("trace")) {
8465
+ return "debugging";
8466
+ }
8467
+ return null;
8468
+ }
8469
+ function shouldSkipCommit(commit, ignorePatterns) {
8470
+ const message = commit.message.toLowerCase();
8471
+ for (const pattern of ignorePatterns) {
8472
+ if (message.includes(pattern.toLowerCase())) {
8473
+ return true;
8474
+ }
8475
+ }
8476
+ if (message.startsWith("merge ") || message.startsWith("wip")) {
8477
+ return true;
8478
+ }
8479
+ if (commit.files.length === 0) {
8480
+ return true;
8481
+ }
8482
+ return false;
8483
+ }
8484
+ function extractPatternFromCommit(commit) {
8485
+ const category = categorizeCommit(commit.message, commit.body);
8486
+ if (!category) return null;
8487
+ const id = `git-${commit.shortHash}`;
8488
+ const title = formatTitle(commit.message);
8489
+ const problem = extractProblem(commit);
8490
+ const solution = extractSolution(commit);
8491
+ const context = extractContext(commit);
8492
+ if (!problem || !solution) return null;
8493
+ return {
8494
+ id,
8495
+ category,
8496
+ title,
8497
+ problem,
8498
+ solution,
8499
+ context,
8500
+ extractedAt: (/* @__PURE__ */ new Date()).toISOString(),
8501
+ source: "git",
8502
+ commitRange: { from: commit.hash, to: commit.hash },
8503
+ approved: false,
8504
+ confidence: calculateConfidence(commit, category)
8505
+ };
8506
+ }
8507
+ function formatTitle(message) {
8508
+ return message.charAt(0).toUpperCase() + message.slice(1);
8509
+ }
8510
+ function extractProblem(commit) {
8511
+ const message = commit.message.toLowerCase();
8512
+ if (message.includes("fix:") || message.includes("fix(")) {
8513
+ const match = commit.message.match(/fix[:(]\s*([^)]+)/i);
8514
+ if (match) {
8515
+ return `Issue: ${match[1]}`;
8516
+ }
8517
+ }
8518
+ if (commit.body) {
8519
+ const problemMatch = commit.body.match(/problem:?\s*(.+)/i);
8520
+ if (problemMatch) {
8521
+ return problemMatch[1].trim();
8522
+ }
8523
+ }
8524
+ return `${commit.message} (from commit ${commit.shortHash})`;
8525
+ }
8526
+ function extractSolution(commit) {
8527
+ if (commit.body) {
8528
+ const solutionMatch = commit.body.match(/solution:?\s*(.+)/i);
8529
+ if (solutionMatch) {
8530
+ return solutionMatch[1].trim();
8531
+ }
8532
+ }
8533
+ const files = commit.files.map((f) => f.path).join(", ");
8534
+ return `Modified: ${files}`;
8535
+ }
8536
+ function extractContext(commit) {
8537
+ const files = commit.files;
8538
+ const extensions = new Set(files.map((f) => f.path.split(".").pop() || ""));
8539
+ const directories = new Set(files.map((f) => f.path.split("/")[0]));
8540
+ const parts = [];
8541
+ if (extensions.size > 0) {
8542
+ parts.push(`Files: ${Array.from(extensions).filter((e) => e).join(", ")}`);
8543
+ }
8544
+ if (directories.size > 0 && directories.size <= 3) {
8545
+ parts.push(`Areas: ${Array.from(directories).join(", ")}`);
8546
+ }
8547
+ return parts.join(". ") || "General codebase";
8548
+ }
8549
+ function calculateConfidence(commit, category) {
8550
+ let confidence = 0.5;
8551
+ if (commit.body && commit.body.length > 50) {
8552
+ confidence += 0.1;
8553
+ }
8554
+ if (commit.message.match(/^(fix|feat|refactor|docs|test|chore)(\(.+\))?:/)) {
8555
+ confidence += 0.1;
8556
+ }
8557
+ if (commit.files.length > 0 && commit.files.length < 10) {
8558
+ confidence += 0.1;
8559
+ }
8560
+ if (category === "error_fix" || category === "workaround") {
8561
+ confidence += 0.05;
8562
+ }
8563
+ return Math.min(0.9, confidence);
8564
+ }
8565
+ function analyzeGitHistory(repoPath, options = {}) {
8566
+ const commits = getGitCommits(repoPath, options);
8567
+ const ignorePatterns = ["merge", "wip", "typo"];
8568
+ const patterns = [];
8569
+ const summary = {
8570
+ totalCommits: commits.length,
8571
+ totalFilesChanged: 0,
8572
+ errorFixes: 0,
8573
+ refactors: 0,
8574
+ features: 0,
8575
+ documentation: 0,
8576
+ tests: 0
8577
+ };
8578
+ const languages = /* @__PURE__ */ new Set();
8579
+ const frameworks = /* @__PURE__ */ new Set();
8580
+ for (const commit of commits) {
8581
+ if (shouldSkipCommit(commit, ignorePatterns)) {
8582
+ continue;
8583
+ }
8584
+ summary.totalFilesChanged += commit.files.length;
8585
+ for (const file of commit.files) {
8586
+ const ext = file.path.split(".").pop()?.toLowerCase();
8587
+ if (ext) {
8588
+ if (["ts", "tsx"].includes(ext)) languages.add("TypeScript");
8589
+ else if (["js", "jsx"].includes(ext)) languages.add("JavaScript");
8590
+ else if (ext === "py") languages.add("Python");
8591
+ else if (ext === "go") languages.add("Go");
8592
+ else if (ext === "rs") languages.add("Rust");
8593
+ else if (ext === "java") languages.add("Java");
8594
+ }
8595
+ if (file.path.includes("next")) frameworks.add("Next.js");
8596
+ if (file.path.includes("react")) frameworks.add("React");
8597
+ if (file.path.includes("vue")) frameworks.add("Vue");
8598
+ }
8599
+ const category = categorizeCommit(commit.message, commit.body);
8600
+ if (category === "error_fix") summary.errorFixes++;
8601
+ else if (category === "refactor") summary.refactors++;
8602
+ if (commit.message.toLowerCase().includes("feat")) summary.features++;
8603
+ if (commit.message.toLowerCase().includes("doc")) summary.documentation++;
8604
+ if (commit.message.toLowerCase().includes("test")) summary.tests++;
8605
+ const pattern = extractPatternFromCommit(commit);
8606
+ if (pattern) {
8607
+ patterns.push(pattern);
8608
+ }
8609
+ }
8610
+ const dates = commits.map((c) => c.date).sort();
8611
+ return {
8612
+ patterns,
8613
+ commitCount: commits.length,
8614
+ dateRange: {
8615
+ from: dates[0] || "",
8616
+ to: dates[dates.length - 1] || ""
8617
+ },
8618
+ languages: Array.from(languages),
8619
+ frameworks: Array.from(frameworks),
8620
+ summary
8621
+ };
8622
+ }
8623
+ function getRecentBugFixes(repoPath, limit = 20) {
8624
+ const result = analyzeGitHistory(repoPath, { commits: limit * 3 });
8625
+ return result.patterns.filter((p) => p.category === "error_fix").slice(0, limit);
8626
+ }
8627
+ function getRecentRefactors(repoPath, limit = 20) {
8628
+ const result = analyzeGitHistory(repoPath, { commits: limit * 3 });
8629
+ return result.patterns.filter((p) => p.category === "refactor").slice(0, limit);
8630
+ }
8631
+
8632
+ // src/session/session-explainer.ts
8633
+ function formatDuration(ms) {
8634
+ const seconds = Math.floor(ms / 1e3);
8635
+ const minutes = Math.floor(seconds / 60);
8636
+ const hours = Math.floor(minutes / 60);
8637
+ if (hours > 0) {
8638
+ const remainMinutes = minutes % 60;
8639
+ return `${hours}h ${remainMinutes}m`;
8640
+ }
8641
+ if (minutes > 0) {
8642
+ return `${minutes}m`;
8643
+ }
8644
+ return `${seconds}s`;
8645
+ }
8646
+ var SessionExplainer = class {
8647
+ projectPath;
8648
+ sessionManager;
8649
+ constructor(projectPath) {
8650
+ this.projectPath = projectPath;
8651
+ this.sessionManager = new SessionManager(projectPath);
8652
+ }
8653
+ explain(options) {
8654
+ const state = this.sessionManager.get();
8655
+ const includeGit = options?.includeGit !== false;
8656
+ const explanation = {
8657
+ date: (/* @__PURE__ */ new Date()).toISOString().split("T")[0],
8658
+ agent: "unknown",
8659
+ skillsUsed: [],
8660
+ tasks: [],
8661
+ filesModified: [],
8662
+ decisions: [],
8663
+ observationCounts: { errors: 0, solutions: 0, patterns: 0, total: 0 },
8664
+ gitCommits: 0
8665
+ };
8666
+ if (!state) {
8667
+ return explanation;
8668
+ }
8669
+ try {
8670
+ const configAgent = loadConfig().agent;
8671
+ if (configAgent && configAgent !== "universal") {
8672
+ explanation.agent = configAgent;
8673
+ } else if (state.currentExecution?.skillSource) {
8674
+ explanation.agent = state.currentExecution.skillSource;
8675
+ }
8676
+ } catch {
8677
+ if (state.currentExecution?.skillSource) {
8678
+ explanation.agent = state.currentExecution.skillSource;
8679
+ }
8680
+ }
8681
+ if (state.currentExecution) {
8682
+ const exec2 = state.currentExecution;
8683
+ const startTime = new Date(exec2.startedAt).getTime();
8684
+ explanation.duration = formatDuration(Date.now() - startTime);
8685
+ explanation.skillsUsed.push({
8686
+ name: exec2.skillName,
8687
+ status: exec2.status
8688
+ });
8689
+ for (const task of exec2.tasks) {
8690
+ const taskEntry = {
8691
+ name: task.name,
8692
+ status: task.status
8693
+ };
8694
+ if (task.startedAt && task.completedAt) {
8695
+ const dur = new Date(task.completedAt).getTime() - new Date(task.startedAt).getTime();
8696
+ taskEntry.duration = formatDuration(dur);
8697
+ }
8698
+ explanation.tasks.push(taskEntry);
8699
+ if (task.filesModified) {
8700
+ explanation.filesModified.push(...task.filesModified);
8701
+ }
8702
+ }
8703
+ }
8704
+ for (const hist of state.history ?? []) {
8705
+ const alreadyListed = explanation.skillsUsed.some(
8706
+ (s) => s.name === hist.skillName
8707
+ );
8708
+ if (!alreadyListed) {
8709
+ explanation.skillsUsed.push({
8710
+ name: hist.skillName,
8711
+ status: hist.status
8712
+ });
8713
+ }
8714
+ if (hist.filesModified) {
8715
+ explanation.filesModified.push(...hist.filesModified);
8716
+ }
8717
+ }
8718
+ explanation.filesModified = [...new Set(explanation.filesModified)];
8719
+ explanation.decisions = (state.decisions ?? []).map(({ key, value }) => ({ key, value }));
8720
+ try {
8721
+ const observations = ObservationStore.readAll(this.projectPath);
8722
+ const countByType = (type) => observations.filter((o) => o.type === type).length;
8723
+ explanation.observationCounts = {
8724
+ total: observations.length,
8725
+ errors: countByType("error"),
8726
+ solutions: countByType("solution"),
8727
+ patterns: countByType("pattern")
8728
+ };
8729
+ } catch {
8730
+ }
8731
+ if (includeGit) {
8732
+ try {
8733
+ const commits = getGitCommits(this.projectPath, { commits: 50 });
8734
+ const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
8735
+ explanation.gitCommits = commits.filter(
8736
+ (c) => c.date.startsWith(today)
8737
+ ).length;
8738
+ } catch {
8739
+ }
8740
+ }
8741
+ return explanation;
8742
+ }
8743
+ formatText(explanation) {
8744
+ const lines = [];
8745
+ lines.push(" Session Summary\n");
8746
+ if (explanation.duration) {
8747
+ lines.push(` Duration: ${explanation.duration}`);
8748
+ }
8749
+ lines.push(` Agent: ${explanation.agent}`);
8750
+ lines.push("");
8751
+ if (explanation.skillsUsed.length > 0) {
8752
+ lines.push(" Skills Used");
8753
+ for (const skill of explanation.skillsUsed) {
8754
+ const icon = skill.status === "completed" ? "\u2713" : "\u25CB";
8755
+ lines.push(` ${icon} ${skill.name} (${skill.status})`);
8756
+ }
8757
+ lines.push("");
8758
+ }
8759
+ if (explanation.tasks.length > 0) {
8760
+ lines.push(` Tasks (${explanation.tasks.length} total)`);
8761
+ for (const task of explanation.tasks) {
8762
+ const icon = task.status === "completed" ? "\u2713" : "\u25CB";
8763
+ const dur = task.duration ? ` (${task.duration})` : "";
8764
+ lines.push(` ${icon} ${task.name}${dur}`);
8765
+ }
8766
+ lines.push("");
8767
+ }
8768
+ lines.push(` Files Modified: ${explanation.filesModified.length} files`);
8769
+ lines.push(` Git Commits: ${explanation.gitCommits}`);
8770
+ lines.push("");
8771
+ if (explanation.decisions.length > 0) {
8772
+ lines.push(" Decisions");
8773
+ for (const d of explanation.decisions) {
8774
+ lines.push(` ${d.key} \u2192 ${d.value}`);
8775
+ }
8776
+ lines.push("");
8777
+ }
8778
+ const obs = explanation.observationCounts;
8779
+ lines.push(
8780
+ ` Observations: ${obs.errors} errors, ${obs.solutions} solutions, ${obs.patterns} patterns`
8781
+ );
8782
+ return lines.join("\n");
8783
+ }
8784
+ formatJson(explanation) {
8785
+ return JSON.stringify(explanation, null, 2);
8786
+ }
8787
+ };
8788
+
7958
8789
  // src/workflow/types.ts
7959
8790
  var WORKFLOWS_DIR = "workflows";
7960
8791
  var WORKFLOW_EXTENSION = ".yaml";
@@ -8017,11 +8848,11 @@ function getBuiltinPipelines() {
8017
8848
  }
8018
8849
 
8019
8850
  // src/workflow/parser.ts
8020
- import { existsSync as existsSync18, readFileSync as readFileSync10, readdirSync as readdirSync5, writeFileSync as writeFileSync9, mkdirSync as mkdirSync9 } from "fs";
8021
- import { join as join17 } from "path";
8022
- import { parse as parse2, stringify as stringify2 } from "yaml";
8851
+ import { existsSync as existsSync22, readFileSync as readFileSync13, readdirSync as readdirSync6, writeFileSync as writeFileSync12, mkdirSync as mkdirSync12 } from "fs";
8852
+ import { join as join21 } from "path";
8853
+ import { parse as parse4, stringify as stringify4 } from "yaml";
8023
8854
  function parseWorkflow(content) {
8024
- const data = parse2(content);
8855
+ const data = parse4(content);
8025
8856
  if (!data.name || typeof data.name !== "string") {
8026
8857
  throw new Error("Workflow must have a name");
8027
8858
  }
@@ -8070,25 +8901,25 @@ function parseWorkflow(content) {
8070
8901
  };
8071
8902
  }
8072
8903
  function loadWorkflow(filePath) {
8073
- if (!existsSync18(filePath)) {
8904
+ if (!existsSync22(filePath)) {
8074
8905
  throw new Error(`Workflow file not found: ${filePath}`);
8075
8906
  }
8076
- const content = readFileSync10(filePath, "utf-8");
8907
+ const content = readFileSync13(filePath, "utf-8");
8077
8908
  return parseWorkflow(content);
8078
8909
  }
8079
8910
  function loadWorkflowByName(projectPath, name) {
8080
- const workflowsDir = join17(projectPath, ".skillkit", WORKFLOWS_DIR);
8081
- if (!existsSync18(workflowsDir)) {
8911
+ const workflowsDir = join21(projectPath, ".skillkit", WORKFLOWS_DIR);
8912
+ if (!existsSync22(workflowsDir)) {
8082
8913
  return null;
8083
8914
  }
8084
- const exactPath = join17(workflowsDir, `${name}${WORKFLOW_EXTENSION}`);
8085
- if (existsSync18(exactPath)) {
8915
+ const exactPath = join21(workflowsDir, `${name}${WORKFLOW_EXTENSION}`);
8916
+ if (existsSync22(exactPath)) {
8086
8917
  return loadWorkflow(exactPath);
8087
8918
  }
8088
- const files = readdirSync5(workflowsDir).filter((f) => f.endsWith(WORKFLOW_EXTENSION));
8919
+ const files = readdirSync6(workflowsDir).filter((f) => f.endsWith(WORKFLOW_EXTENSION));
8089
8920
  for (const file of files) {
8090
8921
  try {
8091
- const workflow = loadWorkflow(join17(workflowsDir, file));
8922
+ const workflow = loadWorkflow(join21(workflowsDir, file));
8092
8923
  if (workflow.name === name) {
8093
8924
  return workflow;
8094
8925
  }
@@ -8098,15 +8929,15 @@ function loadWorkflowByName(projectPath, name) {
8098
8929
  return null;
8099
8930
  }
8100
8931
  function listWorkflows(projectPath) {
8101
- const workflowsDir = join17(projectPath, ".skillkit", WORKFLOWS_DIR);
8102
- if (!existsSync18(workflowsDir)) {
8932
+ const workflowsDir = join21(projectPath, ".skillkit", WORKFLOWS_DIR);
8933
+ if (!existsSync22(workflowsDir)) {
8103
8934
  return [];
8104
8935
  }
8105
- const files = readdirSync5(workflowsDir).filter((f) => f.endsWith(WORKFLOW_EXTENSION));
8936
+ const files = readdirSync6(workflowsDir).filter((f) => f.endsWith(WORKFLOW_EXTENSION));
8106
8937
  const workflows = [];
8107
8938
  for (const file of files) {
8108
8939
  try {
8109
- const workflow = loadWorkflow(join17(workflowsDir, file));
8940
+ const workflow = loadWorkflow(join21(workflowsDir, file));
8110
8941
  workflows.push(workflow);
8111
8942
  } catch {
8112
8943
  }
@@ -8114,17 +8945,17 @@ function listWorkflows(projectPath) {
8114
8945
  return workflows;
8115
8946
  }
8116
8947
  function saveWorkflow(projectPath, workflow) {
8117
- const workflowsDir = join17(projectPath, ".skillkit", WORKFLOWS_DIR);
8118
- if (!existsSync18(workflowsDir)) {
8119
- mkdirSync9(workflowsDir, { recursive: true });
8948
+ const workflowsDir = join21(projectPath, ".skillkit", WORKFLOWS_DIR);
8949
+ if (!existsSync22(workflowsDir)) {
8950
+ mkdirSync12(workflowsDir, { recursive: true });
8120
8951
  }
8121
8952
  const fileName = `${workflow.name.replace(/[^a-z0-9-]/gi, "-").toLowerCase()}${WORKFLOW_EXTENSION}`;
8122
- const filePath = join17(workflowsDir, fileName);
8123
- writeFileSync9(filePath, stringify2(workflow));
8953
+ const filePath = join21(workflowsDir, fileName);
8954
+ writeFileSync12(filePath, stringify4(workflow));
8124
8955
  return filePath;
8125
8956
  }
8126
8957
  function serializeWorkflow(workflow) {
8127
- return stringify2(workflow);
8958
+ return stringify4(workflow);
8128
8959
  }
8129
8960
  function validateWorkflow(workflow) {
8130
8961
  const errors = [];
@@ -8173,7 +9004,7 @@ function createWorkflowTemplate(name, description) {
8173
9004
  }
8174
9005
 
8175
9006
  // src/workflow/orchestrator.ts
8176
- import { randomUUID as randomUUID6 } from "crypto";
9007
+ import { randomUUID as randomUUID7 } from "crypto";
8177
9008
  var WorkflowOrchestrator = class {
8178
9009
  execution = null;
8179
9010
  executor;
@@ -8194,7 +9025,7 @@ var WorkflowOrchestrator = class {
8194
9025
  async execute(workflow) {
8195
9026
  this.execution = {
8196
9027
  workflow,
8197
- executionId: randomUUID6(),
9028
+ executionId: randomUUID7(),
8198
9029
  status: "running",
8199
9030
  currentWave: 0,
8200
9031
  waves: workflow.waves.map((wave, index) => ({
@@ -8386,8 +9217,8 @@ function createWorkflowOrchestrator(executor, onProgress) {
8386
9217
  }
8387
9218
 
8388
9219
  // src/executor/engine.ts
8389
- import { execSync as execSync5 } from "child_process";
8390
- import { randomUUID as randomUUID7 } from "crypto";
9220
+ import { execSync as execSync6 } from "child_process";
9221
+ import { randomUUID as randomUUID8 } from "crypto";
8391
9222
  var SkillExecutionEngine = class {
8392
9223
  projectPath;
8393
9224
  sessionManager;
@@ -8612,7 +9443,7 @@ var SkillExecutionEngine = class {
8612
9443
  */
8613
9444
  async executeTask(task, _skill, _options) {
8614
9445
  const startTime = /* @__PURE__ */ new Date();
8615
- const taskId = task.id || randomUUID7();
9446
+ const taskId = task.id || randomUUID8();
8616
9447
  try {
8617
9448
  await new Promise((resolve6) => setTimeout(resolve6, 100));
8618
9449
  const endTime = /* @__PURE__ */ new Date();
@@ -8726,7 +9557,7 @@ var SkillExecutionEngine = class {
8726
9557
  for (const rule of task.verify.automated) {
8727
9558
  if (rule.command) {
8728
9559
  try {
8729
- const output = execSync5(rule.command, {
9560
+ const output = execSync6(rule.command, {
8730
9561
  cwd: this.projectPath,
8731
9562
  encoding: "utf-8",
8732
9563
  timeout: 3e4
@@ -8784,7 +9615,7 @@ var SkillExecutionEngine = class {
8784
9615
  completedAt: (/* @__PURE__ */ new Date()).toISOString(),
8785
9616
  durationMs: 0,
8786
9617
  tasks: tasks.map((task) => ({
8787
- taskId: task.id || randomUUID7(),
9618
+ taskId: task.id || randomUUID8(),
8788
9619
  taskName: task.name,
8789
9620
  status: "skipped",
8790
9621
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -9040,26 +9871,26 @@ To execute this skill manually:
9040
9871
  }
9041
9872
 
9042
9873
  // src/executor/skill-executor.ts
9043
- import { existsSync as existsSync19 } from "fs";
9044
- import { join as join18 } from "path";
9874
+ import { existsSync as existsSync23 } from "fs";
9875
+ import { join as join22 } from "path";
9045
9876
  import { homedir as homedir7 } from "os";
9046
9877
  function getSearchDirs2(projectPath) {
9047
9878
  const dirs = [];
9048
9879
  for (const searchPath of SKILL_DISCOVERY_PATHS) {
9049
- const fullPath = join18(projectPath, searchPath);
9050
- if (existsSync19(fullPath)) {
9880
+ const fullPath = join22(projectPath, searchPath);
9881
+ if (existsSync23(fullPath)) {
9051
9882
  dirs.push(fullPath);
9052
9883
  }
9053
9884
  }
9054
9885
  const home = homedir7();
9055
9886
  const globalPaths = [
9056
- join18(home, ".claude", "skills"),
9057
- join18(home, ".cursor", "skills"),
9058
- join18(home, ".codex", "skills"),
9059
- join18(home, ".skillkit", "skills")
9887
+ join22(home, ".claude", "skills"),
9888
+ join22(home, ".cursor", "skills"),
9889
+ join22(home, ".codex", "skills"),
9890
+ join22(home, ".skillkit", "skills")
9060
9891
  ];
9061
9892
  for (const globalPath of globalPaths) {
9062
- if (existsSync19(globalPath)) {
9893
+ if (existsSync23(globalPath)) {
9063
9894
  dirs.push(globalPath);
9064
9895
  }
9065
9896
  }
@@ -9189,12 +10020,12 @@ function createSimulatedSkillExecutor(options = {}) {
9189
10020
  }
9190
10021
 
9191
10022
  // src/testing/runner.ts
9192
- import { existsSync as existsSync20, readFileSync as readFileSync11 } from "fs";
9193
- import { join as join19 } from "path";
10023
+ import { existsSync as existsSync24, readFileSync as readFileSync14 } from "fs";
10024
+ import { join as join23 } from "path";
9194
10025
  import { exec } from "child_process";
9195
10026
  import { createServer } from "net";
9196
10027
  import { promisify } from "util";
9197
- import { parse as parseYaml6 } from "yaml";
10028
+ import { parse as parseYaml7 } from "yaml";
9198
10029
  var execAsync = promisify(exec);
9199
10030
  var DEFAULT_TIMEOUT = 3e4;
9200
10031
  async function runAssertion(assertion, cwd, timeout) {
@@ -9255,8 +10086,8 @@ async function runAssertion(assertion, cwd, timeout) {
9255
10086
  }
9256
10087
  }
9257
10088
  function assertFileExists(assertion, cwd, startTime) {
9258
- const filePath = join19(cwd, assertion.target || "");
9259
- const exists = existsSync20(filePath);
10089
+ const filePath = join23(cwd, assertion.target || "");
10090
+ const exists = existsSync24(filePath);
9260
10091
  return {
9261
10092
  assertion,
9262
10093
  passed: exists,
@@ -9267,8 +10098,8 @@ function assertFileExists(assertion, cwd, startTime) {
9267
10098
  };
9268
10099
  }
9269
10100
  function assertFileNotExists(assertion, cwd, startTime) {
9270
- const filePath = join19(cwd, assertion.target || "");
9271
- const exists = existsSync20(filePath);
10101
+ const filePath = join23(cwd, assertion.target || "");
10102
+ const exists = existsSync24(filePath);
9272
10103
  return {
9273
10104
  assertion,
9274
10105
  passed: !exists,
@@ -9279,8 +10110,8 @@ function assertFileNotExists(assertion, cwd, startTime) {
9279
10110
  };
9280
10111
  }
9281
10112
  function assertFileContains(assertion, cwd, startTime) {
9282
- const filePath = join19(cwd, assertion.target || "");
9283
- if (!existsSync20(filePath)) {
10113
+ const filePath = join23(cwd, assertion.target || "");
10114
+ if (!existsSync24(filePath)) {
9284
10115
  return {
9285
10116
  assertion,
9286
10117
  passed: false,
@@ -9288,7 +10119,7 @@ function assertFileContains(assertion, cwd, startTime) {
9288
10119
  duration: Date.now() - startTime
9289
10120
  };
9290
10121
  }
9291
- const content = readFileSync11(filePath, "utf-8");
10122
+ const content = readFileSync14(filePath, "utf-8");
9292
10123
  const expected = String(assertion.expected || "");
9293
10124
  const contains = content.includes(expected);
9294
10125
  return {
@@ -9301,8 +10132,8 @@ function assertFileContains(assertion, cwd, startTime) {
9301
10132
  };
9302
10133
  }
9303
10134
  function assertFileNotContains(assertion, cwd, startTime) {
9304
- const filePath = join19(cwd, assertion.target || "");
9305
- if (!existsSync20(filePath)) {
10135
+ const filePath = join23(cwd, assertion.target || "");
10136
+ if (!existsSync24(filePath)) {
9306
10137
  return {
9307
10138
  assertion,
9308
10139
  passed: true,
@@ -9310,7 +10141,7 @@ function assertFileNotContains(assertion, cwd, startTime) {
9310
10141
  duration: Date.now() - startTime
9311
10142
  };
9312
10143
  }
9313
- const content = readFileSync11(filePath, "utf-8");
10144
+ const content = readFileSync14(filePath, "utf-8");
9314
10145
  const expected = String(assertion.expected || "");
9315
10146
  const contains = content.includes(expected);
9316
10147
  return {
@@ -9323,8 +10154,8 @@ function assertFileNotContains(assertion, cwd, startTime) {
9323
10154
  };
9324
10155
  }
9325
10156
  function assertFileMatches(assertion, cwd, startTime) {
9326
- const filePath = join19(cwd, assertion.target || "");
9327
- if (!existsSync20(filePath)) {
10157
+ const filePath = join23(cwd, assertion.target || "");
10158
+ if (!existsSync24(filePath)) {
9328
10159
  return {
9329
10160
  assertion,
9330
10161
  passed: false,
@@ -9332,7 +10163,7 @@ function assertFileMatches(assertion, cwd, startTime) {
9332
10163
  duration: Date.now() - startTime
9333
10164
  };
9334
10165
  }
9335
- const content = readFileSync11(filePath, "utf-8");
10166
+ const content = readFileSync14(filePath, "utf-8");
9336
10167
  const pattern = new RegExp(String(assertion.expected || ""));
9337
10168
  const matches = pattern.test(content);
9338
10169
  return {
@@ -9419,8 +10250,8 @@ async function assertCommandOutputContains(assertion, cwd, timeout, startTime) {
9419
10250
  }
9420
10251
  }
9421
10252
  function assertJsonValid(assertion, cwd, startTime) {
9422
- const filePath = join19(cwd, assertion.target || "");
9423
- if (!existsSync20(filePath)) {
10253
+ const filePath = join23(cwd, assertion.target || "");
10254
+ if (!existsSync24(filePath)) {
9424
10255
  return {
9425
10256
  assertion,
9426
10257
  passed: false,
@@ -9429,7 +10260,7 @@ function assertJsonValid(assertion, cwd, startTime) {
9429
10260
  };
9430
10261
  }
9431
10262
  try {
9432
- const content = readFileSync11(filePath, "utf-8");
10263
+ const content = readFileSync14(filePath, "utf-8");
9433
10264
  JSON.parse(content);
9434
10265
  return {
9435
10266
  assertion,
@@ -9450,8 +10281,8 @@ function assertJsonValid(assertion, cwd, startTime) {
9450
10281
  }
9451
10282
  }
9452
10283
  function assertJsonHasKey(assertion, cwd, startTime) {
9453
- const filePath = join19(cwd, assertion.target || "");
9454
- if (!existsSync20(filePath)) {
10284
+ const filePath = join23(cwd, assertion.target || "");
10285
+ if (!existsSync24(filePath)) {
9455
10286
  return {
9456
10287
  assertion,
9457
10288
  passed: false,
@@ -9460,7 +10291,7 @@ function assertJsonHasKey(assertion, cwd, startTime) {
9460
10291
  };
9461
10292
  }
9462
10293
  try {
9463
- const content = readFileSync11(filePath, "utf-8");
10294
+ const content = readFileSync14(filePath, "utf-8");
9464
10295
  const json = JSON.parse(content);
9465
10296
  const key = String(assertion.expected || "");
9466
10297
  const keys = key.split(".");
@@ -9495,8 +10326,8 @@ function assertJsonHasKey(assertion, cwd, startTime) {
9495
10326
  }
9496
10327
  }
9497
10328
  function assertYamlValid(assertion, cwd, startTime) {
9498
- const filePath = join19(cwd, assertion.target || "");
9499
- if (!existsSync20(filePath)) {
10329
+ const filePath = join23(cwd, assertion.target || "");
10330
+ if (!existsSync24(filePath)) {
9500
10331
  return {
9501
10332
  assertion,
9502
10333
  passed: false,
@@ -9505,8 +10336,8 @@ function assertYamlValid(assertion, cwd, startTime) {
9505
10336
  };
9506
10337
  }
9507
10338
  try {
9508
- const content = readFileSync11(filePath, "utf-8");
9509
- parseYaml6(content);
10339
+ const content = readFileSync14(filePath, "utf-8");
10340
+ parseYaml7(content);
9510
10341
  return {
9511
10342
  assertion,
9512
10343
  passed: true,
@@ -10028,8 +10859,8 @@ var MARKETPLACE_CACHE_FILE = "marketplace-index.json";
10028
10859
  var DEFAULT_CACHE_TTL = 60 * 60 * 1e3;
10029
10860
 
10030
10861
  // src/marketplace/aggregator.ts
10031
- import { existsSync as existsSync21, readFileSync as readFileSync12, writeFileSync as writeFileSync10, mkdirSync as mkdirSync10, unlinkSync as unlinkSync2 } from "fs";
10032
- import { join as join20 } from "path";
10862
+ import { existsSync as existsSync25, readFileSync as readFileSync15, writeFileSync as writeFileSync13, mkdirSync as mkdirSync13, unlinkSync as unlinkSync3 } from "fs";
10863
+ import { join as join24 } from "path";
10033
10864
  import { homedir as homedir8 } from "os";
10034
10865
  var MarketplaceAggregator = class {
10035
10866
  config;
@@ -10038,10 +10869,10 @@ var MarketplaceAggregator = class {
10038
10869
  index = null;
10039
10870
  constructor(config = {}) {
10040
10871
  this.config = config;
10041
- this.cacheDir = config.cacheDir || join20(homedir8(), ".skillkit", "marketplace");
10042
- this.cachePath = join20(this.cacheDir, MARKETPLACE_CACHE_FILE);
10043
- if (!existsSync21(this.cacheDir)) {
10044
- mkdirSync10(this.cacheDir, { recursive: true });
10872
+ this.cacheDir = config.cacheDir || join24(homedir8(), ".skillkit", "marketplace");
10873
+ this.cachePath = join24(this.cacheDir, MARKETPLACE_CACHE_FILE);
10874
+ if (!existsSync25(this.cacheDir)) {
10875
+ mkdirSync13(this.cacheDir, { recursive: true });
10045
10876
  }
10046
10877
  }
10047
10878
  /**
@@ -10054,11 +10885,11 @@ var MarketplaceAggregator = class {
10054
10885
  * Load cached index
10055
10886
  */
10056
10887
  loadCache() {
10057
- if (!existsSync21(this.cachePath)) {
10888
+ if (!existsSync25(this.cachePath)) {
10058
10889
  return null;
10059
10890
  }
10060
10891
  try {
10061
- const content = readFileSync12(this.cachePath, "utf-8");
10892
+ const content = readFileSync15(this.cachePath, "utf-8");
10062
10893
  const index = JSON.parse(content);
10063
10894
  const cacheAge = Date.now() - new Date(index.updatedAt).getTime();
10064
10895
  const ttl = this.config.cacheTTL || DEFAULT_CACHE_TTL;
@@ -10075,7 +10906,7 @@ var MarketplaceAggregator = class {
10075
10906
  * Save index to cache
10076
10907
  */
10077
10908
  saveCache(index) {
10078
- writeFileSync10(this.cachePath, JSON.stringify(index, null, 2));
10909
+ writeFileSync13(this.cachePath, JSON.stringify(index, null, 2));
10079
10910
  this.index = index;
10080
10911
  }
10081
10912
  /**
@@ -10399,8 +11230,8 @@ var MarketplaceAggregator = class {
10399
11230
  * Clear cache
10400
11231
  */
10401
11232
  clearCache() {
10402
- if (existsSync21(this.cachePath)) {
10403
- unlinkSync2(this.cachePath);
11233
+ if (existsSync25(this.cachePath)) {
11234
+ unlinkSync3(this.cachePath);
10404
11235
  }
10405
11236
  this.index = null;
10406
11237
  }
@@ -10624,203 +11455,9 @@ var DEFAULT_MEMORY_CONFIG = {
10624
11455
  maxLearnings: 500
10625
11456
  };
10626
11457
 
10627
- // src/memory/observation-store.ts
10628
- import { existsSync as existsSync22, mkdirSync as mkdirSync11, readFileSync as readFileSync13, writeFileSync as writeFileSync11 } from "fs";
10629
- import { dirname as dirname4, join as join21 } from "path";
10630
- import { parse as parseYaml7, stringify as stringifyYaml5 } from "yaml";
10631
- import { randomUUID as randomUUID8 } from "crypto";
10632
- var ObservationStore = class {
10633
- filePath;
10634
- projectPath;
10635
- data = null;
10636
- sessionId;
10637
- compressionThreshold;
10638
- autoCompress;
10639
- onThresholdReached;
10640
- compressionInProgress = false;
10641
- constructor(projectPath, sessionId, options = {}) {
10642
- this.projectPath = projectPath;
10643
- this.filePath = join21(projectPath, ".skillkit", "memory", "observations.yaml");
10644
- this.sessionId = sessionId || randomUUID8();
10645
- this.compressionThreshold = options.compressionThreshold ?? 50;
10646
- this.autoCompress = options.autoCompress ?? true;
10647
- this.onThresholdReached = options.onThresholdReached;
10648
- }
10649
- ensureDir() {
10650
- const dir = dirname4(this.filePath);
10651
- if (!existsSync22(dir)) {
10652
- mkdirSync11(dir, { recursive: true });
10653
- }
10654
- }
10655
- load() {
10656
- if (this.data) return this.data;
10657
- if (existsSync22(this.filePath)) {
10658
- try {
10659
- const content = readFileSync13(this.filePath, "utf-8");
10660
- this.data = parseYaml7(content);
10661
- if (this.data.sessionId !== this.sessionId) {
10662
- this.data.sessionId = this.sessionId;
10663
- this.data.observations = [];
10664
- }
10665
- } catch {
10666
- this.data = this.createEmpty();
10667
- }
10668
- } else {
10669
- this.data = this.createEmpty();
10670
- }
10671
- return this.data;
10672
- }
10673
- createEmpty() {
10674
- return {
10675
- version: 1,
10676
- sessionId: this.sessionId,
10677
- observations: []
10678
- };
10679
- }
10680
- save() {
10681
- this.ensureDir();
10682
- const content = stringifyYaml5(this.data, { lineWidth: 0 });
10683
- writeFileSync11(this.filePath, content, "utf-8");
10684
- }
10685
- add(type, content, agent, relevance = 50) {
10686
- const data = this.load();
10687
- const observation = {
10688
- id: randomUUID8(),
10689
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
10690
- sessionId: this.sessionId,
10691
- agent,
10692
- type,
10693
- content,
10694
- relevance
10695
- };
10696
- data.observations.push(observation);
10697
- this.save();
10698
- void this.checkAutoCompression().catch(() => {
10699
- });
10700
- return observation;
10701
- }
10702
- /**
10703
- * Check if auto-compression should trigger
10704
- */
10705
- async checkAutoCompression() {
10706
- if (!this.autoCompress || this.compressionInProgress) return;
10707
- if (!this.onThresholdReached) return;
10708
- const count = this.count();
10709
- if (count >= this.compressionThreshold) {
10710
- this.compressionInProgress = true;
10711
- try {
10712
- const observations = this.getAll();
10713
- await this.onThresholdReached(observations);
10714
- } finally {
10715
- this.compressionInProgress = false;
10716
- }
10717
- }
10718
- }
10719
- /**
10720
- * Set auto-compression callback
10721
- */
10722
- setAutoCompressCallback(callback) {
10723
- this.onThresholdReached = callback;
10724
- }
10725
- /**
10726
- * Enable/disable auto-compression
10727
- */
10728
- setAutoCompress(enabled) {
10729
- this.autoCompress = enabled;
10730
- }
10731
- /**
10732
- * Set compression threshold
10733
- */
10734
- setCompressionThreshold(threshold) {
10735
- if (threshold < 1 || !Number.isInteger(threshold)) {
10736
- throw new Error("Compression threshold must be a positive integer");
10737
- }
10738
- this.compressionThreshold = threshold;
10739
- }
10740
- /**
10741
- * Get compression threshold
10742
- */
10743
- getCompressionThreshold() {
10744
- return this.compressionThreshold;
10745
- }
10746
- /**
10747
- * Check if threshold is reached
10748
- */
10749
- isThresholdReached() {
10750
- return this.count() >= this.compressionThreshold;
10751
- }
10752
- /**
10753
- * Get project path
10754
- */
10755
- getProjectPath() {
10756
- return this.projectPath;
10757
- }
10758
- getAll() {
10759
- return this.load().observations;
10760
- }
10761
- getByType(type) {
10762
- return this.load().observations.filter((o) => o.type === type);
10763
- }
10764
- getByRelevance(minRelevance) {
10765
- return this.load().observations.filter((o) => o.relevance >= minRelevance);
10766
- }
10767
- getRecent(count) {
10768
- const observations = this.load().observations;
10769
- return observations.slice(-count);
10770
- }
10771
- getUncompressed(compressedIds) {
10772
- const compressedSet = new Set(compressedIds);
10773
- return this.load().observations.filter((o) => !compressedSet.has(o.id));
10774
- }
10775
- count() {
10776
- return this.load().observations.length;
10777
- }
10778
- clear() {
10779
- this.data = this.createEmpty();
10780
- this.save();
10781
- }
10782
- getById(id) {
10783
- return this.load().observations.find((o) => o.id === id);
10784
- }
10785
- getByIds(ids) {
10786
- const idSet = new Set(ids);
10787
- return this.load().observations.filter((o) => idSet.has(o.id));
10788
- }
10789
- getSessionId() {
10790
- return this.sessionId;
10791
- }
10792
- setSessionId(sessionId) {
10793
- this.sessionId = sessionId;
10794
- if (this.data) {
10795
- this.data.sessionId = sessionId;
10796
- }
10797
- }
10798
- exists() {
10799
- return existsSync22(this.filePath);
10800
- }
10801
- delete(id) {
10802
- const data = this.load();
10803
- const index = data.observations.findIndex((o) => o.id === id);
10804
- if (index === -1) return false;
10805
- data.observations.splice(index, 1);
10806
- this.save();
10807
- return true;
10808
- }
10809
- deleteMany(ids) {
10810
- const idSet = new Set(ids);
10811
- const data = this.load();
10812
- const initialLength = data.observations.length;
10813
- data.observations = data.observations.filter((o) => !idSet.has(o.id));
10814
- if (data.observations.length !== initialLength) {
10815
- this.save();
10816
- }
10817
- return initialLength - data.observations.length;
10818
- }
10819
- };
10820
-
10821
11458
  // src/memory/learning-store.ts
10822
- import { existsSync as existsSync23, mkdirSync as mkdirSync12, readFileSync as readFileSync14, writeFileSync as writeFileSync12 } from "fs";
10823
- import { dirname as dirname5, join as join22 } from "path";
11459
+ import { existsSync as existsSync26, mkdirSync as mkdirSync14, readFileSync as readFileSync16, writeFileSync as writeFileSync14 } from "fs";
11460
+ import { dirname as dirname5, join as join25 } from "path";
10824
11461
  import { homedir as homedir9 } from "os";
10825
11462
  import { parse as parseYaml8, stringify as stringifyYaml6 } from "yaml";
10826
11463
  import { randomUUID as randomUUID9 } from "crypto";
@@ -10833,22 +11470,22 @@ var LearningStore = class {
10833
11470
  this.scope = scope;
10834
11471
  this.projectName = projectName;
10835
11472
  if (scope === "project" && projectPath) {
10836
- this.filePath = join22(projectPath, ".skillkit", "memory", "learnings.yaml");
11473
+ this.filePath = join25(projectPath, ".skillkit", "memory", "learnings.yaml");
10837
11474
  } else {
10838
- this.filePath = join22(homedir9(), ".skillkit", "memory", "global.yaml");
11475
+ this.filePath = join25(homedir9(), ".skillkit", "memory", "global.yaml");
10839
11476
  }
10840
11477
  }
10841
11478
  ensureDir() {
10842
11479
  const dir = dirname5(this.filePath);
10843
- if (!existsSync23(dir)) {
10844
- mkdirSync12(dir, { recursive: true });
11480
+ if (!existsSync26(dir)) {
11481
+ mkdirSync14(dir, { recursive: true });
10845
11482
  }
10846
11483
  }
10847
11484
  load() {
10848
11485
  if (this.data) return this.data;
10849
- if (existsSync23(this.filePath)) {
11486
+ if (existsSync26(this.filePath)) {
10850
11487
  try {
10851
- const content = readFileSync14(this.filePath, "utf-8");
11488
+ const content = readFileSync16(this.filePath, "utf-8");
10852
11489
  this.data = parseYaml8(content);
10853
11490
  } catch {
10854
11491
  this.data = this.createEmpty();
@@ -10867,7 +11504,7 @@ var LearningStore = class {
10867
11504
  save() {
10868
11505
  this.ensureDir();
10869
11506
  const content = stringifyYaml6(this.data, { lineWidth: 0 });
10870
- writeFileSync12(this.filePath, content, "utf-8");
11507
+ writeFileSync14(this.filePath, content, "utf-8");
10871
11508
  }
10872
11509
  add(learning) {
10873
11510
  const data = this.load();
@@ -10974,7 +11611,7 @@ var LearningStore = class {
10974
11611
  this.save();
10975
11612
  }
10976
11613
  exists() {
10977
- return existsSync23(this.filePath);
11614
+ return existsSync26(this.filePath);
10978
11615
  }
10979
11616
  getScope() {
10980
11617
  return this.scope;
@@ -10982,26 +11619,26 @@ var LearningStore = class {
10982
11619
  };
10983
11620
 
10984
11621
  // src/memory/memory-index.ts
10985
- import { existsSync as existsSync24, mkdirSync as mkdirSync13, readFileSync as readFileSync15, writeFileSync as writeFileSync13 } from "fs";
10986
- import { dirname as dirname6, join as join23 } from "path";
11622
+ import { existsSync as existsSync27, mkdirSync as mkdirSync15, readFileSync as readFileSync17, writeFileSync as writeFileSync15 } from "fs";
11623
+ import { dirname as dirname6, join as join26 } from "path";
10987
11624
  import { parse as parseYaml9, stringify as stringifyYaml7 } from "yaml";
10988
11625
  var MemoryIndexStore = class {
10989
11626
  filePath;
10990
11627
  data = null;
10991
11628
  constructor(basePath, _isGlobal = false) {
10992
- this.filePath = join23(basePath, ".skillkit", "memory", "index.yaml");
11629
+ this.filePath = join26(basePath, ".skillkit", "memory", "index.yaml");
10993
11630
  }
10994
11631
  ensureDir() {
10995
11632
  const dir = dirname6(this.filePath);
10996
- if (!existsSync24(dir)) {
10997
- mkdirSync13(dir, { recursive: true });
11633
+ if (!existsSync27(dir)) {
11634
+ mkdirSync15(dir, { recursive: true });
10998
11635
  }
10999
11636
  }
11000
11637
  load() {
11001
11638
  if (this.data) return this.data;
11002
- if (existsSync24(this.filePath)) {
11639
+ if (existsSync27(this.filePath)) {
11003
11640
  try {
11004
- const content = readFileSync15(this.filePath, "utf-8");
11641
+ const content = readFileSync17(this.filePath, "utf-8");
11005
11642
  this.data = parseYaml9(content);
11006
11643
  } catch {
11007
11644
  this.data = this.createEmpty();
@@ -11025,7 +11662,7 @@ var MemoryIndexStore = class {
11025
11662
  this.data.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
11026
11663
  }
11027
11664
  const content = stringifyYaml7(this.data, { lineWidth: 0 });
11028
- writeFileSync13(this.filePath, content, "utf-8");
11665
+ writeFileSync15(this.filePath, content, "utf-8");
11029
11666
  }
11030
11667
  extractKeywords(text) {
11031
11668
  const stopWords = /* @__PURE__ */ new Set([
@@ -11219,7 +11856,7 @@ var MemoryIndexStore = class {
11219
11856
  this.save();
11220
11857
  }
11221
11858
  exists() {
11222
- return existsSync24(this.filePath);
11859
+ return existsSync27(this.filePath);
11223
11860
  }
11224
11861
  getStats() {
11225
11862
  const data = this.load();
@@ -11232,50 +11869,50 @@ var MemoryIndexStore = class {
11232
11869
  };
11233
11870
 
11234
11871
  // src/memory/initializer.ts
11235
- import { existsSync as existsSync25, mkdirSync as mkdirSync14 } from "fs";
11236
- import { join as join24 } from "path";
11872
+ import { existsSync as existsSync28, mkdirSync as mkdirSync16 } from "fs";
11873
+ import { join as join27 } from "path";
11237
11874
  import { homedir as homedir10 } from "os";
11238
11875
  function getMemoryPaths(projectPath) {
11239
- const projectMemoryDir = join24(projectPath, ".skillkit", "memory");
11240
- const globalMemoryDir = join24(homedir10(), ".skillkit", "memory");
11876
+ const projectMemoryDir = join27(projectPath, ".skillkit", "memory");
11877
+ const globalMemoryDir = join27(homedir10(), ".skillkit", "memory");
11241
11878
  return {
11242
11879
  projectMemoryDir,
11243
11880
  globalMemoryDir,
11244
- observationsFile: join24(projectMemoryDir, "observations.yaml"),
11245
- learningsFile: join24(projectMemoryDir, "learnings.yaml"),
11246
- indexFile: join24(projectMemoryDir, "index.yaml"),
11247
- globalLearningsFile: join24(globalMemoryDir, "global.yaml"),
11248
- globalIndexFile: join24(globalMemoryDir, "index.yaml")
11881
+ observationsFile: join27(projectMemoryDir, "observations.yaml"),
11882
+ learningsFile: join27(projectMemoryDir, "learnings.yaml"),
11883
+ indexFile: join27(projectMemoryDir, "index.yaml"),
11884
+ globalLearningsFile: join27(globalMemoryDir, "global.yaml"),
11885
+ globalIndexFile: join27(globalMemoryDir, "index.yaml")
11249
11886
  };
11250
11887
  }
11251
11888
  function initializeMemoryDirectory(projectPath) {
11252
11889
  const paths = getMemoryPaths(projectPath);
11253
- if (!existsSync25(paths.projectMemoryDir)) {
11254
- mkdirSync14(paths.projectMemoryDir, { recursive: true });
11890
+ if (!existsSync28(paths.projectMemoryDir)) {
11891
+ mkdirSync16(paths.projectMemoryDir, { recursive: true });
11255
11892
  }
11256
- if (!existsSync25(paths.globalMemoryDir)) {
11257
- mkdirSync14(paths.globalMemoryDir, { recursive: true });
11893
+ if (!existsSync28(paths.globalMemoryDir)) {
11894
+ mkdirSync16(paths.globalMemoryDir, { recursive: true });
11258
11895
  }
11259
11896
  return paths;
11260
11897
  }
11261
11898
  function memoryDirectoryExists(projectPath) {
11262
11899
  const paths = getMemoryPaths(projectPath);
11263
- return existsSync25(paths.projectMemoryDir);
11900
+ return existsSync28(paths.projectMemoryDir);
11264
11901
  }
11265
11902
  function globalMemoryDirectoryExists() {
11266
- const globalMemoryDir = join24(homedir10(), ".skillkit", "memory");
11267
- return existsSync25(globalMemoryDir);
11903
+ const globalMemoryDir = join27(homedir10(), ".skillkit", "memory");
11904
+ return existsSync28(globalMemoryDir);
11268
11905
  }
11269
11906
  function getMemoryStatus(projectPath) {
11270
11907
  const paths = getMemoryPaths(projectPath);
11271
11908
  return {
11272
- projectMemoryExists: existsSync25(paths.projectMemoryDir),
11273
- globalMemoryExists: existsSync25(paths.globalMemoryDir),
11274
- hasObservations: existsSync25(paths.observationsFile),
11275
- hasLearnings: existsSync25(paths.learningsFile),
11276
- hasGlobalLearnings: existsSync25(paths.globalLearningsFile),
11277
- hasIndex: existsSync25(paths.indexFile),
11278
- hasGlobalIndex: existsSync25(paths.globalIndexFile)
11909
+ projectMemoryExists: existsSync28(paths.projectMemoryDir),
11910
+ globalMemoryExists: existsSync28(paths.globalMemoryDir),
11911
+ hasObservations: existsSync28(paths.observationsFile),
11912
+ hasLearnings: existsSync28(paths.learningsFile),
11913
+ hasGlobalLearnings: existsSync28(paths.globalLearningsFile),
11914
+ hasIndex: existsSync28(paths.indexFile),
11915
+ hasGlobalIndex: existsSync28(paths.globalIndexFile)
11279
11916
  };
11280
11917
  }
11281
11918
 
@@ -13961,8 +14598,8 @@ function createMemoryHookManager(projectPath, agent = "claude-code", config = {}
13961
14598
  }
13962
14599
 
13963
14600
  // src/memory/claude-md-updater.ts
13964
- import { existsSync as existsSync26, readFileSync as readFileSync16, writeFileSync as writeFileSync14, mkdirSync as mkdirSync15 } from "fs";
13965
- import { join as join25, dirname as dirname7, basename as basename11 } from "path";
14601
+ import { existsSync as existsSync29, readFileSync as readFileSync18, writeFileSync as writeFileSync16, mkdirSync as mkdirSync17 } from "fs";
14602
+ import { join as join28, dirname as dirname7, basename as basename11 } from "path";
13966
14603
  import { homedir as homedir12 } from "os";
13967
14604
  var SKILLKIT_MARKER = "<!-- Auto-populated by SkillKit -->";
13968
14605
  var DEFAULT_UPDATE_OPTIONS = {
@@ -13978,20 +14615,20 @@ var ClaudeMdUpdater = class {
13978
14615
  claudeMdPath;
13979
14616
  constructor(projectPath, claudeMdPath) {
13980
14617
  this.projectPath = projectPath;
13981
- this.claudeMdPath = claudeMdPath || join25(projectPath, "CLAUDE.md");
14618
+ this.claudeMdPath = claudeMdPath || join28(projectPath, "CLAUDE.md");
13982
14619
  }
13983
14620
  /**
13984
14621
  * Parse CLAUDE.md to extract structure
13985
14622
  */
13986
14623
  parse() {
13987
- if (!existsSync26(this.claudeMdPath)) {
14624
+ if (!existsSync29(this.claudeMdPath)) {
13988
14625
  return {
13989
14626
  content: "",
13990
14627
  sections: /* @__PURE__ */ new Map(),
13991
14628
  hasLearnedSection: false
13992
14629
  };
13993
14630
  }
13994
- const content = readFileSync16(this.claudeMdPath, "utf-8");
14631
+ const content = readFileSync18(this.claudeMdPath, "utf-8");
13995
14632
  const sections = /* @__PURE__ */ new Map();
13996
14633
  const lines = content.split("\n");
13997
14634
  let currentSection = null;
@@ -14118,10 +14755,10 @@ var ClaudeMdUpdater = class {
14118
14755
  newContent = this.createNewClaudeMd(newSection);
14119
14756
  }
14120
14757
  const dir = dirname7(this.claudeMdPath);
14121
- if (!existsSync26(dir)) {
14122
- mkdirSync15(dir, { recursive: true });
14758
+ if (!existsSync29(dir)) {
14759
+ mkdirSync17(dir, { recursive: true });
14123
14760
  }
14124
- writeFileSync14(this.claudeMdPath, newContent, "utf-8");
14761
+ writeFileSync16(this.claudeMdPath, newContent, "utf-8");
14125
14762
  return {
14126
14763
  updated: true,
14127
14764
  path: this.claudeMdPath,
@@ -14146,7 +14783,7 @@ var ClaudeMdUpdater = class {
14146
14783
  * Check if CLAUDE.md exists
14147
14784
  */
14148
14785
  exists() {
14149
- return existsSync26(this.claudeMdPath);
14786
+ return existsSync29(this.claudeMdPath);
14150
14787
  }
14151
14788
  /**
14152
14789
  * Get CLAUDE.md path
@@ -14250,7 +14887,7 @@ function updateClaudeMd(projectPath, options = {}) {
14250
14887
  return updater.update(options);
14251
14888
  }
14252
14889
  function syncGlobalClaudeMd(options = {}) {
14253
- const globalClaudeMdPath = join25(homedir12(), ".claude", "CLAUDE.md");
14890
+ const globalClaudeMdPath = join28(homedir12(), ".claude", "CLAUDE.md");
14254
14891
  const updater = new ClaudeMdUpdater(homedir12(), globalClaudeMdPath);
14255
14892
  const globalOpts = {
14256
14893
  ...options,
@@ -14570,9 +15207,9 @@ function createProgressiveDisclosureManager(projectPath, projectName) {
14570
15207
  }
14571
15208
 
14572
15209
  // src/team/manager.ts
14573
- import { existsSync as existsSync27, readFileSync as readFileSync17, writeFileSync as writeFileSync15, mkdirSync as mkdirSync16 } from "fs";
14574
- import { join as join26, dirname as dirname8 } from "path";
14575
- import { execSync as execSync6 } from "child_process";
15210
+ import { existsSync as existsSync30, readFileSync as readFileSync19, writeFileSync as writeFileSync17, mkdirSync as mkdirSync18 } from "fs";
15211
+ import { join as join29, dirname as dirname8 } from "path";
15212
+ import { execSync as execSync7 } from "child_process";
14576
15213
  import { parse as yamlParse, stringify as yamlStringify } from "yaml";
14577
15214
  var TEAM_CONFIG_FILE = "team.yaml";
14578
15215
  var TEAM_DIR = ".skillkit/team";
@@ -14592,9 +15229,9 @@ var TeamManager = class {
14592
15229
  ...config,
14593
15230
  teamId
14594
15231
  };
14595
- const teamDir = join26(this.projectPath, TEAM_DIR);
14596
- if (!existsSync27(teamDir)) {
14597
- mkdirSync16(teamDir, { recursive: true });
15232
+ const teamDir = join29(this.projectPath, TEAM_DIR);
15233
+ if (!existsSync30(teamDir)) {
15234
+ mkdirSync18(teamDir, { recursive: true });
14598
15235
  }
14599
15236
  this.saveConfig(fullConfig);
14600
15237
  this.config = fullConfig;
@@ -14614,12 +15251,12 @@ var TeamManager = class {
14614
15251
  * Load existing team configuration
14615
15252
  */
14616
15253
  load() {
14617
- const configPath = join26(this.projectPath, TEAM_DIR, TEAM_CONFIG_FILE);
14618
- if (!existsSync27(configPath)) {
15254
+ const configPath = join29(this.projectPath, TEAM_DIR, TEAM_CONFIG_FILE);
15255
+ if (!existsSync30(configPath)) {
14619
15256
  return null;
14620
15257
  }
14621
15258
  try {
14622
- const content = readFileSync17(configPath, "utf-8");
15259
+ const content = readFileSync19(configPath, "utf-8");
14623
15260
  this.config = this.parseYaml(content);
14624
15261
  this.loadRegistry();
14625
15262
  return this.config;
@@ -14650,8 +15287,8 @@ var TeamManager = class {
14650
15287
  if (!skillPath) {
14651
15288
  throw new Error(`Skill "${options.skillName}" not found locally.`);
14652
15289
  }
14653
- const skillMdPath = join26(skillPath, "SKILL.md");
14654
- const skillContent = existsSync27(skillMdPath) ? readFileSync17(skillMdPath, "utf-8") : "";
15290
+ const skillMdPath = join29(skillPath, "SKILL.md");
15291
+ const skillContent = existsSync30(skillMdPath) ? readFileSync19(skillMdPath, "utf-8") : "";
14655
15292
  const metadata = this.extractFrontmatter(skillContent);
14656
15293
  const shared = {
14657
15294
  name: options.skillName,
@@ -14716,7 +15353,7 @@ var TeamManager = class {
14716
15353
  if (options.dryRun) {
14717
15354
  return {
14718
15355
  success: true,
14719
- path: join26(this.projectPath, ".skillkit", "skills", skillName)
15356
+ path: join29(this.projectPath, ".skillkit", "skills", skillName)
14720
15357
  };
14721
15358
  }
14722
15359
  try {
@@ -14766,9 +15403,9 @@ var TeamManager = class {
14766
15403
  if (!fetchResult.success || !fetchResult.path) {
14767
15404
  throw new Error(fetchResult.error || "Failed to fetch remote registry");
14768
15405
  }
14769
- const remoteRegistryPath = join26(fetchResult.path, TEAM_DIR, "registry.yaml");
14770
- if (existsSync27(remoteRegistryPath)) {
14771
- const remoteContent = readFileSync17(remoteRegistryPath, "utf-8");
15406
+ const remoteRegistryPath = join29(fetchResult.path, TEAM_DIR, "registry.yaml");
15407
+ if (existsSync30(remoteRegistryPath)) {
15408
+ const remoteContent = readFileSync19(remoteRegistryPath, "utf-8");
14772
15409
  const remoteRegistry = this.parseYaml(remoteContent);
14773
15410
  const localSkillNames = new Set(this.registry?.skills.map((s) => s.name) || []);
14774
15411
  for (const skill of remoteRegistry.skills) {
@@ -14814,32 +15451,32 @@ var TeamManager = class {
14814
15451
  return `team-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
14815
15452
  }
14816
15453
  saveConfig(config) {
14817
- const configPath = join26(this.projectPath, TEAM_DIR, TEAM_CONFIG_FILE);
15454
+ const configPath = join29(this.projectPath, TEAM_DIR, TEAM_CONFIG_FILE);
14818
15455
  const dir = dirname8(configPath);
14819
- if (!existsSync27(dir)) {
14820
- mkdirSync16(dir, { recursive: true });
15456
+ if (!existsSync30(dir)) {
15457
+ mkdirSync18(dir, { recursive: true });
14821
15458
  }
14822
- writeFileSync15(configPath, this.toYaml(config), "utf-8");
15459
+ writeFileSync17(configPath, this.toYaml(config), "utf-8");
14823
15460
  }
14824
15461
  loadRegistry() {
14825
- const registryPath = join26(this.projectPath, TEAM_DIR, "registry.yaml");
14826
- if (existsSync27(registryPath)) {
14827
- const content = readFileSync17(registryPath, "utf-8");
15462
+ const registryPath = join29(this.projectPath, TEAM_DIR, "registry.yaml");
15463
+ if (existsSync30(registryPath)) {
15464
+ const content = readFileSync19(registryPath, "utf-8");
14828
15465
  this.registry = this.parseYaml(content);
14829
15466
  }
14830
15467
  }
14831
15468
  saveRegistry(registry) {
14832
- const registryPath = join26(this.projectPath, TEAM_DIR, "registry.yaml");
14833
- writeFileSync15(registryPath, this.toYaml(registry), "utf-8");
15469
+ const registryPath = join29(this.projectPath, TEAM_DIR, "registry.yaml");
15470
+ writeFileSync17(registryPath, this.toYaml(registry), "utf-8");
14834
15471
  }
14835
15472
  findLocalSkill(skillName) {
14836
15473
  const possiblePaths = [
14837
- join26(this.projectPath, ".skillkit", "skills", skillName),
14838
- join26(this.projectPath, "skills", skillName),
14839
- join26(this.projectPath, ".claude", "skills", skillName)
15474
+ join29(this.projectPath, ".skillkit", "skills", skillName),
15475
+ join29(this.projectPath, "skills", skillName),
15476
+ join29(this.projectPath, ".claude", "skills", skillName)
14840
15477
  ];
14841
15478
  for (const p of possiblePaths) {
14842
- if (existsSync27(p)) {
15479
+ if (existsSync30(p)) {
14843
15480
  return p;
14844
15481
  }
14845
15482
  }
@@ -14847,8 +15484,8 @@ var TeamManager = class {
14847
15484
  }
14848
15485
  getAuthor() {
14849
15486
  try {
14850
- const name = execSync6("git config user.name", { encoding: "utf-8" }).trim();
14851
- const email = execSync6("git config user.email", { encoding: "utf-8" }).trim();
15487
+ const name = execSync7("git config user.name", { encoding: "utf-8" }).trim();
15488
+ const email = execSync7("git config user.email", { encoding: "utf-8" }).trim();
14852
15489
  return email ? `${name} <${email}>` : name;
14853
15490
  } catch {
14854
15491
  return "Unknown";
@@ -14856,13 +15493,13 @@ var TeamManager = class {
14856
15493
  }
14857
15494
  detectCompatibleAgents(skillPath) {
14858
15495
  const agents = [];
14859
- if (existsSync27(join26(skillPath, "SKILL.md"))) {
15496
+ if (existsSync30(join29(skillPath, "SKILL.md"))) {
14860
15497
  agents.push("claude-code", "codex", "gemini-cli", "universal");
14861
15498
  }
14862
- if (existsSync27(join26(skillPath, "skill.mdc"))) {
15499
+ if (existsSync30(join29(skillPath, "skill.mdc"))) {
14863
15500
  agents.push("cursor");
14864
15501
  }
14865
- if (existsSync27(join26(skillPath, "rules.md"))) {
15502
+ if (existsSync30(join29(skillPath, "rules.md"))) {
14866
15503
  agents.push("windsurf");
14867
15504
  }
14868
15505
  return agents.length > 0 ? agents : ["universal"];
@@ -14888,8 +15525,8 @@ function createTeamManager(projectPath) {
14888
15525
  }
14889
15526
 
14890
15527
  // src/team/bundle.ts
14891
- import { existsSync as existsSync28, readFileSync as readFileSync18, writeFileSync as writeFileSync16, mkdirSync as mkdirSync17, readdirSync as readdirSync6, statSync as statSync3 } from "fs";
14892
- import { join as join27, basename as basename12, resolve as resolve4, relative, dirname as dirname9, sep as sep3 } from "path";
15528
+ import { existsSync as existsSync31, readFileSync as readFileSync20, writeFileSync as writeFileSync18, mkdirSync as mkdirSync19, readdirSync as readdirSync7, statSync as statSync3 } from "fs";
15529
+ import { join as join30, basename as basename12, resolve as resolve4, relative, dirname as dirname9, sep as sep3 } from "path";
14893
15530
  import { createHash } from "crypto";
14894
15531
  var BUNDLE_VERSION = 1;
14895
15532
  var SkillBundle = class {
@@ -14971,15 +15608,15 @@ var SkillBundle = class {
14971
15608
  readSkillContent(skillPath) {
14972
15609
  const contents = [];
14973
15610
  const readDir = (dir, prefix = "") => {
14974
- const entries = readdirSync6(dir);
15611
+ const entries = readdirSync7(dir);
14975
15612
  for (const entry of entries) {
14976
- const fullPath = join27(dir, entry);
15613
+ const fullPath = join30(dir, entry);
14977
15614
  const relativePath = prefix ? `${prefix}/${entry}` : entry;
14978
15615
  const stat = statSync3(fullPath);
14979
15616
  if (stat.isDirectory()) {
14980
15617
  readDir(fullPath, relativePath);
14981
15618
  } else if (stat.isFile()) {
14982
- const content = readFileSync18(fullPath, "utf-8");
15619
+ const content = readFileSync20(fullPath, "utf-8");
14983
15620
  contents.push(`--- ${relativePath} ---
14984
15621
  ${content}`);
14985
15622
  }
@@ -14988,13 +15625,13 @@ ${content}`);
14988
15625
  if (statSync3(skillPath).isDirectory()) {
14989
15626
  readDir(skillPath);
14990
15627
  } else {
14991
- contents.push(readFileSync18(skillPath, "utf-8"));
15628
+ contents.push(readFileSync20(skillPath, "utf-8"));
14992
15629
  }
14993
15630
  return contents.join("\n\n");
14994
15631
  }
14995
15632
  detectAgents(skillPath) {
14996
15633
  const agents = [];
14997
- if (existsSync28(skillPath) && statSync3(skillPath).isFile()) {
15634
+ if (existsSync31(skillPath) && statSync3(skillPath).isFile()) {
14998
15635
  const fileName = basename12(skillPath).toLowerCase();
14999
15636
  if (fileName === "skill.md") {
15000
15637
  return ["claude-code", "codex", "gemini-cli", "universal"];
@@ -15007,13 +15644,13 @@ ${content}`);
15007
15644
  }
15008
15645
  return ["universal"];
15009
15646
  }
15010
- if (existsSync28(join27(skillPath, "SKILL.md"))) {
15647
+ if (existsSync31(join30(skillPath, "SKILL.md"))) {
15011
15648
  agents.push("claude-code", "codex", "gemini-cli", "universal");
15012
15649
  }
15013
- if (existsSync28(join27(skillPath, "skill.mdc"))) {
15650
+ if (existsSync31(join30(skillPath, "skill.mdc"))) {
15014
15651
  agents.push("cursor");
15015
15652
  }
15016
- if (existsSync28(join27(skillPath, "rules.md"))) {
15653
+ if (existsSync31(join30(skillPath, "rules.md"))) {
15017
15654
  agents.push("windsurf");
15018
15655
  }
15019
15656
  return agents.length > 0 ? agents : ["universal"];
@@ -15036,10 +15673,10 @@ function exportBundle(bundle, outputPath) {
15036
15673
  }
15037
15674
  }
15038
15675
  const dir = dirname9(outputPath);
15039
- if (dir && !existsSync28(dir)) {
15040
- mkdirSync17(dir, { recursive: true });
15676
+ if (dir && !existsSync31(dir)) {
15677
+ mkdirSync19(dir, { recursive: true });
15041
15678
  }
15042
- writeFileSync16(outputPath, JSON.stringify(exportData, null, 2), "utf-8");
15679
+ writeFileSync18(outputPath, JSON.stringify(exportData, null, 2), "utf-8");
15043
15680
  return { success: true, path: outputPath };
15044
15681
  } catch (err) {
15045
15682
  return {
@@ -15052,7 +15689,7 @@ function importBundle(bundlePath, targetDir, options = {}) {
15052
15689
  const imported = [];
15053
15690
  const errors = [];
15054
15691
  try {
15055
- const content = readFileSync18(bundlePath, "utf-8");
15692
+ const content = readFileSync20(bundlePath, "utf-8");
15056
15693
  const data = JSON.parse(content);
15057
15694
  const absoluteTargetDir = resolve4(targetDir);
15058
15695
  for (const skill of data.manifest.skills) {
@@ -15065,19 +15702,19 @@ function importBundle(bundlePath, targetDir, options = {}) {
15065
15702
  errors.push(`Skill "${skill.name}" has no content in bundle`);
15066
15703
  continue;
15067
15704
  }
15068
- const skillDir = join27(absoluteTargetDir, skill.name);
15705
+ const skillDir = join30(absoluteTargetDir, skill.name);
15069
15706
  const resolvedSkillDir = resolve4(skillDir);
15070
15707
  const relativeToTarget = relative(absoluteTargetDir, resolvedSkillDir);
15071
15708
  if (relativeToTarget.startsWith("..") || relativeToTarget.startsWith(sep3)) {
15072
15709
  errors.push(`Skill "${skill.name}" would escape target directory`);
15073
15710
  continue;
15074
15711
  }
15075
- if (existsSync28(skillDir) && !options.overwrite) {
15712
+ if (existsSync31(skillDir) && !options.overwrite) {
15076
15713
  errors.push(`Skill "${skill.name}" already exists (use --overwrite)`);
15077
15714
  continue;
15078
15715
  }
15079
- if (!existsSync28(skillDir)) {
15080
- mkdirSync17(skillDir, { recursive: true });
15716
+ if (!existsSync31(skillDir)) {
15717
+ mkdirSync19(skillDir, { recursive: true });
15081
15718
  }
15082
15719
  const files = parseSkillContent2(skillContent);
15083
15720
  for (const [filePath, fileContent] of Object.entries(files)) {
@@ -15088,10 +15725,10 @@ function importBundle(bundlePath, targetDir, options = {}) {
15088
15725
  continue;
15089
15726
  }
15090
15727
  const fileDir = dirname9(fullPath);
15091
- if (!existsSync28(fileDir)) {
15092
- mkdirSync17(fileDir, { recursive: true });
15728
+ if (!existsSync31(fileDir)) {
15729
+ mkdirSync19(fileDir, { recursive: true });
15093
15730
  }
15094
- writeFileSync16(fullPath, fileContent, "utf-8");
15731
+ writeFileSync18(fullPath, fileContent, "utf-8");
15095
15732
  }
15096
15733
  imported.push(skill.name);
15097
15734
  }
@@ -15120,8 +15757,8 @@ function parseSkillContent2(content) {
15120
15757
  }
15121
15758
 
15122
15759
  // src/plugins/manager.ts
15123
- import { existsSync as existsSync29, readFileSync as readFileSync19, writeFileSync as writeFileSync17, mkdirSync as mkdirSync18 } from "fs";
15124
- import { join as join28 } from "path";
15760
+ import { existsSync as existsSync32, readFileSync as readFileSync21, writeFileSync as writeFileSync19, mkdirSync as mkdirSync20 } from "fs";
15761
+ import { join as join31 } from "path";
15125
15762
  var PLUGINS_DIR = ".skillkit/plugins";
15126
15763
  var PLUGINS_CONFIG_FILE = "plugins.json";
15127
15764
  var PluginManager = class {
@@ -15362,22 +15999,22 @@ var PluginManager = class {
15362
15999
  }
15363
16000
  // Private helpers
15364
16001
  loadState() {
15365
- const statePath = join28(this.projectPath, PLUGINS_DIR, PLUGINS_CONFIG_FILE);
15366
- if (existsSync29(statePath)) {
16002
+ const statePath = join31(this.projectPath, PLUGINS_DIR, PLUGINS_CONFIG_FILE);
16003
+ if (existsSync32(statePath)) {
15367
16004
  try {
15368
- return JSON.parse(readFileSync19(statePath, "utf-8"));
16005
+ return JSON.parse(readFileSync21(statePath, "utf-8"));
15369
16006
  } catch {
15370
16007
  }
15371
16008
  }
15372
16009
  return { version: 1, plugins: {} };
15373
16010
  }
15374
16011
  saveState() {
15375
- const pluginsDir = join28(this.projectPath, PLUGINS_DIR);
15376
- if (!existsSync29(pluginsDir)) {
15377
- mkdirSync18(pluginsDir, { recursive: true });
16012
+ const pluginsDir = join31(this.projectPath, PLUGINS_DIR);
16013
+ if (!existsSync32(pluginsDir)) {
16014
+ mkdirSync20(pluginsDir, { recursive: true });
15378
16015
  }
15379
- const statePath = join28(pluginsDir, PLUGINS_CONFIG_FILE);
15380
- writeFileSync17(statePath, JSON.stringify(this.state, null, 2), "utf-8");
16016
+ const statePath = join31(pluginsDir, PLUGINS_CONFIG_FILE);
16017
+ writeFileSync19(statePath, JSON.stringify(this.state, null, 2), "utf-8");
15381
16018
  }
15382
16019
  createContext() {
15383
16020
  return {
@@ -15402,15 +16039,15 @@ function createPluginManager(projectPath) {
15402
16039
  }
15403
16040
 
15404
16041
  // src/plugins/loader.ts
15405
- import { existsSync as existsSync30, readFileSync as readFileSync20, readdirSync as readdirSync7, statSync as statSync4 } from "fs";
15406
- import { join as join29, extname, basename as basename13, isAbsolute } from "path";
16042
+ import { existsSync as existsSync33, readFileSync as readFileSync22, readdirSync as readdirSync8, statSync as statSync4 } from "fs";
16043
+ import { join as join32, extname, basename as basename13, isAbsolute } from "path";
15407
16044
  import { pathToFileURL } from "url";
15408
16045
  var PluginLoader = class {
15409
16046
  /**
15410
16047
  * Load a plugin from a file path
15411
16048
  */
15412
16049
  async loadFromFile(filePath) {
15413
- if (!existsSync30(filePath)) {
16050
+ if (!existsSync33(filePath)) {
15414
16051
  throw new Error(`Plugin file not found: ${filePath}`);
15415
16052
  }
15416
16053
  const ext = extname(filePath);
@@ -15452,11 +16089,11 @@ var PluginLoader = class {
15452
16089
  * Load a plugin from a JSON definition (for simple plugins)
15453
16090
  */
15454
16091
  loadFromJson(jsonPath) {
15455
- if (!existsSync30(jsonPath)) {
16092
+ if (!existsSync33(jsonPath)) {
15456
16093
  throw new Error(`Plugin JSON not found: ${jsonPath}`);
15457
16094
  }
15458
16095
  try {
15459
- const content = readFileSync20(jsonPath, "utf-8");
16096
+ const content = readFileSync22(jsonPath, "utf-8");
15460
16097
  const data = JSON.parse(content);
15461
16098
  if (!data.metadata) {
15462
16099
  throw new Error("Invalid plugin JSON: missing metadata");
@@ -15475,13 +16112,13 @@ var PluginLoader = class {
15475
16112
  * Scan a directory for plugins
15476
16113
  */
15477
16114
  async scanDirectory(dirPath) {
15478
- if (!existsSync30(dirPath)) {
16115
+ if (!existsSync33(dirPath)) {
15479
16116
  return [];
15480
16117
  }
15481
16118
  const plugins = [];
15482
- const entries = readdirSync7(dirPath);
16119
+ const entries = readdirSync8(dirPath);
15483
16120
  for (const entry of entries) {
15484
- const fullPath = join29(dirPath, entry);
16121
+ const fullPath = join32(dirPath, entry);
15485
16122
  let stat;
15486
16123
  try {
15487
16124
  stat = statSync4(fullPath);
@@ -15489,11 +16126,11 @@ var PluginLoader = class {
15489
16126
  continue;
15490
16127
  }
15491
16128
  if (stat.isDirectory()) {
15492
- const pkgPath = join29(fullPath, "package.json");
15493
- const pluginPath = join29(fullPath, "plugin.json");
15494
- if (existsSync30(pkgPath)) {
16129
+ const pkgPath = join32(fullPath, "package.json");
16130
+ const pluginPath = join32(fullPath, "plugin.json");
16131
+ if (existsSync33(pkgPath)) {
15495
16132
  try {
15496
- const pkg = JSON.parse(readFileSync20(pkgPath, "utf-8"));
16133
+ const pkg = JSON.parse(readFileSync22(pkgPath, "utf-8"));
15497
16134
  if ((pkg.skillkitPlugin || pkg.keywords?.includes("skillkit-plugin")) && pkg.name && typeof pkg.name === "string" && pkg.version && typeof pkg.version === "string") {
15498
16135
  plugins.push({
15499
16136
  name: pkg.name,
@@ -15505,9 +16142,9 @@ var PluginLoader = class {
15505
16142
  }
15506
16143
  } catch {
15507
16144
  }
15508
- } else if (existsSync30(pluginPath)) {
16145
+ } else if (existsSync33(pluginPath)) {
15509
16146
  try {
15510
- const data = JSON.parse(readFileSync20(pluginPath, "utf-8"));
16147
+ const data = JSON.parse(readFileSync22(pluginPath, "utf-8"));
15511
16148
  if (data.metadata && data.metadata.name && typeof data.metadata.name === "string" && data.metadata.version && typeof data.metadata.version === "string") {
15512
16149
  plugins.push(data.metadata);
15513
16150
  }
@@ -15595,12 +16232,12 @@ async function loadPlugin(source) {
15595
16232
  async function loadPluginsFromDirectory(dirPath) {
15596
16233
  const loader = new PluginLoader();
15597
16234
  const plugins = [];
15598
- if (!existsSync30(dirPath)) {
16235
+ if (!existsSync33(dirPath)) {
15599
16236
  return plugins;
15600
16237
  }
15601
- const entries = readdirSync7(dirPath);
16238
+ const entries = readdirSync8(dirPath);
15602
16239
  for (const entry of entries) {
15603
- const fullPath = join29(dirPath, entry);
16240
+ const fullPath = join32(dirPath, entry);
15604
16241
  let stat;
15605
16242
  try {
15606
16243
  stat = statSync4(fullPath);
@@ -15609,20 +16246,20 @@ async function loadPluginsFromDirectory(dirPath) {
15609
16246
  }
15610
16247
  try {
15611
16248
  if (stat.isDirectory()) {
15612
- const indexMjsPath = join29(fullPath, "index.mjs");
15613
- const indexPath = join29(fullPath, "index.js");
15614
- const mainMjsPath = join29(fullPath, "plugin.mjs");
15615
- const mainPath = join29(fullPath, "plugin.js");
15616
- const jsonPath = join29(fullPath, "plugin.json");
15617
- if (existsSync30(indexMjsPath)) {
16249
+ const indexMjsPath = join32(fullPath, "index.mjs");
16250
+ const indexPath = join32(fullPath, "index.js");
16251
+ const mainMjsPath = join32(fullPath, "plugin.mjs");
16252
+ const mainPath = join32(fullPath, "plugin.js");
16253
+ const jsonPath = join32(fullPath, "plugin.json");
16254
+ if (existsSync33(indexMjsPath)) {
15618
16255
  plugins.push(await loader.loadFromFile(indexMjsPath));
15619
- } else if (existsSync30(indexPath)) {
16256
+ } else if (existsSync33(indexPath)) {
15620
16257
  plugins.push(await loader.loadFromFile(indexPath));
15621
- } else if (existsSync30(mainMjsPath)) {
16258
+ } else if (existsSync33(mainMjsPath)) {
15622
16259
  plugins.push(await loader.loadFromFile(mainMjsPath));
15623
- } else if (existsSync30(mainPath)) {
16260
+ } else if (existsSync33(mainPath)) {
15624
16261
  plugins.push(await loader.loadFromFile(mainPath));
15625
- } else if (existsSync30(jsonPath)) {
16262
+ } else if (existsSync33(jsonPath)) {
15626
16263
  plugins.push(loader.loadFromJson(jsonPath));
15627
16264
  }
15628
16265
  } else if (stat.isFile()) {
@@ -15641,17 +16278,17 @@ async function loadPluginsFromDirectory(dirPath) {
15641
16278
  }
15642
16279
 
15643
16280
  // src/methodology/manager.ts
15644
- import { existsSync as existsSync33, readFileSync as readFileSync23, writeFileSync as writeFileSync18, mkdirSync as mkdirSync19 } from "fs";
15645
- import { join as join32, dirname as dirname11 } from "path";
16281
+ import { existsSync as existsSync36, readFileSync as readFileSync25, writeFileSync as writeFileSync20, mkdirSync as mkdirSync21 } from "fs";
16282
+ import { join as join35, dirname as dirname11 } from "path";
15646
16283
 
15647
16284
  // src/methodology/loader.ts
15648
- import { existsSync as existsSync32, readFileSync as readFileSync22, readdirSync as readdirSync9, statSync as statSync6 } from "fs";
15649
- import { join as join31, dirname as dirname10 } from "path";
16285
+ import { existsSync as existsSync35, readFileSync as readFileSync24, readdirSync as readdirSync10, statSync as statSync6 } from "fs";
16286
+ import { join as join34, dirname as dirname10 } from "path";
15650
16287
  import { fileURLToPath } from "url";
15651
16288
 
15652
16289
  // src/methodology/validator.ts
15653
- import { existsSync as existsSync31, readFileSync as readFileSync21, readdirSync as readdirSync8, statSync as statSync5 } from "fs";
15654
- import { join as join30 } from "path";
16290
+ import { existsSync as existsSync34, readFileSync as readFileSync23, readdirSync as readdirSync9, statSync as statSync5 } from "fs";
16291
+ import { join as join33 } from "path";
15655
16292
  function validatePackManifest(pack) {
15656
16293
  const errors = [];
15657
16294
  const warnings = [];
@@ -15801,15 +16438,15 @@ function validateSkillContent(content) {
15801
16438
  function validatePackDirectory(packPath) {
15802
16439
  const errors = [];
15803
16440
  const warnings = [];
15804
- if (!existsSync31(packPath)) {
16441
+ if (!existsSync34(packPath)) {
15805
16442
  errors.push({
15806
16443
  code: "DIR_NOT_FOUND",
15807
16444
  message: `Pack directory not found: ${packPath}`
15808
16445
  });
15809
16446
  return { valid: false, errors, warnings };
15810
16447
  }
15811
- const manifestPath = join30(packPath, "pack.json");
15812
- if (!existsSync31(manifestPath)) {
16448
+ const manifestPath = join33(packPath, "pack.json");
16449
+ if (!existsSync34(manifestPath)) {
15813
16450
  errors.push({
15814
16451
  code: "MANIFEST_NOT_FOUND",
15815
16452
  message: "Pack must have a pack.json manifest",
@@ -15819,7 +16456,7 @@ function validatePackDirectory(packPath) {
15819
16456
  }
15820
16457
  let manifest;
15821
16458
  try {
15822
- const raw = readFileSync21(manifestPath, "utf-8");
16459
+ const raw = readFileSync23(manifestPath, "utf-8");
15823
16460
  manifest = JSON.parse(raw);
15824
16461
  const manifestResult = validatePackManifest(manifest);
15825
16462
  errors.push(...manifestResult.errors);
@@ -15834,8 +16471,8 @@ function validatePackDirectory(packPath) {
15834
16471
  }
15835
16472
  if (manifest.skills) {
15836
16473
  for (const skillName of manifest.skills) {
15837
- const skillDir = join30(packPath, skillName);
15838
- if (!existsSync31(skillDir)) {
16474
+ const skillDir = join33(packPath, skillName);
16475
+ if (!existsSync34(skillDir)) {
15839
16476
  errors.push({
15840
16477
  code: "SKILL_DIR_NOT_FOUND",
15841
16478
  message: `Skill directory not found: ${skillName}`,
@@ -15851,8 +16488,8 @@ function validatePackDirectory(packPath) {
15851
16488
  });
15852
16489
  continue;
15853
16490
  }
15854
- const skillFile = join30(skillDir, "SKILL.md");
15855
- if (!existsSync31(skillFile)) {
16491
+ const skillFile = join33(skillDir, "SKILL.md");
16492
+ if (!existsSync34(skillFile)) {
15856
16493
  errors.push({
15857
16494
  code: "SKILL_FILE_NOT_FOUND",
15858
16495
  message: `Skill must have a SKILL.md file: ${skillName}`,
@@ -15860,7 +16497,7 @@ function validatePackDirectory(packPath) {
15860
16497
  });
15861
16498
  continue;
15862
16499
  }
15863
- const skillContent = readFileSync21(skillFile, "utf-8");
16500
+ const skillContent = readFileSync23(skillFile, "utf-8");
15864
16501
  const skillResult = validateSkillContent(skillContent);
15865
16502
  for (const err of skillResult.errors) {
15866
16503
  errors.push({
@@ -15884,15 +16521,15 @@ function validatePackDirectory(packPath) {
15884
16521
  }
15885
16522
  function validateBuiltinPacks(packsDir) {
15886
16523
  const results = /* @__PURE__ */ new Map();
15887
- if (!existsSync31(packsDir)) {
16524
+ if (!existsSync34(packsDir)) {
15888
16525
  return results;
15889
16526
  }
15890
- const packDirs = readdirSync8(packsDir).filter((name) => {
15891
- const packPath = join30(packsDir, name);
16527
+ const packDirs = readdirSync9(packsDir).filter((name) => {
16528
+ const packPath = join33(packsDir, name);
15892
16529
  return statSync5(packPath).isDirectory();
15893
16530
  });
15894
16531
  for (const packName of packDirs) {
15895
- const packPath = join30(packsDir, packName);
16532
+ const packPath = join33(packsDir, packName);
15896
16533
  results.set(packName, validatePackDirectory(packPath));
15897
16534
  }
15898
16535
  return results;
@@ -15951,7 +16588,7 @@ function extractSkillMetadata(content) {
15951
16588
  // src/methodology/loader.ts
15952
16589
  var __filename = fileURLToPath(import.meta.url);
15953
16590
  var __dirname = dirname10(__filename);
15954
- var BUILTIN_PACKS_DIR = join31(__dirname, "packs");
16591
+ var BUILTIN_PACKS_DIR = join34(__dirname, "packs");
15955
16592
  var MethodologyLoader = class {
15956
16593
  packsDir;
15957
16594
  loadedPacks = /* @__PURE__ */ new Map();
@@ -15964,11 +16601,11 @@ var MethodologyLoader = class {
15964
16601
  */
15965
16602
  async loadAllPacks() {
15966
16603
  const packs = [];
15967
- if (!existsSync32(this.packsDir)) {
16604
+ if (!existsSync35(this.packsDir)) {
15968
16605
  return packs;
15969
16606
  }
15970
- const packDirs = readdirSync9(this.packsDir).filter((name) => {
15971
- const packPath = join31(this.packsDir, name);
16607
+ const packDirs = readdirSync10(this.packsDir).filter((name) => {
16608
+ const packPath = join34(this.packsDir, name);
15972
16609
  return statSync6(packPath).isDirectory();
15973
16610
  });
15974
16611
  for (const packName of packDirs) {
@@ -15989,9 +16626,9 @@ var MethodologyLoader = class {
15989
16626
  if (this.loadedPacks.has(packName)) {
15990
16627
  return this.loadedPacks.get(packName);
15991
16628
  }
15992
- const packPath = join31(this.packsDir, packName);
15993
- const manifestPath = join31(packPath, "pack.json");
15994
- if (!existsSync32(manifestPath)) {
16629
+ const packPath = join34(this.packsDir, packName);
16630
+ const manifestPath = join34(packPath, "pack.json");
16631
+ if (!existsSync35(manifestPath)) {
15995
16632
  return null;
15996
16633
  }
15997
16634
  const validation = validatePackDirectory(packPath);
@@ -16001,7 +16638,7 @@ var MethodologyLoader = class {
16001
16638
  );
16002
16639
  }
16003
16640
  const manifest = JSON.parse(
16004
- readFileSync22(manifestPath, "utf-8")
16641
+ readFileSync24(manifestPath, "utf-8")
16005
16642
  );
16006
16643
  this.loadedPacks.set(packName, manifest);
16007
16644
  return manifest;
@@ -16031,11 +16668,11 @@ var MethodologyLoader = class {
16031
16668
  if (this.loadedSkills.has(skillId)) {
16032
16669
  return this.loadedSkills.get(skillId);
16033
16670
  }
16034
- const skillPath = join31(this.packsDir, packName, skillName, "SKILL.md");
16035
- if (!existsSync32(skillPath)) {
16671
+ const skillPath = join34(this.packsDir, packName, skillName, "SKILL.md");
16672
+ if (!existsSync35(skillPath)) {
16036
16673
  return null;
16037
16674
  }
16038
- const content = readFileSync22(skillPath, "utf-8");
16675
+ const content = readFileSync24(skillPath, "utf-8");
16039
16676
  const rawMetadata = extractSkillMetadata(content);
16040
16677
  const metadata = {
16041
16678
  triggers: rawMetadata.triggers,
@@ -16114,9 +16751,9 @@ var MethodologyLoader = class {
16114
16751
  * Check if a pack exists
16115
16752
  */
16116
16753
  packExists(packName) {
16117
- const packPath = join31(this.packsDir, packName);
16118
- const manifestPath = join31(packPath, "pack.json");
16119
- return existsSync32(manifestPath);
16754
+ const packPath = join34(this.packsDir, packName);
16755
+ const manifestPath = join34(packPath, "pack.json");
16756
+ return existsSync35(manifestPath);
16120
16757
  }
16121
16758
  /**
16122
16759
  * Clear cache
@@ -16482,10 +17119,10 @@ var MethodologyManager = class {
16482
17119
  }
16483
17120
  // Private helpers
16484
17121
  loadState() {
16485
- const statePath = join32(this.projectPath, METHODOLOGY_STATE_FILE);
16486
- if (existsSync33(statePath)) {
17122
+ const statePath = join35(this.projectPath, METHODOLOGY_STATE_FILE);
17123
+ if (existsSync36(statePath)) {
16487
17124
  try {
16488
- return JSON.parse(readFileSync23(statePath, "utf-8"));
17125
+ return JSON.parse(readFileSync25(statePath, "utf-8"));
16489
17126
  } catch {
16490
17127
  }
16491
17128
  }
@@ -16496,21 +17133,21 @@ var MethodologyManager = class {
16496
17133
  };
16497
17134
  }
16498
17135
  saveState() {
16499
- const statePath = join32(this.projectPath, METHODOLOGY_STATE_FILE);
17136
+ const statePath = join35(this.projectPath, METHODOLOGY_STATE_FILE);
16500
17137
  const dir = dirname11(statePath);
16501
- if (!existsSync33(dir)) {
16502
- mkdirSync19(dir, { recursive: true });
17138
+ if (!existsSync36(dir)) {
17139
+ mkdirSync21(dir, { recursive: true });
16503
17140
  }
16504
- writeFileSync18(statePath, JSON.stringify(this.state, null, 2), "utf-8");
17141
+ writeFileSync20(statePath, JSON.stringify(this.state, null, 2), "utf-8");
16505
17142
  }
16506
17143
  async installSkillLocally(skill) {
16507
- const skillsDir = join32(this.projectPath, ".skillkit", "methodology", "skills");
16508
- const skillDir = join32(skillsDir, skill.pack, skill.id.split("/")[1]);
16509
- if (!existsSync33(skillDir)) {
16510
- mkdirSync19(skillDir, { recursive: true });
17144
+ const skillsDir = join35(this.projectPath, ".skillkit", "methodology", "skills");
17145
+ const skillDir = join35(skillsDir, skill.pack, skill.id.split("/")[1]);
17146
+ if (!existsSync36(skillDir)) {
17147
+ mkdirSync21(skillDir, { recursive: true });
16511
17148
  }
16512
- const targetPath = join32(skillDir, "SKILL.md");
16513
- writeFileSync18(targetPath, skill.content, "utf-8");
17149
+ const targetPath = join35(skillDir, "SKILL.md");
17150
+ writeFileSync20(targetPath, skill.content, "utf-8");
16514
17151
  }
16515
17152
  async removeSkillLocally(_skillId) {
16516
17153
  }
@@ -16538,9 +17175,9 @@ var MethodologyManager = class {
16538
17175
  if (!agentDir) {
16539
17176
  throw new Error(`Unknown agent: ${agent}`);
16540
17177
  }
16541
- const skillsDir = join32(this.projectPath, agentDir);
16542
- if (!existsSync33(skillsDir)) {
16543
- mkdirSync19(skillsDir, { recursive: true });
17178
+ const skillsDir = join35(this.projectPath, agentDir);
17179
+ if (!existsSync36(skillsDir)) {
17180
+ mkdirSync21(skillsDir, { recursive: true });
16544
17181
  }
16545
17182
  const skillName = skillId.split("/")[1];
16546
17183
  let filename;
@@ -16551,8 +17188,8 @@ var MethodologyManager = class {
16551
17188
  } else {
16552
17189
  filename = `${skillName}.md`;
16553
17190
  }
16554
- const targetPath = join32(skillsDir, filename);
16555
- writeFileSync18(targetPath, content, "utf-8");
17191
+ const targetPath = join35(skillsDir, filename);
17192
+ writeFileSync20(targetPath, content, "utf-8");
16556
17193
  }
16557
17194
  detectAgents() {
16558
17195
  const agents = [];
@@ -16575,7 +17212,7 @@ var MethodologyManager = class {
16575
17212
  ["windsurf", ".windsurf"]
16576
17213
  ];
16577
17214
  for (const [agent, dir] of agentDirs) {
16578
- if (existsSync33(join32(this.projectPath, dir))) {
17215
+ if (existsSync36(join35(this.projectPath, dir))) {
16579
17216
  agents.push(agent);
16580
17217
  }
16581
17218
  }
@@ -16588,8 +17225,8 @@ function createMethodologyManager(options) {
16588
17225
  }
16589
17226
 
16590
17227
  // src/hooks/manager.ts
16591
- import { existsSync as existsSync34, readFileSync as readFileSync24, writeFileSync as writeFileSync19, mkdirSync as mkdirSync20 } from "fs";
16592
- import { join as join33, dirname as dirname12 } from "path";
17228
+ import { existsSync as existsSync37, readFileSync as readFileSync26, writeFileSync as writeFileSync21, mkdirSync as mkdirSync22 } from "fs";
17229
+ import { join as join36, dirname as dirname12 } from "path";
16593
17230
  import { randomUUID as randomUUID11 } from "crypto";
16594
17231
  import { minimatch } from "minimatch";
16595
17232
  var DEFAULT_CONFIG_PATH = ".skillkit/hooks.json";
@@ -16600,7 +17237,7 @@ var HookManager = class {
16600
17237
  constructor(options) {
16601
17238
  this.options = {
16602
17239
  projectPath: options.projectPath,
16603
- configPath: options.configPath || join33(options.projectPath, DEFAULT_CONFIG_PATH),
17240
+ configPath: options.configPath || join36(options.projectPath, DEFAULT_CONFIG_PATH),
16604
17241
  autoLoad: options.autoLoad ?? true,
16605
17242
  defaultInjectionMode: options.defaultInjectionMode || "reference"
16606
17243
  };
@@ -16740,11 +17377,11 @@ var HookManager = class {
16740
17377
  * Load hooks from config file
16741
17378
  */
16742
17379
  load() {
16743
- if (!existsSync34(this.options.configPath)) {
17380
+ if (!existsSync37(this.options.configPath)) {
16744
17381
  return;
16745
17382
  }
16746
17383
  try {
16747
- const content = readFileSync24(this.options.configPath, "utf-8");
17384
+ const content = readFileSync26(this.options.configPath, "utf-8");
16748
17385
  const config = JSON.parse(content);
16749
17386
  this.hooks.clear();
16750
17387
  for (const hook of config.hooks) {
@@ -16772,10 +17409,10 @@ var HookManager = class {
16772
17409
  }
16773
17410
  };
16774
17411
  const dir = dirname12(this.options.configPath);
16775
- if (!existsSync34(dir)) {
16776
- mkdirSync20(dir, { recursive: true });
17412
+ if (!existsSync37(dir)) {
17413
+ mkdirSync22(dir, { recursive: true });
16777
17414
  }
16778
- writeFileSync19(this.options.configPath, JSON.stringify(config, null, 2));
17415
+ writeFileSync21(this.options.configPath, JSON.stringify(config, null, 2));
16779
17416
  }
16780
17417
  /**
16781
17418
  * Generate agent-specific hook configuration
@@ -17017,7 +17654,7 @@ function createHookManager(options) {
17017
17654
 
17018
17655
  // src/hooks/triggers.ts
17019
17656
  import { watch } from "fs";
17020
- import { join as join34, relative as relative2 } from "path";
17657
+ import { join as join37, relative as relative2 } from "path";
17021
17658
  function debounce(fn, delay) {
17022
17659
  let timeoutId = null;
17023
17660
  return (...args) => {
@@ -17202,7 +17839,7 @@ var SkillTriggerEngine = class {
17202
17839
  { recursive: true },
17203
17840
  debounce((eventType, filename) => {
17204
17841
  if (!filename) return;
17205
- const relativePath = relative2(this.options.projectPath, join34(this.options.projectPath, filename));
17842
+ const relativePath = relative2(this.options.projectPath, join37(this.options.projectPath, filename));
17206
17843
  if (this.shouldIgnore(relativePath)) return;
17207
17844
  if (eventType === "rename") {
17208
17845
  this.triggerFileCreate(relativePath);
@@ -19645,15 +20282,194 @@ var shellExecutor = async (step, _task, _plan) => {
19645
20282
  error: `Expected output "${step.expectedOutput}" not found`
19646
20283
  };
19647
20284
  }
19648
- return { success: true, output };
19649
- } catch (error) {
19650
- return {
19651
- success: false,
19652
- output: "",
19653
- error: error.message
20285
+ return { success: true, output };
20286
+ } catch (error) {
20287
+ return {
20288
+ success: false,
20289
+ output: "",
20290
+ error: error.message
20291
+ };
20292
+ }
20293
+ };
20294
+
20295
+ // src/plan/issue-planner.ts
20296
+ import { execFileSync } from "child_process";
20297
+ var LABEL_TAG_MAP = {
20298
+ bug: "fix",
20299
+ fix: "fix",
20300
+ enhancement: "feature",
20301
+ feature: "feature",
20302
+ documentation: "docs",
20303
+ docs: "docs",
20304
+ refactor: "refactor",
20305
+ refactoring: "refactor",
20306
+ test: "test",
20307
+ testing: "test",
20308
+ security: "security",
20309
+ performance: "performance",
20310
+ "good first issue": "beginner",
20311
+ chore: "chore",
20312
+ maintenance: "chore"
20313
+ };
20314
+ var FILE_PATH_REGEX = /`([a-zA-Z0-9_./\-]+\.[a-zA-Z0-9]+)`/g;
20315
+ var IssuePlanner = class {
20316
+ parseIssueRef(ref) {
20317
+ const urlMatch = ref.match(
20318
+ /github\.com\/([^/]+)\/([^/]+)\/issues\/(\d+)/
20319
+ );
20320
+ if (urlMatch) {
20321
+ return {
20322
+ owner: urlMatch[1],
20323
+ repo: urlMatch[2],
20324
+ number: parseInt(urlMatch[3], 10)
20325
+ };
20326
+ }
20327
+ const fullMatch = ref.match(/^([^/]+)\/([^#]+)#(\d+)$/);
20328
+ if (fullMatch) {
20329
+ return {
20330
+ owner: fullMatch[1],
20331
+ repo: fullMatch[2],
20332
+ number: parseInt(fullMatch[3], 10)
20333
+ };
20334
+ }
20335
+ const shortMatch = ref.match(/^#?(\d+)$/);
20336
+ if (shortMatch) {
20337
+ return { number: parseInt(shortMatch[1], 10) };
20338
+ }
20339
+ throw new Error(
20340
+ `Invalid issue reference: "${ref}". Use #123, owner/repo#123, or a GitHub URL.`
20341
+ );
20342
+ }
20343
+ fetchIssue(ref) {
20344
+ const parsed = this.parseIssueRef(ref);
20345
+ const args = [
20346
+ "issue",
20347
+ "view",
20348
+ String(parsed.number),
20349
+ "--json",
20350
+ "number,title,body,labels,assignees,url,state"
20351
+ ];
20352
+ if (parsed.owner && parsed.repo) {
20353
+ args.push("--repo", `${parsed.owner}/${parsed.repo}`);
20354
+ }
20355
+ const result = execFileSync("gh", args, {
20356
+ encoding: "utf-8",
20357
+ timeout: 15e3
20358
+ });
20359
+ let data;
20360
+ try {
20361
+ data = JSON.parse(result);
20362
+ } catch {
20363
+ throw new Error(`Failed to parse GitHub CLI response for issue ${parsed.number}`);
20364
+ }
20365
+ return {
20366
+ number: data.number,
20367
+ title: data.title,
20368
+ body: data.body || "",
20369
+ labels: (data.labels || []).map((l) => l.name),
20370
+ assignees: (data.assignees || []).map((a) => a.login),
20371
+ url: data.url,
20372
+ state: data.state
20373
+ };
20374
+ }
20375
+ extractTasksFromBody(body) {
20376
+ const tasks = [];
20377
+ const lines = body.split("\n");
20378
+ for (const line of lines) {
20379
+ const match = line.match(/^[\s]*-\s*\[([ xX])\]\s+(.+)$/);
20380
+ if (match) {
20381
+ tasks.push({
20382
+ name: match[2].trim(),
20383
+ checked: match[1] !== " "
20384
+ });
20385
+ }
20386
+ }
20387
+ return tasks;
20388
+ }
20389
+ extractFileMentions(text) {
20390
+ const files = /* @__PURE__ */ new Set();
20391
+ let match;
20392
+ const regex = new RegExp(FILE_PATH_REGEX.source, "g");
20393
+ while ((match = regex.exec(text)) !== null) {
20394
+ const path4 = match[1];
20395
+ if (path4.includes("/") || path4.includes(".")) {
20396
+ files.add(path4);
20397
+ }
20398
+ }
20399
+ return [...files];
20400
+ }
20401
+ inferLabelsToTags(labels) {
20402
+ const tags = [];
20403
+ for (const label of labels) {
20404
+ const tag = LABEL_TAG_MAP[label.toLowerCase()];
20405
+ if (tag && !tags.includes(tag)) {
20406
+ tags.push(tag);
20407
+ }
20408
+ }
20409
+ return tags;
20410
+ }
20411
+ generatePlan(issue, options) {
20412
+ const agent = options?.agent || "claude-code";
20413
+ const includeTests = options?.includeTests !== false;
20414
+ const bodyFirstParagraph = issue.body.split("\n\n")[0]?.trim() || issue.title;
20415
+ const generator = new PlanGenerator({
20416
+ includeTests,
20417
+ includeCommits: true,
20418
+ techStack: options?.techStack
20419
+ });
20420
+ const plan = generator.createPlan(
20421
+ `Issue #${issue.number}: ${issue.title}`,
20422
+ bodyFirstParagraph
20423
+ );
20424
+ plan.tags = this.inferLabelsToTags(issue.labels);
20425
+ const checklist = this.extractTasksFromBody(issue.body);
20426
+ const allFileMentions = this.extractFileMentions(issue.body);
20427
+ if (checklist.length > 0) {
20428
+ for (const item of checklist) {
20429
+ const taskFiles = this.extractFileMentions(item.name);
20430
+ const files = {};
20431
+ if (taskFiles.length > 0) {
20432
+ files.modify = taskFiles;
20433
+ }
20434
+ const task = generator.addTask(plan, item.name, {
20435
+ files,
20436
+ tags: item.checked ? ["done"] : void 0,
20437
+ steps: [
20438
+ { type: "implement", description: item.name },
20439
+ ...includeTests ? [{ type: "test", description: `Write tests for ${item.name}` }] : []
20440
+ ]
20441
+ });
20442
+ if (item.checked) {
20443
+ task.status = "completed";
20444
+ }
20445
+ }
20446
+ } else {
20447
+ const files = {};
20448
+ if (allFileMentions.length > 0) {
20449
+ files.modify = allFileMentions;
20450
+ }
20451
+ generator.addTask(plan, issue.title, {
20452
+ description: bodyFirstParagraph,
20453
+ files,
20454
+ steps: [
20455
+ { type: "implement", description: issue.title },
20456
+ ...includeTests ? [{ type: "test", description: `Write tests for ${issue.title}` }] : []
20457
+ ]
20458
+ });
20459
+ }
20460
+ plan.metadata = {
20461
+ issueNumber: issue.number,
20462
+ issueUrl: issue.url,
20463
+ issueLabels: issue.labels,
20464
+ agent,
20465
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString()
19654
20466
  };
20467
+ return plan;
19655
20468
  }
19656
20469
  };
20470
+ function createIssuePlanner() {
20471
+ return new IssuePlanner();
20472
+ }
19657
20473
 
19658
20474
  // src/commands/registry.ts
19659
20475
  var CommandRegistry = class {
@@ -22505,8 +23321,8 @@ Source: ${doc.url}`;
22505
23321
  };
22506
23322
 
22507
23323
  // src/ai/context/codebase-source.ts
22508
- import { existsSync as existsSync35, readdirSync as readdirSync10, readFileSync as readFileSync25, statSync as statSync7 } from "fs";
22509
- import { join as join35, extname as extname2, basename as basename14 } from "path";
23324
+ import { existsSync as existsSync38, readdirSync as readdirSync11, readFileSync as readFileSync27, statSync as statSync7 } from "fs";
23325
+ import { join as join38, extname as extname2, basename as basename14 } from "path";
22510
23326
  var CodebaseSource = class {
22511
23327
  name = "codebase";
22512
23328
  displayName = "Local Codebase";
@@ -22534,7 +23350,7 @@ var CodebaseSource = class {
22534
23350
  return chunks;
22535
23351
  }
22536
23352
  async isAvailable() {
22537
- return existsSync35(this.projectPath);
23353
+ return existsSync38(this.projectPath);
22538
23354
  }
22539
23355
  async analyzeCodebase(basePath, query) {
22540
23356
  const patterns = [];
@@ -22551,10 +23367,10 @@ var CodebaseSource = class {
22551
23367
  }
22552
23368
  async detectFrameworks(basePath) {
22553
23369
  const patterns = [];
22554
- const packageJsonPath = join35(basePath, "package.json");
22555
- if (existsSync35(packageJsonPath)) {
23370
+ const packageJsonPath = join38(basePath, "package.json");
23371
+ if (existsSync38(packageJsonPath)) {
22556
23372
  try {
22557
- const content = readFileSync25(packageJsonPath, "utf-8");
23373
+ const content = readFileSync27(packageJsonPath, "utf-8");
22558
23374
  const pkg = JSON.parse(content);
22559
23375
  const deps = { ...pkg.dependencies, ...pkg.devDependencies };
22560
23376
  const frameworks = [
@@ -22581,8 +23397,8 @@ var CodebaseSource = class {
22581
23397
  } catch {
22582
23398
  }
22583
23399
  }
22584
- const pyprojectPath = join35(basePath, "pyproject.toml");
22585
- if (existsSync35(pyprojectPath)) {
23400
+ const pyprojectPath = join38(basePath, "pyproject.toml");
23401
+ if (existsSync38(pyprojectPath)) {
22586
23402
  patterns.push({
22587
23403
  type: "framework",
22588
23404
  name: "Python",
@@ -22591,8 +23407,8 @@ var CodebaseSource = class {
22591
23407
  relevance: 0.7
22592
23408
  });
22593
23409
  }
22594
- const cargoPath = join35(basePath, "Cargo.toml");
22595
- if (existsSync35(cargoPath)) {
23410
+ const cargoPath = join38(basePath, "Cargo.toml");
23411
+ if (existsSync38(cargoPath)) {
22596
23412
  patterns.push({
22597
23413
  type: "framework",
22598
23414
  name: "Rust",
@@ -22601,8 +23417,8 @@ var CodebaseSource = class {
22601
23417
  relevance: 0.7
22602
23418
  });
22603
23419
  }
22604
- const goModPath = join35(basePath, "go.mod");
22605
- if (existsSync35(goModPath)) {
23420
+ const goModPath = join38(basePath, "go.mod");
23421
+ if (existsSync38(goModPath)) {
22606
23422
  patterns.push({
22607
23423
  type: "framework",
22608
23424
  name: "Go",
@@ -22615,10 +23431,10 @@ var CodebaseSource = class {
22615
23431
  }
22616
23432
  async detectTestingSetup(basePath) {
22617
23433
  const patterns = [];
22618
- const packageJsonPath = join35(basePath, "package.json");
22619
- if (existsSync35(packageJsonPath)) {
23434
+ const packageJsonPath = join38(basePath, "package.json");
23435
+ if (existsSync38(packageJsonPath)) {
22620
23436
  try {
22621
- const content = readFileSync25(packageJsonPath, "utf-8");
23437
+ const content = readFileSync27(packageJsonPath, "utf-8");
22622
23438
  const pkg = JSON.parse(content);
22623
23439
  const deps = { ...pkg.dependencies, ...pkg.devDependencies };
22624
23440
  const testFrameworks = [
@@ -22643,10 +23459,10 @@ var CodebaseSource = class {
22643
23459
  } catch {
22644
23460
  }
22645
23461
  }
22646
- const vitestConfig = join35(basePath, "vitest.config.ts");
22647
- if (existsSync35(vitestConfig)) {
23462
+ const vitestConfig = join38(basePath, "vitest.config.ts");
23463
+ if (existsSync38(vitestConfig)) {
22648
23464
  try {
22649
- const content = readFileSync25(vitestConfig, "utf-8");
23465
+ const content = readFileSync27(vitestConfig, "utf-8");
22650
23466
  patterns.push({
22651
23467
  type: "testing",
22652
23468
  name: "Vitest Config",
@@ -22657,10 +23473,10 @@ var CodebaseSource = class {
22657
23473
  } catch {
22658
23474
  }
22659
23475
  }
22660
- const jestConfig = join35(basePath, "jest.config.js");
22661
- if (existsSync35(jestConfig)) {
23476
+ const jestConfig = join38(basePath, "jest.config.js");
23477
+ if (existsSync38(jestConfig)) {
22662
23478
  try {
22663
- const content = readFileSync25(jestConfig, "utf-8");
23479
+ const content = readFileSync27(jestConfig, "utf-8");
22664
23480
  patterns.push({
22665
23481
  type: "testing",
22666
23482
  name: "Jest Config",
@@ -22684,10 +23500,10 @@ var CodebaseSource = class {
22684
23500
  { file: "tailwind.config.ts", name: "Tailwind" }
22685
23501
  ];
22686
23502
  for (const { file, name } of configFiles) {
22687
- const filePath = join35(basePath, file);
22688
- if (existsSync35(filePath)) {
23503
+ const filePath = join38(basePath, file);
23504
+ if (existsSync38(filePath)) {
22689
23505
  try {
22690
- const content = readFileSync25(filePath, "utf-8");
23506
+ const content = readFileSync27(filePath, "utf-8");
22691
23507
  patterns.push({
22692
23508
  type: "config",
22693
23509
  name: `${name} Config`,
@@ -22706,12 +23522,12 @@ var CodebaseSource = class {
22706
23522
  const keywords = query.toLowerCase().split(/\s+/);
22707
23523
  const searchDirs = ["src", "lib", "app", "pages", "components"];
22708
23524
  for (const dir of searchDirs) {
22709
- const dirPath = join35(basePath, dir);
22710
- if (existsSync35(dirPath)) {
23525
+ const dirPath = join38(basePath, dir);
23526
+ if (existsSync38(dirPath)) {
22711
23527
  const files = this.findFilesRecursive(dirPath, [".ts", ".tsx", ".js", ".jsx", ".py", ".go", ".rs"]);
22712
23528
  for (const file of files.slice(0, 20)) {
22713
23529
  try {
22714
- const content = readFileSync25(file, "utf-8");
23530
+ const content = readFileSync27(file, "utf-8");
22715
23531
  const fileName = basename14(file).toLowerCase();
22716
23532
  const relevance = this.calculateRelevance(fileName, content, keywords);
22717
23533
  if (relevance > 0.3) {
@@ -22733,12 +23549,12 @@ var CodebaseSource = class {
22733
23549
  findFilesRecursive(dir, extensions) {
22734
23550
  const files = [];
22735
23551
  try {
22736
- const entries = readdirSync10(dir);
23552
+ const entries = readdirSync11(dir);
22737
23553
  for (const entry of entries) {
22738
23554
  if (entry.startsWith(".") || entry === "node_modules" || entry === "dist") {
22739
23555
  continue;
22740
23556
  }
22741
- const fullPath = join35(dir, entry);
23557
+ const fullPath = join38(dir, entry);
22742
23558
  try {
22743
23559
  const stat = statSync7(fullPath);
22744
23560
  if (stat.isDirectory()) {
@@ -22984,8 +23800,8 @@ This existing skill can be composed with or referenced for patterns.`;
22984
23800
  };
22985
23801
 
22986
23802
  // src/ai/context/memory-source.ts
22987
- import { existsSync as existsSync36, readFileSync as readFileSync26 } from "fs";
22988
- import { join as join36 } from "path";
23803
+ import { existsSync as existsSync39, readFileSync as readFileSync28 } from "fs";
23804
+ import { join as join39 } from "path";
22989
23805
  var MemorySource = class {
22990
23806
  name = "memory";
22991
23807
  displayName = "Memory & Learnings";
@@ -23029,8 +23845,8 @@ ${entry.pattern}`,
23029
23845
  }
23030
23846
  async isAvailable() {
23031
23847
  const claudeMdPath = this.findClaudeMd(this.projectPath);
23032
- const memoryPath = join36(this.projectPath, ".skillkit", "memory", "observations.yaml");
23033
- return existsSync36(claudeMdPath) || existsSync36(memoryPath);
23848
+ const memoryPath = join39(this.projectPath, ".skillkit", "memory", "observations.yaml");
23849
+ return existsSync39(claudeMdPath) || existsSync39(memoryPath);
23034
23850
  }
23035
23851
  async getMemoryPatterns(keywords) {
23036
23852
  const patterns = [];
@@ -23047,11 +23863,11 @@ ${entry.pattern}`,
23047
23863
  }
23048
23864
  async getLearnedEntries(basePath) {
23049
23865
  const claudeMdPath = this.findClaudeMd(basePath);
23050
- if (!existsSync36(claudeMdPath)) {
23866
+ if (!existsSync39(claudeMdPath)) {
23051
23867
  return [];
23052
23868
  }
23053
23869
  try {
23054
- const content = readFileSync26(claudeMdPath, "utf-8");
23870
+ const content = readFileSync28(claudeMdPath, "utf-8");
23055
23871
  return this.parseLearnedSection(content);
23056
23872
  } catch {
23057
23873
  return [];
@@ -23137,18 +23953,18 @@ ${obs.content}
23137
23953
  Relevance: ${obs.relevance}%`;
23138
23954
  }
23139
23955
  findClaudeMd(basePath) {
23140
- const localPath = join36(basePath, "CLAUDE.md");
23141
- if (existsSync36(localPath)) {
23956
+ const localPath = join39(basePath, "CLAUDE.md");
23957
+ if (existsSync39(localPath)) {
23142
23958
  return localPath;
23143
23959
  }
23144
23960
  const homeDir = process.env.HOME || process.env.USERPROFILE || "";
23145
- const globalPath = join36(homeDir, ".claude", "CLAUDE.md");
23146
- if (existsSync36(globalPath)) {
23961
+ const globalPath = join39(homeDir, ".claude", "CLAUDE.md");
23962
+ if (existsSync39(globalPath)) {
23147
23963
  return globalPath;
23148
23964
  }
23149
23965
  const projectKey = basePath.replace(/[\\/]/g, "-");
23150
- const projectMemoryPath = join36(homeDir, ".claude", "projects", projectKey, "memory", "MEMORY.md");
23151
- if (existsSync36(projectMemoryPath)) {
23966
+ const projectMemoryPath = join39(homeDir, ".claude", "projects", projectKey, "memory", "MEMORY.md");
23967
+ if (existsSync39(projectMemoryPath)) {
23152
23968
  return projectMemoryPath;
23153
23969
  }
23154
23970
  return localPath;
@@ -25560,8 +26376,8 @@ var CUSTOM_AGENT_FORMAT_MAP = {
25560
26376
  };
25561
26377
 
25562
26378
  // src/agents/parser.ts
25563
- import { existsSync as existsSync37, readFileSync as readFileSync27, statSync as statSync8 } from "fs";
25564
- import { join as join37, basename as basename15, extname as extname3 } from "path";
26379
+ import { existsSync as existsSync40, readFileSync as readFileSync29, statSync as statSync8 } from "fs";
26380
+ import { join as join40, basename as basename15, extname as extname3 } from "path";
25565
26381
  import { parse as parseYaml10 } from "yaml";
25566
26382
  function extractAgentFrontmatter(content) {
25567
26383
  const match = content.match(/^---\s*\n([\s\S]*?)\n---/);
@@ -25579,14 +26395,14 @@ function extractAgentContent(content) {
25579
26395
  return withoutFrontmatter.trim();
25580
26396
  }
25581
26397
  function parseAgentFile(filePath, location = "project") {
25582
- if (!existsSync37(filePath)) {
26398
+ if (!existsSync40(filePath)) {
25583
26399
  return null;
25584
26400
  }
25585
26401
  if (extname3(filePath) !== ".md") {
25586
26402
  return null;
25587
26403
  }
25588
26404
  try {
25589
- const content = readFileSync27(filePath, "utf-8");
26405
+ const content = readFileSync29(filePath, "utf-8");
25590
26406
  const rawFrontmatter = extractAgentFrontmatter(content);
25591
26407
  const agentContent = extractAgentContent(content);
25592
26408
  if (!rawFrontmatter) {
@@ -25638,16 +26454,16 @@ function parseAgentFile(filePath, location = "project") {
25638
26454
  }
25639
26455
  }
25640
26456
  function parseAgentDir(dirPath, location = "project") {
25641
- const agentMdPath = join37(dirPath, "AGENT.md");
25642
- if (existsSync37(agentMdPath)) {
26457
+ const agentMdPath = join40(dirPath, "AGENT.md");
26458
+ if (existsSync40(agentMdPath)) {
25643
26459
  const agent = parseAgentFile(agentMdPath, location);
25644
26460
  if (agent) {
25645
26461
  agent.path = dirPath;
25646
26462
  }
25647
26463
  return agent;
25648
26464
  }
25649
- const indexMdPath = join37(dirPath, "index.md");
25650
- if (existsSync37(indexMdPath)) {
26465
+ const indexMdPath = join40(dirPath, "index.md");
26466
+ if (existsSync40(indexMdPath)) {
25651
26467
  const agent = parseAgentFile(indexMdPath, location);
25652
26468
  if (agent) {
25653
26469
  agent.path = dirPath;
@@ -25657,11 +26473,11 @@ function parseAgentDir(dirPath, location = "project") {
25657
26473
  return null;
25658
26474
  }
25659
26475
  function loadAgentMetadata(metadataPath) {
25660
- if (!existsSync37(metadataPath)) {
26476
+ if (!existsSync40(metadataPath)) {
25661
26477
  return null;
25662
26478
  }
25663
26479
  try {
25664
- const content = readFileSync27(metadataPath, "utf-8");
26480
+ const content = readFileSync29(metadataPath, "utf-8");
25665
26481
  const data = JSON.parse(content);
25666
26482
  const parsed = AgentMetadata.safeParse(data);
25667
26483
  return parsed.success ? parsed.data : null;
@@ -25762,25 +26578,25 @@ function fromCanonicalAgent(canonical, _targetFormat = "claude-agent") {
25762
26578
  return lines.join("\n");
25763
26579
  }
25764
26580
  function readAgentContent(agentPath) {
25765
- if (existsSync37(agentPath) && extname3(agentPath) === ".md") {
26581
+ if (existsSync40(agentPath) && extname3(agentPath) === ".md") {
25766
26582
  try {
25767
- return readFileSync27(agentPath, "utf-8");
26583
+ return readFileSync29(agentPath, "utf-8");
25768
26584
  } catch {
25769
26585
  return null;
25770
26586
  }
25771
26587
  }
25772
- const agentMdPath = join37(agentPath, "AGENT.md");
25773
- if (existsSync37(agentMdPath)) {
26588
+ const agentMdPath = join40(agentPath, "AGENT.md");
26589
+ if (existsSync40(agentMdPath)) {
25774
26590
  try {
25775
- return readFileSync27(agentMdPath, "utf-8");
26591
+ return readFileSync29(agentMdPath, "utf-8");
25776
26592
  } catch {
25777
26593
  return null;
25778
26594
  }
25779
26595
  }
25780
- const indexMdPath = join37(agentPath, "index.md");
25781
- if (existsSync37(indexMdPath)) {
26596
+ const indexMdPath = join40(agentPath, "index.md");
26597
+ if (existsSync40(indexMdPath)) {
25782
26598
  try {
25783
- return readFileSync27(indexMdPath, "utf-8");
26599
+ return readFileSync29(indexMdPath, "utf-8");
25784
26600
  } catch {
25785
26601
  return null;
25786
26602
  }
@@ -25791,17 +26607,17 @@ function validateAgent(agentPath) {
25791
26607
  const errors = [];
25792
26608
  const warnings = [];
25793
26609
  let filePath = agentPath;
25794
- if (!existsSync37(agentPath)) {
26610
+ if (!existsSync40(agentPath)) {
25795
26611
  errors.push(`Agent file not found: ${agentPath}`);
25796
26612
  return { valid: false, errors, warnings };
25797
26613
  }
25798
26614
  const stats = statSync8(agentPath);
25799
26615
  if (stats.isDirectory()) {
25800
- const agentMd = join37(agentPath, "AGENT.md");
25801
- const indexMd = join37(agentPath, "index.md");
25802
- if (existsSync37(agentMd)) {
26616
+ const agentMd = join40(agentPath, "AGENT.md");
26617
+ const indexMd = join40(agentPath, "index.md");
26618
+ if (existsSync40(agentMd)) {
25803
26619
  filePath = agentMd;
25804
- } else if (existsSync37(indexMd)) {
26620
+ } else if (existsSync40(indexMd)) {
25805
26621
  filePath = indexMd;
25806
26622
  } else {
25807
26623
  errors.push("Directory must contain AGENT.md or index.md");
@@ -25810,7 +26626,7 @@ function validateAgent(agentPath) {
25810
26626
  }
25811
26627
  let content;
25812
26628
  try {
25813
- content = readFileSync27(filePath, "utf-8");
26629
+ content = readFileSync29(filePath, "utf-8");
25814
26630
  } catch {
25815
26631
  errors.push(`Cannot read file: ${filePath}`);
25816
26632
  return { valid: false, errors, warnings };
@@ -25847,18 +26663,18 @@ function validateAgent(agentPath) {
25847
26663
  }
25848
26664
 
25849
26665
  // src/agents/discovery.ts
25850
- import { existsSync as existsSync38, readdirSync as readdirSync11, statSync as statSync9 } from "fs";
25851
- import { join as join38, extname as extname4 } from "path";
26666
+ import { existsSync as existsSync41, readdirSync as readdirSync12, statSync as statSync9 } from "fs";
26667
+ import { join as join41, extname as extname4 } from "path";
25852
26668
  import { homedir as homedir13 } from "os";
25853
26669
  function discoverAgentsInDir(dir, location) {
25854
26670
  const agents = [];
25855
- if (!existsSync38(dir)) {
26671
+ if (!existsSync41(dir)) {
25856
26672
  return agents;
25857
26673
  }
25858
26674
  try {
25859
- const entries = readdirSync11(dir, { withFileTypes: true });
26675
+ const entries = readdirSync12(dir, { withFileTypes: true });
25860
26676
  for (const entry of entries) {
25861
- const entryPath = join38(dir, entry.name);
26677
+ const entryPath = join41(dir, entry.name);
25862
26678
  if (entry.isFile() && extname4(entry.name) === ".md") {
25863
26679
  const agent = parseAgentFile(entryPath, location);
25864
26680
  if (agent) {
@@ -25879,8 +26695,8 @@ function discoverAgents(rootDir) {
25879
26695
  const agents = [];
25880
26696
  const seen = /* @__PURE__ */ new Set();
25881
26697
  for (const searchPath of ALL_AGENT_DISCOVERY_PATHS) {
25882
- const fullPath = join38(rootDir, searchPath);
25883
- if (existsSync38(fullPath)) {
26698
+ const fullPath = join41(rootDir, searchPath);
26699
+ if (existsSync41(fullPath)) {
25884
26700
  for (const agent of discoverAgentsInDir(fullPath, "project")) {
25885
26701
  if (!seen.has(agent.name)) {
25886
26702
  seen.add(agent.name);
@@ -25896,8 +26712,8 @@ function discoverAgentsForAgent(rootDir, agentType) {
25896
26712
  const seen = /* @__PURE__ */ new Set();
25897
26713
  const paths = AGENT_DISCOVERY_PATHS[agentType] || [];
25898
26714
  for (const searchPath of paths) {
25899
- const fullPath = join38(rootDir, searchPath);
25900
- if (existsSync38(fullPath)) {
26715
+ const fullPath = join41(rootDir, searchPath);
26716
+ if (existsSync41(fullPath)) {
25901
26717
  for (const agent of discoverAgentsInDir(fullPath, "project")) {
25902
26718
  if (!seen.has(agent.name)) {
25903
26719
  seen.add(agent.name);
@@ -25913,12 +26729,12 @@ function discoverGlobalAgents() {
25913
26729
  const seen = /* @__PURE__ */ new Set();
25914
26730
  const home = homedir13();
25915
26731
  const globalPaths = [
25916
- join38(home, ".claude", "agents"),
25917
- join38(home, ".skillkit", "agents"),
25918
- join38(home, ".config", "skillkit", "agents")
26732
+ join41(home, ".claude", "agents"),
26733
+ join41(home, ".skillkit", "agents"),
26734
+ join41(home, ".config", "skillkit", "agents")
25919
26735
  ];
25920
26736
  for (const searchPath of globalPaths) {
25921
- if (existsSync38(searchPath)) {
26737
+ if (existsSync41(searchPath)) {
25922
26738
  for (const agent of discoverAgentsInDir(searchPath, "global")) {
25923
26739
  if (!seen.has(agent.name)) {
25924
26740
  seen.add(agent.name);
@@ -25933,7 +26749,7 @@ function findAllAgents(searchDirs) {
25933
26749
  const agents = [];
25934
26750
  const seen = /* @__PURE__ */ new Set();
25935
26751
  for (const dir of searchDirs) {
25936
- if (!existsSync38(dir)) continue;
26752
+ if (!existsSync41(dir)) continue;
25937
26753
  const discovered = discoverAgents(dir);
25938
26754
  for (const agent of discovered) {
25939
26755
  if (!seen.has(agent.name)) {
@@ -25952,33 +26768,33 @@ function findAllAgents(searchDirs) {
25952
26768
  }
25953
26769
  function findAgent(name, searchDirs) {
25954
26770
  for (const dir of searchDirs) {
25955
- if (!existsSync38(dir)) continue;
26771
+ if (!existsSync41(dir)) continue;
25956
26772
  for (const searchPath of ALL_AGENT_DISCOVERY_PATHS) {
25957
- const agentsDir = join38(dir, searchPath);
25958
- if (!existsSync38(agentsDir)) continue;
25959
- const agentFile = join38(agentsDir, `${name}.md`);
25960
- if (existsSync38(agentFile)) {
26773
+ const agentsDir = join41(dir, searchPath);
26774
+ if (!existsSync41(agentsDir)) continue;
26775
+ const agentFile = join41(agentsDir, `${name}.md`);
26776
+ if (existsSync41(agentFile)) {
25961
26777
  return parseAgentFile(agentFile, "project");
25962
26778
  }
25963
- const agentDir = join38(agentsDir, name);
25964
- if (existsSync38(agentDir) && statSync9(agentDir).isDirectory()) {
26779
+ const agentDir = join41(agentsDir, name);
26780
+ if (existsSync41(agentDir) && statSync9(agentDir).isDirectory()) {
25965
26781
  return parseAgentDir(agentDir, "project");
25966
26782
  }
25967
26783
  }
25968
26784
  }
25969
26785
  const home = homedir13();
25970
26786
  const globalPaths = [
25971
- join38(home, ".claude", "agents"),
25972
- join38(home, ".skillkit", "agents")
26787
+ join41(home, ".claude", "agents"),
26788
+ join41(home, ".skillkit", "agents")
25973
26789
  ];
25974
26790
  for (const agentsDir of globalPaths) {
25975
- if (!existsSync38(agentsDir)) continue;
25976
- const agentFile = join38(agentsDir, `${name}.md`);
25977
- if (existsSync38(agentFile)) {
26791
+ if (!existsSync41(agentsDir)) continue;
26792
+ const agentFile = join41(agentsDir, `${name}.md`);
26793
+ if (existsSync41(agentFile)) {
25978
26794
  return parseAgentFile(agentFile, "global");
25979
26795
  }
25980
- const agentDir = join38(agentsDir, name);
25981
- if (existsSync38(agentDir) && statSync9(agentDir).isDirectory()) {
26796
+ const agentDir = join41(agentsDir, name);
26797
+ if (existsSync41(agentDir) && statSync9(agentDir).isDirectory()) {
25982
26798
  return parseAgentDir(agentDir, "global");
25983
26799
  }
25984
26800
  }
@@ -25987,9 +26803,9 @@ function findAgent(name, searchDirs) {
25987
26803
  function getAgentsDirectory(rootDir, agentType) {
25988
26804
  const paths = AGENT_DISCOVERY_PATHS[agentType];
25989
26805
  if (paths && paths.length > 0) {
25990
- return join38(rootDir, paths[0]);
26806
+ return join41(rootDir, paths[0]);
25991
26807
  }
25992
- return join38(rootDir, "agents");
26808
+ return join41(rootDir, "agents");
25993
26809
  }
25994
26810
  function agentExists(name, searchDirs) {
25995
26811
  return findAgent(name, searchDirs) !== null;
@@ -26007,14 +26823,14 @@ function getAgentStats(searchDirs) {
26007
26823
  function discoverAgentsRecursive(rootDir, location = "project") {
26008
26824
  const agents = [];
26009
26825
  const seen = /* @__PURE__ */ new Set();
26010
- if (!existsSync38(rootDir)) {
26826
+ if (!existsSync41(rootDir)) {
26011
26827
  return agents;
26012
26828
  }
26013
26829
  function scanDirectory(dir) {
26014
26830
  try {
26015
- const entries = readdirSync11(dir, { withFileTypes: true });
26831
+ const entries = readdirSync12(dir, { withFileTypes: true });
26016
26832
  for (const entry of entries) {
26017
- const entryPath = join38(dir, entry.name);
26833
+ const entryPath = join41(dir, entry.name);
26018
26834
  if (entry.isFile() && extname4(entry.name) === ".md") {
26019
26835
  const agent = parseAgentFile(entryPath, location);
26020
26836
  if (agent && !seen.has(agent.name)) {
@@ -26041,7 +26857,7 @@ function discoverAgentsRecursive(rootDir, location = "project") {
26041
26857
  return agents;
26042
26858
  }
26043
26859
  function discoverAgentsFromPath(sourcePath, recursive = false, location = "project") {
26044
- if (!existsSync38(sourcePath)) {
26860
+ if (!existsSync41(sourcePath)) {
26045
26861
  return [];
26046
26862
  }
26047
26863
  const stats = statSync9(sourcePath);
@@ -26062,9 +26878,9 @@ function discoverAgentsFromPath(sourcePath, recursive = false, location = "proje
26062
26878
  }
26063
26879
  const agents = [];
26064
26880
  try {
26065
- const entries = readdirSync11(sourcePath, { withFileTypes: true });
26881
+ const entries = readdirSync12(sourcePath, { withFileTypes: true });
26066
26882
  for (const entry of entries) {
26067
- const entryPath = join38(sourcePath, entry.name);
26883
+ const entryPath = join41(sourcePath, entry.name);
26068
26884
  if (entry.isFile() && extname4(entry.name) === ".md") {
26069
26885
  const a = parseAgentFile(entryPath, location);
26070
26886
  if (a) agents.push(a);
@@ -26081,7 +26897,7 @@ function discoverAgentsFromPath(sourcePath, recursive = false, location = "proje
26081
26897
  }
26082
26898
 
26083
26899
  // src/agents/translator.ts
26084
- import { join as join39 } from "path";
26900
+ import { join as join42 } from "path";
26085
26901
  function translateAgent(agent, targetAgent, options) {
26086
26902
  const canonical = toCanonicalAgent(agent);
26087
26903
  return translateCanonicalAgent(canonical, targetAgent, options);
@@ -26302,9 +27118,9 @@ function getAgentFilename(agentName, targetAgent) {
26302
27118
  function getAgentTargetDirectory(rootDir, targetAgent) {
26303
27119
  const paths = AGENT_DISCOVERY_PATHS[targetAgent];
26304
27120
  if (paths && paths.length > 0) {
26305
- return join39(rootDir, paths[0]);
27121
+ return join42(rootDir, paths[0]);
26306
27122
  }
26307
- return join39(rootDir, "agents");
27123
+ return join42(rootDir, "agents");
26308
27124
  }
26309
27125
  function escapeYamlString(str) {
26310
27126
  if (/[:\{\}\[\],&*#?|\-<>=!%@`]/.test(str) || str.includes("\n")) {
@@ -26491,8 +27307,8 @@ function loadAndConvertSkill(skill, options) {
26491
27307
  }
26492
27308
 
26493
27309
  // src/skill-translator.ts
26494
- import { readFileSync as readFileSync28, existsSync as existsSync39, writeFileSync as writeFileSync20, mkdirSync as mkdirSync21 } from "fs";
26495
- import { join as join40, basename as basename16, dirname as dirname13, resolve as resolve5, relative as relative3, isAbsolute as isAbsolute2 } from "path";
27310
+ import { readFileSync as readFileSync30, existsSync as existsSync42, writeFileSync as writeFileSync22, mkdirSync as mkdirSync23 } from "fs";
27311
+ import { join as join43, basename as basename16, dirname as dirname13, resolve as resolve5, relative as relative3, isAbsolute as isAbsolute2 } from "path";
26496
27312
  import { parse as parseYaml11, stringify as stringifyYaml8 } from "yaml";
26497
27313
  var AGENT_SKILL_FORMATS = Object.fromEntries(
26498
27314
  Object.entries(AGENT_CONFIG).map(([agent, config]) => [
@@ -26501,12 +27317,12 @@ var AGENT_SKILL_FORMATS = Object.fromEntries(
26501
27317
  ])
26502
27318
  );
26503
27319
  function parseSkillToCanonical(skillPath, sourceAgent) {
26504
- const skillMdPath = skillPath.endsWith("SKILL.md") ? skillPath : join40(skillPath, "SKILL.md");
26505
- if (!existsSync39(skillMdPath)) {
27320
+ const skillMdPath = skillPath.endsWith("SKILL.md") ? skillPath : join43(skillPath, "SKILL.md");
27321
+ if (!existsSync42(skillMdPath)) {
26506
27322
  return null;
26507
27323
  }
26508
27324
  try {
26509
- const content = readFileSync28(skillMdPath, "utf-8");
27325
+ const content = readFileSync30(skillMdPath, "utf-8");
26510
27326
  return parseSkillContentToCanonical(content, skillPath, sourceAgent);
26511
27327
  } catch {
26512
27328
  return null;
@@ -26594,7 +27410,7 @@ function translateSkillToAgent(canonical, targetAgent, options) {
26594
27410
  }
26595
27411
  const content = generateSkillContent(canonical, targetAgent, format, options);
26596
27412
  const filename = options?.outputFilename || "SKILL.md";
26597
- const targetDir = options?.outputDir || join40(format.skillsDir, canonical.name);
27413
+ const targetDir = options?.outputDir || join43(format.skillsDir, canonical.name);
26598
27414
  return {
26599
27415
  success: true,
26600
27416
  content,
@@ -26769,7 +27585,7 @@ function writeTranslatedSkill(result, rootDir, options) {
26769
27585
  error: "Resolved output path escapes rootDir"
26770
27586
  };
26771
27587
  }
26772
- if (existsSync39(filePath) && options?.overwrite === false) {
27588
+ if (existsSync42(filePath) && options?.overwrite === false) {
26773
27589
  return {
26774
27590
  success: false,
26775
27591
  path: filePath,
@@ -26777,10 +27593,10 @@ function writeTranslatedSkill(result, rootDir, options) {
26777
27593
  skipped: true
26778
27594
  };
26779
27595
  }
26780
- if (!existsSync39(targetPath)) {
26781
- mkdirSync21(targetPath, { recursive: true });
27596
+ if (!existsSync42(targetPath)) {
27597
+ mkdirSync23(targetPath, { recursive: true });
26782
27598
  }
26783
- writeFileSync20(filePath, result.content, "utf-8");
27599
+ writeFileSync22(filePath, result.content, "utf-8");
26784
27600
  return { success: true, path: filePath };
26785
27601
  } catch (error) {
26786
27602
  return {
@@ -26963,16 +27779,16 @@ var getAgentSkillsDir = getSkillsDir;
26963
27779
  var getAgentConfigFile = getConfigFile;
26964
27780
 
26965
27781
  // src/manifest/index.ts
26966
- import { readFileSync as readFileSync29, writeFileSync as writeFileSync21, existsSync as existsSync40 } from "fs";
26967
- import { join as join41, dirname as dirname14 } from "path";
27782
+ import { readFileSync as readFileSync31, writeFileSync as writeFileSync23, existsSync as existsSync43 } from "fs";
27783
+ import { join as join44, dirname as dirname14 } from "path";
26968
27784
  import { parse as parseYaml12, stringify as stringifyYaml9 } from "yaml";
26969
27785
  var MANIFEST_FILENAMES = [".skills", ".skills.yaml", ".skills.yml", "skills.yaml"];
26970
27786
  function findManifestPath(startDir = process.cwd()) {
26971
27787
  let dir = startDir;
26972
27788
  while (dir !== dirname14(dir)) {
26973
27789
  for (const filename of MANIFEST_FILENAMES) {
26974
- const manifestPath = join41(dir, filename);
26975
- if (existsSync40(manifestPath)) {
27790
+ const manifestPath = join44(dir, filename);
27791
+ if (existsSync43(manifestPath)) {
26976
27792
  return manifestPath;
26977
27793
  }
26978
27794
  }
@@ -26982,11 +27798,11 @@ function findManifestPath(startDir = process.cwd()) {
26982
27798
  }
26983
27799
  function loadManifest(manifestPath) {
26984
27800
  const path4 = manifestPath || findManifestPath();
26985
- if (!path4 || !existsSync40(path4)) {
27801
+ if (!path4 || !existsSync43(path4)) {
26986
27802
  return null;
26987
27803
  }
26988
27804
  try {
26989
- const content = readFileSync29(path4, "utf-8");
27805
+ const content = readFileSync31(path4, "utf-8");
26990
27806
  const parsed = parseYaml12(content);
26991
27807
  if (!parsed || typeof parsed !== "object") {
26992
27808
  return null;
@@ -27028,7 +27844,7 @@ function normalizeSkills(skills) {
27028
27844
  }).filter((s) => s.source);
27029
27845
  }
27030
27846
  function saveManifest(manifest, manifestPath) {
27031
- const path4 = manifestPath || join41(process.cwd(), ".skills");
27847
+ const path4 = manifestPath || join44(process.cwd(), ".skills");
27032
27848
  const content = stringifyYaml9({
27033
27849
  version: manifest.version || 1,
27034
27850
  skills: manifest.skills.map((s) => {
@@ -27041,7 +27857,7 @@ function saveManifest(manifest, manifestPath) {
27041
27857
  ...manifest.installMethod && { installMethod: manifest.installMethod },
27042
27858
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
27043
27859
  });
27044
- writeFileSync21(path4, content, "utf-8");
27860
+ writeFileSync23(path4, content, "utf-8");
27045
27861
  }
27046
27862
  function addToManifest(source, options, manifestPath) {
27047
27863
  const existing = loadManifest(manifestPath) || {
@@ -27118,8 +27934,8 @@ function generateManifestFromInstalled(installedSkills) {
27118
27934
  }
27119
27935
 
27120
27936
  // src/quality/index.ts
27121
- import { readFileSync as readFileSync30, existsSync as existsSync41 } from "fs";
27122
- import { join as join42, basename as basename17 } from "path";
27937
+ import { readFileSync as readFileSync32, existsSync as existsSync44 } from "fs";
27938
+ import { join as join45, basename as basename17 } from "path";
27123
27939
 
27124
27940
  // src/quality/benchmark.ts
27125
27941
  var CATEGORY_BENCHMARKS = {
@@ -27721,9 +28537,9 @@ function evaluateSkillContent(content) {
27721
28537
  };
27722
28538
  }
27723
28539
  function evaluateSkillFile(filePath) {
27724
- if (!existsSync41(filePath)) return null;
28540
+ if (!existsSync44(filePath)) return null;
27725
28541
  try {
27726
- const content = readFileSync30(filePath, "utf-8");
28542
+ const content = readFileSync32(filePath, "utf-8");
27727
28543
  return evaluateSkillContent(content);
27728
28544
  } catch {
27729
28545
  return null;
@@ -27749,11 +28565,11 @@ function checkTokenBudget(content) {
27749
28565
  return null;
27750
28566
  }
27751
28567
  function evaluateSkillDirectory(dirPath) {
27752
- const skillMdPath = join42(dirPath, "SKILL.md");
27753
- if (existsSync41(skillMdPath)) {
28568
+ const skillMdPath = join45(dirPath, "SKILL.md");
28569
+ if (existsSync44(skillMdPath)) {
27754
28570
  const result = evaluateSkillFile(skillMdPath);
27755
28571
  if (result) {
27756
- const content = readFileSync30(skillMdPath, "utf-8");
28572
+ const content = readFileSync32(skillMdPath, "utf-8");
27757
28573
  const nameWarning = checkNameDirectoryMatch(content, dirPath);
27758
28574
  if (nameWarning) result.warnings.push(nameWarning);
27759
28575
  const budgetWarning = checkTokenBudget(content);
@@ -27763,8 +28579,8 @@ function evaluateSkillDirectory(dirPath) {
27763
28579
  }
27764
28580
  const mdcFiles = ["index.mdc", `${basename17(dirPath)}.mdc`];
27765
28581
  for (const file of mdcFiles) {
27766
- const mdcPath = join42(dirPath, file);
27767
- if (existsSync41(mdcPath)) {
28582
+ const mdcPath = join45(dirPath, file);
28583
+ if (existsSync44(mdcPath)) {
27768
28584
  return evaluateSkillFile(mdcPath);
27769
28585
  }
27770
28586
  }
@@ -27934,8 +28750,8 @@ var AGENT_INSTRUCTION_TEMPLATES = {
27934
28750
  };
27935
28751
 
27936
28752
  // src/primer/analyzer.ts
27937
- import { existsSync as existsSync42, readFileSync as readFileSync31, readdirSync as readdirSync12 } from "fs";
27938
- import { join as join43, basename as basename18, relative as relative4, sep as sep4 } from "path";
28753
+ import { existsSync as existsSync45, readFileSync as readFileSync33, readdirSync as readdirSync13 } from "fs";
28754
+ import { join as join46, basename as basename18, relative as relative4, sep as sep4 } from "path";
27939
28755
  var PACKAGE_MANAGER_FILES = {
27940
28756
  "package-lock.json": "npm",
27941
28757
  "pnpm-lock.yaml": "pnpm",
@@ -28023,10 +28839,10 @@ var PrimerAnalyzer = class {
28023
28839
  return analysis;
28024
28840
  }
28025
28841
  loadPackageJson() {
28026
- const packageJsonPath = join43(this.projectPath, "package.json");
28027
- if (existsSync42(packageJsonPath)) {
28842
+ const packageJsonPath = join46(this.projectPath, "package.json");
28843
+ if (existsSync45(packageJsonPath)) {
28028
28844
  try {
28029
- const content = readFileSync31(packageJsonPath, "utf-8");
28845
+ const content = readFileSync33(packageJsonPath, "utf-8");
28030
28846
  this.packageJson = JSON.parse(content);
28031
28847
  } catch {
28032
28848
  this.packageJson = null;
@@ -28037,9 +28853,9 @@ var PrimerAnalyzer = class {
28037
28853
  const scan = (dir, depth) => {
28038
28854
  if (depth > maxDepth) return;
28039
28855
  try {
28040
- const entries = readdirSync12(dir, { withFileTypes: true });
28856
+ const entries = readdirSync13(dir, { withFileTypes: true });
28041
28857
  for (const entry of entries) {
28042
- const fullPath = join43(dir, entry.name);
28858
+ const fullPath = join46(dir, entry.name);
28043
28859
  const relativePath = relative4(this.projectPath, fullPath);
28044
28860
  if (entry.name.startsWith(".") && entry.name !== ".github" && entry.name !== ".env.example") {
28045
28861
  if (!entry.isDirectory()) {
@@ -28084,10 +28900,10 @@ var PrimerAnalyzer = class {
28084
28900
  info.repository = String(repo.url);
28085
28901
  }
28086
28902
  }
28087
- const pyprojectPath = join43(this.projectPath, "pyproject.toml");
28088
- if (!this.packageJson && existsSync42(pyprojectPath)) {
28903
+ const pyprojectPath = join46(this.projectPath, "pyproject.toml");
28904
+ if (!this.packageJson && existsSync45(pyprojectPath)) {
28089
28905
  try {
28090
- const content = readFileSync31(pyprojectPath, "utf-8");
28906
+ const content = readFileSync33(pyprojectPath, "utf-8");
28091
28907
  const nameMatch = content.match(/name\s*=\s*["']([^"']+)["']/);
28092
28908
  const versionMatch = content.match(/version\s*=\s*["']([^"']+)["']/);
28093
28909
  const descMatch = content.match(/description\s*=\s*["']([^"']+)["']/);
@@ -28097,10 +28913,10 @@ var PrimerAnalyzer = class {
28097
28913
  } catch {
28098
28914
  }
28099
28915
  }
28100
- const cargoPath = join43(this.projectPath, "Cargo.toml");
28101
- if (!this.packageJson && existsSync42(cargoPath)) {
28916
+ const cargoPath = join46(this.projectPath, "Cargo.toml");
28917
+ if (!this.packageJson && existsSync45(cargoPath)) {
28102
28918
  try {
28103
- const content = readFileSync31(cargoPath, "utf-8");
28919
+ const content = readFileSync33(cargoPath, "utf-8");
28104
28920
  const nameMatch = content.match(/name\s*=\s*["']([^"']+)["']/);
28105
28921
  const versionMatch = content.match(/version\s*=\s*["']([^"']+)["']/);
28106
28922
  const descMatch = content.match(/description\s*=\s*["']([^"']+)["']/);
@@ -28280,8 +29096,8 @@ var PrimerAnalyzer = class {
28280
29096
  }
28281
29097
  if (this.hasFile("tsconfig.json")) {
28282
29098
  try {
28283
- const tsconfigPath = join43(this.projectPath, "tsconfig.json");
28284
- const content = readFileSync31(tsconfigPath, "utf-8");
29099
+ const tsconfigPath = join46(this.projectPath, "tsconfig.json");
29100
+ const content = readFileSync33(tsconfigPath, "utf-8");
28285
29101
  const tsconfig = JSON.parse(content.replace(/\/\/.*$/gm, "").replace(/,\s*}/g, "}"));
28286
29102
  const paths = tsconfig.compilerOptions?.paths;
28287
29103
  if (paths && Object.keys(paths).some((k) => k.startsWith("@"))) {
@@ -28310,8 +29126,8 @@ var PrimerAnalyzer = class {
28310
29126
  ci.provider = "github-actions";
28311
29127
  ci.configFile = ".github/workflows";
28312
29128
  try {
28313
- const workflowsDir = join43(this.projectPath, ".github/workflows");
28314
- const workflows = readdirSync12(workflowsDir);
29129
+ const workflowsDir = join46(this.projectPath, ".github/workflows");
29130
+ const workflows = readdirSync13(workflowsDir);
28315
29131
  const deployWorkflows = workflows.filter(
28316
29132
  (f) => f.includes("deploy") || f.includes("release") || f.includes("publish")
28317
29133
  );
@@ -28331,12 +29147,12 @@ var PrimerAnalyzer = class {
28331
29147
  env.hasEnvFile = this.hasFile(".env");
28332
29148
  env.hasEnvExample = this.hasFile(".env.example") || this.hasFile(".env.template") || this.hasFile(".env.sample");
28333
29149
  if (env.hasEnvExample) {
28334
- const envExamplePath = join43(
29150
+ const envExamplePath = join46(
28335
29151
  this.projectPath,
28336
29152
  this.hasFile(".env.example") ? ".env.example" : this.hasFile(".env.template") ? ".env.template" : ".env.sample"
28337
29153
  );
28338
29154
  try {
28339
- const content = readFileSync31(envExamplePath, "utf-8");
29155
+ const content = readFileSync33(envExamplePath, "utf-8");
28340
29156
  const variables = content.split("\n").filter((line) => line.trim() && !line.startsWith("#")).map((line) => line.split("=")[0].trim()).filter((v) => v);
28341
29157
  env.envVariables = variables;
28342
29158
  } catch {
@@ -28353,8 +29169,8 @@ var PrimerAnalyzer = class {
28353
29169
  docker.hasCompose = this.hasFile("docker-compose.yml") || this.hasFile("docker-compose.yaml") || this.hasFile("compose.yml");
28354
29170
  if (docker.hasDockerfile) {
28355
29171
  try {
28356
- const dockerfilePath = join43(this.projectPath, "Dockerfile");
28357
- const content = readFileSync31(dockerfilePath, "utf-8");
29172
+ const dockerfilePath = join46(this.projectPath, "Dockerfile");
29173
+ const content = readFileSync33(dockerfilePath, "utf-8");
28358
29174
  const fromMatch = content.match(/^FROM\s+(\S+)/m);
28359
29175
  if (fromMatch) {
28360
29176
  docker.baseImage = fromMatch[1];
@@ -28443,7 +29259,7 @@ var PrimerAnalyzer = class {
28443
29259
  }
28444
29260
  return false;
28445
29261
  }
28446
- return this.files.has(name) || existsSync42(join43(this.projectPath, name));
29262
+ return this.files.has(name) || existsSync45(join46(this.projectPath, name));
28447
29263
  }
28448
29264
  getDepVersion(dep) {
28449
29265
  if (!this.packageJson) return void 0;
@@ -28465,10 +29281,10 @@ var PrimerAnalyzer = class {
28465
29281
  }
28466
29282
  readConfigFile(files) {
28467
29283
  for (const file of files) {
28468
- const filePath = join43(this.projectPath, file);
28469
- if (existsSync42(filePath)) {
29284
+ const filePath = join46(this.projectPath, file);
29285
+ if (existsSync45(filePath)) {
28470
29286
  try {
28471
- const content = readFileSync31(filePath, "utf-8");
29287
+ const content = readFileSync33(filePath, "utf-8");
28472
29288
  if (file.endsWith(".json")) {
28473
29289
  return JSON.parse(content);
28474
29290
  }
@@ -28486,8 +29302,8 @@ function analyzePrimer(projectPath) {
28486
29302
  }
28487
29303
 
28488
29304
  // src/primer/generator.ts
28489
- import { existsSync as existsSync43, mkdirSync as mkdirSync22, writeFileSync as writeFileSync22 } from "fs";
28490
- import { join as join44, dirname as dirname15 } from "path";
29305
+ import { existsSync as existsSync46, mkdirSync as mkdirSync24, writeFileSync as writeFileSync24 } from "fs";
29306
+ import { join as join47, dirname as dirname15 } from "path";
28491
29307
  var ALL_AGENTS = Object.keys(AGENT_CONFIG);
28492
29308
  var markdownRenderer = {
28493
29309
  h1: (text) => `# ${text}`,
@@ -28651,14 +29467,14 @@ var PrimerGenerator = class {
28651
29467
  detectInstalledAgents() {
28652
29468
  const detected = [];
28653
29469
  for (const [agent, config] of Object.entries(AGENT_CONFIG)) {
28654
- const configPath = join44(this.projectPath, config.configFile);
28655
- const skillsPath = join44(this.projectPath, config.skillsDir);
28656
- if (existsSync43(configPath) || existsSync43(skillsPath)) {
29470
+ const configPath = join47(this.projectPath, config.configFile);
29471
+ const skillsPath = join47(this.projectPath, config.skillsDir);
29472
+ if (existsSync46(configPath) || existsSync46(skillsPath)) {
28657
29473
  detected.push(agent);
28658
29474
  }
28659
29475
  if (config.altSkillsDirs) {
28660
29476
  for (const altDir of config.altSkillsDirs) {
28661
- if (existsSync43(join44(this.projectPath, altDir))) {
29477
+ if (existsSync46(join47(this.projectPath, altDir))) {
28662
29478
  if (!detected.includes(agent)) {
28663
29479
  detected.push(agent);
28664
29480
  }
@@ -28678,7 +29494,7 @@ var PrimerGenerator = class {
28678
29494
  const template = AGENT_INSTRUCTION_TEMPLATES[agent] || this.getDefaultTemplate(agent, config);
28679
29495
  const content = this.generateContent(template);
28680
29496
  const outputDir = this.options.outputDir || this.projectPath;
28681
- const filepath = join44(outputDir, template.filename);
29497
+ const filepath = join47(outputDir, template.filename);
28682
29498
  return {
28683
29499
  agent,
28684
29500
  filename: template.filename,
@@ -29051,10 +29867,10 @@ var PrimerGenerator = class {
29051
29867
  }
29052
29868
  writeInstruction(instruction) {
29053
29869
  const dir = dirname15(instruction.filepath);
29054
- if (!existsSync43(dir)) {
29055
- mkdirSync22(dir, { recursive: true });
29870
+ if (!existsSync46(dir)) {
29871
+ mkdirSync24(dir, { recursive: true });
29056
29872
  }
29057
- writeFileSync22(instruction.filepath, instruction.content, "utf-8");
29873
+ writeFileSync24(instruction.filepath, instruction.content, "utf-8");
29058
29874
  }
29059
29875
  formatProjectType(type) {
29060
29876
  const typeMap = {
@@ -29068,402 +29884,135 @@ var PrimerGenerator = class {
29068
29884
  };
29069
29885
  return typeMap[type] || type;
29070
29886
  }
29071
- capitalize(str) {
29072
- return str.charAt(0).toUpperCase() + str.slice(1);
29073
- }
29074
- };
29075
- function generatePrimer(projectPath, options = {}) {
29076
- const generator = new PrimerGenerator(projectPath, options);
29077
- return generator.generate();
29078
- }
29079
- function generatePrimerForAgent(projectPath, agent, options = {}) {
29080
- return generatePrimer(projectPath, { ...options, agents: [agent] });
29081
- }
29082
- function analyzeForPrimer(projectPath) {
29083
- const generator = new PrimerGenerator(projectPath, { analyzeOnly: true });
29084
- const result = generator.generate();
29085
- return result.analysis;
29086
- }
29087
-
29088
- // src/learning/types.ts
29089
- var DEFAULT_LEARNING_CONFIG = {
29090
- minSessionLength: 10,
29091
- sensitivity: "medium",
29092
- autoApprove: false,
29093
- outputPath: "~/.skillkit/learned/",
29094
- categories: ["error_fix", "refactor", "workaround", "debugging", "convention"],
29095
- ignorePatterns: ["trivial_typo", "one_off_fix", "wip", "merge"]
29096
- };
29097
-
29098
- // src/learning/config.ts
29099
- import { existsSync as existsSync44, readFileSync as readFileSync32, writeFileSync as writeFileSync23, mkdirSync as mkdirSync23 } from "fs";
29100
- import { join as join45, dirname as dirname16 } from "path";
29101
- import { homedir as homedir14 } from "os";
29102
- import yaml from "yaml";
29103
- function getDefaultConfigPath() {
29104
- return join45(homedir14(), ".skillkit", "learning.yaml");
29105
- }
29106
- function getDefaultStorePath() {
29107
- return join45(homedir14(), ".skillkit", "learned", "patterns.json");
29108
- }
29109
- function loadLearningConfig(configPath) {
29110
- const path4 = configPath || getDefaultConfigPath();
29111
- if (!existsSync44(path4)) {
29112
- return DEFAULT_LEARNING_CONFIG;
29113
- }
29114
- try {
29115
- const content = readFileSync32(path4, "utf-8");
29116
- const config = yaml.parse(content);
29117
- return { ...DEFAULT_LEARNING_CONFIG, ...config };
29118
- } catch {
29119
- return DEFAULT_LEARNING_CONFIG;
29120
- }
29121
- }
29122
- function saveLearningConfig(config, configPath) {
29123
- const path4 = configPath || getDefaultConfigPath();
29124
- const dir = dirname16(path4);
29125
- if (!existsSync44(dir)) {
29126
- mkdirSync23(dir, { recursive: true });
29127
- }
29128
- const content = yaml.stringify(config);
29129
- writeFileSync23(path4, content);
29130
- }
29131
- function loadPatternStore(storePath) {
29132
- const path4 = storePath || getDefaultStorePath();
29133
- if (!existsSync44(path4)) {
29134
- return {
29135
- version: 1,
29136
- updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
29137
- patterns: [],
29138
- evolvingPatterns: []
29139
- };
29140
- }
29141
- try {
29142
- const content = readFileSync32(path4, "utf-8");
29143
- return JSON.parse(content);
29144
- } catch {
29145
- return {
29146
- version: 1,
29147
- updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
29148
- patterns: [],
29149
- evolvingPatterns: []
29150
- };
29151
- }
29152
- }
29153
- function savePatternStore(store, storePath) {
29154
- const path4 = storePath || getDefaultStorePath();
29155
- const dir = dirname16(path4);
29156
- if (!existsSync44(dir)) {
29157
- mkdirSync23(dir, { recursive: true });
29158
- }
29159
- store.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
29160
- const content = JSON.stringify(store, null, 2);
29161
- writeFileSync23(path4, content);
29162
- }
29163
- function addPattern(pattern, storePath) {
29164
- const store = loadPatternStore(storePath);
29165
- const existingIndex = store.patterns.findIndex((p) => p.id === pattern.id);
29166
- if (existingIndex >= 0) {
29167
- store.patterns[existingIndex] = pattern;
29168
- } else {
29169
- store.patterns.push(pattern);
29170
- }
29171
- savePatternStore(store, storePath);
29172
- return store;
29173
- }
29174
- function removePattern(patternId, storePath) {
29175
- const store = loadPatternStore(storePath);
29176
- store.patterns = store.patterns.filter((p) => p.id !== patternId);
29177
- store.evolvingPatterns = store.evolvingPatterns.filter((p) => p.id !== patternId);
29178
- savePatternStore(store, storePath);
29179
- return store;
29180
- }
29181
- function getPattern(patternId, storePath) {
29182
- const store = loadPatternStore(storePath);
29183
- return store.patterns.find((p) => p.id === patternId) || null;
29184
- }
29185
- function getEvolvingPattern(patternId, storePath) {
29186
- const store = loadPatternStore(storePath);
29187
- return store.evolvingPatterns.find((p) => p.id === patternId) || null;
29188
- }
29189
- function getAllPatterns(storePath) {
29190
- const store = loadPatternStore(storePath);
29191
- return store.patterns;
29192
- }
29193
- function getPatternsByCategory(category, storePath) {
29194
- const store = loadPatternStore(storePath);
29195
- return store.patterns.filter((p) => p.category === category);
29196
- }
29197
- function getApprovedPatterns(storePath) {
29198
- const store = loadPatternStore(storePath);
29199
- return store.patterns.filter((p) => p.approved);
29200
- }
29201
-
29202
- // src/learning/git-analyzer.ts
29203
- import { execSync as execSync7 } from "child_process";
29204
- import { existsSync as existsSync45 } from "fs";
29205
- import { join as join46 } from "path";
29206
- function runGitCommand(command, cwd) {
29207
- try {
29208
- return execSync7(command, { cwd, encoding: "utf-8", maxBuffer: 10 * 1024 * 1024 });
29209
- } catch {
29210
- return "";
29211
- }
29212
- }
29213
- function isGitRepository(path4) {
29214
- return existsSync45(join46(path4, ".git"));
29215
- }
29216
- function getGitCommits(repoPath, options = {}) {
29217
- if (!isGitRepository(repoPath)) {
29218
- return [];
29219
- }
29220
- const limit = options.commits || 100;
29221
- const args = [
29222
- "log",
29223
- `--max-count=${limit}`,
29224
- "--format=%H|||%h|||%an|||%aI|||%s|||%b|||END_COMMIT",
29225
- "--name-status"
29226
- ];
29227
- if (options.since) {
29228
- args.push(`--since="${options.since}"`);
29229
- }
29230
- if (options.until) {
29231
- args.push(`--until="${options.until}"`);
29232
- }
29233
- if (options.branch) {
29234
- args.push(options.branch);
29235
- }
29236
- if (options.author) {
29237
- args.push(`--author="${options.author}"`);
29238
- }
29239
- const output = runGitCommand(`git ${args.join(" ")}`, repoPath);
29240
- if (!output) return [];
29241
- const commits = [];
29242
- const commitBlocks = output.split("END_COMMIT").filter((b) => b.trim());
29243
- for (const block of commitBlocks) {
29244
- const lines = block.trim().split("\n");
29245
- if (lines.length === 0) continue;
29246
- const headerLine = lines[0];
29247
- const parts = headerLine.split("|||");
29248
- if (parts.length < 5) continue;
29249
- const [hash, shortHash, author, date, message, body] = parts;
29250
- const files = [];
29251
- for (let i = 1; i < lines.length; i++) {
29252
- const line = lines[i].trim();
29253
- if (!line) continue;
29254
- const match = line.match(/^([AMDRT])\d*\t(.+?)(?:\t(.+))?$/);
29255
- if (match) {
29256
- const [, status, path4, oldPath] = match;
29257
- files.push({
29258
- path: path4,
29259
- status: parseFileStatus(status),
29260
- additions: 0,
29261
- deletions: 0,
29262
- oldPath: oldPath || void 0
29263
- });
29264
- }
29265
- }
29266
- commits.push({
29267
- hash,
29268
- shortHash,
29269
- author,
29270
- date,
29271
- message,
29272
- body: body || void 0,
29273
- files
29274
- });
29275
- }
29276
- return commits;
29277
- }
29278
- function parseFileStatus(status) {
29279
- switch (status) {
29280
- case "A":
29281
- return "added";
29282
- case "D":
29283
- return "deleted";
29284
- case "R":
29285
- return "renamed";
29286
- default:
29287
- return "modified";
29288
- }
29289
- }
29290
- function categorizeCommit(message, body) {
29291
- const text = `${message} ${body || ""}`.toLowerCase();
29292
- if (text.includes("fix") || text.includes("bug") || text.includes("error") || text.includes("issue")) {
29293
- return "error_fix";
29294
- }
29295
- if (text.includes("refactor") || text.includes("clean") || text.includes("simplify")) {
29296
- return "refactor";
29297
- }
29298
- if (text.includes("workaround") || text.includes("hack") || text.includes("temporary")) {
29299
- return "workaround";
29300
- }
29301
- if (text.includes("debug") || text.includes("log") || text.includes("trace")) {
29302
- return "debugging";
29303
- }
29304
- return null;
29305
- }
29306
- function shouldSkipCommit(commit, ignorePatterns) {
29307
- const message = commit.message.toLowerCase();
29308
- for (const pattern of ignorePatterns) {
29309
- if (message.includes(pattern.toLowerCase())) {
29310
- return true;
29311
- }
29312
- }
29313
- if (message.startsWith("merge ") || message.startsWith("wip")) {
29314
- return true;
29315
- }
29316
- if (commit.files.length === 0) {
29317
- return true;
29887
+ capitalize(str) {
29888
+ return str.charAt(0).toUpperCase() + str.slice(1);
29318
29889
  }
29319
- return false;
29890
+ };
29891
+ function generatePrimer(projectPath, options = {}) {
29892
+ const generator = new PrimerGenerator(projectPath, options);
29893
+ return generator.generate();
29320
29894
  }
29321
- function extractPatternFromCommit(commit) {
29322
- const category = categorizeCommit(commit.message, commit.body);
29323
- if (!category) return null;
29324
- const id = `git-${commit.shortHash}`;
29325
- const title = formatTitle(commit.message);
29326
- const problem = extractProblem(commit);
29327
- const solution = extractSolution(commit);
29328
- const context = extractContext(commit);
29329
- if (!problem || !solution) return null;
29330
- return {
29331
- id,
29332
- category,
29333
- title,
29334
- problem,
29335
- solution,
29336
- context,
29337
- extractedAt: (/* @__PURE__ */ new Date()).toISOString(),
29338
- source: "git",
29339
- commitRange: { from: commit.hash, to: commit.hash },
29340
- approved: false,
29341
- confidence: calculateConfidence(commit, category)
29342
- };
29895
+ function generatePrimerForAgent(projectPath, agent, options = {}) {
29896
+ return generatePrimer(projectPath, { ...options, agents: [agent] });
29343
29897
  }
29344
- function formatTitle(message) {
29345
- return message.charAt(0).toUpperCase() + message.slice(1);
29898
+ function analyzeForPrimer(projectPath) {
29899
+ const generator = new PrimerGenerator(projectPath, { analyzeOnly: true });
29900
+ const result = generator.generate();
29901
+ return result.analysis;
29346
29902
  }
29347
- function extractProblem(commit) {
29348
- const message = commit.message.toLowerCase();
29349
- if (message.includes("fix:") || message.includes("fix(")) {
29350
- const match = commit.message.match(/fix[:(]\s*([^)]+)/i);
29351
- if (match) {
29352
- return `Issue: ${match[1]}`;
29353
- }
29354
- }
29355
- if (commit.body) {
29356
- const problemMatch = commit.body.match(/problem:?\s*(.+)/i);
29357
- if (problemMatch) {
29358
- return problemMatch[1].trim();
29359
- }
29360
- }
29361
- return `${commit.message} (from commit ${commit.shortHash})`;
29903
+
29904
+ // src/learning/types.ts
29905
+ var DEFAULT_LEARNING_CONFIG = {
29906
+ minSessionLength: 10,
29907
+ sensitivity: "medium",
29908
+ autoApprove: false,
29909
+ outputPath: "~/.skillkit/learned/",
29910
+ categories: ["error_fix", "refactor", "workaround", "debugging", "convention"],
29911
+ ignorePatterns: ["trivial_typo", "one_off_fix", "wip", "merge"]
29912
+ };
29913
+
29914
+ // src/learning/config.ts
29915
+ import { existsSync as existsSync47, readFileSync as readFileSync34, writeFileSync as writeFileSync25, mkdirSync as mkdirSync25 } from "fs";
29916
+ import { join as join48, dirname as dirname16 } from "path";
29917
+ import { homedir as homedir14 } from "os";
29918
+ import yaml from "yaml";
29919
+ function getDefaultConfigPath() {
29920
+ return join48(homedir14(), ".skillkit", "learning.yaml");
29362
29921
  }
29363
- function extractSolution(commit) {
29364
- if (commit.body) {
29365
- const solutionMatch = commit.body.match(/solution:?\s*(.+)/i);
29366
- if (solutionMatch) {
29367
- return solutionMatch[1].trim();
29368
- }
29369
- }
29370
- const files = commit.files.map((f) => f.path).join(", ");
29371
- return `Modified: ${files}`;
29922
+ function getDefaultStorePath() {
29923
+ return join48(homedir14(), ".skillkit", "learned", "patterns.json");
29372
29924
  }
29373
- function extractContext(commit) {
29374
- const files = commit.files;
29375
- const extensions = new Set(files.map((f) => f.path.split(".").pop() || ""));
29376
- const directories = new Set(files.map((f) => f.path.split("/")[0]));
29377
- const parts = [];
29378
- if (extensions.size > 0) {
29379
- parts.push(`Files: ${Array.from(extensions).filter((e) => e).join(", ")}`);
29925
+ function loadLearningConfig(configPath) {
29926
+ const path4 = configPath || getDefaultConfigPath();
29927
+ if (!existsSync47(path4)) {
29928
+ return DEFAULT_LEARNING_CONFIG;
29380
29929
  }
29381
- if (directories.size > 0 && directories.size <= 3) {
29382
- parts.push(`Areas: ${Array.from(directories).join(", ")}`);
29930
+ try {
29931
+ const content = readFileSync34(path4, "utf-8");
29932
+ const config = yaml.parse(content);
29933
+ return { ...DEFAULT_LEARNING_CONFIG, ...config };
29934
+ } catch {
29935
+ return DEFAULT_LEARNING_CONFIG;
29383
29936
  }
29384
- return parts.join(". ") || "General codebase";
29385
29937
  }
29386
- function calculateConfidence(commit, category) {
29387
- let confidence = 0.5;
29388
- if (commit.body && commit.body.length > 50) {
29389
- confidence += 0.1;
29938
+ function saveLearningConfig(config, configPath) {
29939
+ const path4 = configPath || getDefaultConfigPath();
29940
+ const dir = dirname16(path4);
29941
+ if (!existsSync47(dir)) {
29942
+ mkdirSync25(dir, { recursive: true });
29390
29943
  }
29391
- if (commit.message.match(/^(fix|feat|refactor|docs|test|chore)(\(.+\))?:/)) {
29392
- confidence += 0.1;
29944
+ const content = yaml.stringify(config);
29945
+ writeFileSync25(path4, content);
29946
+ }
29947
+ function loadPatternStore(storePath) {
29948
+ const path4 = storePath || getDefaultStorePath();
29949
+ if (!existsSync47(path4)) {
29950
+ return {
29951
+ version: 1,
29952
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
29953
+ patterns: [],
29954
+ evolvingPatterns: []
29955
+ };
29393
29956
  }
29394
- if (commit.files.length > 0 && commit.files.length < 10) {
29395
- confidence += 0.1;
29957
+ try {
29958
+ const content = readFileSync34(path4, "utf-8");
29959
+ return JSON.parse(content);
29960
+ } catch {
29961
+ return {
29962
+ version: 1,
29963
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
29964
+ patterns: [],
29965
+ evolvingPatterns: []
29966
+ };
29396
29967
  }
29397
- if (category === "error_fix" || category === "workaround") {
29398
- confidence += 0.05;
29968
+ }
29969
+ function savePatternStore(store, storePath) {
29970
+ const path4 = storePath || getDefaultStorePath();
29971
+ const dir = dirname16(path4);
29972
+ if (!existsSync47(dir)) {
29973
+ mkdirSync25(dir, { recursive: true });
29399
29974
  }
29400
- return Math.min(0.9, confidence);
29975
+ store.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
29976
+ const content = JSON.stringify(store, null, 2);
29977
+ writeFileSync25(path4, content);
29401
29978
  }
29402
- function analyzeGitHistory(repoPath, options = {}) {
29403
- const commits = getGitCommits(repoPath, options);
29404
- const ignorePatterns = ["merge", "wip", "typo"];
29405
- const patterns = [];
29406
- const summary = {
29407
- totalCommits: commits.length,
29408
- totalFilesChanged: 0,
29409
- errorFixes: 0,
29410
- refactors: 0,
29411
- features: 0,
29412
- documentation: 0,
29413
- tests: 0
29414
- };
29415
- const languages = /* @__PURE__ */ new Set();
29416
- const frameworks = /* @__PURE__ */ new Set();
29417
- for (const commit of commits) {
29418
- if (shouldSkipCommit(commit, ignorePatterns)) {
29419
- continue;
29420
- }
29421
- summary.totalFilesChanged += commit.files.length;
29422
- for (const file of commit.files) {
29423
- const ext = file.path.split(".").pop()?.toLowerCase();
29424
- if (ext) {
29425
- if (["ts", "tsx"].includes(ext)) languages.add("TypeScript");
29426
- else if (["js", "jsx"].includes(ext)) languages.add("JavaScript");
29427
- else if (ext === "py") languages.add("Python");
29428
- else if (ext === "go") languages.add("Go");
29429
- else if (ext === "rs") languages.add("Rust");
29430
- else if (ext === "java") languages.add("Java");
29431
- }
29432
- if (file.path.includes("next")) frameworks.add("Next.js");
29433
- if (file.path.includes("react")) frameworks.add("React");
29434
- if (file.path.includes("vue")) frameworks.add("Vue");
29435
- }
29436
- const category = categorizeCommit(commit.message, commit.body);
29437
- if (category === "error_fix") summary.errorFixes++;
29438
- else if (category === "refactor") summary.refactors++;
29439
- if (commit.message.toLowerCase().includes("feat")) summary.features++;
29440
- if (commit.message.toLowerCase().includes("doc")) summary.documentation++;
29441
- if (commit.message.toLowerCase().includes("test")) summary.tests++;
29442
- const pattern = extractPatternFromCommit(commit);
29443
- if (pattern) {
29444
- patterns.push(pattern);
29445
- }
29979
+ function addPattern(pattern, storePath) {
29980
+ const store = loadPatternStore(storePath);
29981
+ const existingIndex = store.patterns.findIndex((p) => p.id === pattern.id);
29982
+ if (existingIndex >= 0) {
29983
+ store.patterns[existingIndex] = pattern;
29984
+ } else {
29985
+ store.patterns.push(pattern);
29446
29986
  }
29447
- const dates = commits.map((c) => c.date).sort();
29448
- return {
29449
- patterns,
29450
- commitCount: commits.length,
29451
- dateRange: {
29452
- from: dates[0] || "",
29453
- to: dates[dates.length - 1] || ""
29454
- },
29455
- languages: Array.from(languages),
29456
- frameworks: Array.from(frameworks),
29457
- summary
29458
- };
29987
+ savePatternStore(store, storePath);
29988
+ return store;
29459
29989
  }
29460
- function getRecentBugFixes(repoPath, limit = 20) {
29461
- const result = analyzeGitHistory(repoPath, { commits: limit * 3 });
29462
- return result.patterns.filter((p) => p.category === "error_fix").slice(0, limit);
29990
+ function removePattern(patternId, storePath) {
29991
+ const store = loadPatternStore(storePath);
29992
+ store.patterns = store.patterns.filter((p) => p.id !== patternId);
29993
+ store.evolvingPatterns = store.evolvingPatterns.filter((p) => p.id !== patternId);
29994
+ savePatternStore(store, storePath);
29995
+ return store;
29463
29996
  }
29464
- function getRecentRefactors(repoPath, limit = 20) {
29465
- const result = analyzeGitHistory(repoPath, { commits: limit * 3 });
29466
- return result.patterns.filter((p) => p.category === "refactor").slice(0, limit);
29997
+ function getPattern(patternId, storePath) {
29998
+ const store = loadPatternStore(storePath);
29999
+ return store.patterns.find((p) => p.id === patternId) || null;
30000
+ }
30001
+ function getEvolvingPattern(patternId, storePath) {
30002
+ const store = loadPatternStore(storePath);
30003
+ return store.evolvingPatterns.find((p) => p.id === patternId) || null;
30004
+ }
30005
+ function getAllPatterns(storePath) {
30006
+ const store = loadPatternStore(storePath);
30007
+ return store.patterns;
30008
+ }
30009
+ function getPatternsByCategory(category, storePath) {
30010
+ const store = loadPatternStore(storePath);
30011
+ return store.patterns.filter((p) => p.category === category);
30012
+ }
30013
+ function getApprovedPatterns(storePath) {
30014
+ const store = loadPatternStore(storePath);
30015
+ return store.patterns.filter((p) => p.approved);
29467
30016
  }
29468
30017
 
29469
30018
  // src/learning/extractor.ts
@@ -29716,8 +30265,8 @@ function mergePatterns(existing, newPatterns) {
29716
30265
  }
29717
30266
 
29718
30267
  // src/learning/generator.ts
29719
- import { writeFileSync as writeFileSync24, mkdirSync as mkdirSync24, existsSync as existsSync46 } from "fs";
29720
- import { join as join47 } from "path";
30268
+ import { writeFileSync as writeFileSync26, mkdirSync as mkdirSync26, existsSync as existsSync48 } from "fs";
30269
+ import { join as join49 } from "path";
29721
30270
  import { homedir as homedir15 } from "os";
29722
30271
  function generateSkillFromPatterns(patterns, options = {}) {
29723
30272
  const minConfidence = options.minConfidence ?? 0.5;
@@ -29808,12 +30357,12 @@ function generateSkillContent2(name, patterns, category) {
29808
30357
  return lines.join("\n");
29809
30358
  }
29810
30359
  function saveGeneratedSkill(skill, outputDir) {
29811
- const dir = outputDir || join47(homedir15(), ".skillkit", "skills", "learned");
29812
- if (!existsSync46(dir)) {
29813
- mkdirSync24(dir, { recursive: true });
30360
+ const dir = outputDir || join49(homedir15(), ".skillkit", "skills", "learned");
30361
+ if (!existsSync48(dir)) {
30362
+ mkdirSync26(dir, { recursive: true });
29814
30363
  }
29815
- const filepath = join47(dir, skill.filename);
29816
- writeFileSync24(filepath, skill.content);
30364
+ const filepath = join49(dir, skill.filename);
30365
+ writeFileSync26(filepath, skill.content);
29817
30366
  return filepath;
29818
30367
  }
29819
30368
  function generatePatternReport(patterns) {
@@ -30043,8 +30592,8 @@ var DEFAULT_PROFILE_CONFIG = {
30043
30592
  };
30044
30593
 
30045
30594
  // src/profiles/manager.ts
30046
- import { existsSync as existsSync47, readFileSync as readFileSync33, writeFileSync as writeFileSync25, mkdirSync as mkdirSync25 } from "fs";
30047
- import { join as join48, dirname as dirname17 } from "path";
30595
+ import { existsSync as existsSync49, readFileSync as readFileSync35, writeFileSync as writeFileSync27, mkdirSync as mkdirSync27 } from "fs";
30596
+ import { join as join50, dirname as dirname17 } from "path";
30048
30597
  import { homedir as homedir16 } from "os";
30049
30598
  import yaml2 from "yaml";
30050
30599
  var BUILTIN_PROFILES = [
@@ -30125,15 +30674,15 @@ var BUILTIN_PROFILES = [
30125
30674
  }
30126
30675
  ];
30127
30676
  function getConfigPath() {
30128
- return join48(homedir16(), ".skillkit", "profiles.yaml");
30677
+ return join50(homedir16(), ".skillkit", "profiles.yaml");
30129
30678
  }
30130
30679
  function loadProfileConfig() {
30131
30680
  const path4 = getConfigPath();
30132
- if (!existsSync47(path4)) {
30681
+ if (!existsSync49(path4)) {
30133
30682
  return DEFAULT_PROFILE_CONFIG;
30134
30683
  }
30135
30684
  try {
30136
- const content = readFileSync33(path4, "utf-8");
30685
+ const content = readFileSync35(path4, "utf-8");
30137
30686
  return { ...DEFAULT_PROFILE_CONFIG, ...yaml2.parse(content) };
30138
30687
  } catch {
30139
30688
  return DEFAULT_PROFILE_CONFIG;
@@ -30142,10 +30691,10 @@ function loadProfileConfig() {
30142
30691
  function saveProfileConfig(config) {
30143
30692
  const path4 = getConfigPath();
30144
30693
  const dir = dirname17(path4);
30145
- if (!existsSync47(dir)) {
30146
- mkdirSync25(dir, { recursive: true });
30694
+ if (!existsSync49(dir)) {
30695
+ mkdirSync27(dir, { recursive: true });
30147
30696
  }
30148
- writeFileSync25(path4, yaml2.stringify(config));
30697
+ writeFileSync27(path4, yaml2.stringify(config));
30149
30698
  }
30150
30699
  function getActiveProfile() {
30151
30700
  const config = loadProfileConfig();
@@ -30212,8 +30761,8 @@ var DEFAULT_GUIDELINE_CONFIG = {
30212
30761
  };
30213
30762
 
30214
30763
  // src/guidelines/manager.ts
30215
- import { existsSync as existsSync48, readFileSync as readFileSync34, writeFileSync as writeFileSync26, mkdirSync as mkdirSync26 } from "fs";
30216
- import { join as join49, dirname as dirname18 } from "path";
30764
+ import { existsSync as existsSync50, readFileSync as readFileSync36, writeFileSync as writeFileSync28, mkdirSync as mkdirSync28 } from "fs";
30765
+ import { join as join51, dirname as dirname18 } from "path";
30217
30766
  import { homedir as homedir17 } from "os";
30218
30767
  import yaml3 from "yaml";
30219
30768
  var BUILTIN_GUIDELINES = [
@@ -30391,15 +30940,15 @@ Types: feat, fix, docs, style, refactor, test, chore`
30391
30940
  }
30392
30941
  ];
30393
30942
  function getConfigPath2() {
30394
- return join49(homedir17(), ".skillkit", "guidelines.yaml");
30943
+ return join51(homedir17(), ".skillkit", "guidelines.yaml");
30395
30944
  }
30396
30945
  function loadGuidelineConfig() {
30397
30946
  const path4 = getConfigPath2();
30398
- if (!existsSync48(path4)) {
30947
+ if (!existsSync50(path4)) {
30399
30948
  return DEFAULT_GUIDELINE_CONFIG;
30400
30949
  }
30401
30950
  try {
30402
- const content = readFileSync34(path4, "utf-8");
30951
+ const content = readFileSync36(path4, "utf-8");
30403
30952
  return { ...DEFAULT_GUIDELINE_CONFIG, ...yaml3.parse(content) };
30404
30953
  } catch {
30405
30954
  return DEFAULT_GUIDELINE_CONFIG;
@@ -30408,10 +30957,10 @@ function loadGuidelineConfig() {
30408
30957
  function saveGuidelineConfig(config) {
30409
30958
  const path4 = getConfigPath2();
30410
30959
  const dir = dirname18(path4);
30411
- if (!existsSync48(dir)) {
30412
- mkdirSync26(dir, { recursive: true });
30960
+ if (!existsSync50(dir)) {
30961
+ mkdirSync28(dir, { recursive: true });
30413
30962
  }
30414
- writeFileSync26(path4, yaml3.stringify(config));
30963
+ writeFileSync28(path4, yaml3.stringify(config));
30415
30964
  }
30416
30965
  function getGuideline(id) {
30417
30966
  const builtin = BUILTIN_GUIDELINES.find((g) => g.id === id);
@@ -30493,7 +31042,7 @@ init_generator();
30493
31042
 
30494
31043
  // src/tree/serializer.ts
30495
31044
  init_types3();
30496
- import { readFileSync as readFileSync35, writeFileSync as writeFileSync27, existsSync as existsSync49, mkdirSync as mkdirSync27 } from "fs";
31045
+ import { readFileSync as readFileSync37, writeFileSync as writeFileSync29, existsSync as existsSync51, mkdirSync as mkdirSync29 } from "fs";
30497
31046
  import { dirname as dirname19 } from "path";
30498
31047
  var TREE_FILE_NAME = "skill-tree.json";
30499
31048
  function serializeTree(tree) {
@@ -30505,18 +31054,18 @@ function deserializeTree(json) {
30505
31054
  }
30506
31055
  function saveTree(tree, path4) {
30507
31056
  const dir = dirname19(path4);
30508
- if (!existsSync49(dir)) {
30509
- mkdirSync27(dir, { recursive: true });
31057
+ if (!existsSync51(dir)) {
31058
+ mkdirSync29(dir, { recursive: true });
30510
31059
  }
30511
31060
  const json = serializeTree(tree);
30512
- writeFileSync27(path4, json, "utf-8");
31061
+ writeFileSync29(path4, json, "utf-8");
30513
31062
  }
30514
31063
  function loadTree(path4) {
30515
- if (!existsSync49(path4)) {
31064
+ if (!existsSync51(path4)) {
30516
31065
  return null;
30517
31066
  }
30518
31067
  try {
30519
- const json = readFileSync35(path4, "utf-8");
31068
+ const json = readFileSync37(path4, "utf-8");
30520
31069
  return deserializeTree(json);
30521
31070
  } catch {
30522
31071
  return null;
@@ -31471,12 +32020,12 @@ function createExecutionManager(config) {
31471
32020
  }
31472
32021
 
31473
32022
  // src/execution/mode.ts
31474
- import { existsSync as existsSync50, readFileSync as readFileSync36 } from "fs";
31475
- import { join as join50 } from "path";
32023
+ import { existsSync as existsSync52, readFileSync as readFileSync38 } from "fs";
32024
+ import { join as join52 } from "path";
31476
32025
  import { homedir as homedir18 } from "os";
31477
32026
  var DEFAULT_MCP_CONFIG_PATHS = [
31478
- join50(homedir18(), ".mcp.json"),
31479
- join50(homedir18(), ".config", "claude", "mcp.json"),
32027
+ join52(homedir18(), ".mcp.json"),
32028
+ join52(homedir18(), ".config", "claude", "mcp.json"),
31480
32029
  ".mcp.json",
31481
32030
  "mcp.json"
31482
32031
  ];
@@ -31525,8 +32074,8 @@ function detectMcpServers(configPaths) {
31525
32074
  for (const configPath of configPaths) {
31526
32075
  try {
31527
32076
  const fullPath = configPath.startsWith("~") ? configPath.replace("~", process.env.HOME || "") : configPath;
31528
- if (existsSync50(fullPath)) {
31529
- const content = readFileSync36(fullPath, "utf-8");
32077
+ if (existsSync52(fullPath)) {
32078
+ const content = readFileSync38(fullPath, "utf-8");
31530
32079
  const config = JSON.parse(content);
31531
32080
  if (config.mcpServers) {
31532
32081
  servers.push(...Object.keys(config.mcpServers));
@@ -31664,8 +32213,8 @@ init_expansion();
31664
32213
  init_hybrid();
31665
32214
 
31666
32215
  // src/registry/community.ts
31667
- import { readFileSync as readFileSync37, existsSync as existsSync51 } from "fs";
31668
- import { join as join51, dirname as dirname20 } from "path";
32216
+ import { readFileSync as readFileSync39, existsSync as existsSync53 } from "fs";
32217
+ import { join as join53, dirname as dirname20 } from "path";
31669
32218
  import { fileURLToPath as fileURLToPath2 } from "url";
31670
32219
  var CommunityRegistry = class {
31671
32220
  constructor(skillsMdPath) {
@@ -31678,13 +32227,13 @@ var CommunityRegistry = class {
31678
32227
  if (this.loaded) return;
31679
32228
  this.loaded = true;
31680
32229
  const paths = this.skillsMdPath ? [this.skillsMdPath] : [
31681
- join51(process.cwd(), "registry", "SKILLS.md"),
31682
- join51(dirname20(fileURLToPath2(import.meta.url)), "..", "..", "..", "..", "registry", "SKILLS.md")
32230
+ join53(process.cwd(), "registry", "SKILLS.md"),
32231
+ join53(dirname20(fileURLToPath2(import.meta.url)), "..", "..", "..", "..", "registry", "SKILLS.md")
31683
32232
  ];
31684
32233
  for (const path4 of paths) {
31685
- if (!existsSync51(path4)) continue;
32234
+ if (!existsSync53(path4)) continue;
31686
32235
  try {
31687
- const content = readFileSync37(path4, "utf-8");
32236
+ const content = readFileSync39(path4, "utf-8");
31688
32237
  this.entries = this.parse(content);
31689
32238
  return;
31690
32239
  } catch {
@@ -31983,8 +32532,8 @@ var RelevanceRanker = class {
31983
32532
  };
31984
32533
 
31985
32534
  // src/parser/references.ts
31986
- import { readdirSync as readdirSync13, statSync as statSync10, existsSync as existsSync52 } from "fs";
31987
- import { join as join52 } from "path";
32535
+ import { readdirSync as readdirSync14, statSync as statSync10, existsSync as existsSync54 } from "fs";
32536
+ import { join as join54 } from "path";
31988
32537
  var REFERENCE_DIRS = ["references", "resources", "docs", "examples", "assets", "scripts"];
31989
32538
  var DIR_TYPE_MAP = {
31990
32539
  references: "resource",
@@ -31997,8 +32546,8 @@ var DIR_TYPE_MAP = {
31997
32546
  function discoverReferences(skillDir) {
31998
32547
  const refs = [];
31999
32548
  for (const dir of REFERENCE_DIRS) {
32000
- const fullPath = join52(skillDir, dir);
32001
- if (!existsSync52(fullPath)) continue;
32549
+ const fullPath = join54(skillDir, dir);
32550
+ if (!existsSync54(fullPath)) continue;
32002
32551
  try {
32003
32552
  const stat = statSync10(fullPath);
32004
32553
  if (!stat.isDirectory()) continue;
@@ -32007,14 +32556,14 @@ function discoverReferences(skillDir) {
32007
32556
  }
32008
32557
  const type = DIR_TYPE_MAP[dir] || "resource";
32009
32558
  try {
32010
- const entries = readdirSync13(fullPath);
32559
+ const entries = readdirSync14(fullPath);
32011
32560
  for (const entry of entries) {
32012
- const entryPath = join52(fullPath, entry);
32561
+ const entryPath = join54(fullPath, entry);
32013
32562
  try {
32014
32563
  const entryStat = statSync10(entryPath);
32015
32564
  if (entryStat.isFile()) {
32016
32565
  refs.push({
32017
- path: join52(dir, entry),
32566
+ path: join54(dir, entry),
32018
32567
  type,
32019
32568
  name: entry
32020
32569
  });
@@ -33181,7 +33730,7 @@ var SecretsAnalyzer = class {
33181
33730
 
33182
33731
  // src/scanner/scanner.ts
33183
33732
  import { readdir } from "fs/promises";
33184
- import { join as join53, basename as basename20 } from "path";
33733
+ import { join as join55, basename as basename20 } from "path";
33185
33734
  var SEVERITY_ORDER = {
33186
33735
  ["critical" /* CRITICAL */]: 5,
33187
33736
  ["high" /* HIGH */]: 4,
@@ -33200,7 +33749,7 @@ async function discoverFiles(dirPath) {
33200
33749
  return;
33201
33750
  }
33202
33751
  for (const entry of entries) {
33203
- const fullPath = join53(dir, entry.name);
33752
+ const fullPath = join55(dir, entry.name);
33204
33753
  if (entry.name.startsWith(".") && entry.name !== ".env" && !entry.name.startsWith(".env.")) continue;
33205
33754
  if (entry.name === "node_modules") continue;
33206
33755
  if (entry.isDirectory()) {
@@ -33294,7 +33843,7 @@ var SkillScanner = class {
33294
33843
 
33295
33844
  // src/scanner/reporter.ts
33296
33845
  import { basename as basename21 } from "path";
33297
- var SCANNER_VERSION = true ? "1.17.0" : "0.0.0";
33846
+ var SCANNER_VERSION = true ? "1.19.0" : "0.0.0";
33298
33847
  var SEVERITY_COLORS = {
33299
33848
  ["critical" /* CRITICAL */]: "\x1B[91m",
33300
33849
  ["high" /* HIGH */]: "\x1B[31m",
@@ -33567,8 +34116,8 @@ function getDefaultSeverity(category) {
33567
34116
  }
33568
34117
 
33569
34118
  // src/validation/spec-validator.ts
33570
- import { readFileSync as readFileSync38, existsSync as existsSync53 } from "fs";
33571
- import { join as join54, basename as basename22 } from "path";
34119
+ import { readFileSync as readFileSync40, existsSync as existsSync55 } from "fs";
34120
+ import { join as join56, basename as basename22 } from "path";
33572
34121
  var NAME_PATTERN = /^[a-z0-9]+(-[a-z0-9]+)*$/;
33573
34122
  var SPEC_VERSION = "1.0";
33574
34123
  var SpecValidator = class {
@@ -33576,12 +34125,12 @@ var SpecValidator = class {
33576
34125
  const checks = [];
33577
34126
  const errors = [];
33578
34127
  const warnings = [];
33579
- const skillMdPath = skillPath.endsWith(".md") ? skillPath : join54(skillPath, "SKILL.md");
33580
- if (!existsSync53(skillMdPath)) {
34128
+ const skillMdPath = skillPath.endsWith(".md") ? skillPath : join56(skillPath, "SKILL.md");
34129
+ if (!existsSync55(skillMdPath)) {
33581
34130
  errors.push(`SKILL.md not found at ${skillMdPath}`);
33582
34131
  return { valid: false, errors, warnings, specVersion: SPEC_VERSION, checks };
33583
34132
  }
33584
- const raw = readFileSync38(skillMdPath, "utf-8");
34133
+ const raw = readFileSync40(skillMdPath, "utf-8");
33585
34134
  const { frontmatter, body } = stripFrontmatter(raw);
33586
34135
  const hasName = typeof frontmatter.name === "string" && frontmatter.name.length > 0;
33587
34136
  checks.push({
@@ -33648,7 +34197,7 @@ var SpecValidator = class {
33648
34197
  });
33649
34198
  }
33650
34199
  if (hasName) {
33651
- const skillDir = skillPath.endsWith(".md") ? join54(skillPath, "..") : skillPath;
34200
+ const skillDir = skillPath.endsWith(".md") ? join56(skillPath, "..") : skillPath;
33652
34201
  const dirName = basename22(skillDir);
33653
34202
  const nameStr = frontmatter.name;
33654
34203
  const nameMatchesDir = nameStr === dirName;
@@ -33681,8 +34230,8 @@ var SpecValidator = class {
33681
34230
  };
33682
34231
 
33683
34232
  // src/agents-md/generator.ts
33684
- import { existsSync as existsSync54, readFileSync as readFileSync39 } from "fs";
33685
- import { join as join55 } from "path";
34233
+ import { existsSync as existsSync56, readFileSync as readFileSync41 } from "fs";
34234
+ import { join as join57 } from "path";
33686
34235
  function escapeTableCell(text) {
33687
34236
  return text.replace(/\|/g, "\\|").replace(/\n/g, " ");
33688
34237
  }
@@ -33711,7 +34260,7 @@ var AgentsMdGenerator = class {
33711
34260
  managed: true
33712
34261
  });
33713
34262
  if (this.config.includeSkills !== false) {
33714
- const skillsContent = this.generateSkillsSection(findAllSkills([join55(this.config.projectPath, "skills")]));
34263
+ const skillsContent = this.generateSkillsSection(findAllSkills([join57(this.config.projectPath, "skills")]));
33715
34264
  if (skillsContent) {
33716
34265
  sections.push({
33717
34266
  id: "installed-skills",
@@ -33754,7 +34303,7 @@ var AgentsMdGenerator = class {
33754
34303
  return {
33755
34304
  content,
33756
34305
  sections,
33757
- path: join55(this.config.projectPath, "AGENTS.md")
34306
+ path: join57(this.config.projectPath, "AGENTS.md")
33758
34307
  };
33759
34308
  }
33760
34309
  generateSkillsSection(skills) {
@@ -33785,12 +34334,12 @@ var AgentsMdGenerator = class {
33785
34334
  return lines.join("\n");
33786
34335
  }
33787
34336
  generateBuildSection() {
33788
- const packageJsonPath = join55(this.config.projectPath, "package.json");
33789
- if (!existsSync54(packageJsonPath)) {
34337
+ const packageJsonPath = join57(this.config.projectPath, "package.json");
34338
+ if (!existsSync56(packageJsonPath)) {
33790
34339
  return "";
33791
34340
  }
33792
34341
  try {
33793
- const pkg = JSON.parse(readFileSync39(packageJsonPath, "utf-8"));
34342
+ const pkg = JSON.parse(readFileSync41(packageJsonPath, "utf-8"));
33794
34343
  const scripts = pkg.scripts;
33795
34344
  if (!scripts || Object.keys(scripts).length === 0) {
33796
34345
  return "";
@@ -33942,7 +34491,7 @@ var AgentsMdParser = class {
33942
34491
  };
33943
34492
 
33944
34493
  // src/save/extractor.ts
33945
- import { existsSync as existsSync55, readFileSync as readFileSync40 } from "fs";
34494
+ import { existsSync as existsSync57, readFileSync as readFileSync42 } from "fs";
33946
34495
  import { basename as basename23, extname as extname7 } from "path";
33947
34496
  import TurndownService from "turndown";
33948
34497
  var LANGUAGE_MAP = {
@@ -34044,10 +34593,10 @@ var ContentExtractor = class {
34044
34593
  };
34045
34594
  }
34046
34595
  extractFromFile(filePath, options) {
34047
- if (!existsSync55(filePath)) {
34596
+ if (!existsSync57(filePath)) {
34048
34597
  throw new Error(`File not found: ${filePath}`);
34049
34598
  }
34050
- const raw = readFileSync40(filePath, "utf-8");
34599
+ const raw = readFileSync42(filePath, "utf-8");
34051
34600
  const name = basename23(filePath);
34052
34601
  const language = this.detectLanguage(name);
34053
34602
  const isCode = language !== void 0 && language !== "markdown";
@@ -34247,8 +34796,8 @@ var AutoTagger = class {
34247
34796
  };
34248
34797
 
34249
34798
  // src/save/skill-generator.ts
34250
- import { mkdirSync as mkdirSync28, writeFileSync as writeFileSync28 } from "fs";
34251
- import { join as join56 } from "path";
34799
+ import { mkdirSync as mkdirSync30, writeFileSync as writeFileSync30 } from "fs";
34800
+ import { join as join58 } from "path";
34252
34801
  import { homedir as homedir19 } from "os";
34253
34802
  var MAX_NAME_LENGTH = 64;
34254
34803
  var SUMMARY_LINE_LIMIT = 100;
@@ -34269,14 +34818,14 @@ var SkillGenerator = class {
34269
34818
  ${body}
34270
34819
  `;
34271
34820
  const outputDir = options.outputDir ?? this.defaultOutputDir(name, options.global);
34272
- mkdirSync28(outputDir, { recursive: true });
34273
- const skillPath = join56(outputDir, "SKILL.md");
34274
- writeFileSync28(skillPath, skillMd, "utf-8");
34821
+ mkdirSync30(outputDir, { recursive: true });
34822
+ const skillPath = join58(outputDir, "SKILL.md");
34823
+ writeFileSync30(skillPath, skillMd, "utf-8");
34275
34824
  if (needsSplit) {
34276
- const refsDir = join56(outputDir, "references");
34277
- mkdirSync28(refsDir, { recursive: true });
34278
- writeFileSync28(
34279
- join56(refsDir, "full-content.md"),
34825
+ const refsDir = join58(outputDir, "references");
34826
+ mkdirSync30(refsDir, { recursive: true });
34827
+ writeFileSync30(
34828
+ join58(refsDir, "full-content.md"),
34280
34829
  content.content,
34281
34830
  "utf-8"
34282
34831
  );
@@ -34318,9 +34867,9 @@ ${yamlTags}` : null,
34318
34867
  }
34319
34868
  defaultOutputDir(name, global) {
34320
34869
  if (global) {
34321
- return join56(homedir19(), ".skillkit", "skills", name);
34870
+ return join58(homedir19(), ".skillkit", "skills", name);
34322
34871
  }
34323
- return join56(".skillkit", "skills", name);
34872
+ return join58(".skillkit", "skills", name);
34324
34873
  }
34325
34874
  };
34326
34875
  export {
@@ -34335,6 +34884,7 @@ export {
34335
34884
  AISkillGenerator,
34336
34885
  ALL_AGENT_DISCOVERY_PATHS,
34337
34886
  APIBasedCompressor,
34887
+ ActivityLog,
34338
34888
  AgentFrontmatter,
34339
34889
  AgentHook,
34340
34890
  AgentLocation,
@@ -34406,6 +34956,7 @@ export {
34406
34956
  INDEX_CACHE_HOURS,
34407
34957
  INDEX_PATH,
34408
34958
  InjectionDetector,
34959
+ IssuePlanner,
34409
34960
  KNOWN_SKILL_REPOS,
34410
34961
  LearningConsolidator,
34411
34962
  LearningStore,
@@ -34462,6 +35013,7 @@ export {
34462
35013
  STEP_HANDLERS,
34463
35014
  SecretsAnalyzer,
34464
35015
  SessionEndHook,
35016
+ SessionExplainer,
34465
35017
  SessionManager,
34466
35018
  SessionStartHook,
34467
35019
  Severity,
@@ -34485,6 +35037,7 @@ export {
34485
35037
  SkillWizard,
34486
35038
  SkillkitConfig,
34487
35039
  SkillsSource,
35040
+ SnapshotManager,
34488
35041
  SpecValidator,
34489
35042
  StaticAnalyzer,
34490
35043
  TAG_TO_CATEGORY,
@@ -34548,6 +35101,7 @@ export {
34548
35101
  createHookManager,
34549
35102
  createHybridSearchPipeline,
34550
35103
  createInitialState,
35104
+ createIssuePlanner,
34551
35105
  createMarketplaceAggregator,
34552
35106
  createMemoryCompressor,
34553
35107
  createMemoryEnabledEngine,