import { BaseVerificationStrategy } from "./base-verification.strategy"; import type { VerificationContext, StrategyResult, VerificationIssue } from "../interfaces"; export class BuildOutputStrategy extends BaseVerificationStrategy { name = "build-output"; verify(context: VerificationContext): Promise { const issues: VerificationIssue[] = []; // If no build output, assume build wasn't run (neutral result) if (!context.buildOutput) { return Promise.resolve({ strategyName: this.name, passed: true, confidence: 50, issues: [], }); } const { buildOutput } = context; // Check for TypeScript errors const tsErrorPattern = /error TS\d+:/gi; const tsErrors = this.extractEvidence(buildOutput, tsErrorPattern); if (tsErrors.length > 0) { issues.push({ type: "build-error", severity: "error", message: `Found ${tsErrors.length.toString()} TypeScript error(s)`, evidence: tsErrors.slice(0, 5).join("\n"), // Limit to first 5 }); } // Check for ESLint errors const eslintErrorPattern = /ESLint.*error/gi; const eslintErrors = this.extractEvidence(buildOutput, eslintErrorPattern); if (eslintErrors.length > 0) { issues.push({ type: "build-error", severity: "error", message: `Found ${eslintErrors.length.toString()} ESLint error(s)`, evidence: eslintErrors.slice(0, 5).join("\n"), }); } // Check for generic build errors const buildErrorPattern = /\berror\b.*(?:build|compilation|failed)/gi; const buildErrors = this.extractEvidence(buildOutput, buildErrorPattern); if (buildErrors.length > 0 && tsErrors.length === 0) { // Only add if not already counted as TS errors issues.push({ type: "build-error", severity: "error", message: `Build errors detected`, evidence: buildErrors.slice(0, 5).join("\n"), }); } // Check for compilation failure const compilationFailedPattern = /compilation failed|build failed/gi; if (compilationFailedPattern.test(buildOutput) && issues.length === 0) { issues.push({ type: "build-error", severity: "error", message: "Compilation failed", }); } // Check for warnings const warningPattern = /\bwarning\b/gi; const warnings = this.extractEvidence(buildOutput, warningPattern); if (warnings.length > 0) { issues.push({ type: "build-error", severity: "warning", message: `Found ${warnings.length.toString()} warning(s)`, evidence: warnings.slice(0, 3).join("\n"), }); } // Calculate confidence let confidence = 100; // Count total errors const errorCount = tsErrors.length + eslintErrors.length + buildErrors.length; if (errorCount > 0) { // More aggressive penalty: 30 points per error (3 errors = 10% confidence) confidence = Math.max(0, 100 - errorCount * 30); } // Penalty for warnings if (warnings.length > 0) { confidence -= Math.min(10, warnings.length * 2); } confidence = Math.max(0, Math.round(confidence)); return Promise.resolve({ strategyName: this.name, passed: issues.filter((i) => i.severity === "error").length === 0, confidence, issues, }); } }