@juspay/yama 1.6.0 → 2.1.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 (79) hide show
  1. package/.mcp-config.example.json +26 -0
  2. package/CHANGELOG.md +46 -0
  3. package/README.md +311 -685
  4. package/dist/cli/v2.cli.d.ts +13 -0
  5. package/dist/cli/v2.cli.js +359 -0
  6. package/dist/index.d.ts +12 -13
  7. package/dist/index.js +18 -19
  8. package/dist/v2/config/ConfigLoader.d.ts +50 -0
  9. package/dist/v2/config/ConfigLoader.js +205 -0
  10. package/dist/v2/config/DefaultConfig.d.ts +9 -0
  11. package/dist/v2/config/DefaultConfig.js +187 -0
  12. package/dist/v2/core/LearningOrchestrator.d.ts +65 -0
  13. package/dist/v2/core/LearningOrchestrator.js +499 -0
  14. package/dist/v2/core/MCPServerManager.d.ts +22 -0
  15. package/dist/v2/core/MCPServerManager.js +100 -0
  16. package/dist/v2/core/SessionManager.d.ts +72 -0
  17. package/dist/v2/core/SessionManager.js +200 -0
  18. package/dist/v2/core/YamaV2Orchestrator.d.ts +112 -0
  19. package/dist/v2/core/YamaV2Orchestrator.js +549 -0
  20. package/dist/v2/learning/FeedbackExtractor.d.ts +46 -0
  21. package/dist/v2/learning/FeedbackExtractor.js +237 -0
  22. package/dist/v2/learning/KnowledgeBaseManager.d.ts +91 -0
  23. package/dist/v2/learning/KnowledgeBaseManager.js +475 -0
  24. package/dist/v2/learning/types.d.ts +121 -0
  25. package/dist/v2/learning/types.js +15 -0
  26. package/dist/v2/prompts/EnhancementSystemPrompt.d.ts +8 -0
  27. package/dist/v2/prompts/EnhancementSystemPrompt.js +216 -0
  28. package/dist/v2/prompts/LangfusePromptManager.d.ts +48 -0
  29. package/dist/v2/prompts/LangfusePromptManager.js +144 -0
  30. package/dist/v2/prompts/LearningSystemPrompt.d.ts +11 -0
  31. package/dist/v2/prompts/LearningSystemPrompt.js +180 -0
  32. package/dist/v2/prompts/PromptBuilder.d.ts +45 -0
  33. package/dist/v2/prompts/PromptBuilder.js +257 -0
  34. package/dist/v2/prompts/ReviewSystemPrompt.d.ts +8 -0
  35. package/dist/v2/prompts/ReviewSystemPrompt.js +270 -0
  36. package/dist/v2/types/config.types.d.ts +141 -0
  37. package/dist/v2/types/config.types.js +5 -0
  38. package/dist/v2/types/mcp.types.d.ts +191 -0
  39. package/dist/v2/types/mcp.types.js +6 -0
  40. package/dist/v2/types/v2.types.d.ts +182 -0
  41. package/dist/v2/types/v2.types.js +42 -0
  42. package/dist/v2/utils/ObservabilityConfig.d.ts +22 -0
  43. package/dist/v2/utils/ObservabilityConfig.js +48 -0
  44. package/package.json +16 -10
  45. package/yama.config.example.yaml +259 -204
  46. package/dist/cli/index.d.ts +0 -12
  47. package/dist/cli/index.js +0 -538
  48. package/dist/core/ContextGatherer.d.ts +0 -110
  49. package/dist/core/ContextGatherer.js +0 -470
  50. package/dist/core/Guardian.d.ts +0 -81
  51. package/dist/core/Guardian.js +0 -480
  52. package/dist/core/providers/BitbucketProvider.d.ts +0 -105
  53. package/dist/core/providers/BitbucketProvider.js +0 -489
  54. package/dist/features/CodeReviewer.d.ts +0 -173
  55. package/dist/features/CodeReviewer.js +0 -1707
  56. package/dist/features/DescriptionEnhancer.d.ts +0 -70
  57. package/dist/features/DescriptionEnhancer.js +0 -511
  58. package/dist/features/MultiInstanceProcessor.d.ts +0 -74
  59. package/dist/features/MultiInstanceProcessor.js +0 -360
  60. package/dist/types/index.d.ts +0 -624
  61. package/dist/types/index.js +0 -104
  62. package/dist/utils/Cache.d.ts +0 -103
  63. package/dist/utils/Cache.js +0 -444
  64. package/dist/utils/ConfigManager.d.ts +0 -88
  65. package/dist/utils/ConfigManager.js +0 -602
  66. package/dist/utils/ContentSimilarityService.d.ts +0 -74
  67. package/dist/utils/ContentSimilarityService.js +0 -215
  68. package/dist/utils/ExactDuplicateRemover.d.ts +0 -77
  69. package/dist/utils/ExactDuplicateRemover.js +0 -361
  70. package/dist/utils/Logger.d.ts +0 -31
  71. package/dist/utils/Logger.js +0 -214
  72. package/dist/utils/MemoryBankManager.d.ts +0 -73
  73. package/dist/utils/MemoryBankManager.js +0 -310
  74. package/dist/utils/ParallelProcessing.d.ts +0 -140
  75. package/dist/utils/ParallelProcessing.js +0 -333
  76. package/dist/utils/ProviderLimits.d.ts +0 -58
  77. package/dist/utils/ProviderLimits.js +0 -143
  78. package/dist/utils/RetryManager.d.ts +0 -78
  79. package/dist/utils/RetryManager.js +0 -205
@@ -0,0 +1,475 @@
1
+ /**
2
+ * Knowledge Base Manager
3
+ * Handles reading, writing, and parsing the knowledge base markdown file
4
+ */
5
+ import { readFile, writeFile, mkdir } from "fs/promises";
6
+ import { existsSync } from "fs";
7
+ import { dirname, join } from "path";
8
+ import { createHash } from "crypto";
9
+ import { execFile } from "child_process";
10
+ import { promisify } from "util";
11
+ const execFileAsync = promisify(execFile);
12
+ import { CATEGORY_SECTION_NAMES, } from "./types.js";
13
+ /**
14
+ * Template for a new knowledge base file
15
+ */
16
+ const KNOWLEDGE_BASE_TEMPLATE = `# Project Knowledge Base
17
+ > Learned patterns, preferences, and guidelines from team feedback
18
+
19
+ ## Metadata
20
+ - Last Updated: {{TIMESTAMP}}
21
+ - Total Learnings: 0
22
+ - Last Summarization: N/A
23
+
24
+ ---
25
+
26
+ ## False Positives (Don't Flag These)
27
+
28
+ Things AI incorrectly flagged as issues. Avoid repeating these mistakes.
29
+
30
+ ---
31
+
32
+ ## Style Preferences (Team Conventions)
33
+
34
+ Project-specific coding conventions that differ from general best practices.
35
+
36
+ ---
37
+
38
+ ## Missed Issues (Should Have Flagged)
39
+
40
+ Patterns AI missed that should be caught in future reviews.
41
+
42
+ ---
43
+
44
+ ## Context & Domain Knowledge
45
+
46
+ Project-specific context AI needs for accurate reviews.
47
+
48
+ ---
49
+
50
+ ## Enhancement Guidelines
51
+
52
+ How AI should provide suggestions for this project.
53
+
54
+ `;
55
+ export class KnowledgeBaseManager {
56
+ config;
57
+ projectRoot;
58
+ constructor(config, projectRoot) {
59
+ this.config = config;
60
+ this.projectRoot = projectRoot || process.cwd();
61
+ }
62
+ /**
63
+ * Get the full path to the knowledge base file
64
+ */
65
+ getFilePath() {
66
+ return join(this.projectRoot, this.config.path);
67
+ }
68
+ /**
69
+ * Check if knowledge base file exists
70
+ */
71
+ exists() {
72
+ return existsSync(this.getFilePath());
73
+ }
74
+ /**
75
+ * Load and parse the knowledge base file
76
+ */
77
+ async load() {
78
+ if (!this.exists()) {
79
+ return this.createEmptyKnowledgeBase();
80
+ }
81
+ const content = await readFile(this.getFilePath(), "utf-8");
82
+ return this.parseMarkdown(content);
83
+ }
84
+ /**
85
+ * Append new learnings to the knowledge base
86
+ * Returns count of learnings actually added (excludes duplicates)
87
+ */
88
+ async append(learnings) {
89
+ const kb = await this.load();
90
+ let addedCount = 0;
91
+ for (const learning of learnings) {
92
+ // Check for duplicates
93
+ if (this.isDuplicate(kb, learning)) {
94
+ continue;
95
+ }
96
+ // Get or create section
97
+ let section = kb.sections.get(learning.category);
98
+ if (!section) {
99
+ section = {
100
+ category: learning.category,
101
+ subcategories: new Map(),
102
+ };
103
+ kb.sections.set(learning.category, section);
104
+ }
105
+ // Get or create subcategory
106
+ const subcatKey = learning.subcategory || "General";
107
+ let learningsList = section.subcategories.get(subcatKey);
108
+ if (!learningsList) {
109
+ learningsList = [];
110
+ section.subcategories.set(subcatKey, learningsList);
111
+ }
112
+ // Add the learning
113
+ learningsList.push(learning.learning);
114
+ addedCount++;
115
+ }
116
+ // Update metadata
117
+ kb.metadata.lastUpdated = new Date().toISOString();
118
+ kb.metadata.totalLearnings += addedCount;
119
+ // Write back
120
+ await this.write(kb);
121
+ return addedCount;
122
+ }
123
+ /**
124
+ * Write the knowledge base back to file
125
+ */
126
+ async write(kb) {
127
+ const content = this.toMarkdown(kb);
128
+ const filePath = this.getFilePath();
129
+ const dir = dirname(filePath);
130
+ // Ensure directory exists
131
+ if (!existsSync(dir)) {
132
+ await mkdir(dir, { recursive: true });
133
+ }
134
+ await writeFile(filePath, content, "utf-8");
135
+ }
136
+ /**
137
+ * Write raw markdown content directly to file
138
+ * Used by summarization to write AI-generated consolidated content
139
+ */
140
+ async writeRaw(content) {
141
+ const filePath = this.getFilePath();
142
+ const dir = dirname(filePath);
143
+ // Ensure directory exists
144
+ if (!existsSync(dir)) {
145
+ await mkdir(dir, { recursive: true });
146
+ }
147
+ await writeFile(filePath, content, "utf-8");
148
+ }
149
+ /**
150
+ * Create a new knowledge base file from template
151
+ */
152
+ async create() {
153
+ const content = KNOWLEDGE_BASE_TEMPLATE.replace("{{TIMESTAMP}}", new Date().toISOString());
154
+ const filePath = this.getFilePath();
155
+ const dir = dirname(filePath);
156
+ if (!existsSync(dir)) {
157
+ await mkdir(dir, { recursive: true });
158
+ }
159
+ await writeFile(filePath, content, "utf-8");
160
+ }
161
+ /**
162
+ * Get knowledge base content formatted for AI prompt injection
163
+ */
164
+ async getForPrompt() {
165
+ if (!this.config.enabled || !this.exists()) {
166
+ return null;
167
+ }
168
+ try {
169
+ const content = await readFile(this.getFilePath(), "utf-8");
170
+ // Remove metadata section for cleaner prompt
171
+ const lines = content.split("\n");
172
+ const filteredLines = [];
173
+ let inMetadata = false;
174
+ for (const line of lines) {
175
+ if (line.startsWith("## Metadata")) {
176
+ inMetadata = true;
177
+ continue;
178
+ }
179
+ if (inMetadata && line.startsWith("---")) {
180
+ inMetadata = false;
181
+ continue;
182
+ }
183
+ if (!inMetadata) {
184
+ filteredLines.push(line);
185
+ }
186
+ }
187
+ return filteredLines.join("\n").trim();
188
+ }
189
+ catch {
190
+ return null;
191
+ }
192
+ }
193
+ /**
194
+ * Get count of learnings in the knowledge base
195
+ */
196
+ async getLearningCount() {
197
+ const kb = await this.load();
198
+ return kb.metadata.totalLearnings;
199
+ }
200
+ /**
201
+ * Check if summarization is needed based on entry count
202
+ */
203
+ async needsSummarization() {
204
+ const count = await this.getLearningCount();
205
+ return count >= this.config.maxEntriesBeforeSummarization;
206
+ }
207
+ /**
208
+ * Commit the knowledge base file to git
209
+ * Uses execFile with argument arrays to prevent command injection
210
+ */
211
+ async commit(prId, learningsAdded) {
212
+ const filePath = this.config.path; // Relative path for git
213
+ // Validate inputs to prevent injection
214
+ const safePrId = Math.floor(Number(prId));
215
+ const safeLearningsAdded = Math.floor(Number(learningsAdded));
216
+ if (!Number.isFinite(safePrId) || safePrId < 0) {
217
+ throw new Error("Invalid PR ID");
218
+ }
219
+ try {
220
+ // Stage the file using execFile with args array (safe from injection)
221
+ await execFileAsync("git", ["add", filePath], { cwd: this.projectRoot });
222
+ // Create commit message
223
+ const commitMessage = `chore(yama): update knowledge base from PR #${safePrId}
224
+
225
+ Added ${safeLearningsAdded} new learning${safeLearningsAdded !== 1 ? "s" : ""}.
226
+
227
+ 🤖 Generated with Yama`;
228
+ // Commit using execFile with args array (safe from injection)
229
+ await execFileAsync("git", ["commit", "-m", commitMessage], {
230
+ cwd: this.projectRoot,
231
+ });
232
+ }
233
+ catch (error) {
234
+ throw new Error(`Failed to commit knowledge base: ${error instanceof Error ? error.message : String(error)}`);
235
+ }
236
+ }
237
+ /**
238
+ * Generate a hash for deduplication
239
+ */
240
+ generateLearningId(learning) {
241
+ return createHash("md5")
242
+ .update(learning.toLowerCase().trim())
243
+ .digest("hex")
244
+ .substring(0, 12);
245
+ }
246
+ // ============================================================================
247
+ // Private Methods
248
+ // ============================================================================
249
+ /**
250
+ * Create an empty knowledge base structure
251
+ */
252
+ createEmptyKnowledgeBase() {
253
+ return {
254
+ metadata: {
255
+ lastUpdated: new Date().toISOString(),
256
+ totalLearnings: 0,
257
+ },
258
+ sections: new Map(),
259
+ };
260
+ }
261
+ /**
262
+ * Check if a learning already exists in the knowledge base
263
+ */
264
+ isDuplicate(kb, learning) {
265
+ const section = kb.sections.get(learning.category);
266
+ if (!section) {
267
+ return false;
268
+ }
269
+ const normalizedNew = learning.learning.toLowerCase().trim();
270
+ for (const [, learnings] of section.subcategories) {
271
+ for (const existing of learnings) {
272
+ const normalizedExisting = existing.toLowerCase().trim();
273
+ // Check for exact match or high similarity
274
+ if (normalizedExisting === normalizedNew ||
275
+ this.isSimilar(normalizedExisting, normalizedNew)) {
276
+ return true;
277
+ }
278
+ }
279
+ }
280
+ return false;
281
+ }
282
+ /**
283
+ * Check if two learnings are similar (simple similarity check)
284
+ */
285
+ isSimilar(a, b) {
286
+ // Remove common words and check overlap
287
+ const wordsA = new Set(a.split(/\s+/).filter((w) => w.length > 3));
288
+ const wordsB = new Set(b.split(/\s+/).filter((w) => w.length > 3));
289
+ if (wordsA.size === 0 || wordsB.size === 0) {
290
+ return false;
291
+ }
292
+ let overlap = 0;
293
+ for (const word of wordsA) {
294
+ if (wordsB.has(word)) {
295
+ overlap++;
296
+ }
297
+ }
298
+ const similarity = overlap / Math.max(wordsA.size, wordsB.size);
299
+ return similarity > 0.7; // 70% word overlap = similar
300
+ }
301
+ /**
302
+ * Parse markdown content into structured knowledge base
303
+ */
304
+ parseMarkdown(content) {
305
+ const kb = this.createEmptyKnowledgeBase();
306
+ const lines = content.split("\n");
307
+ let currentCategory = null;
308
+ let currentSubcategory = "General";
309
+ let inMetadata = false;
310
+ for (const line of lines) {
311
+ const trimmed = line.trim();
312
+ // Parse metadata
313
+ if (trimmed.startsWith("## Metadata")) {
314
+ inMetadata = true;
315
+ continue;
316
+ }
317
+ if (inMetadata) {
318
+ if (trimmed.startsWith("---")) {
319
+ inMetadata = false;
320
+ continue;
321
+ }
322
+ if (trimmed.startsWith("- Last Updated:")) {
323
+ kb.metadata.lastUpdated = trimmed
324
+ .replace("- Last Updated:", "")
325
+ .trim();
326
+ }
327
+ else if (trimmed.startsWith("- Total Learnings:")) {
328
+ kb.metadata.totalLearnings =
329
+ parseInt(trimmed.replace("- Total Learnings:", "").trim(), 10) || 0;
330
+ }
331
+ else if (trimmed.startsWith("- Last Summarization:")) {
332
+ const value = trimmed.replace("- Last Summarization:", "").trim();
333
+ if (value !== "N/A") {
334
+ kb.metadata.lastSummarization = value;
335
+ }
336
+ }
337
+ continue;
338
+ }
339
+ // Parse category headers (## level)
340
+ if (trimmed.startsWith("## ")) {
341
+ const sectionName = trimmed.substring(3);
342
+ currentCategory = this.categoryFromSectionName(sectionName);
343
+ currentSubcategory = "General";
344
+ if (currentCategory) {
345
+ kb.sections.set(currentCategory, {
346
+ category: currentCategory,
347
+ subcategories: new Map(),
348
+ });
349
+ }
350
+ continue;
351
+ }
352
+ // Parse subcategory headers (### level)
353
+ if (trimmed.startsWith("### ")) {
354
+ currentSubcategory = trimmed.substring(4);
355
+ continue;
356
+ }
357
+ // Parse learning entries (- bullet points)
358
+ if (trimmed.startsWith("- ") && currentCategory) {
359
+ const learning = trimmed.substring(2);
360
+ const section = kb.sections.get(currentCategory);
361
+ if (section) {
362
+ let learnings = section.subcategories.get(currentSubcategory);
363
+ if (!learnings) {
364
+ learnings = [];
365
+ section.subcategories.set(currentSubcategory, learnings);
366
+ }
367
+ learnings.push(learning);
368
+ }
369
+ }
370
+ }
371
+ return kb;
372
+ }
373
+ /**
374
+ * Convert category section name back to category enum
375
+ */
376
+ categoryFromSectionName(name) {
377
+ for (const [category, sectionName] of Object.entries(CATEGORY_SECTION_NAMES)) {
378
+ if (name.includes(sectionName) || sectionName.includes(name)) {
379
+ return category;
380
+ }
381
+ }
382
+ // Fallback matching
383
+ const lowerName = name.toLowerCase();
384
+ if (lowerName.includes("false positive") ||
385
+ lowerName.includes("don't flag")) {
386
+ return "false_positive";
387
+ }
388
+ if (lowerName.includes("missed") || lowerName.includes("should have")) {
389
+ return "missed_issue";
390
+ }
391
+ if (lowerName.includes("style") || lowerName.includes("convention")) {
392
+ return "style_preference";
393
+ }
394
+ if (lowerName.includes("context") || lowerName.includes("domain")) {
395
+ return "domain_context";
396
+ }
397
+ if (lowerName.includes("enhancement") || lowerName.includes("guideline")) {
398
+ return "enhancement_guideline";
399
+ }
400
+ return null;
401
+ }
402
+ /**
403
+ * Convert knowledge base structure to markdown
404
+ */
405
+ toMarkdown(kb) {
406
+ const lines = [];
407
+ // Header
408
+ lines.push("# Project Knowledge Base");
409
+ lines.push("> Learned patterns, preferences, and guidelines from team feedback");
410
+ lines.push("");
411
+ // Metadata
412
+ lines.push("## Metadata");
413
+ lines.push(`- Last Updated: ${kb.metadata.lastUpdated}`);
414
+ lines.push(`- Total Learnings: ${kb.metadata.totalLearnings}`);
415
+ lines.push(`- Last Summarization: ${kb.metadata.lastSummarization || "N/A"}`);
416
+ lines.push("");
417
+ lines.push("---");
418
+ lines.push("");
419
+ // Sections in order
420
+ const categoryOrder = [
421
+ "false_positive",
422
+ "missed_issue",
423
+ "style_preference",
424
+ "domain_context",
425
+ "enhancement_guideline",
426
+ ];
427
+ for (const category of categoryOrder) {
428
+ const sectionName = CATEGORY_SECTION_NAMES[category];
429
+ lines.push(`## ${sectionName}`);
430
+ lines.push("");
431
+ const section = kb.sections.get(category);
432
+ if (section && section.subcategories.size > 0) {
433
+ // Sort subcategories
434
+ const sortedSubcats = Array.from(section.subcategories.entries()).sort(([a], [b]) => a.localeCompare(b));
435
+ for (const [subcategory, learnings] of sortedSubcats) {
436
+ if (subcategory !== "General") {
437
+ lines.push(`### ${subcategory}`);
438
+ }
439
+ for (const learning of learnings) {
440
+ lines.push(`- ${learning}`);
441
+ }
442
+ lines.push("");
443
+ }
444
+ }
445
+ else {
446
+ // Add description placeholder for empty sections
447
+ lines.push(this.getSectionDescription(category));
448
+ lines.push("");
449
+ }
450
+ lines.push("---");
451
+ lines.push("");
452
+ }
453
+ return lines.join("\n");
454
+ }
455
+ /**
456
+ * Get description text for empty sections
457
+ */
458
+ getSectionDescription(category) {
459
+ switch (category) {
460
+ case "false_positive":
461
+ return "Things AI incorrectly flagged as issues. Avoid repeating these mistakes.";
462
+ case "missed_issue":
463
+ return "Patterns AI missed that should be caught in future reviews.";
464
+ case "style_preference":
465
+ return "Project-specific coding conventions that differ from general best practices.";
466
+ case "domain_context":
467
+ return "Project-specific context AI needs for accurate reviews.";
468
+ case "enhancement_guideline":
469
+ return "How AI should provide suggestions for this project.";
470
+ default:
471
+ return "";
472
+ }
473
+ }
474
+ }
475
+ //# sourceMappingURL=KnowledgeBaseManager.js.map
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Learning Types
3
+ * Type definitions for the knowledge base and learning extraction system
4
+ */
5
+ /**
6
+ * Categories for extracted learnings
7
+ * Maps to sections in the knowledge base file
8
+ */
9
+ export type LearningCategory = "false_positive" | "missed_issue" | "style_preference" | "domain_context" | "enhancement_guideline";
10
+ /**
11
+ * Human-readable category names for knowledge base sections
12
+ */
13
+ export declare const CATEGORY_SECTION_NAMES: Record<LearningCategory, string>;
14
+ /**
15
+ * A single learning extracted from PR feedback
16
+ */
17
+ export interface ExtractedLearning {
18
+ /** Unique hash for deduplication */
19
+ id: string;
20
+ /** Category of the learning */
21
+ category: LearningCategory;
22
+ /** Sub-category within the section (e.g., "Async Patterns", "Security") */
23
+ subcategory?: string;
24
+ /** The actionable, project-level guideline */
25
+ learning: string;
26
+ /** File patterns where this applies (e.g., ["services/*.ts"]) */
27
+ filePatterns?: string[];
28
+ /** Severity for missed_issue learnings */
29
+ severity?: string;
30
+ /** Source info for traceability (not displayed in KB) */
31
+ sourceInfo?: {
32
+ prId: number;
33
+ timestamp: string;
34
+ };
35
+ }
36
+ /**
37
+ * Metadata section of the knowledge base
38
+ */
39
+ export interface KnowledgeBaseMetadata {
40
+ lastUpdated: string;
41
+ totalLearnings: number;
42
+ lastSummarization?: string;
43
+ }
44
+ /**
45
+ * A section in the knowledge base (maps to a category)
46
+ */
47
+ export interface KnowledgeBaseSection {
48
+ category: LearningCategory;
49
+ subcategories: Map<string, string[]>;
50
+ }
51
+ /**
52
+ * Full parsed knowledge base structure
53
+ */
54
+ export interface KnowledgeBase {
55
+ metadata: KnowledgeBaseMetadata;
56
+ sections: Map<LearningCategory, KnowledgeBaseSection>;
57
+ }
58
+ /**
59
+ * Request for the learn command
60
+ */
61
+ export interface LearnRequest {
62
+ workspace: string;
63
+ repository: string;
64
+ pullRequestId: number;
65
+ dryRun?: boolean;
66
+ commit?: boolean;
67
+ summarize?: boolean;
68
+ outputPath?: string;
69
+ outputFormat?: "md" | "json";
70
+ }
71
+ /**
72
+ * Result from the learn command
73
+ */
74
+ export interface LearnResult {
75
+ success: boolean;
76
+ prId: number;
77
+ learningsFound: number;
78
+ learningsAdded: number;
79
+ learningsDuplicate: number;
80
+ learnings: ExtractedLearning[];
81
+ knowledgeBasePath?: string;
82
+ committed?: boolean;
83
+ summarized?: boolean;
84
+ error?: string;
85
+ }
86
+ /**
87
+ * A comment from a PR
88
+ */
89
+ export interface PRComment {
90
+ id: number;
91
+ text: string;
92
+ author: {
93
+ name: string;
94
+ displayName?: string;
95
+ email?: string;
96
+ };
97
+ createdAt: string;
98
+ filePath?: string;
99
+ lineNumber?: number;
100
+ parentId?: number;
101
+ }
102
+ /**
103
+ * A pair of AI comment and developer reply
104
+ */
105
+ export interface CommentPair {
106
+ aiComment: PRComment;
107
+ developerReply: PRComment;
108
+ filePath?: string;
109
+ codeContext?: string;
110
+ }
111
+ /**
112
+ * Output format from AI learning extraction
113
+ */
114
+ export interface AIExtractionOutput {
115
+ category: LearningCategory;
116
+ subcategory?: string;
117
+ learning: string;
118
+ filePatterns?: string[];
119
+ reasoning: string;
120
+ }
121
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Learning Types
3
+ * Type definitions for the knowledge base and learning extraction system
4
+ */
5
+ /**
6
+ * Human-readable category names for knowledge base sections
7
+ */
8
+ export const CATEGORY_SECTION_NAMES = {
9
+ false_positive: "False Positives (Don't Flag These)",
10
+ missed_issue: "Missed Issues (Should Have Flagged)",
11
+ style_preference: "Style Preferences (Team Conventions)",
12
+ domain_context: "Context & Domain Knowledge",
13
+ enhancement_guideline: "Enhancement Guidelines",
14
+ };
15
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Base Enhancement System Prompt
3
+ * Generic, project-agnostic instructions for PR description enhancement
4
+ * Project-specific sections and requirements come from config
5
+ */
6
+ export declare const ENHANCEMENT_SYSTEM_PROMPT = "\n<yama-enhancement-system>\n <identity>\n <role>Technical Documentation Writer</role>\n <focus>Complete PR descriptions with comprehensive, accurate information</focus>\n </identity>\n\n <core-rules>\n <rule priority=\"CRITICAL\" id=\"complete-all-sections\">\n <title>Complete All Required Sections</title>\n <description>\n Fill every required section defined in project configuration.\n For sections that don't apply: explain why with \"Not applicable because {reason}\".\n Never leave sections empty or use generic \"N/A\".\n </description>\n </rule>\n\n <rule priority=\"CRITICAL\" id=\"extract-from-code\">\n <title>Extract Information from Code Changes</title>\n <description>\n Analyze the diff to find configuration changes, API modifications, dependencies.\n Use search_code() to find patterns in the codebase.\n Document what actually changed, not assumptions.\n </description>\n </rule>\n\n <rule priority=\"MAJOR\" id=\"structured-output\">\n <title>Follow Section Structure</title>\n <description>\n Use exact section headers from configuration.\n Maintain consistent formatting.\n Use markdown for readability.\n </description>\n </rule>\n\n <rule priority=\"MAJOR\" id=\"clean-output\">\n <title>Clean Output Only</title>\n <description>\n Return ONLY the enhanced PR description content.\n Do NOT include meta-commentary like \"Here is...\" or explanations.\n Start directly with the enhanced content.\n </description>\n </rule>\n\n <rule priority=\"MAJOR\" id=\"preserve-existing\">\n <title>Preserve User Content When Possible</title>\n <description>\n If preserveContent is enabled, merge existing description with enhancements.\n Don't overwrite manually written sections unless improving them.\n </description>\n </rule>\n </core-rules>\n\n <workflow>\n <phase name=\"analysis\">\n <step>Read PR diff to understand all changes</step>\n <step>Use search_code() to find configuration patterns</step>\n <step>Identify files modified, APIs changed, dependencies added</step>\n <step>Extract information for each required section</step>\n </phase>\n\n <phase name=\"extraction\">\n <step>For each required section from config:</step>\n <step>- Extract relevant information from diff and codebase</step>\n <step>- Use search_code() if patterns need to be found</step>\n <step>- If not applicable: write clear reason why</step>\n </phase>\n\n <phase name=\"composition\">\n <step>Build description with all sections in order</step>\n <step>Verify completeness against config requirements</step>\n <step>Format as clean markdown</step>\n <step>Ensure no meta-commentary included</step>\n </phase>\n\n <phase name=\"update\">\n <step>Call update_pull_request() with enhanced description</step>\n </phase>\n </workflow>\n\n <tools>\n <tool name=\"get_pull_request\">\n <purpose>Get current PR description and context</purpose>\n <usage>Read existing description to preserve user content</usage>\n </tool>\n\n <tool name=\"get_pull_request_diff\">\n <purpose>Analyze code changes to extract information</purpose>\n <usage>Find what files changed, what was modified</usage>\n </tool>\n\n <tool name=\"search_code\">\n <purpose>Find patterns, configurations, similar implementations</purpose>\n <examples>\n <example>Search for configuration getters to find config keys</example>\n <example>Search for API endpoint definitions</example>\n <example>Search for test file patterns</example>\n <example>Search for environment variable usage</example>\n <example>Search for database migration patterns</example>\n </examples>\n </tool>\n\n <tool name=\"list_directory_content\">\n <purpose>Understand project structure</purpose>\n <usage>Find related files, understand organization</usage>\n </tool>\n\n <tool name=\"get_file_content\">\n <purpose>Read specific files for context</purpose>\n <usage>Read config files, package.json, migration files</usage>\n </tool>\n\n <tool name=\"update_pull_request\">\n <purpose>Update PR description with enhanced content</purpose>\n <parameters>\n <param name=\"description\">Enhanced markdown description</param>\n </parameters>\n </tool>\n </tools>\n\n <section-completion-guide>\n <guideline>For applicable sections: Be specific and detailed</guideline>\n <guideline>For non-applicable sections: Write \"Not applicable for this PR because {specific reason}\"</guideline>\n <guideline>Never use generic \"N/A\" without explanation</guideline>\n <guideline>Link changes to business/technical value</guideline>\n <guideline>Include file references where relevant (e.g., \"Modified src/auth/Login.tsx\")</guideline>\n <guideline>Use lists and checkboxes for better readability</guideline>\n </section-completion-guide>\n\n <extraction-strategies>\n <strategy name=\"configuration-changes\">\n <description>How to find and document configuration changes</description>\n <steps>\n <step>Search diff for configuration file changes (config.yaml, .env.example, etc.)</step>\n <step>Use search_code() to find configuration getters in code</step>\n <step>Document key names and their purpose</step>\n <step>Explain impact of configuration changes</step>\n </steps>\n </strategy>\n\n <strategy name=\"api-modifications\">\n <description>How to identify API changes</description>\n <steps>\n <step>Look for route definitions, endpoint handlers in diff</step>\n <step>Search for API client calls, fetch/axios usage</step>\n <step>Document endpoints added/modified/removed</step>\n <step>Note request/response format changes</step>\n </steps>\n </strategy>\n\n <strategy name=\"database-changes\">\n <description>How to find database alterations</description>\n <steps>\n <step>Look for migration files in diff</step>\n <step>Search for schema definitions, model changes</step>\n <step>Document table/column changes</step>\n <step>Note any data migration requirements</step>\n </steps>\n </strategy>\n\n <strategy name=\"dependency-changes\">\n <description>How to document library updates</description>\n <steps>\n <step>Check package.json, requirements.txt, etc. in diff</step>\n <step>Document added/updated/removed dependencies</step>\n <step>Note version changes and breaking changes</step>\n <step>Explain why dependency was added/updated</step>\n </steps>\n </strategy>\n\n <strategy name=\"testing-coverage\">\n <description>How to document testing</description>\n <steps>\n <step>Look for test files in diff (*.test.*, *.spec.*)</step>\n <step>Document test scenarios covered</step>\n <step>Note integration/unit/e2e tests added</step>\n <step>Create testing checklist for reviewers</step>\n </steps>\n </strategy>\n </extraction-strategies>\n\n <output-format>\n <requirement>Return enhanced description as clean markdown</requirement>\n <requirement>No meta-commentary or wrapper text</requirement>\n <requirement>Start directly with section headers</requirement>\n <requirement>Use consistent formatting throughout</requirement>\n <requirement>Follow section order from configuration</requirement>\n </output-format>\n\n <formatting-guidelines>\n <guideline>Use ## for section headers</guideline>\n <guideline>Use - or * for bulleted lists</guideline>\n <guideline>Use - [ ] for checkboxes in test cases</guideline>\n <guideline>Use `code` for inline code references</guideline>\n <guideline>Use ```language for code blocks</guideline>\n <guideline>Use **bold** for emphasis on important items</guideline>\n <guideline>Use tables for structured data when appropriate</guideline>\n </formatting-guidelines>\n\n <anti-patterns>\n <dont>Start with \"Here is the enhanced description...\"</dont>\n <dont>Include explanatory wrapper text</dont>\n <dont>Use generic \"N/A\" without explanation</dont>\n <dont>Skip sections even if they seem not applicable</dont>\n <dont>Make assumptions - verify with code search</dont>\n <dont>Copy code changes verbatim - summarize meaningfully</dont>\n </anti-patterns>\n</yama-enhancement-system>\n";
7
+ export default ENHANCEMENT_SYSTEM_PROMPT;
8
+ //# sourceMappingURL=EnhancementSystemPrompt.d.ts.map