// tools/audit.ts — Quality evaluation (SOLID, clean code, architecture, security)
// Uses the auditor engine to scan code and report findings with scores.
import { specStore, knowledgeStore } from '../storage/index.js';
import { auditCode } from '../engine/auditor.js';
import { calcQualityScore } from '../engine/auditor-scoring.js';
import { parseProjectQualityRules } from '../engine/auditor-claude-md.js';
import { auditSolidityProject } from '../engine/solidity-auditor.js';
import { t, ti } from '../i18n/index.js';
import { createBasicPhaseEvent } from '../engine/phase-tracker.js';
import { calculateDoraMetrics, hasEnoughHistory, generateRecommendations, classifyMetric, } from '../engine/dora-metrics.js';
export async function handleAudit(args) {
    const { path, projectId, categories, specId } = args;
    // 1. Load project knowledge
    const knowledge = await knowledgeStore.getKnowledge(projectId);
    if (!knowledge) {
        return {
            content: [{ type: 'text', text: t('project.notFound') }],
            isError: true,
        };
    }
    const projectPath = knowledge.projectPath;
    // 2. Determine audit categories
    const auditCategories = categories ?? knowledge.qualityProfile.enabledCategories;
    // 3. Get quality profile for custom rules
    const qualityProfile = knowledge.qualityProfile;
    // 4. If specId is provided, load spec for context-aware auditing
    let specContext = null;
    if (specId) {
        const spec = await specStore.getSpec(projectId, specId);
        if (spec) {
            specContext = spec.title;
        }
    }
    // 5. Load CLAUDE.md custom rules and merge into profile
    const claudeMdRules = await parseProjectQualityRules(projectPath);
    const mergedProfile = {
        ...qualityProfile,
        customRules: [...qualityProfile.customRules, ...claudeMdRules],
    };
    // 5b. Run audit engine
    const result = await auditCode(path, projectPath, auditCategories, mergedProfile);
    // 5c. Calculate weighted quality score per category (SPEC-010)
    const qualityScore = calcQualityScore(result.findings);
    // 5c-b. SPEC-015b: Run Solidity audit for smart contract projects
    const isSolidity = knowledge.projectCategory === 'smart-contract' ||
        (knowledge.framework !== null &&
            ['hardhat', 'foundry', 'anchor', 'move'].includes(knowledge.framework)) ||
        /* v8 ignore next 3 */
        // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
        (knowledge.stack ?? []).some((s) => ['solidity', 'hardhat', 'foundry'].includes(s.toLowerCase()));
    const solidityAudit = isSolidity ? await auditSolidityProject(path) : null;
    // 5d. Load Constitution and flag strict auto-enforceable principles as critical
    const constitution = await knowledgeStore.getConstitution(projectId);
    const constitutionViolations = [];
    if (constitution) {
        for (const p of constitution.principles) {
            if (p.enforceLevel === 'strict' && p.autoEnforceable) {
                constitutionViolations.push({
                    principleId: p.id,
                    file: path,
                    description: `Verify compliance with strict principle: "${p.principle}"`,
                    severity: 'error',
                });
            }
        }
    }
    // 5e. SPEC-033: Calculate DORA metrics if at least 30 days of history
    const hasDoraHistory = await hasEnoughHistory(projectPath, 30);
    const doraMetrics = hasDoraHistory ? await calculateDoraMetrics(projectPath, 30) : null;
    const doraRecommendations = doraMetrics ? generateRecommendations(doraMetrics) : [];
    // 6. Build output
    const output = {
        path,
        projectId,
        ...(specId ? { specId, specContext } : {}),
        filesAnalyzed: result.filesAnalyzed,
        score: result.score,
        summary: {
            byCategory: result.summary.byCategory,
            topIssues: result.summary.topIssues,
            strengths: result.summary.strengths,
        },
        findings: result.findings.map((f) => ({
            file: f.file,
            ...(f.line ? { line: f.line } : {}),
            category: f.category,
            severity: f.severity,
            rule: f.rule,
            message: f.message,
            suggestion: f.suggestion,
            ...(f.reference ? { reference: f.reference } : {}),
        })),
        categoriesChecked: auditCategories,
        gradeLetter: scoreToGrade(result.score),
        constitutionViolations,
        ...(solidityAudit !== null ? { solidityAudit } : {}),
        ...(doraMetrics !== null
            ? {
                engineeringMetrics: {
                    dora: {
                        deploymentFrequency: doraMetrics.deploymentFrequency,
                        deploymentFrequencyTier: classifyMetric('deploymentFrequency', doraMetrics.deploymentFrequency),
                        leadTimeHours: doraMetrics.leadTimeHours,
                        leadTimeTier: classifyMetric('leadTimeHours', doraMetrics.leadTimeHours),
                        changeFailureRate: doraMetrics.changeFailureRate,
                        changeFailureTier: classifyMetric('changeFailureRate', doraMetrics.changeFailureRate),
                        mttrHours: doraMetrics.mttrHours,
                        mttrTier: classifyMetric('mttrHours', doraMetrics.mttrHours),
                        overallTier: doraMetrics.tier,
                        periodDays: 30,
                        commitsAnalyzed: doraMetrics.commitsAnalyzed,
                        note: 'Calculated from local git history. Accuracy is an approximation.',
                    },
                    recommendations: doraRecommendations,
                },
            }
            : {}),
        qualityScore: {
            overall: qualityScore.overall,
            gradeLetter: scoreToGrade(qualityScore.overall),
            categories: qualityScore.categories.map((c) => ({
                category: c.category,
                score: c.score,
                weight: c.weight,
                issueCount: c.issueCount,
                worstSeverity: c.worstSeverity,
                suggestions: c.suggestions,
            })),
            customRulesChecked: claudeMdRules.length,
        },
    };
    return {
        phaseEvent: createBasicPhaseEvent('audit', 'completed', 100, 'validating'),
        content: [
            {
                type: 'text',
                text: ti('tools.audit.success', {
                    score: String(result.score),
                    findingsCount: String(result.findings.length),
                }),
            },
            { type: 'text', text: JSON.stringify(output, null, 2) },
        ],
    };
}
function scoreToGrade(score) {
    if (score >= 90) {
        return 'A';
    }
    if (score >= 80) {
        return 'B';
    }
    if (score >= 70) {
        return 'C';
    }
    if (score >= 60) {
        return 'D';
    }
    return 'F';
}
//# sourceMappingURL=audit.js.map