// engine/ears/criterion-scorer.ts — EARS criterion scoring (SPEC-410)
import { detectEarsPattern, detectVaguenessFlags, isEarsCompliant } from './pattern-matcher.js';
import { generateRewrites } from './rewriter.js';
// Patterns that indicate a measurable numeric threshold
const NUMERIC_VALUE_REGEX = /\d+\s*(?:ms|milliseconds?|seconds?|minutes?|hours?|items?|%|percent|kb|mb|gb|px|requests?|users?|calls?|retries?)/i;
// Patterns for specific API routes/endpoints
const ENDPOINT_REGEX = /(?:\/api\/|GET\s+|POST\s+|PUT\s+|DELETE\s+|PATCH\s+)/i;
// Patterns for clear success conditions
const SUCCESS_CONDITION_REGEX = /\b(?:returns?|displays?|shows?|navigates?\s+to|renders?|saves?|stores?|loads?|creates?|sends?|emits?)\b/i;
// Patterns for a measurable threshold (numeric value with unit or comparison)
const MEASURABLE_THRESHOLD_REGEX = /\b(?:at (?:most|least)|no more than|within|fewer than|greater than|more than|\d+\s*(?:ms|seconds?|items?|%|kb|mb))\b/i;
// Patterns for named components/features
const COMPONENT_REGEX = /\b(?:[A-Z][a-zA-Z]+(?:Component|Page|Modal|Service|Store|API|Endpoint|Handler|Manager|Controller|View|Form|Button|Panel|Screen)|\w+[-_]\w+)\b/;
// Patterns for trigger conditions
const TRIGGER_REGEX = /\b(?:when|if|while|where|after|before|on(?:ce)?)\b/i;
// Patterns for actors
const ACTOR_REGEX = /\b(?:user|admin|system|operator|manager|client|server|guest|subscriber|owner)\b/i;
/**
 * Score a single acceptance criterion using EARS and testability heuristics.
 */
export function scoreCriterion(text) {
    const earsPattern = detectEarsPattern(text);
    const earsCompliant = isEarsCompliant(text);
    const vaguenessFlagsFound = detectVaguenessFlags(text);
    const vaguenessDeduction = Math.min(vaguenessFlagsFound.length * 2, 10);
    // --- Testability Score (0-10) ---
    let testabilityScore = 0;
    if (NUMERIC_VALUE_REGEX.test(text)) {
        testabilityScore += 3;
    }
    if (earsCompliant) {
        testabilityScore += 3;
    }
    if (ENDPOINT_REGEX.test(text)) {
        testabilityScore += 2;
    }
    if (SUCCESS_CONDITION_REGEX.test(text)) {
        testabilityScore += 2;
    }
    testabilityScore = Math.max(0, testabilityScore - vaguenessDeduction);
    testabilityScore = Math.min(10, testabilityScore);
    // --- Specificity Score (0-10) ---
    let specificityScore = 0;
    if (MEASURABLE_THRESHOLD_REGEX.test(text) || NUMERIC_VALUE_REGEX.test(text)) {
        specificityScore += 4;
    }
    if (COMPONENT_REGEX.test(text)) {
        specificityScore += 3;
    }
    if (TRIGGER_REGEX.test(text)) {
        specificityScore += 2;
    }
    if (ACTOR_REGEX.test(text)) {
        specificityScore += 1;
    }
    specificityScore = Math.max(0, specificityScore - vaguenessDeduction);
    specificityScore = Math.min(10, specificityScore);
    const overallScore = Math.round(((testabilityScore + specificityScore) / 2) * 10) / 10;
    // Generate rewrite suggestions only when score is below threshold
    const rewriteSuggestions = overallScore < 7 ? generateRewrites(text, earsPattern) : [];
    return {
        text,
        testabilityScore,
        specificityScore,
        earsPattern,
        earsCompliant,
        vaguenessFlagsFound,
        overallScore,
        rewriteSuggestions,
    };
}
export function gradeSpec(avgScore) {
    if (avgScore >= 9) {
        return 'A';
    }
    if (avgScore >= 7) {
        return 'B';
    }
    if (avgScore >= 5) {
        return 'C';
    }
    if (avgScore >= 3) {
        return 'D';
    }
    return 'F';
}
//# sourceMappingURL=criterion-scorer.js.map