import { debug } from "../core/logger.js";
/**
 * 失败分类模块。
 * @description 对任务执行过程中的失败进行智能分类，判断失败类型（确定性/可修复/范围不足）、
 *              是否可以自动修复、是否需要升级到人工处理。内置复发检测和修复循环上限机制，
 *              防止无限重试。同时检测上游阶段（需求/设计/权限/DDL/契约）问题，禁止自动修复。
 */
/**
 * 不可自动修复的上游阶段关键词映射。
 * @description 当错误输出中包含这些关键词时，判定根因在上游阶段，强制升级到人工处理。
 */
const UPSTREAM_PHASE_PATTERNS = [
    { pattern: /requirement|需求|spec/i, phase: "requirement" },
    { pattern: /design|架构|设计|DDL|表结构|接口定义/i, phase: "design" },
    { pattern: /permission|权限|角色|授权/i, phase: "permission" },
    { pattern: /migration|数据库变更|schema/i, phase: "ddl" },
    { pattern: /api.*contract|接口契约|swagger/i, phase: "api_contract" },
];
/**
 * 失败分类器。
 * @description 通过分析错误输出内容，结合重试计数和复发历史，给出失败类型和处理建议。
 */
export class FailureClassifier {
    /** 上一次错误信息（用于判断是否为相同错误） */
    lastError = "";
    /** 历史错误列表（用于复发检测） */
    errorHistory = [];
    /** 最大重试次数 */
    maxRetries;
    /** 最大自动修复次数（防无限循环） */
    maxAutoRepair;
    /**
     * 创建失败分类器实例。
     * @param maxRetries - 最大重试次数，默认 3
     * @param maxAutoRepair - 最大自动修复循环次数，默认 3
     */
    constructor(maxRetries = 3, maxAutoRepair = 3) {
        this.maxRetries = maxRetries;
        this.maxAutoRepair = maxAutoRepair;
    }
    /**
     * 分类错误输出，返回失败分类结果。
     * @description 分类优先级：上游阶段检测 > 修复循环上限 > 复发检测（>=4次） >
     *              相同错误检测 > 范围不足检测 > 可修复错误 > 默认可重试。
     * @param errorOutput - 错误输出文本
     * @param retryCount - 当前重试次数
     * @param repairLoopCount - 当前修复循环次数
     * @returns 失败分类结果，包含失败类型、处理动作、是否可自动修复等信息
     */
    classify(errorOutput, retryCount = 0, repairLoopCount = 0) {
        debug("FailureClassifier", "开始分类错误输出", { retryCount, repairLoopCount });
        const isSameError = errorOutput.trim() === this.lastError.trim();
        this.lastError = errorOutput.trim();
        this.errorHistory.push(errorOutput.trim());
        const retryRemaining = Math.max(0, this.maxRetries - retryCount);
        const recurrenceCount = this.countRecurrence(errorOutput);
        // 检测根因是否在上游阶段
        const upstreamPhase = detectUpstreamPhase(errorOutput);
        // 上游阶段问题不可自动修复，强制升级到人工处理
        if (upstreamPhase) {
            debug("FailureClassifier", "根因在上游阶段，强制升级", { phase: upstreamPhase });
            return {
                failure_type: "deterministic",
                is_same_error: isSameError,
                retry_remaining: retryRemaining,
                action: "escalate",
                phase_origin: upstreamPhase,
                auto_repairable: false,
                escalation_reason: `根因在 ${upstreamPhase} 阶段，禁止自动修复`,
                recurrence_count: recurrenceCount,
            };
        }
        // 修复循环已达上限，停止自动修复并升级
        if (repairLoopCount >= this.maxAutoRepair) {
            debug("FailureClassifier", "修复循环已达上限，停止自动修复", { repairLoopCount, maxAutoRepair: this.maxAutoRepair });
            return {
                failure_type: "deterministic",
                is_same_error: isSameError,
                retry_remaining: retryRemaining,
                action: "escalate",
                phase_origin: "implementation",
                auto_repairable: false,
                escalation_reason: `自动修复循环已达 ${repairLoopCount}/${this.maxAutoRepair} 上限`,
                recurrence_count: recurrenceCount,
            };
        }
        // 复发检测：同一错误出现 4 次及以上，判定为复发缺陷
        if (recurrenceCount >= 4) {
            debug("FailureClassifier", "同一错误复发次数达到上限", { recurrenceCount });
            return {
                failure_type: "deterministic",
                is_same_error: true,
                retry_remaining: retryRemaining,
                action: "escalate",
                phase_origin: "implementation",
                auto_repairable: false,
                escalation_reason: `同一错误复发 ${recurrenceCount} 次，记录为复发缺陷`,
                recurrence_count: recurrenceCount,
            };
        }
        if (isSameError) {
            debug("FailureClassifier", "检测到相同错误，升级处理");
            return {
                failure_type: "deterministic",
                is_same_error: true,
                retry_remaining: retryRemaining,
                action: "escalate",
                phase_origin: "implementation",
                auto_repairable: recurrenceCount < 2,
                recurrence_count: recurrenceCount,
            };
        }
        // 文件/模块找不到 → 范围不足，需要扩大作用域
        if (/cannot find|not found|no such file|import.*not resolved/i.test(errorOutput)) {
            debug("FailureClassifier", "文件/模块未找到，判定为范围不足");
            return {
                failure_type: "scope_insufficient",
                is_same_error: false,
                retry_remaining: retryRemaining,
                action: "expand_scope",
                phase_origin: "implementation",
                auto_repairable: true,
                recurrence_count: recurrenceCount,
            };
        }
        // 编译/语法错误 → 可自动修复
        if (/error TS|compilation error|syntax error/i.test(errorOutput)) {
            debug("FailureClassifier", "检测到编译/语法错误，判定为可自动修复");
            return {
                failure_type: "fixable",
                is_same_error: false,
                retry_remaining: retryRemaining,
                action: "retry",
                phase_origin: "implementation",
                auto_repairable: true,
                recurrence_count: recurrenceCount,
            };
        }
        // 默认情况：视为可修复的可重试错误
        debug("FailureClassifier", "默认判定为可修复可重试错误");
        return {
            failure_type: "fixable",
            is_same_error: false,
            retry_remaining: retryRemaining,
            action: "retry",
            phase_origin: "implementation",
            auto_repairable: true,
            recurrence_count: recurrenceCount,
        };
    }
    /**
     * 统计指定错误输出在历史中的出现次数。
     * @description 用于复发检测，统计同一错误信息的累计出现频次。
     * @param errorOutput - 待统计的错误输出文本
     * @returns 该错误在历史记录中的出现次数
     */
    countRecurrence(errorOutput) {
        const normalized = errorOutput.trim();
        return this.errorHistory.filter((e) => e === normalized).length;
    }
}
/**
 * 检测错误输出是否涉及不可自动修复的上游阶段。
 * @description 遍历上游阶段关键词模式，匹配成功则返回对应的阶段名称。
 * @param errorOutput - 错误输出文本
 * @returns 匹配到的上游阶段名称，若未匹配到则返回 undefined
 */
function detectUpstreamPhase(errorOutput) {
    for (const { pattern, phase } of UPSTREAM_PHASE_PATTERNS) {
        if (pattern.test(errorOutput))
            return phase;
    }
    return undefined;
}
//# sourceMappingURL=failure_classifier.js.map