// engine/drift-watcher/criteria-checker.ts — SPEC-388: criterion checks on file change
import { readFile } from 'node:fs/promises';
import { matchAnyKeyword } from '../keyword-matcher/index.js';
const HIGH_SEVERITY_KEYWORDS = [
    'auth',
    'security',
    'permission',
    'access',
    'token',
    'password',
];
const MEDIUM_SEVERITY_KEYWORDS = [
    'validate',
    'error',
    'fail',
    'reject',
    'limit',
    'timeout',
];
/**
 * Parse spec.md lines starting with "- [ ]" or "- [x]" as criteria.
 * Returns the criterion text stripped of the checkbox prefix.
 */
export async function extractCriteriaFromSpec(specPath) {
    try {
        const content = await readFile(specPath, 'utf-8');
        const lines = content.split('\n');
        const criteria = [];
        for (const line of lines) {
            const trimmed = line.trim();
            if (trimmed.startsWith('- [ ]') || trimmed.startsWith('- [x]')) {
                const text = trimmed.replace(/^- \[[ x]\]\s*/, '').trim();
                if (text.length > 0) {
                    criteria.push(text);
                }
            }
        }
        return criteria;
    }
    catch {
        return [];
    }
}
/**
 * Extract key terms from a criterion (words >=4 chars, lowercased).
 */
function extractKeyTerms(criterion) {
    return criterion
        .toLowerCase()
        .split(/\W+/)
        .filter((w) => w.length >= 4);
}
/**
 * Check if a file's content contains key terms from the criterion.
 * Returns true if any key term is found in the file.
 */
export async function checkCriterionInFile(criterion, filePath) {
    try {
        const content = await readFile(filePath, 'utf-8');
        const lower = content.toLowerCase();
        const terms = extractKeyTerms(criterion);
        return terms.some((term) => lower.includes(term));
    }
    catch {
        return false;
    }
}
/**
 * Determine severity based on criterion keywords.
 * auth/security keywords = high, validate/error = medium, otherwise low.
 *
 * Uses semantic boundary matching (minWordLength:3) to prevent false positives
 * like "error" matching inside "terror", while still catching short signals
 * like "auth", "fail", "go", etc. that are legitimate security indicators.
 */
function determineSeverity(criterion) {
    const lower = criterion.toLowerCase();
    // minWordLength:3 keeps short but specific signals (auth=4, fail=4, etc.)
    // requireBoundary:true prevents "error" matching in "terror", "auth" in "authority"
    if (matchAnyKeyword(lower, HIGH_SEVERITY_KEYWORDS, { minWordLength: 3, requireBoundary: true })
        .length > 0) {
        return 'high';
    }
    if (matchAnyKeyword(lower, MEDIUM_SEVERITY_KEYWORDS, { minWordLength: 3, requireBoundary: true })
        .length > 0) {
        return 'medium';
    }
    return 'low';
}
/**
 * Build a DriftAlert for a criterion that may no longer be satisfied.
 */
export function buildDriftAlert(specId, criterion, filePath) {
    const severity = determineSeverity(criterion);
    return {
        specId,
        criterionText: criterion,
        affectedFile: filePath,
        detectedAt: new Date().toISOString(),
        severity,
        suggestedFix: `Review ${filePath} to ensure it still satisfies: "${criterion}"`,
    };
}
//# sourceMappingURL=criteria-checker.js.map