// engine/auditor-claude-md.ts — CLAUDE.md parser for custom quality rules
// SPEC-010: reads CLAUDE.md/.cursorrules from project root, extracts quality rules.
import { readFile } from 'node:fs/promises';
import { join } from 'node:path';
// Source file candidates (in priority order)
const CONFIG_FILES = ['CLAUDE.md', '.cursorrules', '.windsurfrules'];
/**
 * Parse project-level config files and extract quality rules.
 * Returns an array of QualityRule[] that can be added to QualityProfile.customRules.
 */
export async function parseProjectQualityRules(projectPath) {
    for (const configFile of CONFIG_FILES) {
        const content = await tryRead(join(projectPath, configFile));
        if (content) {
            return extractRulesFromContent(content, configFile);
        }
    }
    return [];
}
/**
 * Evaluate custom rules against file content and return pass/fail results.
 */
export function evaluateCustomRules(fileContent, rules, filePath) {
    return rules.map((rule) => {
        if (!rule.pattern) {
            return {
                rule: rule.id,
                source: rule.source,
                passed: true,
                detail: `Rule "${rule.description}" has no pattern — skipped.`,
            };
        }
        try {
            const regex = new RegExp(rule.pattern, 'gi');
            const violated = regex.test(fileContent);
            return {
                rule: rule.id,
                source: rule.source,
                passed: !violated,
                detail: violated
                    ? `Rule "${rule.description}" violated in ${filePath}`
                    : `Rule "${rule.description}" passed`,
            };
        }
        catch {
            return {
                rule: rule.id,
                source: rule.source,
                passed: true,
                detail: `Invalid pattern for rule "${rule.id}" — skipped.`,
            };
        }
    });
}
// === Helpers ===
async function tryRead(filePath) {
    try {
        return await readFile(filePath, 'utf-8');
    }
    catch {
        return null;
    }
}
function extractRulesFromContent(content, source) {
    const rules = [];
    // Extract ESLint-style rules mentioned in code blocks
    const eslintRules = [
        ...content.matchAll(/`([a-z-]+\/[a-z-]+|no-[a-z-]+|[a-z]+-[a-z-]+):\s*(error|warn)/g),
    ];
    for (const match of eslintRules) {
        const ruleId = match[1];
        const severity = match[2] === 'error' ? 'error' : 'warning';
        /* v8 ignore next 2 */
        if (!ruleId) {
            continue;
        }
        rules.push({
            id: `custom-${ruleId}`,
            description: `ESLint rule from ${source}: ${ruleId}`,
            category: mapRuleToCategory(ruleId),
            severity: severity,
            source,
        });
    }
    // Extract max-lines mentions
    const maxLines = /max.lines[^0-9]*(\d+)/i.exec(content);
    if (maxLines?.[1]) {
        const limit = parseInt(maxLines[1], 10);
        rules.push({
            id: 'custom-max-lines',
            description: `Files must not exceed ${limit} lines (from ${source})`,
            category: 'clean-code',
            severity: 'warning',
            source,
            pattern: undefined,
        });
    }
    // Extract no-any / no-explicit-any mentions
    if (/no.explicit.any|no.any/i.exec(content)) {
        rules.push({
            id: 'custom-no-any',
            description: `No explicit 'any' type (from ${source})`,
            category: 'clean-code',
            severity: 'error',
            source,
            pattern: ':\\s*any\\b',
        });
    }
    // Extract security keywords from Coding Rules sections
    if (/sql.injection|xss|owasp|sanitize/i.exec(content)) {
        rules.push({
            id: 'custom-security-awareness',
            description: `Project enforces security best practices (from ${source})`,
            category: 'security',
            severity: 'warning',
            source,
        });
    }
    return rules;
}
function mapRuleToCategory(ruleName) {
    if (/security|secret|injection|xss|csrf/i.exec(ruleName)) {
        return 'security';
    }
    if (/performance|async|sync|loop/i.exec(ruleName)) {
        return 'performance';
    }
    if (/complexity|lines|function|params|nesting/i.exec(ruleName)) {
        return 'clean-code';
    }
    if (/import|depend|layer|module/i.exec(ruleName)) {
        return 'architecture';
    }
    if (/test|spec|coverage/i.exec(ruleName)) {
        return 'testing';
    }
    return 'clean-code'; // sensible default
}
//# sourceMappingURL=auditor-claude-md.js.map