@probelabs/visor 0.1.86 → 0.1.87
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -0
- package/dist/action-cli-bridge.d.ts.map +1 -1
- package/dist/ai-review-service.d.ts.map +1 -1
- package/dist/check-execution-engine.d.ts.map +1 -1
- package/dist/failure-condition-evaluator.d.ts.map +1 -1
- package/dist/index.js +145 -45
- package/dist/output-formatters.d.ts +8 -0
- package/dist/output-formatters.d.ts.map +1 -1
- package/dist/sdk/{check-execution-engine-WI7LJL2G.mjs → check-execution-engine-2YUDSTZS.mjs} +2 -2
- package/dist/sdk/{chunk-P4XLP7NN.mjs → chunk-VQGP55ZL.mjs} +81 -25
- package/dist/sdk/chunk-VQGP55ZL.mjs.map +1 -0
- package/dist/sdk/sdk.js +79 -23
- package/dist/sdk/sdk.js.map +1 -1
- package/dist/sdk/sdk.mjs +1 -1
- package/package.json +1 -1
- package/dist/sdk/chunk-P4XLP7NN.mjs.map +0 -1
- /package/dist/sdk/{check-execution-engine-WI7LJL2G.mjs.map → check-execution-engine-2YUDSTZS.mjs.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/session-registry.ts","../../src/github-comments.ts","../../src/ai-review-service.ts","../../src/logger.ts","../../src/reviewer.ts","../../src/git-repository-analyzer.ts","../../src/providers/check-provider.interface.ts","../../src/utils/env-resolver.ts","../../src/issue-filter.ts","../../src/providers/ai-check-provider.ts","../../src/providers/http-check-provider.ts","../../src/providers/http-input-provider.ts","../../src/providers/http-client-provider.ts","../../src/providers/noop-check-provider.ts","../../src/providers/log-check-provider.ts","../../src/providers/claude-code-check-provider.ts","../../src/providers/claude-code-types.ts","../../src/providers/command-check-provider.ts","../../src/providers/check-provider-registry.ts","../../src/dependency-resolver.ts","../../src/failure-condition-evaluator.ts","../../src/github-check-service.ts","../../src/check-execution-engine.ts"],"sourcesContent":["import { ProbeAgent } from '@probelabs/probe';\n\n/**\n * Registry to manage active ProbeAgent sessions for session reuse\n */\nexport class SessionRegistry {\n private static instance: SessionRegistry;\n private sessions: Map<string, ProbeAgent> = new Map();\n private exitHandlerRegistered = false;\n\n private constructor() {\n // Register process exit handlers to cleanup sessions\n this.registerExitHandlers();\n }\n\n /**\n * Get the singleton instance of SessionRegistry\n */\n public static getInstance(): SessionRegistry {\n if (!SessionRegistry.instance) {\n SessionRegistry.instance = new SessionRegistry();\n }\n return SessionRegistry.instance;\n }\n\n /**\n * Register a ProbeAgent session\n */\n public registerSession(sessionId: string, agent: ProbeAgent): void {\n console.error(`🔄 Registering AI session: ${sessionId}`);\n this.sessions.set(sessionId, agent);\n }\n\n /**\n * Get an existing ProbeAgent session\n */\n public getSession(sessionId: string): ProbeAgent | undefined {\n const agent = this.sessions.get(sessionId);\n if (agent) {\n console.error(`♻️ Reusing AI session: ${sessionId}`);\n }\n return agent;\n }\n\n /**\n * Remove a session from the registry\n */\n public unregisterSession(sessionId: string): void {\n if (this.sessions.has(sessionId)) {\n console.error(`🗑️ Unregistering AI session: ${sessionId}`);\n const agent = this.sessions.get(sessionId);\n this.sessions.delete(sessionId);\n\n // Cleanup the ProbeAgent instance to prevent hanging processes\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n if (agent && typeof (agent as any).cleanup === 'function') {\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (agent as any).cleanup();\n } catch (error) {\n console.error(`⚠️ Warning: Failed to cleanup ProbeAgent: ${error}`);\n }\n }\n }\n }\n\n /**\n * Clear all sessions (useful for cleanup)\n */\n public clearAllSessions(): void {\n console.error(`🧹 Clearing all AI sessions (${this.sessions.size} sessions)`);\n\n // Cleanup each ProbeAgent instance before clearing\n for (const [, agent] of this.sessions.entries()) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n if (agent && typeof (agent as any).cleanup === 'function') {\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (agent as any).cleanup();\n } catch {\n // Silent fail during bulk cleanup\n }\n }\n }\n\n this.sessions.clear();\n }\n\n /**\n * Get all active session IDs\n */\n public getActiveSessionIds(): string[] {\n return Array.from(this.sessions.keys());\n }\n\n /**\n * Check if a session exists\n */\n public hasSession(sessionId: string): boolean {\n return this.sessions.has(sessionId);\n }\n\n /**\n * Register process exit handlers to cleanup sessions on exit\n */\n private registerExitHandlers(): void {\n if (this.exitHandlerRegistered) {\n return;\n }\n\n const cleanupAndExit = (signal: string) => {\n if (this.sessions.size > 0) {\n console.error(`\\n🧹 [${signal}] Cleaning up ${this.sessions.size} active AI sessions...`);\n this.clearAllSessions();\n }\n };\n\n // Handle normal process exit\n process.on('exit', () => {\n if (this.sessions.size > 0) {\n console.error(`🧹 [exit] Cleaning up ${this.sessions.size} active AI sessions...`);\n // Note: async operations won't complete here, but sync cleanup methods will\n for (const [, agent] of this.sessions.entries()) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n if (agent && typeof (agent as any).cleanup === 'function') {\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (agent as any).cleanup();\n } catch {\n // Silent fail on exit\n }\n }\n }\n this.sessions.clear();\n }\n });\n\n // Handle SIGINT (Ctrl+C)\n process.on('SIGINT', () => {\n cleanupAndExit('SIGINT');\n process.exit(0);\n });\n\n // Handle SIGTERM\n process.on('SIGTERM', () => {\n cleanupAndExit('SIGTERM');\n process.exit(0);\n });\n\n this.exitHandlerRegistered = true;\n }\n}\n","import { Octokit } from '@octokit/rest';\nimport { v4 as uuidv4 } from 'uuid';\n\nexport interface Comment {\n id: number;\n body: string;\n user: {\n login: string;\n };\n created_at: string;\n updated_at: string;\n}\n\nexport interface RetryConfig {\n maxRetries: number;\n baseDelay: number;\n maxDelay: number;\n backoffFactor: number;\n}\n\nexport interface CommentMetadata {\n commentId: string;\n lastUpdated: string;\n triggeredBy: string;\n commitSha?: string;\n}\n\ninterface GitHubApiError {\n status?: number;\n response?: {\n status?: number;\n data?: {\n message?: string;\n };\n };\n}\n\n/**\n * Manages GitHub PR comments with dynamic updating capabilities\n */\nexport class CommentManager {\n private octokit: Octokit;\n private retryConfig: RetryConfig;\n\n constructor(octokit: Octokit, retryConfig?: Partial<RetryConfig>) {\n this.octokit = octokit;\n this.retryConfig = {\n maxRetries: 3,\n baseDelay: 1000,\n maxDelay: 10000,\n backoffFactor: 2,\n ...retryConfig,\n };\n }\n\n /**\n * Find existing Visor comment by comment ID marker\n */\n public async findVisorComment(\n owner: string,\n repo: string,\n prNumber: number,\n commentId?: string\n ): Promise<Comment | null> {\n try {\n const comments = await this.octokit.rest.issues.listComments({\n owner,\n repo,\n issue_number: prNumber,\n per_page: 100, // GitHub default max\n });\n\n for (const comment of comments.data) {\n if (comment.body && this.isVisorComment(comment.body, commentId)) {\n return comment as Comment;\n }\n }\n\n return null;\n } catch (error) {\n if (\n this.isRateLimitError(\n error as { status?: number; response?: { data?: { message?: string } } }\n )\n ) {\n await this.handleRateLimit(error as { response?: { headers?: Record<string, string> } });\n return this.findVisorComment(owner, repo, prNumber, commentId);\n }\n throw error;\n }\n }\n\n /**\n * Update existing comment or create new one with collision detection\n */\n public async updateOrCreateComment(\n owner: string,\n repo: string,\n prNumber: number,\n content: string,\n options: {\n commentId?: string;\n triggeredBy?: string;\n allowConcurrentUpdates?: boolean;\n commitSha?: string;\n } = {}\n ): Promise<Comment> {\n const {\n commentId = this.generateCommentId(),\n triggeredBy = 'unknown',\n allowConcurrentUpdates = false,\n commitSha,\n } = options;\n\n return this.withRetry(async () => {\n const existingComment = await this.findVisorComment(owner, repo, prNumber, commentId);\n\n const formattedContent = this.formatCommentWithMetadata(content, {\n commentId,\n lastUpdated: new Date().toISOString(),\n triggeredBy,\n commitSha,\n });\n\n if (existingComment) {\n // Check for collision if not allowing concurrent updates\n if (!allowConcurrentUpdates) {\n const currentComment = await this.octokit.rest.issues.getComment({\n owner,\n repo,\n comment_id: existingComment.id,\n });\n\n if (currentComment.data.updated_at !== existingComment.updated_at) {\n throw new Error(\n `Comment collision detected for comment ${commentId}. Another process may have updated it.`\n );\n }\n }\n\n const updatedComment = await this.octokit.rest.issues.updateComment({\n owner,\n repo,\n comment_id: existingComment.id,\n body: formattedContent,\n });\n\n return updatedComment.data as Comment;\n } else {\n const newComment = await this.octokit.rest.issues.createComment({\n owner,\n repo,\n issue_number: prNumber,\n body: formattedContent,\n });\n\n return newComment.data as Comment;\n }\n });\n }\n\n /**\n * Format comment content with metadata markers\n */\n public formatCommentWithMetadata(content: string, metadata: CommentMetadata): string {\n const { commentId, lastUpdated, triggeredBy, commitSha } = metadata;\n\n const commitInfo = commitSha ? ` | Commit: ${commitSha.substring(0, 7)}` : '';\n\n return `<!-- visor-comment-id:${commentId} -->\n${content}\n\n*Last updated: ${lastUpdated} | Triggered by: ${triggeredBy}${commitInfo}*\n<!-- /visor-comment-id:${commentId} -->`;\n }\n\n /**\n * Create collapsible sections for comment content\n */\n public createCollapsibleSection(\n title: string,\n content: string,\n isExpanded: boolean = false\n ): string {\n const openAttribute = isExpanded ? ' open' : '';\n return `<details${openAttribute}>\n<summary>${title}</summary>\n\n${content}\n\n</details>`;\n }\n\n /**\n * Group review results by check type with collapsible sections\n */\n public formatGroupedResults(\n results: Array<{ checkType: string; content: string; score?: number; issuesFound?: number }>,\n groupBy: 'check' | 'severity' = 'check'\n ): string {\n const grouped = this.groupResults(results, groupBy);\n const sections: string[] = [];\n\n for (const [groupKey, items] of Object.entries(grouped)) {\n const totalScore = items.reduce((sum, item) => sum + (item.score || 0), 0) / items.length;\n const totalIssues = items.reduce((sum, item) => sum + (item.issuesFound || 0), 0);\n\n const emoji = this.getCheckTypeEmoji(groupKey);\n const title = `${emoji} ${this.formatGroupTitle(groupKey, totalScore, totalIssues)}`;\n\n const sectionContent = items.map(item => item.content).join('\\n\\n');\n sections.push(this.createCollapsibleSection(title, sectionContent, totalIssues > 0));\n }\n\n return sections.join('\\n\\n');\n }\n\n /**\n * Generate unique comment ID\n */\n private generateCommentId(): string {\n return uuidv4().substring(0, 8);\n }\n\n /**\n * Check if comment is a Visor comment\n */\n private isVisorComment(body: string, commentId?: string): boolean {\n if (commentId) {\n // Check for the new format with exact matching - look for the exact ID followed by space or \" -->\"\n if (\n body.includes(`visor-comment-id:${commentId} `) ||\n body.includes(`visor-comment-id:${commentId} -->`)\n ) {\n return true;\n }\n // Check for legacy format (visor-review-* pattern) for backwards compatibility\n if (commentId.startsWith('pr-review-') && body.includes('visor-review-')) {\n return true;\n }\n // If we have a specific commentId but no exact match, return false\n return false;\n }\n // General Visor comment detection (only when no specific commentId provided)\n return (\n (body.includes('visor-comment-id:') && body.includes('<!-- /visor-comment-id:')) ||\n body.includes('visor-review-')\n );\n }\n\n /**\n * Extract comment ID from comment body\n */\n public extractCommentId(body: string): string | null {\n const match = body.match(/visor-comment-id:([a-f0-9-]+)/);\n return match ? match[1] : null;\n }\n\n /**\n * Handle rate limiting with exponential backoff\n */\n private async handleRateLimit(error: {\n response?: { headers?: Record<string, string> };\n }): Promise<void> {\n const resetTime = error.response?.headers?.['x-ratelimit-reset'];\n if (resetTime) {\n const resetDate = new Date(parseInt(resetTime) * 1000);\n const waitTime = Math.max(resetDate.getTime() - Date.now(), this.retryConfig.baseDelay);\n console.log(`Rate limit exceeded. Waiting ${Math.round(waitTime / 1000)}s until reset...`);\n await this.sleep(Math.min(waitTime, this.retryConfig.maxDelay));\n } else {\n await this.sleep(this.retryConfig.baseDelay);\n }\n }\n\n /**\n * Check if error is a rate limit error\n */\n private isRateLimitError(error: GitHubApiError): boolean {\n return error.status === 403 && (error.response?.data?.message?.includes('rate limit') ?? false);\n }\n\n /**\n * Check if error should not be retried (auth errors, not found, etc.)\n */\n private isNonRetryableError(error: GitHubApiError): boolean {\n // Don't retry auth errors, not found, etc., but allow rate limit errors to be handled separately\n const nonRetryableStatuses = [401, 404, 422]; // Unauthorized, Not Found, Unprocessable Entity\n const status = error.status || error.response?.status;\n\n // 403 is non-retryable unless it's a rate limit error\n if (status === 403) {\n return !this.isRateLimitError(error);\n }\n\n return status !== undefined && nonRetryableStatuses.includes(status);\n }\n\n /**\n * Retry wrapper with exponential backoff\n */\n private async withRetry<T>(operation: () => Promise<T>): Promise<T> {\n let lastError: Error = new Error('Unknown error');\n\n for (let attempt = 0; attempt <= this.retryConfig.maxRetries; attempt++) {\n try {\n return await operation();\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n\n if (attempt === this.retryConfig.maxRetries) {\n break;\n }\n\n if (\n this.isRateLimitError(\n error as { status?: number; response?: { data?: { message?: string } } }\n )\n ) {\n await this.handleRateLimit(error as { response?: { headers?: Record<string, string> } });\n } else if (this.isNonRetryableError(error as GitHubApiError)) {\n // Don't retry auth errors, not found errors, etc.\n throw error;\n } else {\n const delay = Math.min(\n this.retryConfig.baseDelay * Math.pow(this.retryConfig.backoffFactor, attempt),\n this.retryConfig.maxDelay\n );\n await this.sleep(delay);\n }\n }\n }\n\n throw lastError;\n }\n\n /**\n * Sleep utility\n */\n private sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n }\n\n /**\n * Group results by specified criteria\n */\n private groupResults(\n results: Array<{ checkType: string; content: string; score?: number; issuesFound?: number }>,\n groupBy: 'check' | 'severity'\n ): Record<\n string,\n Array<{ checkType: string; content: string; score?: number; issuesFound?: number }>\n > {\n const grouped: Record<\n string,\n Array<{ checkType: string; content: string; score?: number; issuesFound?: number }>\n > = {};\n\n for (const result of results) {\n const key = groupBy === 'check' ? result.checkType : this.getSeverityGroup(result.score);\n if (!grouped[key]) {\n grouped[key] = [];\n }\n grouped[key].push(result);\n }\n\n return grouped;\n }\n\n /**\n * Get severity group based on score\n */\n private getSeverityGroup(score?: number): string {\n if (!score) return 'Unknown';\n if (score >= 90) return 'Excellent';\n if (score >= 75) return 'Good';\n if (score >= 50) return 'Needs Improvement';\n return 'Critical Issues';\n }\n\n /**\n * Get emoji for check type\n */\n private getCheckTypeEmoji(checkType: string): string {\n const emojiMap: Record<string, string> = {\n performance: '📈',\n security: '🔒',\n architecture: '🏗️',\n style: '🎨',\n all: '🔍',\n Excellent: '✅',\n Good: '👍',\n 'Needs Improvement': '⚠️',\n 'Critical Issues': '🚨',\n Unknown: '❓',\n };\n return emojiMap[checkType] || '📝';\n }\n\n /**\n * Format group title with score and issue count\n */\n private formatGroupTitle(groupKey: string, score: number, issuesFound: number): string {\n const formattedScore = Math.round(score);\n return `${groupKey} Review (Score: ${formattedScore}/100)${issuesFound > 0 ? ` - ${issuesFound} issues found` : ''}`;\n }\n}\n","import { ProbeAgent } from '@probelabs/probe';\nimport type { ProbeAgentOptions } from '@probelabs/probe';\nimport { PRInfo } from './pr-analyzer';\nimport { ReviewSummary, ReviewIssue } from './reviewer';\nimport { SessionRegistry } from './session-registry';\nimport { logger } from './logger';\n\n/**\n * Helper function to log debug messages using the centralized logger\n */\nfunction log(...args: unknown[]): void {\n logger.debug(args.join(' '));\n}\n\nexport interface AIReviewConfig {\n apiKey?: string; // From env: GOOGLE_API_KEY, ANTHROPIC_API_KEY, OPENAI_API_KEY, CLAUDE_CODE_API_KEY, or AWS credentials\n model?: string; // From env: MODEL_NAME (e.g., gemini-2.5-pro-preview-06-05)\n timeout?: number; // Default: 600000ms (10 minutes)\n provider?: 'google' | 'anthropic' | 'openai' | 'bedrock' | 'mock' | 'claude-code';\n debug?: boolean; // Enable debug mode\n tools?: Array<{ name: string; [key: string]: unknown }>; // (unused) Legacy tool listing\n // Pass-through MCP server configuration for ProbeAgent\n mcpServers?: Record<string, import('./types/config').McpServerConfig>;\n}\n\nexport interface AIDebugInfo {\n /** The prompt sent to the AI */\n prompt: string;\n /** Raw response from the AI service */\n rawResponse: string;\n /** Provider used (google, anthropic, openai) */\n provider: string;\n /** Model used */\n model: string;\n /** API key source (for privacy, just show which env var) */\n apiKeySource: string;\n /** Processing time in milliseconds */\n processingTime: number;\n /** Prompt length in characters */\n promptLength: number;\n /** Response length in characters */\n responseLength: number;\n /** Any errors encountered */\n errors?: string[];\n /** Whether JSON parsing succeeded */\n jsonParseSuccess: boolean;\n /** Schema used for response validation */\n schema?: string;\n /** Schema name/type requested */\n schemaName?: string;\n /** Checks executed during this review */\n checksExecuted?: string[];\n /** Whether parallel execution was used */\n parallelExecution?: boolean;\n /** Timestamp when request was made */\n timestamp: string;\n /** Total API calls made */\n totalApiCalls?: number;\n /** Details about API calls made */\n apiCallDetails?: Array<{\n checkName: string;\n provider: string;\n model: string;\n processingTime: number;\n success: boolean;\n }>;\n}\n\n// REMOVED: ReviewFocus type - only use custom prompts from .visor.yaml\n\ninterface AIResponseFormat {\n // Array of issues for code review\n issues?: Array<{\n file: string;\n line: number;\n endLine?: number;\n ruleId: string;\n message: string;\n severity: 'info' | 'warning' | 'error' | 'critical';\n category: 'security' | 'performance' | 'style' | 'logic' | 'documentation';\n suggestion?: string;\n replacement?: string;\n }>;\n}\n\nexport class AIReviewService {\n private config: AIReviewConfig;\n private sessionRegistry: SessionRegistry;\n\n constructor(config: AIReviewConfig = {}) {\n this.config = {\n timeout: 600000, // Increased timeout to 10 minutes for AI responses\n ...config,\n };\n\n this.sessionRegistry = SessionRegistry.getInstance();\n\n // Auto-detect provider and API key from environment\n if (!this.config.apiKey) {\n if (process.env.CLAUDE_CODE_API_KEY) {\n this.config.apiKey = process.env.CLAUDE_CODE_API_KEY;\n this.config.provider = 'claude-code';\n } else if (process.env.GOOGLE_API_KEY) {\n this.config.apiKey = process.env.GOOGLE_API_KEY;\n this.config.provider = 'google';\n } else if (process.env.ANTHROPIC_API_KEY) {\n this.config.apiKey = process.env.ANTHROPIC_API_KEY;\n this.config.provider = 'anthropic';\n } else if (process.env.OPENAI_API_KEY) {\n this.config.apiKey = process.env.OPENAI_API_KEY;\n this.config.provider = 'openai';\n } else if (\n // Check for AWS Bedrock credentials\n (process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY) ||\n process.env.AWS_BEDROCK_API_KEY\n ) {\n // For Bedrock, we don't set apiKey as it uses AWS credentials\n // ProbeAgent will handle the authentication internally\n this.config.provider = 'bedrock';\n // Set a placeholder to pass validation\n this.config.apiKey = 'AWS_CREDENTIALS';\n }\n }\n\n // Auto-detect model from environment\n if (!this.config.model && process.env.MODEL_NAME) {\n this.config.model = process.env.MODEL_NAME;\n }\n }\n\n /**\n * Execute AI review using probe agent\n */\n async executeReview(\n prInfo: PRInfo,\n customPrompt: string,\n schema?: string | Record<string, unknown>,\n _checkName?: string,\n sessionId?: string\n ): Promise<ReviewSummary> {\n const startTime = Date.now();\n const timestamp = new Date().toISOString();\n\n // Build prompt from custom instructions\n const prompt = await this.buildCustomPrompt(prInfo, customPrompt, schema);\n\n log(`Executing AI review with ${this.config.provider} provider...`);\n log(`🔧 Debug: Raw schema parameter: ${JSON.stringify(schema)} (type: ${typeof schema})`);\n log(`Schema type: ${schema || 'none (no schema)'}`);\n\n let debugInfo: AIDebugInfo | undefined;\n if (this.config.debug) {\n debugInfo = {\n prompt,\n rawResponse: '',\n provider: this.config.provider || 'unknown',\n model: this.config.model || 'default',\n apiKeySource: this.getApiKeySource(),\n processingTime: 0,\n promptLength: prompt.length,\n responseLength: 0,\n errors: [],\n jsonParseSuccess: false,\n timestamp,\n schemaName: typeof schema === 'object' ? 'custom' : schema,\n schema: undefined, // Will be populated when schema is loaded\n };\n }\n\n // Handle mock model/provider first (no API key needed)\n if (this.config.model === 'mock' || this.config.provider === 'mock') {\n log('🎭 Using mock AI model/provider for testing - skipping API key validation');\n } else {\n // Check if API key is available for real AI models\n if (!this.config.apiKey) {\n const errorMessage =\n 'No API key configured. Please set GOOGLE_API_KEY, ANTHROPIC_API_KEY, OPENAI_API_KEY environment variable, or configure AWS credentials for Bedrock (AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY).';\n\n // In debug mode, return a review with the error captured\n if (debugInfo) {\n debugInfo.errors = [errorMessage];\n debugInfo.processingTime = Date.now() - startTime;\n debugInfo.rawResponse = 'API call not attempted - no API key configured';\n\n return {\n issues: [\n {\n file: 'system',\n line: 0,\n ruleId: 'system/api-key-missing',\n message: errorMessage,\n severity: 'error',\n category: 'logic',\n },\n ],\n debug: debugInfo,\n };\n }\n\n throw new Error(errorMessage);\n }\n }\n\n try {\n const { response, effectiveSchema } = await this.callProbeAgent(\n prompt,\n schema,\n debugInfo,\n _checkName,\n sessionId\n );\n const processingTime = Date.now() - startTime;\n\n if (debugInfo) {\n debugInfo.rawResponse = response;\n debugInfo.responseLength = response.length;\n debugInfo.processingTime = processingTime;\n }\n\n const result = this.parseAIResponse(response, debugInfo, effectiveSchema);\n\n if (debugInfo) {\n result.debug = debugInfo;\n }\n\n return result;\n } catch (error) {\n if (debugInfo) {\n debugInfo.errors = [error instanceof Error ? error.message : String(error)];\n debugInfo.processingTime = Date.now() - startTime;\n\n // In debug mode, return a review with the error captured\n return {\n issues: [\n {\n file: 'system',\n line: 0,\n ruleId: 'system/ai-execution-error',\n message: error instanceof Error ? error.message : String(error),\n severity: 'error',\n category: 'logic',\n },\n ],\n debug: debugInfo,\n };\n }\n throw error;\n }\n }\n\n /**\n * Execute AI review using session reuse - reuses an existing ProbeAgent session\n */\n async executeReviewWithSessionReuse(\n prInfo: PRInfo,\n customPrompt: string,\n parentSessionId: string,\n schema?: string | Record<string, unknown>,\n checkName?: string\n ): Promise<ReviewSummary> {\n const startTime = Date.now();\n const timestamp = new Date().toISOString();\n\n // Get the existing session\n const existingAgent = this.sessionRegistry.getSession(parentSessionId);\n if (!existingAgent) {\n throw new Error(\n `Session not found for reuse: ${parentSessionId}. Ensure the parent check completed successfully.`\n );\n }\n\n // Build prompt from custom instructions\n const prompt = await this.buildCustomPrompt(prInfo, customPrompt, schema);\n\n log(`🔄 Reusing AI session ${parentSessionId} for review...`);\n log(`🔧 Debug: Raw schema parameter: ${JSON.stringify(schema)} (type: ${typeof schema})`);\n log(`Schema type: ${schema || 'none (no schema)'}`);\n\n let debugInfo: AIDebugInfo | undefined;\n if (this.config.debug) {\n debugInfo = {\n prompt,\n rawResponse: '',\n provider: this.config.provider || 'unknown',\n model: this.config.model || 'default',\n apiKeySource: this.getApiKeySource(),\n processingTime: 0,\n promptLength: prompt.length,\n responseLength: 0,\n errors: [],\n jsonParseSuccess: false,\n timestamp,\n schemaName: typeof schema === 'object' ? 'custom' : schema,\n schema: undefined, // Will be populated when schema is loaded\n };\n }\n\n try {\n // Use existing agent's answer method instead of creating new agent\n const { response, effectiveSchema } = await this.callProbeAgentWithExistingSession(\n existingAgent,\n prompt,\n schema,\n debugInfo,\n checkName\n );\n const processingTime = Date.now() - startTime;\n\n if (debugInfo) {\n debugInfo.rawResponse = response;\n debugInfo.responseLength = response.length;\n debugInfo.processingTime = processingTime;\n }\n\n const result = this.parseAIResponse(response, debugInfo, effectiveSchema);\n\n if (debugInfo) {\n result.debug = debugInfo;\n }\n\n return result;\n } catch (error) {\n if (debugInfo) {\n debugInfo.errors = [error instanceof Error ? error.message : String(error)];\n debugInfo.processingTime = Date.now() - startTime;\n\n // In debug mode, return a review with the error captured\n return {\n issues: [\n {\n file: 'system',\n line: 0,\n ruleId: 'system/ai-session-reuse-error',\n message: error instanceof Error ? error.message : String(error),\n severity: 'error',\n category: 'logic',\n },\n ],\n debug: debugInfo,\n };\n }\n throw error;\n }\n }\n\n /**\n * Register a new AI session in the session registry\n */\n registerSession(sessionId: string, agent: ProbeAgent): void {\n this.sessionRegistry.registerSession(sessionId, agent);\n }\n\n /**\n * Cleanup a session from the registry\n */\n cleanupSession(sessionId: string): void {\n this.sessionRegistry.unregisterSession(sessionId);\n }\n\n /**\n * Build a custom prompt for AI review with XML-formatted data\n */\n private async buildCustomPrompt(\n prInfo: PRInfo,\n customInstructions: string,\n schema?: string | Record<string, unknown>\n ): Promise<string> {\n const prContext = this.formatPRContext(prInfo);\n const isIssue = (prInfo as PRInfo & { isIssue?: boolean }).isIssue === true;\n\n // Check if we're using the code-review schema\n const isCodeReviewSchema = schema === 'code-review';\n\n if (isIssue) {\n // Issue context - no code analysis needed\n return `<review_request>\n <instructions>\n${customInstructions}\n </instructions>\n\n <context>\n${prContext}\n </context>\n\n <rules>\n <rule>Understand the issue context and requirements from the XML data structure</rule>\n <rule>Provide helpful, actionable guidance based on the issue details</rule>\n <rule>Be constructive and supportive in your analysis</rule>\n <rule>Consider project conventions and patterns when making recommendations</rule>\n <rule>Suggest practical solutions or next steps that address the specific concern</rule>\n <rule>Focus on addressing the specific concern raised in the issue</rule>\n <rule>Reference relevant XML elements like metadata, description, labels, assignees when providing context</rule>\n </rules>\n</review_request>`;\n }\n\n // Only add review_request wrapper and PR-specific rules for code-review schema\n if (isCodeReviewSchema) {\n // PR context with code-review schema - structured XML format\n const analysisType = prInfo.isIncremental ? 'INCREMENTAL' : 'FULL';\n\n return `<review_request>\n <analysis_type>${analysisType}</analysis_type>\n\n <analysis_focus>\n ${\n analysisType === 'INCREMENTAL'\n ? 'You are analyzing a NEW COMMIT added to an existing PR. Focus on the changes in the commit_diff section for this specific commit.'\n : 'You are analyzing the COMPLETE PR. Review all changes in the full_diff section.'\n }\n </analysis_focus>\n\n <instructions>\n${customInstructions}\n </instructions>\n\n <context>\n${prContext}\n </context>\n\n <rules>\n <rule>Only analyze code that appears with + (additions) or - (deletions) in the diff sections</rule>\n <rule>Ignore unchanged code unless directly relevant to understanding a change</rule>\n <rule>Line numbers in your response should match actual file line numbers from the diff</rule>\n <rule>Focus on real issues, not nitpicks or cosmetic concerns</rule>\n <rule>Provide actionable, specific feedback with clear remediation steps</rule>\n <rule>For INCREMENTAL analysis, ONLY review changes in commit_diff section</rule>\n <rule>For FULL analysis, review all changes in full_diff section</rule>\n <rule>Reference specific XML elements like files_summary, metadata when providing context</rule>\n <rule>STRICT OUTPUT POLICY: Report only actual problems, risks, or deficiencies. Do not write praise, congratulations, or celebratory text. Do not create issues that merely restate improvements or say \"no action needed\".</rule>\n <rule>SEVERITY ASSIGNMENT: Assign severity ONLY to problems introduced or left unresolved by this change (critical/error/warning/info as appropriate). Do NOT create issue entries solely to acknowledge improvements; if no problems exist, return zero issues.</rule>\n </rules>\n</review_request>`;\n }\n\n // For non-code-review schemas, just provide instructions and context without review-specific wrapper\n return `<instructions>\n${customInstructions}\n</instructions>\n\n<context>\n${prContext}\n</context>`;\n }\n\n // REMOVED: Built-in prompts - only use custom prompts from .visor.yaml\n\n // REMOVED: getFocusInstructions - only use custom prompts from .visor.yaml\n\n /**\n * Format PR or Issue context for the AI using XML structure\n */\n private formatPRContext(prInfo: PRInfo): string {\n // Check if this is an issue (not a PR)\n const prContextInfo = prInfo as PRInfo & {\n isPRContext?: boolean;\n includeCodeContext?: boolean;\n };\n const isIssue = prContextInfo.isIssue === true;\n\n // Check if we should include code context (diffs)\n const isPRContext = prContextInfo.isPRContext === true;\n // In PR context, always include diffs. Otherwise check the flag.\n const includeCodeContext = isPRContext || prContextInfo.includeCodeContext !== false;\n\n // Log the decision for transparency\n const log = this.config.debug ? console.error : () => {};\n if (isPRContext) {\n log('🔍 Including full code diffs in AI context (PR mode)');\n } else if (!includeCodeContext) {\n log('📊 Including only file summary in AI context (no diffs)');\n } else {\n log('🔍 Including code diffs in AI context');\n }\n\n if (isIssue) {\n // Format as issue context\n let context = `<issue>\n <!-- Core issue metadata including identification, status, and timeline information -->\n <metadata>\n <number>${prInfo.number}</number>\n <title>${this.escapeXml(prInfo.title)}</title>\n <author>${prInfo.author}</author>\n <state>${(prInfo as PRInfo & { eventContext?: { issue?: { state?: string; created_at?: string; updated_at?: string; comments?: number } } }).eventContext?.issue?.state || 'open'}</state>\n <created_at>${(prInfo as PRInfo & { eventContext?: { issue?: { state?: string; created_at?: string; updated_at?: string; comments?: number } } }).eventContext?.issue?.created_at || ''}</created_at>\n <updated_at>${(prInfo as PRInfo & { eventContext?: { issue?: { state?: string; updated_at?: string; comments?: number } } }).eventContext?.issue?.updated_at || ''}</updated_at>\n <comments_count>${(prInfo as PRInfo & { eventContext?: { issue?: { comments?: number } } }).eventContext?.issue?.comments || 0}</comments_count>\n </metadata>`;\n\n // Add issue body/description if available\n if (prInfo.body) {\n context += `\n <!-- Full issue description and body text provided by the issue author -->\n <description>\n${this.escapeXml(prInfo.body)}\n </description>`;\n }\n\n // Add labels if available\n const eventContext = prInfo as PRInfo & {\n eventContext?: { issue?: { labels?: Array<{ name?: string } | string> } };\n };\n const labels = eventContext.eventContext?.issue?.labels;\n if (labels && labels.length > 0) {\n context += `\n <!-- Applied labels for issue categorization and organization -->\n <labels>`;\n labels.forEach((label: { name?: string } | string) => {\n const labelName = typeof label === 'string' ? label : label.name || 'unknown';\n context += `\n <label>${this.escapeXml(labelName)}</label>`;\n });\n context += `\n </labels>`;\n }\n\n // Add assignees if available\n const assignees = (\n prInfo as PRInfo & {\n eventContext?: { issue?: { assignees?: Array<{ login?: string } | string> } };\n }\n ).eventContext?.issue?.assignees;\n if (assignees && assignees.length > 0) {\n context += `\n <!-- Users assigned to work on this issue -->\n <assignees>`;\n assignees.forEach((assignee: { login?: string } | string) => {\n const assigneeName =\n typeof assignee === 'string' ? assignee : assignee.login || 'unknown';\n context += `\n <assignee>${this.escapeXml(assigneeName)}</assignee>`;\n });\n context += `\n </assignees>`;\n }\n\n // Add milestone if available\n const milestone = (\n prInfo as PRInfo & {\n eventContext?: {\n issue?: { milestone?: { title?: string; state?: string; due_on?: string } };\n };\n }\n ).eventContext?.issue?.milestone;\n if (milestone) {\n context += `\n <!-- Associated project milestone information -->\n <milestone>\n <title>${this.escapeXml(milestone.title || '')}</title>\n <state>${milestone.state || 'open'}</state>\n <due_on>${milestone.due_on || ''}</due_on>\n </milestone>`;\n }\n\n // Add current/triggering comment if this is a comment event\n const triggeringComment = (\n prInfo as PRInfo & {\n eventContext?: {\n comment?: {\n user?: { login?: string };\n created_at?: string;\n body?: string;\n id?: number;\n };\n };\n }\n ).eventContext?.comment;\n if (triggeringComment) {\n context += `\n <!-- The comment that triggered this analysis -->\n <triggering_comment>\n <author>${this.escapeXml(triggeringComment.user?.login || 'unknown')}</author>\n <created_at>${triggeringComment.created_at || ''}</created_at>\n <body>${this.escapeXml(triggeringComment.body || '')}</body>\n </triggering_comment>`;\n }\n\n // Add comment history (excluding the current comment if it exists)\n const issueComments = (\n prInfo as PRInfo & {\n comments?: Array<{ id?: number; author?: string; body?: string; createdAt?: string }>;\n }\n ).comments;\n if (issueComments && issueComments.length > 0) {\n // Filter out the triggering comment from history if present\n const historicalComments = triggeringComment\n ? issueComments.filter(c => c.id !== triggeringComment.id)\n : issueComments;\n\n if (historicalComments.length > 0) {\n context += `\n <!-- Previous comments in chronological order (excluding triggering comment) -->\n <comment_history>`;\n historicalComments.forEach(comment => {\n context += `\n <comment>\n <author>${this.escapeXml(comment.author || 'unknown')}</author>\n <created_at>${comment.createdAt || ''}</created_at>\n <body>${this.escapeXml(comment.body || '')}</body>\n </comment>`;\n });\n context += `\n </comment_history>`;\n }\n }\n\n // Close the issue tag\n context += `\n</issue>`;\n\n return context;\n }\n\n // Original PR context formatting\n let context = `<pull_request>\n <!-- Core pull request metadata including identification, branches, and change statistics -->\n <metadata>\n <number>${prInfo.number}</number>\n <title>${this.escapeXml(prInfo.title)}</title>\n <author>${prInfo.author}</author>\n <base_branch>${prInfo.base}</base_branch>\n <target_branch>${prInfo.head}</target_branch>\n <total_additions>${prInfo.totalAdditions}</total_additions>\n <total_deletions>${prInfo.totalDeletions}</total_deletions>\n <files_changed_count>${prInfo.files.length}</files_changed_count>\n </metadata>`;\n\n // Add PR description if available\n if (prInfo.body) {\n context += `\n <!-- Full pull request description provided by the author -->\n <description>\n${this.escapeXml(prInfo.body)}\n </description>`;\n }\n\n // Add diffs only if includeCodeContext is true (or in PR mode)\n if (includeCodeContext) {\n // Add full diff if available (for complete PR review)\n if (prInfo.fullDiff) {\n context += `\n <!-- Complete unified diff showing all changes in the pull request -->\n <full_diff>\n${this.escapeXml(prInfo.fullDiff)}\n </full_diff>`;\n }\n\n // Add incremental commit diff if available (for new commit analysis)\n if (prInfo.isIncremental) {\n if (prInfo.commitDiff && prInfo.commitDiff.length > 0) {\n context += `\n <!-- Diff of only the latest commit for incremental analysis -->\n <commit_diff>\n${this.escapeXml(prInfo.commitDiff)}\n </commit_diff>`;\n } else {\n context += `\n <!-- Commit diff could not be retrieved - falling back to full diff analysis -->\n <commit_diff>\n${prInfo.fullDiff ? this.escapeXml(prInfo.fullDiff) : ''}\n </commit_diff>`;\n }\n }\n } else {\n // When not including diffs, add a note about it\n context += `\n <!-- Code diffs excluded to reduce token usage (no code-review schema detected or disabled by flag) -->`;\n }\n\n // Add file summary for context\n if (prInfo.files.length > 0) {\n context += `\n <!-- Summary of all files changed with statistics -->\n <files_summary>`;\n prInfo.files.forEach(file => {\n context += `\n <file>\n <filename>${this.escapeXml(file.filename)}</filename>\n <status>${file.status}</status>\n <additions>${file.additions}</additions>\n <deletions>${file.deletions}</deletions>\n </file>`;\n });\n context += `\n </files_summary>`;\n }\n\n // Add current/triggering comment if this is a comment event\n const triggeringComment = (\n prInfo as PRInfo & {\n eventContext?: {\n comment?: { user?: { login?: string }; created_at?: string; body?: string; id?: number };\n };\n }\n ).eventContext?.comment;\n if (triggeringComment) {\n context += `\n <!-- The comment that triggered this analysis -->\n <triggering_comment>\n <author>${this.escapeXml(triggeringComment.user?.login || 'unknown')}</author>\n <created_at>${triggeringComment.created_at || ''}</created_at>\n <body>${this.escapeXml(triggeringComment.body || '')}</body>\n </triggering_comment>`;\n }\n\n // Add comment history (excluding the current comment if it exists)\n const prComments = (\n prInfo as PRInfo & {\n comments?: Array<{ id?: number; author?: string; body?: string; createdAt?: string }>;\n }\n ).comments;\n if (prComments && prComments.length > 0) {\n // Filter out the triggering comment from history if present\n const historicalComments = triggeringComment\n ? prComments.filter(c => c.id !== triggeringComment.id)\n : prComments;\n\n if (historicalComments.length > 0) {\n context += `\n <!-- Previous PR comments in chronological order (excluding triggering comment) -->\n <comment_history>`;\n historicalComments.forEach(comment => {\n context += `\n <comment>\n <author>${this.escapeXml(comment.author || 'unknown')}</author>\n <created_at>${comment.createdAt || ''}</created_at>\n <body>${this.escapeXml(comment.body || '')}</body>\n </comment>`;\n });\n context += `\n </comment_history>`;\n }\n }\n\n context += `\n</pull_request>`;\n\n return context;\n }\n\n /**\n * No longer escaping XML - returning text as-is\n */\n private escapeXml(text: string): string {\n return text;\n }\n\n /**\n * Call ProbeAgent with an existing session\n */\n private async callProbeAgentWithExistingSession(\n agent: ProbeAgent,\n prompt: string,\n schema?: string | Record<string, unknown>,\n debugInfo?: AIDebugInfo,\n _checkName?: string\n ): Promise<{ response: string; effectiveSchema?: string }> {\n // Handle mock model/provider for testing\n if (this.config.model === 'mock' || this.config.provider === 'mock') {\n log('🎭 Using mock AI model/provider for testing (session reuse)');\n const response = await this.generateMockResponse(prompt);\n return { response, effectiveSchema: typeof schema === 'object' ? 'custom' : schema };\n }\n\n log('🔄 Reusing existing ProbeAgent session for AI review...');\n log(`📝 Prompt length: ${prompt.length} characters`);\n log(`⚙️ Model: ${this.config.model || 'default'}, Provider: ${this.config.provider || 'auto'}`);\n\n try {\n log('🚀 Calling existing ProbeAgent with answer()...');\n\n // Load and pass the actual schema content if provided (skip for plain schema)\n let schemaString: string | undefined = undefined;\n let effectiveSchema: string | undefined = typeof schema === 'object' ? 'custom' : schema;\n\n if (schema && schema !== 'plain') {\n try {\n schemaString = await this.loadSchemaContent(schema);\n log(`📋 Loaded schema content for: ${schema}`);\n log(`📄 Raw schema JSON:\\n${schemaString}`);\n } catch (error) {\n log(`⚠️ Failed to load schema ${schema}, proceeding without schema:`, error);\n schemaString = undefined;\n effectiveSchema = undefined; // Schema loading failed, treat as no schema\n if (debugInfo && debugInfo.errors) {\n debugInfo.errors.push(`Failed to load schema: ${error}`);\n }\n }\n } else if (schema === 'plain') {\n log(`📋 Using plain schema - no JSON validation will be applied`);\n }\n\n // Pass schema in options object with 'schema' property\n const schemaOptions = schemaString ? { schema: schemaString } : undefined;\n\n // Store the exact schema options being passed to ProbeAgent in debug info\n if (debugInfo && schemaOptions) {\n debugInfo.schema = JSON.stringify(schemaOptions, null, 2);\n }\n\n // Log the schema options being passed to ProbeAgent\n if (schemaOptions) {\n log(`🎯 Schema options passed to ProbeAgent.answer() (session reuse):`);\n log(JSON.stringify(schemaOptions, null, 2));\n }\n\n // Use existing agent's answer method - this reuses the conversation context\n const response = await agent.answer(prompt, undefined, schemaOptions);\n\n log('✅ ProbeAgent session reuse completed successfully');\n log(`📤 Response length: ${response.length} characters`);\n\n return { response, effectiveSchema };\n } catch (error) {\n console.error('❌ ProbeAgent session reuse failed:', error);\n throw new Error(\n `ProbeAgent session reuse failed: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n }\n }\n\n /**\n * Call ProbeAgent SDK with built-in schema validation\n */\n private async callProbeAgent(\n prompt: string,\n schema?: string | Record<string, unknown>,\n debugInfo?: AIDebugInfo,\n _checkName?: string,\n providedSessionId?: string\n ): Promise<{ response: string; effectiveSchema?: string }> {\n // Handle mock model/provider for testing\n if (this.config.model === 'mock' || this.config.provider === 'mock') {\n log('🎭 Using mock AI model/provider for testing');\n const response = await this.generateMockResponse(prompt);\n return { response, effectiveSchema: typeof schema === 'object' ? 'custom' : schema };\n }\n\n // Create ProbeAgent instance with proper options\n const sessionId =\n providedSessionId ||\n (() => {\n const timestamp = new Date().toISOString();\n return `visor-${timestamp.replace(/[:.]/g, '-')}-${_checkName || 'unknown'}`;\n })();\n\n log('🤖 Creating ProbeAgent for AI review...');\n log(`🆔 Session ID: ${sessionId}`);\n log(`📝 Prompt length: ${prompt.length} characters`);\n log(`⚙️ Model: ${this.config.model || 'default'}, Provider: ${this.config.provider || 'auto'}`);\n\n // Store original env vars to restore later\n const originalEnv: Record<string, string | undefined> = {\n CLAUDE_CODE_API_KEY: process.env.CLAUDE_CODE_API_KEY,\n GOOGLE_API_KEY: process.env.GOOGLE_API_KEY,\n ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY,\n OPENAI_API_KEY: process.env.OPENAI_API_KEY,\n };\n\n try {\n // Set environment variables for ProbeAgent\n // ProbeAgent SDK expects these to be in the environment\n if (this.config.provider === 'claude-code' && this.config.apiKey) {\n process.env.CLAUDE_CODE_API_KEY = this.config.apiKey;\n // Also set ANTHROPIC_API_KEY as fallback since Claude Code uses Anthropic API\n process.env.ANTHROPIC_API_KEY = this.config.apiKey;\n } else if (this.config.provider === 'google' && this.config.apiKey) {\n process.env.GOOGLE_API_KEY = this.config.apiKey;\n } else if (this.config.provider === 'anthropic' && this.config.apiKey) {\n process.env.ANTHROPIC_API_KEY = this.config.apiKey;\n } else if (this.config.provider === 'openai' && this.config.apiKey) {\n process.env.OPENAI_API_KEY = this.config.apiKey;\n } else if (this.config.provider === 'bedrock') {\n // For Bedrock, ProbeAgent will use AWS credentials from environment\n // No need to set apiKey as it uses AWS SDK authentication\n // ProbeAgent will check for AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, etc.\n }\n const options: ProbeAgentOptions = {\n sessionId: sessionId,\n promptType: schema ? ('code-review-template' as 'code-review') : undefined,\n allowEdit: false, // We don't want the agent to modify files\n debug: this.config.debug || false,\n };\n\n // Wire MCP configuration when provided\n if (this.config.mcpServers && Object.keys(this.config.mcpServers).length > 0) {\n (options as any).enableMcp = true;\n (options as any).mcpConfig = { mcpServers: this.config.mcpServers };\n }\n\n // Add provider-specific options if configured\n if (this.config.provider) {\n // Map claude-code to anthropic for ProbeAgent compatibility\n // Map bedrock to anthropic temporarily until ProbeAgent adds bedrock type\n const providerOverride: ProbeAgentOptions['provider'] | undefined =\n this.config.provider === 'claude-code' || this.config.provider === 'bedrock'\n ? 'anthropic'\n : this.config.provider === 'anthropic' ||\n this.config.provider === 'openai' ||\n this.config.provider === 'google'\n ? this.config.provider\n : undefined;\n\n if (providerOverride) {\n options.provider = providerOverride;\n }\n }\n if (this.config.model) {\n options.model = this.config.model;\n }\n\n const agent = new ProbeAgent(options);\n\n log('🚀 Calling ProbeAgent...');\n // Load and pass the actual schema content if provided (skip for plain schema)\n let schemaString: string | undefined = undefined;\n let effectiveSchema: string | undefined = typeof schema === 'object' ? 'custom' : schema;\n\n if (schema && schema !== 'plain') {\n try {\n schemaString = await this.loadSchemaContent(schema);\n log(`📋 Loaded schema content for: ${schema}`);\n log(`📄 Raw schema JSON:\\n${schemaString}`);\n } catch (error) {\n log(`⚠️ Failed to load schema ${schema}, proceeding without schema:`, error);\n schemaString = undefined;\n effectiveSchema = undefined; // Schema loading failed, treat as no schema\n if (debugInfo && debugInfo.errors) {\n debugInfo.errors.push(`Failed to load schema: ${error}`);\n }\n }\n } else if (schema === 'plain') {\n log(`📋 Using plain schema - no JSON validation will be applied`);\n }\n\n // ProbeAgent now handles schema formatting internally!\n // Pass schema in options object with 'schema' property\n const schemaOptions = schemaString ? { schema: schemaString } : undefined;\n\n // Store the exact schema options being passed to ProbeAgent in debug info\n if (debugInfo && schemaOptions) {\n debugInfo.schema = JSON.stringify(schemaOptions, null, 2);\n }\n\n // Log the schema options being passed to ProbeAgent\n if (schemaOptions) {\n log(`🎯 Schema options passed to ProbeAgent.answer():`);\n log(JSON.stringify(schemaOptions, null, 2));\n }\n\n // Log the equivalent CLI command for local reproduction\n const provider = this.config.provider || 'auto';\n const model = this.config.model || 'default';\n\n // Save prompt to a temp file for easier reproduction\n try {\n const fs = require('fs');\n const path = require('path');\n const os = require('os');\n const tempDir = os.tmpdir();\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\n const promptFile = path.join(tempDir, `visor-prompt-${timestamp}.txt`);\n\n fs.writeFileSync(promptFile, prompt, 'utf-8');\n log(`\\n💾 Prompt saved to: ${promptFile}`);\n\n log(`\\n📝 To reproduce locally, run:`);\n\n let cliCommand = `npx @probelabs/probe@latest agent`;\n cliCommand += ` --provider ${provider}`;\n if (model !== 'default') {\n cliCommand += ` --model ${model}`;\n }\n if (schema) {\n cliCommand += ` --schema output/${schema}/schema.json`;\n }\n cliCommand += ` \"${promptFile}\"`;\n\n log(`\\n$ ${cliCommand}\\n`);\n } catch (error) {\n log(`⚠️ Could not save prompt file: ${error}`);\n }\n\n const response = await agent.answer(prompt, undefined, schemaOptions);\n\n log('✅ ProbeAgent completed successfully');\n log(`📤 Response length: ${response.length} characters`);\n\n // Register the session for potential reuse by dependent checks\n if (_checkName) {\n this.registerSession(sessionId, agent);\n log(`🔧 Debug: Registered AI session for potential reuse: ${sessionId}`);\n }\n\n return { response, effectiveSchema };\n } catch (error) {\n console.error('❌ ProbeAgent failed:', error);\n throw new Error(\n `ProbeAgent execution failed: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n } finally {\n // Restore original environment variables\n Object.keys(originalEnv).forEach(key => {\n if (originalEnv[key] === undefined) {\n delete process.env[key];\n } else {\n process.env[key] = originalEnv[key];\n }\n });\n }\n }\n\n /**\n * Load schema content from schema files or inline definitions\n */\n private async loadSchemaContent(schema: string | Record<string, unknown>): Promise<string> {\n const fs = require('fs').promises;\n const path = require('path');\n\n // Check if schema is already an object (inline definition from YAML)\n if (typeof schema === 'object' && schema !== null) {\n // It's already a schema object, convert to JSON string\n log('📋 Using inline schema object from configuration');\n return JSON.stringify(schema);\n }\n\n // Check if schema string is already a JSON schema (inline JSON string)\n // This happens when a schema is passed directly as JSON instead of a reference\n try {\n const parsed = JSON.parse(schema);\n if (typeof parsed === 'object' && parsed !== null) {\n // It's already a valid JSON schema, return it as-is\n log('📋 Using inline schema JSON string');\n return schema;\n }\n } catch {\n // Not JSON, treat as schema name reference or file path\n }\n\n // Check if it's a file path (starts with ./ or contains .json but not absolute paths)\n if ((schema.startsWith('./') || schema.includes('.json')) && !path.isAbsolute(schema)) {\n // It's a relative file path to a custom schema\n // Validate the path to prevent traversal attacks\n if (schema.includes('..') || schema.includes('\\x00')) {\n throw new Error('Invalid schema path: path traversal not allowed');\n }\n\n try {\n const schemaPath = path.resolve(process.cwd(), schema);\n log(`📋 Loading custom schema from file: ${schemaPath}`);\n const schemaContent = await fs.readFile(schemaPath, 'utf-8');\n return schemaContent.trim();\n } catch (error) {\n throw new Error(\n `Failed to load custom schema from ${schema}: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n }\n }\n\n // Otherwise, treat as a built-in schema name\n // Sanitize schema name to prevent path traversal attacks\n const sanitizedSchemaName = schema.replace(/[^a-zA-Z0-9-]/g, '');\n if (!sanitizedSchemaName || sanitizedSchemaName !== schema) {\n throw new Error('Invalid schema name');\n }\n\n // Construct path to built-in schema file\n const schemaPath = path.join(process.cwd(), 'output', sanitizedSchemaName, 'schema.json');\n\n try {\n // Return the schema as a string, not parsed JSON\n const schemaContent = await fs.readFile(schemaPath, 'utf-8');\n return schemaContent.trim();\n } catch (error) {\n throw new Error(\n `Failed to load schema from ${schemaPath}: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n }\n }\n\n /**\n * Parse AI response JSON\n */\n private parseAIResponse(\n response: string,\n debugInfo?: AIDebugInfo,\n _schema?: string\n ): ReviewSummary {\n log('🔍 Parsing AI response...');\n log(`📊 Raw response length: ${response.length} characters`);\n\n // Log first and last 200 chars for debugging\n if (response.length > 400) {\n log('📋 Response preview (first 200 chars):', response.substring(0, 200));\n log('📋 Response preview (last 200 chars):', response.substring(response.length - 200));\n } else {\n log('📋 Full response preview:', response);\n }\n\n try {\n // Handle different schema types differently\n let reviewData: AIResponseFormat;\n\n // Handle plain schema or no schema - no JSON parsing, return response as-is\n if (_schema === 'plain' || !_schema) {\n log(\n `📋 ${_schema === 'plain' ? 'Plain' : 'No'} schema detected - returning raw response without JSON parsing`\n );\n\n // For plain schema, return the raw response as an issue\n\n return {\n issues: [\n {\n file: 'AI_RESPONSE',\n line: 1,\n ruleId: 'ai/raw_response',\n message: response,\n severity: 'info',\n category: 'documentation',\n },\n ],\n debug: debugInfo,\n };\n }\n\n {\n // For other schemas (code-review, etc.), extract and parse JSON with boundary detection\n log('🔍 Extracting JSON from AI response...');\n\n // Try direct parsing first - if AI returned pure JSON\n try {\n reviewData = JSON.parse(response.trim());\n log('✅ Successfully parsed direct JSON response');\n if (debugInfo) debugInfo.jsonParseSuccess = true;\n } catch {\n log('🔍 Direct parsing failed, trying to extract JSON from response...');\n\n // If the response starts with \"I cannot\" or similar, it's likely a refusal\n if (\n response.toLowerCase().includes('i cannot') ||\n response.toLowerCase().includes('unable to')\n ) {\n console.error('🚫 AI refused to analyze - returning empty result');\n return {\n issues: [],\n };\n }\n\n // Try to extract JSON using improved method with proper bracket matching\n const jsonString = this.extractJsonFromResponse(response);\n\n if (jsonString) {\n try {\n reviewData = JSON.parse(jsonString);\n log('✅ Successfully parsed extracted JSON');\n if (debugInfo) debugInfo.jsonParseSuccess = true;\n } catch {\n log('🔧 Extracted JSON parsing failed, falling back to plain text handling...');\n\n // Check if response is plain text and doesn't contain structured data\n if (!response.includes('{') && !response.includes('}')) {\n log('🔧 Plain text response detected, creating structured fallback...');\n\n reviewData = {\n issues: [\n {\n file: 'AI_RESPONSE',\n line: 1,\n ruleId: 'ai/raw_response',\n message: response,\n severity: 'info',\n category: 'documentation',\n },\n ],\n };\n } else {\n // Fallback: treat the entire response as an issue\n log('🔧 Creating fallback response from non-JSON content...');\n reviewData = {\n issues: [\n {\n file: 'AI_RESPONSE',\n line: 1,\n ruleId: 'ai/raw_response',\n message: response,\n severity: 'info',\n category: 'documentation',\n },\n ],\n };\n }\n }\n } else {\n // No JSON found at all - treat as plain text response\n log('🔧 No JSON found in response, treating as plain text...');\n reviewData = {\n issues: [\n {\n file: 'AI_RESPONSE',\n line: 1,\n ruleId: 'ai/raw_response',\n message: response,\n severity: 'info',\n category: 'documentation',\n },\n ],\n };\n }\n }\n }\n\n // Check if this is a custom schema (free-form data)\n // Custom schemas are:\n // 1. Inline schemas (effectiveSchema === 'custom')\n // 2. File-based custom schemas (starts with ./ or contains .json)\n // 3. Any schema that is NOT 'code-review' or other built-in schemas\n const isCustomSchema =\n _schema === 'custom' ||\n (_schema && (_schema.startsWith('./') || _schema.endsWith('.json'))) ||\n (_schema && _schema !== 'code-review' && !_schema.includes('output/'));\n\n if (isCustomSchema) {\n // For custom schemas, preserve ALL fields from the parsed JSON\n // Don't force the response into the standard ReviewSummary format\n log('📋 Custom schema detected - preserving all fields from parsed JSON');\n log(`📊 Schema: ${_schema}`);\n log(`📊 Custom schema keys: ${Object.keys(reviewData).join(', ')}`);\n\n // Return the full parsed data as the output, with an empty issues array\n // This allows downstream checks to access all custom fields via outputs\n const result: ReviewSummary & { output?: unknown } = {\n issues: [], // Empty array for custom schemas (no code review issues)\n output: reviewData, // Preserve ALL custom schema fields here\n };\n\n log('✅ Successfully created ReviewSummary with custom schema output');\n return result;\n }\n\n // Standard code-review schema processing\n log('🔍 Validating parsed review data...');\n log(`📊 Overall score: ${0}`);\n log(`📋 Total issues: ${reviewData.issues?.length || 0}`);\n log(\n `🚨 Critical issues: ${reviewData.issues?.filter((i: { severity?: string }) => i.severity === 'critical').length || 0}`\n );\n log(`💬 Comments count: ${Array.isArray(reviewData.issues) ? reviewData.issues.length : 0}`);\n\n // Process issues from the simplified format\n const processedIssues = Array.isArray(reviewData.issues)\n ? reviewData.issues.map((issue, index) => {\n log(`🔍 Processing issue ${index + 1}:`, issue);\n return {\n file: issue.file || 'unknown',\n line: issue.line || 1,\n endLine: issue.endLine,\n ruleId: issue.ruleId || `${issue.category || 'general'}/unknown`,\n message: issue.message || '',\n severity: issue.severity,\n category: issue.category,\n suggestion: issue.suggestion,\n replacement: issue.replacement,\n } as ReviewIssue;\n })\n : [];\n\n // Validate and convert to ReviewSummary format\n const result: ReviewSummary = {\n issues: processedIssues,\n };\n\n // Log issue counts\n const criticalCount = (result.issues || []).filter(i => i.severity === 'critical').length;\n if (criticalCount > 0) {\n log(`🚨 Found ${criticalCount} critical severity issue(s)`);\n }\n log(`📈 Total issues: ${(result.issues || []).length}`);\n\n log('✅ Successfully created ReviewSummary');\n return result;\n } catch (error) {\n console.error('❌ Failed to parse AI response:', error);\n console.error('📄 FULL RAW RESPONSE:');\n console.error('='.repeat(80));\n console.error(response);\n console.error('='.repeat(80));\n console.error(`📏 Response length: ${response.length} characters`);\n\n // Try to provide more helpful error information\n if (error instanceof SyntaxError) {\n console.error('🔍 JSON parsing error - the response may not be valid JSON');\n console.error('🔍 Error details:', error.message);\n\n // Try to identify where the parsing failed\n const errorMatch = error.message.match(/position (\\d+)/);\n if (errorMatch) {\n const position = parseInt(errorMatch[1]);\n console.error(`🔍 Error at position ${position}:`);\n const start = Math.max(0, position - 50);\n const end = Math.min(response.length, position + 50);\n console.error(`🔍 Context: \"${response.substring(start, end)}\"`);\n\n // Show the first 100 characters to understand what format the AI returned\n console.error(`🔍 Response beginning: \"${response.substring(0, 100)}\"`);\n }\n\n // Check if response contains common non-JSON patterns\n if (response.includes('I cannot')) {\n console.error('🔍 Response appears to be a refusal/explanation rather than JSON');\n }\n if (response.includes('```')) {\n console.error('🔍 Response appears to contain markdown code blocks');\n }\n if (response.startsWith('<')) {\n console.error('🔍 Response appears to start with XML/HTML');\n }\n }\n\n throw new Error(\n `Invalid AI response format: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n }\n }\n\n /**\n * Extract JSON from a response that might contain surrounding text\n * Uses proper bracket matching to find valid JSON objects or arrays\n */\n private extractJsonFromResponse(response: string): string | null {\n const text = response.trim();\n\n // Try to find JSON objects first (higher priority)\n let bestJson = this.findJsonWithBracketMatching(text, '{', '}');\n\n // If no object found, try arrays\n if (!bestJson) {\n bestJson = this.findJsonWithBracketMatching(text, '[', ']');\n }\n\n return bestJson;\n }\n\n /**\n * Find JSON with proper bracket matching to avoid false positives\n */\n private findJsonWithBracketMatching(\n text: string,\n openChar: string,\n closeChar: string\n ): string | null {\n const firstIndex = text.indexOf(openChar);\n if (firstIndex === -1) return null;\n\n let depth = 0;\n let inString = false;\n let escaping = false;\n\n for (let i = firstIndex; i < text.length; i++) {\n const char = text[i];\n\n if (escaping) {\n escaping = false;\n continue;\n }\n\n if (char === '\\\\' && inString) {\n escaping = true;\n continue;\n }\n\n if (char === '\"' && !escaping) {\n inString = !inString;\n continue;\n }\n\n if (!inString) {\n if (char === openChar) {\n depth++;\n } else if (char === closeChar) {\n depth--;\n if (depth === 0) {\n // Found matching closing bracket\n const candidate = text.substring(firstIndex, i + 1);\n try {\n JSON.parse(candidate); // Validate it's actually valid JSON\n return candidate;\n } catch {\n // This wasn't valid JSON, keep looking\n break;\n }\n }\n }\n }\n }\n\n return null;\n }\n\n /**\n * Generate mock response for testing\n */\n private async generateMockResponse(_prompt: string): Promise<string> {\n // Simulate some processing time\n await new Promise(resolve => setTimeout(resolve, 500));\n\n // Generate mock response based on prompt content\n const mockResponse = {\n content: JSON.stringify({\n issues: [\n {\n file: 'test.ts',\n line: 7,\n endLine: 11,\n ruleId: 'security/sql-injection',\n message: 'SQL injection vulnerability detected in dynamic query construction',\n severity: 'critical',\n category: 'security',\n suggestion: 'Use parameterized queries or ORM methods to prevent SQL injection',\n },\n {\n file: 'test.ts',\n line: 14,\n endLine: 23,\n ruleId: 'performance/nested-loops',\n message: 'Inefficient nested loops with O(n²) complexity',\n severity: 'warning',\n category: 'performance',\n suggestion: 'Consider using more efficient algorithms or caching mechanisms',\n },\n {\n file: 'test.ts',\n line: 28,\n ruleId: 'style/inconsistent-naming',\n message: 'Inconsistent variable naming and formatting',\n severity: 'info',\n category: 'style',\n suggestion: 'Use consistent camelCase naming and proper spacing',\n },\n ],\n summary: {\n totalIssues: 3,\n criticalIssues: 1,\n },\n }),\n };\n\n return JSON.stringify(mockResponse);\n }\n\n /**\n * Get the API key source for debugging (without revealing the key)\n */\n private getApiKeySource(): string {\n if (process.env.CLAUDE_CODE_API_KEY && this.config.provider === 'claude-code') {\n return 'CLAUDE_CODE_API_KEY';\n }\n if (process.env.GOOGLE_API_KEY && this.config.provider === 'google') {\n return 'GOOGLE_API_KEY';\n }\n if (process.env.ANTHROPIC_API_KEY && this.config.provider === 'anthropic') {\n return 'ANTHROPIC_API_KEY';\n }\n if (process.env.OPENAI_API_KEY && this.config.provider === 'openai') {\n return 'OPENAI_API_KEY';\n }\n if (this.config.provider === 'bedrock') {\n if (process.env.AWS_BEDROCK_API_KEY) {\n return 'AWS_BEDROCK_API_KEY';\n }\n if (process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY) {\n return 'AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY';\n }\n }\n return 'unknown';\n }\n}\n","/*\n * Centralized logger for Visor CLI and Action modes.\n * - Respects output format (suppresses info in JSON/SARIF unless debug)\n * - Supports levels: silent < error < warn < info < verbose < debug\n * - Routes logs to stderr to keep stdout clean for machine-readable output\n */\n\nexport type LogLevel = 'silent' | 'error' | 'warn' | 'info' | 'verbose' | 'debug';\n\nfunction levelToNumber(level: LogLevel): number {\n switch (level) {\n case 'silent':\n return 0;\n case 'error':\n return 10;\n case 'warn':\n return 20;\n case 'info':\n return 30;\n case 'verbose':\n return 40;\n case 'debug':\n return 50;\n }\n}\n\nclass Logger {\n private level: LogLevel = 'info';\n private isJsonLike: boolean = false;\n private isTTY: boolean = typeof process !== 'undefined' ? !!process.stderr.isTTY : false;\n\n configure(\n opts: {\n outputFormat?: string;\n level?: LogLevel;\n debug?: boolean;\n verbose?: boolean;\n quiet?: boolean;\n } = {}\n ): void {\n // Determine base level\n let lvl: LogLevel = 'info';\n\n if (opts.debug || process.env.VISOR_DEBUG === 'true') {\n lvl = 'debug';\n } else if (opts.verbose || process.env.VISOR_LOG_LEVEL === 'verbose') {\n lvl = 'verbose';\n } else if (opts.quiet || process.env.VISOR_LOG_LEVEL === 'quiet') {\n lvl = 'warn';\n } else if (opts.level) {\n lvl = opts.level;\n } else if (process.env.VISOR_LOG_LEVEL) {\n const envLvl = process.env.VISOR_LOG_LEVEL as LogLevel;\n if (['silent', 'error', 'warn', 'info', 'verbose', 'debug'].includes(envLvl)) {\n lvl = envLvl as LogLevel;\n }\n }\n\n this.level = lvl;\n const output = opts.outputFormat || process.env.VISOR_OUTPUT_FORMAT || 'table';\n // In JSON/SARIF we suppress non-error logs unless explicitly verbose/debug\n this.isJsonLike = output === 'json' || output === 'sarif';\n }\n\n private shouldLog(level: LogLevel): boolean {\n const desired = levelToNumber(level);\n const current = levelToNumber(this.level);\n if (desired > current) return false;\n if (\n this.isJsonLike &&\n desired < levelToNumber('error') &&\n this.level !== 'debug' &&\n this.level !== 'verbose'\n ) {\n // In JSON/SARIF, hide info/warn unless explicitly verbose/debug\n return false;\n }\n return true;\n }\n\n private write(msg: string): void {\n // Always route to stderr to keep stdout clean for results\n try {\n process.stderr.write(msg + '\\n');\n } catch {\n // Ignore write errors\n }\n }\n\n info(msg: string): void {\n if (this.shouldLog('info')) this.write(msg);\n }\n\n warn(msg: string): void {\n if (this.shouldLog('warn')) this.write(msg);\n }\n\n error(msg: string): void {\n if (this.shouldLog('error')) this.write(msg);\n }\n\n verbose(msg: string): void {\n if (this.shouldLog('verbose')) this.write(msg);\n }\n\n debug(msg: string): void {\n if (this.shouldLog('debug')) this.write(msg);\n }\n\n step(msg: string): void {\n // High-level phase indicator\n if (this.shouldLog('info')) this.write(`▶ ${msg}`);\n }\n\n success(msg: string): void {\n if (this.shouldLog('info')) this.write(`✔ ${msg}`);\n }\n}\n\n// Singleton instance\nexport const logger = new Logger();\n\n// Helper to configure from CLI options in a single place\nexport function configureLoggerFromCli(options: {\n output?: string;\n debug?: boolean;\n verbose?: boolean;\n quiet?: boolean;\n}): void {\n logger.configure({\n outputFormat: options.output,\n debug: options.debug,\n verbose: options.verbose,\n quiet: options.quiet,\n });\n}\n","import { Octokit } from '@octokit/rest';\nimport { PRInfo } from './pr-analyzer';\nimport { CommentManager } from './github-comments';\nimport { AIReviewService, AIDebugInfo } from './ai-review-service';\n\nexport interface ReviewIssue {\n // Location\n file: string;\n line: number;\n endLine?: number;\n // Issue details\n ruleId: string;\n message: string;\n severity: 'info' | 'warning' | 'error' | 'critical';\n category: 'security' | 'performance' | 'style' | 'logic' | 'documentation';\n // Check identification - which check created this issue\n checkName?: string;\n // Group and schema for comment separation\n group?: string;\n schema?: string;\n // Timestamp when the issue was created (for ordering)\n timestamp?: number;\n // Optional enhancement\n suggestion?: string;\n replacement?: string;\n}\n\n// Legacy interface - ONLY for GitHub integration compatibility\nexport interface ReviewComment {\n file: string;\n line: number;\n message: string;\n severity: 'info' | 'warning' | 'error' | 'critical';\n category: 'security' | 'performance' | 'style' | 'logic' | 'documentation';\n suggestion?: string;\n replacement?: string;\n ruleId?: string;\n}\n\n// Individual check result - each check produces one of these\nexport interface CheckResult {\n checkName: string;\n content: string; // Rendered output for this specific check\n group: string; // Which group this check belongs to\n debug?: AIDebugInfo;\n issues?: ReviewIssue[]; // Structured issues alongside rendered content\n}\n\n// Results grouped by group name\nexport interface GroupedCheckResults {\n [groupName: string]: CheckResult[];\n}\n\n// Legacy interface - only for backward compatibility\nexport interface ReviewSummary {\n issues?: ReviewIssue[];\n debug?: AIDebugInfo;\n}\n\n// Test utility function - Convert old ReviewSummary to new GroupedCheckResults format\n// This is for backward compatibility with tests only\nexport function convertReviewSummaryToGroupedResults(\n reviewSummary: ReviewSummary,\n checkName: string = 'test-check',\n groupName: string = 'default'\n): GroupedCheckResults {\n // Create a simple content string from issues\n let content = '';\n\n if (reviewSummary.issues && reviewSummary.issues.length > 0) {\n content += `## Issues Found (${reviewSummary.issues.length})\\n\\n`;\n reviewSummary.issues.forEach(issue => {\n content += `- **${issue.severity.toUpperCase()}**: ${issue.message} (${issue.file}:${issue.line})\\n`;\n });\n content += '\\n';\n }\n\n if (!content) {\n content = 'No issues found.';\n }\n\n const checkResult: CheckResult = {\n checkName,\n content: content.trim(),\n group: groupName,\n debug: reviewSummary.debug,\n issues: reviewSummary.issues, // Include structured issues\n };\n\n const groupedResults: GroupedCheckResults = {};\n groupedResults[groupName] = [checkResult];\n\n return groupedResults;\n}\n\n// Helper functions for GitHub checks - ONLY for structured schemas that have issues\n// These are the ONLY acceptable hardcoded schema dependencies, and only for GitHub integration\nexport function calculateTotalIssues(issues?: ReviewIssue[]): number {\n return (issues || []).length;\n}\n\nexport function calculateCriticalIssues(issues?: ReviewIssue[]): number {\n return (issues || []).filter(i => i.severity === 'critical').length;\n}\n\n// Legacy converter - ONLY for GitHub integration compatibility\nexport function convertIssuesToComments(issues: ReviewIssue[]): ReviewComment[] {\n return issues.map(issue => ({\n file: issue.file,\n line: issue.line,\n message: issue.message,\n severity: issue.severity,\n category: issue.category,\n suggestion: issue.suggestion,\n replacement: issue.replacement,\n ruleId: issue.ruleId,\n }));\n}\n\nexport interface ReviewOptions {\n focus?: 'security' | 'performance' | 'style' | 'all';\n format?: 'table' | 'json' | 'markdown' | 'sarif';\n debug?: boolean;\n config?: import('./types/config').VisorConfig;\n checks?: string[];\n parallelExecution?: boolean;\n}\n\nexport class PRReviewer {\n private commentManager: CommentManager;\n private aiReviewService: AIReviewService;\n\n constructor(private octokit: Octokit) {\n this.commentManager = new CommentManager(octokit);\n this.aiReviewService = new AIReviewService();\n }\n\n async reviewPR(\n owner: string,\n repo: string,\n prNumber: number,\n prInfo: PRInfo,\n options: ReviewOptions = {}\n ): Promise<GroupedCheckResults> {\n const { debug = false, config, checks } = options;\n\n if (config && checks && checks.length > 0) {\n const { CheckExecutionEngine } = await import('./check-execution-engine');\n const engine = new CheckExecutionEngine();\n const { results } = await engine.executeGroupedChecks(\n prInfo,\n checks,\n undefined,\n config,\n undefined,\n debug\n );\n return results;\n }\n\n throw new Error(\n 'No configuration provided. Please create a .visor.yaml file with check definitions. ' +\n 'Built-in prompts have been removed - all checks must be explicitly configured.'\n );\n }\n\n async postReviewComment(\n owner: string,\n repo: string,\n prNumber: number,\n groupedResults: GroupedCheckResults,\n options: ReviewOptions & { commentId?: string; triggeredBy?: string; commitSha?: string } = {}\n ): Promise<void> {\n // Post separate comments for each group\n for (const [groupName, checkResults] of Object.entries(groupedResults)) {\n const comment = await this.formatGroupComment(checkResults, options, {\n owner,\n repo,\n prNumber,\n commitSha: options.commitSha,\n });\n\n // Generate comment ID - use unique ID for \"dynamic\" group\n let commentId: string;\n if (groupName === 'dynamic') {\n // Dynamic group creates a new comment each time with timestamp-based ID\n const timestamp = Date.now();\n commentId = `visor-dynamic-${timestamp}`;\n } else {\n // Regular groups use static IDs that get updated\n commentId = options.commentId\n ? `${options.commentId}-${groupName}`\n : `visor-review-${groupName}`;\n }\n\n await this.commentManager.updateOrCreateComment(owner, repo, prNumber, comment, {\n commentId,\n triggeredBy: options.triggeredBy || 'unknown',\n allowConcurrentUpdates: false,\n commitSha: options.commitSha,\n });\n }\n }\n\n private async formatGroupComment(\n checkResults: CheckResult[],\n _options: ReviewOptions,\n _githubContext?: { owner: string; repo: string; prNumber: number; commitSha?: string }\n ): Promise<string> {\n let comment = '';\n comment += `## 🔍 Code Analysis Results\\n\\n`;\n\n // Simple concatenation of all check outputs in this group\n const checkContents = checkResults\n .map(result => result.content)\n .filter(content => content.trim());\n comment += checkContents.join('\\n\\n');\n\n // Add debug info if any check has it\n const debugInfo = checkResults.find(result => result.debug)?.debug;\n if (debugInfo) {\n comment += '\\n\\n' + this.formatDebugSection(debugInfo);\n comment += '\\n\\n';\n }\n\n comment += `\\n\\n---\\n\\n*Powered by [Visor](https://probelabs.com/visor) from [Probelabs](https://probelabs.com)*`;\n return comment;\n }\n\n private formatDebugSection(debug: AIDebugInfo): string {\n const formattedContent = [\n `**Provider:** ${debug.provider}`,\n `**Model:** ${debug.model}`,\n `**API Key Source:** ${debug.apiKeySource}`,\n `**Processing Time:** ${debug.processingTime}ms`,\n `**Timestamp:** ${debug.timestamp}`,\n `**Prompt Length:** ${debug.promptLength} characters`,\n `**Response Length:** ${debug.responseLength} characters`,\n `**JSON Parse Success:** ${debug.jsonParseSuccess ? '✅' : '❌'}`,\n ];\n\n if (debug.errors && debug.errors.length > 0) {\n formattedContent.push('', '### Errors');\n debug.errors.forEach(error => {\n formattedContent.push(`- ${error}`);\n });\n }\n\n const fullDebugContent = [\n ...formattedContent,\n '',\n '### AI Prompt',\n '```',\n debug.prompt,\n '```',\n '',\n '### Raw AI Response',\n '```json',\n debug.rawResponse,\n '```',\n ].join('\\n');\n\n if (fullDebugContent.length > 60000) {\n const artifactPath = this.saveDebugArtifact(debug);\n formattedContent.push('');\n formattedContent.push('### Debug Details');\n formattedContent.push('⚠️ Debug information is too large for GitHub comments.');\n if (artifactPath) {\n formattedContent.push(\n `📁 **Full debug information saved to artifact:** \\`${artifactPath}\\``\n );\n formattedContent.push('');\n const runId = process.env.GITHUB_RUN_ID;\n const repoUrl =\n process.env.GITHUB_SERVER_URL && process.env.GITHUB_REPOSITORY\n ? `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}`\n : null;\n if (runId && repoUrl) {\n formattedContent.push(\n `🔗 **Download Link:** [visor-debug-${process.env.GITHUB_RUN_NUMBER || runId}](${repoUrl}/actions/runs/${runId})`\n );\n }\n formattedContent.push(\n '💡 Go to the GitHub Action run above and download the debug artifact to view complete prompts and responses.'\n );\n } else {\n formattedContent.push('📝 **Prompt preview:** ' + debug.prompt.substring(0, 500) + '...');\n formattedContent.push(\n '📝 **Response preview:** ' + debug.rawResponse.substring(0, 500) + '...'\n );\n }\n } else {\n formattedContent.push('');\n formattedContent.push('### AI Prompt');\n formattedContent.push('```');\n formattedContent.push(debug.prompt);\n formattedContent.push('```');\n formattedContent.push('');\n formattedContent.push('### Raw AI Response');\n formattedContent.push('```json');\n formattedContent.push(debug.rawResponse);\n formattedContent.push('```');\n }\n\n return this.commentManager.createCollapsibleSection(\n '🐛 Debug Information',\n formattedContent.join('\\n'),\n false\n );\n }\n\n private saveDebugArtifact(debug: AIDebugInfo): string | null {\n try {\n const fs = require('fs');\n const path = require('path');\n const debugDir = path.join(process.cwd(), 'debug-artifacts');\n if (!fs.existsSync(debugDir)) {\n fs.mkdirSync(debugDir, { recursive: true });\n }\n\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\n const filename = `visor-debug-${timestamp}.md`;\n const filepath = path.join(debugDir, filename);\n\n const content = [\n `# Visor Debug Information`,\n ``,\n `**Timestamp:** ${debug.timestamp}`,\n `**Provider:** ${debug.provider}`,\n `**Model:** ${debug.model}`,\n `**Processing Time:** ${debug.processingTime}ms`,\n ``,\n `## AI Prompt`,\n ``,\n '```',\n debug.prompt,\n '```',\n ``,\n `## Raw AI Response`,\n ``,\n '```json',\n debug.rawResponse,\n '```',\n ].join('\\n');\n\n fs.writeFileSync(filepath, content, 'utf8');\n return filename;\n } catch (error) {\n console.error('Failed to save debug artifact:', error);\n return null;\n }\n }\n}\n","import { simpleGit, SimpleGit, type DefaultLogFields, type ListLogLine } from 'simple-git';\nimport * as path from 'path';\nimport * as fs from 'fs';\nimport { PRInfo, PRDiff } from './pr-analyzer';\n\nexport interface GitFileChange {\n filename: string;\n status: 'added' | 'removed' | 'modified' | 'renamed';\n additions: number;\n deletions: number;\n changes: number;\n content?: string;\n patch?: string;\n}\n\nexport interface GitRepositoryInfo {\n title: string;\n body: string;\n author: string;\n base: string;\n head: string;\n files: GitFileChange[];\n totalAdditions: number;\n totalDeletions: number;\n isGitRepository: boolean;\n workingDirectory: string;\n}\n\nexport class GitRepositoryAnalyzer {\n private git: SimpleGit;\n private cwd: string;\n\n constructor(workingDirectory: string = process.cwd()) {\n this.cwd = workingDirectory;\n this.git = simpleGit(workingDirectory);\n }\n\n /**\n * Analyze the current git repository state and return data compatible with PRInfo interface\n */\n async analyzeRepository(includeContext: boolean = true): Promise<GitRepositoryInfo> {\n // Check if we're in a git repository\n const isRepo = await this.isGitRepository();\n if (!isRepo) {\n return this.createEmptyRepositoryInfo('Not a git repository');\n }\n\n try {\n // Get current branch and status\n const [status, currentBranch] = await Promise.all([\n this.git.status(),\n this.getCurrentBranch(),\n ]);\n\n // Get uncommitted changes\n const uncommittedFiles = await this.getUncommittedChanges(includeContext);\n\n // Get recent commit info (handle repos with no commits)\n let lastCommit: (ListLogLine & DefaultLogFields) | null = null;\n try {\n const recentCommits = await this.git.log({ maxCount: 1 });\n lastCommit = recentCommits.latest;\n } catch {\n // Repository has no commits yet - this is OK\n console.log('📝 Repository has no commits yet, analyzing uncommitted changes');\n }\n\n // Get author from git config if no commits exist\n let author = lastCommit?.author_name;\n if (!author) {\n try {\n const [userName, userEmail] = await Promise.all([\n this.git.raw(['config', 'user.name']).catch(() => null),\n this.git.raw(['config', 'user.email']).catch(() => null),\n ]);\n author = userName?.trim() || userEmail?.trim() || 'unknown';\n } catch {\n author = 'unknown';\n }\n }\n\n // Create repository info\n const repositoryInfo: GitRepositoryInfo = {\n title: this.generateTitle(status, currentBranch),\n body: this.generateDescription(status, lastCommit),\n author,\n base: await this.getBaseBranch(),\n head: currentBranch,\n files: uncommittedFiles,\n totalAdditions: uncommittedFiles.reduce((sum, file) => sum + file.additions, 0),\n totalDeletions: uncommittedFiles.reduce((sum, file) => sum + file.deletions, 0),\n isGitRepository: true,\n workingDirectory: this.cwd,\n };\n\n return repositoryInfo;\n } catch (error) {\n // Don't log the full error object to avoid confusing stack traces\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n console.error('Error analyzing git repository:', errorMessage);\n return this.createEmptyRepositoryInfo('Error analyzing git repository');\n }\n }\n\n /**\n * Convert GitRepositoryInfo to PRInfo format for compatibility with existing PRReviewer\n */\n toPRInfo(repositoryInfo: GitRepositoryInfo, includeContext: boolean = true): PRInfo {\n const files = repositoryInfo.files.map(\n (file): PRDiff => ({\n filename: file.filename,\n additions: file.additions,\n deletions: file.deletions,\n changes: file.changes,\n patch: includeContext ? file.patch : undefined,\n status: file.status,\n })\n );\n\n // Generate fullDiff from patches if includeContext is true\n let fullDiff: string | undefined;\n if (includeContext) {\n fullDiff = files\n .filter(file => file.patch)\n .map(file => `--- ${file.filename}\\n${file.patch}`)\n .join('\\n\\n');\n }\n\n return {\n number: 0, // Local analysis doesn't have PR number\n title: repositoryInfo.title,\n body: repositoryInfo.body,\n author: repositoryInfo.author,\n base: repositoryInfo.base,\n head: repositoryInfo.head,\n files,\n totalAdditions: repositoryInfo.totalAdditions,\n totalDeletions: repositoryInfo.totalDeletions,\n fullDiff,\n };\n }\n\n private async isGitRepository(): Promise<boolean> {\n try {\n await this.git.checkIsRepo();\n return true;\n } catch {\n return false;\n }\n }\n\n private async getCurrentBranch(): Promise<string> {\n try {\n const branchSummary = await this.git.branch();\n return branchSummary.current || 'unknown';\n } catch {\n return 'unknown';\n }\n }\n\n private async getBaseBranch(): Promise<string> {\n try {\n // Try to get the default branch from remote\n const branches = await this.git.branch(['-r']);\n const mainBranches = ['origin/main', 'origin/master', 'origin/develop'];\n\n for (const mainBranch of mainBranches) {\n if (branches.all.includes(mainBranch)) {\n return mainBranch.replace('origin/', '');\n }\n }\n\n // Fallback to main/master\n return 'main';\n } catch {\n return 'main';\n }\n }\n\n private async getRemoteInfo(): Promise<{ name: string; url: string } | null> {\n try {\n const remotes = await this.git.getRemotes(true);\n const origin = remotes.find(r => r.name === 'origin');\n return origin\n ? { name: origin.name, url: origin.refs.fetch || origin.refs.push || '' }\n : null;\n } catch {\n return null;\n }\n }\n\n private async getUncommittedChanges(includeContext: boolean = true): Promise<GitFileChange[]> {\n try {\n const status = await this.git.status();\n const changes: GitFileChange[] = [];\n\n // Process different types of changes\n const fileChanges = [\n ...status.created.map(f => ({ file: f, status: 'added' as const })),\n ...status.deleted.map(f => ({ file: f, status: 'removed' as const })),\n ...status.modified.map(f => ({ file: f, status: 'modified' as const })),\n ...status.renamed.map(f => ({\n file: typeof f === 'string' ? f : f.to || f.from,\n status: 'renamed' as const,\n })),\n ];\n\n for (const { file, status } of fileChanges) {\n const filePath = path.join(this.cwd, file);\n const fileChange = await this.analyzeFileChange(file, status, filePath, includeContext);\n changes.push(fileChange);\n }\n\n return changes;\n } catch (error) {\n console.error('Error getting uncommitted changes:', error);\n return [];\n }\n }\n\n private async analyzeFileChange(\n filename: string,\n status: 'added' | 'removed' | 'modified' | 'renamed',\n filePath: string,\n includeContext: boolean = true\n ): Promise<GitFileChange> {\n let additions = 0;\n let deletions = 0;\n let patch: string | undefined;\n let content: string | undefined;\n\n try {\n // Get diff for the file if it exists and is not binary\n if (includeContext && status !== 'added' && fs.existsSync(filePath)) {\n const diff = await this.git.diff(['--', filename]).catch(() => '');\n if (diff) {\n patch = diff;\n // Count additions and deletions from diff\n const lines = diff.split('\\n');\n additions = lines.filter(line => line.startsWith('+')).length;\n deletions = lines.filter(line => line.startsWith('-')).length;\n }\n } else if (status !== 'added' && fs.existsSync(filePath)) {\n // If not including context, still count changes for statistics\n const diff = await this.git.diff(['--', filename]).catch(() => '');\n if (diff) {\n const lines = diff.split('\\n');\n additions = lines.filter(line => line.startsWith('+')).length;\n deletions = lines.filter(line => line.startsWith('-')).length;\n }\n }\n\n // For added files\n if (status === 'added' && fs.existsSync(filePath)) {\n try {\n const stats = fs.statSync(filePath);\n if (stats.isFile() && stats.size < 1024 * 1024) {\n // Skip files larger than 1MB\n if (includeContext) {\n content = fs.readFileSync(filePath, 'utf8');\n patch = content; // For new files, the entire content is the \"patch\"\n }\n // Always count additions for statistics\n const fileContent = includeContext ? content : fs.readFileSync(filePath, 'utf8');\n additions = fileContent!.split('\\n').length;\n }\n } catch {\n // Skip binary or unreadable files\n }\n }\n\n // For removed files, we can't easily count the lines without the previous version\n if (status === 'removed') {\n deletions = 1; // Placeholder - in real git we'd need the previous version\n }\n } catch (error) {\n console.error(`Error analyzing file change for ${filename}:`, error);\n }\n\n return {\n filename,\n status,\n additions,\n deletions,\n changes: additions + deletions,\n content,\n patch,\n };\n }\n\n private generateTitle(status: import('simple-git').StatusResult, branch: string): string {\n if (status.files.length === 0) {\n return `Local Analysis: ${branch} (No changes)`;\n }\n\n const changeTypes = [];\n if (status.created.length > 0) changeTypes.push(`${status.created.length} added`);\n if (status.modified.length > 0) changeTypes.push(`${status.modified.length} modified`);\n if (status.deleted.length > 0) changeTypes.push(`${status.deleted.length} deleted`);\n if (status.renamed.length > 0) changeTypes.push(`${status.renamed.length} renamed`);\n\n return `Local Analysis: ${branch} (${changeTypes.join(', ')})`;\n }\n\n private generateDescription(\n status: import('simple-git').StatusResult,\n lastCommit: import('simple-git').DefaultLogFields | null\n ): string {\n let description = `Analysis of local git repository working directory.\\n\\n`;\n\n if (lastCommit) {\n description += `**Last Commit:** ${lastCommit.message}\\n`;\n description += `**Author:** ${lastCommit.author_name} <${lastCommit.author_email}>\\n`;\n description += `**Date:** ${lastCommit.date}\\n\\n`;\n }\n\n if (status.files.length === 0) {\n description += `**Status:** Working directory is clean - no uncommitted changes found.\\n`;\n } else {\n description += `**Changes Summary:**\\n`;\n description += `- Files to be committed: ${status.staged.length}\\n`;\n description += `- Modified files: ${status.modified.length}\\n`;\n description += `- Untracked files: ${status.not_added.length}\\n`;\n\n if (status.conflicted.length > 0) {\n description += `- Conflicted files: ${status.conflicted.length}\\n`;\n }\n }\n\n return description;\n }\n\n private createEmptyRepositoryInfo(reason: string): GitRepositoryInfo {\n return {\n title: `Local Analysis: ${reason}`,\n body: `Unable to analyze repository: ${reason}`,\n author: 'system',\n base: 'main',\n head: 'HEAD',\n files: [],\n totalAdditions: 0,\n totalDeletions: 0,\n isGitRepository: false,\n workingDirectory: this.cwd,\n };\n }\n}\n","import { PRInfo } from '../pr-analyzer';\nimport { ReviewSummary } from '../reviewer';\nimport { EnvConfig } from '../types/config';\n\n/**\n * Configuration for a check provider\n */\nexport interface CheckProviderConfig {\n type: string;\n prompt?: string;\n eventContext?: Record<string, unknown>;\n focus?: string;\n command?: string; // For PR comment triggers\n exec?: string; // For command execution (supports Liquid templates)\n stdin?: string; // Optional stdin input (supports Liquid templates)\n args?: string[]; // Deprecated: use exec with inline args instead\n interpreter?: string;\n url?: string;\n method?: string;\n headers?: Record<string, string>;\n timeout?: number;\n metadata?: Record<string, unknown>;\n workingDirectory?: string;\n env?: EnvConfig;\n ai?: import('../types/config').AIProviderConfig;\n /** AI model to use for this check - overrides global setting */\n ai_model?: string;\n /** AI provider to use for this check - overrides global setting */\n ai_provider?: 'google' | 'anthropic' | 'openai' | string;\n /** Check name for sessionID and logging purposes */\n checkName?: string;\n /** Session ID for AI session management */\n sessionId?: string;\n [key: string]: unknown;\n}\n\n/**\n * Abstract base class for all check providers\n * Implementing classes provide specific check functionality (AI, tool, script, etc.)\n */\nexport abstract class CheckProvider {\n /**\n * Get the unique name/type of this provider\n */\n abstract getName(): string;\n\n /**\n * Get a human-readable description of this provider\n */\n abstract getDescription(): string;\n\n /**\n * Validate provider-specific configuration\n * @param config The configuration to validate\n * @returns true if configuration is valid, false otherwise\n */\n abstract validateConfig(config: unknown): Promise<boolean>;\n\n /**\n * Execute the check on the given PR information\n * @param prInfo Information about the pull request\n * @param config Provider-specific configuration\n * @param dependencyResults Optional results from dependency checks that this check depends on\n * @param sessionInfo Optional session information for AI session reuse\n * @returns Review summary with scores, issues, and comments\n */\n abstract execute(\n prInfo: PRInfo,\n config: CheckProviderConfig,\n dependencyResults?: Map<string, ReviewSummary>,\n sessionInfo?: { parentSessionId?: string; reuseSession?: boolean }\n ): Promise<ReviewSummary>;\n\n /**\n * Get the list of configuration keys this provider supports\n * Used for documentation and validation\n */\n abstract getSupportedConfigKeys(): string[];\n\n /**\n * Check if this provider is available (e.g., has required API keys)\n * @returns true if provider can be used, false otherwise\n */\n abstract isAvailable(): Promise<boolean>;\n\n /**\n * Get provider requirements (e.g., environment variables needed)\n */\n abstract getRequirements(): string[];\n\n /**\n * Set webhook context for providers that need access to webhook data\n * This is optional and only used by http_input providers\n * @param webhookContext Map of endpoint paths to webhook data\n */\n setWebhookContext?(webhookContext: Map<string, unknown>): void;\n}\n","/**\n * Environment variable resolution utilities\n * Supports GitHub Actions-like syntax for referencing environment variables\n */\n\nimport { EnvConfig } from '../types/config';\n\n/**\n * Resolves environment variables in configuration values\n * Supports the following syntaxes:\n * - ${{ env.VARIABLE_NAME }} (GitHub Actions style)\n * - ${VARIABLE_NAME} (shell style)\n * - $VARIABLE_NAME (simple shell style)\n * - Direct environment variable names\n */\nexport class EnvironmentResolver {\n /**\n * Resolves a single configuration value that may contain environment variable references\n */\n static resolveValue(value: string | number | boolean): string | number | boolean {\n if (typeof value !== 'string') {\n return value;\n }\n\n // GitHub Actions style: ${{ env.VARIABLE_NAME }}\n let resolved = value.replace(/\\$\\{\\{\\s*env\\.([A-Z_][A-Z0-9_]*)\\s*\\}\\}/g, (match, envVar) => {\n return process.env[envVar] || match;\n });\n\n // Shell style: ${VARIABLE_NAME}\n resolved = resolved.replace(/\\$\\{([A-Z_][A-Z0-9_]*)\\}/g, (match, envVar) => {\n return process.env[envVar] || match;\n });\n\n // Simple shell style: $VARIABLE_NAME\n resolved = resolved.replace(/\\$([A-Z_][A-Z0-9_]*)/g, (match, envVar) => {\n return process.env[envVar] || match;\n });\n\n return resolved;\n }\n\n /**\n * Resolves all environment variables in an EnvConfig object\n */\n static resolveEnvConfig(envConfig: EnvConfig): EnvConfig {\n const resolved: EnvConfig = {};\n\n for (const [key, value] of Object.entries(envConfig)) {\n resolved[key] = this.resolveValue(value);\n }\n\n return resolved;\n }\n\n /**\n * Applies environment configuration to the process environment\n * This allows checks to access their specific environment variables\n */\n static applyEnvConfig(envConfig: EnvConfig): void {\n const resolved = this.resolveEnvConfig(envConfig);\n\n for (const [key, value] of Object.entries(resolved)) {\n if (value !== undefined) {\n process.env[key] = String(value);\n }\n }\n }\n\n /**\n * Creates a temporary environment for a specific check execution\n * Returns a cleanup function to restore the original environment\n */\n static withTemporaryEnv<T>(envConfig: EnvConfig, callback: () => T | Promise<T>): T | Promise<T> {\n const resolved = this.resolveEnvConfig(envConfig);\n const originalValues: Record<string, string | undefined> = {};\n\n // Store original values and apply new ones\n for (const [key, value] of Object.entries(resolved)) {\n originalValues[key] = process.env[key];\n if (value !== undefined) {\n process.env[key] = String(value);\n }\n }\n\n try {\n const result = callback();\n\n // If callback returns a promise, handle cleanup after it resolves\n if (result instanceof Promise) {\n return result.finally(() => {\n // Restore original values\n for (const [key, originalValue] of Object.entries(originalValues)) {\n if (originalValue === undefined) {\n delete process.env[key];\n } else {\n process.env[key] = originalValue;\n }\n }\n });\n }\n\n // Restore original values immediately for sync callbacks\n for (const [key, originalValue] of Object.entries(originalValues)) {\n if (originalValue === undefined) {\n delete process.env[key];\n } else {\n process.env[key] = originalValue;\n }\n }\n\n return result;\n } catch (error) {\n // Restore original values on error\n for (const [key, originalValue] of Object.entries(originalValues)) {\n if (originalValue === undefined) {\n delete process.env[key];\n } else {\n process.env[key] = originalValue;\n }\n }\n throw error;\n }\n }\n\n /**\n * Validates that all required environment variables are available\n */\n static validateRequiredEnvVars(envConfig: EnvConfig, requiredVars: string[]): string[] {\n const resolved = this.resolveEnvConfig(envConfig);\n const missing: string[] = [];\n\n for (const varName of requiredVars) {\n const value = resolved[varName] || process.env[varName];\n if (!value) {\n missing.push(varName);\n }\n }\n\n return missing;\n }\n}\n","import * as fs from 'fs';\nimport * as path from 'path';\nimport { ReviewIssue } from './reviewer';\n\n/**\n * Filter for suppressing Visor issues based on special comments in code\n */\nexport class IssueFilter {\n private fileCache: Map<string, string[]> = new Map();\n private suppressionEnabled: boolean;\n\n constructor(suppressionEnabled: boolean = true) {\n this.suppressionEnabled = suppressionEnabled;\n }\n\n /**\n * Filter out issues that have suppression comments\n * @param issues Array of issues to filter\n * @param workingDir Working directory for resolving file paths\n * @returns Filtered array of issues with suppressed ones removed\n */\n public filterIssues(issues: ReviewIssue[], workingDir: string = process.cwd()): ReviewIssue[] {\n if (!this.suppressionEnabled || !issues || issues.length === 0) {\n return issues;\n }\n\n const filteredIssues: ReviewIssue[] = [];\n const suppressedCount: { [file: string]: number } = {};\n\n for (const issue of issues) {\n if (this.shouldSuppressIssue(issue, workingDir)) {\n // Track suppressed issues for logging\n suppressedCount[issue.file] = (suppressedCount[issue.file] || 0) + 1;\n } else {\n filteredIssues.push(issue);\n }\n }\n\n // Log suppression summary if any issues were suppressed\n const totalSuppressed = Object.values(suppressedCount).reduce((sum, count) => sum + count, 0);\n if (totalSuppressed > 0) {\n console.log(`🔇 Suppressed ${totalSuppressed} issue(s) via visor-disable comments:`);\n for (const [file, count] of Object.entries(suppressedCount)) {\n console.log(` - ${file}: ${count} issue(s)`);\n }\n }\n\n return filteredIssues;\n }\n\n /**\n * Check if an issue should be suppressed based on comments in the file\n */\n private shouldSuppressIssue(issue: ReviewIssue, workingDir: string): boolean {\n // Skip system-level issues or issues without file/line info\n if (!issue.file || issue.file === 'system' || issue.file === 'webhook' || issue.line === 0) {\n return false;\n }\n\n const lines = this.getFileLines(issue.file, workingDir);\n if (!lines || lines.length === 0) {\n return false;\n }\n\n // Check for file-level suppression (visor-disable-file in first 5 lines)\n const firstFiveLines = lines.slice(0, 5).join('\\n').toLowerCase();\n if (firstFiveLines.includes('visor-disable-file')) {\n return true;\n }\n\n // Check for line-level suppression (visor-disable within ±2 lines)\n const lineIndex = issue.line - 1; // Convert to 0-based index\n const startLine = Math.max(0, lineIndex - 2);\n const endLine = Math.min(lines.length - 1, lineIndex + 2);\n\n for (let i = startLine; i <= endLine; i++) {\n if (lines[i].toLowerCase().includes('visor-disable')) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Get file lines from cache or read from disk\n */\n private getFileLines(filePath: string, workingDir: string): string[] | null {\n // Check cache first\n if (this.fileCache.has(filePath)) {\n return this.fileCache.get(filePath)!;\n }\n\n try {\n // Resolve the file path\n const resolvedPath = path.isAbsolute(filePath) ? filePath : path.join(workingDir, filePath);\n\n if (!fs.existsSync(resolvedPath)) {\n // Try without working directory if the file doesn't exist\n if (fs.existsSync(filePath)) {\n const content = fs.readFileSync(filePath, 'utf8');\n const lines = content.split('\\n');\n this.fileCache.set(filePath, lines);\n return lines;\n }\n return null;\n }\n\n const content = fs.readFileSync(resolvedPath, 'utf8');\n const lines = content.split('\\n');\n this.fileCache.set(filePath, lines);\n return lines;\n } catch {\n // Silently skip files that can't be read\n return null;\n }\n }\n\n /**\n * Clear the file cache (useful for testing or long-running processes)\n */\n public clearCache(): void {\n this.fileCache.clear();\n }\n}\n","import { CheckProvider, CheckProviderConfig } from './check-provider.interface';\nimport { PRInfo } from '../pr-analyzer';\nimport { ReviewSummary } from '../reviewer';\nimport { AIReviewService, AIReviewConfig } from '../ai-review-service';\nimport { EnvironmentResolver } from '../utils/env-resolver';\nimport { IssueFilter } from '../issue-filter';\nimport { Liquid } from 'liquidjs';\nimport { createExtendedLiquid } from '../liquid-extensions';\nimport fs from 'fs/promises';\nimport path from 'path';\n\n/**\n * AI-powered check provider using probe agent\n */\nexport class AICheckProvider extends CheckProvider {\n private aiReviewService: AIReviewService;\n private liquidEngine: Liquid;\n\n constructor() {\n super();\n this.aiReviewService = new AIReviewService();\n this.liquidEngine = createExtendedLiquid();\n }\n\n getName(): string {\n return 'ai';\n }\n\n getDescription(): string {\n return 'AI-powered code review using Google Gemini, Anthropic Claude, OpenAI GPT, or AWS Bedrock models';\n }\n\n async validateConfig(config: unknown): Promise<boolean> {\n if (!config || typeof config !== 'object') {\n return false;\n }\n\n const cfg = config as CheckProviderConfig;\n\n // Type must be 'ai'\n if (cfg.type !== 'ai') {\n return false;\n }\n\n // Check for prompt or focus\n const prompt = cfg.prompt || cfg.focus;\n if (typeof prompt !== 'string') {\n return false;\n }\n\n // Validate focus if specified\n if (cfg.focus && !['security', 'performance', 'style', 'all'].includes(cfg.focus as string)) {\n return false;\n }\n\n // Validate AI provider config if present\n if (cfg.ai) {\n if (\n cfg.ai.provider &&\n !['google', 'anthropic', 'openai', 'bedrock', 'mock'].includes(cfg.ai.provider as string)\n ) {\n return false;\n }\n\n // Validate mcpServers if present\n if (cfg.ai.mcpServers) {\n if (!this.validateMcpServers(cfg.ai.mcpServers)) {\n return false;\n }\n }\n }\n\n // Validate check-level MCP servers if present\n const checkLevelMcpServers = (cfg as CheckProviderConfig & { ai_mcp_servers?: unknown })\n .ai_mcp_servers;\n if (checkLevelMcpServers) {\n if (!this.validateMcpServers(checkLevelMcpServers)) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * Validate MCP servers configuration\n */\n private validateMcpServers(mcpServers: unknown): boolean {\n if (typeof mcpServers !== 'object' || mcpServers === null) {\n return false;\n }\n\n for (const serverConfig of Object.values(mcpServers)) {\n if (!serverConfig || typeof serverConfig !== 'object') {\n return false;\n }\n const config = serverConfig as { command?: unknown; args?: unknown };\n if (typeof config.command !== 'string') {\n return false;\n }\n if (config.args !== undefined && !Array.isArray(config.args)) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * Group files by their file extension for template context\n */\n private groupFilesByExtension(\n files: import('../pr-analyzer').PRFile[]\n ): Record<string, import('../pr-analyzer').PRFile[]> {\n const grouped: Record<string, import('../pr-analyzer').PRFile[]> = {};\n\n files.forEach(file => {\n const parts = file.filename.split('.');\n const ext = parts.length > 1 ? parts.pop()?.toLowerCase() || 'noext' : 'noext';\n if (!grouped[ext]) {\n grouped[ext] = [];\n }\n grouped[ext].push(file);\n });\n\n return grouped;\n }\n\n /**\n * Process prompt configuration to resolve final prompt string\n */\n private async processPrompt(\n promptConfig: string,\n prInfo: PRInfo,\n eventContext?: Record<string, unknown>,\n dependencyResults?: Map<string, ReviewSummary>\n ): Promise<string> {\n let promptContent: string;\n\n // Auto-detect if it's a file path or inline content\n if (await this.isFilePath(promptConfig)) {\n promptContent = await this.loadPromptFromFile(promptConfig);\n } else {\n promptContent = promptConfig;\n }\n\n // Process Liquid templates in the prompt\n return await this.renderPromptTemplate(promptContent, prInfo, eventContext, dependencyResults);\n }\n\n /**\n * Detect if a string is likely a file path and if the file exists\n */\n private async isFilePath(str: string): Promise<boolean> {\n // Quick checks to exclude obvious non-file-path content\n if (!str || str.trim() !== str || str.length > 512) {\n return false;\n }\n\n // Exclude strings that are clearly content (contain common content indicators)\n // But be more careful with paths that might contain common words as directory names\n if (\n /\\s{2,}/.test(str) || // Multiple consecutive spaces\n /\\n/.test(str) || // Contains newlines\n /^(please|analyze|review|check|find|identify|look|search)/i.test(str.trim()) || // Starts with command words\n str.split(' ').length > 8 // Too many words for a typical file path\n ) {\n return false;\n }\n\n // For strings with path separators, be more lenient about common words\n // as they might be legitimate directory names\n if (!/[\\/\\\\]/.test(str)) {\n // Only apply strict English word filter to non-path strings\n if (/\\b(the|and|or|but|for|with|by|from|in|on|at|as)\\b/i.test(str)) {\n return false;\n }\n }\n\n // Positive indicators for file paths\n const hasFileExtension = /\\.[a-zA-Z0-9]{1,10}$/i.test(str);\n const hasPathSeparators = /[\\/\\\\]/.test(str);\n const isRelativePath = /^\\.{1,2}\\//.test(str);\n const isAbsolutePath = path.isAbsolute(str);\n const hasTypicalFileChars = /^[a-zA-Z0-9._\\-\\/\\\\:~]+$/.test(str);\n\n // Must have at least one strong indicator\n if (!(hasFileExtension || isRelativePath || isAbsolutePath || hasPathSeparators)) {\n return false;\n }\n\n // Must contain only typical file path characters\n if (!hasTypicalFileChars) {\n return false;\n }\n\n // Additional validation for suspected file paths\n try {\n // Try to resolve and check if file exists\n let resolvedPath: string;\n\n if (path.isAbsolute(str)) {\n resolvedPath = path.normalize(str);\n } else {\n // Resolve relative to current working directory\n resolvedPath = path.resolve(process.cwd(), str);\n }\n\n // Check if file exists\n const fs = require('fs').promises;\n try {\n const stat = await fs.stat(resolvedPath);\n return stat.isFile();\n } catch {\n // File doesn't exist, but might still be a valid file path format\n // Return true if it has strong file path indicators\n return hasFileExtension && (isRelativePath || isAbsolutePath || hasPathSeparators);\n }\n } catch {\n return false;\n }\n }\n\n /**\n * Load prompt content from file with security validation\n */\n private async loadPromptFromFile(promptPath: string): Promise<string> {\n // Enforce .liquid file extension for all prompt files\n if (!promptPath.endsWith('.liquid')) {\n throw new Error('Prompt file must have .liquid extension');\n }\n\n let resolvedPath: string;\n\n if (path.isAbsolute(promptPath)) {\n // Absolute path - use as-is\n resolvedPath = promptPath;\n } else {\n // Relative path - resolve relative to current working directory\n resolvedPath = path.resolve(process.cwd(), promptPath);\n }\n\n // Security: For relative paths, ensure they don't escape the current directory\n if (!path.isAbsolute(promptPath)) {\n const normalizedPath = path.normalize(resolvedPath);\n const currentDir = path.resolve(process.cwd());\n if (!normalizedPath.startsWith(currentDir)) {\n throw new Error('Invalid prompt file path: path traversal detected');\n }\n }\n\n // Security: Check for obvious path traversal patterns\n if (promptPath.includes('../..')) {\n throw new Error('Invalid prompt file path: path traversal detected');\n }\n\n try {\n const promptContent = await fs.readFile(resolvedPath, 'utf-8');\n return promptContent;\n } catch (error) {\n throw new Error(\n `Failed to load prompt from ${resolvedPath}: ${\n error instanceof Error ? error.message : 'Unknown error'\n }`\n );\n }\n }\n\n /**\n * Render Liquid template in prompt with comprehensive event context\n */\n private async renderPromptTemplate(\n promptContent: string,\n prInfo: PRInfo,\n eventContext?: Record<string, unknown>,\n dependencyResults?: Map<string, ReviewSummary>\n ): Promise<string> {\n // Create comprehensive template context with PR and event information\n const templateContext = {\n // PR Information\n pr: {\n number: prInfo.number,\n title: prInfo.title,\n body: prInfo.body,\n author: prInfo.author,\n baseBranch: prInfo.base,\n headBranch: prInfo.head,\n isIncremental: prInfo.isIncremental,\n filesChanged: prInfo.files?.map(f => f.filename) || [],\n totalAdditions: prInfo.files?.reduce((sum, f) => sum + f.additions, 0) || 0,\n totalDeletions: prInfo.files?.reduce((sum, f) => sum + f.deletions, 0) || 0,\n totalChanges: prInfo.files?.reduce((sum, f) => sum + f.changes, 0) || 0,\n base: prInfo.base,\n head: prInfo.head,\n },\n\n // File Details\n files: prInfo.files || [],\n description: prInfo.body || '',\n\n // GitHub Event Context\n event: eventContext\n ? {\n name: eventContext.event_name || 'unknown',\n action: eventContext.action,\n isPullRequest: !prInfo.isIssue, // Set based on whether this is a PR or an issue\n\n // Repository Info\n repository: eventContext.repository\n ? {\n owner: (eventContext.repository as { owner?: { login?: string } })?.owner?.login,\n name: (eventContext.repository as { name?: string })?.name,\n fullName: eventContext.repository\n ? `${(eventContext.repository as { owner?: { login?: string } })?.owner?.login}/${(eventContext.repository as { name?: string })?.name}`\n : undefined,\n }\n : undefined,\n\n // Comment Data (for comment events)\n comment: eventContext.comment\n ? {\n body: (eventContext.comment as { body?: string })?.body,\n author: (eventContext.comment as { user?: { login?: string } })?.user?.login,\n }\n : undefined,\n\n // Issue Data (for issue events)\n issue: eventContext.issue\n ? {\n number: (eventContext.issue as { number?: number })?.number,\n title: (eventContext.issue as { title?: string })?.title,\n body: (eventContext.issue as { body?: string })?.body,\n state: (eventContext.issue as { state?: string })?.state,\n author: (eventContext.issue as { user?: { login?: string } })?.user?.login,\n labels: (eventContext.issue as { labels?: unknown[] })?.labels || [],\n assignees:\n (\n eventContext as { issue?: { assignees?: Array<{ login: string }> } }\n )?.issue?.assignees?.map(a => a.login) || [],\n createdAt: (eventContext.issue as { created_at?: string })?.created_at,\n updatedAt: (eventContext.issue as { updated_at?: string })?.updated_at,\n isPullRequest: !!(eventContext.issue as { pull_request?: unknown })?.pull_request,\n }\n : undefined,\n\n // Pull Request Event Data\n pullRequest: eventContext.pull_request\n ? {\n number: (eventContext.pull_request as { number?: number })?.number,\n state: (eventContext.pull_request as { state?: string })?.state,\n draft: (eventContext.pull_request as { draft?: boolean })?.draft,\n headSha: (eventContext.pull_request as { head?: { sha?: string } })?.head?.sha,\n headRef: (eventContext.pull_request as { head?: { ref?: string } })?.head?.ref,\n baseSha: (eventContext.pull_request as { base?: { sha?: string } })?.base?.sha,\n baseRef: (eventContext.pull_request as { base?: { ref?: string } })?.base?.ref,\n }\n : undefined,\n\n // Raw event payload for advanced use cases\n payload: eventContext,\n }\n : undefined,\n\n // Utility data for templates\n utils: {\n // Date/time helpers\n now: new Date().toISOString(),\n today: new Date().toISOString().split('T')[0],\n\n // Dynamic file grouping by extension\n filesByExtension: this.groupFilesByExtension(prInfo.files || []),\n\n // File status categorizations\n addedFiles: (prInfo.files || []).filter(f => f.status === 'added'),\n modifiedFiles: (prInfo.files || []).filter(f => f.status === 'modified'),\n removedFiles: (prInfo.files || []).filter(f => f.status === 'removed'),\n renamedFiles: (prInfo.files || []).filter(f => f.status === 'renamed'),\n\n // Change analysis\n hasLargeChanges: (prInfo.files || []).some(f => f.changes > 50),\n totalFiles: (prInfo.files || []).length,\n },\n\n // Previous check outputs (dependency results)\n // Expose raw output directly if available, otherwise expose the result as-is\n outputs: dependencyResults\n ? Object.fromEntries(\n Array.from(dependencyResults.entries()).map(([checkName, result]) => [\n checkName,\n (() => {\n const summary = result as ReviewSummary & { output?: unknown };\n return summary.output !== undefined ? summary.output : summary;\n })(),\n ])\n )\n : {},\n };\n\n try {\n return await this.liquidEngine.parseAndRender(promptContent, templateContext);\n } catch (error) {\n throw new Error(\n `Failed to render prompt template: ${\n error instanceof Error ? error.message : 'Unknown error'\n }`\n );\n }\n }\n\n async execute(\n prInfo: PRInfo,\n config: CheckProviderConfig,\n _dependencyResults?: Map<string, ReviewSummary>,\n sessionInfo?: { parentSessionId?: string; reuseSession?: boolean }\n ): Promise<ReviewSummary> {\n // Apply environment configuration if present\n if (config.env) {\n const result = EnvironmentResolver.withTemporaryEnv(config.env, () => {\n // This will be executed with the temporary environment\n return this.executeWithConfig(prInfo, config, _dependencyResults, sessionInfo);\n });\n\n if (result instanceof Promise) {\n return result;\n }\n return result;\n }\n\n return this.executeWithConfig(prInfo, config, _dependencyResults, sessionInfo);\n }\n\n private async executeWithConfig(\n prInfo: PRInfo,\n config: CheckProviderConfig,\n _dependencyResults?: Map<string, ReviewSummary>,\n sessionInfo?: { parentSessionId?: string; reuseSession?: boolean }\n ): Promise<ReviewSummary> {\n // Extract AI configuration - only set properties that are explicitly provided\n const aiConfig: AIReviewConfig = {};\n\n // Check-level AI configuration (ai object)\n if (config.ai) {\n // Only set properties that are actually defined to avoid overriding env vars\n if (config.ai.apiKey !== undefined) {\n aiConfig.apiKey = config.ai.apiKey as string;\n }\n if (config.ai.model !== undefined) {\n aiConfig.model = config.ai.model as string;\n }\n if (config.ai.timeout !== undefined) {\n aiConfig.timeout = config.ai.timeout as number;\n }\n if (config.ai.provider !== undefined) {\n aiConfig.provider = config.ai.provider as\n | 'google'\n | 'anthropic'\n | 'openai'\n | 'bedrock'\n | 'mock';\n }\n if (config.ai.debug !== undefined) {\n aiConfig.debug = config.ai.debug as boolean;\n }\n }\n\n // Check-level AI model and provider (top-level properties)\n if (config.ai_model !== undefined) {\n aiConfig.model = config.ai_model as string;\n }\n if (config.ai_provider !== undefined) {\n aiConfig.provider = config.ai_provider as\n | 'google'\n | 'anthropic'\n | 'openai'\n | 'bedrock'\n | 'mock';\n }\n\n // Get custom prompt from config - REQUIRED, no fallbacks\n const customPrompt = config.prompt;\n\n if (!customPrompt) {\n throw new Error(\n `No prompt defined for check. All checks must have prompts defined in .visor.yaml configuration.`\n );\n }\n\n // Setup MCP tools from multiple configuration levels\n const mcpServers: Record<string, import('../types/config').McpServerConfig> = {};\n\n // 1. Start with global MCP servers (from visor config root)\n const globalConfig = config as CheckProviderConfig & {\n ai_mcp_servers?: Record<string, import('../types/config').McpServerConfig>;\n };\n if (globalConfig.ai_mcp_servers) {\n Object.assign(mcpServers, globalConfig.ai_mcp_servers);\n }\n\n // 2. Add check-level MCP servers (overrides global)\n if (config.ai_mcp_servers) {\n Object.assign(mcpServers, config.ai_mcp_servers);\n }\n\n // 3. Add ai.mcpServers (overrides everything)\n if (config.ai?.mcpServers) {\n Object.assign(mcpServers, config.ai.mcpServers);\n }\n\n // Pass MCP server config directly to AI service\n if (Object.keys(mcpServers).length > 0) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (aiConfig as any).mcpServers = mcpServers;\n if (aiConfig.debug) {\n console.error(\n `🔧 Debug: AI check MCP configured with ${Object.keys(mcpServers).length} servers`\n );\n }\n }\n\n // Process prompt with Liquid templates and file loading\n const processedPrompt = await this.processPrompt(\n customPrompt,\n prInfo,\n config.eventContext,\n _dependencyResults\n );\n\n // Create AI service with config - environment variables will be used if aiConfig is empty\n const service = new AIReviewService(aiConfig);\n\n // Pass the custom prompt and schema - no fallbacks\n const schema = config.schema as string | Record<string, unknown> | undefined;\n\n // Only output debug messages if debug mode is enabled\n if (aiConfig.debug) {\n console.error(\n `🔧 Debug: AICheckProvider using processed prompt: ${processedPrompt.substring(0, 100)}...`\n );\n console.error(`🔧 Debug: AICheckProvider schema from config: ${JSON.stringify(schema)}`);\n console.error(`🔧 Debug: AICheckProvider full config: ${JSON.stringify(config, null, 2)}`);\n }\n\n try {\n if (aiConfig.debug) {\n console.error(\n `🔧 Debug: AICheckProvider passing checkName: ${config.checkName} to service`\n );\n }\n\n let result: ReviewSummary;\n\n // Check if we should use session reuse\n if (sessionInfo?.reuseSession && sessionInfo.parentSessionId) {\n if (aiConfig.debug) {\n console.error(\n `🔄 Debug: Using session reuse with parent session: ${sessionInfo.parentSessionId}`\n );\n }\n result = await service.executeReviewWithSessionReuse(\n prInfo,\n processedPrompt,\n sessionInfo.parentSessionId,\n schema,\n config.checkName\n );\n } else {\n if (aiConfig.debug) {\n console.error(`🆕 Debug: Creating new AI session for check: ${config.checkName}`);\n }\n result = await service.executeReview(\n prInfo,\n processedPrompt,\n schema,\n config.checkName,\n config.sessionId\n );\n }\n\n // Apply issue suppression filtering\n const suppressionEnabled = config.suppressionEnabled !== false;\n const issueFilter = new IssueFilter(suppressionEnabled);\n const filteredIssues = issueFilter.filterIssues(result.issues || [], process.cwd());\n\n return {\n ...result,\n issues: filteredIssues,\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n // Log detailed error information\n console.error(`❌ AI Check Provider Error for check: ${errorMessage}`);\n\n // Check if this is a critical error (authentication, rate limits, etc)\n const isCriticalError =\n errorMessage.includes('API rate limit') ||\n errorMessage.includes('403') ||\n errorMessage.includes('401') ||\n errorMessage.includes('authentication') ||\n errorMessage.includes('API key');\n\n if (isCriticalError) {\n console.error(`🚨 CRITICAL ERROR: AI provider authentication or rate limit issue detected`);\n console.error(`🚨 This check cannot proceed without valid API credentials`);\n }\n\n // Re-throw with more context\n throw new Error(`AI analysis failed: ${errorMessage}`);\n }\n }\n\n getSupportedConfigKeys(): string[] {\n return [\n 'type',\n 'prompt',\n 'focus',\n 'schema',\n 'group',\n 'ai.provider',\n 'ai.model',\n 'ai.apiKey',\n 'ai.timeout',\n 'ai.mcpServers',\n 'ai_model',\n 'ai_provider',\n 'ai_mcp_servers',\n 'env',\n ];\n }\n\n async isAvailable(): Promise<boolean> {\n // Check if any AI API key is available\n return !!(\n process.env.GOOGLE_API_KEY ||\n process.env.ANTHROPIC_API_KEY ||\n process.env.OPENAI_API_KEY ||\n // AWS Bedrock credentials check\n (process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY) ||\n process.env.AWS_BEDROCK_API_KEY\n );\n }\n\n getRequirements(): string[] {\n return [\n 'At least one of: GOOGLE_API_KEY, ANTHROPIC_API_KEY, OPENAI_API_KEY, or AWS credentials (AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY)',\n 'Optional: MODEL_NAME environment variable',\n 'Optional: AWS_REGION for Bedrock provider',\n 'Network access to AI provider APIs',\n ];\n }\n}\n","import { CheckProvider, CheckProviderConfig } from './check-provider.interface';\nimport { PRInfo } from '../pr-analyzer';\nimport { ReviewSummary, ReviewIssue } from '../reviewer';\nimport { IssueFilter } from '../issue-filter';\nimport { Liquid } from 'liquidjs';\nimport { createExtendedLiquid } from '../liquid-extensions';\n\n/**\n * Check provider that sends data to an HTTP endpoint, typically used as an output/notification provider\n */\nexport class HttpCheckProvider extends CheckProvider {\n private liquid: Liquid;\n\n constructor() {\n super();\n this.liquid = createExtendedLiquid();\n }\n getName(): string {\n return 'http';\n }\n\n getDescription(): string {\n return 'Send data to external HTTP endpoint for notifications or integration';\n }\n\n async validateConfig(config: unknown): Promise<boolean> {\n if (!config || typeof config !== 'object') {\n return false;\n }\n\n const cfg = config as CheckProviderConfig;\n\n // Type must be 'http'\n if (cfg.type !== 'http') {\n return false;\n }\n\n // Must have URL specified\n if (typeof cfg.url !== 'string' || !cfg.url) {\n return false;\n }\n\n // Must have body template specified\n if (typeof cfg.body !== 'string' || !cfg.body) {\n return false;\n }\n\n // Validate URL format\n try {\n new URL(cfg.url as string);\n return true;\n } catch {\n return false;\n }\n }\n\n async execute(\n prInfo: PRInfo,\n config: CheckProviderConfig,\n dependencyResults?: Map<string, ReviewSummary>,\n _sessionInfo?: { parentSessionId?: string; reuseSession?: boolean }\n ): Promise<ReviewSummary> {\n const url = config.url as string;\n const bodyTemplate = config.body as string;\n const method = (config.method as string) || 'POST';\n const headers = (config.headers as Record<string, string>) || {};\n const timeout = (config.timeout as number) || 30000;\n\n // Prepare template context with all available data\n const templateContext = {\n pr: {\n number: prInfo.number,\n title: prInfo.title,\n body: prInfo.body,\n author: prInfo.author,\n base: prInfo.base,\n head: prInfo.head,\n totalAdditions: prInfo.totalAdditions,\n totalDeletions: prInfo.totalDeletions,\n },\n files: prInfo.files.map(f => ({\n filename: f.filename,\n status: f.status,\n additions: f.additions,\n deletions: f.deletions,\n changes: f.changes,\n patch: f.patch,\n })),\n outputs: dependencyResults ? Object.fromEntries(dependencyResults) : {},\n metadata: config.metadata || {},\n };\n\n // Render the body template\n let payload: Record<string, unknown>;\n try {\n const renderedBody = await this.liquid.parseAndRender(bodyTemplate, templateContext);\n // Try to parse as JSON, otherwise send as plain text\n try {\n payload = JSON.parse(renderedBody);\n } catch {\n payload = { message: renderedBody };\n }\n } catch (error) {\n return this.createErrorResult(\n url,\n new Error(\n `Template rendering failed: ${error instanceof Error ? error.message : 'Unknown error'}`\n )\n );\n }\n\n try {\n // Send webhook request\n const response = await this.sendWebhookRequest(url, method, headers, payload, timeout);\n\n // Parse webhook response\n const result = this.parseWebhookResponse(response, url);\n\n // Apply issue suppression filtering\n const suppressionEnabled = config.suppressionEnabled !== false;\n const issueFilter = new IssueFilter(suppressionEnabled);\n const filteredIssues = issueFilter.filterIssues(result.issues || [], process.cwd());\n\n return {\n ...result,\n issues: filteredIssues,\n };\n } catch (error) {\n return this.createErrorResult(url, error);\n }\n }\n\n private async sendWebhookRequest(\n url: string,\n method: string,\n headers: Record<string, string>,\n payload: Record<string, unknown>,\n timeout: number\n ): Promise<Record<string, unknown>> {\n // Check if fetch is available (Node 18+)\n if (typeof fetch === 'undefined') {\n throw new Error('Webhook provider requires Node.js 18+ or node-fetch package');\n }\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n const response = await fetch(url, {\n method,\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n },\n body: JSON.stringify(payload),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n throw new Error(`Webhook returned ${response.status}: ${response.statusText}`);\n }\n\n return (await response.json()) as Record<string, unknown>;\n } catch (error: unknown) {\n clearTimeout(timeoutId);\n\n if (error instanceof Error && error.name === 'AbortError') {\n throw new Error(`Webhook request timed out after ${timeout}ms`);\n }\n\n throw error;\n }\n }\n\n private parseWebhookResponse(response: Record<string, unknown>, url: string): ReviewSummary {\n // Validate and normalize the webhook response\n if (!response || typeof response !== 'object') {\n return this.createErrorResult(url, new Error('Invalid webhook response format'));\n }\n\n const issues: ReviewIssue[] = Array.isArray(response.comments)\n ? (response.comments as Array<Record<string, unknown>>).map(c => ({\n file: (c.file as string) || 'unknown',\n line: (c.line as number) || 0,\n endLine: c.endLine as number | undefined,\n ruleId: (c.ruleId as string) || `webhook/${this.validateCategory(c.category)}`,\n message: (c.message as string) || '',\n severity: this.validateSeverity(c.severity),\n category: this.validateCategory(c.category),\n suggestion: c.suggestion as string | undefined,\n replacement: c.replacement as string | undefined,\n }))\n : [];\n\n return {\n issues,\n };\n }\n\n private createErrorResult(url: string, error: unknown): ReviewSummary {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n\n return {\n issues: [\n {\n file: 'webhook',\n line: 0,\n endLine: undefined,\n ruleId: 'webhook/error',\n message: `Webhook execution error: ${errorMessage}`,\n severity: 'error',\n category: 'logic',\n suggestion: undefined,\n replacement: undefined,\n },\n ],\n };\n }\n\n private validateSeverity(severity: unknown): 'info' | 'warning' | 'error' | 'critical' {\n const valid = ['info', 'warning', 'error', 'critical'];\n return valid.includes(severity as string)\n ? (severity as 'info' | 'warning' | 'error' | 'critical')\n : 'info';\n }\n\n private validateCategory(\n category: unknown\n ): 'security' | 'performance' | 'style' | 'logic' | 'documentation' {\n const valid = ['security', 'performance', 'style', 'logic', 'documentation'];\n return valid.includes(category as string)\n ? (category as 'security' | 'performance' | 'style' | 'logic' | 'documentation')\n : 'logic';\n }\n\n getSupportedConfigKeys(): string[] {\n return [\n 'type',\n 'url',\n 'body',\n 'method',\n 'headers',\n 'timeout',\n 'metadata',\n 'depends_on',\n 'on',\n 'if',\n 'group',\n 'schedule',\n ];\n }\n\n async isAvailable(): Promise<boolean> {\n // HTTP provider is available if fetch is available\n return typeof fetch !== 'undefined';\n }\n\n getRequirements(): string[] {\n return [\n 'Valid HTTP URL',\n 'Body template (Liquid) for payload construction',\n 'Network access to HTTP endpoint',\n 'Optional: Dependencies for accessing their outputs in templates',\n ];\n }\n}\n","import { CheckProvider, CheckProviderConfig } from './check-provider.interface';\nimport { PRInfo } from '../pr-analyzer';\nimport { ReviewSummary } from '../reviewer';\nimport { Liquid } from 'liquidjs';\nimport { createExtendedLiquid } from '../liquid-extensions';\nimport { logger } from '../logger';\n\n/**\n * Check provider that receives input from HTTP webhooks and makes it available to dependent checks\n */\nexport class HttpInputProvider extends CheckProvider {\n private liquid: Liquid;\n private webhookContext?: Map<string, unknown>;\n\n constructor() {\n super();\n this.liquid = createExtendedLiquid();\n }\n\n /**\n * Set webhook context for accessing webhook data\n */\n setWebhookContext(webhookContext: Map<string, unknown>): void {\n this.webhookContext = webhookContext;\n }\n\n getName(): string {\n return 'http_input';\n }\n\n getDescription(): string {\n return 'Receive and process HTTP webhook input data for use by dependent checks';\n }\n\n async validateConfig(config: unknown): Promise<boolean> {\n if (!config || typeof config !== 'object') {\n return false;\n }\n\n const cfg = config as CheckProviderConfig;\n\n // Type must be 'http_input'\n if (cfg.type !== 'http_input') {\n return false;\n }\n\n // Must have endpoint specified\n if (typeof cfg.endpoint !== 'string' || !cfg.endpoint) {\n return false;\n }\n\n // Transform is optional but must be string if provided\n if (cfg.transform !== undefined && typeof cfg.transform !== 'string') {\n return false;\n }\n\n return true;\n }\n\n async execute(\n prInfo: PRInfo,\n config: CheckProviderConfig,\n _dependencyResults?: Map<string, ReviewSummary>,\n _sessionInfo?: { parentSessionId?: string; reuseSession?: boolean }\n ): Promise<ReviewSummary> {\n const endpoint = config.endpoint as string;\n const transform = config.transform as string | undefined;\n\n // In actual implementation, this would receive data from the webhook server\n // For now, we'll check if there's webhook data in the execution context\n const webhookData = this.getWebhookData(endpoint);\n\n if (!webhookData) {\n return {\n issues: [],\n };\n }\n\n // Apply transformation if specified\n let processedData = webhookData;\n if (transform) {\n try {\n const templateContext = {\n webhook: webhookData,\n pr: {\n number: prInfo.number,\n title: prInfo.title,\n author: prInfo.author,\n base: prInfo.base,\n head: prInfo.head,\n },\n };\n const rendered = await this.liquid.parseAndRender(transform, templateContext);\n processedData = JSON.parse(rendered);\n logger.verbose(`✓ Applied webhook transform successfully`);\n } catch (error) {\n logger.error(\n `✗ Failed to transform webhook data: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n return {\n issues: [\n {\n file: 'webhook_input',\n line: 0,\n ruleId: 'webhook_input/transform_error',\n message: `Failed to transform webhook data: ${error instanceof Error ? error.message : 'Unknown error'}`,\n severity: 'error',\n category: 'logic',\n },\n ],\n };\n }\n }\n\n // Return the processed data as a custom field for dependent checks to access\n // This will be available in outputs for dependent checks\n return {\n issues: [],\n // Add custom data field that will be passed through\n data: processedData,\n } as ReviewSummary & { data: unknown };\n }\n\n private getWebhookData(endpoint: string): Record<string, unknown> | null {\n // Use webhook context if available (preferred method)\n if (this.webhookContext) {\n return (this.webhookContext.get(endpoint) as Record<string, unknown>) || null;\n }\n\n // Fallback to global store for backwards compatibility\n // This should be removed once all usages are migrated\n const globalWebhookStore = (global as Record<string, unknown>).__visor_webhook_data as\n | Map<string, Record<string, unknown>>\n | undefined;\n if (globalWebhookStore && globalWebhookStore.get) {\n console.warn(\n 'HttpInputProvider: Using deprecated global webhook store. Please use webhook context instead.'\n );\n return globalWebhookStore.get(endpoint) || null;\n }\n\n return null;\n }\n\n getSupportedConfigKeys(): string[] {\n return ['type', 'endpoint', 'transform', 'on', 'depends_on', 'if', 'group'];\n }\n\n async isAvailable(): Promise<boolean> {\n // Available if webhook server is configured and running\n return true;\n }\n\n getRequirements(): string[] {\n return [\n 'HTTP server must be configured and running',\n 'Valid endpoint path specified',\n 'Optional: Transform template for data processing',\n ];\n }\n}\n","import { CheckProvider, CheckProviderConfig } from './check-provider.interface';\nimport { PRInfo } from '../pr-analyzer';\nimport { ReviewSummary } from '../reviewer';\nimport { Liquid } from 'liquidjs';\nimport { createExtendedLiquid } from '../liquid-extensions';\n\n/**\n * Check provider that fetches data from HTTP endpoints\n */\nexport class HttpClientProvider extends CheckProvider {\n private liquid: Liquid;\n\n constructor() {\n super();\n this.liquid = createExtendedLiquid();\n }\n\n getName(): string {\n return 'http_client';\n }\n\n getDescription(): string {\n return 'Fetch data from HTTP endpoints for use by dependent checks';\n }\n\n async validateConfig(config: unknown): Promise<boolean> {\n if (!config || typeof config !== 'object') {\n return false;\n }\n\n const cfg = config as CheckProviderConfig;\n\n // Type must be 'http_client'\n if (cfg.type !== 'http_client') {\n return false;\n }\n\n // Must have URL specified\n if (typeof cfg.url !== 'string' || !cfg.url) {\n return false;\n }\n\n // Validate URL format\n try {\n new URL(cfg.url as string);\n return true;\n } catch {\n return false;\n }\n }\n\n async execute(\n prInfo: PRInfo,\n config: CheckProviderConfig,\n dependencyResults?: Map<string, ReviewSummary>,\n _sessionInfo?: { parentSessionId?: string; reuseSession?: boolean }\n ): Promise<ReviewSummary> {\n const url = config.url as string;\n const method = (config.method as string) || 'GET';\n const headers = (config.headers as Record<string, string>) || {};\n const timeout = (config.timeout as number) || 30000;\n const transform = config.transform as string | undefined;\n const bodyTemplate = config.body as string | undefined;\n\n try {\n // Prepare template context for URL and body\n const templateContext = {\n pr: {\n number: prInfo.number,\n title: prInfo.title,\n body: prInfo.body,\n author: prInfo.author,\n base: prInfo.base,\n head: prInfo.head,\n totalAdditions: prInfo.totalAdditions,\n totalDeletions: prInfo.totalDeletions,\n },\n outputs: dependencyResults ? Object.fromEntries(dependencyResults) : {},\n env: process.env,\n };\n\n // Render URL with template if it contains liquid syntax\n let renderedUrl = url;\n if (url.includes('{{') || url.includes('{%')) {\n renderedUrl = await this.liquid.parseAndRender(url, templateContext);\n }\n\n // Prepare request body if provided\n let requestBody: string | undefined;\n if (bodyTemplate) {\n const renderedBody = await this.liquid.parseAndRender(bodyTemplate, templateContext);\n requestBody = renderedBody;\n }\n\n // Fetch data from the endpoint\n const data = await this.fetchData(renderedUrl, method, headers, requestBody, timeout);\n\n // Apply transformation if specified\n let processedData = data;\n if (transform) {\n try {\n const transformContext = {\n response: data,\n pr: templateContext.pr,\n outputs: templateContext.outputs,\n };\n const rendered = await this.liquid.parseAndRender(transform, transformContext);\n // Try to parse as JSON if the transform result looks like JSON\n if (rendered.trim().startsWith('{') || rendered.trim().startsWith('[')) {\n processedData = JSON.parse(rendered);\n } else {\n processedData = rendered;\n }\n } catch (error) {\n return {\n issues: [\n {\n file: 'http_client',\n line: 0,\n ruleId: 'http_client/transform_error',\n message: `Failed to transform response data: ${error instanceof Error ? error.message : 'Unknown error'}`,\n severity: 'error',\n category: 'logic',\n },\n ],\n };\n }\n }\n\n // Return the fetched data as a custom field for dependent checks to access\n return {\n issues: [],\n // Add custom data field that will be passed through to dependent checks\n data: processedData,\n } as ReviewSummary & { data: unknown };\n } catch (error) {\n return {\n issues: [\n {\n file: 'http_client',\n line: 0,\n ruleId: 'http_client/fetch_error',\n message: `Failed to fetch from ${url}: ${error instanceof Error ? error.message : 'Unknown error'}`,\n severity: 'error',\n category: 'logic',\n },\n ],\n };\n }\n }\n\n private async fetchData(\n url: string,\n method: string,\n headers: Record<string, string>,\n body?: string,\n timeout: number = 30000\n ): Promise<unknown> {\n // Check if fetch is available (Node 18+)\n if (typeof fetch === 'undefined') {\n throw new Error('HTTP client provider requires Node.js 18+ or node-fetch package');\n }\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n const requestOptions: RequestInit = {\n method,\n headers: {\n ...headers,\n },\n signal: controller.signal,\n };\n\n // Add body for non-GET requests\n if (method !== 'GET' && body) {\n requestOptions.body = body;\n // Set Content-Type if not already set\n if (!headers['Content-Type'] && !headers['content-type']) {\n requestOptions.headers = {\n ...requestOptions.headers,\n 'Content-Type': 'application/json',\n };\n }\n }\n\n const response = await fetch(url, requestOptions);\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n // Try to parse as JSON first\n const contentType = response.headers.get('content-type');\n if (contentType && contentType.includes('application/json')) {\n return await response.json();\n }\n\n // Otherwise return as text\n const text = await response.text();\n\n // Try to parse as JSON if it looks like JSON\n if (text.trim().startsWith('{') || text.trim().startsWith('[')) {\n try {\n return JSON.parse(text);\n } catch {\n // Not JSON, return as text\n return text;\n }\n }\n\n return text;\n } catch (error: unknown) {\n clearTimeout(timeoutId);\n\n if (error instanceof Error && error.name === 'AbortError') {\n throw new Error(`Request timed out after ${timeout}ms`);\n }\n\n throw error;\n }\n }\n\n getSupportedConfigKeys(): string[] {\n return [\n 'type',\n 'url',\n 'method',\n 'headers',\n 'body',\n 'transform',\n 'timeout',\n 'depends_on',\n 'on',\n 'if',\n 'group',\n 'schedule',\n ];\n }\n\n async isAvailable(): Promise<boolean> {\n // HTTP client is available if fetch is available\n return typeof fetch !== 'undefined';\n }\n\n getRequirements(): string[] {\n return [\n 'Valid HTTP/HTTPS URL to fetch from',\n 'Network access to the endpoint',\n 'Optional: Transform template for processing response data',\n 'Optional: Body template for POST/PUT requests',\n ];\n }\n}\n","import { CheckProvider, CheckProviderConfig } from './check-provider.interface';\nimport { PRInfo } from '../pr-analyzer';\nimport { ReviewSummary } from '../reviewer';\n\n/**\n * No-operation check provider that doesn't perform any analysis.\n *\n * This provider is designed for command orchestration - it allows creating\n * checks that exist purely to trigger other checks through dependencies.\n *\n * Example use case: A \"/review\" command that triggers multiple analysis checks\n * without performing any analysis itself.\n */\nexport class NoopCheckProvider extends CheckProvider {\n getName(): string {\n return 'noop';\n }\n\n getDescription(): string {\n return 'No-operation provider for command orchestration and dependency triggering';\n }\n\n async validateConfig(config: unknown): Promise<boolean> {\n if (!config || typeof config !== 'object') {\n return false;\n }\n\n const cfg = config as CheckProviderConfig;\n\n // Type must be 'noop'\n if (cfg.type !== 'noop') {\n return false;\n }\n\n return true;\n }\n\n async execute(\n _prInfo: PRInfo,\n _config: CheckProviderConfig,\n _dependencyResults?: Map<string, ReviewSummary>,\n _sessionInfo?: { parentSessionId?: string; reuseSession?: boolean }\n ): Promise<ReviewSummary> {\n // Noop provider doesn't perform any analysis\n // It exists purely for command orchestration and dependency triggering\n return {\n issues: [],\n };\n }\n\n getSupportedConfigKeys(): string[] {\n return ['type', 'command', 'depends_on', 'on', 'if', 'group'];\n }\n\n async isAvailable(): Promise<boolean> {\n // Noop provider is always available\n return true;\n }\n\n getRequirements(): string[] {\n return [\n 'No external dependencies required',\n 'Used for command orchestration and dependency triggering',\n ];\n }\n}\n","import { CheckProvider, CheckProviderConfig } from './check-provider.interface';\nimport { PRInfo } from '../pr-analyzer';\nimport { ReviewSummary } from '../reviewer';\nimport { Liquid } from 'liquidjs';\nimport { createExtendedLiquid } from '../liquid-extensions';\nimport { logger } from '../logger';\n\n/**\n * Log levels supported by the log provider\n */\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error';\n\n/**\n * Check provider that outputs debugging and logging information.\n * Useful for troubleshooting check workflows and understanding execution flow.\n */\nexport class LogCheckProvider extends CheckProvider {\n private liquid: Liquid;\n\n constructor() {\n super();\n this.liquid = createExtendedLiquid({\n strictVariables: false,\n strictFilters: false,\n });\n }\n\n getName(): string {\n return 'log';\n }\n\n getDescription(): string {\n return 'Output debugging and logging information for troubleshooting check workflows';\n }\n\n async validateConfig(config: unknown): Promise<boolean> {\n if (!config || typeof config !== 'object') {\n return false;\n }\n\n const cfg = config as CheckProviderConfig;\n\n // Type must be 'log'\n if (cfg.type !== 'log') {\n return false;\n }\n\n // Message is required\n if (!cfg.message || typeof cfg.message !== 'string') {\n return false;\n }\n\n // Validate log level if provided\n if (cfg.level && !['debug', 'info', 'warn', 'error'].includes(cfg.level as string)) {\n return false;\n }\n\n return true;\n }\n\n async execute(\n prInfo: PRInfo,\n config: CheckProviderConfig,\n dependencyResults?: Map<string, ReviewSummary>,\n _sessionInfo?: { parentSessionId?: string; reuseSession?: boolean }\n ): Promise<ReviewSummary> {\n const message = config.message as string;\n const level = (config.level as LogLevel) || 'info';\n const includePrContext = config.include_pr_context !== false;\n const includeDependencies = config.include_dependencies !== false;\n const includeMetadata = config.include_metadata !== false;\n\n // Prepare template context\n const templateContext = this.buildTemplateContext(\n prInfo,\n dependencyResults,\n includePrContext,\n includeDependencies,\n includeMetadata\n );\n\n // Render the log message template\n const renderedMessage = await this.liquid.parseAndRender(message, templateContext);\n\n // Build the log output\n const logOutput = this.formatLogOutput(\n level,\n renderedMessage,\n templateContext,\n includePrContext,\n includeDependencies,\n includeMetadata\n );\n\n // Route through centralized logger to keep stdout clean in JSON/SARIF\n if (level === 'error') logger.error(logOutput);\n else if (level === 'warn') logger.warn(logOutput);\n else if (level === 'debug') logger.debug(logOutput);\n else logger.info(logOutput);\n\n // Return with the log content as custom data for dependent checks\n return {\n issues: [],\n // Add log output as custom field\n logOutput,\n } as ReviewSummary & { logOutput: string };\n }\n\n private buildTemplateContext(\n prInfo: PRInfo,\n dependencyResults?: Map<string, ReviewSummary>,\n _includePrContext: boolean = true,\n _includeDependencies: boolean = true,\n includeMetadata: boolean = true\n ): Record<string, unknown> {\n const context: Record<string, unknown> = {};\n\n // Always provide pr context for template rendering\n context.pr = {\n number: prInfo.number,\n title: prInfo.title,\n body: prInfo.body,\n author: prInfo.author,\n base: prInfo.base,\n head: prInfo.head,\n totalAdditions: prInfo.totalAdditions,\n totalDeletions: prInfo.totalDeletions,\n files: prInfo.files.map(f => ({\n filename: f.filename,\n status: f.status,\n additions: f.additions,\n deletions: f.deletions,\n changes: f.changes,\n })),\n };\n\n // Add convenience data\n context.filenames = prInfo.files.map(f => f.filename);\n context.fileCount = prInfo.files.length;\n\n // Always provide dependency data for template rendering\n if (dependencyResults) {\n const dependencies: Record<string, unknown> = {};\n const outputs: Record<string, unknown> = {};\n context.dependencyCount = dependencyResults.size;\n\n for (const [checkName, result] of dependencyResults.entries()) {\n dependencies[checkName] = {\n issueCount: result.issues?.length || 0,\n suggestionCount: 0,\n issues: result.issues || [],\n };\n\n // Add outputs namespace for accessing dependency results directly\n const summary = result as import('../reviewer').ReviewSummary & { output?: unknown };\n outputs[checkName] = summary.output !== undefined ? summary.output : summary;\n }\n\n context.dependencies = dependencies;\n context.outputs = outputs;\n }\n\n if (includeMetadata) {\n context.metadata = {\n timestamp: new Date().toISOString(),\n executionTime: Date.now(),\n nodeVersion: process.version,\n platform: process.platform,\n workingDirectory: process.cwd(),\n };\n }\n\n return context;\n }\n\n private formatLogOutput(\n level: LogLevel,\n message: string,\n templateContext: Record<string, unknown>,\n includePrContext: boolean,\n includeDependencies: boolean,\n includeMetadata: boolean\n ): string {\n const sections: string[] = [];\n\n // Log level and message\n const levelEmoji = this.getLevelEmoji(level);\n sections.push(`${levelEmoji} **${level.toUpperCase()}**: ${message}`);\n\n // PR context section\n if (includePrContext && templateContext.pr) {\n const pr = templateContext.pr as Record<string, unknown>;\n sections.push('');\n sections.push('### PR Context');\n sections.push(`- **PR #${pr.number}**: ${pr.title}`);\n sections.push(`- **Author**: ${pr.author}`);\n sections.push(`- **Base**: ${pr.base} → **Head**: ${pr.head}`);\n sections.push(`- **Changes**: +${pr.totalAdditions} -${pr.totalDeletions}`);\n sections.push(`- **Files Modified**: ${templateContext.fileCount}`);\n }\n\n // Dependencies section\n if (includeDependencies && templateContext.dependencies) {\n const deps = templateContext.dependencies as Record<string, Record<string, unknown>>;\n sections.push('');\n sections.push('### Dependency Results');\n\n if (Object.keys(deps).length === 0) {\n sections.push('- No dependency results available');\n } else {\n for (const [checkName, result] of Object.entries(deps)) {\n sections.push(\n `- **${checkName}**: ${result.issueCount} issues, ${result.suggestionCount} suggestions`\n );\n }\n }\n }\n\n // Metadata section\n if (includeMetadata && templateContext.metadata) {\n const meta = templateContext.metadata as Record<string, unknown>;\n sections.push('');\n sections.push('### Execution Metadata');\n sections.push(`- **Timestamp**: ${meta.timestamp}`);\n sections.push(`- **Node Version**: ${meta.nodeVersion}`);\n sections.push(`- **Platform**: ${meta.platform}`);\n sections.push(`- **Working Directory**: ${meta.workingDirectory}`);\n }\n\n return sections.join('\\n');\n }\n\n private getLevelEmoji(level: LogLevel): string {\n switch (level) {\n case 'debug':\n return '🐛';\n case 'info':\n return 'ℹ️';\n case 'warn':\n return '⚠️';\n case 'error':\n return '❌';\n default:\n return 'ℹ️';\n }\n }\n\n getSupportedConfigKeys(): string[] {\n return [\n 'type',\n 'message',\n 'level',\n 'include_pr_context',\n 'include_dependencies',\n 'include_metadata',\n 'group',\n 'command',\n 'depends_on',\n 'on',\n 'if',\n ];\n }\n\n async isAvailable(): Promise<boolean> {\n // Log provider is always available\n return true;\n }\n\n getRequirements(): string[] {\n return [\n 'No external dependencies required',\n 'Used for debugging and logging check execution flow',\n ];\n }\n}\n","import { CheckProvider, CheckProviderConfig } from './check-provider.interface';\nimport { PRInfo } from '../pr-analyzer';\nimport { ReviewSummary } from '../reviewer';\nimport { EnvironmentResolver } from '../utils/env-resolver';\nimport { IssueFilter } from '../issue-filter';\nimport { Liquid } from 'liquidjs';\nimport { createExtendedLiquid } from '../liquid-extensions';\nimport fs from 'fs/promises';\nimport path from 'path';\nimport {\n ClaudeCodeQuery,\n ClaudeCodeResponse,\n ClaudeCodeConfig,\n ClaudeCodeClient,\n safeImport,\n} from './claude-code-types';\n\ntype ClaudeCodeConstructor = new (options: { apiKey: string }) => ClaudeCodeClient;\n\nfunction isClaudeCodeConstructor(value: unknown): value is ClaudeCodeConstructor {\n return typeof value === 'function';\n}\n\n/**\n * Error thrown when Claude Code SDK is not installed\n */\nexport class ClaudeCodeSDKNotInstalledError extends Error {\n constructor() {\n super(\n 'Claude Code SDK is not installed. Install with: npm install @anthropic/claude-code-sdk @modelcontextprotocol/sdk'\n );\n this.name = 'ClaudeCodeSDKNotInstalledError';\n }\n}\n\n/**\n * Error thrown when Claude Code API key is not configured\n */\nexport class ClaudeCodeAPIKeyMissingError extends Error {\n constructor() {\n super(\n 'No API key found for Claude Code provider. Set CLAUDE_CODE_API_KEY or ANTHROPIC_API_KEY environment variable.'\n );\n this.name = 'ClaudeCodeAPIKeyMissingError';\n }\n}\n\n/**\n * Claude Code check provider using the Claude Code TypeScript SDK\n * Supports MCP tools and streaming responses\n */\nexport class ClaudeCodeCheckProvider extends CheckProvider {\n private liquidEngine: Liquid;\n private claudeCodeClient: ClaudeCodeClient | null = null;\n\n constructor() {\n super();\n this.liquidEngine = createExtendedLiquid();\n }\n\n getName(): string {\n return 'claude-code';\n }\n\n getDescription(): string {\n return 'AI-powered code review using Claude Code with MCP tools support';\n }\n\n async validateConfig(config: unknown): Promise<boolean> {\n if (!config || typeof config !== 'object') {\n return false;\n }\n\n const cfg = config as CheckProviderConfig;\n\n // Type must be 'claude-code'\n if (cfg.type !== 'claude-code') {\n return false;\n }\n\n // Check for prompt\n if (!cfg.prompt || typeof cfg.prompt !== 'string') {\n return false;\n }\n\n // Validate Claude Code specific configuration\n if (cfg.claude_code) {\n const claudeCodeConfig = cfg.claude_code as ClaudeCodeConfig;\n\n // Validate allowedTools if present\n if (claudeCodeConfig.allowedTools && !Array.isArray(claudeCodeConfig.allowedTools)) {\n return false;\n }\n\n // Validate maxTurns if present\n if (claudeCodeConfig.maxTurns && typeof claudeCodeConfig.maxTurns !== 'number') {\n return false;\n }\n\n // Validate systemPrompt if present\n if (claudeCodeConfig.systemPrompt && typeof claudeCodeConfig.systemPrompt !== 'string') {\n return false;\n }\n\n // Validate mcpServers if present\n if (claudeCodeConfig.mcpServers) {\n if (typeof claudeCodeConfig.mcpServers !== 'object') {\n return false;\n }\n\n for (const serverConfig of Object.values(claudeCodeConfig.mcpServers)) {\n if (!serverConfig.command || typeof serverConfig.command !== 'string') {\n return false;\n }\n if (serverConfig.args && !Array.isArray(serverConfig.args)) {\n return false;\n }\n }\n }\n }\n\n return true;\n }\n\n /**\n * Initialize Claude Code SDK client\n */\n private async initializeClaudeCodeClient(): Promise<ClaudeCodeClient> {\n if (this.claudeCodeClient) {\n return this.claudeCodeClient;\n }\n\n // Use safe import to avoid TypeScript compilation errors\n const claudeCodeModule = await safeImport<{\n ClaudeCode?: unknown;\n default?: { ClaudeCode?: unknown };\n }>('@anthropic/claude-code-sdk');\n\n if (!claudeCodeModule) {\n throw new ClaudeCodeSDKNotInstalledError();\n }\n\n const ClaudeCodeCtor = claudeCodeModule.ClaudeCode || claudeCodeModule.default?.ClaudeCode;\n\n if (!isClaudeCodeConstructor(ClaudeCodeCtor)) {\n throw new Error('ClaudeCode class not found in @anthropic/claude-code-sdk');\n }\n\n // Initialize with API key from environment\n const apiKey = process.env.CLAUDE_CODE_API_KEY || process.env.ANTHROPIC_API_KEY;\n if (!apiKey) {\n throw new ClaudeCodeAPIKeyMissingError();\n }\n\n try {\n const client = new ClaudeCodeCtor({\n apiKey,\n }) as ClaudeCodeClient;\n\n this.claudeCodeClient = client;\n return client;\n } catch (error) {\n throw new Error(\n `Failed to initialize Claude Code SDK: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n }\n }\n\n /**\n * Group files by their file extension for template context\n */\n private groupFilesByExtension(\n files: import('../pr-analyzer').PRFile[]\n ): Record<string, import('../pr-analyzer').PRFile[]> {\n const grouped: Record<string, import('../pr-analyzer').PRFile[]> = {};\n\n files.forEach(file => {\n const parts = file.filename.split('.');\n const ext = parts.length > 1 ? parts.pop()?.toLowerCase() || 'noext' : 'noext';\n if (!grouped[ext]) {\n grouped[ext] = [];\n }\n grouped[ext].push(file);\n });\n\n return grouped;\n }\n\n /**\n * Process prompt configuration to resolve final prompt string\n */\n private async processPrompt(\n promptConfig: string,\n prInfo: PRInfo,\n eventContext?: Record<string, unknown>,\n dependencyResults?: Map<string, ReviewSummary>\n ): Promise<string> {\n let promptContent: string;\n\n // Auto-detect if it's a file path or inline content\n if (await this.isFilePath(promptConfig)) {\n promptContent = await this.loadPromptFromFile(promptConfig);\n } else {\n promptContent = promptConfig;\n }\n\n // Process Liquid templates in the prompt\n return await this.renderPromptTemplate(promptContent, prInfo, eventContext, dependencyResults);\n }\n\n /**\n * Detect if a string is likely a file path and if the file exists\n */\n private async isFilePath(str: string): Promise<boolean> {\n // Quick checks to exclude obvious non-file-path content\n if (!str || str.trim() !== str || str.length > 512) {\n return false;\n }\n\n // Exclude strings that are clearly content (contain common content indicators)\n if (\n /\\s{2,}/.test(str) || // Multiple consecutive spaces\n /\\n/.test(str) || // Contains newlines\n /^(please|analyze|review|check|find|identify|look|search)/i.test(str.trim()) || // Starts with command words\n str.split(' ').length > 8 // Too many words for a typical file path\n ) {\n return false;\n }\n\n // For strings with path separators, be more lenient about common words\n if (!/[\\/\\\\]/.test(str)) {\n // Only apply strict English word filter to non-path strings\n if (/\\b(the|and|or|but|for|with|by|from|in|on|at|as)\\b/i.test(str)) {\n return false;\n }\n }\n\n // Positive indicators for file paths\n const hasFileExtension = /\\.[a-zA-Z0-9]{1,10}$/i.test(str);\n const hasPathSeparators = /[\\/\\\\]/.test(str);\n const isRelativePath = /^\\.{1,2}\\//.test(str);\n const isAbsolutePath = path.isAbsolute(str);\n const hasTypicalFileChars = /^[a-zA-Z0-9._\\-\\/\\\\:~]+$/.test(str);\n\n // Must have at least one strong indicator\n if (!(hasFileExtension || isRelativePath || isAbsolutePath || hasPathSeparators)) {\n return false;\n }\n\n // Must contain only typical file path characters\n if (!hasTypicalFileChars) {\n return false;\n }\n\n // Additional validation for suspected file paths\n try {\n // Try to resolve and check if file exists\n let resolvedPath: string;\n\n if (path.isAbsolute(str)) {\n resolvedPath = path.normalize(str);\n } else {\n // Resolve relative to current working directory\n resolvedPath = path.resolve(process.cwd(), str);\n }\n\n // Check if file exists\n try {\n const stat = await fs.stat(resolvedPath);\n return stat.isFile();\n } catch {\n // File doesn't exist, but might still be a valid file path format\n return hasFileExtension && (isRelativePath || isAbsolutePath || hasPathSeparators);\n }\n } catch {\n return false;\n }\n }\n\n /**\n * Load prompt content from file with security validation\n */\n private async loadPromptFromFile(promptPath: string): Promise<string> {\n // Enforce .liquid file extension for all prompt files\n if (!promptPath.endsWith('.liquid')) {\n throw new Error('Prompt file must have .liquid extension');\n }\n\n let resolvedPath: string;\n\n if (path.isAbsolute(promptPath)) {\n // Absolute path - use as-is\n resolvedPath = promptPath;\n } else {\n // Relative path - resolve relative to current working directory\n resolvedPath = path.resolve(process.cwd(), promptPath);\n }\n\n // Security: For relative paths, ensure they don't escape the current directory\n if (!path.isAbsolute(promptPath)) {\n const normalizedPath = path.normalize(resolvedPath);\n const currentDir = path.resolve(process.cwd());\n if (!normalizedPath.startsWith(currentDir)) {\n throw new Error('Invalid prompt file path: path traversal detected');\n }\n }\n\n // Security: Check for obvious path traversal patterns\n if (promptPath.includes('../..')) {\n throw new Error('Invalid prompt file path: path traversal detected');\n }\n\n try {\n const promptContent = await fs.readFile(resolvedPath, 'utf-8');\n return promptContent;\n } catch (error) {\n throw new Error(\n `Failed to load prompt from ${resolvedPath}: ${\n error instanceof Error ? error.message : 'Unknown error'\n }`\n );\n }\n }\n\n /**\n * Render Liquid template in prompt with comprehensive context\n */\n private async renderPromptTemplate(\n promptContent: string,\n prInfo: PRInfo,\n eventContext?: Record<string, unknown>,\n dependencyResults?: Map<string, ReviewSummary>\n ): Promise<string> {\n // Create comprehensive template context with PR and event information\n const templateContext = {\n // PR Information\n pr: {\n number: prInfo.number,\n title: prInfo.title,\n body: prInfo.body,\n author: prInfo.author,\n baseBranch: prInfo.base,\n headBranch: prInfo.head,\n isIncremental: prInfo.isIncremental,\n filesChanged: prInfo.files?.map(f => f.filename) || [],\n totalAdditions: prInfo.files?.reduce((sum, f) => sum + f.additions, 0) || 0,\n totalDeletions: prInfo.files?.reduce((sum, f) => sum + f.deletions, 0) || 0,\n totalChanges: prInfo.files?.reduce((sum, f) => sum + f.changes, 0) || 0,\n base: prInfo.base,\n head: prInfo.head,\n },\n\n // File Details\n files: prInfo.files || [],\n description: prInfo.body || '',\n\n // GitHub Event Context\n event: eventContext\n ? {\n name: eventContext.event_name || 'unknown',\n action: eventContext.action,\n isPullRequest: !prInfo.isIssue,\n\n // Repository Info\n repository: eventContext.repository\n ? {\n owner: (eventContext.repository as { owner?: { login?: string } })?.owner?.login,\n name: (eventContext.repository as { name?: string })?.name,\n fullName: eventContext.repository\n ? `${(eventContext.repository as { owner?: { login?: string } })?.owner?.login}/${(eventContext.repository as { name?: string })?.name}`\n : undefined,\n }\n : undefined,\n\n // Comment Data (for comment events)\n comment: eventContext.comment\n ? {\n body: (eventContext.comment as { body?: string })?.body,\n author: (eventContext.comment as { user?: { login?: string } })?.user?.login,\n }\n : undefined,\n\n // Raw event payload for advanced use cases\n payload: eventContext,\n }\n : undefined,\n\n // Utility data for templates\n utils: {\n // Date/time helpers\n now: new Date().toISOString(),\n today: new Date().toISOString().split('T')[0],\n\n // Dynamic file grouping by extension\n filesByExtension: this.groupFilesByExtension(prInfo.files || []),\n\n // File status categorizations\n addedFiles: (prInfo.files || []).filter(f => f.status === 'added'),\n modifiedFiles: (prInfo.files || []).filter(f => f.status === 'modified'),\n removedFiles: (prInfo.files || []).filter(f => f.status === 'removed'),\n renamedFiles: (prInfo.files || []).filter(f => f.status === 'renamed'),\n\n // Change analysis\n hasLargeChanges: (prInfo.files || []).some(f => f.changes > 50),\n totalFiles: (prInfo.files || []).length,\n },\n\n // Previous check outputs (dependency results)\n // Expose raw output directly if available, otherwise expose the result as-is\n outputs: dependencyResults\n ? Object.fromEntries(\n Array.from(dependencyResults.entries()).map(([checkName, result]) => [\n checkName,\n // If the result has a direct output field, use it directly\n // Otherwise, expose the entire result\n (() => {\n const summary = result as ReviewSummary & { output?: unknown };\n return summary.output !== undefined ? summary.output : summary;\n })(),\n ])\n )\n : {},\n };\n\n try {\n return await this.liquidEngine.parseAndRender(promptContent, templateContext);\n } catch (error) {\n throw new Error(\n `Failed to render prompt template: ${\n error instanceof Error ? error.message : 'Unknown error'\n }`\n );\n }\n }\n\n /**\n * Parse structured response from Claude Code\n */\n private parseStructuredResponse(content: string): ReviewSummary {\n try {\n // Try to parse as JSON first\n const parsed = JSON.parse(content);\n\n // Convert to ReviewSummary format\n return {\n issues: parsed.issues || [],\n };\n } catch {\n // If not JSON, treat as plain text comment\n return {\n issues: [],\n };\n }\n }\n\n async execute(\n prInfo: PRInfo,\n config: CheckProviderConfig,\n dependencyResults?: Map<string, ReviewSummary>,\n sessionInfo?: { parentSessionId?: string; reuseSession?: boolean }\n ): Promise<ReviewSummary> {\n // Apply environment configuration if present\n if (config.env) {\n const result = EnvironmentResolver.withTemporaryEnv(config.env, () => {\n return this.executeWithConfig(prInfo, config, dependencyResults, sessionInfo);\n });\n\n if (result instanceof Promise) {\n return result;\n }\n return result;\n }\n\n return this.executeWithConfig(prInfo, config, dependencyResults, sessionInfo);\n }\n\n private async executeWithConfig(\n prInfo: PRInfo,\n config: CheckProviderConfig,\n dependencyResults?: Map<string, ReviewSummary>,\n sessionInfo?: { parentSessionId?: string; reuseSession?: boolean }\n ): Promise<ReviewSummary> {\n // Extract Claude Code configuration\n const claudeCodeConfig = (config.claude_code as ClaudeCodeConfig) || {};\n\n // Get custom prompt from config - REQUIRED\n const customPrompt = config.prompt;\n if (!customPrompt) {\n throw new Error(\n `No prompt defined for check. All checks must have prompts defined in .visor.yaml configuration.`\n );\n }\n\n // Process prompt with Liquid templates and file loading\n const processedPrompt = await this.processPrompt(\n customPrompt,\n prInfo,\n config.eventContext,\n dependencyResults\n );\n\n const startTime = Date.now();\n\n try {\n // Initialize Claude Code client\n const client = await this.initializeClaudeCodeClient();\n\n // Prepare query object with MCP servers passed directly to SDK\n const query: ClaudeCodeQuery = {\n query: processedPrompt,\n maxTurns: claudeCodeConfig.maxTurns || 5,\n systemPrompt: claudeCodeConfig.systemPrompt,\n subagent: claudeCodeConfig.subagent,\n };\n\n // Add allowed tools if specified\n if (claudeCodeConfig.allowedTools && claudeCodeConfig.allowedTools.length > 0) {\n query.tools = claudeCodeConfig.allowedTools.map(name => ({ name }));\n }\n\n // Pass MCP servers directly to the SDK - let it handle spawning and tool discovery\n if (claudeCodeConfig.mcpServers && Object.keys(claudeCodeConfig.mcpServers).length > 0) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (query as any).mcpServers = claudeCodeConfig.mcpServers;\n }\n\n // Execute query with Claude Code\n let response: ClaudeCodeResponse;\n\n if (sessionInfo?.reuseSession && sessionInfo.parentSessionId) {\n // Use session reuse if available\n response = await client.query({\n ...query,\n sessionId: sessionInfo.parentSessionId,\n });\n } else {\n // Create new session\n response = await client.query(query);\n }\n\n // Parse the response\n const result = this.parseStructuredResponse(response.content) as ReviewSummary & {\n debug?: import('../ai-review-service').AIDebugInfo & {\n sessionId?: string;\n turnCount?: number;\n usage?: unknown;\n toolsUsed?: string[];\n };\n };\n\n result.debug = {\n prompt: processedPrompt,\n rawResponse: response.content,\n provider: 'claude-code',\n model: 'claude-code',\n apiKeySource: 'CLAUDE_CODE_API_KEY',\n processingTime: Date.now() - startTime,\n promptLength: processedPrompt.length,\n responseLength: response.content.length,\n jsonParseSuccess: true,\n errors: [],\n checksExecuted: [config.checkName || 'claude-code-check'],\n parallelExecution: false,\n timestamp: new Date().toISOString(),\n // Claude Code specific debug info\n sessionId: response.session_id,\n turnCount: response.turn_count,\n usage: response.usage,\n };\n\n // Apply issue suppression filtering\n const suppressionEnabled = config.suppressionEnabled !== false;\n const issueFilter = new IssueFilter(suppressionEnabled);\n const filteredIssues = issueFilter.filterIssues(result.issues || [], process.cwd());\n\n return {\n ...result,\n issues: filteredIssues,\n };\n } catch (error) {\n // Re-throw setup/configuration errors that should terminate the application\n if (\n error instanceof ClaudeCodeSDKNotInstalledError ||\n error instanceof ClaudeCodeAPIKeyMissingError\n ) {\n throw error;\n }\n\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n // Log detailed error information\n console.error(`❌ Claude Code Check Provider Error: ${errorMessage}`);\n\n // Check if this is a critical error\n const isCriticalError =\n errorMessage.includes('API rate limit') ||\n errorMessage.includes('403') ||\n errorMessage.includes('401') ||\n errorMessage.includes('authentication');\n\n if (isCriticalError) {\n console.error(\n `🚨 CRITICAL ERROR: Claude Code provider authentication or setup issue detected`\n );\n console.error(\n `🚨 This check cannot proceed without valid API credentials and SDK installation`\n );\n }\n\n // Re-throw with more context\n throw new Error(`Claude Code analysis failed: ${errorMessage}`);\n }\n }\n\n getSupportedConfigKeys(): string[] {\n return [\n 'type',\n 'prompt',\n 'claude_code.allowedTools',\n 'claude_code.maxTurns',\n 'claude_code.systemPrompt',\n 'claude_code.mcpServers',\n 'claude_code.subagent',\n 'claude_code.hooks',\n 'env',\n 'checkName',\n 'sessionId',\n 'suppressionEnabled',\n ];\n }\n\n async isAvailable(): Promise<boolean> {\n try {\n // Check if Claude Code API key is available\n const hasApiKey = !!(process.env.CLAUDE_CODE_API_KEY || process.env.ANTHROPIC_API_KEY);\n\n if (!hasApiKey) {\n return false;\n }\n\n // Try to import the SDK to check if it's installed\n const claudeCodeModule = await safeImport<{\n ClaudeCode?: unknown;\n default?: { ClaudeCode?: unknown };\n }>('@anthropic/claude-code-sdk');\n if (!claudeCodeModule) {\n return false;\n }\n const ClaudeCode = claudeCodeModule.ClaudeCode || claudeCodeModule.default?.ClaudeCode;\n\n return !!ClaudeCode;\n } catch {\n // If import fails, the SDK is not installed\n return false;\n }\n }\n\n getRequirements(): string[] {\n return [\n 'CLAUDE_CODE_API_KEY or ANTHROPIC_API_KEY environment variable',\n '@anthropic/claude-code-sdk npm package',\n '@modelcontextprotocol/sdk npm package (for MCP support)',\n 'Network access to Claude Code API',\n ];\n }\n}\n","/**\n * Type definitions for Claude Code SDK and MCP SDK\n * These are placeholder types for when the packages aren't installed\n */\n\n// Claude Code SDK types\nexport interface ClaudeCodeQuery {\n query: string;\n tools?: Array<{\n name: string;\n [key: string]: unknown;\n }>;\n subagent?: string;\n maxTurns?: number;\n systemPrompt?: string;\n sessionId?: string;\n}\n\nexport interface ClaudeCodeResponse {\n content: string;\n usage?: {\n input_tokens: number;\n output_tokens: number;\n };\n turn_count?: number;\n session_id?: string;\n}\n\nexport interface ClaudeCodeClient {\n query(options: ClaudeCodeQuery): Promise<ClaudeCodeResponse>;\n}\n\n// MCP Server configuration interface\nexport interface McpServerConfig {\n command: string;\n args?: string[];\n env?: Record<string, string>;\n}\n\n// MCP Tool interface\nexport interface McpTool {\n name: string;\n description?: string;\n inputSchema?: Record<string, unknown>;\n handler?: (args: Record<string, unknown>) => Promise<unknown>;\n}\n\n// MCP Server interface\nexport interface McpServer {\n name: string;\n command?: string;\n args?: string[];\n env?: Record<string, string>;\n tools?: McpTool[];\n}\n\n// MCP Server Instance interface\nexport interface McpServerInstance {\n name: string;\n listTools(): Promise<McpTool[]>;\n callTool(name: string, args: Record<string, unknown>): Promise<unknown>;\n close(): Promise<void>;\n}\n\n// Claude Code configuration interface\nexport interface ClaudeCodeConfig {\n allowedTools?: string[];\n maxTurns?: number;\n systemPrompt?: string;\n mcpServers?: Record<string, McpServerConfig>;\n subagent?: string;\n hooks?: {\n onStart?: string;\n onEnd?: string;\n onError?: string;\n };\n}\n\n/**\n * Utility function to safely import optional dependencies\n */\nexport async function safeImport<T>(moduleName: string): Promise<T | null> {\n try {\n return await import(moduleName);\n } catch {\n return null;\n }\n}\n","import { CheckProvider, CheckProviderConfig } from './check-provider.interface';\nimport { PRInfo } from '../pr-analyzer';\nimport { ReviewSummary, ReviewIssue } from '../reviewer';\nimport { Liquid } from 'liquidjs';\nimport Sandbox from '@nyariv/sandboxjs';\nimport { createExtendedLiquid } from '../liquid-extensions';\nimport { logger } from '../logger';\n\n/**\n * Check provider that executes shell commands and captures their output\n * Supports JSON parsing and integration with forEach functionality\n */\nexport class CommandCheckProvider extends CheckProvider {\n private liquid: Liquid;\n private sandbox?: Sandbox;\n\n constructor() {\n super();\n this.liquid = createExtendedLiquid({\n cache: false,\n strictFilters: false,\n strictVariables: false,\n });\n // Lazily create sandbox only when transform_js is used\n }\n\n private createSecureSandbox(): Sandbox {\n const globals = {\n ...Sandbox.SAFE_GLOBALS,\n console: console,\n JSON: JSON,\n };\n\n const prototypeWhitelist = new Map(Sandbox.SAFE_PROTOTYPES);\n return new Sandbox({ globals, prototypeWhitelist });\n }\n\n getName(): string {\n return 'command';\n }\n\n getDescription(): string {\n return 'Execute shell commands and capture output for processing';\n }\n\n async validateConfig(config: unknown): Promise<boolean> {\n if (!config || typeof config !== 'object') {\n return false;\n }\n\n const cfg = config as CheckProviderConfig;\n\n // Must have exec specified\n if (!cfg.exec || typeof cfg.exec !== 'string') {\n return false;\n }\n\n return true;\n }\n\n async execute(\n prInfo: PRInfo,\n config: CheckProviderConfig,\n dependencyResults?: Map<string, ReviewSummary>\n ): Promise<ReviewSummary> {\n const command = config.exec as string;\n const transform = config.transform as string | undefined;\n const transformJs = config.transform_js as string | undefined;\n\n // Prepare template context for Liquid rendering\n const templateContext = {\n pr: {\n number: prInfo.number,\n title: prInfo.title,\n author: prInfo.author,\n branch: prInfo.head,\n base: prInfo.base,\n },\n files: prInfo.files,\n fileCount: prInfo.files.length,\n outputs: this.buildOutputContext(dependencyResults),\n env: this.getSafeEnvironmentVariables(),\n };\n\n logger.debug(\n `🔧 Debug: Template outputs keys: ${Object.keys(templateContext.outputs || {}).join(', ')}`\n );\n\n try {\n // Render the command with Liquid templates if needed\n let renderedCommand = command;\n if (command.includes('{{') || command.includes('{%')) {\n renderedCommand = await this.renderCommandTemplate(command, templateContext);\n }\n\n logger.debug(`🔧 Debug: Rendered command: ${renderedCommand}`);\n\n // Prepare environment variables - convert all to strings\n const scriptEnv: Record<string, string> = {};\n for (const [key, value] of Object.entries(process.env)) {\n if (value !== undefined) {\n scriptEnv[key] = value;\n }\n }\n if (config.env) {\n for (const [key, value] of Object.entries(config.env)) {\n if (value !== undefined && value !== null) {\n scriptEnv[key] = String(value);\n }\n }\n }\n\n // Execute the script using dynamic import to avoid Jest issues\n const { exec } = await import('child_process');\n const { promisify } = await import('util');\n const execAsync = promisify(exec);\n\n // Get timeout from config (in seconds) or use default (60 seconds)\n const timeoutSeconds = (config.timeout as number) || 60;\n const timeoutMs = timeoutSeconds * 1000;\n\n const { stdout, stderr } = await execAsync(renderedCommand, {\n env: scriptEnv,\n timeout: timeoutMs,\n maxBuffer: 10 * 1024 * 1024, // 10MB buffer\n });\n\n if (stderr) {\n logger.debug(`Command stderr: ${stderr}`);\n }\n\n // Keep raw output for transforms\n const rawOutput = stdout.trim();\n\n // Try to parse output as JSON for default behavior\n let output: unknown = rawOutput;\n try {\n // Attempt to parse as JSON\n const parsed = JSON.parse(rawOutput);\n output = parsed;\n logger.debug(`🔧 Debug: Parsed entire output as JSON successfully`);\n } catch {\n // Try to extract JSON from the end of output (for commands with debug logs)\n const extracted = this.extractJsonFromEnd(rawOutput);\n if (extracted) {\n try {\n output = JSON.parse(extracted);\n logger.debug(\n `🔧 Debug: Extracted and parsed JSON from end of output (${extracted.length} chars from ${rawOutput.length} total)`\n );\n logger.debug(`🔧 Debug: Extracted JSON content: ${extracted.slice(0, 200)}`);\n } catch (parseError) {\n // Extraction found something but it's not valid JSON\n logger.debug(\n `🔧 Debug: Extracted text is not valid JSON: ${parseError instanceof Error ? parseError.message : 'Unknown error'}`\n );\n output = rawOutput;\n }\n } else {\n // Not JSON, keep as string\n logger.debug(`🔧 Debug: No JSON found in output, keeping as string`);\n output = rawOutput;\n }\n }\n\n // Log the parsed structure for debugging\n if (output !== rawOutput) {\n try {\n const outputType = Array.isArray(output) ? `array[${output.length}]` : typeof output;\n logger.debug(`🔧 Debug: Parsed output type: ${outputType}`);\n if (typeof output === 'object' && output !== null) {\n logger.debug(`🔧 Debug: Parsed output keys: ${Object.keys(output).join(', ')}`);\n }\n } catch {\n // Ignore logging errors\n }\n }\n\n // Apply transform if specified (Liquid or JavaScript)\n let finalOutput = output;\n\n // First apply Liquid transform if present\n if (transform) {\n try {\n const transformContext = {\n ...templateContext,\n output: output, // Use parsed output for Liquid (object if JSON, string otherwise)\n };\n const rendered = await this.liquid.parseAndRender(transform, transformContext);\n\n // Try to parse the transformed result as JSON\n try {\n finalOutput = JSON.parse(rendered.trim());\n logger.verbose(`✓ Applied Liquid transform successfully (parsed as JSON)`);\n } catch {\n finalOutput = rendered.trim();\n logger.verbose(`✓ Applied Liquid transform successfully (string output)`);\n }\n } catch (error) {\n logger.error(\n `✗ Failed to apply Liquid transform: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n return {\n issues: [\n {\n file: 'command',\n line: 0,\n ruleId: 'command/transform_error',\n message: `Failed to apply Liquid transform: ${error instanceof Error ? error.message : 'Unknown error'}`,\n severity: 'error',\n category: 'logic',\n },\n ],\n };\n }\n }\n\n // Then apply JavaScript transform if present\n if (transformJs) {\n try {\n // For transform_js, provide a JSON-smart wrapper that:\n // - behaves like a string when coerced (so JSON.parse(output) still works)\n // - exposes parsed JSON properties if stdout is valid JSON (so output.key works)\n const jsContext = {\n output: this.makeJsonSmart(rawOutput),\n pr: templateContext.pr,\n files: templateContext.files,\n outputs: this.makeOutputsJsonSmart(templateContext.outputs),\n env: templateContext.env,\n };\n\n // Compile and execute the JavaScript expression\n // Use direct property access instead of destructuring to avoid syntax issues\n const trimmedTransform = transformJs.trim();\n let transformExpression: string;\n\n if (/return\\s+/.test(trimmedTransform)) {\n transformExpression = `(() => {\\n${trimmedTransform}\\n})()`;\n } else {\n const lines = trimmedTransform.split('\\n');\n if (lines.length > 1) {\n const lastLine = lines[lines.length - 1].trim();\n const remaining = lines.slice(0, -1).join('\\n');\n if (lastLine && !lastLine.includes('}') && !lastLine.includes('{')) {\n const returnTarget = lastLine.replace(/;$/, '');\n transformExpression = `(() => {\\n${remaining}\\nreturn ${returnTarget};\\n})()`;\n } else {\n transformExpression = `(${trimmedTransform})`;\n }\n } else {\n transformExpression = `(${trimmedTransform})`;\n }\n }\n\n const code = `\n const output = scope.output;\n const pr = scope.pr;\n const files = scope.files;\n const outputs = scope.outputs;\n const env = scope.env;\n const log = (...args) => {\n console.log('🔍 Debug:', ...args);\n };\n return ${transformExpression};\n `;\n\n try {\n logger.debug(`🔧 Debug: JavaScript transform code: ${code}`);\n logger.debug(\n `🔧 Debug: JavaScript context: ${JSON.stringify(jsContext).slice(0, 200)}`\n );\n } catch {\n // Ignore logging errors\n }\n\n if (!this.sandbox) {\n this.sandbox = this.createSecureSandbox();\n }\n const exec = this.sandbox.compile(code);\n finalOutput = exec({ scope: jsContext }).run();\n\n logger.verbose(`✓ Applied JavaScript transform successfully`);\n try {\n const preview = JSON.stringify(finalOutput);\n logger.debug(\n `🔧 Debug: transform_js result: ${typeof preview === 'string' ? preview.slice(0, 200) : String(preview).slice(0, 200)}`\n );\n } catch {\n try {\n const preview = String(finalOutput);\n logger.debug(`🔧 Debug: transform_js result: ${preview.slice(0, 200)}`);\n } catch {\n // Ignore logging errors\n }\n }\n } catch (error) {\n logger.error(\n `✗ Failed to apply JavaScript transform: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n return {\n issues: [\n {\n file: 'command',\n line: 0,\n ruleId: 'command/transform_js_error',\n message: `Failed to apply JavaScript transform: ${error instanceof Error ? error.message : 'Unknown error'}`,\n severity: 'error',\n category: 'logic',\n },\n ],\n };\n }\n }\n\n // Extract structured issues when the command returns them (skip for forEach parents)\n let issues: ReviewIssue[] = [];\n let outputForDependents: unknown = finalOutput;\n let content: string | undefined;\n let extracted: { issues: ReviewIssue[]; remainingOutput: unknown } | null = null;\n\n const trimmedRawOutput = typeof rawOutput === 'string' ? rawOutput.trim() : undefined;\n\n const commandConfig = config as CheckProviderConfig & { forEach?: boolean };\n const isForEachParent = commandConfig.forEach === true;\n\n if (!isForEachParent) {\n extracted = this.extractIssuesFromOutput(finalOutput);\n if (!extracted && typeof finalOutput === 'string') {\n // Attempt to parse string output as JSON and extract issues again\n try {\n const parsed = JSON.parse(finalOutput);\n extracted = this.extractIssuesFromOutput(parsed);\n if (extracted) {\n issues = extracted.issues;\n outputForDependents = extracted.remainingOutput;\n }\n } catch {\n // Ignore JSON parse errors – leave output as-is\n }\n } else if (extracted) {\n issues = extracted.issues;\n outputForDependents = extracted.remainingOutput;\n }\n\n if (!issues.length && this.shouldTreatAsTextOutput(trimmedRawOutput)) {\n content = trimmedRawOutput;\n } else if (issues.length && typeof extracted?.remainingOutput === 'string') {\n const trimmed = extracted.remainingOutput.trim();\n if (trimmed) {\n content = trimmed;\n }\n }\n }\n\n if (!content && this.shouldTreatAsTextOutput(trimmedRawOutput) && !isForEachParent) {\n content = trimmedRawOutput;\n }\n\n // Return the output and issues as part of the review summary so dependent checks can use them\n const result = {\n issues,\n output: outputForDependents,\n ...(content ? { content } : {}),\n } as ReviewSummary;\n\n if (transformJs) {\n try {\n const outputValue = (result as ReviewSummary & { output?: unknown }).output;\n const stringified = JSON.stringify(outputValue);\n logger.debug(\n `🔧 Debug: Command provider returning output: ${stringified ? stringified.slice(0, 200) : '(empty)'}`\n );\n } catch {\n // Ignore logging errors\n }\n }\n\n return result;\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n\n // Check if this is a timeout error\n let isTimeout = false;\n if (error && typeof error === 'object') {\n const execError = error as { killed?: boolean; signal?: string; code?: string | number };\n // Node's child_process sets killed=true and signal='SIGTERM' on timeout\n if (execError.killed && execError.signal === 'SIGTERM') {\n isTimeout = true;\n }\n // Some versions may also set code to 'ETIMEDOUT'\n if (execError.code === 'ETIMEDOUT') {\n isTimeout = true;\n }\n }\n\n // Extract stderr from the error if available (child_process errors include stdout/stderr)\n let stderrOutput = '';\n if (error && typeof error === 'object') {\n const execError = error as { stderr?: string; stdout?: string };\n if (execError.stderr) {\n stderrOutput = execError.stderr.trim();\n }\n }\n\n // Construct detailed error message\n let detailedMessage: string;\n let ruleId: string;\n\n if (isTimeout) {\n const timeoutSeconds = (config.timeout as number) || 60;\n detailedMessage = `Command execution timed out after ${timeoutSeconds} seconds`;\n if (stderrOutput) {\n detailedMessage += `\\n\\nStderr output:\\n${stderrOutput}`;\n }\n ruleId = 'command/timeout';\n } else {\n detailedMessage = stderrOutput\n ? `Command execution failed: ${errorMessage}\\n\\nStderr output:\\n${stderrOutput}`\n : `Command execution failed: ${errorMessage}`;\n ruleId = 'command/execution_error';\n }\n\n logger.error(`✗ ${detailedMessage}`);\n\n return {\n issues: [\n {\n file: 'command',\n line: 0,\n ruleId,\n message: detailedMessage,\n severity: 'error',\n category: 'logic',\n },\n ],\n };\n }\n }\n\n private buildOutputContext(\n dependencyResults?: Map<string, ReviewSummary>\n ): Record<string, unknown> {\n if (!dependencyResults) {\n return {};\n }\n\n const outputs: Record<string, unknown> = {};\n for (const [checkName, result] of dependencyResults) {\n // If the result has a direct output field, use it directly\n // Otherwise, expose the entire result as-is\n const summary = result as ReviewSummary & { output?: unknown };\n const value = summary.output !== undefined ? summary.output : summary;\n outputs[checkName] = this.makeJsonSmart(value);\n }\n return outputs;\n }\n\n /**\n * Wrap a value with JSON-smart behavior:\n * - If it's a JSON string, expose parsed properties via Proxy (e.g., value.key)\n * - When coerced to string (toString/valueOf/Symbol.toPrimitive), return the original raw string\n * - If parsing fails or value is not a string, return the value unchanged\n * - Attempts to extract JSON from the end of the output if full parse fails\n */\n private makeJsonSmart<T = unknown>(value: T): T | any {\n if (typeof value !== 'string') {\n return value;\n }\n\n const raw = value as unknown as string;\n let parsed: any;\n\n // First try: parse the entire string as JSON\n try {\n parsed = JSON.parse(raw);\n } catch {\n // Second try: extract JSON from the end of the output\n // Look for { or [ at the start of a line and take everything after it\n const jsonMatch = this.extractJsonFromEnd(raw);\n if (jsonMatch) {\n try {\n parsed = JSON.parse(jsonMatch);\n logger.debug(\n `🔧 Debug: Extracted JSON from end of output (${jsonMatch.length} chars from ${raw.length} total)`\n );\n } catch {\n // Not valid JSON even after extraction, return original string\n return raw;\n }\n } else {\n // Not JSON, return original string\n return raw;\n }\n }\n\n // Use a boxed string so string methods still work via Proxy fallback\n const boxed = new String(raw);\n const handler: ProxyHandler<any> = {\n get(target, prop, receiver) {\n if (prop === 'toString' || prop === 'valueOf') {\n return () => raw;\n }\n if (prop === Symbol.toPrimitive) {\n return () => raw;\n }\n if (parsed != null && (typeof parsed === 'object' || Array.isArray(parsed))) {\n if (prop in parsed) {\n return (parsed as any)[prop as any];\n }\n }\n return Reflect.get(target, prop, receiver);\n },\n has(_target, prop) {\n if (parsed != null && (typeof parsed === 'object' || Array.isArray(parsed))) {\n if (prop in parsed) return true;\n }\n return false;\n },\n ownKeys(_target) {\n if (parsed != null && (typeof parsed === 'object' || Array.isArray(parsed))) {\n try {\n return Reflect.ownKeys(parsed);\n } catch {\n return [];\n }\n }\n return [];\n },\n getOwnPropertyDescriptor(_target, prop) {\n if (parsed != null && (typeof parsed === 'object' || Array.isArray(parsed))) {\n const descriptor = Object.getOwnPropertyDescriptor(parsed, prop as any);\n if (descriptor) return descriptor;\n }\n return {\n configurable: true,\n enumerable: true,\n writable: false,\n value: undefined,\n };\n },\n };\n return new Proxy(boxed, handler);\n }\n\n /**\n * Extract JSON from the end of a string that may contain logs/debug output\n * Looks for the last occurrence of { or [ and tries to parse from there\n */\n private extractJsonFromEnd(text: string): string | null {\n // Strategy: Find the last line that starts with { or [\n // Then try to parse from that point to the end\n const lines = text.split('\\n');\n\n // Search backwards for a line starting with { or [\n for (let i = lines.length - 1; i >= 0; i--) {\n const trimmed = lines[i].trim();\n if (trimmed.startsWith('{') || trimmed.startsWith('[')) {\n // Found potential JSON start - take everything from here to the end\n const candidate = lines.slice(i).join('\\n');\n // Quick validation: does it look like valid JSON structure?\n const trimmedCandidate = candidate.trim();\n if (\n (trimmedCandidate.startsWith('{') && trimmedCandidate.endsWith('}')) ||\n (trimmedCandidate.startsWith('[') && trimmedCandidate.endsWith(']'))\n ) {\n return trimmedCandidate;\n }\n }\n }\n\n return null;\n }\n\n /**\n * Recursively apply JSON-smart wrapper to outputs object values\n */\n private makeOutputsJsonSmart(outputs: Record<string, unknown>): Record<string, unknown> {\n const wrapped: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(outputs || {})) {\n wrapped[k] = this.makeJsonSmart(v);\n }\n return wrapped;\n }\n\n private getSafeEnvironmentVariables(): Record<string, string> {\n const safeVars: Record<string, string> = {};\n const allowedPrefixes = ['CI_', 'GITHUB_', 'RUNNER_', 'NODE_', 'npm_', 'PATH', 'HOME', 'USER'];\n\n for (const [key, value] of Object.entries(process.env)) {\n if (value !== undefined && allowedPrefixes.some(prefix => key.startsWith(prefix))) {\n safeVars[key] = value;\n }\n }\n\n // Add current working directory\n safeVars['PWD'] = process.cwd();\n\n return safeVars;\n }\n\n getSupportedConfigKeys(): string[] {\n return [\n 'type',\n 'exec',\n 'transform',\n 'transform_js',\n 'env',\n 'timeout',\n 'depends_on',\n 'on',\n 'if',\n 'group',\n 'forEach',\n ];\n }\n\n async isAvailable(): Promise<boolean> {\n // Command provider is always available as long as we can execute commands\n return true;\n }\n\n getRequirements(): string[] {\n return [\n 'Valid shell command to execute',\n 'Shell environment available',\n 'Optional: Transform template for processing output',\n ];\n }\n\n private extractIssuesFromOutput(\n output: unknown\n ): { issues: ReviewIssue[]; remainingOutput: unknown } | null {\n if (output === null || output === undefined) {\n return null;\n }\n\n // If output is already a string, do not treat it as issues here (caller may try parsing JSON)\n if (typeof output === 'string') {\n return null;\n }\n\n if (Array.isArray(output)) {\n const issues = this.normalizeIssueArray(output);\n if (issues) {\n return { issues, remainingOutput: undefined };\n }\n return null;\n }\n\n if (typeof output === 'object') {\n const record = output as Record<string, unknown>;\n\n if (Array.isArray(record.issues)) {\n const issues = this.normalizeIssueArray(record.issues);\n if (!issues) {\n return null;\n }\n\n const remaining = { ...record };\n delete (remaining as { issues?: unknown }).issues;\n\n const remainingKeys = Object.keys(remaining);\n const remainingOutput = remainingKeys.length > 0 ? remaining : undefined;\n\n return {\n issues,\n remainingOutput,\n };\n }\n\n const singleIssue = this.normalizeIssue(record);\n if (singleIssue) {\n return { issues: [singleIssue], remainingOutput: undefined };\n }\n }\n\n return null;\n }\n\n private shouldTreatAsTextOutput(value?: string): value is string {\n if (!value) {\n return false;\n }\n\n const trimmed = value.trim();\n if (!trimmed) {\n return false;\n }\n\n // Heuristic: consider it JSON-like if it starts with { or [ and ends with } or ]\n const startsJson =\n (trimmed.startsWith('{') && trimmed.endsWith('}')) ||\n (trimmed.startsWith('[') && trimmed.endsWith(']'));\n\n return !startsJson;\n }\n\n private normalizeIssueArray(values: unknown[]): ReviewIssue[] | null {\n const normalized: ReviewIssue[] = [];\n\n for (const value of values) {\n const issue = this.normalizeIssue(value);\n if (!issue) {\n return null;\n }\n normalized.push(issue);\n }\n\n return normalized;\n }\n\n private normalizeIssue(raw: unknown): ReviewIssue | null {\n if (!raw || typeof raw !== 'object') {\n return null;\n }\n\n const data = raw as Record<string, unknown>;\n\n const message = this.toTrimmedString(\n data.message || data.text || data.description || data.summary\n );\n if (!message) {\n return null;\n }\n\n const allowedSeverities = new Set(['info', 'warning', 'error', 'critical']);\n const severityRaw = this.toTrimmedString(data.severity || data.level || data.priority);\n let severity: ReviewIssue['severity'] = 'warning';\n if (severityRaw) {\n const lower = severityRaw.toLowerCase();\n if (allowedSeverities.has(lower)) {\n severity = lower as ReviewIssue['severity'];\n } else if (['fatal', 'high'].includes(lower)) {\n severity = 'error';\n } else if (['medium', 'moderate'].includes(lower)) {\n severity = 'warning';\n } else if (['low', 'minor'].includes(lower)) {\n severity = 'info';\n }\n }\n\n const allowedCategories = new Set([\n 'security',\n 'performance',\n 'style',\n 'logic',\n 'documentation',\n ]);\n const categoryRaw = this.toTrimmedString(data.category || data.type || data.group);\n let category: ReviewIssue['category'] = 'logic';\n if (categoryRaw && allowedCategories.has(categoryRaw.toLowerCase())) {\n category = categoryRaw.toLowerCase() as ReviewIssue['category'];\n }\n\n const file = this.toTrimmedString(data.file || data.path || data.filename) || 'system';\n\n const line = this.toNumber(data.line || data.startLine || data.lineNumber) ?? 0;\n const endLine = this.toNumber(data.endLine || data.end_line || data.stopLine);\n\n const suggestion = this.toTrimmedString(data.suggestion);\n const replacement = this.toTrimmedString(data.replacement);\n\n const ruleId =\n this.toTrimmedString(data.ruleId || data.rule || data.id || data.check) || 'command';\n\n return {\n file,\n line,\n endLine: endLine ?? undefined,\n ruleId,\n message,\n severity,\n category,\n suggestion: suggestion || undefined,\n replacement: replacement || undefined,\n };\n }\n\n private toTrimmedString(value: unknown): string | null {\n if (typeof value === 'string') {\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : null;\n }\n if (value !== null && value !== undefined && typeof value.toString === 'function') {\n const converted = String(value).trim();\n return converted.length > 0 ? converted : null;\n }\n return null;\n }\n\n private toNumber(value: unknown): number | null {\n if (value === null || value === undefined) {\n return null;\n }\n const num = Number(value);\n if (Number.isFinite(num)) {\n return Math.trunc(num);\n }\n return null;\n }\n\n private async renderCommandTemplate(\n template: string,\n context: {\n pr: Record<string, unknown>;\n files: unknown[];\n outputs: Record<string, unknown>;\n env: Record<string, string>;\n }\n ): Promise<string> {\n try {\n return await this.liquid.parseAndRender(template, context);\n } catch (error) {\n logger.debug(`🔧 Debug: Liquid rendering failed, falling back to JS evaluation: ${error}`);\n return this.renderWithJsExpressions(template, context);\n }\n }\n\n private renderWithJsExpressions(\n template: string,\n context: {\n pr: Record<string, unknown>;\n files: unknown[];\n outputs: Record<string, unknown>;\n env: Record<string, string>;\n }\n ): string {\n const scope = {\n pr: context.pr,\n files: context.files,\n outputs: context.outputs,\n env: context.env,\n };\n\n const expressionRegex = /\\{\\{\\s*([^{}]+?)\\s*\\}\\}/g;\n\n return template.replace(expressionRegex, (_match, expr) => {\n const expression = String(expr).trim();\n if (!expression) {\n return '';\n }\n\n try {\n const evalCode = `\n const pr = scope.pr;\n const files = scope.files;\n const outputs = scope.outputs;\n const env = scope.env;\n return (${expression});\n `;\n\n if (!this.sandbox) {\n this.sandbox = this.createSecureSandbox();\n }\n const evaluator = this.sandbox.compile(evalCode);\n const result = evaluator({ scope }).run();\n return result === undefined || result === null ? '' : String(result);\n } catch (evaluationError) {\n logger.debug(`🔧 Debug: Failed to evaluate expression: ${expression} - ${evaluationError}`);\n return '';\n }\n });\n }\n}\n","import { CheckProvider } from './check-provider.interface';\nimport { AICheckProvider } from './ai-check-provider';\nimport { HttpCheckProvider } from './http-check-provider';\nimport { HttpInputProvider } from './http-input-provider';\nimport { HttpClientProvider } from './http-client-provider';\nimport { NoopCheckProvider } from './noop-check-provider';\nimport { LogCheckProvider } from './log-check-provider';\nimport { ClaudeCodeCheckProvider } from './claude-code-check-provider';\nimport { CommandCheckProvider } from './command-check-provider';\n\n/**\n * Registry for managing check providers\n */\nexport class CheckProviderRegistry {\n private providers: Map<string, CheckProvider> = new Map();\n private static instance: CheckProviderRegistry;\n\n private constructor() {\n // Register default providers\n this.registerDefaultProviders();\n }\n\n /**\n * Get singleton instance\n */\n static getInstance(): CheckProviderRegistry {\n if (!CheckProviderRegistry.instance) {\n CheckProviderRegistry.instance = new CheckProviderRegistry();\n }\n return CheckProviderRegistry.instance;\n }\n\n /**\n * Register default built-in providers\n */\n private registerDefaultProviders(): void {\n // Register all built-in providers\n this.register(new AICheckProvider());\n this.register(new CommandCheckProvider());\n this.register(new HttpCheckProvider());\n this.register(new HttpInputProvider());\n this.register(new HttpClientProvider());\n this.register(new NoopCheckProvider());\n this.register(new LogCheckProvider());\n\n // Try to register ClaudeCodeCheckProvider - it may fail if dependencies are missing\n try {\n this.register(new ClaudeCodeCheckProvider());\n } catch (error) {\n console.error(\n `Warning: Failed to register ClaudeCodeCheckProvider: ${\n error instanceof Error ? error.message : 'Unknown error'\n }`\n );\n }\n }\n\n /**\n * Register a check provider\n */\n register(provider: CheckProvider): void {\n const name = provider.getName();\n if (this.providers.has(name)) {\n throw new Error(`Provider '${name}' is already registered`);\n }\n this.providers.set(name, provider);\n // Only log provider registration in debug mode to avoid contaminating output\n if (process.env.VISOR_DEBUG === 'true') {\n console.error(`Registered check provider: ${name}`);\n }\n }\n\n /**\n * Unregister a check provider\n */\n unregister(name: string): void {\n if (!this.providers.has(name)) {\n throw new Error(`Provider '${name}' not found`);\n }\n this.providers.delete(name);\n // Send provider unregistration messages to stderr to avoid contaminating JSON output\n console.error(`Unregistered check provider: ${name}`);\n }\n\n /**\n * Get a provider by name\n */\n getProvider(name: string): CheckProvider | undefined {\n return this.providers.get(name);\n }\n\n /**\n * Get provider or throw if not found\n */\n getProviderOrThrow(name: string): CheckProvider {\n const provider = this.providers.get(name);\n if (!provider) {\n throw new Error(\n `Check provider '${name}' not found. Available providers: ${this.getAvailableProviders().join(', ')}`\n );\n }\n return provider;\n }\n\n /**\n * Check if a provider exists\n */\n hasProvider(name: string): boolean {\n return this.providers.has(name);\n }\n\n /**\n * Get all registered provider names\n */\n getAvailableProviders(): string[] {\n return Array.from(this.providers.keys());\n }\n\n /**\n * Get all providers\n */\n getAllProviders(): CheckProvider[] {\n return Array.from(this.providers.values());\n }\n\n /**\n * Get providers that are currently available (have required dependencies)\n */\n async getActiveProviders(): Promise<CheckProvider[]> {\n const providers = this.getAllProviders();\n const activeProviders: CheckProvider[] = [];\n\n for (const provider of providers) {\n if (await provider.isAvailable()) {\n activeProviders.push(provider);\n }\n }\n\n return activeProviders;\n }\n\n /**\n * List provider information\n */\n async listProviders(): Promise<\n Array<{\n name: string;\n description: string;\n available: boolean;\n requirements: string[];\n }>\n > {\n const providers = this.getAllProviders();\n const info = [];\n\n for (const provider of providers) {\n info.push({\n name: provider.getName(),\n description: provider.getDescription(),\n available: await provider.isAvailable(),\n requirements: provider.getRequirements(),\n });\n }\n\n return info;\n }\n\n /**\n * Reset registry (mainly for testing)\n */\n reset(): void {\n this.providers.clear();\n this.registerDefaultProviders();\n }\n\n /**\n * Clear singleton instance (for testing)\n */\n static clearInstance(): void {\n CheckProviderRegistry.instance = undefined!;\n }\n}\n","/**\n * Dependency resolution and execution ordering for checks\n */\n\nexport interface CheckNode {\n id: string;\n dependencies: string[];\n dependents: string[];\n depth: number;\n}\n\nexport interface ExecutionGroup {\n /** Checks that can run in parallel */\n parallel: string[];\n /** Execution level/wave (0 = no dependencies, 1 = depends on level 0, etc.) */\n level: number;\n}\n\nexport interface DependencyGraph {\n nodes: Map<string, CheckNode>;\n executionOrder: ExecutionGroup[];\n hasCycles: boolean;\n cycleNodes?: string[];\n}\n\nexport class DependencyResolver {\n /**\n * Build dependency graph from check dependencies\n */\n static buildDependencyGraph(checkDependencies: Record<string, string[]>): DependencyGraph {\n const nodes = new Map<string, CheckNode>();\n\n // Initialize all nodes\n for (const checkId of Object.keys(checkDependencies)) {\n nodes.set(checkId, {\n id: checkId,\n dependencies: checkDependencies[checkId] || [],\n dependents: [],\n depth: 0,\n });\n }\n\n // Build bidirectional relationships\n for (const [checkId, dependencies] of Object.entries(checkDependencies)) {\n for (const depId of dependencies || []) {\n if (!nodes.has(depId)) {\n throw new Error(`Check \"${checkId}\" depends on \"${depId}\" but \"${depId}\" is not defined`);\n }\n\n const depNode = nodes.get(depId)!;\n depNode.dependents.push(checkId);\n }\n }\n\n // Detect cycles using DFS\n const cycleDetection = this.detectCycles(nodes);\n if (cycleDetection.hasCycles) {\n return {\n nodes,\n executionOrder: [],\n hasCycles: true,\n cycleNodes: cycleDetection.cycleNodes,\n };\n }\n\n // Calculate execution order using topological sort\n const executionOrder = this.topologicalSort(nodes);\n\n return {\n nodes,\n executionOrder,\n hasCycles: false,\n };\n }\n\n /**\n * Detect cycles in the dependency graph using DFS\n */\n private static detectCycles(nodes: Map<string, CheckNode>): {\n hasCycles: boolean;\n cycleNodes?: string[];\n } {\n const visited = new Set<string>();\n const recursionStack = new Set<string>();\n const cycleNodes: string[] = [];\n\n const dfs = (nodeId: string): boolean => {\n if (recursionStack.has(nodeId)) {\n cycleNodes.push(nodeId);\n return true;\n }\n if (visited.has(nodeId)) {\n return false;\n }\n\n visited.add(nodeId);\n recursionStack.add(nodeId);\n\n const node = nodes.get(nodeId);\n if (node) {\n for (const depId of node.dependencies) {\n if (dfs(depId)) {\n cycleNodes.push(nodeId);\n return true;\n }\n }\n }\n\n recursionStack.delete(nodeId);\n return false;\n };\n\n for (const nodeId of nodes.keys()) {\n if (!visited.has(nodeId)) {\n if (dfs(nodeId)) {\n return { hasCycles: true, cycleNodes: [...new Set(cycleNodes)] };\n }\n }\n }\n\n return { hasCycles: false };\n }\n\n /**\n * Perform topological sort to determine execution order\n * Groups checks that can run in parallel at each level\n */\n private static topologicalSort(nodes: Map<string, CheckNode>): ExecutionGroup[] {\n const remainingNodes = new Map(nodes);\n const executionGroups: ExecutionGroup[] = [];\n let level = 0;\n\n while (remainingNodes.size > 0) {\n // Find nodes with no remaining dependencies\n const readyNodes: string[] = [];\n\n for (const [nodeId, node] of remainingNodes.entries()) {\n const unmetDependencies = node.dependencies.filter(depId => remainingNodes.has(depId));\n if (unmetDependencies.length === 0) {\n readyNodes.push(nodeId);\n }\n }\n\n if (readyNodes.length === 0) {\n // This shouldn't happen if cycle detection worked correctly\n throw new Error('Unable to resolve dependencies - possible circular dependency detected');\n }\n\n // Add this group to execution order\n executionGroups.push({\n parallel: readyNodes,\n level,\n });\n\n // Remove processed nodes\n for (const nodeId of readyNodes) {\n remainingNodes.delete(nodeId);\n }\n\n level++;\n }\n\n return executionGroups;\n }\n\n /**\n * Validate that all dependencies exist\n */\n static validateDependencies(\n checkIds: string[],\n dependencies: Record<string, string[]>\n ): { valid: boolean; errors: string[] } {\n const errors: string[] = [];\n const checkIdSet = new Set(checkIds);\n\n for (const [checkId, deps] of Object.entries(dependencies)) {\n if (!checkIdSet.has(checkId)) {\n errors.push(`Check \"${checkId}\" is not in the list of available checks`);\n continue;\n }\n\n for (const depId of deps || []) {\n if (!checkIdSet.has(depId)) {\n errors.push(`Check \"${checkId}\" depends on \"${depId}\" which is not available`);\n }\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n }\n\n /**\n * Get all transitive dependencies (ancestors) for a given check\n * This returns all checks that must complete before the given check can run,\n * not just the direct dependencies.\n *\n * For example, if A -> B -> C, then:\n * - getAllDependencies(C) returns [A, B]\n * - getAllDependencies(B) returns [A]\n * - getAllDependencies(A) returns []\n *\n * @param checkId The check to find dependencies for\n * @param nodes The dependency graph nodes\n * @returns Array of all transitive dependency IDs\n */\n static getAllDependencies(checkId: string, nodes: Map<string, CheckNode>): string[] {\n const allDeps = new Set<string>();\n const visited = new Set<string>();\n\n const collectDependencies = (currentId: string) => {\n if (visited.has(currentId)) {\n return;\n }\n visited.add(currentId);\n\n const node = nodes.get(currentId);\n if (!node) {\n return;\n }\n\n // Add direct dependencies and recurse\n for (const depId of node.dependencies) {\n allDeps.add(depId);\n collectDependencies(depId);\n }\n };\n\n collectDependencies(checkId);\n return Array.from(allDeps);\n }\n\n /**\n * Get execution statistics for debugging\n */\n static getExecutionStats(graph: DependencyGraph): {\n totalChecks: number;\n parallelLevels: number;\n maxParallelism: number;\n averageParallelism: number;\n checksWithDependencies: number;\n } {\n const totalChecks = graph.nodes.size;\n const parallelLevels = graph.executionOrder.length;\n const maxParallelism = Math.max(...graph.executionOrder.map(group => group.parallel.length));\n const averageParallelism = totalChecks / parallelLevels;\n const checksWithDependencies = Array.from(graph.nodes.values()).filter(\n node => node.dependencies.length > 0\n ).length;\n\n return {\n totalChecks,\n parallelLevels,\n maxParallelism,\n averageParallelism,\n checksWithDependencies,\n };\n }\n}\n","/**\n * Failure condition evaluation engine using SandboxJS for secure expression evaluation\n */\n\nimport { ReviewSummary } from './reviewer';\nimport {\n FailureConditions,\n FailureCondition,\n FailureConditionContext,\n FailureConditionResult,\n FailureConditionSeverity,\n} from './types/config';\nimport Sandbox from '@nyariv/sandboxjs';\n\n/**\n * Evaluates failure conditions using SandboxJS for secure evaluation\n */\nexport class FailureConditionEvaluator {\n private sandbox?: Sandbox;\n\n constructor() {}\n\n /**\n * Create a secure sandbox with whitelisted functions and globals\n */\n private createSecureSandbox(): Sandbox {\n // Start with safe globals and prototypes\n const globals = {\n ...Sandbox.SAFE_GLOBALS,\n // Allow Math for calculations\n Math,\n // Allow console for debugging (in controlled environment)\n console: {\n log: console.log,\n warn: console.warn,\n error: console.error,\n },\n };\n\n // Create prototype whitelist - use safe defaults\n const prototypeWhitelist = new Map(Sandbox.SAFE_PROTOTYPES);\n\n // Explicitly allow array methods that we need\n const arrayMethods = new Set([\n 'some',\n 'every',\n 'filter',\n 'map',\n 'reduce',\n 'find',\n 'includes',\n 'indexOf',\n 'length',\n 'slice',\n 'concat',\n 'join',\n ]);\n prototypeWhitelist.set(Array.prototype, arrayMethods);\n\n // Allow string methods\n const stringMethods = new Set([\n 'toLowerCase',\n 'toUpperCase',\n 'includes',\n 'indexOf',\n 'startsWith',\n 'endsWith',\n 'slice',\n 'substring',\n 'length',\n 'trim',\n 'split',\n 'replace',\n ]);\n prototypeWhitelist.set(String.prototype, stringMethods);\n\n // Allow basic object methods\n const objectMethods = new Set(['hasOwnProperty', 'toString', 'valueOf']);\n prototypeWhitelist.set(Object.prototype, objectMethods);\n\n return new Sandbox({\n globals,\n prototypeWhitelist,\n });\n }\n\n /**\n * Evaluate simple fail_if condition\n */\n async evaluateSimpleCondition(\n checkName: string,\n checkSchema: string,\n checkGroup: string,\n reviewSummary: ReviewSummary,\n expression: string,\n previousOutputs?: Record<string, ReviewSummary>\n ): Promise<boolean> {\n const context = this.buildEvaluationContext(\n checkName,\n checkSchema,\n checkGroup,\n reviewSummary,\n previousOutputs\n );\n\n try {\n return this.evaluateExpression(expression, context);\n } catch (error) {\n console.warn(`Failed to evaluate fail_if expression: ${error}`);\n return false; // Don't fail on evaluation errors\n }\n }\n\n /**\n * Determine if the event is related to pull requests\n */\n private determineIfPullRequest(eventType?: string): boolean {\n if (!eventType) return false;\n\n const prEvents = ['pr_opened', 'pr_updated', 'pr_closed', 'pull_request'];\n return prEvents.includes(eventType) || eventType.startsWith('pr_');\n }\n\n /**\n * Determine if the event is related to issues\n */\n private determineIfIssue(eventType?: string): boolean {\n if (!eventType) return false;\n\n const issueEvents = ['issue_opened', 'issue_comment', 'issues'];\n return issueEvents.includes(eventType) || eventType.startsWith('issue_');\n }\n\n /**\n * Evaluate if condition to determine whether a check should run\n */\n async evaluateIfCondition(\n checkName: string,\n expression: string,\n contextData?: {\n branch?: string;\n baseBranch?: string;\n filesChanged?: string[];\n event?: string;\n environment?: Record<string, string>;\n previousResults?: Map<string, ReviewSummary>;\n }\n ): Promise<boolean> {\n // Build context for if evaluation\n const context = {\n // Check metadata\n checkName,\n\n // Git context\n branch: contextData?.branch || 'unknown',\n baseBranch: contextData?.baseBranch || 'main',\n filesChanged: contextData?.filesChanged || [],\n filesCount: contextData?.filesChanged?.length || 0,\n\n // GitHub event context\n event: {\n event_name: contextData?.event || 'manual',\n action: undefined, // Would be populated from actual GitHub context\n repository: undefined, // Would be populated from actual GitHub context\n },\n\n // Environment variables\n env: contextData?.environment || {},\n\n // Previous check results (unwrap output field like templates do)\n outputs: contextData?.previousResults\n ? (() => {\n const outputs: Record<string, unknown> = {};\n for (const [checkName, result] of contextData.previousResults) {\n // If the result has a direct output field, use it directly\n // Otherwise, expose the entire result as-is\n const summary = result as ReviewSummary & { output?: unknown };\n outputs[checkName] = summary.output !== undefined ? summary.output : summary;\n }\n return outputs;\n })()\n : {},\n\n // Required output property (empty for if conditions)\n output: {\n issues: [],\n },\n\n // Utility metadata\n metadata: {\n checkName,\n schema: '',\n group: '',\n criticalIssues: 0,\n errorIssues: 0,\n warningIssues: 0,\n infoIssues: 0,\n totalIssues: 0,\n hasChanges: (contextData?.filesChanged?.length || 0) > 0,\n branch: contextData?.branch || 'unknown',\n event: contextData?.event || 'manual',\n },\n };\n\n try {\n return this.evaluateExpression(expression, context);\n } catch (error) {\n console.warn(`Failed to evaluate if expression for check '${checkName}': ${error}`);\n // Default to running the check if evaluation fails\n return true;\n }\n }\n\n /**\n * Evaluate all failure conditions for a check result\n */\n async evaluateConditions(\n checkName: string,\n checkSchema: string,\n checkGroup: string,\n reviewSummary: ReviewSummary,\n globalConditions?: FailureConditions,\n checkConditions?: FailureConditions,\n previousOutputs?: Record<string, ReviewSummary>\n ): Promise<FailureConditionResult[]> {\n const context = this.buildEvaluationContext(\n checkName,\n checkSchema,\n checkGroup,\n reviewSummary,\n previousOutputs\n );\n\n const results: FailureConditionResult[] = [];\n\n // Evaluate global conditions first\n if (globalConditions) {\n const globalResults = await this.evaluateConditionSet(globalConditions, context, 'global');\n results.push(...globalResults);\n }\n\n // Evaluate check-specific conditions (these override global ones with same name)\n if (checkConditions) {\n const checkResults = await this.evaluateConditionSet(checkConditions, context, 'check');\n\n // Remove global conditions that are overridden by check-specific ones\n const overriddenConditions = new Set(Object.keys(checkConditions));\n const filteredResults = results.filter(\n result => !overriddenConditions.has(result.conditionName)\n );\n\n results.length = 0;\n results.push(...filteredResults, ...checkResults);\n }\n\n return results;\n }\n\n /**\n * Evaluate a set of failure conditions\n */\n private async evaluateConditionSet(\n conditions: FailureConditions,\n context: FailureConditionContext,\n source: 'global' | 'check'\n ): Promise<FailureConditionResult[]> {\n const results: FailureConditionResult[] = [];\n\n for (const [conditionName, condition] of Object.entries(conditions)) {\n try {\n const result = await this.evaluateSingleCondition(conditionName, condition, context);\n results.push(result);\n } catch (error) {\n // If evaluation fails, create an error result\n results.push({\n conditionName,\n failed: false,\n expression: this.extractExpression(condition),\n severity: 'error',\n haltExecution: false,\n error: `Failed to evaluate ${source} condition '${conditionName}': ${\n error instanceof Error ? error.message : String(error)\n }`,\n });\n }\n }\n\n return results;\n }\n\n /**\n * Evaluate a single failure condition\n */\n private async evaluateSingleCondition(\n conditionName: string,\n condition: FailureCondition,\n context: FailureConditionContext\n ): Promise<FailureConditionResult> {\n const expression = this.extractExpression(condition);\n const config = this.extractConditionConfig(condition);\n\n try {\n const failed = this.evaluateExpression(expression, context);\n\n return {\n conditionName,\n failed,\n expression,\n message: config.message,\n severity: config.severity || 'error',\n haltExecution: config.halt_execution || false,\n };\n } catch (error) {\n throw new Error(\n `Expression evaluation error: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n /**\n * Secure expression evaluation using SandboxJS\n * Supports the same GitHub Actions-style functions as the previous implementation\n */\n private evaluateExpression(condition: string, context: FailureConditionContext): boolean {\n try {\n // Normalize multi-line or semicolon-separated expressions.\n // Allows writing debug statements on separate lines, e.g.:\n // log(\"start\")\n // log(outputs)\n // outputs[\"fetch-tickets\"].issueType === 'Bug'\n // We convert to a single expression using the comma operator so the\n // final expression determines the boolean result.\n const normalize = (expr: string): string => {\n const trimmed = expr.trim();\n // If it's already a single-line expression without semicolons, keep it.\n if (!/[\\n;]/.test(trimmed)) return trimmed;\n\n // Split on newlines/semicolons, drop empty and comment-only lines.\n const parts = trimmed\n .split(/[\\n;]+/)\n .map(s => s.trim())\n .filter(s => s.length > 0 && !s.startsWith('//'));\n\n if (parts.length === 0) return 'true';\n\n // Support an explicit return in the last statement.\n const lastRaw = parts.pop() as string;\n const last = lastRaw.replace(/^return\\s+/i, '').trim();\n\n // Join leading statements with comma operator; last expression returns value.\n if (parts.length === 0) return last;\n return `(${parts.join(', ')}, ${last})`;\n };\n\n // note: normalization happens later only if raw compilation fails\n // Helper functions for GitHub Actions-style expressions\n const contains = (searchString: string, searchValue: string): boolean =>\n String(searchString).toLowerCase().includes(String(searchValue).toLowerCase());\n\n const startsWith = (searchString: string, searchValue: string): boolean =>\n String(searchString).toLowerCase().startsWith(String(searchValue).toLowerCase());\n\n const endsWith = (searchString: string, searchValue: string): boolean =>\n String(searchString).toLowerCase().endsWith(String(searchValue).toLowerCase());\n\n const length = (value: string | unknown[] | Record<string, unknown>): number => {\n if (typeof value === 'string' || Array.isArray(value)) {\n return value.length;\n }\n if (value && typeof value === 'object') {\n return Object.keys(value).length;\n }\n return 0;\n };\n\n const always = (): boolean => true;\n const success = (): boolean => true;\n const failure = (): boolean => false;\n\n // Debug logging function for printing to console\n const log = (...args: unknown[]): void => {\n console.log('🔍 Debug:', ...args);\n };\n\n // Helper functions for array operations\n const hasIssue = (issues: unknown[], field: string, value: unknown): boolean => {\n if (!Array.isArray(issues)) return false;\n return issues.some(issue => (issue as Record<string, unknown>)[field] === value);\n };\n\n const countIssues = (issues: unknown[], field: string, value: unknown): number => {\n if (!Array.isArray(issues)) return 0;\n return issues.filter(issue => (issue as Record<string, unknown>)[field] === value).length;\n };\n\n const hasFileMatching = (issues: unknown[], pattern: string): boolean => {\n if (!Array.isArray(issues)) return false;\n return issues.some(issue => (issue as { file?: string }).file?.includes(pattern));\n };\n\n const hasSuggestion = (suggestions: string[], text: string): boolean => {\n if (!Array.isArray(suggestions)) return false;\n return suggestions.some(s => s.toLowerCase().includes(text.toLowerCase()));\n };\n\n // Backward compatibility aliases\n const hasIssueWith = hasIssue;\n const hasFileWith = hasFileMatching;\n\n // Extract context variables\n const output = context.output || {};\n const issues = output.issues || [];\n const suggestions: string[] = [];\n\n // Backward compatibility: provide metadata for transition period\n // TODO: Remove after all configurations are updated\n const metadata = context.metadata || {\n checkName: context.checkName || '',\n schema: context.schema || '',\n group: context.group || '',\n criticalIssues: issues.filter((i: { severity?: string }) => i.severity === 'critical')\n .length,\n errorIssues: issues.filter((i: { severity?: string }) => i.severity === 'error').length,\n warningIssues: issues.filter((i: { severity?: string }) => i.severity === 'warning').length,\n infoIssues: issues.filter((i: { severity?: string }) => i.severity === 'info').length,\n totalIssues: issues.length,\n hasChanges: context.hasChanges || false,\n };\n\n // Legacy variables for backward compatibility\n const criticalIssues = metadata.criticalIssues;\n const errorIssues = metadata.errorIssues;\n const totalIssues = metadata.totalIssues;\n const warningIssues = metadata.warningIssues;\n const infoIssues = metadata.infoIssues;\n\n // Additional context for 'if' conditions and some failure conditions\n const checkName = context.checkName || '';\n const schema = context.schema || '';\n const group = context.group || '';\n const branch = context.branch || 'unknown';\n const baseBranch = context.baseBranch || 'main';\n const filesChanged = context.filesChanged || [];\n const filesCount = context.filesCount || 0;\n const event = context.event || 'manual';\n const env = context.env || {};\n const outputs = context.outputs || {};\n const debugData = context.debug || null;\n\n // Create scope with all context variables and helper functions\n const scope = {\n // Primary context variables\n output,\n outputs,\n debug: debugData,\n // Legacy compatibility variables\n issues,\n suggestions,\n metadata,\n criticalIssues,\n errorIssues,\n totalIssues,\n warningIssues,\n infoIssues,\n // If condition context\n checkName,\n schema,\n group,\n branch,\n baseBranch,\n filesChanged,\n filesCount,\n event,\n env,\n // Helper functions\n contains,\n startsWith,\n endsWith,\n length,\n always,\n success,\n failure,\n log,\n hasIssue,\n countIssues,\n hasFileMatching,\n hasSuggestion,\n hasIssueWith,\n hasFileWith,\n };\n\n // Compile and execute the expression in the sandbox\n const raw = condition.trim();\n if (!this.sandbox) {\n this.sandbox = this.createSecureSandbox();\n }\n let exec: ReturnType<typeof this.sandbox.compile>;\n try {\n // Try compiling the raw expression as-is first (supports multi-line logical expressions)\n exec = this.sandbox.compile(`return (${raw});`);\n } catch {\n // Fallback: normalize multi-line statements into a comma-chain expression\n const normalizedExpr = normalize(condition);\n exec = this.sandbox.compile(`return (${normalizedExpr});`);\n }\n const result = exec(scope).run();\n\n // Ensure we return a boolean\n return Boolean(result);\n } catch (error) {\n console.error('❌ Failed to evaluate expression:', condition, error);\n // Re-throw the error so it can be caught at a higher level for error reporting\n throw error;\n }\n }\n\n /**\n * Extract the expression from a failure condition\n */\n private extractExpression(condition: FailureCondition): string {\n if (typeof condition === 'string') {\n return condition;\n }\n return condition.condition;\n }\n\n /**\n * Extract configuration from a failure condition\n */\n private extractConditionConfig(condition: FailureCondition): {\n message?: string;\n severity?: FailureConditionSeverity;\n halt_execution?: boolean;\n } {\n if (typeof condition === 'string') {\n return {};\n }\n return {\n message: condition.message,\n severity: condition.severity,\n halt_execution: condition.halt_execution,\n };\n }\n\n /**\n * Build the evaluation context for expressions\n */\n private buildEvaluationContext(\n checkName: string,\n checkSchema: string,\n checkGroup: string,\n reviewSummary: ReviewSummary,\n previousOutputs?: Record<string, ReviewSummary>\n ): FailureConditionContext {\n const { issues, debug } = reviewSummary;\n const reviewSummaryWithOutput = reviewSummary as ReviewSummary & { output?: unknown };\n\n // Extract output field to avoid nesting (output.output)\n const {\n output: extractedOutput,\n // Exclude issues from otherFields since we handle it separately\n issues: _issues, // eslint-disable-line @typescript-eslint/no-unused-vars\n ...otherFields\n } = reviewSummaryWithOutput as any;\n\n // Build output object with safety for array-based outputs (forEach aggregation)\n const aggregatedOutput: Record<string, unknown> = {\n issues: (issues || []).map(issue => ({\n file: issue.file,\n line: issue.line,\n endLine: issue.endLine,\n ruleId: issue.ruleId,\n message: issue.message,\n severity: issue.severity,\n category: issue.category,\n group: issue.group,\n schema: issue.schema,\n suggestion: issue.suggestion,\n replacement: issue.replacement,\n })),\n // Include additional schema-specific data from reviewSummary\n ...otherFields,\n };\n\n if (Array.isArray(extractedOutput)) {\n // Preserve items array and lift common flags for convenience (e.g., output.error)\n aggregatedOutput.items = extractedOutput;\n const anyError = extractedOutput.find(\n it => it && typeof it === 'object' && (it as Record<string, unknown>).error\n ) as Record<string, unknown> | undefined;\n if (anyError && anyError.error !== undefined) {\n aggregatedOutput.error = anyError.error;\n }\n } else if (extractedOutput && typeof extractedOutput === 'object') {\n Object.assign(aggregatedOutput, extractedOutput as Record<string, unknown>);\n }\n\n const context: FailureConditionContext = {\n output: aggregatedOutput,\n outputs: (() => {\n if (!previousOutputs) return {};\n const outputs: Record<string, unknown> = {};\n for (const [checkName, result] of Object.entries(previousOutputs)) {\n // If the result has a direct output field, use it directly\n // Otherwise, expose the entire result as-is\n const summary = result as ReviewSummary & { output?: unknown };\n outputs[checkName] = summary.output !== undefined ? summary.output : summary;\n }\n return outputs;\n })(),\n // Add basic context info for failure conditions\n checkName: checkName,\n schema: checkSchema,\n group: checkGroup,\n };\n\n // Add debug information if available\n if (debug) {\n context.debug = {\n errors: debug.errors || [],\n processingTime: debug.processingTime || 0,\n provider: debug.provider || 'unknown',\n model: debug.model || 'unknown',\n };\n }\n\n return context;\n }\n\n /**\n * Check if any failure condition requires halting execution\n */\n static shouldHaltExecution(results: FailureConditionResult[]): boolean {\n return results.some(result => result.failed && result.haltExecution);\n }\n\n /**\n * Get all failed conditions\n */\n static getFailedConditions(results: FailureConditionResult[]): FailureConditionResult[] {\n return results.filter(result => result.failed);\n }\n\n /**\n * Group results by severity\n */\n static groupResultsBySeverity(results: FailureConditionResult[]): {\n error: FailureConditionResult[];\n warning: FailureConditionResult[];\n info: FailureConditionResult[];\n } {\n return {\n // Only 'error' severity now (no backward compatibility needed here as this is internal)\n error: results.filter(r => r.severity === 'error'),\n warning: results.filter(r => r.severity === 'warning'),\n info: results.filter(r => r.severity === 'info'),\n };\n }\n\n /**\n * Format results for display\n */\n static formatResults(results: FailureConditionResult[]): string {\n const failed = FailureConditionEvaluator.getFailedConditions(results);\n\n if (failed.length === 0) {\n return '✅ All failure conditions passed';\n }\n\n const grouped = FailureConditionEvaluator.groupResultsBySeverity(failed);\n const sections: string[] = [];\n\n if (grouped.error.length > 0) {\n sections.push(`❌ **Error severity conditions (${grouped.error.length}):**`);\n grouped.error.forEach(result => {\n sections.push(` - ${result.conditionName}: ${result.message || result.expression}`);\n });\n }\n\n if (grouped.warning.length > 0) {\n sections.push(`⚠️ **Warning conditions (${grouped.warning.length}):**`);\n grouped.warning.forEach(result => {\n sections.push(` - ${result.conditionName}: ${result.message || result.expression}`);\n });\n }\n\n if (grouped.info.length > 0) {\n sections.push(`ℹ️ **Info conditions (${grouped.info.length}):**`);\n grouped.info.forEach(result => {\n sections.push(` - ${result.conditionName}: ${result.message || result.expression}`);\n });\n }\n\n return sections.join('\\n');\n }\n}\n","/**\n * GitHub Check Service for creating and managing check runs based on failure conditions\n */\n\nimport { Octokit } from '@octokit/rest';\nimport { FailureConditionResult } from './types/config';\nimport { ReviewIssue } from './reviewer';\n\nexport interface CheckRunOptions {\n owner: string;\n repo: string;\n head_sha: string;\n name: string;\n details_url?: string;\n external_id?: string;\n}\n\nexport interface CheckRunAnnotation {\n path: string;\n start_line: number;\n end_line: number;\n annotation_level: 'notice' | 'warning' | 'failure';\n message: string;\n title?: string;\n raw_details?: string;\n}\n\nexport interface CheckRunSummary {\n title: string;\n summary: string;\n text?: string;\n}\n\nexport type CheckRunStatus = 'queued' | 'in_progress' | 'completed';\nexport type CheckRunConclusion =\n | 'success'\n | 'failure'\n | 'neutral'\n | 'cancelled'\n | 'timed_out'\n | 'action_required';\n\n/**\n * Service for managing GitHub Check Runs based on Visor failure conditions\n */\nexport class GitHubCheckService {\n private octokit: Octokit;\n private maxAnnotations = 50; // GitHub API limit\n\n constructor(octokit: Octokit) {\n this.octokit = octokit;\n }\n\n /**\n * Create a new check run in queued status\n */\n async createCheckRun(\n options: CheckRunOptions,\n summary?: CheckRunSummary\n ): Promise<{ id: number; url: string }> {\n try {\n const response = await this.octokit.rest.checks.create({\n owner: options.owner,\n repo: options.repo,\n name: options.name,\n head_sha: options.head_sha,\n status: 'queued',\n details_url: options.details_url,\n external_id: options.external_id,\n output: summary\n ? {\n title: summary.title,\n summary: summary.summary,\n text: summary.text,\n }\n : undefined,\n });\n\n return {\n id: response.data.id,\n url: response.data.html_url || '',\n };\n } catch (error) {\n throw new Error(\n `Failed to create check run: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n /**\n * Update check run to in_progress status\n */\n async updateCheckRunInProgress(\n owner: string,\n repo: string,\n check_run_id: number,\n summary?: CheckRunSummary\n ): Promise<void> {\n try {\n await this.octokit.rest.checks.update({\n owner,\n repo,\n check_run_id,\n status: 'in_progress',\n output: summary\n ? {\n title: summary.title,\n summary: summary.summary,\n text: summary.text,\n }\n : undefined,\n });\n } catch (error) {\n throw new Error(\n `Failed to update check run to in_progress: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n /**\n * Complete a check run with results based on failure conditions\n */\n async completeCheckRun(\n owner: string,\n repo: string,\n check_run_id: number,\n checkName: string,\n failureResults: FailureConditionResult[],\n reviewIssues: ReviewIssue[] = [],\n executionError?: string,\n filesChangedInCommit?: string[],\n prNumber?: number,\n currentCommitSha?: string\n ): Promise<void> {\n try {\n // Clear old annotations from ALL previous check runs (including older runs on the same commit)\n // This prevents annotation accumulation when a check runs multiple times\n if (prNumber && currentCommitSha) {\n await this.clearOldAnnotations(\n owner,\n repo,\n prNumber,\n checkName,\n currentCommitSha,\n check_run_id\n );\n }\n\n const { conclusion, summary } = this.determineCheckRunConclusion(\n checkName,\n failureResults,\n reviewIssues,\n executionError\n );\n\n // Filter annotations to only include files changed in this commit\n // This prevents old annotations from previous commits showing up in the Files tab\n let filteredIssues = reviewIssues;\n if (filesChangedInCommit && filesChangedInCommit.length > 0) {\n filteredIssues = reviewIssues.filter(issue =>\n filesChangedInCommit.some(changedFile => issue.file === changedFile)\n );\n }\n\n const annotations = this.convertIssuesToAnnotations(filteredIssues);\n\n await this.octokit.rest.checks.update({\n owner,\n repo,\n check_run_id,\n status: 'completed',\n conclusion,\n completed_at: new Date().toISOString(),\n output: {\n title: summary.title,\n summary: summary.summary,\n text: summary.text,\n annotations: annotations.slice(0, this.maxAnnotations), // GitHub limit\n },\n });\n } catch (error) {\n throw new Error(\n `Failed to complete check run: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n /**\n * Determine check run conclusion based on failure conditions and issues\n */\n private determineCheckRunConclusion(\n checkName: string,\n failureResults: FailureConditionResult[],\n reviewIssues: ReviewIssue[],\n executionError?: string\n ): { conclusion: CheckRunConclusion; summary: CheckRunSummary } {\n // Handle execution errors first\n if (executionError) {\n return {\n conclusion: 'failure',\n summary: {\n title: '❌ Check Execution Failed',\n summary: `The ${checkName} check failed to execute properly.`,\n text: `**Error:** ${executionError}\\n\\nPlease check your configuration and try again.`,\n },\n };\n }\n\n // Check if any fail_if conditions were met\n const failedConditions = failureResults.filter(result => result.failed);\n\n // Count issues by severity (for informational display only)\n const criticalIssues = reviewIssues.filter(issue => issue.severity === 'critical').length;\n const errorIssues = reviewIssues.filter(issue => issue.severity === 'error').length;\n const warningIssues = reviewIssues.filter(issue => issue.severity === 'warning').length;\n const totalIssues = reviewIssues.length;\n\n // Determine conclusion ONLY based on fail_if evaluation results\n // The presence of issues (critical, error, warning) does NOT affect the conclusion\n // Only the fail_if condition determines pass/fail status\n let conclusion: CheckRunConclusion;\n let title: string;\n let summaryText: string;\n let details: string;\n\n if (failedConditions.length > 0) {\n // Check fails if fail_if condition is met\n conclusion = 'failure';\n title = '🚨 Check Failed';\n summaryText = `${checkName} check failed because fail_if condition was met.`;\n\n details = this.formatCheckDetails(failureResults, reviewIssues, {\n failedConditions: failedConditions.length,\n warningConditions: 0,\n criticalIssues,\n errorIssues,\n warningIssues,\n totalIssues,\n });\n } else {\n // No fail_if conditions met - check passes regardless of issues found\n conclusion = 'success';\n\n // Adjust the title and summary based on issues found, but conclusion remains success\n if (criticalIssues > 0 || errorIssues > 0) {\n title = '✅ Check Passed (Issues Found)';\n summaryText = `${checkName} check passed. Found ${criticalIssues} critical and ${errorIssues} error issues, but fail_if condition was not met.`;\n } else if (warningIssues > 0) {\n title = '✅ Check Passed (Warnings Found)';\n summaryText = `${checkName} check passed. Found ${warningIssues} warning${warningIssues === 1 ? '' : 's'}, but fail_if condition was not met.`;\n } else {\n title = '✅ Check Passed';\n summaryText = `${checkName} check completed successfully with no issues found.`;\n }\n\n details = this.formatCheckDetails(failureResults, reviewIssues, {\n failedConditions: 0,\n warningConditions: 0,\n criticalIssues,\n errorIssues,\n warningIssues,\n totalIssues,\n });\n }\n\n return {\n conclusion,\n summary: {\n title,\n summary: summaryText,\n text: details,\n },\n };\n }\n\n /**\n * Format detailed check results for the check run summary\n */\n private formatCheckDetails(\n failureResults: FailureConditionResult[],\n reviewIssues: ReviewIssue[],\n counts: {\n failedConditions: number;\n warningConditions: number;\n criticalIssues: number;\n errorIssues: number;\n warningIssues: number;\n totalIssues: number;\n }\n ): string {\n const sections: string[] = [];\n\n // Summary section\n sections.push('## 📊 Summary');\n sections.push(`- **Total Issues:** ${counts.totalIssues}`);\n if (counts.criticalIssues > 0) {\n sections.push(`- **Critical Issues:** ${counts.criticalIssues}`);\n }\n if (counts.errorIssues > 0) {\n sections.push(`- **Error Issues:** ${counts.errorIssues}`);\n }\n if (counts.warningIssues > 0) {\n sections.push(`- **Warning Issues:** ${counts.warningIssues}`);\n }\n sections.push('');\n\n // Failure conditions section\n if (failureResults.length > 0) {\n sections.push('## 🔍 Failure Condition Results');\n\n const failedConditions = failureResults.filter(result => result.failed);\n const passedConditions = failureResults.filter(result => !result.failed);\n\n if (failedConditions.length > 0) {\n sections.push('### ❌ Failed Conditions');\n failedConditions.forEach(condition => {\n sections.push(\n `- **${condition.conditionName}**: ${condition.message || condition.expression}`\n );\n if (condition.severity === 'error') {\n sections.push(` - ⚠️ **Severity:** Error`);\n }\n });\n sections.push('');\n }\n\n if (passedConditions.length > 0) {\n sections.push('### ✅ Passed Conditions');\n passedConditions.forEach(condition => {\n sections.push(\n `- **${condition.conditionName}**: ${condition.message || 'Condition passed'}`\n );\n });\n sections.push('');\n }\n }\n\n // Issues by category section\n if (reviewIssues.length > 0) {\n const issuesByCategory = this.groupIssuesByCategory(reviewIssues);\n sections.push('## 🐛 Issues by Category');\n\n Object.entries(issuesByCategory).forEach(([category, issues]) => {\n if (issues.length > 0) {\n sections.push(\n `### ${this.getCategoryEmoji(category)} ${category.charAt(0).toUpperCase() + category.slice(1)} (${issues.length})`\n );\n\n // Show only first 5 issues per category to keep the summary concise\n const displayIssues = issues.slice(0, 5);\n displayIssues.forEach(issue => {\n const severityIcon = this.getSeverityIcon(issue.severity);\n sections.push(`- ${severityIcon} **${issue.file}:${issue.line}** - ${issue.message}`);\n });\n\n if (issues.length > 5) {\n sections.push(`- *...and ${issues.length - 5} more ${category} issues*`);\n }\n sections.push('');\n }\n });\n }\n\n // Footer\n sections.push('');\n sections.push('---');\n sections.push('');\n sections.push(\n '*Generated by [Visor](https://github.com/probelabs/visor) - AI-powered code review*'\n );\n\n return sections.join('\\n');\n }\n\n /**\n * Convert review issues to GitHub check run annotations\n */\n private convertIssuesToAnnotations(reviewIssues: ReviewIssue[]): CheckRunAnnotation[] {\n return reviewIssues\n .slice(0, this.maxAnnotations) // Respect GitHub's annotation limit\n .map(issue => ({\n path: issue.file,\n start_line: issue.line,\n end_line: issue.endLine || issue.line,\n annotation_level: this.mapSeverityToAnnotationLevel(issue.severity),\n message: issue.message,\n title: `${issue.category} Issue`,\n raw_details: issue.suggestion || undefined,\n }));\n }\n\n /**\n * Map Visor issue severity to GitHub annotation level\n */\n private mapSeverityToAnnotationLevel(severity: string): 'notice' | 'warning' | 'failure' {\n switch (severity) {\n case 'critical':\n case 'error':\n return 'failure';\n case 'warning':\n return 'warning';\n case 'info':\n default:\n return 'notice';\n }\n }\n\n /**\n * Group issues by category\n */\n private groupIssuesByCategory(issues: ReviewIssue[]): Record<string, ReviewIssue[]> {\n const grouped: Record<string, ReviewIssue[]> = {};\n\n issues.forEach(issue => {\n const category = issue.category || 'general';\n if (!grouped[category]) {\n grouped[category] = [];\n }\n grouped[category].push(issue);\n });\n\n return grouped;\n }\n\n /**\n * Get emoji for issue category\n */\n private getCategoryEmoji(category: string): string {\n const emojiMap: Record<string, string> = {\n security: '🔐',\n performance: '⚡',\n style: '🎨',\n logic: '🧠',\n architecture: '🏗️',\n documentation: '📚',\n general: '📝',\n };\n return emojiMap[category.toLowerCase()] || '📝';\n }\n\n /**\n * Get icon for issue severity\n */\n private getSeverityIcon(severity: string): string {\n const iconMap: Record<string, string> = {\n critical: '🚨',\n error: '❌',\n warning: '⚠️',\n info: 'ℹ️',\n };\n return iconMap[severity.toLowerCase()] || 'ℹ️';\n }\n\n /**\n * Create multiple check runs for different checks with failure condition support\n */\n async createMultipleCheckRuns(\n options: CheckRunOptions,\n checkResults: Array<{\n checkName: string;\n failureResults: FailureConditionResult[];\n reviewIssues: ReviewIssue[];\n executionError?: string;\n }>\n ): Promise<Array<{ checkName: string; id: number; url: string }>> {\n const results: Array<{ checkName: string; id: number; url: string }> = [];\n\n for (const checkResult of checkResults) {\n try {\n // Create check run\n const checkRun = await this.createCheckRun({\n ...options,\n name: `Visor: ${checkResult.checkName}`,\n external_id: `visor-${checkResult.checkName}-${options.head_sha.substring(0, 7)}`,\n });\n\n // Update to in progress\n await this.updateCheckRunInProgress(options.owner, options.repo, checkRun.id, {\n title: `Running ${checkResult.checkName} check...`,\n summary: `Analyzing code with ${checkResult.checkName} check using AI.`,\n });\n\n // Complete with results\n await this.completeCheckRun(\n options.owner,\n options.repo,\n checkRun.id,\n checkResult.checkName,\n checkResult.failureResults,\n checkResult.reviewIssues,\n checkResult.executionError\n );\n\n results.push({\n checkName: checkResult.checkName,\n id: checkRun.id,\n url: checkRun.url,\n });\n } catch (error) {\n console.error(`Failed to create check run for ${checkResult.checkName}:`, error);\n // Continue with other checks even if one fails\n }\n }\n\n return results;\n }\n\n /**\n * Get check runs for a specific commit\n */\n async getCheckRuns(\n owner: string,\n repo: string,\n ref: string\n ): Promise<Array<{ id: number; name: string; status: string; conclusion: string | null }>> {\n try {\n const response = await this.octokit.rest.checks.listForRef({\n owner,\n repo,\n ref,\n filter: 'all',\n });\n\n return response.data.check_runs\n .filter(check => check.name.startsWith('Visor:'))\n .map(check => ({\n id: check.id,\n name: check.name,\n status: check.status,\n conclusion: check.conclusion,\n }));\n } catch (error) {\n throw new Error(\n `Failed to get check runs: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n /**\n * Get check runs for a specific commit SHA\n * Returns all check runs with the given name on this commit\n */\n async getCheckRunsForCommit(\n owner: string,\n repo: string,\n commitSha: string,\n checkName: string\n ): Promise<Array<{ id: number; head_sha: string }>> {\n try {\n const checksResponse = await this.octokit.rest.checks.listForRef({\n owner,\n repo,\n ref: commitSha,\n check_name: `Visor: ${checkName}`,\n });\n\n return checksResponse.data.check_runs.map(check => ({\n id: check.id,\n head_sha: commitSha,\n }));\n } catch (error) {\n throw new Error(\n `Failed to get check runs for commit ${commitSha}: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n /**\n * Clear annotations from old check runs on the current commit\n * This prevents annotation accumulation when a check runs multiple times on the same commit\n * (e.g., force push, re-running checks)\n */\n async clearOldAnnotations(\n owner: string,\n repo: string,\n prNumber: number, // Not used, kept for backward compatibility\n checkName: string,\n currentCommitSha: string,\n currentCheckRunId: number\n ): Promise<void> {\n try {\n // Get all check runs for this check name on the current commit\n const allCheckRuns = await this.getCheckRunsForCommit(\n owner,\n repo,\n currentCommitSha,\n checkName\n );\n\n // Filter out the CURRENT check run (by ID)\n // This handles the case where Visor runs multiple times on the same commit\n const oldRuns = allCheckRuns.filter(run => run.id !== currentCheckRunId);\n\n if (oldRuns.length === 0) {\n console.debug(`No old check runs to clear for ${checkName} on commit ${currentCommitSha}`);\n return;\n }\n\n console.debug(\n `Clearing ${oldRuns.length} old check run(s) for ${checkName} on commit ${currentCommitSha.substring(0, 7)} (keeping current run ${currentCheckRunId})`\n );\n\n // Update each old check run to have empty annotations\n for (const run of oldRuns) {\n try {\n await this.octokit.rest.checks.update({\n owner,\n repo,\n check_run_id: run.id,\n output: {\n title: 'Outdated',\n summary: 'This check has been superseded by a newer run.',\n annotations: [], // Clear annotations\n },\n });\n console.debug(`✓ Cleared annotations from check run ${run.id}`);\n } catch (error) {\n console.debug(`Could not clear annotations for check run ${run.id}:`, error);\n }\n }\n } catch (error) {\n // Don't fail the whole check if we can't clear old annotations\n console.warn('Failed to clear old annotations:', error);\n }\n }\n}\n","import {\n PRReviewer,\n ReviewSummary,\n ReviewOptions,\n GroupedCheckResults,\n CheckResult,\n ReviewIssue,\n} from './reviewer';\nimport { GitRepositoryAnalyzer, GitRepositoryInfo } from './git-repository-analyzer';\nimport { AnalysisResult } from './output-formatters';\nimport { PRInfo } from './pr-analyzer';\nimport { CheckProviderRegistry } from './providers/check-provider-registry';\nimport { CheckProviderConfig } from './providers/check-provider.interface';\nimport { DependencyResolver, DependencyGraph } from './dependency-resolver';\nimport { FailureConditionEvaluator } from './failure-condition-evaluator';\nimport { FailureConditionResult, CheckConfig } from './types/config';\nimport { GitHubCheckService, CheckRunOptions } from './github-check-service';\nimport { IssueFilter } from './issue-filter';\nimport { logger } from './logger';\nimport Sandbox from '@nyariv/sandboxjs';\nimport { VisorConfig, OnFailConfig, OnSuccessConfig } from './types/config';\n\ntype ExtendedReviewSummary = ReviewSummary & {\n output?: unknown;\n content?: string;\n isForEach?: boolean;\n forEachItems?: unknown[];\n};\n\n/**\n * Statistics for a single check execution\n */\nexport interface CheckExecutionStats {\n checkName: string;\n totalRuns: number; // How many times the check executed (1 or forEach iterations)\n successfulRuns: number;\n failedRuns: number;\n skipped: boolean;\n skipReason?: 'if_condition' | 'fail_fast' | 'dependency_failed';\n skipCondition?: string; // The actual if condition text\n totalDuration: number; // Total duration in milliseconds\n perIterationDuration?: number[]; // Duration for each iteration (if forEach)\n issuesFound: number;\n issuesBySeverity: {\n critical: number;\n error: number;\n warning: number;\n info: number;\n };\n outputsProduced?: number; // Number of outputs for forEach checks\n errorMessage?: string; // Error message if failed\n forEachPreview?: string[]; // Preview of forEach items processed (first few)\n}\n\n/**\n * Overall execution statistics for all checks\n */\nexport interface ExecutionStatistics {\n totalChecksConfigured: number;\n totalExecutions: number; // Sum of all runs including forEach iterations\n successfulExecutions: number;\n failedExecutions: number;\n skippedChecks: number;\n totalDuration: number;\n checks: CheckExecutionStats[];\n}\n\n/**\n * Result of executing checks, including both the grouped results and execution statistics\n */\nexport interface ExecutionResult {\n results: GroupedCheckResults;\n statistics: ExecutionStatistics;\n}\n\n/**\n * Filter environment variables to only include safe ones for sandbox evaluation\n */\nfunction getSafeEnvironmentVariables(): Record<string, string> {\n const safeEnvVars = [\n 'CI',\n 'GITHUB_EVENT_NAME',\n 'GITHUB_REPOSITORY',\n 'GITHUB_REF',\n 'GITHUB_SHA',\n 'GITHUB_HEAD_REF',\n 'GITHUB_BASE_REF',\n 'GITHUB_ACTOR',\n 'GITHUB_WORKFLOW',\n 'GITHUB_RUN_ID',\n 'GITHUB_RUN_NUMBER',\n 'NODE_ENV',\n ];\n\n const safeEnv: Record<string, string> = {};\n\n for (const key of safeEnvVars) {\n if (process.env[key]) {\n safeEnv[key] = process.env[key];\n }\n }\n\n return safeEnv;\n}\n\nexport interface MockOctokit {\n rest: {\n pulls: {\n get: () => Promise<{ data: Record<string, unknown> }>;\n listFiles: () => Promise<{ data: Record<string, unknown>[] }>;\n };\n issues: {\n listComments: () => Promise<{ data: Record<string, unknown>[] }>;\n createComment: () => Promise<{ data: Record<string, unknown> }>;\n };\n };\n request: () => Promise<{ data: Record<string, unknown> }>;\n graphql: () => Promise<Record<string, unknown>>;\n log: {\n debug: (...args: unknown[]) => void;\n info: (...args: unknown[]) => void;\n warn: (...args: unknown[]) => void;\n error: (...args: unknown[]) => void;\n };\n hook: {\n before: (...args: unknown[]) => void;\n after: (...args: unknown[]) => void;\n error: (...args: unknown[]) => void;\n wrap: (...args: unknown[]) => void;\n };\n auth: () => Promise<{ token: string }>;\n}\n\nexport interface CheckExecutionOptions {\n checks: string[];\n workingDirectory?: string;\n showDetails?: boolean;\n timeout?: number;\n maxParallelism?: number; // Maximum number of checks to run in parallel (default: 3)\n failFast?: boolean; // Stop execution when any check fails (default: false)\n outputFormat?: string;\n config?: import('./types/config').VisorConfig;\n debug?: boolean; // Enable debug mode to collect AI execution details\n // Tag filter for selective check execution\n tagFilter?: import('./types/config').TagFilter;\n // Webhook context for passing webhook data to http_input providers\n webhookContext?: {\n webhookData: Map<string, unknown>;\n };\n // GitHub Check integration options\n githubChecks?: {\n enabled: boolean;\n octokit?: import('@octokit/rest').Octokit;\n owner?: string;\n repo?: string;\n headSha?: string;\n prNumber?: number;\n };\n}\n\nexport class CheckExecutionEngine {\n private gitAnalyzer: GitRepositoryAnalyzer;\n private mockOctokit: MockOctokit;\n private reviewer: PRReviewer;\n private providerRegistry: CheckProviderRegistry;\n private failureEvaluator: FailureConditionEvaluator;\n private githubCheckService?: GitHubCheckService;\n private checkRunMap?: Map<string, { id: number; url: string }>;\n private githubContext?: { owner: string; repo: string };\n private workingDirectory: string;\n private config?: import('./types/config').VisorConfig;\n private webhookContext?: { webhookData: Map<string, unknown> };\n private routingSandbox?: Sandbox;\n private executionStats: Map<string, CheckExecutionStats> = new Map();\n\n constructor(workingDirectory?: string) {\n this.workingDirectory = workingDirectory || process.cwd();\n this.gitAnalyzer = new GitRepositoryAnalyzer(this.workingDirectory);\n this.providerRegistry = CheckProviderRegistry.getInstance();\n this.failureEvaluator = new FailureConditionEvaluator();\n\n // Create a mock Octokit instance for local analysis\n // This allows us to reuse the existing PRReviewer logic without network calls\n this.mockOctokit = this.createMockOctokit();\n this.reviewer = new PRReviewer(this.mockOctokit as unknown as import('@octokit/rest').Octokit);\n }\n\n /**\n * Lazily create a secure sandbox for routing JS (goto_js, run_js)\n */\n private getRoutingSandbox(): Sandbox {\n if (this.routingSandbox) return this.routingSandbox;\n const globals = {\n ...Sandbox.SAFE_GLOBALS,\n Math,\n JSON,\n console: { log: console.log },\n };\n const prototypeWhitelist = new Map(Sandbox.SAFE_PROTOTYPES);\n this.routingSandbox = new Sandbox({ globals, prototypeWhitelist });\n return this.routingSandbox;\n }\n\n private redact(str: unknown, limit = 200): string {\n try {\n const s = typeof str === 'string' ? str : JSON.stringify(str);\n return s.length > limit ? s.slice(0, limit) + '…' : s;\n } catch {\n return String(str).slice(0, limit);\n }\n }\n\n private async sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n }\n\n private deterministicJitter(baseMs: number, seedStr: string): number {\n let h = 2166136261;\n for (let i = 0; i < seedStr.length; i++) h = (h ^ seedStr.charCodeAt(i)) * 16777619;\n const frac = ((h >>> 0) % 1000) / 1000; // 0..1\n return Math.floor(baseMs * 0.15 * frac); // up to 15% jitter\n }\n\n private computeBackoffDelay(\n attempt: number,\n mode: 'fixed' | 'exponential',\n baseMs: number,\n seed: string\n ): number {\n const jitter = this.deterministicJitter(baseMs, seed);\n if (mode === 'exponential') {\n return baseMs * Math.pow(2, Math.max(0, attempt - 1)) + jitter;\n }\n return baseMs + jitter;\n }\n\n /**\n * Execute a check with retry/backoff and routing semantics (on_fail/on_success)\n */\n private async executeWithRouting(\n checkName: string,\n checkConfig: CheckConfig,\n provider: import('./providers/check-provider.interface').CheckProvider,\n providerConfig: CheckProviderConfig,\n prInfo: PRInfo,\n dependencyResults: Map<string, ReviewSummary>,\n sessionInfo: { parentSessionId?: string; reuseSession?: boolean } | undefined,\n config: VisorConfig | undefined,\n dependencyGraph: DependencyGraph,\n debug?: boolean,\n resultsMap?: Map<string, ReviewSummary>,\n foreachContext?: { index: number; total: number; parent: string }\n ): Promise<ReviewSummary> {\n const log = (msg: string) =>\n (this.config?.output?.pr_comment ? console.error : console.log)(msg);\n const maxLoops = config?.routing?.max_loops ?? 10;\n const defaults = config?.routing?.defaults?.on_fail || {};\n\n const onFail: OnFailConfig | undefined = checkConfig.on_fail\n ? { ...defaults, ...checkConfig.on_fail }\n : Object.keys(defaults).length\n ? defaults\n : undefined;\n const onSuccess: OnSuccessConfig | undefined = checkConfig.on_success;\n\n let attempt = 1;\n let loopCount = 0;\n const seed = `${checkName}-${prInfo.number || 'local'}`;\n\n const allAncestors = DependencyResolver.getAllDependencies(checkName, dependencyGraph.nodes);\n\n const evalRunJs = async (expr?: string, error?: unknown): Promise<string[]> => {\n if (!expr) return [];\n try {\n const sandbox = this.getRoutingSandbox();\n const scope = {\n step: { id: checkName, tags: checkConfig.tags || [], group: checkConfig.group },\n attempt,\n loop: loopCount,\n error,\n foreach: foreachContext\n ? {\n index: foreachContext.index,\n total: foreachContext.total,\n parent: foreachContext.parent,\n }\n : null,\n outputs: Object.fromEntries((dependencyResults || new Map()).entries()),\n pr: {\n number: prInfo.number,\n title: prInfo.title,\n author: prInfo.author,\n branch: prInfo.head,\n base: prInfo.base,\n },\n files: prInfo.files,\n env: getSafeEnvironmentVariables(),\n };\n const code = `\n const step = scope.step; const attempt = scope.attempt; const loop = scope.loop; const error = scope.error; const foreach = scope.foreach; const outputs = scope.outputs; const pr = scope.pr; const files = scope.files; const env = scope.env; const log = (...a)=>console.log('🔍 Debug:',...a);\n const __fn = () => {\\n${expr}\\n};\n const __res = __fn();\n return Array.isArray(__res) ? __res : (__res ? [__res] : []);\n `;\n const exec = sandbox.compile(code);\n const res = exec({ scope }).run();\n if (debug) {\n log(`🔧 Debug: run_js evaluated → [${this.redact(res)}]`);\n }\n return Array.isArray(res) ? res.filter(x => typeof x === 'string') : [];\n } catch (e) {\n if (debug) {\n log(`⚠️ Debug: run_js evaluation failed: ${e instanceof Error ? e.message : String(e)}`);\n }\n return [];\n }\n };\n\n const evalGotoJs = async (expr?: string, error?: unknown): Promise<string | null> => {\n if (!expr) return null;\n try {\n const sandbox = this.getRoutingSandbox();\n const scope = {\n step: { id: checkName, tags: checkConfig.tags || [], group: checkConfig.group },\n attempt,\n loop: loopCount,\n error,\n foreach: foreachContext\n ? {\n index: foreachContext.index,\n total: foreachContext.total,\n parent: foreachContext.parent,\n }\n : null,\n outputs: Object.fromEntries((dependencyResults || new Map()).entries()),\n pr: {\n number: prInfo.number,\n title: prInfo.title,\n author: prInfo.author,\n branch: prInfo.head,\n base: prInfo.base,\n },\n files: prInfo.files,\n env: getSafeEnvironmentVariables(),\n };\n const code = `\n const step = scope.step; const attempt = scope.attempt; const loop = scope.loop; const error = scope.error; const foreach = scope.foreach; const outputs = scope.outputs; const pr = scope.pr; const files = scope.files; const env = scope.env; const log = (...a)=>console.log('🔍 Debug:',...a);\n const __fn = () => {\\n${expr}\\n};\n const __res = __fn();\n return (typeof __res === 'string' && __res) ? __res : null;\n `;\n const exec = sandbox.compile(code);\n const res = exec({ scope }).run();\n if (debug) {\n log(`🔧 Debug: goto_js evaluated → ${this.redact(res)}`);\n }\n return typeof res === 'string' && res ? res : null;\n } catch (e) {\n if (debug) {\n log(`⚠️ Debug: goto_js evaluation failed: ${e instanceof Error ? e.message : String(e)}`);\n }\n return null;\n }\n };\n\n const getAllDepsFromConfig = (name: string): string[] => {\n const visited = new Set<string>();\n const acc: string[] = [];\n const dfs = (n: string) => {\n if (visited.has(n)) return;\n visited.add(n);\n const cfg = config?.checks?.[n];\n const deps = cfg?.depends_on || [];\n for (const d of deps) {\n acc.push(d);\n dfs(d);\n }\n };\n dfs(name);\n return Array.from(new Set(acc));\n };\n\n const executeNamedCheckInline = async (target: string): Promise<ReviewSummary> => {\n const targetCfg = config?.checks?.[target];\n if (!targetCfg) {\n throw new Error(`on_* referenced unknown check '${target}'`);\n }\n // Ensure all dependencies of target are available; execute missing ones in topological order\n // Use config graph (not only current dependencyGraph) so inline steps can bring their own deps\n const allTargetDeps = getAllDepsFromConfig(target);\n if (allTargetDeps.length > 0) {\n // Build subgraph mapping for ordered execution\n const subSet = new Set<string>([...allTargetDeps]);\n const subDeps: Record<string, string[]> = {};\n for (const id of subSet) {\n const cfg = config?.checks?.[id];\n subDeps[id] = (cfg?.depends_on || []).filter(d => subSet.has(d));\n }\n const subGraph = DependencyResolver.buildDependencyGraph(subDeps);\n for (const group of subGraph.executionOrder) {\n for (const depId of group.parallel) {\n // Skip if already have results\n if (resultsMap?.has(depId) || dependencyResults.has(depId)) continue;\n // Execute dependency inline (recursively ensures its deps are also present)\n await executeNamedCheckInline(depId);\n }\n }\n }\n const providerType = targetCfg.type || 'ai';\n const prov = this.providerRegistry.getProviderOrThrow(providerType);\n this.setProviderWebhookContext(prov);\n const provCfg: CheckProviderConfig = {\n type: providerType,\n prompt: targetCfg.prompt,\n exec: targetCfg.exec,\n focus: targetCfg.focus || this.mapCheckNameToFocus(target),\n schema: targetCfg.schema,\n group: targetCfg.group,\n checkName: target,\n eventContext: prInfo.eventContext,\n transform: targetCfg.transform,\n transform_js: targetCfg.transform_js,\n env: targetCfg.env,\n forEach: targetCfg.forEach,\n ai: {\n timeout: providerConfig.ai?.timeout || 600000,\n debug: !!debug,\n ...(targetCfg.ai || {}),\n },\n };\n // Build dependencyResults for target using already computed global results (after ensuring deps executed)\n const targetDeps = getAllDepsFromConfig(target);\n const depResults = new Map<string, ReviewSummary>();\n for (const depId of targetDeps) {\n // Prefer per-scope dependencyResults (e.g., forEach item context) over global results\n const res = dependencyResults.get(depId) || resultsMap?.get(depId);\n if (res) depResults.set(depId, res);\n }\n // Debug: log key dependent outputs for visibility\n try {\n // Try to log a small preview of dependent outputs if available\n const depPreview: Record<string, unknown> = {};\n for (const [k, v] of depResults.entries()) {\n const out = (v as any)?.output;\n if (out !== undefined) depPreview[k] = out;\n }\n if (debug) {\n log(`🔧 Debug: inline exec '${target}' deps output: ${JSON.stringify(depPreview)}`);\n }\n } catch {}\n\n if (debug) {\n const execStr = (provCfg as any).exec;\n if (execStr) log(`🔧 Debug: inline exec '${target}' command: ${execStr}`);\n }\n const r = await prov.execute(prInfo, provCfg, depResults, sessionInfo);\n // enrich with metadata similar to main flow\n const enrichedIssues = (r.issues || []).map(issue => ({\n ...issue,\n checkName: target,\n ruleId: `${target}/${issue.ruleId}`,\n group: targetCfg.group,\n schema: typeof targetCfg.schema === 'object' ? 'custom' : targetCfg.schema,\n template: targetCfg.template,\n timestamp: Date.now(),\n }));\n const enriched = { ...r, issues: enrichedIssues } as ReviewSummary;\n resultsMap?.set(target, enriched);\n if (debug) log(`🔧 Debug: inline executed '${target}', issues: ${enrichedIssues.length}`);\n return enriched;\n };\n\n // Begin attempts loop\n // We treat each retry/goto/run as consuming one loop budget entry\n while (true) {\n try {\n const res = await provider.execute(prInfo, providerConfig, dependencyResults, sessionInfo);\n // Success path\n // Treat result issues with severity error/critical as a soft-failure eligible for on_fail routing\n const hasSoftFailure = (res.issues || []).some(\n i => i.severity === 'error' || i.severity === 'critical'\n );\n if (hasSoftFailure && onFail) {\n if (debug)\n log(\n `🔧 Debug: Soft failure detected for '${checkName}' with ${(res.issues || []).length} issue(s)`\n );\n const lastError: any = {\n message: 'soft-failure: issues present',\n code: 'soft_failure',\n issues: res.issues,\n };\n const dynamicRun = await evalRunJs(onFail.run_js, lastError);\n let runList = [...(onFail.run || []), ...dynamicRun].filter(Boolean);\n runList = Array.from(new Set(runList));\n if (debug) log(`🔧 Debug: on_fail.run (soft) list = [${runList.join(', ')}]`);\n if (runList.length > 0) {\n loopCount++;\n if (loopCount > maxLoops) {\n throw new Error(\n `Routing loop budget exceeded (max_loops=${maxLoops}) during on_fail run`\n );\n }\n if (debug) log(`🔧 Debug: on_fail.run (soft) executing [${runList.join(', ')}]`);\n for (const stepId of runList) {\n await executeNamedCheckInline(stepId);\n }\n }\n let target = await evalGotoJs(onFail.goto_js, lastError);\n if (!target && onFail.goto) target = onFail.goto;\n if (debug) log(`🔧 Debug: on_fail.goto (soft) target = ${target}`);\n if (target) {\n if (!allAncestors.includes(target)) {\n if (debug)\n log(\n `⚠️ Debug: on_fail.goto (soft) '${target}' is not an ancestor of '${checkName}' — skipping`\n );\n } else {\n loopCount++;\n if (loopCount > maxLoops) {\n throw new Error(\n `Routing loop budget exceeded (max_loops=${maxLoops}) during on_fail goto`\n );\n }\n await executeNamedCheckInline(target);\n }\n }\n\n const retryMax = onFail.retry?.max ?? 0;\n const base = onFail.retry?.backoff?.delay_ms ?? 0;\n const mode = onFail.retry?.backoff?.mode ?? 'fixed';\n if (attempt <= retryMax) {\n loopCount++;\n if (loopCount > maxLoops) {\n throw new Error(`Routing loop budget exceeded (max_loops=${maxLoops}) during retry`);\n }\n const delay = base > 0 ? this.computeBackoffDelay(attempt, mode, base, seed) : 0;\n if (debug)\n log(\n `🔁 Debug: retrying '${checkName}' (soft) attempt ${attempt + 1}/${retryMax + 1} after ${delay}ms`\n );\n if (delay > 0) await this.sleep(delay);\n attempt++;\n continue; // loop\n }\n // No retry configured: return existing result\n return res;\n }\n let needRerun = false;\n if (onSuccess) {\n // Compute run list\n const dynamicRun = await evalRunJs(onSuccess.run_js);\n const runList = [...(onSuccess.run || []), ...dynamicRun].filter(Boolean);\n if (runList.length > 0) {\n loopCount++;\n if (loopCount > maxLoops) {\n throw new Error(\n `Routing loop budget exceeded (max_loops=${maxLoops}) during on_success run`\n );\n }\n for (const stepId of Array.from(new Set(runList))) {\n await executeNamedCheckInline(stepId);\n }\n }\n // Optional goto\n let target = await evalGotoJs(onSuccess.goto_js);\n if (!target && onSuccess.goto) target = onSuccess.goto;\n if (target) {\n if (!allAncestors.includes(target)) {\n if (debug)\n log(\n `⚠️ Debug: on_success.goto '${target}' is not an ancestor of '${checkName}' — skipping`\n );\n } else {\n loopCount++;\n if (loopCount > maxLoops) {\n throw new Error(\n `Routing loop budget exceeded (max_loops=${maxLoops}) during on_success goto`\n );\n }\n await executeNamedCheckInline(target);\n // After jumping back to an ancestor, re-run the current check to re-validate with new state\n needRerun = true;\n }\n }\n }\n if (needRerun) {\n if (debug) log(`🔄 Debug: Re-running '${checkName}' after on_success.goto`);\n attempt++;\n continue; // loop will execute the check again\n }\n return res;\n } catch (err) {\n // Failure path\n if (!onFail) {\n throw err; // no routing policy\n }\n\n const lastError = err instanceof Error ? err : new Error(String(err));\n\n // Dynamic compute run/goto\n const dynamicRun = await evalRunJs(onFail.run_js, lastError);\n let runList = [...(onFail.run || []), ...dynamicRun].filter(Boolean);\n // Dedup while preserving order\n runList = Array.from(new Set(runList));\n\n if (runList.length > 0) {\n loopCount++;\n if (loopCount > maxLoops) {\n throw new Error(\n `Routing loop budget exceeded (max_loops=${maxLoops}) during on_fail run`\n );\n }\n if (debug) log(`🔧 Debug: on_fail.run executing [${runList.join(', ')}]`);\n for (const stepId of runList) {\n await executeNamedCheckInline(stepId);\n }\n }\n\n let target = await evalGotoJs(onFail.goto_js, lastError);\n if (!target && onFail.goto) target = onFail.goto;\n if (target) {\n if (!allAncestors.includes(target)) {\n if (debug)\n log(\n `⚠️ Debug: on_fail.goto '${target}' is not an ancestor of '${checkName}' — skipping`\n );\n } else {\n loopCount++;\n if (loopCount > maxLoops) {\n throw new Error(\n `Routing loop budget exceeded (max_loops=${maxLoops}) during on_fail goto`\n );\n }\n await executeNamedCheckInline(target);\n }\n }\n\n // Retry if allowed\n const retryMax = onFail.retry?.max ?? 0;\n const base = onFail.retry?.backoff?.delay_ms ?? 0;\n const mode = onFail.retry?.backoff?.mode ?? 'fixed';\n if (attempt <= retryMax) {\n loopCount++;\n if (loopCount > maxLoops) {\n throw new Error(`Routing loop budget exceeded (max_loops=${maxLoops}) during retry`);\n }\n const delay = base > 0 ? this.computeBackoffDelay(attempt, mode, base, seed) : 0;\n if (debug)\n log(\n `🔁 Debug: retrying '${checkName}' attempt ${attempt + 1}/${retryMax + 1} after ${delay}ms`\n );\n if (delay > 0) await this.sleep(delay);\n attempt++;\n continue; // loop\n }\n\n // Exhausted retry budget; rethrow\n throw lastError;\n }\n }\n }\n\n /**\n * Set webhook context on a provider if it supports it\n */\n private setProviderWebhookContext(\n provider: import('./providers/check-provider.interface').CheckProvider\n ): void {\n if (this.webhookContext && provider.setWebhookContext) {\n provider.setWebhookContext(this.webhookContext.webhookData);\n }\n }\n\n /**\n * Filter checks based on tag filter configuration\n */\n private filterChecksByTags(\n checks: string[],\n config: import('./types/config').VisorConfig | undefined,\n tagFilter: import('./types/config').TagFilter | undefined\n ): string[] {\n const logFn = this.config?.output?.pr_comment ? console.error : console.log;\n\n return checks.filter(checkName => {\n const checkConfig = config?.checks?.[checkName];\n if (!checkConfig) {\n // If no config for this check, include it by default\n return true;\n }\n\n const checkTags = checkConfig.tags || [];\n\n // If check has tags but no tag filter is specified, exclude it\n if (checkTags.length > 0 && (!tagFilter || (!tagFilter.include && !tagFilter.exclude))) {\n logFn(`⏭️ Skipping check '${checkName}' - check has tags but no tag filter specified`);\n return false;\n }\n\n // If no tag filter is specified and check has no tags, include it\n if (!tagFilter || (!tagFilter.include && !tagFilter.exclude)) {\n return true;\n }\n\n // If check has no tags and a tag filter is specified, include it (untagged checks always run)\n if (checkTags.length === 0) {\n return true;\n }\n\n // Check exclude tags first (if any exclude tag matches, skip the check)\n if (tagFilter.exclude && tagFilter.exclude.length > 0) {\n const hasExcludedTag = tagFilter.exclude.some(tag => checkTags.includes(tag));\n if (hasExcludedTag) {\n logFn(`⏭️ Skipping check '${checkName}' - has excluded tag`);\n return false;\n }\n }\n\n // Check include tags (if specified, at least one must match)\n if (tagFilter.include && tagFilter.include.length > 0) {\n const hasIncludedTag = tagFilter.include.some(tag => checkTags.includes(tag));\n if (!hasIncludedTag) {\n logFn(`⏭️ Skipping check '${checkName}' - does not have required tags`);\n return false;\n }\n }\n\n return true;\n });\n }\n\n /**\n * Execute checks on the local repository\n */\n async executeChecks(options: CheckExecutionOptions): Promise<AnalysisResult> {\n const startTime = Date.now();\n const timestamp = new Date().toISOString();\n\n try {\n // Store webhook context if provided\n this.webhookContext = options.webhookContext;\n\n // Determine where to send log messages based on output format\n const logFn = (msg: string) => logger.info(msg);\n\n // Initialize GitHub checks if enabled\n if (options.githubChecks?.enabled && options.githubChecks.octokit) {\n await this.initializeGitHubChecks(options, logFn);\n }\n\n // Analyze the repository\n logFn('🔍 Analyzing local git repository...');\n const repositoryInfo = await this.gitAnalyzer.analyzeRepository();\n\n if (!repositoryInfo.isGitRepository) {\n // Complete GitHub checks with error if they were initialized\n if (this.checkRunMap) {\n await this.completeGitHubChecksWithError('Not a git repository or no changes found');\n }\n\n return this.createErrorResult(\n repositoryInfo,\n 'Not a git repository or no changes found',\n startTime,\n timestamp,\n options.checks\n );\n }\n\n // Convert to PRInfo format for compatibility with existing reviewer\n const prInfo = this.gitAnalyzer.toPRInfo(repositoryInfo);\n\n // Apply tag filtering if specified\n const filteredChecks = this.filterChecksByTags(\n options.checks,\n options.config,\n options.tagFilter || options.config?.tag_filter\n );\n\n if (filteredChecks.length === 0) {\n logger.warn('⚠️ No checks match the tag filter criteria');\n // Complete GitHub checks with no checks message if they were initialized\n if (this.checkRunMap) {\n await this.completeGitHubChecksWithError('No checks match the tag filter criteria');\n }\n return this.createErrorResult(\n repositoryInfo,\n 'No checks match the tag filter criteria',\n startTime,\n timestamp,\n options.checks\n );\n }\n\n // Update GitHub checks to in-progress status\n if (this.checkRunMap) {\n await this.updateGitHubChecksInProgress(options);\n }\n\n // Execute checks using the existing PRReviewer\n logFn(`🤖 Executing checks: ${filteredChecks.join(', ')}`);\n const reviewSummary = await this.executeReviewChecks(\n prInfo,\n filteredChecks,\n options.timeout,\n options.config,\n options.outputFormat,\n options.debug,\n options.maxParallelism,\n options.failFast\n );\n\n // Complete GitHub checks with results\n if (this.checkRunMap) {\n await this.completeGitHubChecksWithResults(reviewSummary, options, prInfo);\n }\n\n const executionTime = Date.now() - startTime;\n\n // Collect debug information when debug mode is enabled\n let debugInfo: import('./output-formatters').DebugInfo | undefined;\n if (options.debug && reviewSummary.debug) {\n debugInfo = {\n provider: reviewSummary.debug.provider,\n model: reviewSummary.debug.model,\n processingTime: reviewSummary.debug.processingTime,\n parallelExecution: options.checks.length > 1,\n checksExecuted: options.checks,\n totalApiCalls: reviewSummary.debug.totalApiCalls || options.checks.length,\n apiCallDetails: reviewSummary.debug.apiCallDetails,\n };\n }\n\n // Build execution statistics\n const executionStatistics = this.buildExecutionStatistics();\n\n return {\n repositoryInfo,\n reviewSummary,\n executionTime,\n timestamp,\n checksExecuted: filteredChecks,\n executionStatistics,\n debug: debugInfo,\n };\n } catch (error) {\n logger.error(\n 'Error executing checks: ' + (error instanceof Error ? error.message : String(error))\n );\n\n // Complete GitHub checks with error if they were initialized\n if (this.checkRunMap) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';\n await this.completeGitHubChecksWithError(errorMessage);\n }\n\n const fallbackRepositoryInfo: GitRepositoryInfo = {\n title: 'Error during analysis',\n body: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`,\n author: 'system',\n base: 'main',\n head: 'HEAD',\n files: [],\n totalAdditions: 0,\n totalDeletions: 0,\n isGitRepository: false,\n workingDirectory: options.workingDirectory || process.cwd(),\n };\n\n return this.createErrorResult(\n fallbackRepositoryInfo,\n error instanceof Error ? error.message : 'Unknown error occurred',\n startTime,\n timestamp,\n options.checks\n );\n }\n }\n\n /**\n * Execute tasks with controlled parallelism using a pool pattern\n */\n private async executeWithLimitedParallelism<T>(\n tasks: (() => Promise<T>)[],\n maxParallelism: number,\n failFast?: boolean\n ): Promise<PromiseSettledResult<T>[]> {\n if (maxParallelism <= 0) {\n throw new Error('Max parallelism must be greater than 0');\n }\n\n if (tasks.length === 0) {\n return [];\n }\n\n const results: PromiseSettledResult<T>[] = new Array(tasks.length);\n let currentIndex = 0;\n let shouldStop = false;\n\n // Worker function that processes tasks\n const worker = async (): Promise<void> => {\n while (currentIndex < tasks.length && !shouldStop) {\n const taskIndex = currentIndex++;\n if (taskIndex >= tasks.length) break;\n\n try {\n const result = await tasks[taskIndex]();\n results[taskIndex] = { status: 'fulfilled', value: result };\n\n // Check if we should stop due to fail-fast\n if (failFast && this.shouldFailFast(result)) {\n shouldStop = true;\n break;\n }\n } catch (error) {\n results[taskIndex] = { status: 'rejected', reason: error };\n\n // If fail-fast is enabled and we have an error, stop execution\n if (failFast) {\n shouldStop = true;\n break;\n }\n }\n }\n };\n\n // Create workers up to the parallelism limit\n const workers: Promise<void>[] = [];\n const workerCount = Math.min(maxParallelism, tasks.length);\n\n for (let i = 0; i < workerCount; i++) {\n workers.push(worker());\n }\n\n // Wait for all workers to complete\n await Promise.all(workers);\n\n return results;\n }\n\n /**\n * Execute review checks using parallel execution for multiple AI checks\n */\n private async executeReviewChecks(\n prInfo: PRInfo,\n checks: string[],\n timeout?: number,\n config?: import('./types/config').VisorConfig,\n outputFormat?: string,\n debug?: boolean,\n maxParallelism?: number,\n failFast?: boolean\n ): Promise<ReviewSummary> {\n // Store config for use in filtering\n this.config = config;\n\n // Determine where to send log messages based on output format\n // Use debug logger for internal engine messages; important notices use logger.warn/info directly.\n const logFn = (msg: string) => logger.debug(msg);\n\n // Only output debug messages if debug mode is enabled\n if (debug) {\n logFn(`🔧 Debug: executeReviewChecks called with checks: ${JSON.stringify(checks)}`);\n logFn(`🔧 Debug: Config available: ${!!config}, Config has checks: ${!!config?.checks}`);\n }\n\n // Filter checks based on current event type to prevent execution of checks that shouldn't run\n const filteredChecks = this.filterChecksByEvent(checks, config, prInfo, logFn, debug);\n if (filteredChecks.length !== checks.length && debug) {\n logFn(\n `🔧 Debug: Event filtering reduced checks from ${checks.length} to ${filteredChecks.length}: ${JSON.stringify(filteredChecks)}`\n );\n }\n\n // Use filtered checks for execution\n checks = filteredChecks;\n\n // If we have a config with individual check definitions, prefer dependency-aware execution\n // even for a single check, so provider types other than 'ai' work consistently.\n const allConfigured = config?.checks ? checks.every(name => !!config.checks[name]) : false;\n if (allConfigured) {\n if (debug) {\n logFn(\n `🔧 Debug: Using dependency-aware execution for ${checks.length} configured check(s)`\n );\n }\n return await this.executeDependencyAwareChecks(\n prInfo,\n checks,\n timeout,\n config,\n logFn,\n debug,\n maxParallelism,\n failFast\n );\n }\n\n // Single check execution (existing logic)\n if (checks.length === 1) {\n if (debug) {\n logFn(`🔧 Debug: Using single check execution for: ${checks[0]}`);\n }\n\n // If we have a config definition for this check, use it\n if (config?.checks?.[checks[0]]) {\n return await this.executeSingleConfiguredCheck(prInfo, checks[0], timeout, config, logFn);\n }\n\n // Try provider system for single checks\n if (this.providerRegistry.hasProvider(checks[0])) {\n const provider = this.providerRegistry.getProviderOrThrow(checks[0]);\n this.setProviderWebhookContext(provider);\n const providerConfig: CheckProviderConfig = {\n type: checks[0],\n prompt: 'all',\n eventContext: prInfo.eventContext, // Pass event context for templates\n ai: timeout ? { timeout } : undefined,\n };\n const result = await provider.execute(prInfo, providerConfig);\n\n // Prefix issues with check name for consistent grouping\n const prefixedIssues = (result.issues || []).map(issue => ({\n ...issue,\n ruleId: `${checks[0]}/${issue.ruleId}`,\n }));\n\n return {\n ...result,\n issues: prefixedIssues,\n };\n }\n }\n\n // Check if 'ai' provider is available for focus-based checks (legacy support)\n if (this.providerRegistry.hasProvider('ai')) {\n if (debug) {\n logFn(`🔧 Debug: Using AI provider with focus mapping`);\n }\n const provider = this.providerRegistry.getProviderOrThrow('ai');\n this.setProviderWebhookContext(provider);\n\n let focus = 'all';\n let checkName = 'all';\n if (checks.length === 1) {\n checkName = checks[0];\n if (checks[0] === 'security' || checks[0] === 'performance' || checks[0] === 'style') {\n focus = checks[0];\n }\n } else {\n // For multiple checks, combine them into 'all' focus\n focus = 'all';\n }\n\n const providerConfig: CheckProviderConfig = {\n type: 'ai',\n prompt: focus,\n focus: focus,\n eventContext: prInfo.eventContext, // Pass event context for templates\n ai: timeout ? { timeout } : undefined,\n // Inherit global AI provider and model settings if config is available\n ai_provider: config?.ai_provider,\n ai_model: config?.ai_model,\n };\n\n const result = await provider.execute(prInfo, providerConfig);\n\n // Prefix issues with check name for consistent grouping\n const prefixedIssues = (result.issues || []).map(issue => ({\n ...issue,\n ruleId: `${checkName}/${issue.ruleId}`,\n }));\n\n return {\n ...result,\n issues: prefixedIssues,\n };\n }\n\n // Fallback to existing PRReviewer for backward compatibility\n if (debug) {\n logFn(`🔧 Debug: Using legacy PRReviewer fallback`);\n }\n const focusMap: Record<string, ReviewOptions['focus']> = {\n security: 'security',\n performance: 'performance',\n style: 'style',\n all: 'all',\n architecture: 'all',\n };\n\n let focus: ReviewOptions['focus'] = 'all';\n if (checks.length === 1 && focusMap[checks[0]]) {\n focus = focusMap[checks[0]];\n }\n\n return await this.reviewer.reviewPR('local', 'repository', 0, prInfo, {\n focus,\n format: 'table',\n });\n }\n\n /**\n * Execute review checks and return grouped results with statistics for new architecture\n */\n public async executeGroupedChecks(\n prInfo: PRInfo,\n checks: string[],\n timeout?: number,\n config?: import('./types/config').VisorConfig,\n outputFormat?: string,\n debug?: boolean,\n maxParallelism?: number,\n failFast?: boolean,\n tagFilter?: import('./types/config').TagFilter\n ): Promise<ExecutionResult> {\n // Determine where to send log messages based on output format\n const logFn =\n outputFormat === 'json' || outputFormat === 'sarif'\n ? debug\n ? console.error\n : () => {}\n : console.log;\n\n // Only output debug messages if debug mode is enabled\n if (debug) {\n logger.debug(`🔧 Debug: executeGroupedChecks called with checks: ${JSON.stringify(checks)}`);\n logger.debug(\n `🔧 Debug: Config available: ${!!config}, Config has checks: ${!!config?.checks}`\n );\n }\n\n // Filter checks based on current event type to prevent execution of checks that shouldn't run\n const filteredChecks = this.filterChecksByEvent(checks, config, prInfo, logFn, debug);\n if (filteredChecks.length !== checks.length && debug) {\n logger.debug(\n `🔧 Debug: Event filtering reduced checks from ${checks.length} to ${filteredChecks.length}: ${JSON.stringify(filteredChecks)}`\n );\n }\n\n // Apply tag filtering if specified\n const tagFilteredChecks = this.filterChecksByTags(\n filteredChecks,\n config,\n tagFilter || config?.tag_filter\n );\n\n if (tagFilteredChecks.length !== filteredChecks.length && debug) {\n logger.debug(\n `🔧 Debug: Tag filtering reduced checks from ${filteredChecks.length} to ${tagFilteredChecks.length}: ${JSON.stringify(tagFilteredChecks)}`\n );\n }\n\n // Use filtered checks for execution\n checks = tagFilteredChecks;\n\n // Check if we have any checks left after filtering\n if (checks.length === 0) {\n logger.warn('⚠️ No checks remain after tag filtering');\n return {\n results: {},\n statistics: this.buildExecutionStatistics(),\n };\n }\n\n if (!config?.checks) {\n throw new Error('Config with check definitions required for grouped execution');\n }\n\n // If we have a config with individual check definitions, use dependency-aware execution\n const hasDependencies = checks.some(checkName => {\n const checkConfig = config.checks[checkName];\n return checkConfig?.depends_on && checkConfig.depends_on.length > 0;\n });\n\n if (checks.length > 1 || hasDependencies) {\n if (debug) {\n logger.debug(\n `🔧 Debug: Using grouped dependency-aware execution for ${checks.length} checks (has dependencies: ${hasDependencies})`\n );\n }\n return await this.executeGroupedDependencyAwareChecks(\n prInfo,\n checks,\n timeout,\n config,\n logFn,\n debug,\n maxParallelism,\n failFast\n );\n }\n\n // Single check execution\n if (checks.length === 1) {\n if (debug) {\n logger.debug(`🔧 Debug: Using grouped single check execution for: ${checks[0]}`);\n }\n const checkResult = await this.executeSingleGroupedCheck(\n prInfo,\n checks[0],\n timeout,\n config,\n logFn,\n debug\n );\n\n const groupedResults: GroupedCheckResults = {};\n groupedResults[checkResult.group] = [checkResult];\n return {\n results: groupedResults,\n statistics: this.buildExecutionStatistics(),\n };\n }\n\n // No checks to execute\n return {\n results: {},\n statistics: this.buildExecutionStatistics(),\n };\n }\n\n /**\n * Execute single check and return grouped result\n */\n private async executeSingleGroupedCheck(\n prInfo: PRInfo,\n checkName: string,\n timeout?: number,\n config?: import('./types/config').VisorConfig,\n logFn?: (message: string) => void,\n debug?: boolean\n ): Promise<CheckResult> {\n if (!config?.checks?.[checkName]) {\n throw new Error(`No configuration found for check: ${checkName}`);\n }\n\n const checkConfig = config.checks[checkName];\n const providerType = checkConfig.type || 'ai';\n const provider = this.providerRegistry.getProviderOrThrow(providerType);\n this.setProviderWebhookContext(provider);\n\n const providerConfig: CheckProviderConfig = {\n type: providerType,\n prompt: checkConfig.prompt,\n focus: checkConfig.focus || this.mapCheckNameToFocus(checkName),\n schema: checkConfig.schema,\n group: checkConfig.group,\n eventContext: prInfo.eventContext, // Pass event context for templates\n ai: {\n timeout: timeout || 600000,\n debug: debug,\n ...(checkConfig.ai || {}),\n },\n ai_provider: checkConfig.ai_provider || config.ai_provider,\n ai_model: checkConfig.ai_model || config.ai_model,\n // Pass claude_code config if present\n claude_code: checkConfig.claude_code,\n // Pass any provider-specific config\n ...checkConfig,\n };\n providerConfig.forEach = checkConfig.forEach;\n\n const result = await provider.execute(prInfo, providerConfig);\n\n // Validate forEach output (skip if there are already errors from transform_js or other sources)\n if (checkConfig.forEach && (!result.issues || result.issues.length === 0)) {\n const reviewSummaryWithOutput = result as ReviewSummary & { output?: unknown };\n const validation = this.validateAndNormalizeForEachOutput(\n checkName,\n reviewSummaryWithOutput.output,\n checkConfig.group\n );\n\n if (!validation.isValid) {\n return validation.error;\n }\n }\n\n // Evaluate fail_if conditions\n if (config && (config.fail_if || checkConfig.fail_if)) {\n const failureResults = await this.evaluateFailureConditions(checkName, result, config);\n\n // Add failure condition issues to the result\n if (failureResults.length > 0) {\n const failureIssues = failureResults\n .filter(f => f.failed)\n .map(f => ({\n file: 'system',\n line: 0,\n ruleId: f.conditionName,\n message: f.message || `Failure condition met: ${f.expression}`,\n severity: (f.severity || 'error') as 'info' | 'warning' | 'error' | 'critical',\n category: 'logic' as const,\n }));\n\n result.issues = [...(result.issues || []), ...failureIssues];\n }\n }\n\n // Render the check content using the appropriate template\n const content = await this.renderCheckContent(checkName, result, checkConfig, prInfo);\n\n return {\n checkName,\n content,\n group: checkConfig.group || 'default',\n debug: result.debug,\n issues: result.issues, // Include structured issues\n };\n }\n\n /**\n * Validate and normalize forEach output\n * Returns normalized array or throws validation error result\n */\n private validateAndNormalizeForEachOutput(\n checkName: string,\n output: unknown,\n checkGroup?: string\n ):\n | {\n isValid: true;\n normalizedOutput: unknown[];\n }\n | {\n isValid: false;\n error: {\n checkName: string;\n content: string;\n group: string;\n issues: Array<{\n file: string;\n line: number;\n ruleId: string;\n message: string;\n severity: 'error';\n category: 'logic';\n }>;\n };\n } {\n if (output === undefined) {\n logger.error(`✗ forEach check \"${checkName}\" produced undefined output`);\n return {\n isValid: false,\n error: {\n checkName,\n content: '',\n group: checkGroup || 'default',\n issues: [\n {\n file: 'system',\n line: 0,\n ruleId: 'forEach/undefined_output',\n message: `forEach check \"${checkName}\" produced undefined output. Verify your command outputs valid data and your transform_js returns a value.`,\n severity: 'error',\n category: 'logic',\n },\n ],\n },\n };\n }\n\n // Normalize output to array\n let normalizedOutput: unknown[];\n\n if (Array.isArray(output)) {\n normalizedOutput = output;\n } else if (typeof output === 'string') {\n try {\n const parsed = JSON.parse(output);\n normalizedOutput = Array.isArray(parsed) ? parsed : [parsed];\n } catch {\n normalizedOutput = [output];\n }\n } else if (output === null) {\n normalizedOutput = [];\n } else {\n normalizedOutput = [output];\n }\n\n // Log the result (empty arrays are valid, just result in 0 iterations)\n logger.info(` Found ${normalizedOutput.length} items for forEach iteration`);\n return {\n isValid: true,\n normalizedOutput,\n };\n }\n\n /**\n * Execute multiple checks with dependency awareness - return grouped results with statistics\n */\n private async executeGroupedDependencyAwareChecks(\n prInfo: PRInfo,\n checks: string[],\n timeout?: number,\n config?: import('./types/config').VisorConfig,\n logFn?: (message: string) => void,\n debug?: boolean,\n maxParallelism?: number,\n failFast?: boolean\n ): Promise<ExecutionResult> {\n // Use the existing dependency-aware execution logic\n const reviewSummary = await this.executeDependencyAwareChecks(\n prInfo,\n checks,\n timeout,\n config,\n logFn,\n debug,\n maxParallelism,\n failFast\n );\n\n // Build execution statistics\n const executionStatistics = this.buildExecutionStatistics();\n\n // Convert the flat ReviewSummary to grouped CheckResults\n const groupedResults = await this.convertReviewSummaryToGroupedResults(\n reviewSummary,\n checks,\n config,\n prInfo\n );\n\n return {\n results: groupedResults,\n statistics: executionStatistics,\n };\n }\n\n /**\n * Convert ReviewSummary to GroupedCheckResults\n */\n private async convertReviewSummaryToGroupedResults(\n reviewSummary: ReviewSummary,\n checks: string[],\n config?: import('./types/config').VisorConfig,\n prInfo?: PRInfo\n ): Promise<GroupedCheckResults> {\n const groupedResults: GroupedCheckResults = {};\n const contentMap = (\n reviewSummary as ReviewSummary & {\n __contents?: Record<string, string | undefined>;\n }\n ).__contents;\n\n // Process each check individually\n for (const checkName of checks) {\n const checkConfig = config?.checks?.[checkName];\n if (!checkConfig) continue;\n\n // Extract issues for this check\n const checkIssues = (reviewSummary.issues || []).filter(\n issue => issue.checkName === checkName\n );\n\n // Create a mini ReviewSummary for this check\n const checkSummary: ReviewSummary = {\n issues: checkIssues,\n debug: reviewSummary.debug,\n };\n\n if (contentMap?.[checkName]) {\n const summaryWithContent = checkSummary as ReviewSummary & { content?: string };\n summaryWithContent.content = contentMap[checkName];\n }\n\n // Render content for this check\n const content = await this.renderCheckContent(checkName, checkSummary, checkConfig, prInfo);\n\n const checkResult: CheckResult = {\n checkName,\n content,\n group: checkConfig.group || 'default',\n debug: reviewSummary.debug,\n issues: checkIssues, // Include structured issues\n };\n\n // Add to appropriate group\n const group = checkResult.group;\n if (!groupedResults[group]) {\n groupedResults[group] = [];\n }\n groupedResults[group].push(checkResult);\n }\n\n return groupedResults;\n }\n\n /**\n * Validates that a file path is safe and within the project directory\n * Prevents path traversal attacks by:\n * - Blocking absolute paths\n * - Blocking paths with \"..\" segments\n * - Ensuring resolved path is within project directory\n * - Blocking special characters and null bytes\n * - Enforcing .liquid file extension\n */\n private async validateTemplatePath(templatePath: string): Promise<string> {\n const path = await import('path');\n\n // Validate input\n if (!templatePath || typeof templatePath !== 'string' || templatePath.trim() === '') {\n throw new Error('Template path must be a non-empty string');\n }\n\n // Block null bytes and other dangerous characters\n if (templatePath.includes('\\0') || templatePath.includes('\\x00')) {\n throw new Error('Template path contains invalid characters');\n }\n\n // Enforce .liquid file extension\n if (!templatePath.endsWith('.liquid')) {\n throw new Error('Template file must have .liquid extension');\n }\n\n // Block absolute paths\n if (path.isAbsolute(templatePath)) {\n throw new Error('Template path must be relative to project directory');\n }\n\n // Block paths with \"..\" segments\n if (templatePath.includes('..')) {\n throw new Error('Template path cannot contain \"..\" segments');\n }\n\n // Block paths starting with ~ (home directory)\n if (templatePath.startsWith('~')) {\n throw new Error('Template path cannot reference home directory');\n }\n\n // Get the project root directory from git analyzer\n const repositoryInfo = await this.gitAnalyzer.analyzeRepository();\n const projectRoot = repositoryInfo.workingDirectory;\n\n // Validate project root\n if (!projectRoot || typeof projectRoot !== 'string') {\n throw new Error('Unable to determine project root directory');\n }\n\n // Resolve the template path relative to project root\n const resolvedPath = path.resolve(projectRoot, templatePath);\n const resolvedProjectRoot = path.resolve(projectRoot);\n\n // Validate resolved paths\n if (\n !resolvedPath ||\n !resolvedProjectRoot ||\n resolvedPath === '' ||\n resolvedProjectRoot === ''\n ) {\n throw new Error(\n `Unable to resolve template path: projectRoot=\"${projectRoot}\", templatePath=\"${templatePath}\", resolvedPath=\"${resolvedPath}\", resolvedProjectRoot=\"${resolvedProjectRoot}\"`\n );\n }\n\n // Ensure the resolved path is still within the project directory\n if (\n !resolvedPath.startsWith(resolvedProjectRoot + path.sep) &&\n resolvedPath !== resolvedProjectRoot\n ) {\n throw new Error('Template path escapes project directory');\n }\n\n return resolvedPath;\n }\n\n /**\n * Evaluate `if` condition for a check\n * @param checkName Name of the check\n * @param condition The condition string to evaluate\n * @param prInfo PR information\n * @param results Current check results\n * @param debug Whether debug mode is enabled\n * @returns true if the check should run, false if it should be skipped\n */\n private async evaluateCheckCondition(\n checkName: string,\n condition: string,\n prInfo: PRInfo,\n results: Map<string, ReviewSummary>,\n debug?: boolean\n ): Promise<boolean> {\n const shouldRun = await this.failureEvaluator.evaluateIfCondition(checkName, condition, {\n branch: prInfo.head,\n baseBranch: prInfo.base,\n filesChanged: prInfo.files.map(f => f.filename),\n event: 'issue_comment',\n environment: getSafeEnvironmentVariables(),\n previousResults: results,\n });\n\n if (!shouldRun && debug) {\n logger.debug(`🔧 Debug: Skipping check '${checkName}' - if condition evaluated to false`);\n }\n\n return shouldRun;\n }\n\n /**\n * Render check content using the appropriate template\n */\n private async renderCheckContent(\n checkName: string,\n reviewSummary: ReviewSummary,\n checkConfig: CheckConfig,\n _prInfo?: PRInfo\n ): Promise<string> {\n const directContent = (reviewSummary as ReviewSummary & { content?: string }).content;\n if (typeof directContent === 'string' && directContent.trim()) {\n return directContent.trim();\n }\n\n // Import the liquid template system\n const { createExtendedLiquid } = await import('./liquid-extensions');\n const fs = await import('fs/promises');\n const path = await import('path');\n\n const liquid = createExtendedLiquid({\n trimTagLeft: false,\n trimTagRight: false,\n trimOutputLeft: false,\n trimOutputRight: false,\n greedy: false,\n });\n\n // Determine template to use\n // If schema is an object (inline JSON schema), use 'plain' rendering\n // If schema is a file path (legitimate path with / and ends with .json), treat as plain (schema file reference)\n let schemaName: string;\n if (typeof checkConfig.schema === 'object') {\n schemaName = 'plain';\n } else if (\n typeof checkConfig.schema === 'string' &&\n checkConfig.schema.includes('/') &&\n checkConfig.schema.endsWith('.json') &&\n !checkConfig.schema.includes('..') // Reject paths containing .. (parent directory)\n ) {\n // Schema is a file path reference - use plain rendering\n // The schema file will be handled by the AI provider when making the request\n schemaName = 'plain';\n } else {\n schemaName = checkConfig.schema || 'plain';\n }\n\n let templateContent: string;\n\n if (checkConfig.template) {\n // Custom template\n if (checkConfig.template.content) {\n templateContent = checkConfig.template.content;\n } else if (checkConfig.template.file) {\n // Validate the template file path to prevent path traversal attacks\n const validatedPath = await this.validateTemplatePath(checkConfig.template.file);\n templateContent = await fs.readFile(validatedPath, 'utf-8');\n } else {\n throw new Error('Custom template must specify either \"file\" or \"content\"');\n }\n } else if (schemaName === 'plain') {\n // Plain schema - return raw content directly\n return reviewSummary.issues?.[0]?.message || '';\n } else {\n // Use built-in schema template\n const sanitizedSchema = schemaName.replace(/[^a-zA-Z0-9-]/g, '');\n if (!sanitizedSchema) {\n throw new Error('Invalid schema name');\n }\n const templatePath = path.join(__dirname, `../output/${sanitizedSchema}/template.liquid`);\n templateContent = await fs.readFile(templatePath, 'utf-8');\n }\n\n // Prepare template data\n const templateData = {\n issues: reviewSummary.issues || [],\n checkName: checkName,\n };\n\n const rendered = await liquid.parseAndRender(templateContent, templateData);\n return rendered.trim();\n }\n\n /**\n * Execute multiple checks with dependency awareness - intelligently parallel and sequential\n */\n private async executeDependencyAwareChecks(\n prInfo: PRInfo,\n checks: string[],\n timeout?: number,\n config?: import('./types/config').VisorConfig,\n logFn?: (message: string) => void,\n debug?: boolean,\n maxParallelism?: number,\n failFast?: boolean\n ): Promise<ReviewSummary> {\n const log = logFn || console.error;\n\n if (debug) {\n log(`🔧 Debug: Starting dependency-aware execution of ${checks.length} checks`);\n }\n\n if (!config?.checks) {\n throw new Error('Config with check definitions required for dependency-aware execution');\n }\n\n // Determine effective max parallelism (CLI > config > default)\n const effectiveMaxParallelism = maxParallelism ?? config.max_parallelism ?? 3;\n // Determine effective fail-fast setting (CLI > config > default)\n const effectiveFailFast = failFast ?? config.fail_fast ?? false;\n\n if (debug) {\n log(`🔧 Debug: Using max parallelism: ${effectiveMaxParallelism}`);\n log(`🔧 Debug: Using fail-fast: ${effectiveFailFast}`);\n }\n\n // Build dependency graph and check for session reuse requirements\n const dependencies: Record<string, string[]> = {};\n const sessionReuseChecks = new Set<string>();\n const sessionProviders = new Map<string, string>(); // checkName -> parent session provider\n\n for (const checkName of checks) {\n const checkConfig = config.checks[checkName];\n if (checkConfig) {\n dependencies[checkName] = checkConfig.depends_on || [];\n\n // Track checks that need session reuse\n if (checkConfig.reuse_ai_session) {\n sessionReuseChecks.add(checkName);\n\n // Determine the session provider check name\n if (typeof checkConfig.reuse_ai_session === 'string') {\n // Explicit check name provided\n sessionProviders.set(checkName, checkConfig.reuse_ai_session);\n } else if (checkConfig.reuse_ai_session === true) {\n // Use first dependency as fallback\n if (checkConfig.depends_on && checkConfig.depends_on.length > 0) {\n sessionProviders.set(checkName, checkConfig.depends_on[0]);\n }\n }\n }\n } else {\n dependencies[checkName] = [];\n }\n }\n\n if (sessionReuseChecks.size > 0 && debug) {\n log(\n `🔄 Debug: Found ${sessionReuseChecks.size} checks requiring session reuse: ${Array.from(sessionReuseChecks).join(', ')}`\n );\n }\n\n // Validate dependencies for the initially requested checks first\n const validation = DependencyResolver.validateDependencies(checks, dependencies);\n if (!validation.valid) {\n return {\n issues: [\n {\n severity: 'error' as const,\n message: `Dependency validation failed: ${validation.errors.join(', ')}`,\n file: '',\n line: 0,\n ruleId: 'dependency-validation-error',\n category: 'logic' as const,\n },\n ],\n };\n }\n\n // Expand requested checks with transitive dependencies present in config for execution\n const expandWithTransitives = (rootChecks: string[]): string[] => {\n if (!config?.checks) return rootChecks;\n const set = new Set<string>(rootChecks);\n const visit = (name: string) => {\n const cfg = config.checks[name];\n if (!cfg || !cfg.depends_on) return;\n for (const dep of cfg.depends_on) {\n if (!set.has(dep)) {\n set.add(dep);\n visit(dep);\n }\n }\n };\n for (const c of rootChecks) visit(c);\n return Array.from(set);\n };\n\n checks = expandWithTransitives(checks);\n\n // Rebuild dependencies map for the expanded set\n for (const checkName of checks) {\n const checkConfig = config.checks[checkName];\n dependencies[checkName] = checkConfig?.depends_on || [];\n }\n\n // Build dependency graph\n const dependencyGraph = DependencyResolver.buildDependencyGraph(dependencies);\n\n if (dependencyGraph.hasCycles) {\n return {\n issues: [\n {\n severity: 'error' as const,\n message: `Circular dependencies detected: ${dependencyGraph.cycleNodes?.join(' -> ')}`,\n file: '',\n line: 0,\n ruleId: 'circular-dependency-error',\n category: 'logic' as const,\n },\n ],\n };\n }\n\n // Log execution plan\n const stats = DependencyResolver.getExecutionStats(dependencyGraph);\n if (debug) {\n log(\n `🔧 Debug: Execution plan - ${stats.totalChecks} checks in ${stats.parallelLevels} levels, max parallelism: ${stats.maxParallelism}`\n );\n }\n\n // Execute checks level by level\n const results = new Map<string, ReviewSummary>();\n const sessionRegistry = require('./session-registry').SessionRegistry.getInstance();\n // Note: We'll get the provider dynamically per check, not a single one for all\n const sessionIds = new Map<string, string>(); // checkName -> sessionId\n let shouldStopExecution = false;\n let completedChecksCount = 0;\n const totalChecksCount = stats.totalChecks;\n\n // Initialize execution statistics for all checks\n for (const checkName of checks) {\n this.initializeCheckStats(checkName);\n }\n\n for (\n let levelIndex = 0;\n levelIndex < dependencyGraph.executionOrder.length && !shouldStopExecution;\n levelIndex++\n ) {\n const executionGroup = dependencyGraph.executionOrder[levelIndex];\n\n // Check if any checks in this level require session reuse - if so, force sequential execution\n const checksInLevel = executionGroup.parallel;\n const hasSessionReuseInLevel = checksInLevel.some(checkName =>\n sessionReuseChecks.has(checkName)\n );\n\n let actualParallelism = Math.min(effectiveMaxParallelism, executionGroup.parallel.length);\n if (hasSessionReuseInLevel) {\n // Force sequential execution when session reuse is involved\n actualParallelism = 1;\n if (debug) {\n log(\n `🔄 Debug: Level ${executionGroup.level} contains session reuse checks - forcing sequential execution (parallelism: 1)`\n );\n }\n }\n\n if (debug) {\n log(\n `🔧 Debug: Executing level ${executionGroup.level} with ${executionGroup.parallel.length} checks (parallelism: ${actualParallelism})`\n );\n }\n\n // Create task functions for checks in this level\n const levelTaskFunctions = executionGroup.parallel.map(checkName => async () => {\n const checkConfig = config.checks[checkName];\n if (!checkConfig) {\n return {\n checkName,\n error: `No configuration found for check: ${checkName}`,\n result: null,\n };\n }\n\n const checkStartTime = Date.now();\n completedChecksCount++;\n logger.step(`Running check: ${checkName} [${completedChecksCount}/${totalChecksCount}]`);\n\n try {\n if (debug) {\n log(`🔧 Debug: Starting check: ${checkName} at level ${executionGroup.level}`);\n }\n\n // Get the appropriate provider for this check type\n const providerType = checkConfig.type || 'ai';\n const provider = this.providerRegistry.getProviderOrThrow(providerType);\n if (debug) {\n log(`🔧 Debug: Provider for '${checkName}' is '${providerType}'`);\n }\n this.setProviderWebhookContext(provider);\n\n // Create provider config for this specific check\n const extendedCheckConfig = checkConfig as CheckConfig & {\n level?: string;\n message?: string;\n };\n\n const providerConfig: CheckProviderConfig = {\n type: providerType,\n prompt: checkConfig.prompt,\n exec: checkConfig.exec,\n focus: checkConfig.focus || this.mapCheckNameToFocus(checkName),\n schema: checkConfig.schema,\n group: checkConfig.group,\n checkName: checkName, // Add checkName for sessionID\n eventContext: prInfo.eventContext, // Pass event context for templates\n transform: checkConfig.transform,\n transform_js: checkConfig.transform_js,\n // Important: pass through provider-level timeout from check config\n // (e.g., command/http_client providers expect seconds/ms here)\n timeout: checkConfig.timeout,\n level: extendedCheckConfig.level,\n message: extendedCheckConfig.message,\n env: checkConfig.env,\n forEach: checkConfig.forEach,\n ai: {\n timeout: timeout || 600000,\n debug: debug,\n ...(checkConfig.ai || {}),\n },\n };\n\n // Pass results from ALL transitive dependencies (not just direct ones)\n // This ensures the \"outputs\" variable has access to all ancestor check results\n const dependencyResults = new Map<string, ReviewSummary>();\n let isForEachDependent = false;\n let forEachItems: unknown[] = [];\n let forEachParentName: string | undefined;\n const forEachParents: string[] = []; // Track ALL forEach parents\n\n // Get all transitive dependencies (ancestors) for this check\n const allDependencies = DependencyResolver.getAllDependencies(\n checkName,\n dependencyGraph.nodes\n );\n\n // Include results from ALL dependencies (direct and transitive)\n for (const depId of allDependencies) {\n if (results.has(depId)) {\n const depResult = results.get(depId)!;\n dependencyResults.set(depId, depResult);\n }\n }\n\n // If any direct dependency failed or was skipped, skip this check\n const directDeps = checkConfig.depends_on || [];\n const failedDeps: string[] = [];\n for (const depId of directDeps) {\n const depRes = results.get(depId);\n if (!depRes) continue;\n\n // Check if dependency was skipped\n const wasSkipped = (depRes.issues || []).some(issue => {\n const id = issue.ruleId || '';\n return id.endsWith('/__skipped');\n });\n\n // Treat these as fatal in direct dependencies:\n // - command provider execution/transform failures\n // - forEach validation/iteration errors\n // - fail_if conditions (global or check-specific)\n let hasFatalFailure = (depRes.issues || []).some(issue => {\n const id = issue.ruleId || '';\n return (\n id === 'command/execution_error' ||\n id.endsWith('/command/execution_error') ||\n id === 'command/timeout' ||\n id.endsWith('/command/timeout') ||\n id === 'command/transform_js_error' ||\n id.endsWith('/command/transform_js_error') ||\n id === 'command/transform_error' ||\n id.endsWith('/command/transform_error') ||\n id.endsWith('/forEach/iteration_error') ||\n id === 'forEach/undefined_output' ||\n id.endsWith('/forEach/undefined_output') ||\n id.endsWith('_fail_if') ||\n id.endsWith('/global_fail_if')\n );\n });\n\n // As a fallback, evaluate fail_if on the dependency result now (in case the provider path didn't add issues yet)\n if (!hasFatalFailure && config && (config.fail_if || config.checks[depId]?.fail_if)) {\n const failIfResults = await this.evaluateFailureConditions(depId, depRes, config);\n hasFatalFailure = failIfResults.some(r => r.failed);\n }\n\n if (debug) {\n log(\n `🔧 Debug: gating check '${checkName}' against dep '${depId}': wasSkipped=${wasSkipped} hasFatalFailure=${hasFatalFailure}`\n );\n }\n if (wasSkipped || hasFatalFailure) failedDeps.push(depId);\n }\n\n if (failedDeps.length > 0) {\n // Record skip and provide a concise console message\n this.recordSkip(checkName, 'dependency_failed');\n logger.info(`⏭ Skipped (dependency failed: ${failedDeps.join(', ')})`);\n return {\n checkName,\n error: null,\n result: { issues: [] },\n skipped: true,\n };\n }\n\n // Check direct dependencies for forEach behavior\n for (const depId of checkConfig.depends_on || []) {\n if (results.has(depId)) {\n const depResult = results.get(depId)!;\n\n // Check if this dependency has forEach enabled\n const depForEachResult = depResult as ReviewSummary & {\n isForEach?: boolean;\n forEachItems?: unknown[];\n };\n\n if (depForEachResult.isForEach && Array.isArray(depForEachResult.forEachItems)) {\n if (!isForEachDependent) {\n // First forEach dependency found - use it as the primary\n isForEachDependent = true;\n forEachItems = depForEachResult.forEachItems;\n forEachParentName = depId;\n }\n // Track all forEach parents for unwrapping\n forEachParents.push(depId);\n }\n }\n }\n\n // Determine if we should use session reuse\n let sessionInfo: { parentSessionId?: string; reuseSession?: boolean } | undefined =\n undefined;\n if (sessionReuseChecks.has(checkName)) {\n const parentCheckName = sessionProviders.get(checkName);\n if (parentCheckName && sessionIds.has(parentCheckName)) {\n const parentSessionId = sessionIds.get(parentCheckName)!;\n\n sessionInfo = {\n parentSessionId: parentSessionId,\n reuseSession: true,\n };\n\n if (debug) {\n log(\n `🔄 Debug: Check ${checkName} will reuse session from parent ${parentCheckName}: ${parentSessionId}`\n );\n }\n } else {\n if (debug) {\n log(\n `⚠️ Warning: Check ${checkName} requires session reuse but parent ${parentCheckName} session not found`\n );\n }\n }\n }\n\n // For checks that create new sessions, generate a session ID\n let currentSessionId: string | undefined = undefined;\n if (!sessionInfo?.reuseSession) {\n const timestamp = new Date().toISOString();\n currentSessionId = `visor-${timestamp.replace(/[:.]/g, '-')}-${checkName}`;\n sessionIds.set(checkName, currentSessionId);\n if (debug) {\n log(`🆕 Debug: Check ${checkName} will create new session: ${currentSessionId}`);\n }\n\n // Add session ID to provider config\n providerConfig.sessionId = currentSessionId;\n }\n\n // Handle forEach dependent execution\n let finalResult: ReviewSummary;\n\n if (isForEachDependent && forEachParentName) {\n // Record forEach preview items\n this.recordForEachPreview(checkName, forEachItems);\n\n // If the forEach parent returned an empty array, skip this check entirely\n if (forEachItems.length === 0) {\n if (debug) {\n log(\n `🔄 Debug: Skipping check \"${checkName}\" - forEach check \"${forEachParentName}\" returned 0 items`\n );\n }\n logger.info(` forEach: no items from \"${forEachParentName}\", skipping check...`);\n\n // Return a special marker result so that dependent checks can detect the skip\n finalResult = {\n issues: [],\n output: [],\n } as ReviewSummary;\n\n // Mark this result as forEach-capable but with empty items\n (finalResult as ExtendedReviewSummary).isForEach = true;\n (finalResult as ExtendedReviewSummary).forEachItems = [];\n\n // Skip to the end - don't execute this check\n } else {\n if (debug) {\n log(\n `🔄 Debug: Check \"${checkName}\" depends on forEach check \"${forEachParentName}\", executing ${forEachItems.length} times`\n );\n }\n\n // Log forEach processing start (non-debug)\n logger.info(\n ` forEach: processing ${forEachItems.length} items from \"${forEachParentName}\"...`\n );\n\n const allIssues: ReviewIssue[] = [];\n const allOutputs: unknown[] = [];\n const aggregatedContents: string[] = [];\n\n // Create task functions (not executed yet) - these will be executed with controlled concurrency\n // via executeWithLimitedParallelism to respect maxParallelism setting\n const itemTasks = forEachItems.map((item, itemIndex) => async () => {\n // Create modified dependency results with current item\n // For forEach branching: unwrap ALL forEach parents to create isolated execution branch\n const forEachDependencyResults = new Map<string, ReviewSummary>();\n for (const [depName, depResult] of dependencyResults) {\n if (forEachParents.includes(depName)) {\n // This is a forEach parent - unwrap its output for this iteration\n const depForEachResult = depResult as ReviewSummary & {\n output?: unknown;\n forEachItems?: unknown[];\n };\n\n if (\n Array.isArray(depForEachResult.output) &&\n depForEachResult.output[itemIndex] !== undefined\n ) {\n // Unwrap to the item at the current index\n const modifiedResult: ReviewSummary & { output?: unknown } = {\n issues: [],\n output: depForEachResult.output[itemIndex],\n };\n forEachDependencyResults.set(depName, modifiedResult);\n\n // Also provide -raw access to the full array\n const rawResult: ReviewSummary & { output?: unknown } = {\n issues: [],\n output: depForEachResult.output,\n };\n forEachDependencyResults.set(`${depName}-raw`, rawResult);\n } else {\n // Fallback: use the result as-is\n forEachDependencyResults.set(depName, depResult);\n }\n } else {\n forEachDependencyResults.set(depName, depResult);\n }\n }\n\n // Evaluate if condition for this forEach item\n if (checkConfig.if) {\n // Merge current results with forEach-specific dependency results for condition evaluation\n const conditionResults = new Map(results);\n for (const [depName, depResult] of forEachDependencyResults) {\n conditionResults.set(depName, depResult);\n }\n\n const shouldRun = await this.evaluateCheckCondition(\n checkName,\n checkConfig.if,\n prInfo,\n conditionResults,\n debug\n );\n\n if (!shouldRun) {\n if (debug) {\n log(\n `🔄 Debug: Skipping forEach item ${itemIndex + 1} for check \"${checkName}\" (if condition evaluated to false)`\n );\n }\n // Return empty result for skipped items\n return {\n index: itemIndex,\n itemResult: { issues: [] } as ReviewSummary,\n skipped: true,\n };\n }\n }\n\n if (debug) {\n log(\n `🔄 Debug: Executing check \"${checkName}\" for item ${itemIndex + 1}/${forEachItems.length}`\n );\n }\n\n // Track iteration start\n const iterationStart = this.recordIterationStart(checkName);\n\n // Execute with retry/routing semantics per item\n const itemResult = await this.executeWithRouting(\n checkName,\n checkConfig,\n provider,\n providerConfig,\n prInfo,\n forEachDependencyResults,\n sessionInfo,\n config,\n dependencyGraph,\n debug,\n results,\n /*foreachContext*/ {\n index: itemIndex,\n total: forEachItems.length,\n parent: forEachParentName,\n }\n );\n\n // Record iteration completion\n // Check if this iteration had fatal errors\n const hadFatalError = (itemResult.issues || []).some(issue => {\n const id = issue.ruleId || '';\n return (\n id === 'command/execution_error' ||\n id.endsWith('/command/execution_error') ||\n id === 'command/transform_js_error' ||\n id.endsWith('/command/transform_js_error') ||\n id === 'command/transform_error' ||\n id.endsWith('/command/transform_error') ||\n id === 'forEach/undefined_output' ||\n id.endsWith('/forEach/undefined_output')\n );\n });\n const iterationDuration = (Date.now() - iterationStart) / 1000;\n this.recordIterationComplete(\n checkName,\n iterationStart,\n !hadFatalError, // Success if no fatal errors\n itemResult.issues || [],\n (itemResult as any).output\n );\n\n // Log iteration progress\n logger.info(\n ` ✔ ${itemIndex + 1}/${forEachItems.length} (${iterationDuration.toFixed(1)}s)`\n );\n\n return { index: itemIndex, itemResult };\n });\n\n const forEachConcurrency = Math.max(\n 1,\n Math.min(forEachItems.length, effectiveMaxParallelism)\n );\n\n if (debug && forEachConcurrency > 1) {\n log(\n `🔄 Debug: Limiting forEach concurrency for check \"${checkName}\" to ${forEachConcurrency}`\n );\n }\n\n const forEachResults = await this.executeWithLimitedParallelism(\n itemTasks,\n forEachConcurrency,\n false\n );\n\n for (const result of forEachResults) {\n if (result.status === 'rejected') {\n // Instead of throwing, record the failure and continue with other iterations\n const error = result.reason;\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n // Create an error issue for this failed iteration\n allIssues.push({\n ruleId: `${checkName}/forEach/iteration_error`,\n severity: 'error',\n category: 'logic',\n message: `forEach iteration failed: ${errorMessage}`,\n file: '',\n line: 0,\n });\n\n if (debug) {\n log(\n `🔄 Debug: forEach iteration for check \"${checkName}\" failed: ${errorMessage}`\n );\n }\n continue;\n }\n\n // Skip results from skipped items (those that failed if condition)\n if ((result.value as any).skipped) {\n continue;\n }\n\n const { itemResult } = result.value;\n\n if (itemResult.issues) {\n allIssues.push(...itemResult.issues);\n }\n\n const resultWithOutput = itemResult as ReviewSummary & {\n output?: unknown;\n content?: string;\n };\n\n if (resultWithOutput.output !== undefined) {\n allOutputs.push(resultWithOutput.output);\n }\n\n const itemContent = resultWithOutput.content;\n if (typeof itemContent === 'string' && itemContent.trim()) {\n aggregatedContents.push(itemContent.trim());\n }\n }\n\n const finalOutput = allOutputs.length > 0 ? allOutputs : undefined;\n\n finalResult = {\n issues: allIssues,\n ...(finalOutput !== undefined ? { output: finalOutput } : {}),\n } as ExtendedReviewSummary;\n\n // Evaluate fail_if for aggregated forEach results (applies to the whole check)\n if (config && (config.fail_if || checkConfig.fail_if)) {\n const failureResults = await this.evaluateFailureConditions(\n checkName,\n finalResult,\n config\n );\n if (failureResults.length > 0) {\n const failureIssues = failureResults\n .filter(f => f.failed)\n .map(f => ({\n file: 'system',\n line: 0,\n ruleId: f.conditionName,\n message: f.message || `Failure condition met: ${f.expression}`,\n severity: (f.severity || 'error') as\n | 'info'\n | 'warning'\n | 'error'\n | 'critical',\n category: 'logic' as const,\n }));\n finalResult.issues = [...(finalResult.issues || []), ...failureIssues];\n }\n }\n\n // IMPORTANT: Mark this result as forEach-capable so that checks depending on it\n // will also iterate over the items (propagate forEach behavior down the chain)\n if (allOutputs.length > 0) {\n (finalResult as ExtendedReviewSummary).isForEach = true;\n (finalResult as ExtendedReviewSummary).forEachItems = allOutputs;\n }\n\n if (aggregatedContents.length > 0) {\n (finalResult as ReviewSummary & { content?: string }).content =\n aggregatedContents.join('\\n');\n }\n\n log(\n `🔄 Debug: Completed forEach execution for check \"${checkName}\", total issues: ${allIssues.length}`\n );\n } // End of else block for forEachItems.length > 0\n } else {\n // Normal single execution\n // Evaluate if condition for non-forEach-dependent checks\n if (checkConfig.if) {\n const shouldRun = await this.evaluateCheckCondition(\n checkName,\n checkConfig.if,\n prInfo,\n results,\n debug\n );\n\n if (!shouldRun) {\n // Record skip with condition\n this.recordSkip(checkName, 'if_condition', checkConfig.if);\n logger.info(`⏭ Skipped (if: ${this.truncate(checkConfig.if, 40)})`);\n return {\n checkName,\n error: null,\n result: {\n issues: [],\n },\n skipped: true,\n };\n }\n }\n\n // Execute with retry/routing semantics\n finalResult = await this.executeWithRouting(\n checkName,\n checkConfig,\n provider,\n providerConfig,\n prInfo,\n dependencyResults,\n sessionInfo,\n config,\n dependencyGraph,\n debug,\n results\n );\n\n // Evaluate fail_if for normal (non-forEach) execution\n if (config && (config.fail_if || checkConfig.fail_if)) {\n const failureResults = await this.evaluateFailureConditions(\n checkName,\n finalResult,\n config\n );\n if (failureResults.length > 0) {\n const failureIssues = failureResults\n .filter(f => f.failed)\n .map(f => ({\n file: 'system',\n line: 0,\n ruleId: f.conditionName,\n message: f.message || `Failure condition met: ${f.expression}`,\n severity: (f.severity || 'error') as 'info' | 'warning' | 'error' | 'critical',\n category: 'logic' as const,\n }));\n finalResult.issues = [...(finalResult.issues || []), ...failureIssues];\n }\n }\n\n // Record normal (non-forEach) execution\n // Check if this check had fatal errors\n const hadFatalError = (finalResult.issues || []).some(issue => {\n const id = issue.ruleId || '';\n return (\n id === 'command/execution_error' ||\n id.endsWith('/command/execution_error') ||\n id === 'command/timeout' ||\n id.endsWith('/command/timeout') ||\n id === 'command/transform_js_error' ||\n id.endsWith('/command/transform_js_error') ||\n id === 'command/transform_error' ||\n id.endsWith('/command/transform_error') ||\n id === 'forEach/undefined_output' ||\n id.endsWith('/forEach/undefined_output')\n );\n });\n this.recordIterationComplete(\n checkName,\n checkStartTime,\n !hadFatalError, // Success if no fatal errors\n finalResult.issues || [],\n (finalResult as any).output\n );\n\n if (checkConfig.forEach) {\n try {\n const finalResultWithOutput = finalResult as ExtendedReviewSummary;\n const outputPreview =\n JSON.stringify(finalResultWithOutput.output)?.slice(0, 200) || '(empty)';\n logger.debug(`🔧 Debug: Check \"${checkName}\" provider returned: ${outputPreview}`);\n } catch {\n // Ignore logging errors\n }\n }\n\n if (debug) {\n log(\n `🔧 Debug: Completed check: ${checkName}, issues found: ${(finalResult.issues || []).length}`\n );\n }\n }\n\n // Add checkName, group, schema, template info and timestamp to issues from config\n const enrichedIssues = (finalResult.issues || []).map(issue => ({\n ...issue,\n checkName: checkName,\n ruleId: `${checkName}/${issue.ruleId}`,\n group: checkConfig.group,\n schema: typeof checkConfig.schema === 'object' ? 'custom' : checkConfig.schema,\n template: checkConfig.template,\n timestamp: Date.now(),\n }));\n\n const enrichedResult = {\n ...finalResult,\n issues: enrichedIssues,\n };\n\n const checkDuration = ((Date.now() - checkStartTime) / 1000).toFixed(1);\n const issueCount = enrichedIssues.length;\n const checkStats = this.executionStats.get(checkName);\n\n // Enhanced completion message with forEach stats\n if (checkStats && checkStats.totalRuns > 1) {\n if (issueCount > 0) {\n logger.success(\n `Check complete: ${checkName} (${checkDuration}s) - ${checkStats.totalRuns} runs, ${issueCount} issue${issueCount === 1 ? '' : 's'}`\n );\n } else {\n logger.success(\n `Check complete: ${checkName} (${checkDuration}s) - ${checkStats.totalRuns} runs`\n );\n }\n } else if (checkStats && checkStats.outputsProduced && checkStats.outputsProduced > 0) {\n logger.success(\n `Check complete: ${checkName} (${checkDuration}s) - ${checkStats.outputsProduced} items`\n );\n } else if (issueCount > 0) {\n logger.success(\n `Check complete: ${checkName} (${checkDuration}s) - ${issueCount} issue${issueCount === 1 ? '' : 's'} found`\n );\n } else {\n logger.success(`Check complete: ${checkName} (${checkDuration}s)`);\n }\n\n return {\n checkName,\n error: null,\n result: enrichedResult,\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n const checkDuration = ((Date.now() - checkStartTime) / 1000).toFixed(1);\n\n // Record error in stats\n this.recordError(checkName, error instanceof Error ? error : new Error(String(error)));\n this.recordIterationComplete(checkName, checkStartTime, false, [], undefined);\n\n logger.error(`✖ Check failed: ${checkName} (${checkDuration}s) - ${errorMessage}`);\n\n if (debug) {\n log(`🔧 Debug: Error in check ${checkName}: ${errorMessage}`);\n }\n\n return {\n checkName,\n error: errorMessage,\n result: null,\n };\n }\n });\n\n // Execute checks in this level with controlled parallelism\n const levelResults = await this.executeWithLimitedParallelism(\n levelTaskFunctions,\n actualParallelism,\n effectiveFailFast\n );\n\n // Process results and store them for next level\n for (let i = 0; i < levelResults.length; i++) {\n const checkName = executionGroup.parallel[i];\n const result = levelResults[i];\n const checkConfig = config.checks[checkName];\n\n if (result.status === 'fulfilled' && result.value.result && !result.value.error) {\n // For skipped checks, store a marker so dependent checks can detect the skip\n if ((result.value as any).skipped) {\n if (debug) {\n log(`🔧 Debug: Storing skip marker for skipped check \"${checkName}\"`);\n }\n // Store a special marker result with a skip issue so dependencies can detect it\n results.set(checkName, {\n issues: [\n {\n ruleId: `${checkName}/__skipped`,\n severity: 'info',\n category: 'logic',\n message: 'Check was skipped',\n file: '',\n line: 0,\n },\n ],\n });\n continue;\n }\n\n const reviewResult = result.value.result;\n\n // Handle forEach logic - process array outputs\n const reviewSummaryWithOutput = reviewResult as ExtendedReviewSummary;\n\n if (checkConfig?.forEach && (!reviewResult.issues || reviewResult.issues.length === 0)) {\n const validation = this.validateAndNormalizeForEachOutput(\n checkName,\n reviewSummaryWithOutput.output,\n checkConfig.group\n );\n\n if (!validation.isValid) {\n results.set(\n checkName,\n validation.error.issues ? { issues: validation.error.issues } : {}\n );\n continue;\n }\n\n const normalizedOutput = validation.normalizedOutput;\n\n logger.debug(\n `🔧 Debug: Raw output for forEach check ${checkName}: ${\n Array.isArray(reviewSummaryWithOutput.output)\n ? `array(${reviewSummaryWithOutput.output.length})`\n : typeof reviewSummaryWithOutput.output\n }`\n );\n\n try {\n const preview = JSON.stringify(normalizedOutput);\n logger.debug(\n `🔧 Debug: Check \"${checkName}\" forEach output: ${preview?.slice(0, 200) || '(empty)'}`\n );\n } catch {\n // Ignore logging errors\n }\n\n // Store the array for iteration by dependent checks\n reviewSummaryWithOutput.forEachItems = normalizedOutput;\n reviewSummaryWithOutput.isForEach = true;\n }\n\n results.set(checkName, reviewResult);\n } else {\n // Store error result for dependency tracking\n const errorSummary: ReviewSummary = {\n issues: [\n {\n file: 'system',\n line: 0,\n endLine: undefined,\n ruleId: `${checkName}/error`,\n message:\n result.status === 'fulfilled'\n ? result.value.error || 'Unknown error'\n : result.reason instanceof Error\n ? result.reason.message\n : String(result.reason),\n severity: 'error',\n category: 'logic',\n suggestion: undefined,\n replacement: undefined,\n },\n ],\n };\n results.set(checkName, errorSummary);\n\n // Check if we should stop execution due to fail-fast\n if (effectiveFailFast) {\n if (debug) {\n log(`🛑 Check \"${checkName}\" failed and fail-fast is enabled - stopping execution`);\n }\n shouldStopExecution = true;\n break;\n }\n }\n }\n\n // If fail-fast is enabled, check if any successful checks have failure conditions\n if (effectiveFailFast && !shouldStopExecution) {\n for (let i = 0; i < levelResults.length; i++) {\n const checkName = executionGroup.parallel[i];\n const result = levelResults[i];\n\n if (result.status === 'fulfilled' && result.value.result && !result.value.error) {\n // Check for issues that should trigger fail-fast\n const hasFailuresToReport = (result.value.result.issues || []).some(\n issue => issue.severity === 'error' || issue.severity === 'critical'\n );\n\n if (hasFailuresToReport) {\n if (debug) {\n log(\n `🛑 Check \"${checkName}\" found critical/high issues and fail-fast is enabled - stopping execution`\n );\n }\n shouldStopExecution = true;\n break;\n }\n }\n }\n }\n }\n\n if (debug) {\n if (shouldStopExecution) {\n log(\n `🛑 Execution stopped early due to fail-fast after processing ${results.size} of ${checks.length} checks`\n );\n } else {\n log(`✅ Dependency-aware execution completed successfully for all ${results.size} checks`);\n }\n }\n\n // Cleanup sessions BEFORE printing summary to avoid mixing debug logs with table output\n if (sessionIds.size > 0 && debug) {\n log(`🧹 Cleaning up ${sessionIds.size} AI sessions...`);\n for (const [checkName, sessionId] of sessionIds) {\n try {\n sessionRegistry.unregisterSession(sessionId);\n log(`🗑️ Cleaned up session for check ${checkName}: ${sessionId}`);\n } catch (error) {\n log(`⚠️ Failed to cleanup session for check ${checkName}: ${error}`);\n }\n }\n }\n\n // Build and log final execution summary\n const executionStatistics = this.buildExecutionStatistics();\n\n // Show detailed summary table (only if logFn outputs to console)\n // Skip when output format is JSON/SARIF to avoid polluting structured output\n // Check if logFn is console.log (not a no-op or console.error)\n if (logFn === console.log) {\n this.logExecutionSummary(executionStatistics);\n }\n\n // Add warning if execution stopped early\n if (shouldStopExecution) {\n logger.info('');\n logger.warn(`⚠️ Execution stopped early due to fail-fast`);\n }\n\n // Aggregate all results\n return this.aggregateDependencyAwareResults(\n results,\n dependencyGraph,\n debug,\n shouldStopExecution\n );\n }\n\n /**\n * Execute multiple checks in parallel using controlled parallelism (legacy method)\n */\n private async executeParallelChecks(\n prInfo: PRInfo,\n checks: string[],\n timeout?: number,\n config?: import('./types/config').VisorConfig,\n logFn?: (message: string) => void,\n debug?: boolean,\n maxParallelism?: number,\n failFast?: boolean\n ): Promise<ReviewSummary> {\n const log = logFn || console.error;\n log(`🔧 Debug: Starting parallel execution of ${checks.length} checks`);\n\n if (!config?.checks) {\n throw new Error('Config with check definitions required for parallel execution');\n }\n\n // Determine effective max parallelism (CLI > config > default)\n const effectiveMaxParallelism = maxParallelism ?? config.max_parallelism ?? 3;\n // Determine effective fail-fast setting (CLI > config > default)\n const effectiveFailFast = failFast ?? config.fail_fast ?? false;\n log(`🔧 Debug: Using max parallelism: ${effectiveMaxParallelism}`);\n log(`🔧 Debug: Using fail-fast: ${effectiveFailFast}`);\n\n const provider = this.providerRegistry.getProviderOrThrow('ai');\n this.setProviderWebhookContext(provider);\n\n // Create individual check task functions\n const checkTaskFunctions = checks.map(checkName => async () => {\n const checkConfig = config.checks[checkName];\n if (!checkConfig) {\n log(`🔧 Debug: No config found for check: ${checkName}`);\n return {\n checkName,\n error: `No configuration found for check: ${checkName}`,\n result: null,\n };\n }\n\n try {\n console.error(\n `🔧 Debug: Starting check: ${checkName} with prompt type: ${typeof checkConfig.prompt}`\n );\n\n // Evaluate if condition to determine whether to run this check\n if (checkConfig.if) {\n const shouldRun = await this.failureEvaluator.evaluateIfCondition(\n checkName,\n checkConfig.if,\n {\n branch: prInfo.head,\n baseBranch: prInfo.base,\n filesChanged: prInfo.files.map(f => f.filename),\n event: 'issue_comment', // Command triggered from comment\n environment: getSafeEnvironmentVariables(),\n previousResults: new Map(), // No previous results in parallel execution\n }\n );\n\n if (!shouldRun) {\n console.error(\n `🔧 Debug: Skipping check '${checkName}' - if condition evaluated to false`\n );\n return {\n checkName,\n error: null,\n result: {\n issues: [],\n },\n };\n }\n }\n\n // Create provider config for this specific check\n const providerConfig: CheckProviderConfig = {\n type: 'ai',\n prompt: checkConfig.prompt,\n focus: checkConfig.focus || this.mapCheckNameToFocus(checkName),\n schema: checkConfig.schema,\n group: checkConfig.group,\n eventContext: prInfo.eventContext, // Pass event context for templates\n ai: {\n timeout: timeout || 600000,\n debug: debug, // Pass debug flag to AI provider\n ...(checkConfig.ai || {}),\n },\n };\n\n const result = await provider.execute(prInfo, providerConfig);\n console.error(\n `🔧 Debug: Completed check: ${checkName}, issues found: ${(result.issues || []).length}`\n );\n\n // Add group, schema info and timestamp to issues from config\n const enrichedIssues = (result.issues || []).map(issue => ({\n ...issue,\n ruleId: `${checkName}/${issue.ruleId}`,\n group: checkConfig.group,\n schema: typeof checkConfig.schema === 'object' ? 'custom' : checkConfig.schema,\n template: checkConfig.template,\n timestamp: Date.now(),\n }));\n\n const enrichedResult = {\n ...result,\n issues: enrichedIssues,\n };\n\n return {\n checkName,\n error: null,\n result: enrichedResult,\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n log(`🔧 Debug: Error in check ${checkName}: ${errorMessage}`);\n\n return {\n checkName,\n error: errorMessage,\n result: null,\n };\n }\n });\n\n // Execute all checks with controlled parallelism\n log(\n `🔧 Debug: Executing ${checkTaskFunctions.length} checks with max parallelism: ${effectiveMaxParallelism}`\n );\n const results = await this.executeWithLimitedParallelism(\n checkTaskFunctions,\n effectiveMaxParallelism,\n effectiveFailFast\n );\n\n // Check if execution was stopped early\n const completedChecks = results.filter(\n r => r.status === 'fulfilled' || r.status === 'rejected'\n ).length;\n const stoppedEarly = completedChecks < checks.length;\n\n if (stoppedEarly && effectiveFailFast) {\n log(\n `🛑 Parallel execution stopped early due to fail-fast after processing ${completedChecks} of ${checks.length} checks`\n );\n } else {\n log(`✅ Parallel execution completed for all ${completedChecks} checks`);\n }\n\n // Aggregate results from all checks\n return this.aggregateParallelResults(results, checks, debug, stoppedEarly);\n }\n\n /**\n * Execute a single configured check\n */\n private async executeSingleConfiguredCheck(\n prInfo: PRInfo,\n checkName: string,\n timeout?: number,\n config?: import('./types/config').VisorConfig,\n _logFn?: (message: string) => void\n ): Promise<ReviewSummary> {\n if (!config?.checks?.[checkName]) {\n throw new Error(`No configuration found for check: ${checkName}`);\n }\n\n const checkConfig = config.checks[checkName];\n const provider = this.providerRegistry.getProviderOrThrow('ai');\n this.setProviderWebhookContext(provider);\n\n const providerConfig: CheckProviderConfig = {\n type: 'ai',\n prompt: checkConfig.prompt,\n focus: checkConfig.focus || this.mapCheckNameToFocus(checkName),\n schema: checkConfig.schema,\n group: checkConfig.group,\n eventContext: prInfo.eventContext, // Pass event context for templates\n ai: {\n timeout: timeout || 600000,\n ...(checkConfig.ai || {}),\n },\n // Inherit global AI provider and model settings\n ai_provider: checkConfig.ai_provider || config.ai_provider,\n ai_model: checkConfig.ai_model || config.ai_model,\n };\n\n const result = await provider.execute(prInfo, providerConfig);\n\n // Prefix issues with check name and add group/schema info and timestamp from config\n const prefixedIssues = (result.issues || []).map(issue => ({\n ...issue,\n ruleId: `${checkName}/${issue.ruleId}`,\n group: checkConfig.group,\n schema: typeof checkConfig.schema === 'object' ? 'custom' : checkConfig.schema,\n timestamp: Date.now(),\n }));\n\n return {\n ...result,\n issues: prefixedIssues,\n };\n }\n\n /**\n * Map check name to focus for AI provider\n * This is a fallback when focus is not explicitly configured\n */\n private mapCheckNameToFocus(checkName: string): string {\n const focusMap: Record<string, string> = {\n security: 'security',\n performance: 'performance',\n style: 'style',\n architecture: 'architecture',\n };\n\n return focusMap[checkName] || 'all';\n }\n\n /**\n * Aggregate results from dependency-aware check execution\n */\n private aggregateDependencyAwareResults(\n results: Map<string, ReviewSummary>,\n dependencyGraph: DependencyGraph,\n debug?: boolean,\n stoppedEarly?: boolean\n ): ReviewSummary {\n const aggregatedIssues: ReviewSummary['issues'] = [];\n const debugInfo: string[] = [];\n const contentMap: Record<string, string> = {};\n\n // Add execution plan info\n const stats = DependencyResolver.getExecutionStats(dependencyGraph);\n const executionInfo = [\n stoppedEarly\n ? `🛑 Dependency-aware execution stopped early (fail-fast):`\n : `🔍 Dependency-aware execution completed:`,\n ` - ${results.size} of ${stats.totalChecks} checks processed`,\n ` - Execution levels: ${stats.parallelLevels}`,\n ` - Maximum parallelism: ${stats.maxParallelism}`,\n ` - Average parallelism: ${stats.averageParallelism.toFixed(1)}`,\n ` - Checks with dependencies: ${stats.checksWithDependencies}`,\n stoppedEarly ? ` - Stopped early due to fail-fast behavior` : ``,\n ].filter(Boolean);\n\n debugInfo.push(...executionInfo);\n\n // Process results in dependency order for better output organization\n for (const executionGroup of dependencyGraph.executionOrder) {\n for (const checkName of executionGroup.parallel) {\n const result = results.get(checkName);\n\n if (!result) {\n debugInfo.push(`❌ Check \"${checkName}\" had no result`);\n continue;\n }\n\n // Check if this was a successful result\n const hasErrors = (result.issues || []).some(\n issue => issue.ruleId?.includes('/error') || issue.ruleId?.includes('/promise-error')\n );\n\n if (hasErrors) {\n debugInfo.push(`❌ Check \"${checkName}\" failed with errors`);\n } else {\n debugInfo.push(\n `✅ Check \"${checkName}\" completed: ${(result.issues || []).length} issues found (level ${executionGroup.level})`\n );\n }\n\n // Issues are already prefixed and enriched with group/schema info\n // Filter out internal __skipped markers\n const nonInternalIssues = (result.issues || []).filter(\n issue => !issue.ruleId?.endsWith('/__skipped')\n );\n aggregatedIssues.push(...nonInternalIssues);\n\n const resultSummary = result as ExtendedReviewSummary;\n const resultContent = resultSummary.content;\n if (typeof resultContent === 'string' && resultContent.trim()) {\n contentMap[checkName] = resultContent.trim();\n }\n }\n }\n\n if (debug) {\n console.error(\n `🔧 Debug: Aggregated ${aggregatedIssues.length} issues from ${results.size} dependency-aware checks`\n );\n }\n\n // Apply issue suppression filtering\n const suppressionEnabled = this.config?.output?.suppressionEnabled !== false;\n const issueFilter = new IssueFilter(suppressionEnabled);\n const filteredIssues = issueFilter.filterIssues(aggregatedIssues, this.workingDirectory);\n\n // Collect debug information when debug mode is enabled\n let aggregatedDebug: import('./ai-review-service').AIDebugInfo | undefined;\n if (debug) {\n const debugResults = Array.from(results.entries()).filter(([_, result]) => result.debug);\n\n if (debugResults.length > 0) {\n const [, firstResult] = debugResults[0];\n const firstDebug = firstResult.debug!;\n\n const totalProcessingTime = debugResults.reduce((sum, [_, result]) => {\n return sum + (result.debug!.processingTime || 0);\n }, 0);\n\n aggregatedDebug = {\n provider: firstDebug.provider,\n model: firstDebug.model,\n apiKeySource: firstDebug.apiKeySource,\n processingTime: totalProcessingTime,\n prompt: debugResults\n .map(([checkName, result]) => `[${checkName}]\\n${result.debug!.prompt}`)\n .join('\\n\\n'),\n rawResponse: debugResults\n .map(([checkName, result]) => `[${checkName}]\\n${result.debug!.rawResponse}`)\n .join('\\n\\n'),\n promptLength: debugResults.reduce(\n (sum, [_, result]) => sum + (result.debug!.promptLength || 0),\n 0\n ),\n responseLength: debugResults.reduce(\n (sum, [_, result]) => sum + (result.debug!.responseLength || 0),\n 0\n ),\n jsonParseSuccess: debugResults.every(([_, result]) => result.debug!.jsonParseSuccess),\n errors: debugResults.flatMap(([checkName, result]) =>\n (result.debug!.errors || []).map((error: string) => `[${checkName}] ${error}`)\n ),\n timestamp: new Date().toISOString(),\n totalApiCalls: debugResults.length,\n apiCallDetails: debugResults.map(([checkName, result]) => ({\n checkName,\n provider: result.debug!.provider,\n model: result.debug!.model,\n processingTime: result.debug!.processingTime,\n success: result.debug!.jsonParseSuccess,\n })),\n };\n }\n }\n\n const summary: ReviewSummary & { __contents?: Record<string, string> } = {\n issues: filteredIssues,\n debug: aggregatedDebug,\n };\n\n if (Object.keys(contentMap).length > 0) {\n summary.__contents = contentMap;\n }\n\n return summary;\n }\n\n /**\n * Aggregate results from parallel check execution (legacy method)\n */\n private aggregateParallelResults(\n results: PromiseSettledResult<{\n checkName: string;\n error: string | null;\n result: ReviewSummary | null;\n }>[],\n checkNames: string[],\n debug?: boolean,\n _stoppedEarly?: boolean\n ): ReviewSummary {\n const aggregatedIssues: ReviewSummary['issues'] = [];\n const debugInfo: string[] = [];\n\n results.forEach((result, index) => {\n const checkName = checkNames[index];\n\n if (result.status === 'fulfilled') {\n const checkResult = result.value;\n\n if (checkResult.error) {\n logger.debug(`🔧 Debug: Check ${checkName} failed: ${checkResult.error}`);\n debugInfo.push(`❌ Check \"${checkName}\" failed: ${checkResult.error}`);\n\n // Check if this is a critical error\n const isCriticalError =\n checkResult.error.includes('API rate limit') ||\n checkResult.error.includes('403') ||\n checkResult.error.includes('401') ||\n checkResult.error.includes('authentication') ||\n checkResult.error.includes('API key');\n\n // Add error as an issue with appropriate severity\n aggregatedIssues.push({\n file: 'system',\n line: 0,\n endLine: undefined,\n ruleId: `${checkName}/error`,\n message: `Check \"${checkName}\" failed: ${checkResult.error}`,\n severity: isCriticalError ? 'critical' : 'error',\n category: 'logic',\n suggestion: isCriticalError\n ? 'Please check your API credentials and rate limits'\n : undefined,\n replacement: undefined,\n });\n } else if (checkResult.result) {\n logger.debug(\n `🔧 Debug: Check ${checkName} succeeded with ${(checkResult.result.issues || []).length} issues`\n );\n debugInfo.push(\n `✅ Check \"${checkName}\" completed: ${(checkResult.result.issues || []).length} issues found`\n );\n\n // Issues are already prefixed and enriched with group/schema info\n aggregatedIssues.push(...(checkResult.result.issues || []));\n }\n } else {\n const errorMessage =\n result.reason instanceof Error ? result.reason.message : String(result.reason);\n logger.debug(`🔧 Debug: Check ${checkName} promise rejected: ${errorMessage}`);\n debugInfo.push(`❌ Check \"${checkName}\" promise rejected: ${errorMessage}`);\n\n // Check if this is a critical error\n const isCriticalError =\n errorMessage.includes('API rate limit') ||\n errorMessage.includes('403') ||\n errorMessage.includes('401') ||\n errorMessage.includes('authentication') ||\n errorMessage.includes('API key');\n\n aggregatedIssues.push({\n file: 'system',\n line: 0,\n endLine: undefined,\n ruleId: `${checkName}/promise-error`,\n message: `Check \"${checkName}\" execution failed: ${errorMessage}`,\n severity: isCriticalError ? 'critical' : 'error',\n category: 'logic',\n suggestion: isCriticalError\n ? 'Please check your API credentials and rate limits'\n : undefined,\n replacement: undefined,\n });\n }\n });\n\n if (debug) {\n console.error(\n `🔧 Debug: Aggregated ${aggregatedIssues.length} issues from ${results.length} checks`\n );\n }\n\n // Apply issue suppression filtering\n const suppressionEnabled = this.config?.output?.suppressionEnabled !== false;\n const issueFilter = new IssueFilter(suppressionEnabled);\n const filteredIssues = issueFilter.filterIssues(aggregatedIssues, this.workingDirectory);\n\n // Collect debug information when debug mode is enabled\n let aggregatedDebug: import('./ai-review-service').AIDebugInfo | undefined;\n if (debug) {\n // Find the first successful result with debug information to use as template\n const debugResults = results\n .map((result, index) => ({\n result,\n checkName: checkNames[index],\n }))\n .filter(({ result }) => result.status === 'fulfilled' && result.value?.result?.debug);\n\n if (debugResults.length > 0) {\n const firstResult = debugResults[0].result;\n if (firstResult.status === 'fulfilled') {\n const firstDebug = firstResult.value!.result!.debug!;\n const totalProcessingTime = debugResults.reduce((sum, { result }) => {\n if (result.status === 'fulfilled') {\n return sum + (result.value!.result!.debug!.processingTime || 0);\n }\n return sum;\n }, 0);\n\n aggregatedDebug = {\n // Use first result as template for provider/model info\n provider: firstDebug.provider,\n model: firstDebug.model,\n apiKeySource: firstDebug.apiKeySource,\n // Aggregate processing time from all checks\n processingTime: totalProcessingTime,\n // Combine prompts with check names\n prompt: debugResults\n .map(({ checkName, result }) => {\n if (result.status === 'fulfilled') {\n return `[${checkName}]\\n${result.value!.result!.debug!.prompt}`;\n }\n return `[${checkName}] Error: Promise was rejected`;\n })\n .join('\\n\\n'),\n // Combine responses\n rawResponse: debugResults\n .map(({ checkName, result }) => {\n if (result.status === 'fulfilled') {\n return `[${checkName}]\\n${result.value!.result!.debug!.rawResponse}`;\n }\n return `[${checkName}] Error: Promise was rejected`;\n })\n .join('\\n\\n'),\n promptLength: debugResults.reduce((sum, { result }) => {\n if (result.status === 'fulfilled') {\n return sum + (result.value!.result!.debug!.promptLength || 0);\n }\n return sum;\n }, 0),\n responseLength: debugResults.reduce((sum, { result }) => {\n if (result.status === 'fulfilled') {\n return sum + (result.value!.result!.debug!.responseLength || 0);\n }\n return sum;\n }, 0),\n jsonParseSuccess: debugResults.every(({ result }) => {\n if (result.status === 'fulfilled') {\n return result.value!.result!.debug!.jsonParseSuccess;\n }\n return false;\n }),\n errors: debugResults.flatMap(({ result, checkName }) => {\n if (result.status === 'fulfilled') {\n return (result.value!.result!.debug!.errors || []).map(\n (error: string) => `[${checkName}] ${error}`\n );\n }\n return [`[${checkName}] Promise was rejected`];\n }),\n timestamp: new Date().toISOString(),\n // Add additional debug information for parallel execution\n totalApiCalls: debugResults.length,\n apiCallDetails: debugResults.map(({ checkName, result }) => {\n if (result.status === 'fulfilled') {\n return {\n checkName,\n provider: result.value!.result!.debug!.provider,\n model: result.value!.result!.debug!.model,\n processingTime: result.value!.result!.debug!.processingTime,\n success: result.value!.result!.debug!.jsonParseSuccess,\n };\n }\n return {\n checkName,\n provider: 'unknown',\n model: 'unknown',\n processingTime: 0,\n success: false,\n };\n }),\n };\n }\n }\n }\n\n return {\n issues: filteredIssues,\n debug: aggregatedDebug,\n };\n }\n\n /**\n * Get available check types\n */\n static getAvailableCheckTypes(): string[] {\n const registry = CheckProviderRegistry.getInstance();\n const providerTypes = registry.getAvailableProviders();\n // Add standard focus-based checks\n const standardTypes = ['security', 'performance', 'style', 'architecture', 'all'];\n // Combine provider types with standard types (remove duplicates)\n return [...new Set([...providerTypes, ...standardTypes])];\n }\n\n /**\n * Validate check types\n */\n static validateCheckTypes(checks: string[]): { valid: string[]; invalid: string[] } {\n const availableChecks = CheckExecutionEngine.getAvailableCheckTypes();\n const valid: string[] = [];\n const invalid: string[] = [];\n\n for (const check of checks) {\n if (availableChecks.includes(check)) {\n valid.push(check);\n } else {\n invalid.push(check);\n }\n }\n\n return { valid, invalid };\n }\n\n /**\n * List available providers with their status\n */\n async listProviders(): Promise<\n Array<{\n name: string;\n description: string;\n available: boolean;\n requirements: string[];\n }>\n > {\n return await this.providerRegistry.listProviders();\n }\n\n /**\n * Create a mock Octokit instance for local analysis\n */\n private createMockOctokit(): MockOctokit {\n // Create simple mock functions that return promises\n const mockGet = async () => ({\n data: {\n number: 0,\n title: 'Local Analysis',\n body: 'Local repository analysis',\n user: { login: 'local-user' },\n base: { ref: 'main' },\n head: { ref: 'HEAD' },\n },\n });\n\n const mockListFiles = async () => ({\n data: [],\n });\n\n const mockListComments = async () => ({\n data: [],\n });\n\n const mockCreateComment = async () => ({\n data: { id: 1 },\n });\n\n return {\n rest: {\n pulls: {\n get: mockGet,\n listFiles: mockListFiles,\n },\n issues: {\n listComments: mockListComments,\n createComment: mockCreateComment,\n },\n },\n request: async () => ({ data: {} }),\n graphql: async () => ({}),\n log: {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n },\n hook: {\n before: () => {},\n after: () => {},\n error: () => {},\n wrap: () => {},\n },\n auth: async () => ({ token: 'mock-token' }),\n };\n }\n\n /**\n * Create an error result\n */\n private createErrorResult(\n repositoryInfo: GitRepositoryInfo,\n errorMessage: string,\n startTime: number,\n timestamp: string,\n checksExecuted: string[]\n ): AnalysisResult {\n const executionTime = Date.now() - startTime;\n\n return {\n repositoryInfo,\n reviewSummary: {\n issues: [\n {\n file: 'system',\n line: 0,\n endLine: undefined,\n ruleId: 'system/error',\n message: errorMessage,\n severity: 'error',\n category: 'logic',\n suggestion: undefined,\n replacement: undefined,\n },\n ],\n },\n executionTime,\n timestamp,\n checksExecuted,\n };\n }\n\n /**\n * Check if a task result should trigger fail-fast behavior\n */\n private isFailFastCandidate(value: unknown): value is {\n error?: string;\n result?: { issues?: Array<{ severity?: string }> };\n } {\n if (typeof value !== 'object' || value === null) {\n return false;\n }\n\n const candidate = value as {\n error?: unknown;\n result?: unknown;\n };\n\n if (candidate.error !== undefined && typeof candidate.error !== 'string') {\n return false;\n }\n\n if (candidate.result !== undefined) {\n if (typeof candidate.result !== 'object' || candidate.result === null) {\n return false;\n }\n\n const issues = (candidate.result as { issues?: unknown }).issues;\n if (issues !== undefined && !Array.isArray(issues)) {\n return false;\n }\n }\n\n return true;\n }\n\n private shouldFailFast(result: unknown): boolean {\n if (!this.isFailFastCandidate(result)) {\n return false;\n }\n\n if (result.error) {\n return true;\n }\n\n // If the result has a result with critical or error issues, it should fail fast\n const issues = result.result?.issues;\n if (Array.isArray(issues)) {\n return issues.some(issue => issue?.severity === 'error' || issue?.severity === 'critical');\n }\n\n return false;\n }\n\n /**\n * Check if the working directory is a valid git repository\n */\n async isGitRepository(): Promise<boolean> {\n try {\n const repositoryInfo = await this.gitAnalyzer.analyzeRepository();\n return repositoryInfo.isGitRepository;\n } catch {\n return false;\n }\n }\n\n /**\n * Evaluate failure conditions for a check result\n */\n async evaluateFailureConditions(\n checkName: string,\n reviewSummary: ReviewSummary,\n config?: import('./types/config').VisorConfig\n ): Promise<FailureConditionResult[]> {\n if (!config) {\n return [];\n }\n\n const checkConfig = config.checks[checkName];\n const checkSchema =\n typeof checkConfig?.schema === 'object' ? 'custom' : checkConfig?.schema || '';\n const checkGroup = checkConfig?.group || '';\n\n // Handle new simple fail_if syntax\n const globalFailIf = config.fail_if;\n const checkFailIf = checkConfig?.fail_if;\n\n // If using new fail_if syntax\n if (globalFailIf || checkFailIf) {\n const results: FailureConditionResult[] = [];\n\n // Evaluate global fail_if\n if (globalFailIf) {\n const failed = await this.failureEvaluator.evaluateSimpleCondition(\n checkName,\n checkSchema,\n checkGroup,\n reviewSummary,\n globalFailIf\n );\n\n if (failed) {\n logger.warn(`⚠️ Check \"${checkName}\" - global fail_if condition met: ${globalFailIf}`);\n results.push({\n conditionName: 'global_fail_if',\n expression: globalFailIf,\n failed: true,\n severity: 'error',\n message: 'Global failure condition met',\n haltExecution: false,\n });\n } else {\n logger.debug(`✓ Check \"${checkName}\" - global fail_if condition passed`);\n }\n }\n\n // Evaluate check-specific fail_if (overrides global if present)\n if (checkFailIf) {\n const failed = await this.failureEvaluator.evaluateSimpleCondition(\n checkName,\n checkSchema,\n checkGroup,\n reviewSummary,\n checkFailIf\n );\n\n if (failed) {\n logger.warn(`⚠️ Check \"${checkName}\" - fail_if condition met: ${checkFailIf}`);\n results.push({\n conditionName: `${checkName}_fail_if`,\n expression: checkFailIf,\n failed: true,\n severity: 'error',\n message: `Check ${checkName} failure condition met`,\n haltExecution: false,\n });\n } else {\n logger.debug(`✓ Check \"${checkName}\" - fail_if condition passed`);\n }\n }\n\n return results;\n }\n\n // Fall back to old failure_conditions syntax\n const globalConditions = config.failure_conditions;\n const checkConditions = checkConfig?.failure_conditions;\n\n return await this.failureEvaluator.evaluateConditions(\n checkName,\n checkSchema,\n checkGroup,\n reviewSummary,\n globalConditions,\n checkConditions\n );\n }\n\n /**\n * Get repository status summary\n */\n async getRepositoryStatus(): Promise<{\n isGitRepository: boolean;\n hasChanges: boolean;\n branch: string;\n filesChanged: number;\n }> {\n try {\n const repositoryInfo = await this.gitAnalyzer.analyzeRepository();\n return {\n isGitRepository: repositoryInfo.isGitRepository,\n hasChanges: repositoryInfo.files.length > 0,\n branch: repositoryInfo.head,\n filesChanged: repositoryInfo.files.length,\n };\n } catch {\n return {\n isGitRepository: false,\n hasChanges: false,\n branch: 'unknown',\n filesChanged: 0,\n };\n }\n }\n\n /**\n * Initialize GitHub check runs for each configured check\n */\n private async initializeGitHubChecks(\n options: CheckExecutionOptions,\n logFn: (message: string) => void\n ): Promise<void> {\n if (\n !options.githubChecks?.octokit ||\n !options.githubChecks.owner ||\n !options.githubChecks.repo ||\n !options.githubChecks.headSha\n ) {\n logFn('⚠️ GitHub checks enabled but missing required parameters');\n return;\n }\n\n try {\n this.githubCheckService = new GitHubCheckService(options.githubChecks.octokit);\n this.checkRunMap = new Map();\n this.githubContext = {\n owner: options.githubChecks.owner,\n repo: options.githubChecks.repo,\n };\n\n logFn(`🔍 Creating GitHub check runs for ${options.checks.length} checks...`);\n\n for (const checkName of options.checks) {\n try {\n const checkRunOptions: CheckRunOptions = {\n owner: options.githubChecks.owner,\n repo: options.githubChecks.repo,\n head_sha: options.githubChecks.headSha,\n name: `Visor: ${checkName}`,\n external_id: `visor-${checkName}-${options.githubChecks.headSha.substring(0, 7)}`,\n };\n\n const checkRun = await this.githubCheckService.createCheckRun(checkRunOptions, {\n title: `${checkName} Analysis`,\n summary: `Running ${checkName} check using AI-powered analysis...`,\n });\n\n this.checkRunMap.set(checkName, checkRun);\n logFn(`✅ Created check run for ${checkName}: ${checkRun.url}`);\n } catch (error) {\n logFn(`❌ Failed to create check run for ${checkName}: ${error}`);\n }\n }\n } catch (error) {\n // Check if this is a permissions error\n if (\n error instanceof Error &&\n (error.message.includes('403') || error.message.includes('checks:write'))\n ) {\n logFn(\n '⚠️ GitHub checks API not available - insufficient permissions. Check runs will be skipped.'\n );\n logFn('💡 To enable check runs, ensure your GitHub token has \"checks:write\" permission.');\n this.githubCheckService = undefined;\n this.checkRunMap = undefined;\n } else {\n logFn(`❌ Failed to initialize GitHub check runs: ${error}`);\n this.githubCheckService = undefined;\n this.checkRunMap = undefined;\n }\n }\n }\n\n /**\n * Update GitHub check runs to in-progress status\n */\n private async updateGitHubChecksInProgress(options: CheckExecutionOptions): Promise<void> {\n if (\n !this.githubCheckService ||\n !this.checkRunMap ||\n !options.githubChecks?.owner ||\n !options.githubChecks.repo\n ) {\n return;\n }\n\n for (const [checkName, checkRun] of this.checkRunMap) {\n try {\n await this.githubCheckService.updateCheckRunInProgress(\n options.githubChecks.owner,\n options.githubChecks.repo,\n checkRun.id,\n {\n title: `Analyzing with ${checkName}...`,\n summary: `AI-powered analysis is in progress for ${checkName} check.`,\n }\n );\n console.log(`🔄 Updated ${checkName} check to in-progress status`);\n } catch (error) {\n console.error(`❌ Failed to update ${checkName} check to in-progress: ${error}`);\n }\n }\n }\n\n /**\n * Complete GitHub check runs with results\n */\n private async completeGitHubChecksWithResults(\n reviewSummary: ReviewSummary,\n options: CheckExecutionOptions,\n prInfo: import('./pr-analyzer').PRInfo\n ): Promise<void> {\n if (\n !this.githubCheckService ||\n !this.checkRunMap ||\n !options.githubChecks?.owner ||\n !options.githubChecks.repo\n ) {\n return;\n }\n\n // Group issues by check name\n const issuesByCheck = new Map<string, import('./reviewer').ReviewIssue[]>();\n\n // Initialize empty arrays for all checks\n for (const checkName of this.checkRunMap.keys()) {\n issuesByCheck.set(checkName, []);\n }\n\n // Group issues by their check name\n for (const issue of reviewSummary.issues || []) {\n if (issue.checkName && issuesByCheck.has(issue.checkName)) {\n issuesByCheck.get(issue.checkName)!.push(issue);\n }\n }\n\n console.log(`🏁 Completing ${this.checkRunMap.size} GitHub check runs...`);\n\n for (const [checkName, checkRun] of this.checkRunMap) {\n try {\n const checkIssues = issuesByCheck.get(checkName) || [];\n\n // Evaluate failure conditions for this specific check\n const failureResults = await this.evaluateFailureConditions(\n checkName,\n { issues: checkIssues },\n options.config\n );\n\n await this.githubCheckService.completeCheckRun(\n options.githubChecks.owner,\n options.githubChecks.repo,\n checkRun.id,\n checkName,\n failureResults,\n checkIssues,\n undefined, // executionError\n prInfo.files.map((f: import('./pr-analyzer').PRFile) => f.filename), // filesChangedInCommit\n options.githubChecks.prNumber, // prNumber\n options.githubChecks.headSha // currentCommitSha\n );\n\n console.log(`✅ Completed ${checkName} check with ${checkIssues.length} issues`);\n } catch (error) {\n console.error(`❌ Failed to complete ${checkName} check: ${error}`);\n\n // Try to mark the check as failed due to execution error\n try {\n await this.githubCheckService.completeCheckRun(\n options.githubChecks.owner,\n options.githubChecks.repo,\n checkRun.id,\n checkName,\n [],\n [],\n error instanceof Error ? error.message : 'Unknown error occurred'\n );\n } catch (finalError) {\n console.error(`❌ Failed to mark ${checkName} check as failed: ${finalError}`);\n }\n }\n }\n }\n\n /**\n * Complete GitHub check runs with error status\n */\n private async completeGitHubChecksWithError(errorMessage: string): Promise<void> {\n if (!this.githubCheckService || !this.checkRunMap || !this.githubContext) {\n return;\n }\n\n console.log(`❌ Completing ${this.checkRunMap.size} GitHub check runs with error...`);\n\n for (const [checkName, checkRun] of this.checkRunMap) {\n try {\n await this.githubCheckService.completeCheckRun(\n this.githubContext.owner,\n this.githubContext.repo,\n checkRun.id,\n checkName,\n [],\n [],\n errorMessage\n );\n console.log(`❌ Completed ${checkName} check with error: ${errorMessage}`);\n } catch (error) {\n console.error(`❌ Failed to complete ${checkName} check with error: ${error}`);\n }\n }\n }\n\n /**\n * Filter checks based on their event triggers to prevent execution of checks\n * that shouldn't run for the current event type\n */\n private filterChecksByEvent(\n checks: string[],\n config?: import('./types/config').VisorConfig,\n prInfo?: PRInfo,\n logFn?: (message: string) => void,\n debug?: boolean\n ): string[] {\n if (!config?.checks) {\n // No config available, return all checks (fallback behavior)\n return checks;\n }\n\n // If we have event context from GitHub (prInfo with eventType), apply strict filtering\n // Otherwise (CLI, tests), use conservative filtering\n const prInfoWithEvent = prInfo as PRInfo & {\n eventType?: import('./types/config').EventTrigger;\n };\n const hasEventContext =\n prInfoWithEvent && 'eventType' in prInfoWithEvent && prInfoWithEvent.eventType;\n\n if (hasEventContext) {\n // GitHub Action context - apply strict event filtering\n const currentEvent = prInfoWithEvent.eventType!;\n if (debug) {\n logFn?.(`🔧 Debug: GitHub Action context, current event: ${currentEvent}`);\n }\n\n const filteredChecks: string[] = [];\n for (const checkName of checks) {\n const checkConfig = config.checks[checkName];\n if (!checkConfig) {\n filteredChecks.push(checkName);\n continue;\n }\n\n const eventTriggers = checkConfig.on || [];\n if (eventTriggers.length === 0) {\n // No triggers specified, include it\n filteredChecks.push(checkName);\n if (debug) {\n logFn?.(`🔧 Debug: Check '${checkName}' has no event triggers, including`);\n }\n } else if (eventTriggers.includes(currentEvent)) {\n // Check matches current event\n filteredChecks.push(checkName);\n if (debug) {\n logFn?.(`🔧 Debug: Check '${checkName}' matches event '${currentEvent}', including`);\n }\n } else {\n // Check doesn't match current event\n if (debug) {\n logFn?.(\n `🔧 Debug: Check '${checkName}' does not match event '${currentEvent}' (triggers: ${JSON.stringify(eventTriggers)}), skipping`\n );\n }\n }\n }\n return filteredChecks;\n } else {\n // CLI/Test context - conservative filtering (only exclude manual-only checks)\n if (debug) {\n logFn?.(`🔧 Debug: CLI/Test context, using conservative filtering`);\n }\n\n const filteredChecks: string[] = [];\n for (const checkName of checks) {\n const checkConfig = config.checks[checkName];\n if (!checkConfig) {\n filteredChecks.push(checkName);\n continue;\n }\n\n const eventTriggers = checkConfig.on || [];\n\n // Only exclude checks that are explicitly manual-only\n if (eventTriggers.length === 1 && eventTriggers[0] === 'manual') {\n if (debug) {\n logFn?.(`🔧 Debug: Check '${checkName}' is manual-only, skipping`);\n }\n } else {\n filteredChecks.push(checkName);\n if (debug) {\n logFn?.(\n `🔧 Debug: Check '${checkName}' included (triggers: ${JSON.stringify(eventTriggers)})`\n );\n }\n }\n }\n return filteredChecks;\n }\n }\n\n /**\n * Determine the current event type from PR info\n */\n private getCurrentEventType(prInfo?: PRInfo): import('./types/config').EventTrigger {\n if (!prInfo) {\n return 'pr_opened'; // Default fallback\n }\n\n // For now, assume all PR-related operations are 'pr_updated' since we don't have\n // direct access to the original GitHub event here. This is a simplification.\n // In the future, we could pass the actual event type through the call chain.\n\n // The key insight is that issue-assistant should only run on issue_opened/issue_comment\n // events, which don't generate PRInfo objects in the first place.\n return 'pr_updated';\n }\n\n /**\n * Initialize execution statistics for a check\n */\n private initializeCheckStats(checkName: string): void {\n this.executionStats.set(checkName, {\n checkName,\n totalRuns: 0,\n successfulRuns: 0,\n failedRuns: 0,\n skipped: false,\n totalDuration: 0,\n issuesFound: 0,\n issuesBySeverity: {\n critical: 0,\n error: 0,\n warning: 0,\n info: 0,\n },\n perIterationDuration: [],\n });\n }\n\n /**\n * Record the start of a check iteration\n * Returns the start timestamp for duration tracking\n */\n private recordIterationStart(_checkName: string): number {\n return Date.now();\n }\n\n /**\n * Record completion of a check iteration\n */\n private recordIterationComplete(\n checkName: string,\n startTime: number,\n success: boolean,\n issues: ReviewIssue[],\n output?: unknown\n ): void {\n const stats = this.executionStats.get(checkName);\n if (!stats) return;\n\n const duration = Date.now() - startTime;\n stats.totalRuns++;\n if (success) {\n stats.successfulRuns++;\n } else {\n stats.failedRuns++;\n }\n stats.totalDuration += duration;\n stats.perIterationDuration!.push(duration);\n\n // Count issues by severity\n for (const issue of issues) {\n stats.issuesFound++;\n if (issue.severity === 'critical') stats.issuesBySeverity.critical++;\n else if (issue.severity === 'error') stats.issuesBySeverity.error++;\n else if (issue.severity === 'warning') stats.issuesBySeverity.warning++;\n else if (issue.severity === 'info') stats.issuesBySeverity.info++;\n }\n\n // Track outputs produced\n if (output !== undefined) {\n stats.outputsProduced = (stats.outputsProduced || 0) + 1;\n }\n }\n\n /**\n * Record that a check was skipped\n */\n private recordSkip(\n checkName: string,\n reason: 'if_condition' | 'fail_fast' | 'dependency_failed',\n condition?: string\n ): void {\n const stats = this.executionStats.get(checkName);\n if (!stats) return;\n\n stats.skipped = true;\n stats.skipReason = reason;\n if (condition) {\n stats.skipCondition = condition;\n }\n }\n\n /**\n * Record forEach preview items\n */\n private recordForEachPreview(checkName: string, items: unknown[]): void {\n const stats = this.executionStats.get(checkName);\n if (!stats || !items.length) return;\n\n // Store preview of first 3 items\n const preview = items.slice(0, 3).map(item => {\n const str = typeof item === 'string' ? item : JSON.stringify(item);\n return str.length > 50 ? str.substring(0, 47) + '...' : str;\n });\n\n if (items.length > 3) {\n preview.push(`...${items.length - 3} more`);\n }\n\n stats.forEachPreview = preview;\n }\n\n /**\n * Record an error for a check\n */\n private recordError(checkName: string, error: Error | string): void {\n const stats = this.executionStats.get(checkName);\n if (!stats) return;\n\n stats.errorMessage = error instanceof Error ? error.message : String(error);\n }\n\n /**\n * Build the final execution statistics object\n */\n private buildExecutionStatistics(): ExecutionStatistics {\n const checks = Array.from(this.executionStats.values());\n const totalExecutions = checks.reduce((sum, s) => sum + s.totalRuns, 0);\n const successfulExecutions = checks.reduce((sum, s) => sum + s.successfulRuns, 0);\n const failedExecutions = checks.reduce((sum, s) => sum + s.failedRuns, 0);\n const skippedChecks = checks.filter(s => s.skipped).length;\n const totalDuration = checks.reduce((sum, s) => sum + s.totalDuration, 0);\n\n return {\n totalChecksConfigured: checks.length,\n totalExecutions,\n successfulExecutions,\n failedExecutions,\n skippedChecks,\n totalDuration,\n checks,\n };\n }\n\n /**\n * Truncate a string to max length with ellipsis\n */\n private truncate(str: string, maxLen: number): string {\n if (str.length <= maxLen) return str;\n return str.substring(0, maxLen - 3) + '...';\n }\n\n /**\n * Format the Status column for execution summary table\n */\n private formatStatusColumn(stats: CheckExecutionStats): string {\n if (stats.skipped) {\n if (stats.skipReason === 'if_condition') return '⏭ if';\n if (stats.skipReason === 'fail_fast') return '⏭ ff';\n if (stats.skipReason === 'dependency_failed') return '⏭ dep';\n return '⏭';\n }\n\n if (stats.totalRuns === 0) return '-';\n\n const symbol = stats.failedRuns === 0 ? '✔' : stats.successfulRuns === 0 ? '✖' : '✔/✖';\n\n // Show iteration count if > 1\n if (stats.totalRuns > 1) {\n if (stats.failedRuns > 0 && stats.successfulRuns > 0) {\n // Partial success\n return `${symbol} ${stats.successfulRuns}/${stats.totalRuns}`;\n } else {\n // All success or all failed\n return `${symbol} ×${stats.totalRuns}`;\n }\n }\n\n return symbol;\n }\n\n /**\n * Format the Details column for execution summary table\n */\n private formatDetailsColumn(stats: CheckExecutionStats): string {\n const parts: string[] = [];\n\n // Outputs produced (forEach)\n if (stats.outputsProduced && stats.outputsProduced > 0) {\n parts.push(`→${stats.outputsProduced}`);\n }\n\n // Critical issues\n if (stats.issuesBySeverity.critical > 0) {\n parts.push(`${stats.issuesBySeverity.critical}🔴`);\n }\n\n // Warnings\n if (stats.issuesBySeverity.warning > 0) {\n parts.push(`${stats.issuesBySeverity.warning}⚠️`);\n }\n\n // Info (only if no critical/warnings)\n if (\n stats.issuesBySeverity.info > 0 &&\n stats.issuesBySeverity.critical === 0 &&\n stats.issuesBySeverity.warning === 0\n ) {\n parts.push(`${stats.issuesBySeverity.info}💡`);\n }\n\n // Error message or skip condition\n if (stats.errorMessage) {\n parts.push(this.truncate(stats.errorMessage, 20));\n } else if (stats.skipCondition) {\n parts.push(this.truncate(stats.skipCondition, 20));\n }\n\n return parts.join(' ');\n }\n\n /**\n * Log the execution summary table\n */\n private logExecutionSummary(stats: ExecutionStatistics): void {\n const totalIssues = stats.checks.reduce((sum, s) => sum + s.issuesFound, 0);\n const criticalIssues = stats.checks.reduce((sum, s) => sum + s.issuesBySeverity.critical, 0);\n const warningIssues = stats.checks.reduce((sum, s) => sum + s.issuesBySeverity.warning, 0);\n const durationSec = (stats.totalDuration / 1000).toFixed(1);\n\n // Summary box\n const summaryTable = new (require('cli-table3'))({\n style: {\n head: [],\n border: [],\n },\n colWidths: [41],\n });\n\n summaryTable.push(\n [`Execution Complete (${durationSec}s)`],\n [`Checks: ${stats.totalChecksConfigured} configured → ${stats.totalExecutions} executions`],\n [\n `Status: ${stats.successfulExecutions} ✔ │ ${stats.failedExecutions} ✖ │ ${stats.skippedChecks} ⏭`,\n ]\n );\n\n if (totalIssues > 0) {\n let issuesLine = `Issues: ${totalIssues} total`;\n if (criticalIssues > 0) issuesLine += ` (${criticalIssues} 🔴`;\n if (warningIssues > 0) issuesLine += `${criticalIssues > 0 ? ' ' : ' ('}${warningIssues} ⚠️)`;\n else if (criticalIssues > 0) issuesLine += ')';\n summaryTable.push([issuesLine]);\n }\n\n logger.info('');\n logger.info(summaryTable.toString());\n\n // Details table\n logger.info('');\n logger.info('Check Details:');\n\n const detailsTable = new (require('cli-table3'))({\n head: ['Check', 'Duration', 'Status', 'Details'],\n colWidths: [21, 10, 10, 21],\n style: {\n head: ['cyan'],\n border: ['grey'],\n },\n });\n\n for (const checkStats of stats.checks) {\n const duration = checkStats.skipped\n ? '-'\n : `${(checkStats.totalDuration / 1000).toFixed(1)}s`;\n const status = this.formatStatusColumn(checkStats);\n const details = this.formatDetailsColumn(checkStats);\n\n detailsTable.push([checkStats.checkName, duration, status, details]);\n }\n\n logger.info(detailsTable.toString());\n\n // Legend\n logger.info('');\n logger.info(\n 'Legend: ✔=success │ ✖=failed │ ⏭=skipped │ ×N=iterations │ →N=outputs │ N🔴=critical │ N⚠️=warnings'\n );\n }\n}\n"],"mappings":"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","names":["log","context","triggeringComment","fs","path","schemaPath","result","CheckExecutionEngine","fs","path","status","fs","path","content","lines","fs","path","fs","path","path","fs","extracted","exec","Sandbox","checkName","log","issues","suggestions","Sandbox","log","focus","path","createExtendedLiquid","fs","validation"]}
|