kirograph 0.27.2 → 0.28.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.
Files changed (155) hide show
  1. package/README.md +14 -7
  2. package/dist/bin/commands/annotations.js +56 -0
  3. package/dist/bin/commands/annotations.js.map +7 -0
  4. package/dist/bin/commands/ast-rewrite.js +55 -0
  5. package/dist/bin/commands/ast-rewrite.js.map +7 -0
  6. package/dist/bin/commands/bench.js +103 -0
  7. package/dist/bin/commands/bench.js.map +7 -0
  8. package/dist/bin/commands/branch.js +133 -0
  9. package/dist/bin/commands/branch.js.map +7 -0
  10. package/dist/bin/commands/changelog.js +55 -0
  11. package/dist/bin/commands/changelog.js.map +7 -0
  12. package/dist/bin/commands/commit-context.js +55 -0
  13. package/dist/bin/commands/commit-context.js.map +7 -0
  14. package/dist/bin/commands/complexity.js +60 -0
  15. package/dist/bin/commands/complexity.js.map +7 -0
  16. package/dist/bin/commands/cost.js +146 -0
  17. package/dist/bin/commands/cost.js.map +7 -0
  18. package/dist/bin/commands/dependency-depth.js +55 -0
  19. package/dist/bin/commands/dependency-depth.js.map +7 -0
  20. package/dist/bin/commands/diff-context.js +55 -0
  21. package/dist/bin/commands/diff-context.js.map +7 -0
  22. package/dist/bin/commands/distribution.js +56 -0
  23. package/dist/bin/commands/distribution.js.map +7 -0
  24. package/dist/bin/commands/doc-coverage.js +56 -0
  25. package/dist/bin/commands/doc-coverage.js.map +7 -0
  26. package/dist/bin/commands/doctor.js +202 -0
  27. package/dist/bin/commands/doctor.js.map +7 -0
  28. package/dist/bin/commands/dsm.js +56 -0
  29. package/dist/bin/commands/dsm.js.map +7 -0
  30. package/dist/bin/commands/gini.js +55 -0
  31. package/dist/bin/commands/gini.js.map +7 -0
  32. package/dist/bin/commands/god-class.js +56 -0
  33. package/dist/bin/commands/god-class.js.map +7 -0
  34. package/dist/bin/commands/health.js +55 -0
  35. package/dist/bin/commands/health.js.map +7 -0
  36. package/dist/bin/commands/help.js +224 -45
  37. package/dist/bin/commands/help.js.map +2 -2
  38. package/dist/bin/commands/inheritance-depth.js +56 -0
  39. package/dist/bin/commands/inheritance-depth.js.map +7 -0
  40. package/dist/bin/commands/insert-at.js +55 -0
  41. package/dist/bin/commands/insert-at.js.map +7 -0
  42. package/dist/bin/commands/largest.js +56 -0
  43. package/dist/bin/commands/largest.js.map +7 -0
  44. package/dist/bin/commands/manifest.js +158 -0
  45. package/dist/bin/commands/manifest.js.map +7 -0
  46. package/dist/bin/commands/module-api.js +57 -0
  47. package/dist/bin/commands/module-api.js.map +7 -0
  48. package/dist/bin/commands/monitor.js +91 -0
  49. package/dist/bin/commands/monitor.js.map +7 -0
  50. package/dist/bin/commands/multi-replace.js +66 -0
  51. package/dist/bin/commands/multi-replace.js.map +7 -0
  52. package/dist/bin/commands/pr-context.js +55 -0
  53. package/dist/bin/commands/pr-context.js.map +7 -0
  54. package/dist/bin/commands/query.js +19 -1
  55. package/dist/bin/commands/query.js.map +3 -3
  56. package/dist/bin/commands/rank.js +56 -0
  57. package/dist/bin/commands/rank.js.map +7 -0
  58. package/dist/bin/commands/read.js +1 -1
  59. package/dist/bin/commands/read.js.map +2 -2
  60. package/dist/bin/commands/recursion.js +56 -0
  61. package/dist/bin/commands/recursion.js.map +7 -0
  62. package/dist/bin/commands/rename-preview.js +56 -0
  63. package/dist/bin/commands/rename-preview.js.map +7 -0
  64. package/dist/bin/commands/session.js +60 -0
  65. package/dist/bin/commands/session.js.map +7 -0
  66. package/dist/bin/commands/simplify-scan.js +56 -0
  67. package/dist/bin/commands/simplify-scan.js.map +7 -0
  68. package/dist/bin/commands/str-replace.js +55 -0
  69. package/dist/bin/commands/str-replace.js.map +7 -0
  70. package/dist/bin/commands/test-coverage.js +59 -0
  71. package/dist/bin/commands/test-coverage.js.map +7 -0
  72. package/dist/bin/commands/test-map.js +56 -0
  73. package/dist/bin/commands/test-map.js.map +7 -0
  74. package/dist/bin/commands/test-risk.js +59 -0
  75. package/dist/bin/commands/test-risk.js.map +7 -0
  76. package/dist/bin/commands/unused-imports.js +55 -0
  77. package/dist/bin/commands/unused-imports.js.map +7 -0
  78. package/dist/bin/commands/upgrade.js +78 -0
  79. package/dist/bin/commands/upgrade.js.map +7 -0
  80. package/dist/bin/installer/common.js +5 -1
  81. package/dist/bin/installer/common.js.map +2 -2
  82. package/dist/bin/installer/config-prompt.js +140 -11
  83. package/dist/bin/installer/config-prompt.js.map +3 -3
  84. package/dist/bin/installer/index.js +38 -6
  85. package/dist/bin/installer/index.js.map +2 -2
  86. package/dist/bin/installer/instructions.js +7 -11
  87. package/dist/bin/installer/instructions.js.map +2 -2
  88. package/dist/bin/installer/mcp.js.map +2 -2
  89. package/dist/bin/installer/steering.js +531 -100
  90. package/dist/bin/installer/steering.js.map +2 -2
  91. package/dist/bin/installer/targets/kiro.js +7 -3
  92. package/dist/bin/installer/targets/kiro.js.map +2 -2
  93. package/dist/bin/kirograph.js +73 -1
  94. package/dist/bin/kirograph.js.map +3 -3
  95. package/dist/config.js +26 -8
  96. package/dist/config.js.map +2 -2
  97. package/dist/core/branch-manager.js +111 -0
  98. package/dist/core/branch-manager.js.map +7 -0
  99. package/dist/core/pipeline.js +3 -3
  100. package/dist/core/pipeline.js.map +2 -2
  101. package/dist/data/pixelrag-bridge.js +93 -0
  102. package/dist/data/pixelrag-bridge.js.map +7 -0
  103. package/dist/data/pixelrag-manager.js +416 -0
  104. package/dist/data/pixelrag-manager.js.map +7 -0
  105. package/dist/db/database.js +34 -7
  106. package/dist/db/database.js.map +2 -2
  107. package/dist/db/schema.sql +7 -1
  108. package/dist/extraction/complexity.js +116 -0
  109. package/dist/extraction/complexity.js.map +7 -0
  110. package/dist/extraction/extractor.js +52 -1
  111. package/dist/extraction/extractor.js.map +2 -2
  112. package/dist/graph/git-context.js +229 -0
  113. package/dist/graph/git-context.js.map +7 -0
  114. package/dist/index.js +4 -2
  115. package/dist/index.js.map +2 -2
  116. package/dist/mcp/handler.js +446 -0
  117. package/dist/mcp/handler.js.map +7 -0
  118. package/dist/mcp/handlers/architecture.js +297 -0
  119. package/dist/mcp/handlers/architecture.js.map +7 -0
  120. package/dist/mcp/handlers/branch.js +175 -0
  121. package/dist/mcp/handlers/branch.js.map +7 -0
  122. package/dist/mcp/handlers/code-health.js +563 -0
  123. package/dist/mcp/handlers/code-health.js.map +7 -0
  124. package/dist/mcp/handlers/complexity.js +267 -0
  125. package/dist/mcp/handlers/complexity.js.map +7 -0
  126. package/dist/mcp/handlers/core.js +611 -0
  127. package/dist/mcp/handlers/core.js.map +7 -0
  128. package/dist/mcp/handlers/data.js +337 -0
  129. package/dist/mcp/handlers/data.js.map +7 -0
  130. package/dist/mcp/handlers/docs.js +159 -0
  131. package/dist/mcp/handlers/docs.js.map +7 -0
  132. package/dist/mcp/handlers/edit-primitives.js +200 -0
  133. package/dist/mcp/handlers/edit-primitives.js.map +7 -0
  134. package/dist/mcp/handlers/git-context.js +286 -0
  135. package/dist/mcp/handlers/git-context.js.map +7 -0
  136. package/dist/mcp/handlers/memory.js +363 -0
  137. package/dist/mcp/handlers/memory.js.map +7 -0
  138. package/dist/mcp/handlers/patterns.js +310 -0
  139. package/dist/mcp/handlers/patterns.js.map +7 -0
  140. package/dist/mcp/handlers/security.js +699 -0
  141. package/dist/mcp/handlers/security.js.map +7 -0
  142. package/dist/mcp/handlers/utils.js +97 -0
  143. package/dist/mcp/handlers/utils.js.map +7 -0
  144. package/dist/mcp/handlers/watchmen.js +104 -0
  145. package/dist/mcp/handlers/watchmen.js.map +7 -0
  146. package/dist/mcp/handlers/wiki.js +242 -0
  147. package/dist/mcp/handlers/wiki.js.map +7 -0
  148. package/dist/mcp/server.js +72 -3
  149. package/dist/mcp/server.js.map +2 -2
  150. package/dist/mcp/tool-names.js +94 -7
  151. package/dist/mcp/tool-names.js.map +2 -2
  152. package/dist/mcp/tools.js +445 -3210
  153. package/dist/mcp/tools.js.map +3 -3
  154. package/dist/types.js.map +2 -2
  155. package/package.json +36 -10
@@ -0,0 +1,310 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var patterns_exports = {};
30
+ __export(patterns_exports, {
31
+ handlePatterns: () => handlePatterns
32
+ });
33
+ module.exports = __toCommonJS(patterns_exports);
34
+ var import_fs = __toESM(require("fs"));
35
+ var import_path = __toESM(require("path"));
36
+ var import_utils = require("./utils");
37
+ async function handlePatterns(toolName, args, cg) {
38
+ switch (toolName) {
39
+ case "kirograph_live_search": {
40
+ const { loadConfig } = await Promise.resolve().then(() => require("../../config.js"));
41
+ const projectRoot = cg.getProjectRoot();
42
+ const config = await loadConfig(projectRoot);
43
+ if (!config.enablePatterns) {
44
+ return "kirograph_live_search requires enablePatterns: true in .kirograph/config.json";
45
+ }
46
+ const { PatternRunner } = await Promise.resolve().then(() => require("../../patterns/runner.js"));
47
+ const runner = new PatternRunner();
48
+ if (!runner.isAvailable()) {
49
+ return "kirograph_live_search requires @ast-grep/napi. Run: npm install @ast-grep/napi";
50
+ }
51
+ const pattern = args.pattern;
52
+ const language = args.language;
53
+ const rawLimit = typeof args.limit === "number" ? args.limit : 20;
54
+ const limit = Math.max(1, Math.min(100, Math.round(rawLimit)));
55
+ const db = cg.getDatabase();
56
+ const rawDb = db.getRawDb();
57
+ const files = rawDb.all(
58
+ "SELECT path FROM files WHERE language = ? LIMIT 5000",
59
+ [language]
60
+ );
61
+ const results = [];
62
+ let truncated = false;
63
+ for (const file of files) {
64
+ if (results.length >= limit) {
65
+ truncated = true;
66
+ break;
67
+ }
68
+ let content;
69
+ try {
70
+ const fullPath = import_path.default.isAbsolute(file.path) ? file.path : import_path.default.join(projectRoot, file.path);
71
+ content = import_fs.default.readFileSync(fullPath, "utf8");
72
+ } catch {
73
+ continue;
74
+ }
75
+ const matches = await runner.runInline(pattern, language, content);
76
+ for (const m of matches) {
77
+ if (results.length >= limit) {
78
+ truncated = true;
79
+ break;
80
+ }
81
+ results.push({ filePath: file.path, line: m.line, matchText: m.matchText });
82
+ }
83
+ }
84
+ if (results.length === 0) {
85
+ return `0 matches for '${pattern}' in ${language} files`;
86
+ }
87
+ const lines = [
88
+ `${results.length} match${results.length !== 1 ? "es" : ""} for '${pattern}' in ${language} files`,
89
+ ""
90
+ ];
91
+ for (const r of results) {
92
+ lines.push(` ${r.filePath}:${r.line}`);
93
+ lines.push(` ${r.matchText}`);
94
+ lines.push("");
95
+ }
96
+ if (truncated) {
97
+ lines.push(`[truncated \u2014 showing first ${limit} results; refine your pattern or use --lang to narrow scope]`);
98
+ }
99
+ return (0, import_utils.truncate)(lines.join("\n"));
100
+ }
101
+ case "kirograph_pattern_coverage": {
102
+ const { loadConfig } = await Promise.resolve().then(() => require("../../config.js"));
103
+ const projectRoot = cg.getProjectRoot();
104
+ const config = await loadConfig(projectRoot);
105
+ if (!config.enablePatterns) {
106
+ return "Pattern analysis is not enabled. Set enablePatterns: true in .kirograph/config.json and run kirograph index.";
107
+ }
108
+ const { PatternLibraryLoader } = await Promise.resolve().then(() => require("../../patterns/loader.js"));
109
+ const loader = new PatternLibraryLoader();
110
+ const builtinPath = import_path.default.join(__dirname, "../../patterns/library");
111
+ const customPath = config.patternLibraryPath;
112
+ let rules = [];
113
+ try {
114
+ rules = loader.load(builtinPath, customPath);
115
+ } catch {
116
+ }
117
+ const rulesByCategory = /* @__PURE__ */ new Map();
118
+ for (const rule of rules) {
119
+ const prefix = rule.owaspCategory.match(/^(A\d{2})/)?.[1] ?? rule.owaspCategory;
120
+ if (!rulesByCategory.has(prefix)) rulesByCategory.set(prefix, []);
121
+ rulesByCategory.get(prefix).push(rule);
122
+ }
123
+ const db = cg.getDatabase();
124
+ db.applyPatternsSchema();
125
+ const rawDb = db.getRawDb();
126
+ const matchCountsByCategory = /* @__PURE__ */ new Map();
127
+ try {
128
+ const tableExists = rawDb.get("SELECT name FROM sqlite_master WHERE type='table' AND name='pattern_matches'");
129
+ if (tableExists) {
130
+ const rows = rawDb.all(
131
+ "SELECT owasp_category, COUNT(*) as cnt FROM pattern_matches GROUP BY owasp_category"
132
+ );
133
+ for (const row of rows) {
134
+ const prefix = row.owasp_category.match(/^(A\d{2})/)?.[1] ?? row.owasp_category;
135
+ matchCountsByCategory.set(prefix, (matchCountsByCategory.get(prefix) ?? 0) + row.cnt);
136
+ }
137
+ }
138
+ } catch {
139
+ }
140
+ const owaspTop10 = [
141
+ "A01",
142
+ "A02",
143
+ "A03",
144
+ "A04",
145
+ "A05",
146
+ "A06",
147
+ "A07",
148
+ "A08",
149
+ "A09",
150
+ "A10"
151
+ ];
152
+ const owaspNames = {
153
+ A01: "Broken Access Control",
154
+ A02: "Cryptographic Failures",
155
+ A03: "Injection",
156
+ A04: "Insecure Design",
157
+ A05: "Security Misconfiguration",
158
+ A06: "Vulnerable and Outdated Components",
159
+ A07: "Identification and Authentication Failures",
160
+ A08: "Software and Data Integrity Failures",
161
+ A09: "Security Logging and Monitoring Failures",
162
+ A10: "Server-Side Request Forgery"
163
+ };
164
+ const covered = [];
165
+ const uncovered = [];
166
+ const lines = [
167
+ "# OWASP Top 10 Pattern Coverage",
168
+ "",
169
+ `Total rules loaded: ${rules.length}`,
170
+ "",
171
+ "Category | Rules | Matches",
172
+ "-------- | ----- | -------"
173
+ ];
174
+ for (const cat of owaspTop10) {
175
+ const catRules = rulesByCategory.get(cat) ?? [];
176
+ const matchCount = matchCountsByCategory.get(cat) ?? 0;
177
+ const label = `${cat}: ${owaspNames[cat] ?? cat}`;
178
+ if (catRules.length > 0) {
179
+ covered.push(label);
180
+ lines.push(`${label} | ${catRules.length} | ${matchCount}`);
181
+ } else {
182
+ uncovered.push(label);
183
+ }
184
+ }
185
+ for (const [cat, catRules] of rulesByCategory.entries()) {
186
+ if (!owaspTop10.includes(cat)) {
187
+ const matchCount = matchCountsByCategory.get(cat) ?? 0;
188
+ lines.push(`${cat} | ${catRules.length} | ${matchCount}`);
189
+ }
190
+ }
191
+ if (uncovered.length > 0) {
192
+ lines.push("", `Uncovered categories (${uncovered.length}):`, ...uncovered.map((c) => ` - ${c}`));
193
+ }
194
+ lines.push("", `Coverage: ${covered.length} / ${owaspTop10.length} OWASP Top 10 categories`);
195
+ return lines.join("\n");
196
+ }
197
+ case "kirograph_pattern_save_baseline": {
198
+ const { loadConfig } = await Promise.resolve().then(() => require("../../config.js"));
199
+ const projectRoot = cg.getProjectRoot();
200
+ const config = await loadConfig(projectRoot);
201
+ if (!config.enablePatterns) {
202
+ return "Pattern analysis is not enabled. Set enablePatterns: true in .kirograph/config.json and run kirograph index.";
203
+ }
204
+ const label = args.label ?? "default";
205
+ const db = cg.getDatabase();
206
+ db.applyPatternsSchema();
207
+ const rawDb = db.getRawDb();
208
+ const tableExists = rawDb.get("SELECT name FROM sqlite_master WHERE type='table' AND name='pattern_matches'");
209
+ if (!tableExists) {
210
+ return "No pattern_matches table found. Run kirograph index first to populate pattern data.";
211
+ }
212
+ const rows = rawDb.all(
213
+ "SELECT pattern_id, COUNT(*) as cnt FROM pattern_matches GROUP BY pattern_id"
214
+ );
215
+ const baseline = {};
216
+ for (const row of rows) {
217
+ baseline[row.pattern_id] = row.cnt;
218
+ }
219
+ const kirographDir = import_path.default.join(projectRoot, ".kirograph");
220
+ if (!import_fs.default.existsSync(kirographDir)) import_fs.default.mkdirSync(kirographDir, { recursive: true });
221
+ const baselinePath = import_path.default.join(kirographDir, `pattern-baseline-${label}.json`);
222
+ import_fs.default.writeFileSync(baselinePath, JSON.stringify({ label, savedAt: Date.now(), counts: baseline }, null, 2));
223
+ const totalMatches = Object.values(baseline).reduce((s, c) => s + c, 0);
224
+ return `Baseline "${label}" saved: ${Object.keys(baseline).length} patterns, ${totalMatches} total matches \u2192 ${baselinePath}`;
225
+ }
226
+ case "kirograph_pattern_diff": {
227
+ const { loadConfig } = await Promise.resolve().then(() => require("../../config.js"));
228
+ const projectRoot = cg.getProjectRoot();
229
+ const config = await loadConfig(projectRoot);
230
+ if (!config.enablePatterns) {
231
+ return "Pattern analysis is not enabled. Set enablePatterns: true in .kirograph/config.json and run kirograph index.";
232
+ }
233
+ const label = args.label ?? "default";
234
+ const baselinePath = import_path.default.join(projectRoot, ".kirograph", `pattern-baseline-${label}.json`);
235
+ if (!import_fs.default.existsSync(baselinePath)) {
236
+ return `Baseline "${label}" not found. Run kirograph_pattern_save_baseline first.`;
237
+ }
238
+ let baseline;
239
+ try {
240
+ baseline = JSON.parse(import_fs.default.readFileSync(baselinePath, "utf8"));
241
+ } catch {
242
+ return `Failed to read baseline file: ${baselinePath}`;
243
+ }
244
+ const db = cg.getDatabase();
245
+ db.applyPatternsSchema();
246
+ const rawDb = db.getRawDb();
247
+ const tableExists = rawDb.get("SELECT name FROM sqlite_master WHERE type='table' AND name='pattern_matches'");
248
+ const currentCounts = {};
249
+ if (tableExists) {
250
+ const rows = rawDb.all(
251
+ "SELECT pattern_id, COUNT(*) as cnt FROM pattern_matches GROUP BY pattern_id"
252
+ );
253
+ for (const row of rows) {
254
+ currentCounts[row.pattern_id] = row.cnt;
255
+ }
256
+ }
257
+ const allPatternIds = /* @__PURE__ */ new Set([...Object.keys(baseline.counts), ...Object.keys(currentCounts)]);
258
+ const newFindings = [];
259
+ const resolvedFindings = [];
260
+ const unchanged = [];
261
+ const changed = [];
262
+ for (const id of allPatternIds) {
263
+ const before = baseline.counts[id] ?? 0;
264
+ const after = currentCounts[id] ?? 0;
265
+ if (before === 0 && after > 0) {
266
+ newFindings.push({ id, count: after });
267
+ } else if (before > 0 && after === 0) {
268
+ resolvedFindings.push({ id, count: before });
269
+ } else if (before === after) {
270
+ unchanged.push({ id, count: after });
271
+ } else {
272
+ changed.push({ id, before, after, delta: after - before });
273
+ }
274
+ }
275
+ const savedDate = new Date(baseline.savedAt).toISOString().slice(0, 16).replace("T", " ");
276
+ const lines = [
277
+ `# Pattern Diff: "${label}" (saved ${savedDate}) \u2192 current`,
278
+ "",
279
+ `NEW: ${newFindings.length} RESOLVED: ${resolvedFindings.length} CHANGED: ${changed.length} UNCHANGED: ${unchanged.length}`
280
+ ];
281
+ if (newFindings.length > 0) {
282
+ lines.push("", "## New Findings (not in baseline)");
283
+ for (const f of newFindings.sort((a, b) => b.count - a.count)) {
284
+ lines.push(` + ${f.id}: ${f.count} matches`);
285
+ }
286
+ }
287
+ if (resolvedFindings.length > 0) {
288
+ lines.push("", "## Resolved (in baseline, not in current)");
289
+ for (const f of resolvedFindings.sort((a, b) => b.count - a.count)) {
290
+ lines.push(` - ${f.id}: was ${f.count} matches`);
291
+ }
292
+ }
293
+ if (changed.length > 0) {
294
+ lines.push("", "## Changed");
295
+ for (const f of changed.sort((a, b) => Math.abs(b.delta) - Math.abs(a.delta))) {
296
+ const sign = f.delta > 0 ? "+" : "";
297
+ lines.push(` ~ ${f.id}: ${f.before} \u2192 ${f.after} (${sign}${f.delta})`);
298
+ }
299
+ }
300
+ return lines.join("\n");
301
+ }
302
+ default:
303
+ return `Unknown tool: ${toolName}`;
304
+ }
305
+ }
306
+ // Annotate the CommonJS export names for ESM import in node:
307
+ 0 && (module.exports = {
308
+ handlePatterns
309
+ });
310
+ //# sourceMappingURL=patterns.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/mcp/handlers/patterns.ts"],
4
+ "sourcesContent": ["import fs from 'fs';\nimport path from 'path';\nimport KiroGraph from '../../index';\nimport { truncate } from './utils';\n\nexport async function handlePatterns(toolName: string, args: Record<string, unknown>, cg: KiroGraph): Promise<string> {\n switch (toolName) {\n case 'kirograph_live_search': {\n const { loadConfig } = await Promise.resolve().then(() => require('../../config.js'));\n const projectRoot = cg.getProjectRoot();\n const config = await loadConfig(projectRoot);\n\n if (!config.enablePatterns) {\n return 'kirograph_live_search requires enablePatterns: true in .kirograph/config.json';\n }\n\n const { PatternRunner } = await Promise.resolve().then(() => require('../../patterns/runner.js'));\n const runner = new PatternRunner();\n\n if (!runner.isAvailable()) {\n return 'kirograph_live_search requires @ast-grep/napi. Run: npm install @ast-grep/napi';\n }\n\n const pattern = args.pattern as string;\n const language = args.language as string;\n const rawLimit = typeof args.limit === 'number' ? args.limit : 20;\n const limit = Math.max(1, Math.min(100, Math.round(rawLimit)));\n\n const db = cg.getDatabase();\n const rawDb = db.getRawDb();\n\n const files: Array<{ path: string }> = rawDb.all(\n 'SELECT path FROM files WHERE language = ? LIMIT 5000',\n [language],\n );\n\n const results: Array<{ filePath: string; line: number; matchText: string }> = [];\n let truncated = false;\n\n for (const file of files) {\n if (results.length >= limit) { truncated = true; break; }\n\n let content: string;\n try {\n const fullPath = path.isAbsolute(file.path) ? file.path : path.join(projectRoot, file.path);\n content = fs.readFileSync(fullPath, 'utf8');\n } catch {\n continue;\n }\n\n const matches = await runner.runInline(pattern, language, content);\n for (const m of matches) {\n if (results.length >= limit) { truncated = true; break; }\n results.push({ filePath: file.path, line: m.line, matchText: m.matchText });\n }\n }\n\n if (results.length === 0) {\n return `0 matches for '${pattern}' in ${language} files`;\n }\n\n const lines: string[] = [\n `${results.length} match${results.length !== 1 ? 'es' : ''} for '${pattern}' in ${language} files`,\n '',\n ];\n\n for (const r of results) {\n lines.push(` ${r.filePath}:${r.line}`);\n lines.push(` ${r.matchText}`);\n lines.push('');\n }\n\n if (truncated) {\n lines.push(`[truncated \u2014 showing first ${limit} results; refine your pattern or use --lang to narrow scope]`);\n }\n\n return truncate(lines.join('\\n'));\n }\n\n case 'kirograph_pattern_coverage': {\n const { loadConfig } = await Promise.resolve().then(() => require('../../config.js'));\n const projectRoot = cg.getProjectRoot();\n const config = await loadConfig(projectRoot);\n if (!(config as any).enablePatterns) {\n return 'Pattern analysis is not enabled. Set enablePatterns: true in .kirograph/config.json and run kirograph index.';\n }\n\n // Load all pattern rules to enumerate coverage\n const { PatternLibraryLoader } = await Promise.resolve().then(() => require('../../patterns/loader.js'));\n const loader = new PatternLibraryLoader();\n const builtinPath = path.join(__dirname, '../../patterns/library');\n const customPath = (config as any).patternLibraryPath as string | undefined;\n let rules: import('../../patterns/types').PatternRule[] = [];\n try {\n rules = loader.load(builtinPath, customPath);\n } catch { /* no rules \u2014 continue */ }\n\n // Group rules by owaspCategory prefix (A01\u2013A10)\n const rulesByCategory = new Map<string, import('../../patterns/types').PatternRule[]>();\n for (const rule of rules) {\n const prefix = rule.owaspCategory.match(/^(A\\d{2})/)?.[1] ?? rule.owaspCategory;\n if (!rulesByCategory.has(prefix)) rulesByCategory.set(prefix, []);\n rulesByCategory.get(prefix)!.push(rule);\n }\n\n // Query match counts from DB if table exists\n const db = cg.getDatabase();\n db.applyPatternsSchema();\n const rawDb = db.getRawDb();\n const matchCountsByCategory = new Map<string, number>();\n try {\n const tableExists = rawDb.get(\"SELECT name FROM sqlite_master WHERE type='table' AND name='pattern_matches'\");\n if (tableExists) {\n const rows: Array<{ owasp_category: string; cnt: number }> = rawDb.all(\n 'SELECT owasp_category, COUNT(*) as cnt FROM pattern_matches GROUP BY owasp_category'\n );\n for (const row of rows) {\n const prefix = row.owasp_category.match(/^(A\\d{2})/)?.[1] ?? row.owasp_category;\n matchCountsByCategory.set(prefix, (matchCountsByCategory.get(prefix) ?? 0) + row.cnt);\n }\n }\n } catch { /* non-critical */ }\n\n // All OWASP Top 10 categories\n const owaspTop10 = [\n 'A01', 'A02', 'A03', 'A04', 'A05',\n 'A06', 'A07', 'A08', 'A09', 'A10',\n ];\n const owaspNames: Record<string, string> = {\n A01: 'Broken Access Control',\n A02: 'Cryptographic Failures',\n A03: 'Injection',\n A04: 'Insecure Design',\n A05: 'Security Misconfiguration',\n A06: 'Vulnerable and Outdated Components',\n A07: 'Identification and Authentication Failures',\n A08: 'Software and Data Integrity Failures',\n A09: 'Security Logging and Monitoring Failures',\n A10: 'Server-Side Request Forgery',\n };\n\n const covered: string[] = [];\n const uncovered: string[] = [];\n\n const lines: string[] = [\n '# OWASP Top 10 Pattern Coverage',\n '',\n `Total rules loaded: ${rules.length}`,\n '',\n 'Category | Rules | Matches',\n '-------- | ----- | -------',\n ];\n\n for (const cat of owaspTop10) {\n const catRules = rulesByCategory.get(cat) ?? [];\n const matchCount = matchCountsByCategory.get(cat) ?? 0;\n const label = `${cat}: ${owaspNames[cat] ?? cat}`;\n if (catRules.length > 0) {\n covered.push(label);\n lines.push(`${label} | ${catRules.length} | ${matchCount}`);\n } else {\n uncovered.push(label);\n }\n }\n\n // Extra categories not in top 10\n for (const [cat, catRules] of rulesByCategory.entries()) {\n if (!owaspTop10.includes(cat)) {\n const matchCount = matchCountsByCategory.get(cat) ?? 0;\n lines.push(`${cat} | ${catRules.length} | ${matchCount}`);\n }\n }\n\n if (uncovered.length > 0) {\n lines.push('', `Uncovered categories (${uncovered.length}):`, ...uncovered.map(c => ` - ${c}`));\n }\n\n lines.push('', `Coverage: ${covered.length} / ${owaspTop10.length} OWASP Top 10 categories`);\n\n return lines.join('\\n');\n }\n\n case 'kirograph_pattern_save_baseline': {\n const { loadConfig } = await Promise.resolve().then(() => require('../../config.js'));\n const projectRoot = cg.getProjectRoot();\n const config = await loadConfig(projectRoot);\n if (!(config as any).enablePatterns) {\n return 'Pattern analysis is not enabled. Set enablePatterns: true in .kirograph/config.json and run kirograph index.';\n }\n\n const label = (args.label as string) ?? 'default';\n\n const db = cg.getDatabase();\n db.applyPatternsSchema();\n const rawDb = db.getRawDb();\n\n const tableExists = rawDb.get(\"SELECT name FROM sqlite_master WHERE type='table' AND name='pattern_matches'\");\n if (!tableExists) {\n return 'No pattern_matches table found. Run kirograph index first to populate pattern data.';\n }\n\n const rows: Array<{ pattern_id: string; cnt: number }> = rawDb.all(\n 'SELECT pattern_id, COUNT(*) as cnt FROM pattern_matches GROUP BY pattern_id'\n );\n\n const baseline: Record<string, number> = {};\n for (const row of rows) {\n baseline[row.pattern_id] = row.cnt;\n }\n\n const kirographDir = path.join(projectRoot, '.kirograph');\n if (!fs.existsSync(kirographDir)) fs.mkdirSync(kirographDir, { recursive: true });\n\n const baselinePath = path.join(kirographDir, `pattern-baseline-${label}.json`);\n fs.writeFileSync(baselinePath, JSON.stringify({ label, savedAt: Date.now(), counts: baseline }, null, 2));\n\n const totalMatches = Object.values(baseline).reduce((s, c) => s + c, 0);\n return `Baseline \"${label}\" saved: ${Object.keys(baseline).length} patterns, ${totalMatches} total matches \u2192 ${baselinePath}`;\n }\n\n case 'kirograph_pattern_diff': {\n const { loadConfig } = await Promise.resolve().then(() => require('../../config.js'));\n const projectRoot = cg.getProjectRoot();\n const config = await loadConfig(projectRoot);\n if (!(config as any).enablePatterns) {\n return 'Pattern analysis is not enabled. Set enablePatterns: true in .kirograph/config.json and run kirograph index.';\n }\n\n const label = (args.label as string) ?? 'default';\n const baselinePath = path.join(projectRoot, '.kirograph', `pattern-baseline-${label}.json`);\n\n if (!fs.existsSync(baselinePath)) {\n return `Baseline \"${label}\" not found. Run kirograph_pattern_save_baseline first.`;\n }\n\n let baseline: { label: string; savedAt: number; counts: Record<string, number> };\n try {\n baseline = JSON.parse(fs.readFileSync(baselinePath, 'utf8'));\n } catch {\n return `Failed to read baseline file: ${baselinePath}`;\n }\n\n const db = cg.getDatabase();\n db.applyPatternsSchema();\n const rawDb = db.getRawDb();\n\n const tableExists = rawDb.get(\"SELECT name FROM sqlite_master WHERE type='table' AND name='pattern_matches'\");\n const currentCounts: Record<string, number> = {};\n if (tableExists) {\n const rows: Array<{ pattern_id: string; cnt: number }> = rawDb.all(\n 'SELECT pattern_id, COUNT(*) as cnt FROM pattern_matches GROUP BY pattern_id'\n );\n for (const row of rows) {\n currentCounts[row.pattern_id] = row.cnt;\n }\n }\n\n const allPatternIds = new Set([...Object.keys(baseline.counts), ...Object.keys(currentCounts)]);\n\n const newFindings: Array<{ id: string; count: number }> = [];\n const resolvedFindings: Array<{ id: string; count: number }> = [];\n const unchanged: Array<{ id: string; count: number }> = [];\n const changed: Array<{ id: string; before: number; after: number; delta: number }> = [];\n\n for (const id of allPatternIds) {\n const before = baseline.counts[id] ?? 0;\n const after = currentCounts[id] ?? 0;\n if (before === 0 && after > 0) {\n newFindings.push({ id, count: after });\n } else if (before > 0 && after === 0) {\n resolvedFindings.push({ id, count: before });\n } else if (before === after) {\n unchanged.push({ id, count: after });\n } else {\n changed.push({ id, before, after, delta: after - before });\n }\n }\n\n const savedDate = new Date(baseline.savedAt).toISOString().slice(0, 16).replace('T', ' ');\n const lines: string[] = [\n `# Pattern Diff: \"${label}\" (saved ${savedDate}) \u2192 current`,\n '',\n `NEW: ${newFindings.length} RESOLVED: ${resolvedFindings.length} CHANGED: ${changed.length} UNCHANGED: ${unchanged.length}`,\n ];\n\n if (newFindings.length > 0) {\n lines.push('', '## New Findings (not in baseline)');\n for (const f of newFindings.sort((a, b) => b.count - a.count)) {\n lines.push(` + ${f.id}: ${f.count} matches`);\n }\n }\n\n if (resolvedFindings.length > 0) {\n lines.push('', '## Resolved (in baseline, not in current)');\n for (const f of resolvedFindings.sort((a, b) => b.count - a.count)) {\n lines.push(` - ${f.id}: was ${f.count} matches`);\n }\n }\n\n if (changed.length > 0) {\n lines.push('', '## Changed');\n for (const f of changed.sort((a, b) => Math.abs(b.delta) - Math.abs(a.delta))) {\n const sign = f.delta > 0 ? '+' : '';\n lines.push(` ~ ${f.id}: ${f.before} \u2192 ${f.after} (${sign}${f.delta})`);\n }\n }\n\n return lines.join('\\n');\n }\n\n default:\n return `Unknown tool: ${toolName}`;\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["path", "fs"]
7
+ }