/**
 * 遗漏扫描引擎 — 聚合扫描 + 对抗性 AI prompt 生成。
 *
 * 职责：
 * 1. 聚合三种确定性检测（空洞章节、占位符、空表格）+ 现有缺失检测
 * 2. 生成 OmissionScanResult（passed / findings / summary）
 * 3. 生成对抗性 AI prompt，用于 sf_verify 的二次 AI 审计
 *
 * 设计决策：
 * - 确定性扫描做第一道（快速、无 IO），对抗性 prompt 做第二道（AI 深度审计）
 * - 对抗性 prompt 基于 findings 生成，聚焦已确认遗漏 + 潜在遗漏
 * - 扫描配置可外部注入，默认值适合大多数场景
 */
import { findHollowSections, findPlaceholders, findEmptyTables, findMissingSections, findMissingTables, getArtifactSchema, } from "./artifact_schema_registry.js";
/** 默认扫描配置 */
const DEFAULT_CONFIG = {
    hollow_threshold_chars: 50,
    placeholder_patterns: [],
    generate_adversarial_prompt: false,
    adversarial_max_findings: 5,
};
// ── 核心扫描函数 ──
/**
 * 聚合扫描 — 对产物内容执行全面的遗漏检测。
 *
 * 检测维度（按顺序）：
 * 1. 缺失章节（findMissingSections）
 * 2. 缺失表格（findMissingTables）
 * 3. 空洞章节（findHollowSections）
 * 4. 占位符（findPlaceholders）
 * 5. 空表格（findEmptyTables）
 *
 * @param kind 产物类型（ArtifactKind）
 * @param content 产物 markdown 内容
 * @param configOverrides 可选配置覆盖
 * @returns 扫描结果
 */
export function scanArtifactForOmissions(kind, content, configOverrides) {
    const config = { ...DEFAULT_CONFIG, ...configOverrides };
    const schema = getArtifactSchema(kind);
    const findings = [];
    // 维度 1: 缺失章节（基于 registry schema 或空 schema 兜底）
    if (schema) {
        const missingSections = findMissingSections(content, schema);
        for (const section of missingSections) {
            findings.push({
                type: "missing_section",
                severity: "hard_fail",
                section_name: section,
                message: `缺少必填章节: ${section}`,
                evidence: `章节 "${section}" 在文档中未找到匹配标题`,
            });
        }
        // 维度 2: 缺失表格
        const missingTables = findMissingTables(content, schema);
        for (const table of missingTables) {
            findings.push({
                type: "missing_table",
                severity: "hard_fail",
                section_name: "",
                message: `缺少必填表格: ${table}`,
                evidence: `表格关键词 "${table}" 在文档中未找到匹配`,
            });
        }
        // 维度 3: 空洞章节
        const hollowSections = findHollowSections(content, schema, config.hollow_threshold_chars);
        for (const hollow of hollowSections) {
            findings.push({
                type: "hollow_section",
                severity: "hard_fail",
                section_name: hollow.section_name,
                line_number: hollow.line_number,
                message: `章节 "${hollow.section_name}" 正文不足 ${config.hollow_threshold_chars} 字符（实际 ${hollow.body_chars} 字符）`,
                evidence: `第 ${hollow.line_number} 行，正文长度=${hollow.body_chars}`,
            });
        }
        // 维度 5: 空表格
        const emptyTables = findEmptyTables(content, schema);
        for (const empty of emptyTables) {
            findings.push({
                type: "empty_table",
                severity: empty.is_required ? "hard_fail" : "warning",
                section_name: "",
                line_number: empty.line_number,
                message: `${empty.is_required ? "必填" : "非必填"}表格 "${empty.table_keyword}" 有标题但无数据行`,
                evidence: `第 ${empty.line_number} 行，表格 "${empty.table_keyword}" 为空`,
            });
        }
    }
    // 维度 4: 占位符（不需要 schema）
    const extraPatterns = config.placeholder_patterns.map((p) => new RegExp(p));
    const placeholders = findPlaceholders(content, extraPatterns);
    for (const ph of placeholders) {
        findings.push({
            type: "placeholder",
            severity: "warning",
            section_name: "",
            line_number: ph.line_number,
            message: `发现占位符文本: ${ph.placeholder}`,
            evidence: ph.context,
        });
    }
    // 汇总
    const hardFailCount = findings.filter((f) => f.severity === "hard_fail").length;
    const warningCount = findings.filter((f) => f.severity === "warning").length;
    const passed = hardFailCount === 0;
    const summary = passed
        ? `✅ 遗漏扫描通过（${warningCount} 个警告）`
        : `❌ 遗漏扫描未通过（${hardFailCount} 个阻塞项，${warningCount} 个警告）`;
    const result = {
        passed,
        findings,
        summary,
    };
    // 对抗性 prompt 生成（可选）
    if (config.generate_adversarial_prompt) {
        result.adversarial_prompt = generateAdversarialPrompt(findings, schema, content, config.adversarial_max_findings);
    }
    return result;
}
// ── 对抗性 Prompt 生成 ──
/**
 * 生成对抗性 AI prompt — 基于确定性扫描结果，引导 AI 进行深度审计。
 *
 * 框架设计：
 * - 已确认遗漏 → 要求 AI 验证并量化影响
 * - 潜在遗漏 → 要求 AI 基于模板/行业经验推断可能遗漏
 * - 聚焦策略 → 限制 max_findings 避免信息过载
 *
 * @param findings 确定性扫描的发现项
 * @param schema 产物 Schema（可能为 null）
 * @param content 产物内容
 * @param maxFindings 最大发现数
 * @returns 对抗性 prompt 文本
 */
export function generateAdversarialPrompt(findings, schema, content, maxFindings = 5) {
    const kind = schema?.kind ?? "未知";
    const lines = content.split("\n");
    // 已确认遗漏列表
    const confirmedFindings = findings
        .slice(0, maxFindings)
        .map((f, i) => `${i + 1}. [${f.severity === "hard_fail" ? "阻塞" : "警告"}] ${f.message}` +
        (f.line_number ? `（第 ${f.line_number} 行）` : "") +
        ` — 证据: ${f.evidence}`)
        .join("\n");
    // Schema 约束摘要
    const schemaSummary = schema
        ? [
            `必填章节: ${schema.required_sections.join("、")}`,
            schema.required_tables.length > 0
                ? `必填表格: ${schema.required_tables.join("、")}`
                : null,
            schema.required_fields
                ? Object.entries(schema.required_fields)
                    .map(([t, fs]) => `  ${t} → ${fs.join("、")}`)
                    .join("\n")
                : null,
        ]
            .filter(Boolean)
            .join("\n")
        : "无 Schema 定义";
    // 内容统计
    const contentStats = `总行数: ${lines.length}，总字符: ${content.length}`;
    return [
        `你是一个严格的产物审计员。以下是产物「${kind}」的结构约束和实际内容统计。`,
        "",
        "## 已确认的遗漏（确定性扫描发现）",
        confirmedFindings || "（无确定性发现）",
        "",
        "## Schema 结构约束",
        schemaSummary,
        "",
        "## 内容统计",
        contentStats,
        "",
        "## 你的任务",
        "假设这份产物一定还有未发现的遗漏。基于 Schema 定义，逐项检查每个章节的内容质量：",
        "1. 章节内容是否与 Schema 要求匹配？是否有空洞章节（标题存在但正文不足）？",
        "2. 表格数据是否完整（有无空单元格、缺失行）？",
        "3. 附属产物（Mermaid 图、SQL DDL、OpenAPI schema）是否真实存在且非空？",
        "4. 跨章节引用是否一致（如交互流转引用的页面在布局树中是否存在）？",
        `5. 是否有隐藏的占位符（非标准表达但语义等同于"待补充"的文本）？`,
        "",
        "对每个发现附上：行号（如果可定位）+ 证据片段 + 缺失描述。",
        `最多报告 ${maxFindings} 项最严重的遗漏。`,
        "",
        "格式要求：每项一行，格式为",
        "  [遗漏类型] 行号:行号 — 描述 — 证据:前80字符",
    ].join("\n");
}
//# sourceMappingURL=omission_scanner.js.map