const SECURITY_PATTERNS = [/password/i, /token/i, /secret/i, /apiKey/i, /api_key/i, /process\.env/];
const SECURITY_PATHS = ['auth/', 'middleware/', 'oauth/', 'jwt/', 'permissions/'];
/**
 * 30% weight — detects security-sensitive patterns in diff and file paths.
 */
export function analyzeSecuritySurface(files, diff) {
    const sensitiveFiles = files.filter((f) => SECURITY_PATHS.some((p) => f.includes(p)));
    const patternMatches = SECURITY_PATTERNS.filter((p) => p.test(diff));
    if (sensitiveFiles.length > 0 && patternMatches.length > 0) {
        return {
            score: 90,
            reason: `Security-sensitive files modified (${sensitiveFiles[0]}) with credential patterns detected`,
        };
    }
    if (sensitiveFiles.length > 0) {
        return {
            score: 70,
            reason: `Security-sensitive paths modified: ${sensitiveFiles.slice(0, 2).join(', ')}`,
        };
    }
    if (patternMatches.length >= 3) {
        return {
            score: 60,
            reason: `Multiple credential patterns in diff (password, token, secret, etc.)`,
        };
    }
    if (patternMatches.length > 0) {
        return {
            score: 35,
            reason: `Credential-related patterns detected in diff`,
        };
    }
    return { score: 10, reason: 'No security-sensitive patterns detected' };
}
/**
 * 25% weight — checks if tests accompany code changes.
 */
export function analyzeCoverageDelta(linesAdded, files) {
    const hasTests = files.some((f) => f.includes('.test.ts') ||
        f.includes('.spec.ts') ||
        f.includes('.test.js') ||
        f.includes('tests/') ||
        f.includes('__tests__/'));
    if (linesAdded === 0) {
        return { score: 10, reason: 'No new lines added — deletion/refactor only' };
    }
    if (hasTests) {
        const codeFiles = files.filter((f) => !f.includes('.test.') && !f.includes('.spec.') && !f.includes('__tests__/'));
        if (codeFiles.length === 0) {
            return { score: 5, reason: 'Test-only changes' };
        }
        return { score: 20, reason: 'Test files included in the changeset' };
    }
    if (linesAdded > 200) {
        return { score: 85, reason: `Large addition (${linesAdded} lines) with no test coverage` };
    }
    if (linesAdded > 50) {
        return { score: 65, reason: `Significant addition (${linesAdded} lines) without tests` };
    }
    return { score: 45, reason: 'No test files in changeset' };
}
const CORE_FILES = ['index.ts', 'types/index.ts', 'base-store.ts'];
/**
 * 20% weight — estimates blast radius by file count and core file changes.
 */
export function analyzeBlastRadius(filesChanged, files) {
    const touchesCoreFiles = files.some((f) => CORE_FILES.some((c) => f.endsWith(c)));
    let baseScore;
    let reason;
    if (filesChanged > 20) {
        baseScore = 80;
        reason = `Very large changeset: ${filesChanged} files modified`;
    }
    else if (filesChanged > 10) {
        baseScore = 50;
        reason = `Large changeset: ${filesChanged} files modified`;
    }
    else if (filesChanged > 5) {
        baseScore = 30;
        reason = `Moderate changeset: ${filesChanged} files modified`;
    }
    else {
        baseScore = 10;
        reason = `Small changeset: ${filesChanged} files modified`;
    }
    if (touchesCoreFiles) {
        const capped = Math.min(100, Math.round(baseScore * 1.5));
        return {
            score: capped,
            reason: `${reason} — includes core files (index.ts, types/index.ts, or base-store.ts)`,
        };
    }
    return { score: baseScore, reason };
}
const MIGRATION_PATTERNS = [/migration/i, /ALTER\s+TABLE/i, /DROP\s+TABLE/i, /DROP\s+COLUMN/i];
const SCHEMA_FILES = ['schema.ts', 'schema.js', 'migrations/', 'migrate/'];
/**
 * 15% weight — detects schema migrations and irreversible changes.
 */
export function analyzeReversibility(files, diff) {
    const hasMigrationFile = files.some((f) => SCHEMA_FILES.some((s) => f.includes(s)));
    const hasDestructivePatterns = MIGRATION_PATTERNS.filter((p) => p.test(diff));
    if (hasMigrationFile && hasDestructivePatterns.length > 0) {
        return {
            score: 95,
            reason: 'Migration files with destructive SQL patterns (ALTER/DROP) detected',
        };
    }
    if (hasMigrationFile) {
        return { score: 70, reason: 'Database migration files in changeset' };
    }
    if (hasDestructivePatterns.length > 0) {
        return {
            score: 60,
            reason: 'Destructive schema patterns detected in diff',
        };
    }
    return { score: 10, reason: 'No migration or schema changes detected' };
}
/**
 * 10% weight — checks spec compliance via context.
 */
export function analyzeSpecCompliance(files, context) {
    // Unused but kept for API consistency
    void files;
    if (context && /SPEC-\d+/i.test(context)) {
        return {
            score: 20,
            reason: 'Spec ID found in context — changes appear spec-driven',
        };
    }
    if (context && context.trim().length > 10) {
        return {
            score: 35,
            reason: 'Context provided but no spec ID — partially compliant',
        };
    }
    return {
        score: 50,
        reason: 'No spec context provided — cannot verify spec-driven development',
    };
}
//# sourceMappingURL=analyzers.js.map