import { loadKnowledgeConfig, extractNumberRule, extractListRule } from "../knowledge/knowledge_config_loader.js";
import { debug } from "../core/logger.js";
/**
 * 测试质量分析器 — 对测试文件进行纯规则维度的质量评估，包含断言密度、边界覆盖、
 * 命名规范性、断言重复和场景覆盖五个检查维度。零 AI 依赖。
 *
 * 机制 4: 变异测试防造假 — 通过逻辑算符反转和边界值偏移模拟代码变异，
 * 检测现有测试是否能捕捉到变更。若变异后测试依然全绿，判定测试无效。
 *
 * 分析测试文件质量，返回结构化报告，包含各项检查的评分和改进建议。
 * @param testContent - 测试文件内容
 * @param filename - 测试文件名（用于结果标识）
 * @param sourceContent - 可选的被测源码内容（用于变异测试）
 * @returns 测试质量报告，包含总分(0-100)、各项检查结果和改进建议列表
 */
/**
 * 分析测试文件质量，返回评分和检查结果。
 * @param filename - 测试文件名
 * @param content - 文件内容
 * @returns 质量评分和检查项列表
 */
export function analyzeTestQuality(testContent, filename, sourceContent, coverageMap, sourceFilePath) {
    debug("测试质量分析", `开始分析 ${filename}`);
    const checks = [];
    const suggestions = [];
    // ── 1. assertion_density ──
    const assertionDensityCheck = checkAssertionDensity(testContent);
    checks.push(assertionDensityCheck);
    if (!assertionDensityCheck.passed) {
        suggestions.push("建议为每个测试函数添加至少一个断言 (expect/assert)");
    }
    // ── 2. boundary_coverage ──
    const boundaryCheck = checkBoundaryCoverage(testContent);
    checks.push(boundaryCheck);
    if (!boundaryCheck.passed) {
        suggestions.push("建议增加边界值测试 (null, undefined, 空值, 极端值等)");
    }
    // ── 3. naming ──
    const namingCheck = checkNaming(testContent);
    checks.push(namingCheck);
    if (!namingCheck.passed) {
        suggestions.push("建议使用更具描述性的测试命名 (should/when/returns/handles/throws)");
    }
    // ── 4. duplication ──
    const duplicationCheck = checkDuplication(testContent);
    checks.push(duplicationCheck);
    if (!duplicationCheck.passed) {
        suggestions.push("建议提取公共断言为辅助函数，减少重复断言");
    }
    // ── 5. scenario_coverage ──
    const scenarioCheck = checkScenarioCoverage();
    checks.push(scenarioCheck);
    // ── 6. mutation_audit (机制 4: 变异测试防造假 + 覆盖率联动) ──
    if (sourceContent) {
        debug("测试质量分析", `启动变异测试防造假检测`);
        const mutationCheck = checkMutationResistanceWithCoverage(testContent, sourceContent, coverageMap, sourceFilePath);
        checks.push(mutationCheck);
        if (!mutationCheck.passed) {
            suggestions.push("测试可能存在'自己证明自己'问题：变异后断言仍能通过。建议增加反向用例和精确断言");
        }
    }
    else {
        // 无源码时跳过变异测试，不扣分
        checks.push({
            dimension: "scenario_coverage",
            passed: true,
            detail: "变异测试跳过（未提供被测源码）",
        });
    }
    // 评分计算: 满分 100，每项未通过的检查扣 16.7 分（6 项），最低 0 分
    // ── 评分计算 ──
    let score = 100;
    const deduction = Math.floor(100 / checks.length);
    for (const check of checks) {
        if (!check.passed) {
            score -= deduction;
        }
    }
    score = Math.max(0, score);
    debug("测试质量分析", `${filename} 评分 ${score}/100，${checks.filter(c => c.passed).length}/${checks.length} 项通过`);
    // ── 门禁硬化：为未通过的检查标记 severity ──
    let warningCount = 0;
    for (const check of checks) {
        if (!check.passed) {
            check.severity = "warning";
            warningCount++;
        }
    }
    return {
        file: filename,
        score,
        checks,
        suggestions,
        warning_count: warningCount,
    };
}
// ────────────────────────────────────────────
// 检查实现
// ────────────────────────────────────────────
/** 断言密度检查 — 统计测试函数数与断言数的比率，阈值 >= 1.0（每个测试至少一个断言） */
function checkAssertionDensity(content) {
    // 匹配 it/test/@Test 函数调用，统计测试函数总数
    const testFnMatches = content.match(/\b(it|test|@Test)\s*\(/g) ?? [];
    const testCount = testFnMatches.length;
    if (testCount === 0) {
        return {
            dimension: "assertion_density",
            passed: false,
            detail: "未检测到测试函数",
        };
    }
    // 匹配 expect/assert/assertEquals/assertEquals/assertThat/assertStrictEquals 调用
    const assertMatches = content.match(/\b(expect|assert|assertEquals|assertThat|assertStrictEquals)\s*\(/g) ?? [];
    // 过滤非断言的 expect 匹配器 (expect.any(), expect.arrayContaining() 等)
    const matcherSuffixes = ["any(", "arrayContaining(", "objectContaining(", "stringContaining(", "stringMatching(", "extend(", "anything(", "closeTo(", "assertions("];
    const assertCount = assertMatches.filter((m) => {
        // 对于 expect( 调用，检查括号后面跟随的内容
        const expectMatch = m.match(/^expect\s*\($/);
        if (expectMatch) {
            // 在内容中定位匹配位置并检查后续内容
            const idx = content.indexOf(m);
            const afterOpen = content.slice(idx + m.length).trimStart();
            return !matcherSuffixes.some((suffix) => afterOpen.startsWith(suffix));
        }
        return true;
    }).length;
    const density = assertCount / testCount;
    if (density >= 1.0) {
        return {
            dimension: "assertion_density",
            passed: true,
            detail: `断言密度: ${density.toFixed(1)} (${assertCount} 断言 / ${testCount} 测试)`,
        };
    }
    return {
        dimension: "assertion_density",
        passed: false,
        detail: `断言密度不足: ${density.toFixed(1)} (${assertCount} 断言 / ${testCount} 测试, 阈值 >= 1.0)`,
    };
}
/** 边界覆盖检查 — 在 expect() 和 it()/test() 代码块内搜索边界值关键字（null/undefined/空值/极值等） */
function checkBoundaryCoverage(content) {
    // 仅在 expect() 上下文和 it()/test() 代码块内搜索，避免误匹配 URL/端口/import 中的值
    // 提取所有 expect(...) 代码块内容（按括号深度匹配到闭合）
    const expectContexts = [];
    const expectRegex = /\bexpect\s*\(/g;
    let expectMatch;
    while ((expectMatch = expectRegex.exec(content)) !== null) {
        // 跳过非断言匹配器 (expect.any(), expect.arrayContaining() 等)
        const afterOpen = content.slice(expectMatch.index + expectMatch[0].length).trimStart();
        if (/^(any|arrayContaining|objectContaining|stringContaining|stringMatching|extend|anything|closeTo|assertions)\s*\(/.test(afterOpen)) {
            continue;
        }
        // 提取 expect 块内容（按括号深度匹配到对应的闭合括号）
        let depth = 1;
        let pos = expectMatch.index + expectMatch[0].length;
        while (pos < content.length && depth > 0) {
            if (content[pos] === "(")
                depth++;
            else if (content[pos] === ")")
                depth--;
            pos++;
        }
        expectContexts.push(content.slice(expectMatch.index, pos));
    }
    // 同时搜索 it()/test() 代码块内部
    const testBlockRegex = /\b(?:it|test)\s*\(\s*["'`][^"'`]*["'`]\s*,\s*(?:async\s+)?/g;
    let testMatch;
    while ((testMatch = testBlockRegex.exec(content)) !== null) {
        // 提取回调函数开始后的代码块内容
        let depth = 0;
        let pos = testMatch.index + testMatch[0].length;
        while (pos < content.length && depth >= 0) {
            if (content[pos] === "{")
                depth++;
            else if (content[pos] === "}") {
                depth--;
                if (depth === 0) {
                    pos++;
                    break;
                }
            }
            pos++;
        }
        expectContexts.push(content.slice(testMatch.index, pos));
    }
    const searchableText = expectContexts.join("\n");
    // 跳过注释行和 import 语句
    const filteredLines = searchableText
        .split("\n")
        .filter((line) => !line.trim().startsWith("//") && !line.trim().startsWith("*") && !line.trimStart().startsWith("import "));
    const filteredText = filteredLines.join("\n");
    // 边界值关键字列表: null、undefined、空字符串、数字边界、中文描述
    const boundaryKeywords = [
        "null", "undefined", '""', "''", "0",
        "MAX_VALUE", "MIN_VALUE", "MAX_SAFE_INTEGER", "MIN_SAFE_INTEGER",
        "empty", "blank", "边界", "极端",
    ];
    const found = [];
    for (const keyword of boundaryKeywords) {
        if (filteredText.includes(keyword)) {
            found.push(keyword);
        }
    }
    if (found.length > 0) {
        return {
            dimension: "boundary_coverage",
            passed: true,
            detail: `检测到边界值测试: ${found.join(", ")}`,
        };
    }
    return {
        dimension: "boundary_coverage",
        passed: false,
        detail: "未检测到边界值测试",
    };
}
/**
 * 命名规范性检查 — 提取 it()/test() 中的测试名称，检查描述性关键词占比是否 >= 50%。
 * 支持英文关键词（should/when/returns/handles/throws）和中文关键词（应该/当/返回/处理/抛出）。
 */
function checkNaming(content) {
    // 从 it("...", test("...", 模式中提取测试名称
    const namePattern = /\b(?:it|test)\s*\(\s*["'`]([^"'`]+)["'`]/g;
    const names = [];
    let match;
    while ((match = namePattern.exec(content)) !== null) {
        names.push(match[1]);
    }
    if (names.length === 0) {
        // 无法提取测试名称（如仅使用 describe）— 中性通过（无法评估）
        return {
            dimension: "naming",
            passed: true,
            detail: "未提取到测试名称 (可能使用 describe-only 模式)",
        };
    }
    // 描述性关键词: 英文 BDD 命名约定和中文命名约定
    const descriptiveKeywords = [
        "should", "when", "returns", "can", "handles", "throws",
        "shouldn't", "must", "will",
        "应该", "当", "返回", "处理", "抛出", "正确", "失败",
    ];
    let descriptiveCount = 0;
    for (const name of names) {
        const lowerName = name.toLowerCase();
        for (const keyword of descriptiveKeywords) {
            if (lowerName.includes(keyword.toLowerCase())) {
                descriptiveCount++;
                break;
            }
        }
    }
    const ratio = descriptiveCount / names.length;
    if (ratio >= 0.5) {
        return {
            dimension: "naming",
            passed: true,
            detail: `描述性命名比例: ${(ratio * 100).toFixed(0)}% (${descriptiveCount}/${names.length})`,
        };
    }
    return {
        dimension: "naming",
        passed: false,
        detail: `测试命名不够描述性: ${(ratio * 100).toFixed(0)}% (${descriptiveCount}/${names.length})`,
    };
}
/** 断言重复检查 — 提取所有 expect() 语句，计算重复比率，阈值 > 30% 则不通过 */
function checkDuplication(content) {
    // 提取 expect(...) 语句
    const expectPattern = /\bexpect\s*\([^)]*\)/g;
    const expectCalls = [];
    let match;
    while ((match = expectPattern.exec(content)) !== null) {
        expectCalls.push(match[0].trim());
    }
    if (expectCalls.length === 0) {
        // 无可衡量的内容 — 中性通过
        return {
            dimension: "duplication",
            passed: true,
            detail: "无断言语句，跳过重复检查",
        };
    }
    // 排序后统计唯一断言数，重复率 = 1 - (唯一数/总数)
    const sorted = [...expectCalls].sort();
    const unique = new Set(sorted);
    const duplicateRatio = 1 - unique.size / sorted.length;
    if (duplicateRatio > 0.3) {
        const duplicateCount = sorted.length - unique.size;
        return {
            dimension: "duplication",
            passed: false,
            detail: `存在重复断言: ${duplicateCount}/${sorted.length} 条重复 (${(duplicateRatio * 100).toFixed(0)}%)`,
        };
    }
    return {
        dimension: "duplication",
        passed: true,
        detail: `断言重复率: ${(duplicateRatio * 100).toFixed(0)}%`,
    };
}
/** 场景覆盖检查 — 占位检查，实际场景覆盖需结合知识模板验收项进行交叉评估 */
function checkScenarioCoverage() {
    return {
        dimension: "scenario_coverage",
        passed: true,
        detail: "需结合知识模板验收项进行交叉检查",
    };
}
// ── 机制 4: 变异测试防造假（知识库驱动） ──
/** 从知识库 变异审计.md 读取变异审计配置 */
function loadMutationConfig() {
    const config = loadKnowledgeConfig("patterns/core/变异审计.md");
    const body = config?.body ?? "";
    return {
        precision_threshold: extractNumberRule(body, "Precision_Threshold") ?? 0.5,
        max_sample_lines: 8,
        whitelist_keywords: extractListRule(body, "变异白名单") ?? ["if", "else", "switch", "===", "!=="],
        blacklist_keywords: extractListRule(body, "变异黑名单") ?? ["console.log", "import", "export", "debugger"],
    };
}
const MUTATION_CONFIG = loadMutationConfig();
/** 预定义变异操作集 */
const MUTATION_OPERATORS = [
    {
        description: "逻辑算符反转 (=== → !==, !== → ===, > → <=, < → >=)",
        mutate: (line) => {
            if (/===/.test(line) && !/!==/.test(line))
                return line.replace(/===/g, "!==");
            if (/!==/.test(line))
                return line.replace(/!==/g, "===");
            if (/>=/.test(line))
                return line.replace(/>=/g, "<");
            if (/<=/.test(line))
                return line.replace(/<=/g, ">");
            if (/>/.test(line) && !/>=/.test(line))
                return line.replace(/>/g, "<=");
            if (/</.test(line) && !/<=/.test(line))
                return line.replace(/</g, ">=");
            return line;
        },
    },
    {
        description: "边界值偏移 (+1/-1 常量数字)",
        mutate: (line) => {
            return line.replace(/\b(\d+)\b/g, (_, num) => {
                const n = parseInt(num, 10);
                if (n === 0)
                    return "1";
                if (n === 1)
                    return "0";
                return (n + 1).toString();
            });
        },
    },
    {
        description: "布尔值反转 (true → false, false → true)",
        mutate: (line) => {
            if (/\btrue\b/.test(line))
                return line.replace(/\btrue\b/g, "false");
            if (/\bfalse\b/.test(line))
                return line.replace(/\bfalse\b/g, "true");
            return line;
        },
    },
    {
        description: "返回值篡改 (return → return null)",
        mutate: (line) => {
            if (/return\s+/.test(line) && !/return\s+null/.test(line)) {
                return line.replace(/return\s+/, "return null; // ");
            }
            return line;
        },
    },
];
// ── 变异白名单: AST 级别节点过滤 ──
/**
 * 判断一行代码是否属于可变异的白名单节点。
 * 白名单: 条件分支(if/else/switch)、比较/逻辑操作符、return 语句、算术表达式。
 * 黑名单: console.log、注释、import/export、纯字符串/变量名赋值、类型声明。
 */
function isMutationCandidate(line) {
    const trimmed = line.trim();
    // 黑名单: 跳过注释
    if (trimmed.startsWith("//") || trimmed.startsWith("*") || trimmed.startsWith("/*"))
        return false;
    // 黑名单: 跳过 import/export 声明
    if (/^(import |export |from )/.test(trimmed))
        return false;
    // 黑名单: 跳过 console.log / console.warn / console.error 等无副作用日志
    if (/console\.(log|warn|error|info|debug)\s*\(/.test(trimmed))
        return false;
    // 黑名单: 跳过纯类型声明（TypeScript interface/type/enum）
    if (/^(interface |type |enum |declare )/.test(trimmed))
        return false;
    // 黑名单: 跳过纯字符串字面量行（无逻辑）
    if (/^['"`]/.test(trimmed) && trimmed.endsWith(';'))
        return false;
    // 黑名单: 跳过 debugger / breakpoint
    if (/^debugger/.test(trimmed))
        return false;
    // 白名单: 条件分支 (if / else if / switch / case / ternary)
    if (/\b(if|else|switch|case)\b/.test(trimmed) && /[(){}?]/.test(trimmed))
        return true;
    // 白名单: 比较操作符
    if (/(===|!==|==|!=|>=|<=|>|<)/.test(trimmed))
        return true;
    // 白名单: 逻辑操作符 (&& ||)
    if (/(&&|\|\|)/.test(trimmed))
        return true;
    // 白名单: return 语句（非 return void）
    if (/\breturn\b/.test(trimmed) && !/return\s*;\s*$/.test(trimmed))
        return true;
    // 白名单: 布尔字面量在表达式中
    if (/\b(true|false)\b/.test(trimmed) && /[=(){}?]/.test(trimmed))
        return true;
    // 白名单: 算术表达式在赋值/返回中
    if (/[+\-*/%]/.test(trimmed) && /[=()]/.test(trimmed))
        return true;
    return false;
}
/**
 * 变异测试防造假 — 通过对源码模拟变异，检查测试的断言是否精确到能检测变异。
 * 策略: 从源码中提取白名单关键逻辑行（AST 级别过滤），执行变异，
 * 检查测试中是否有断言针对这些逻辑的精确值。
 * 若测试只含模糊断言（如 toBeTruthy），判定为可能存在"自己证明自己"问题。
 */
/** 伪随机数生成器 (基于种子，确保可复现且不由 AI 控制) */
function seededRandom(seed) {
    let s = seed;
    return () => {
        s = (s * 1103515245 + 12345) & 0x7fffffff;
        return s / 0x7fffffff;
    };
}
/** 基于 RNG 的随机抽样（Fisher-Yates 部分洗牌）*/
function seededSample(arr, count, rng) {
    const result = [...arr];
    const n = Math.min(count, result.length);
    for (let i = 0; i < n; i++) {
        const j = i + Math.floor(rng() * (result.length - i));
        [result[i], result[j]] = [result[j], result[i]];
    }
    return result.slice(0, n);
}
/**
 * 将旧版扁平 src/engine/X.ts 路径重映射到重组后的子目录路径。
 * engine/ 目录重组后，很多模块被移入 core/、pipeline/、templates/ 等子目录。
 * lcov 报告可能仍使用旧路径，需要规范化。
 */
function remapEnginePath(sfPath) {
    // src/engine/ 下已知的子目录归属映射（扁平文件名 → 子目录）
    const engineSubdirMap = {
        // core/
        llm_gateway: "core",
        logger: "core",
        debug_log: "core",
        helpers: "core",
        io_controller: "core",
        git_deps: "core",
        log_governance: "core",
        path_scope_utils: "core",
        // pipeline/
        classifier: "pipeline",
        intent_router: "pipeline",
        intent_expander: "pipeline",
        task_context: "pipeline",
        scope_controller: "pipeline",
        job_manager: "pipeline",
        task_planner: "pipeline",
        // templates/
        scaffolder: "templates",
        template_sync: "templates",
        consumable_asset_registry: "templates",
        asset_manifest: "templates",
        // audit/
        code_reviewer: "audit",
        test_quality: "audit",
        audit_verifier: "audit",
        mutation_audit: "audit",
        privacy_secret_contract: "audit",
        // contracts/
        contract_registry: "contracts",
        mechanism_contract_registry: "contracts",
        dual_layer_mechanism_registry: "contracts",
        tool_invocation_contract_registry: "contracts",
        // knowledge/
        knowledge_config_loader: "knowledge",
        knowledge_manager: "knowledge",
        // release/
        verifier: "release",
        release_readiness_gate: "release",
    };
    const prefix = "src/engine/";
    if (!sfPath.startsWith(prefix))
        return sfPath;
    const rest = sfPath.slice(prefix.length);
    // 已经在子目录中的路径直接返回
    if (rest.includes("/"))
        return sfPath;
    const baseName = rest.replace(/\.ts$/, "");
    const subdir = engineSubdirMap[baseName];
    if (subdir)
        return `${prefix}${subdir}/${rest}`;
    return sfPath;
}
/**
 * 解析 lcov.info 报告，提取每个文件的已覆盖行号。
 * lcov 格式:
 *   SF:path/to/file.ts
 *   DA:10,1
 *   DA:25,0
 *   end_of_record
 * DA 行中第二个字段 > 0 表示该行被执行过（已覆盖）。
 * @param lcovContent - lcov.info 文件内容
 * @returns 覆盖率映射（文件路径 → 已覆盖行号集合）
 */
export function parseLcov(lcovContent) {
    const map = new Map();
    debug("覆盖率解析", `开始解析 lcov 报告`);
    let currentFile = "";
    for (const line of lcovContent.split("\n")) {
        const sfMatch = line.match(/^SF:(.+)$/);
        if (sfMatch) {
            currentFile = remapEnginePath(sfMatch[1]);
            continue;
        }
        const daMatch = line.match(/^DA:(\d+),(\d+)/);
        if (daMatch && currentFile) {
            const lineNum = parseInt(daMatch[1], 10);
            const hitCount = parseInt(daMatch[2], 10);
            if (hitCount > 0) {
                if (!map.has(currentFile))
                    map.set(currentFile, new Set());
                map.get(currentFile).add(lineNum);
            }
        }
        if (line === "end_of_record") {
            currentFile = "";
        }
    }
    return map;
}
/**
 * 带覆盖率联动的变异测试 — 只变异被测试覆盖的代码行。
 * 若变异了未覆盖行，该变异无法被测试检测到，审计结果无效。
 * @param testContent - 测试文件内容
 * @param sourceContent - 被测源码内容
 * @param coverageMap - 可选的覆盖率映射（文件 → 已覆盖行号），无则退化为全行变异
 * @param sourceFilePath - 源码文件路径，用于在 coverageMap 中查找覆盖行
 */
function checkMutationResistanceWithCoverage(testContent, sourceContent, coverageMap, sourceFilePath) {
    const sourceLines = sourceContent.split("\n");
    const coveredLineNumbers = (sourceFilePath && coverageMap) ? coverageMap.get(sourceFilePath) : undefined;
    // 提取白名单关键逻辑行，并记录行号
    const candidates = [];
    for (let i = 0; i < sourceLines.length; i++) {
        if (isMutationCandidate(sourceLines[i])) {
            candidates.push({ line: sourceLines[i], lineNum: i + 1 });
        }
    }
    if (candidates.length === 0) {
        return {
            dimension: "scenario_coverage",
            passed: true,
            detail: "无可变异的关键逻辑行，跳过变异测试",
        };
    }
    // 覆盖率过滤: 只保留被测试覆盖的行
    let filteredCandidates = candidates;
    const hasCoverageData = coverageMap !== undefined && sourceFilePath !== undefined;
    if (hasCoverageData) {
        const covered = coveredLineNumbers ?? new Set();
        const beforeCount = candidates.length;
        if (covered.size === 0) {
            return {
                dimension: "scenario_coverage",
                passed: false,
                detail: `变异审计无效: ${beforeCount} 个可变异行均未被测试覆盖（覆盖率联动）`,
            };
        }
        filteredCandidates = candidates.filter((c) => covered.has(c.lineNum));
        if (filteredCandidates.length === 0) {
            return {
                dimension: "scenario_coverage",
                passed: false,
                detail: `变异审计无效: ${beforeCount} 个可变异行均未被测试覆盖（覆盖率联动）`,
            };
        }
    }
    // 随机抽样
    const seed = sourceContent.split("").reduce((acc, ch) => acc + ch.charCodeAt(0), 0);
    const rng = seededRandom(seed);
    const sampleSize = Math.min(filteredCandidates.length, 8);
    const keyLines = seededSample(filteredCandidates, sampleSize, rng);
    // 断言精确度检查 — 使用宽松正则以支持嵌套括号如 expect(fn(a, b))
    const preciseAssertions = testContent.match(/\bexpect\b.*?\.(toBe|toEqual|toStrictEqual|toBeLessThan|toBeGreaterThan|toThrow|toThrowError)\s*\(/g) ?? [];
    const looseAssertions = testContent.match(/\bexpect\b.*?\.(toBeTruthy|toBeFalsy|toBeDefined|toBeUndefined)\s*\(/g) ?? [];
    const totalAssertions = preciseAssertions.length + looseAssertions.length;
    if (totalAssertions === 0) {
        return {
            dimension: "scenario_coverage",
            passed: false,
            detail: "无断言，无法检测源码变异（变异测试防造假失败）",
        };
    }
    const precisionRatio = preciseAssertions.length / totalAssertions;
    let mutationsApplied = 0;
    let mutationsUndetected = 0;
    for (const item of keyLines) {
        const shuffledOps = seededSample([...MUTATION_OPERATORS], MUTATION_OPERATORS.length, rng);
        for (const mut of shuffledOps) {
            const mutated = mut.mutate(item.line);
            if (mutated !== item.line) {
                mutationsApplied++;
                const mutatedValues = mutated.match(/(!==|===|<=|>=|>|<|\b\d+\b|true|false)/g) ?? [];
                const hasDetection = mutatedValues.some((v) => testContent.includes(v));
                if (!hasDetection)
                    mutationsUndetected++;
                break;
            }
        }
    }
    const passThreshold = MUTATION_CONFIG.precision_threshold;
    const precisionOk = precisionRatio >= passThreshold;
    const detectionOk = mutationsApplied === 0 || (mutationsUndetected / mutationsApplied) < passThreshold;
    const coverageNote = hasCoverageData ? `（覆盖率联动: ${filteredCandidates.length}/${candidates.length} 可变异行已被覆盖）` : "";
    if (precisionOk && detectionOk) {
        return {
            dimension: "scenario_coverage",
            passed: true,
            detail: `变异测试通过（随机抽样 ${keyLines.length} 行${coverageNote}）— 精确断言率 ${(precisionRatio * 100).toFixed(0)}%，${mutationsApplied} 次变异中 ${mutationsApplied - mutationsUndetected} 次可检测`,
        };
    }
    return {
        dimension: "scenario_coverage",
        passed: false,
        detail: `变异测试未通过（随机抽样 ${keyLines.length} 行${coverageNote}）— 精确断言率 ${(precisionRatio * 100).toFixed(0)}%（阈值 50%），${mutationsApplied} 次变异中 ${mutationsUndetected} 次不可检测。测试可能存在"自己证明自己"问题`,
    };
}
//# sourceMappingURL=test_quality.js.map