// engine/spec-migrator/criteria-scanner.ts — SPEC-487: Scan lean specs for ambiguous criteria
import { readFile, readdir, stat } from 'node:fs/promises';
import { join } from 'node:path';
import { checkCriteriaQuality } from '../criteria-quality-checker.js';
import { isNativeActive, fastScanSpecs } from '../core-bridge.js';
const SPEC_DIR_RE = /^SPEC-\d+/;
/** Extract YAML frontmatter content (between first and second ---). */
function extractFrontmatterAndBody(content) {
    if (!content.startsWith('---\n')) {
        return null;
    }
    const closingIdx = content.indexOf('\n---', 4);
    if (closingIdx < 0) {
        return null;
    }
    return {
        frontmatter: content.slice(4, closingIdx),
        body: content.slice(closingIdx + 4).trim(),
    };
}
/** Extract criterion texts from lean spec frontmatter YAML. */
function extractCriteriaTexts(frontmatter) {
    const texts = [];
    // Match lines like:   - text: "criterion text here"
    const re = /^ {2}- text: "(.+?)"\s*$/gm;
    let match = re.exec(frontmatter);
    while (match) {
        const text = match[1]?.replace(/\\"/g, '"') ?? '';
        if (text.length > 0) {
            texts.push(text);
        }
        match = re.exec(frontmatter);
    }
    return texts;
}
/** Extract a field value from YAML frontmatter. */
function extractField(frontmatter, field) {
    const re = new RegExp(`^${field}:\\s+"?(.+?)"?\\s*$`, 'm');
    return re.exec(frontmatter)?.[1] ?? '';
}
/**
 * Scan all lean specs in a project for criteria with quality score < 50.
 * Returns an array of ambiguous criteria with context for LLM rewriting.
 */
export async function scanForAmbiguousCriteria(projectPath) {
    if (isNativeActive()) {
        const briefs = fastScanSpecs(projectPath);
        if (briefs) {
            return briefs.flatMap((b) => b.ambiguousCriteria.map((a) => ({
                specId: a.specId,
                specTitle: a.specTitle,
                specContext: '', // Native scanner doesn't return full body context yet
                criterionText: a.criterionText,
                score: a.score,
                reason: a.reason,
            })));
        }
    }
    const ambiguous = [];
    const specsDir = join(projectPath, 'planu/specs');
    let entries;
    try {
        entries = await readdir(specsDir);
    }
    catch {
        return [];
    }
    for (const entry of entries) {
        if (!SPEC_DIR_RE.test(entry)) {
            continue;
        }
        const specDir = join(specsDir, entry);
        try {
            const info = await stat(specDir);
            if (!info.isDirectory()) {
                continue;
            }
        }
        catch {
            continue;
        }
        const specPath = join(specDir, 'spec.md');
        let content;
        try {
            content = await readFile(specPath, 'utf-8');
        }
        catch {
            continue;
        }
        const parsed = extractFrontmatterAndBody(content);
        if (!parsed) {
            continue;
        }
        const { frontmatter, body } = parsed;
        const specId = extractField(frontmatter, 'id') || entry.replace(/-[a-z].*/i, '');
        const specTitle = extractField(frontmatter, 'title') || entry;
        const specContext = body.slice(0, 300);
        const criteria = extractCriteriaTexts(frontmatter);
        for (const criterionText of criteria) {
            const quality = checkCriteriaQuality(criterionText);
            if (quality.score < 50) {
                ambiguous.push({
                    specId,
                    specTitle,
                    specContext,
                    criterionText,
                    score: quality.score,
                    reason: quality.reason,
                });
            }
        }
    }
    return ambiguous;
}
//# sourceMappingURL=criteria-scanner.js.map