import { scoreConfidence } from "./confidence_scorer.js";
import { KnowledgeWriter } from "../../knowledge/writer.js";
import { debugLog } from "../core/logger.js";
export { FailureClassifier } from "./failure_classifier.js";
/**
 * 模式漂移检测 — 对比代码实现与知识库模式规则，检测偏离度。
 * 使用静态规则匹配扫描代码库，不依赖 AI。
 * @param patterns - 知识库中的模式条目
 * @param codeFiles - 代码文件内容映射（文件路径 → 文件内容）
 * @returns 漂移检测结果
 */
export function detectPatternDrift(patterns, codeFiles) {
    debugLog("漂移检测: 开始检测模式漂移");
    const driftDetails = [];
    for (const pattern of patterns) {
        if (!pattern.body)
            continue;
        // 从模式正文中提取"禁止"规则
        const prohibitRules = extractProhibitRules(pattern.body);
        for (const rule of prohibitRules) {
            let violated = false;
            let violationFile = "";
            for (const [filePath, content] of Object.entries(codeFiles)) {
                // 跳过测试文件和非源码文件
                if (/\.test\.|\.spec\.|\.d\.ts/.test(filePath))
                    continue;
                if (/node_modules|\.soloforge|dist/.test(filePath))
                    continue;
                if (rule.pattern.test(content)) {
                    violated = true;
                    violationFile = filePath;
                    break;
                }
            }
            if (violated) {
                driftDetails.push({
                    pattern_name: pattern.name,
                    expected_rule: rule.description,
                    detected_violation: violationFile,
                    severity: rule.severity,
                });
            }
        }
    }
    const totalPatterns = patterns.filter((p) => p.body).length;
    const driftedPatterns = new Set(driftDetails.map((d) => d.pattern_name)).size;
    const driftRatio = totalPatterns > 0 ? driftedPatterns / totalPatterns : 0;
    const syncRequired = driftRatio >= 0.3;
    // 根因分析: 防止"循环修正"死锁
    let rootCause;
    if (syncRequired && driftDetails.length > 0) {
        rootCause = analyzeDriftRootCause(driftDetails, codeFiles);
        debugLog(`漂移检测: 偏离率 ${(driftRatio * 100).toFixed(0)}%，触发同步任务，正在分析根因`);
    }
    let recommendation;
    if (syncRequired) {
        const rca = rootCause;
        if (rca?.conclusion === "business_evolution") {
            recommendation = `⚠ 偏离率 ${(driftRatio * 100).toFixed(0)}% 超过阈值 30%。根因: 业务进化（${rca.evidence}）。允许更新知识库规则`;
        }
        else if (rca?.conclusion === "code_degradation") {
            recommendation = `⚠ 偏离率 ${(driftRatio * 100).toFixed(0)}% 超过阈值 30%。根因: 代码退化（${rca.evidence}）。禁止更新知识库，应重构代码以符合规范`;
        }
        else {
            recommendation = `⚠ 偏离率 ${(driftRatio * 100).toFixed(0)}% 超过阈值 30%。根因不确定。必须人工判定后再决定更新知识库还是重构代码`;
        }
        debugLog(`漂移检测: ${recommendation}`);
    }
    else if (driftRatio > 0) {
        recommendation = `偏离率 ${(driftRatio * 100).toFixed(0)}%，在可接受范围内。建议关注 ${driftDetails.filter((d) => d.severity === "critical").length} 个严重偏离`;
    }
    else {
        recommendation = "代码实现与知识库规范一致，无漂移";
    }
    debugLog(`漂移检测: 完成，检测 ${totalPatterns} 个模式，${driftedPatterns} 个偏离`);
    return {
        total_patterns: totalPatterns,
        drifted_patterns: driftedPatterns,
        drift_ratio: driftRatio,
        sync_required: syncRequired,
        drift_details: driftDetails,
        recommendation,
        root_cause_analysis: rootCause,
    };
}
/** 从模式正文中提取"禁止"类规则，转为可检测的正则模式 */
function extractProhibitRules(body) {
    const rules = [];
    if (!body.includes("## 决策规则"))
        return rules;
    const lines = body.split("\n");
    let inSection = false;
    for (const line of lines) {
        if (line.startsWith("## 决策规则")) {
            inSection = true;
            continue;
        }
        if (inSection && line.startsWith("## "))
            break;
        if (inSection) {
            // 提取"禁止"规则
            const prohibitMatch = line.match(/-\s*禁止(.+)/);
            if (prohibitMatch) {
                const description = `禁止${prohibitMatch[1].trim()}`;
                // 从禁止规则生成检测正则
                const pattern = buildProhibitPattern(prohibitMatch[1]);
                if (pattern) {
                    rules.push({ description, pattern, severity: "warning" });
                }
            }
        }
    }
    return rules;
}
/** 从禁止规则描述生成检测正则 */
function buildProhibitPattern(ruleText) {
    // 常见禁止模式的正则映射
    if (/console\.log/.test(ruleText))
        return /console\.log\s*\(/;
    if (/eval/.test(ruleText))
        return /\beval\s*\(/;
    if (/innerHTML/.test(ruleText))
        return /\.innerHTML\s*=/;
    if (/SQL.*拼接|字符串拼接/.test(ruleText))
        return /(SELECT|INSERT|UPDATE|DELETE).*[+${]/;
    if (/同步导出/.test(ruleText))
        return /export\s*\(.*res\.write/;
    if (/Controller.*导出|Controller.*业务/.test(ruleText))
        return /Controller/;
    if (/硬编码/.test(ruleText))
        return /(?:password|secret|api[_-]?key)\s*[:=]\s*["'][^"']+["']/i;
    return null;
}
/**
 * 漂移根因分析 — 判断偏离是"代码退化"还是"业务进化"，防止循环修正死锁。
 * 启发式规则:
 * - 安全/数据完整性相关规则违反 → 倾向代码退化
 * - 多文件同时违反同一规则 → 可能规范过时（业务进化）
 * - 其余 → 需人工审核
 */
function analyzeDriftRootCause(details, _codeFiles) {
    const totalViolations = details.length;
    const uniqueFiles = new Set(details.map((d) => d.detected_violation)).size;
    const securityRelated = details.filter((d) => /eval|innerHTML|password|secret|SQL|注入|加密|脱敏|权限/i.test(d.expected_rule)).length;
    if (securityRelated > totalViolations * 0.3) {
        return {
            conclusion: "code_degradation",
            evidence: `${securityRelated}/${totalViolations} 项偏离涉及安全/数据完整性规则，不应通过更新规范来"合法化"`,
            allow_pattern_update: false,
        };
    }
    if (uniqueFiles >= 3 && totalViolations >= 3) {
        return {
            conclusion: "business_evolution",
            evidence: `${totalViolations} 项偏离分布在 ${uniqueFiles} 个文件中，可能反映合理的技术演进`,
            allow_pattern_update: true,
        };
    }
    return {
        conclusion: "unknown",
        evidence: `偏离分布在 ${uniqueFiles} 个文件中，无法自动判定根因，需人工审核`,
        allow_pattern_update: false,
    };
}
// 跟踪重复模式学习以提升置信度（限制大小防止内存泄漏）
const MAX_PATTERN_TRACK_SIZE = 1000;
const patternLearnCount = new Map();
/**
 * 从任务执行结果中提取知识并写入知识库。
 * @param input - 进化输入，包含任务上下文、执行结果和验证输出
 * @param projectPath - 项目路径，用于知识文件写入
 * @returns 学习结果，包含是否采纳、置信度、暂存路径等
 */
export async function evolve(input, projectPath) {
    const { taskContext, result, failureType, retryCount } = input;
    debugLog(`演进器: 开始处理任务 ${taskContext.task_id}，结果: ${result}`);
    // 跳过 passthrough 任务的学习
    if (taskContext.classification?.strategy === "skip_soloForge") {
        debugLog(`演进器: 任务 ${taskContext.task_id} 为 passthrough 任务，跳过学习`);
        return { task_id: taskContext.task_id, learned: false, confidence: 0, status: "skipped" };
    }
    // 提取知识候选
    const candidate = extractKnowledge(input);
    if (!candidate) {
        debugLog(`演进器: 任务 ${taskContext.task_id} 无法提取知识候选，跳过`);
        return { task_id: taskContext.task_id, learned: false, confidence: 0, status: "skipped" };
    }
    // 评估置信度
    const isDegraded = taskContext.expansion?.degraded ?? false;
    let confidence = scoreConfidence({
        result,
        retryCount: retryCount ?? 0,
        failureType,
        matchedPatternsCount: taskContext.expansion?.matched_patterns?.length ?? 0,
        hasClearRootCause: failureType !== undefined,
        isDegraded,
    });
    // 持续同模式置信度提升: 每 3 次同一类型+范围的组合加 0.1，上限 1.0
    const patternKey = `${candidate.type}:${candidate.scope.join(",")}`;
    const count = (patternLearnCount.get(patternKey) ?? 0) + 1;
    patternLearnCount.set(patternKey, count);
    // 防止内存泄漏：超过上限时清理计数最低的条目（近似 LRU）
    if (patternLearnCount.size > MAX_PATTERN_TRACK_SIZE) {
        let minKey = null;
        let minCount = Infinity;
        for (const [k, v] of patternLearnCount) {
            if (v < minCount) {
                minCount = v;
                minKey = k;
            }
        }
        if (minKey)
            patternLearnCount.delete(minKey);
    }
    if (count > 0 && count % 3 === 0) {
        confidence = Math.min(confidence + 0.1, 1.0);
    }
    // 置信度决策: < 0.3 跳过，>= 0.8 直接采纳，其余暂存等待审核
    if (confidence < 0.3) {
        debugLog(`演进器: 任务 ${taskContext.task_id} 置信度 ${confidence.toFixed(2)} 不足，跳过`);
        return { task_id: taskContext.task_id, learned: false, new_knowledge: candidate, confidence, status: "skipped" };
    }
    if (confidence >= 0.8) {
        debugLog(`演进器: 任务 ${taskContext.task_id} 置信度 ${confidence.toFixed(2)}，直接采纳知识 [${candidate.type}]`);
        return { task_id: taskContext.task_id, learned: true, new_knowledge: candidate, confidence, status: "accepted" };
    }
    // 暂存等待审核 — 写入文件
    debugLog(`演进器: 任务 ${taskContext.task_id} 置信度 ${confidence.toFixed(2)}，暂存等待人工审核`);
    const writer = new KnowledgeWriter(projectPath);
    const entry = {
        id: `learned-${Date.now()}`,
        file_path: "",
        name: candidate.content.slice(0, 50),
        type: mapToKnowledgeType(candidate.type),
        when: taskContext.intent,
        scope: candidate.scope,
        products: candidate.products,
        created_at: new Date().toISOString().split("T")[0],
        updated_at: new Date().toISOString().split("T")[0],
        usage_count: 0,
        confidence,
        status: "staged",
    };
    const stagedPath = await writer.writeToStaged(entry, candidate.content);
    return { task_id: taskContext.task_id, learned: true, new_knowledge: candidate, confidence, status: "staged", staged_path: stagedPath };
}
/**
 * 将进化学习类型映射到知识库条目类型。
 * rule_upgrade 和 prompt_optimization 归类为 pattern，acceptance_supplement 归类为 acceptance_template。
 * @param t - 进化学习类型
 * @returns 知识库条目类型
 */
function mapToKnowledgeType(t) {
    if (t === "rule_upgrade" || t === "prompt_optimization")
        return "pattern";
    if (t === "acceptance_supplement")
        return "acceptance_template";
    return t;
}
/**
 * 从任务执行结果中提取知识候选。
 * 失败时按失败类型生成不同知识: 验收遗漏 / 确定性规则升级 / 范围模式 / prompt 优化。
 * 成功时从匹配的知识模式中提取重复模式。
 * @param input - 进化输入
 * @returns 知识候选对象，无法提取时返回 undefined
 */
function extractKnowledge(input) {
    const { taskContext, result, verifyOutput, failureType } = input;
    const scope = taskContext.classification?.affected_repos ?? ["shared"];
    const products = [taskContext.product_profile];
    if (result === "failure") {
        if (!failureType)
            return undefined;
        // 优先检查验收遗漏
        if (verifyOutput?.acceptance_results) {
            const failedChecks = Object.entries(verifyOutput.acceptance_results)
                .filter(([, passed]) => !passed)
                .map(([id]) => id);
            if (failedChecks.length > 0) {
                return {
                    type: "acceptance_supplement",
                    content: `## 决策规则\n- ${taskContext.intent} 时必须确保 ${failedChecks.join("、")} 通过\n\n## 验收项\n${failedChecks.map((id, i) => `- [AC-${String(i + 1).padStart(2, "0")}] ${id} 检查通过`).join("\n")}`,
                    scope,
                    products,
                };
            }
        }
        const errorMsg = taskContext.execution?.failure_history[0]?.message || "unknown";
        switch (failureType) {
            case "deterministic": {
                const correctAction = inferCorrectAction(taskContext.intent, errorMsg);
                return {
                    type: "rule_upgrade",
                    content: `## 决策规则\n- ${taskContext.intent} 时必须 ${correctAction}\n\n## 验收项\n- [AC-01] ${correctAction}`,
                    scope,
                    products,
                };
            }
            case "scope_insufficient": {
                const missingFiles = inferMissingScope(taskContext.intent, errorMsg);
                return {
                    type: "pattern",
                    content: `## 决策规则\n- ${taskContext.intent} 需要同时修改 ${missingFiles}\n\n## 验收项\n- [AC-01] 变更文件包含 ${missingFiles}`,
                    scope,
                    products,
                };
            }
            case "fixable": {
                const errorPattern = inferErrorPattern(errorMsg);
                return {
                    type: "prompt_optimization",
                    content: `## 决策规则\n- ${taskContext.intent} 时注意 ${errorPattern}\n\n## 验收项\n- [AC-01] 编译/测试无 ${errorPattern} 错误`,
                    scope,
                    products,
                };
            }
            default:
                return undefined;
        }
    }
    // 成功: 从匹配的知识中提取模式
    if (taskContext.expansion?.matched_patterns?.length) {
        const usedPatterns = taskContext.expansion.matched_patterns.join("、");
        return {
            type: "pattern",
            content: `## 决策规则\n- ${taskContext.intent} 遵循 ${usedPatterns}\n\n## 验收项\n- [AC-01] 符合 ${usedPatterns} 模式`,
            scope,
            products,
        };
    }
    return undefined;
}
/**
 * 根据错误消息推断正确的操作建议。
 * @param intent - 任务意图（未使用，预留参数）
 * @param errorMsg - 错误消息
 * @returns 正确操作描述
 */
function inferCorrectAction(_intent, errorMsg) {
    if (errorMsg.includes("编译") || errorMsg.includes("compile"))
        return "确保编译通过";
    if (errorMsg.includes("类型") || errorMsg.includes("type"))
        return "确保类型正确";
    if (errorMsg.includes("权限") || errorMsg.includes("permission"))
        return "检查权限配置";
    return "避免相同错误重试";
}
/**
 * 根据错误消息推断缺失的修改范围。
 * @param intent - 任务意图（未使用，预留参数）
 * @param errorMsg - 错误消息
 * @returns 缺失范围描述
 */
function inferMissingScope(_intent, errorMsg) {
    if (errorMsg.includes("import") || errorMsg.includes("引用"))
        return "被引用的相关模块";
    if (errorMsg.includes("config") || errorMsg.includes("配置"))
        return "相关配置文件";
    return "关联文件";
}
/**
 * 根据错误消息推断错误类型关键词。
 * @param errorMsg - 错误消息
 * @returns 错误类型关键词，如 "类型" / "引用" / "语法" / "空值"
 */
function inferErrorPattern(errorMsg) {
    if (errorMsg.includes("TypeError") || errorMsg.includes("类型错误"))
        return "类型";
    if (errorMsg.includes("ReferenceError") || errorMsg.includes("引用"))
        return "引用";
    if (errorMsg.includes("SyntaxError") || errorMsg.includes("语法"))
        return "语法";
    if (errorMsg.includes("null") || errorMsg.includes("undefined"))
        return "空值";
    return "常见";
}
//# sourceMappingURL=evolver.js.map