@juspay/yama 2.2.1 → 2.3.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 (35) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/LICENSE +21 -0
  3. package/README.md +73 -110
  4. package/dist/cli/cli.d.ts +13 -0
  5. package/dist/cli/cli.js +341 -0
  6. package/dist/cli/v2.cli.d.ts +2 -11
  7. package/dist/cli/v2.cli.js +4 -354
  8. package/dist/index.d.ts +7 -5
  9. package/dist/index.js +5 -3
  10. package/dist/v2/config/ConfigLoader.d.ts +20 -5
  11. package/dist/v2/config/ConfigLoader.js +76 -24
  12. package/dist/v2/config/DefaultConfig.d.ts +3 -3
  13. package/dist/v2/config/DefaultConfig.js +9 -2
  14. package/dist/v2/core/LearningOrchestrator.d.ts +1 -0
  15. package/dist/v2/core/LearningOrchestrator.js +64 -4
  16. package/dist/v2/core/LocalDiffSource.d.ts +26 -0
  17. package/dist/v2/core/LocalDiffSource.js +129 -0
  18. package/dist/v2/core/MCPServerManager.d.ts +13 -1
  19. package/dist/v2/core/MCPServerManager.js +111 -7
  20. package/dist/v2/core/SessionManager.d.ts +1 -1
  21. package/dist/v2/core/SessionManager.js +3 -3
  22. package/dist/v2/core/YamaV2Orchestrator.d.ts +48 -13
  23. package/dist/v2/core/YamaV2Orchestrator.js +543 -63
  24. package/dist/v2/learning/types.d.ts +10 -0
  25. package/dist/v2/memory/MemoryManager.d.ts +57 -0
  26. package/dist/v2/memory/MemoryManager.js +185 -0
  27. package/dist/v2/prompts/PromptBuilder.d.ts +10 -4
  28. package/dist/v2/prompts/PromptBuilder.js +94 -3
  29. package/dist/v2/prompts/ReviewSystemPrompt.d.ts +1 -1
  30. package/dist/v2/prompts/ReviewSystemPrompt.js +7 -5
  31. package/dist/v2/types/config.types.d.ts +61 -1
  32. package/dist/v2/types/v2.types.d.ts +66 -5
  33. package/dist/v2/types/v2.types.js +8 -6
  34. package/package.json +20 -15
  35. package/yama.config.example.yaml +23 -5
@@ -58,12 +58,22 @@ export interface KnowledgeBase {
58
58
  /**
59
59
  * Request for the learn command
60
60
  */
61
+ /**
62
+ * Controls which storage systems are committed after learning extraction.
63
+ * - "kb" — commit only the knowledge base file (existing behavior)
64
+ * - "memory" — commit only per-repo memory files (via NeuroLink + git push)
65
+ * - "all" — commit both knowledge base and per-repo memory
66
+ */
67
+ export type LearnCommitMode = "kb" | "memory" | "all";
61
68
  export interface LearnRequest {
62
69
  workspace: string;
63
70
  repository: string;
64
71
  pullRequestId: number;
65
72
  dryRun?: boolean;
73
+ /** @deprecated Use commitMode instead */
66
74
  commit?: boolean;
75
+ /** Controls which storage systems are committed after extraction */
76
+ commitMode?: LearnCommitMode;
67
77
  summarize?: boolean;
68
78
  outputPath?: string;
69
79
  outputFormat?: "md" | "json";
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Memory Manager
3
+ *
4
+ * Provides per-repository condensed memory configuration for NeuroLink.
5
+ *
6
+ * This manager builds the NeuroLink-compatible memory SDK config with
7
+ * file-based custom storage, so that NeuroLink's generate()/stream() calls
8
+ * can retrieve and store memory using context.userId as the per-repo key.
9
+ *
10
+ * Callers control WHEN memory is read/written via per-call flags:
11
+ * memory: { enabled: true, read: true, write: false }
12
+ *
13
+ * This avoids noise from operational calls (e.g., fetching PR data)
14
+ * polluting the condensed memory.
15
+ *
16
+ * Storage: file-based (.yama/memory/{workspace}-{repository}.txt) (lowercased)
17
+ * Condensation: LLM-powered via NeuroLink's built-in Hippocampus
18
+ */
19
+ import { MemoryConfig } from "../types/config.types.js";
20
+ export declare class MemoryManager {
21
+ private readonly config;
22
+ private readonly projectRoot;
23
+ private readonly aiProvider;
24
+ private readonly aiModel;
25
+ constructor(config: MemoryConfig, aiProvider: string, aiModel: string, projectRoot?: string);
26
+ /**
27
+ * Resolve the storage directory path (handles both absolute and relative paths).
28
+ */
29
+ private resolveStorageDir;
30
+ /**
31
+ * Build the NeuroLink-compatible Memory config object.
32
+ *
33
+ * Passed to NeuroLink constructor as `conversationMemory.memory`.
34
+ * NeuroLink internally initializes Hippocampus with our file-based
35
+ * storage and review-specific condensation prompt.
36
+ */
37
+ buildNeuroLinkMemoryConfig(): Record<string, unknown>;
38
+ /**
39
+ * Build a deterministic owner ID from workspace and repository.
40
+ * This value is passed as `context.userId` in generate() calls.
41
+ */
42
+ static buildOwnerId(workspace: string, repository: string): string;
43
+ /**
44
+ * Commit memory files to the repository if autoCommit is enabled.
45
+ *
46
+ * Checks git status for changes in the storagePath directory,
47
+ * then stages, commits, and pushes. Uses [skip ci] to prevent
48
+ * infinite CI loops. Never throws — failures are logged and ignored
49
+ * so they never block the review result.
50
+ */
51
+ commitMemoryChanges(): Promise<boolean>;
52
+ /**
53
+ * Map an ownerId to a safe file path.
54
+ */
55
+ private ownerIdToFilePath;
56
+ }
57
+ //# sourceMappingURL=MemoryManager.d.ts.map
@@ -0,0 +1,185 @@
1
+ /**
2
+ * Memory Manager
3
+ *
4
+ * Provides per-repository condensed memory configuration for NeuroLink.
5
+ *
6
+ * This manager builds the NeuroLink-compatible memory SDK config with
7
+ * file-based custom storage, so that NeuroLink's generate()/stream() calls
8
+ * can retrieve and store memory using context.userId as the per-repo key.
9
+ *
10
+ * Callers control WHEN memory is read/written via per-call flags:
11
+ * memory: { enabled: true, read: true, write: false }
12
+ *
13
+ * This avoids noise from operational calls (e.g., fetching PR data)
14
+ * polluting the condensed memory.
15
+ *
16
+ * Storage: file-based (.yama/memory/{workspace}-{repository}.txt) (lowercased)
17
+ * Condensation: LLM-powered via NeuroLink's built-in Hippocampus
18
+ */
19
+ import { readFile, writeFile, mkdir, unlink } from "fs/promises";
20
+ import { existsSync } from "fs";
21
+ import { join, dirname, isAbsolute } from "path";
22
+ import { execFile } from "child_process";
23
+ import { promisify } from "util";
24
+ const execFileAsync = promisify(execFile);
25
+ // ============================================================================
26
+ // Constants
27
+ // ============================================================================
28
+ /**
29
+ * Condensation prompt tailored for code review memory.
30
+ * Guides the LLM to retain review patterns, team conventions, and
31
+ * frequently flagged issues rather than individual PR details.
32
+ */
33
+ const REVIEW_MEMORY_CONDENSATION_PROMPT = `You are a memory condensation engine for an AI code reviewer called Yama.
34
+ You receive:
35
+ 1. OLD_MEMORY: the existing condensed memory for a specific repository (may be empty)
36
+ 2. NEW_CONTENT: new information from a recent code review or learning extraction
37
+
38
+ Your job: merge old memory with the new information into a single condensed summary.
39
+
40
+ Rules:
41
+ - Output ONLY the condensed memory text, nothing else
42
+ - Maximum {{MAX_WORDS}} words
43
+ - PRIORITIZE retaining (most important first):
44
+ 1. False positive patterns: things the team confirmed are NOT issues
45
+ 2. Team coding conventions and style preferences
46
+ 3. Recurring review themes and common issue categories
47
+ 4. Repository-specific domain knowledge and architecture decisions
48
+ 5. Patterns the AI missed that developers caught
49
+ 6. Review outcome trends (approval rate, common blocking reasons)
50
+ - DROP: individual PR numbers, timestamps, one-off issues, greeting text
51
+ - Keep learnings GENERIC and applicable to future reviews
52
+ - If NEW_CONTENT has nothing worth remembering, return OLD_MEMORY unchanged
53
+ - If both are empty, return empty string`;
54
+ // ============================================================================
55
+ // Manager
56
+ // ============================================================================
57
+ export class MemoryManager {
58
+ config;
59
+ projectRoot;
60
+ aiProvider;
61
+ aiModel;
62
+ constructor(config, aiProvider, aiModel, projectRoot) {
63
+ this.config = config;
64
+ this.aiProvider = aiProvider;
65
+ this.aiModel = aiModel;
66
+ this.projectRoot = projectRoot || process.cwd();
67
+ }
68
+ /**
69
+ * Resolve the storage directory path (handles both absolute and relative paths).
70
+ */
71
+ resolveStorageDir() {
72
+ return isAbsolute(this.config.storagePath)
73
+ ? this.config.storagePath
74
+ : join(this.projectRoot, this.config.storagePath);
75
+ }
76
+ /**
77
+ * Build the NeuroLink-compatible Memory config object.
78
+ *
79
+ * Passed to NeuroLink constructor as `conversationMemory.memory`.
80
+ * NeuroLink internally initializes Hippocampus with our file-based
81
+ * storage and review-specific condensation prompt.
82
+ */
83
+ buildNeuroLinkMemoryConfig() {
84
+ const storageDir = this.resolveStorageDir();
85
+ return {
86
+ enabled: true,
87
+ storage: this.config.storage || {
88
+ type: "custom",
89
+ onGet: async (ownerId) => {
90
+ const filePath = this.ownerIdToFilePath(storageDir, ownerId);
91
+ if (!existsSync(filePath)) {
92
+ return null;
93
+ }
94
+ try {
95
+ return await readFile(filePath, "utf-8");
96
+ }
97
+ catch {
98
+ return null;
99
+ }
100
+ },
101
+ onSet: async (ownerId, memory) => {
102
+ const filePath = this.ownerIdToFilePath(storageDir, ownerId);
103
+ const dir = dirname(filePath);
104
+ if (!existsSync(dir)) {
105
+ await mkdir(dir, { recursive: true });
106
+ }
107
+ await writeFile(filePath, memory, "utf-8");
108
+ },
109
+ onDelete: async (ownerId) => {
110
+ const filePath = this.ownerIdToFilePath(storageDir, ownerId);
111
+ if (existsSync(filePath)) {
112
+ await unlink(filePath);
113
+ }
114
+ },
115
+ },
116
+ neurolink: this.config.neurolink || {
117
+ provider: this.aiProvider,
118
+ model: this.aiModel,
119
+ temperature: 0.1,
120
+ },
121
+ maxWords: this.config.maxWords,
122
+ prompt: this.config.prompt || REVIEW_MEMORY_CONDENSATION_PROMPT,
123
+ };
124
+ }
125
+ /**
126
+ * Build a deterministic owner ID from workspace and repository.
127
+ * This value is passed as `context.userId` in generate() calls.
128
+ */
129
+ static buildOwnerId(workspace, repository) {
130
+ return `${workspace}-${repository}`.toLowerCase();
131
+ }
132
+ /**
133
+ * Commit memory files to the repository if autoCommit is enabled.
134
+ *
135
+ * Checks git status for changes in the storagePath directory,
136
+ * then stages, commits, and pushes. Uses [skip ci] to prevent
137
+ * infinite CI loops. Never throws — failures are logged and ignored
138
+ * so they never block the review result.
139
+ */
140
+ async commitMemoryChanges() {
141
+ if (!this.config.autoCommit) {
142
+ return false;
143
+ }
144
+ const storageDir = this.resolveStorageDir();
145
+ if (!existsSync(storageDir)) {
146
+ return false;
147
+ }
148
+ try {
149
+ // Check if there are any changes to commit
150
+ const { stdout: statusOutput } = await execFileAsync("git", ["status", "--porcelain", storageDir], { cwd: this.projectRoot });
151
+ if (!statusOutput.trim()) {
152
+ console.log(" 🧠 No memory changes to commit");
153
+ return false;
154
+ }
155
+ const commitMessage = this.config.commitMessage ||
156
+ "chore: update yama review memory [skip ci]";
157
+ // Stage memory files
158
+ await execFileAsync("git", ["add", storageDir], {
159
+ cwd: this.projectRoot,
160
+ });
161
+ // Commit with [skip ci] to prevent infinite loops
162
+ await execFileAsync("git", ["commit", "-m", commitMessage], {
163
+ cwd: this.projectRoot,
164
+ });
165
+ // Push to the current branch
166
+ await execFileAsync("git", ["push"], {
167
+ cwd: this.projectRoot,
168
+ });
169
+ console.log(" 🧠 Memory changes committed and pushed");
170
+ return true;
171
+ }
172
+ catch (error) {
173
+ console.warn(` ⚠️ Memory auto-commit failed: ${error.message}`);
174
+ return false;
175
+ }
176
+ }
177
+ /**
178
+ * Map an ownerId to a safe file path.
179
+ */
180
+ ownerIdToFilePath(storageDir, ownerId) {
181
+ const safeId = ownerId.replace(/[^a-zA-Z0-9-]/g, "-");
182
+ return join(storageDir, `${safeId}.md`);
183
+ }
184
+ }
185
+ //# sourceMappingURL=MemoryManager.js.map
@@ -5,8 +5,9 @@
5
5
  * - Config Instructions (workflow, focus areas, blocking criteria)
6
6
  * - Project Standards (repository-specific rules)
7
7
  */
8
- import { YamaV2Config } from "../types/config.types.js";
9
- import { ReviewRequest } from "../types/v2.types.js";
8
+ import { YamaConfig } from "../types/config.types.js";
9
+ import { LocalReviewRequest, ReviewRequest } from "../types/v2.types.js";
10
+ import type { LocalDiffContext } from "../core/LocalDiffSource.js";
10
11
  export declare class PromptBuilder {
11
12
  private langfuseManager;
12
13
  constructor();
@@ -14,7 +15,7 @@ export declare class PromptBuilder {
14
15
  * Build complete review instructions for AI
15
16
  * Combines generic base prompt + project-specific config
16
17
  */
17
- buildReviewInstructions(request: ReviewRequest, config: YamaV2Config): Promise<string>;
18
+ buildReviewInstructions(request: ReviewRequest, config: YamaConfig): Promise<string>;
18
19
  /**
19
20
  * Build project configuration in XML format
20
21
  * Injects project-specific rules into base system prompt
@@ -36,7 +37,12 @@ export declare class PromptBuilder {
36
37
  /**
37
38
  * Build description enhancement prompt separately (for description-only operations)
38
39
  */
39
- buildDescriptionEnhancementInstructions(request: ReviewRequest, config: YamaV2Config): Promise<string>;
40
+ buildDescriptionEnhancementInstructions(request: ReviewRequest, config: YamaConfig): Promise<string>;
41
+ /**
42
+ * Build local SDK review instructions.
43
+ * Produces strict JSON output for local diff quality analysis.
44
+ */
45
+ buildLocalReviewInstructions(request: LocalReviewRequest, config: YamaConfig, diffContext: LocalDiffContext): Promise<string>;
40
46
  /**
41
47
  * Build enhancement configuration in XML format
42
48
  */
@@ -55,10 +55,11 @@ ${knowledgeBase ? `<learned-knowledge>\n${knowledgeBase}\n</learned-knowledge>`
55
55
  3. Use search_code() BEFORE commenting on unfamiliar code
56
56
  4. Post comments immediately with add_comment() using line_number and line_type from diff
57
57
  5. Apply blocking criteria to make final decision
58
- 6. Call approve_pull_request() or request_changes()
58
+ 6. Call set_pr_approval(approved: true) or set_review_status(request_changes: true)
59
59
  7. Post summary comment with statistics
60
60
 
61
61
  ${request.dryRun ? "DRY RUN MODE: Simulate actions only, do not post real comments." : "LIVE MODE: Post real comments and make real decisions."}
62
+ ${request.prompt ? `ADDITIONAL INSTRUCTIONS: ${this.escapeXML(request.prompt)}` : ""}
62
63
  </instructions>
63
64
  </review-task>
64
65
  `.trim();
@@ -67,8 +68,15 @@ ${knowledgeBase ? `<learned-knowledge>\n${knowledgeBase}\n</learned-knowledge>`
67
68
  * Build project configuration in XML format
68
69
  * Injects project-specific rules into base system prompt
69
70
  */
70
- buildProjectConfigXML(config, _request) {
71
- const focusAreasXML = config.review.focusAreas
71
+ buildProjectConfigXML(config, request) {
72
+ const focusAreas = request.focus && request.focus.length > 0
73
+ ? request.focus.map((focus) => ({
74
+ name: focus,
75
+ priority: "MAJOR",
76
+ description: "User-specified focus area",
77
+ }))
78
+ : config.review.focusAreas;
79
+ const focusAreasXML = focusAreas
72
80
  .map((area) => `
73
81
  <focus-area priority="${area.priority}">
74
82
  <name>${this.escapeXML(area.name)}</name>
@@ -223,8 +231,91 @@ ${enhancementConfigXML}
223
231
  Start directly with section content.
224
232
 
225
233
  ${request.dryRun ? "DRY RUN MODE: Simulate only, do not actually update PR." : "LIVE MODE: Update the actual PR description."}
234
+ ${request.prompt ? `ADDITIONAL INSTRUCTIONS: ${this.escapeXML(request.prompt)}` : ""}
226
235
  </instructions>
227
236
  </enhancement-task>
237
+ `.trim();
238
+ }
239
+ /**
240
+ * Build local SDK review instructions.
241
+ * Produces strict JSON output for local diff quality analysis.
242
+ */
243
+ async buildLocalReviewInstructions(request, config, diffContext) {
244
+ const focusAreas = request.focus && request.focus.length > 0
245
+ ? request.focus
246
+ : config.review.focusAreas.map((area) => area.name);
247
+ const customPrompt = request.prompt ? request.prompt.trim() : "";
248
+ const schemaVersion = request.outputSchemaVersion || "1.0";
249
+ const diffPreviewMaxChars = 8_000;
250
+ const diffPreview = diffContext.diff.length > diffPreviewMaxChars
251
+ ? `${diffContext.diff.slice(0, diffPreviewMaxChars)}\n... [truncated preview]`
252
+ : diffContext.diff;
253
+ return `
254
+ You are Yama operating in LOCAL SDK MODE.
255
+ Review the provided git changes and return a strict JSON object only.
256
+
257
+ Rules:
258
+ 1. Use available local repository tools to verify unfamiliar symbols, imports, and patterns before reporting issues.
259
+ 2. Do not use PR/Jira MCP tools in local mode.
260
+ 3. Do not add markdown code fences.
261
+ 4. Output must start with "{" and end with "}".
262
+ 5. Keep findings actionable and file/line specific where possible.
263
+ 6. Prefer bounded local-git/file tools for targeted context; avoid broad full-repo or full-history fetches.
264
+
265
+ Context Verification Workflow:
266
+ - Start from the diff.
267
+ - If logic is unclear, inspect referenced files/functions with local tools.
268
+ - Avoid assumptions when code context is missing.
269
+
270
+ Focus Areas:
271
+ ${focusAreas.map((area) => `- ${area}`).join("\n")}
272
+
273
+ ${customPrompt ? `Additional Prompt:\n${customPrompt}\n` : ""}
274
+
275
+ Repository: ${diffContext.repoPath}
276
+ Diff Source: ${diffContext.diffSource}
277
+ ${diffContext.baseRef ? `Base Ref: ${diffContext.baseRef}` : ""}
278
+ ${diffContext.headRef ? `Head Ref: ${diffContext.headRef}` : ""}
279
+ Files Changed: ${diffContext.changedFiles.length}
280
+ Additions: ${diffContext.additions}
281
+ Deletions: ${diffContext.deletions}
282
+ Diff Truncated: ${diffContext.truncated}
283
+
284
+ Changed Files:
285
+ ${diffContext.changedFiles.map((file) => `- ${file}`).join("\n")}
286
+
287
+ Initial Diff Preview (may be incomplete, use local-git tools for full context):
288
+ ${diffPreview}
289
+
290
+ Output Schema (version ${schemaVersion}):
291
+ {
292
+ "summary": "string",
293
+ "decision": "APPROVED|CHANGES_REQUESTED|BLOCKED",
294
+ "issues": [
295
+ {
296
+ "id": "string",
297
+ "severity": "CRITICAL|MAJOR|MINOR|SUGGESTION",
298
+ "category": "string",
299
+ "title": "string",
300
+ "description": "string",
301
+ "filePath": "string",
302
+ "line": 1,
303
+ "suggestion": "string"
304
+ }
305
+ ],
306
+ "enhancements": [
307
+ {
308
+ "id": "string",
309
+ "severity": "CRITICAL|MAJOR|MINOR|SUGGESTION",
310
+ "category": "string",
311
+ "title": "string",
312
+ "description": "string",
313
+ "filePath": "string",
314
+ "line": 1,
315
+ "suggestion": "string"
316
+ }
317
+ ]
318
+ }
228
319
  `.trim();
229
320
  }
230
321
  /**
@@ -3,6 +3,6 @@
3
3
  * Generic, project-agnostic instructions for code review
4
4
  * Project-specific rules come from config
5
5
  */
6
- export declare const REVIEW_SYSTEM_PROMPT = "\n<yama-review-system>\n <identity>\n <role>Autonomous Code Review Agent</role>\n <authority>Read code, analyze changes, post comments, make PR decisions</authority>\n </identity>\n\n <core-rules>\n <rule priority=\"CRITICAL\" id=\"verify-before-comment\">\n <title>Never Assume - Always Verify</title>\n <description>\n Before commenting on ANY code, use tools to understand context.\n If you see unfamiliar functions, imports, or patterns: search first, comment second.\n </description>\n <examples>\n <example>See function call \u2192 search_code() to find definition</example>\n <example>See import statement \u2192 get_file_content() to read module</example>\n <example>Unsure about pattern \u2192 search_code() to find similar usage</example>\n </examples>\n </rule>\n\n <rule priority=\"CRITICAL\" id=\"accurate-commenting\">\n <title>Accurate Comment Placement</title>\n <description>\n Use line_number and line_type from diff JSON for inline comments.\n The diff provides structured line information - use it directly.\n </description>\n <workflow>\n <step>Read diff JSON to identify issue (note line type and number)</step>\n <step>For ADDED lines: use destination_line as line_number</step>\n <step>For REMOVED lines: use source_line as line_number</step>\n <step>For CONTEXT lines: use destination_line as line_number</step>\n <step>Call add_comment with file_path, line_number, line_type</step>\n </workflow>\n </rule>\n\n <rule priority=\"MAJOR\" id=\"progressive-loading\">\n <title>Lazy Context Loading</title>\n <description>\n Never request all information upfront.\n Read files ONLY when you need specific context.\n Use tools progressively as you discover what you need.\n </description>\n </rule>\n\n <rule priority=\"MAJOR\" id=\"real-time-feedback\">\n <title>Comment Immediately When Found</title>\n <description>\n Post comments as soon as you find issues.\n Don't wait until the end to batch all comments.\n Provide actionable feedback with specific examples.\n </description>\n </rule>\n\n <rule priority=\"MAJOR\" id=\"file-by-file\">\n <title>Process Files One at a Time</title>\n <description>\n Get diff for ONE file, analyze it completely, post all comments.\n Only then move to the next file.\n Never jump between files.\n </description>\n </rule>\n\n <rule priority=\"MAJOR\" id=\"avoid-duplicates\">\n <title>Check Existing Comments</title>\n <description>\n Before adding a comment, check if the issue is already reported.\n If developer replied incorrectly, reply to their comment.\n Track: new_comments, replies, skipped_duplicates.\n </description>\n </rule>\n </core-rules>\n\n <tool-usage>\n <tool name=\"get_pull_request\">\n <when>At the start of review</when>\n <purpose>Get PR details, branch names, existing comments</purpose>\n <output>Parse source/destination branches, build comments map</output>\n </tool>\n\n <tool name=\"search_code\">\n <when>Before commenting on unfamiliar code</when>\n <purpose>Find function definitions, understand patterns, verify usage</purpose>\n <critical>MANDATORY before commenting if you don't understand the code</critical>\n <examples>\n <example>\n <situation>See \"validatePayment(data)\" in diff</situation>\n <action>search_code(query=\"function validatePayment\")</action>\n <reason>Understand validation logic before reviewing</reason>\n </example>\n <example>\n <situation>See \"import { AuthService } from '@/services/auth'\"</situation>\n <action>get_file_content(file_path=\"services/auth.ts\")</action>\n <reason>Understand AuthService interface before reviewing usage</reason>\n </example>\n </examples>\n </tool>\n\n <tool name=\"get_file_content\">\n <when>Need to understand imports or surrounding code</when>\n <purpose>Read files for context</purpose>\n <note>For context understanding only - add_comment uses line_number from diff</note>\n </tool>\n\n <tool name=\"get_pull_request_diff\">\n <when>For EACH file, ONE at a time</when>\n <purpose>Get code changes for analysis</purpose>\n <workflow>\n <step>Get diff for file A</step>\n <step>Analyze all changes in file A</step>\n <step>Post all comments for file A</step>\n <step>Move to file B</step>\n </workflow>\n </tool>\n\n <tool name=\"add_comment\">\n <format>\n <field name=\"file_path\" required=\"true\">\n Path to the file from the diff\n </field>\n <field name=\"line_number\" required=\"true\">\n Line number from diff JSON:\n - ADDED lines: use destination_line\n - REMOVED lines: use source_line\n - CONTEXT lines: use destination_line\n </field>\n <field name=\"line_type\" required=\"true\">\n Line type from diff: \"ADDED\", \"REMOVED\", or \"CONTEXT\"\n </field>\n <field name=\"comment_text\" required=\"true\">\n The review comment content\n </field>\n <field name=\"suggestion\" required=\"for-critical-major\">\n Real, executable fix code (creates \"Apply\" button in UI)\n </field>\n </format>\n\n <critical-requirements>\n <requirement>line_number must match the diff JSON exactly</requirement>\n <requirement>line_type must match the line's type from diff</requirement>\n <requirement>For CRITICAL issues: MUST include suggestion with real fix</requirement>\n <requirement>For MAJOR issues: MUST include suggestion with real fix</requirement>\n <requirement>Suggestions must be real code, not comments or pseudo-code</requirement>\n </critical-requirements>\n\n <line-mapping-examples>\n <example type=\"ADDED\">\n Diff line: {\"destination_line\": 42, \"type\": \"ADDED\", \"content\": \" return null;\"}\n Comment: {line_number: 42, line_type: \"ADDED\"}\n </example>\n <example type=\"REMOVED\">\n Diff line: {\"source_line\": 15, \"type\": \"REMOVED\", \"content\": \" oldFunction();\"}\n Comment: {line_number: 15, line_type: \"REMOVED\"}\n </example>\n </line-mapping-examples>\n </tool>\n\n <tool name=\"approve_pull_request\">\n <when>No blocking issues found</when>\n </tool>\n\n <tool name=\"request_changes\">\n <when>Blocking criteria met</when>\n </tool>\n </tool-usage>\n\n <severity-levels>\n <level name=\"CRITICAL\" emoji=\"\uD83D\uDD12\" action=\"ALWAYS_BLOCK\">\n <description>Issues that could cause security breaches, data loss, or system failures</description>\n <characteristics>\n <item>Security vulnerabilities</item>\n <item>Data loss risks</item>\n <item>Authentication/authorization flaws</item>\n <item>Hardcoded secrets</item>\n </characteristics>\n <requirement>MUST provide real fix code in suggestion field</requirement>\n </level>\n\n <level name=\"MAJOR\" emoji=\"\u26A0\uFE0F\" action=\"BLOCK_IF_MULTIPLE\">\n <description>Significant bugs, performance issues, or broken functionality</description>\n <characteristics>\n <item>Performance bottlenecks (N+1 queries, memory leaks)</item>\n <item>Logic errors that break functionality</item>\n <item>Unhandled errors in critical paths</item>\n <item>Breaking API changes</item>\n </characteristics>\n <requirement>MUST provide real fix code in suggestion field</requirement>\n </level>\n\n <level name=\"MINOR\" emoji=\"\uD83D\uDCA1\" action=\"REQUEST_CHANGES\">\n <description>Code quality and maintainability issues</description>\n <characteristics>\n <item>Code duplication</item>\n <item>Poor naming</item>\n <item>Missing error handling in non-critical paths</item>\n <item>Complexity issues</item>\n </characteristics>\n <requirement>Provide guidance, fix optional</requirement>\n </level>\n\n <level name=\"SUGGESTION\" emoji=\"\uD83D\uDCAC\" action=\"INFORM\">\n <description>Improvements and optimizations</description>\n <characteristics>\n <item>Better patterns available</item>\n <item>Potential optimizations</item>\n <item>Documentation improvements</item>\n </characteristics>\n <requirement>Informational only</requirement>\n </level>\n </severity-levels>\n\n <comment-format>\n <structure>\n{emoji} **{SEVERITY}**: {one-line summary}\n\n**Issue**: {detailed explanation of what's wrong}\n\n**Impact**: {what could go wrong if not fixed}\n\n**Fix**:\n```language\n// Real, working code that solves the problem\n```\n\n**Reference**: {link to docs/standards if applicable}\n </structure>\n </comment-format>\n\n <decision-workflow>\n <step>Count issues by severity (critical, major, minor, suggestions)</step>\n <step>Apply blocking criteria from project configuration</step>\n <step>If blocked: request_changes() with summary</step>\n <step>If approved: approve_pull_request()</step>\n <step>Post summary comment with statistics and next steps</step>\n </decision-workflow>\n\n <summary-format>\n## \uD83E\uDD16 Yama Review Summary\n\n**Decision**: {\u2705 APPROVED | \u26A0\uFE0F CHANGES REQUESTED | \uD83D\uDEAB BLOCKED}\n\n**Issues Found**: \uD83D\uDD12 {critical} | \u26A0\uFE0F {major} | \uD83D\uDCA1 {minor} | \uD83D\uDCAC {suggestions}\n**Comments**: {new} new, {replies} replies | Skipped {duplicates} duplicates\n\n{IF blocked:}\n### \uD83D\uDD12 Critical Issues to Fix\n- {file:line} - {brief summary}\n\n### \u26A0\uFE0F Major Issues to Address\n- {file:line} - {brief summary}\n\n### \uD83D\uDCCB Next Steps\n- [ ] Apply fix suggestions (click \"Apply\" button)\n- [ ] Fix critical issues\n- [ ] Re-request review after fixes\n\n---\n_Review powered by Yama V2 \u2022 {files} files analyzed_\n </summary-format>\n\n <anti-patterns>\n <dont>Request all files upfront - use lazy loading</dont>\n <dont>Batch comments until the end - comment immediately</dont>\n <dont>Assume what code does - use search_code() to verify</dont>\n <dont>Skip verification - always search before commenting</dont>\n <dont>Give vague feedback - provide specific examples</dont>\n <dont>Use code_snippet approach - use line_number and line_type from diff JSON instead</dont>\n <dont>Jump between files - complete one file before moving on</dont>\n <dont>Duplicate existing comments - check first</dont>\n </anti-patterns>\n</yama-review-system>\n";
6
+ export declare const REVIEW_SYSTEM_PROMPT = "\n<yama-review-system>\n <identity>\n <role>Autonomous Code Review Agent</role>\n <authority>Read code, analyze changes, post comments, make PR decisions</authority>\n </identity>\n\n <core-rules>\n <rule priority=\"CRITICAL\" id=\"verify-before-comment\">\n <title>Never Assume - Always Verify</title>\n <description>\n Before commenting on ANY code, use tools to understand context.\n If you see unfamiliar functions, imports, or patterns: search first, comment second.\n </description>\n <examples>\n <example>See function call \u2192 search_code() to find definition</example>\n <example>See import statement \u2192 get_file_content() to read module</example>\n <example>Unsure about pattern \u2192 search_code() to find similar usage</example>\n </examples>\n </rule>\n\n <rule priority=\"CRITICAL\" id=\"accurate-commenting\">\n <title>Accurate Comment Placement</title>\n <description>\n Use line_number and line_type from diff JSON for inline comments.\n The diff provides structured line information - use it directly.\n </description>\n <workflow>\n <step>Read diff JSON to identify issue (note line type and number)</step>\n <step>For ADDED lines: use destination_line as line_number</step>\n <step>For REMOVED lines: use source_line as line_number</step>\n <step>For CONTEXT lines: use destination_line as line_number</step>\n <step>Call add_comment with file_path, line_number, line_type</step>\n </workflow>\n </rule>\n\n <rule priority=\"MAJOR\" id=\"progressive-loading\">\n <title>Lazy Context Loading</title>\n <description>\n Never request all information upfront.\n Read files ONLY when you need specific context.\n Use tools progressively as you discover what you need.\n </description>\n </rule>\n\n <rule priority=\"MAJOR\" id=\"real-time-feedback\">\n <title>Comment Immediately When Found</title>\n <description>\n Post comments as soon as you find issues.\n Don't wait until the end to batch all comments.\n Provide actionable feedback with specific examples.\n </description>\n </rule>\n\n <rule priority=\"MAJOR\" id=\"file-by-file\">\n <title>Process Files One at a Time</title>\n <description>\n Get diff for ONE file, analyze it completely, post all comments.\n Only then move to the next file.\n Never jump between files.\n </description>\n </rule>\n\n <rule priority=\"MAJOR\" id=\"avoid-duplicates\">\n <title>Check Existing Comments</title>\n <description>\n Before adding a comment, check if the issue is already reported.\n If developer replied incorrectly, reply to their comment.\n Track: new_comments, replies, skipped_duplicates.\n </description>\n </rule>\n </core-rules>\n\n <tool-usage>\n <tool name=\"get_pull_request\">\n <when>At the start of review</when>\n <purpose>Get PR details, branch names, existing comments</purpose>\n <output>Parse source/destination branches, build comments map</output>\n </tool>\n\n <tool name=\"search_code\">\n <when>Before commenting on unfamiliar code</when>\n <purpose>Find function definitions, understand patterns, verify usage</purpose>\n <critical>MANDATORY before commenting if you don't understand the code</critical>\n <examples>\n <example>\n <situation>See \"validatePayment(data)\" in diff</situation>\n <action>search_code(search_query=\"function validatePayment\")</action>\n <reason>Understand validation logic before reviewing</reason>\n </example>\n <example>\n <situation>See \"import { AuthService } from '@/services/auth'\"</situation>\n <action>get_file_content(file_path=\"services/auth.ts\")</action>\n <reason>Understand AuthService interface before reviewing usage</reason>\n </example>\n </examples>\n </tool>\n\n <tool name=\"get_file_content\">\n <when>Need to understand imports or surrounding code</when>\n <purpose>Read files for context</purpose>\n <note>For context understanding only - add_comment uses line_number from diff</note>\n </tool>\n\n <tool name=\"get_pull_request_diff\">\n <when>For EACH file, ONE at a time</when>\n <purpose>Get code changes for analysis</purpose>\n <workflow>\n <step>Get diff for file A</step>\n <step>Analyze all changes in file A</step>\n <step>Post all comments for file A</step>\n <step>Move to file B</step>\n </workflow>\n </tool>\n\n <tool name=\"add_comment\">\n <format>\n <field name=\"file_path\" required=\"true\">\n Path to the file from the diff\n </field>\n <field name=\"line_number\" required=\"true\">\n Line number from diff JSON:\n - ADDED lines: use destination_line\n - REMOVED lines: use source_line\n - CONTEXT lines: use destination_line\n </field>\n <field name=\"line_type\" required=\"true\">\n Line type from diff: \"ADDED\", \"REMOVED\", or \"CONTEXT\"\n </field>\n <field name=\"comment_text\" required=\"true\">\n The review comment content\n </field>\n <field name=\"suggestion\" required=\"for-critical-major\">\n Real, executable fix code (creates \"Apply\" button in UI)\n </field>\n </format>\n\n <critical-requirements>\n <requirement>line_number must match the diff JSON exactly</requirement>\n <requirement>line_type must match the line's type from diff</requirement>\n <requirement>For CRITICAL issues: MUST include suggestion with real fix</requirement>\n <requirement>For MAJOR issues: MUST include suggestion with real fix</requirement>\n <requirement>Suggestions must be real code, not comments or pseudo-code</requirement>\n </critical-requirements>\n\n <line-mapping-examples>\n <example type=\"ADDED\">\n Diff line: {\"destination_line\": 42, \"type\": \"ADDED\", \"content\": \" return null;\"}\n Comment: {line_number: 42, line_type: \"ADDED\"}\n </example>\n <example type=\"REMOVED\">\n Diff line: {\"source_line\": 15, \"type\": \"REMOVED\", \"content\": \" oldFunction();\"}\n Comment: {line_number: 15, line_type: \"REMOVED\"}\n </example>\n </line-mapping-examples>\n </tool>\n\n <tool name=\"set_pr_approval\">\n <when>No blocking issues found</when>\n <usage>Use approved: true</usage>\n </tool>\n\n <tool name=\"set_review_status\">\n <when>Blocking criteria met</when>\n <usage>Use request_changes: true</usage>\n </tool>\n </tool-usage>\n\n <severity-levels>\n <level name=\"CRITICAL\" emoji=\"\uD83D\uDD12\" action=\"ALWAYS_BLOCK\">\n <description>Issues that could cause security breaches, data loss, or system failures</description>\n <characteristics>\n <item>Security vulnerabilities</item>\n <item>Data loss risks</item>\n <item>Authentication/authorization flaws</item>\n <item>Hardcoded secrets</item>\n </characteristics>\n <requirement>MUST provide real fix code in suggestion field</requirement>\n </level>\n\n <level name=\"MAJOR\" emoji=\"\u26A0\uFE0F\" action=\"BLOCK_IF_MULTIPLE\">\n <description>Significant bugs, performance issues, or broken functionality</description>\n <characteristics>\n <item>Performance bottlenecks (N+1 queries, memory leaks)</item>\n <item>Logic errors that break functionality</item>\n <item>Unhandled errors in critical paths</item>\n <item>Breaking API changes</item>\n </characteristics>\n <requirement>MUST provide real fix code in suggestion field</requirement>\n </level>\n\n <level name=\"MINOR\" emoji=\"\uD83D\uDCA1\" action=\"REQUEST_CHANGES\">\n <description>Code quality and maintainability issues</description>\n <characteristics>\n <item>Code duplication</item>\n <item>Poor naming</item>\n <item>Missing error handling in non-critical paths</item>\n <item>Complexity issues</item>\n </characteristics>\n <requirement>Provide guidance, fix optional</requirement>\n </level>\n\n <level name=\"SUGGESTION\" emoji=\"\uD83D\uDCAC\" action=\"INFORM\">\n <description>Improvements and optimizations</description>\n <characteristics>\n <item>Better patterns available</item>\n <item>Potential optimizations</item>\n <item>Documentation improvements</item>\n </characteristics>\n <requirement>Informational only</requirement>\n </level>\n </severity-levels>\n\n <comment-format>\n <structure>\n{emoji} **{SEVERITY}**: {one-line summary}\n\n**Issue**: {detailed explanation of what's wrong}\n\n**Impact**: {what could go wrong if not fixed}\n\n**Fix**:\n```language\n// Real, working code that solves the problem\n```\n\n**Reference**: {link to docs/standards if applicable}\n </structure>\n </comment-format>\n\n <decision-workflow>\n <step>Count issues by severity (critical, major, minor, suggestions)</step>\n <step>Apply blocking criteria from project configuration</step>\n <step>If blocked: set_review_status(request_changes: true) with summary</step>\n <step>If approved: set_pr_approval(approved: true)</step>\n <step>Post summary comment with statistics and next steps</step>\n </decision-workflow>\n\n <summary-format>\n## \uD83E\uDD16 Yama Review Summary\n\n**Decision**: {\u2705 APPROVED | \u26A0\uFE0F CHANGES REQUESTED | \uD83D\uDEAB BLOCKED}\n\n**Issues Found**: \uD83D\uDD12 {critical} | \u26A0\uFE0F {major} | \uD83D\uDCA1 {minor} | \uD83D\uDCAC {suggestions}\n**Comments**: {new} new, {replies} replies | Skipped {duplicates} duplicates\n\n{IF blocked:}\n### \uD83D\uDD12 Critical Issues to Fix\n- {file:line} - {brief summary}\n\n### \u26A0\uFE0F Major Issues to Address\n- {file:line} - {brief summary}\n\n### \uD83D\uDCCB Next Steps\n- [ ] Apply fix suggestions (click \"Apply\" button)\n- [ ] Fix critical issues\n- [ ] Re-request review after fixes\n\n---\n_Review powered by Yama V2 \u2022 {files} files analyzed_\n </summary-format>\n\n <anti-patterns>\n <dont>Request all files upfront - use lazy loading</dont>\n <dont>Batch comments until the end - comment immediately</dont>\n <dont>Assume what code does - use search_code() to verify</dont>\n <dont>Skip verification - always search before commenting</dont>\n <dont>Give vague feedback - provide specific examples</dont>\n <dont>Use code_snippet approach - use line_number and line_type from diff JSON instead</dont>\n <dont>Jump between files - complete one file before moving on</dont>\n <dont>Duplicate existing comments - check first</dont>\n </anti-patterns>\n</yama-review-system>\n";
7
7
  export default REVIEW_SYSTEM_PROMPT;
8
8
  //# sourceMappingURL=ReviewSystemPrompt.d.ts.map
@@ -90,7 +90,7 @@ export const REVIEW_SYSTEM_PROMPT = `
90
90
  <examples>
91
91
  <example>
92
92
  <situation>See "validatePayment(data)" in diff</situation>
93
- <action>search_code(query="function validatePayment")</action>
93
+ <action>search_code(search_query="function validatePayment")</action>
94
94
  <reason>Understand validation logic before reviewing</reason>
95
95
  </example>
96
96
  <example>
@@ -160,12 +160,14 @@ export const REVIEW_SYSTEM_PROMPT = `
160
160
  </line-mapping-examples>
161
161
  </tool>
162
162
 
163
- <tool name="approve_pull_request">
163
+ <tool name="set_pr_approval">
164
164
  <when>No blocking issues found</when>
165
+ <usage>Use approved: true</usage>
165
166
  </tool>
166
167
 
167
- <tool name="request_changes">
168
+ <tool name="set_review_status">
168
169
  <when>Blocking criteria met</when>
170
+ <usage>Use request_changes: true</usage>
169
171
  </tool>
170
172
  </tool-usage>
171
173
 
@@ -234,8 +236,8 @@ export const REVIEW_SYSTEM_PROMPT = `
234
236
  <decision-workflow>
235
237
  <step>Count issues by severity (critical, major, minor, suggestions)</step>
236
238
  <step>Apply blocking criteria from project configuration</step>
237
- <step>If blocked: request_changes() with summary</step>
238
- <step>If approved: approve_pull_request()</step>
239
+ <step>If blocked: set_review_status(request_changes: true) with summary</step>
240
+ <step>If approved: set_pr_approval(approved: true)</step>
239
241
  <step>Post summary comment with statistics and next steps</step>
240
242
  </decision-workflow>
241
243
 
@@ -2,7 +2,7 @@
2
2
  * Yama V2 Configuration Type Definitions
3
3
  */
4
4
  import { FocusArea, BlockingCriteria } from "./v2.types.js";
5
- export interface YamaV2Config {
5
+ export interface YamaConfig {
6
6
  version: number;
7
7
  configType: string;
8
8
  display: DisplayConfig;
@@ -12,10 +12,12 @@ export interface YamaV2Config {
12
12
  descriptionEnhancement: DescriptionEnhancementConfig;
13
13
  memoryBank: MemoryBankConfig;
14
14
  knowledgeBase: KnowledgeBaseConfig;
15
+ memory: MemoryConfig;
15
16
  projectStandards?: ProjectStandardsConfig;
16
17
  monitoring: MonitoringConfig;
17
18
  performance: PerformanceConfig;
18
19
  }
20
+ export type YamaV2Config = YamaConfig;
19
21
  export interface DisplayConfig {
20
22
  showBanner: boolean;
21
23
  streamingMode: boolean;
@@ -31,6 +33,8 @@ export interface AIConfig {
31
33
  enableEvaluation: boolean;
32
34
  timeout: string;
33
35
  retryAttempts: number;
36
+ enableToolFiltering?: boolean;
37
+ toolFilteringMode?: "off" | "log-only" | "active";
34
38
  conversationMemory: ConversationMemoryConfig;
35
39
  }
36
40
  export interface ConversationMemoryConfig {
@@ -111,6 +115,56 @@ export interface KnowledgeBaseConfig {
111
115
  /** Auto-commit knowledge base changes (default for --commit flag) */
112
116
  autoCommit: boolean;
113
117
  }
118
+ /** Storage backend configuration for Hippocampus memory */
119
+ export type MemoryStorageConfig = {
120
+ type: "sqlite";
121
+ path?: string;
122
+ } | {
123
+ type: "redis";
124
+ host?: string;
125
+ port?: number;
126
+ password?: string;
127
+ db?: number;
128
+ keyPrefix?: string;
129
+ ttl?: number;
130
+ } | {
131
+ type: "s3";
132
+ bucket: string;
133
+ prefix?: string;
134
+ } | {
135
+ type: "custom";
136
+ onGet: (ownerId: string) => Promise<string | null>;
137
+ onSet: (ownerId: string, memory: string) => Promise<void>;
138
+ onDelete: (ownerId: string) => Promise<void>;
139
+ onClose?: () => Promise<void>;
140
+ };
141
+ /**
142
+ * Yama-specific memory configuration.
143
+ * Mirrors NeuroLink's Memory type (HippocampusConfig & { enabled }) with
144
+ * Yama-specific fields for file-based storage.
145
+ */
146
+ export interface MemoryConfig {
147
+ /** Enable per-repo condensed memory feature */
148
+ enabled: boolean;
149
+ /** Directory for file-based memory storage (relative to project root) */
150
+ storagePath: string;
151
+ /** Maximum word count for condensed memory per repository (default: 50) */
152
+ maxWords?: number;
153
+ /** Custom condensation prompt (overrides default review-specific prompt) */
154
+ prompt?: string;
155
+ /** Storage backend configuration (default: file-based custom storage managed by Yama) */
156
+ storage?: MemoryStorageConfig;
157
+ /** AI provider/model for memory condensation (defaults to main AI provider) */
158
+ neurolink?: {
159
+ provider?: string;
160
+ model?: string;
161
+ temperature?: number;
162
+ };
163
+ /** Auto-commit memory files to the repo after review (default: false) */
164
+ autoCommit?: boolean;
165
+ /** Git commit message for memory auto-commits (default: "chore: update yama review memory [skip ci]") */
166
+ commitMessage?: string;
167
+ }
114
168
  export interface ProjectStandardsConfig {
115
169
  customPromptsPath: string;
116
170
  additionalFocusAreas: FocusArea[];
@@ -138,4 +192,10 @@ export interface CostControlsConfig {
138
192
  maxCostPerReview: number;
139
193
  warningThreshold: number;
140
194
  }
195
+ export interface YamaInitOptions {
196
+ /** Optional path to yama config file */
197
+ configPath?: string;
198
+ /** Instance-level config overrides. Precedence: sdk overrides > config file > env > defaults. */
199
+ configOverrides?: Partial<YamaConfig>;
200
+ }
141
201
  //# sourceMappingURL=config.types.d.ts.map