/**
 * Plan / Proposal First Gate — 问题五十五核心机制。
 *
 * 任何写入、编码、构建、Docker、迁移、发布、外部副作用或交付动作前，
 * AI 必须先给出与任务风险匹配的计划或方案。
 *
 * 核心原则: 先说明计划，再执行动作。
 */
import { isPathInScope } from "../core/path_scope_utils.js";
// ── 任务类型到最低计划等级的映射 ──
const MIN_PLAN_LEVEL = {
    simple_answer: "none_with_reason",
    read_only_analysis: "brief_plan",
    code_change: "execution_plan",
    file_edit: "execution_plan",
    test_or_review: "execution_plan",
    architecture_design: "option_proposal",
    existing_system_development: "execution_plan",
    local_acceptance: "execution_plan",
    batch_documentation_update: "execution_plan",
    migration: "human_confirmation_required",
    delete_or_overwrite: "human_confirmation_required",
    high_risk_operation: "human_confirmation_required",
};
/** 需要用户确认的任务类型 */
const NEEDS_CONFIRMATION_TYPES = new Set([
    "migration",
    "delete_or_overwrite",
    "high_risk_operation",
]);
/** plan_level 排序权重 */
const LEVEL_WEIGHT = {
    none_with_reason: 0,
    brief_plan: 1,
    execution_plan: 2,
    option_proposal: 3,
    human_confirmation_required: 4,
};
/** 风险升级触发条件 — 同时命中多个 task_type 时取最高 */
const RISK_UPGRADE_TRIGGERS = [
    { types: ["code_change", "delete_or_overwrite"], upgrade_to: "human_confirmation_required" },
    { types: ["code_change", "migration"], upgrade_to: "human_confirmation_required" },
    { types: ["file_edit", "delete_or_overwrite"], upgrade_to: "human_confirmation_required" },
    { types: ["code_change", "high_risk_operation"], upgrade_to: "human_confirmation_required" },
];
/** 高风险关键词 — 检测用户意图中的高风险信号 */
const HIGH_RISK_KEYWORDS = [
    "删除", "drop", "truncate", "rm -rf", "DELETE FROM",
    "覆盖", "force push", "--force",
    "数据库", "database", "schema",
    "权限", "permission", "auth",
    "技术栈", "framework", "migration",
    "发布", "deploy", "publish", "release",
    "Docker", "docker", "端口", "port",
    "安装", "install", "依赖", "dependency",
    "用户数据", "user data",
];
/** none_with_reason 禁止用于的任务类型 */
const NONE_WITH_REASON_FORBIDDEN = new Set([
    "code_change", "file_edit", "test_or_review",
    "local_acceptance", "batch_documentation_update",
    "migration", "delete_or_overwrite", "high_risk_operation",
]);
// ── 核心函数 ──
/**
 * 评估计划前置门 — 检查任务是否有足够等级的计划。
 */
export function evaluatePlanProposalGate(input) {
    const violations = [];
    const blockedActions = [];
    // 确定最低要求等级
    let requiredLevel = MIN_PLAN_LEVEL[input.task_type] ?? "execution_plan";
    // 风险升级: 当意图同时命中多个高风险类型时取最高等级
    for (const trigger of RISK_UPGRADE_TRIGGERS) {
        const allTypesMatch = trigger.types.every((t) => {
            if (t === input.task_type)
                return true;
            return inferPlanGateTaskType(input.user_intent) === t;
        });
        if (allTypesMatch) {
            const currentWeight = LEVEL_WEIGHT[requiredLevel];
            const upgradeWeight = LEVEL_WEIGHT[trigger.upgrade_to];
            if (upgradeWeight > currentWeight) {
                requiredLevel = trigger.upgrade_to;
            }
        }
    }
    // 检测意图中的高风险关键词
    const intentHasHighRisk = HIGH_RISK_KEYWORDS.some((kw) => input.user_intent.toLowerCase().includes(kw.toLowerCase()));
    if (intentHasHighRisk && LEVEL_WEIGHT[requiredLevel] < LEVEL_WEIGHT["execution_plan"]) {
        requiredLevel = "execution_plan";
    }
    // scope 扩大或风险升高 → 升级
    if (input.scope_expanded || input.risk_elevated) {
        if (LEVEL_WEIGHT[requiredLevel] < LEVEL_WEIGHT["human_confirmation_required"]) {
            requiredLevel = "human_confirmation_required";
        }
    }
    const currentLevel = input.plan_level ?? "none_with_reason";
    // 检查 1: none_with_reason 适用范围
    if (currentLevel === "none_with_reason" && NONE_WITH_REASON_FORBIDDEN.has(input.task_type)) {
        violations.push({
            rule: "none_with_reason_forbidden_for_write",
            severity: "hard_fail",
            reason_zh: `任务类型 ${input.task_type} 不得使用 none_with_reason，写入/高风险任务必须有计划`,
            diagnostic_code: "SF-PLAN-5010",
        });
        blockedActions.push("write_file", "code_change", "build", "docker", "migrate", "publish", "deliver");
    }
    // 检查 2: 计划等级不足
    if (LEVEL_WEIGHT[currentLevel] < LEVEL_WEIGHT[requiredLevel]) {
        violations.push({
            rule: "plan_level_insufficient",
            severity: "hard_fail",
            reason_zh: `计划等级 ${currentLevel} 不足，任务类型 ${input.task_type} 至少需要 ${requiredLevel}`,
            diagnostic_code: "SF-PLAN-5002",
        });
        blockedActions.push("write_file", "code_change", "build", "docker", "migrate", "publish", "deliver");
    }
    // 检查 3: 需要用户确认
    if (NEEDS_CONFIRMATION_TYPES.has(input.task_type) && !input.user_confirmation_ref) {
        violations.push({
            rule: "confirmation_required",
            severity: "hard_fail",
            reason_zh: `任务类型 ${input.task_type} 需要用户确认，但缺少 user_confirmation_ref`,
            diagnostic_code: "SF-PLAN-5003",
        });
        blockedActions.push("write_file", "code_change", "build", "docker", "migrate", "publish", "deliver");
    }
    // 检查 4: 高风险意图无确认
    if (intentHasHighRisk && !input.user_confirmation_ref &&
        LEVEL_WEIGHT[requiredLevel] >= LEVEL_WEIGHT["human_confirmation_required"]) {
        violations.push({
            rule: "high_risk_no_confirmation",
            severity: "hard_fail",
            reason_zh: "意图包含高风险操作但缺少用户确认",
            diagnostic_code: "SF-PLAN-5003",
        });
        blockedActions.push("write_file", "code_change", "build", "docker", "migrate", "publish", "deliver");
    }
    // 检查 5: 缺少计划本身
    if (!input.plan_summary_zh && currentLevel !== "none_with_reason") {
        violations.push({
            rule: "no_plan",
            severity: "hard_fail",
            reason_zh: "执行前缺少计划",
            diagnostic_code: "SF-PLAN-5001",
        });
        blockedActions.push("write_file", "code_change", "build", "docker", "migrate", "publish", "deliver");
    }
    // 检查 6: 缺少验证计划（execution_plan 及以上）
    if (LEVEL_WEIGHT[currentLevel] >= LEVEL_WEIGHT["execution_plan"] &&
        (!input.verification_plan || input.verification_plan.length === 0)) {
        violations.push({
            rule: "verification_plan_missing",
            severity: "hard_fail",
            reason_zh: "计划未记录验证方式",
            diagnostic_code: "SF-PLAN-5005",
        });
    }
    // 检查 7: 缺少 evidence refs
    if (!input.evidence_refs || input.evidence_refs.length === 0) {
        violations.push({
            rule: "evidence_refs_missing",
            severity: "hard_fail",
            reason_zh: "计划未进入 evidence refs",
            diagnostic_code: "SF-PLAN-5006",
        });
    }
    // 自动修复循环: 同 scope 内可用原计划
    if (input.is_auto_repair_step && input.auto_repair_origin_plan_id && !input.scope_expanded) {
        // 自动修复每轮仍需要 evidence
        if (!input.evidence_refs || input.evidence_refs.length === 0) {
            violations.push({
                rule: "auto_repair_evidence_missing",
                severity: "hard_fail",
                reason_zh: "自动修复每轮必须有 evidence",
                diagnostic_code: "SF-PLAN-5006",
            });
        }
        // 自动修复在授权 scope 内不阻断
    }
    const hardFails = violations.filter((v) => v.severity === "hard_fail");
    const passed = hardFails.length === 0;
    return {
        passed,
        plan_gate_status: passed ? "passed" : hardFails.some((v) => v.diagnostic_code === "SF-PLAN-5003") ? "manual_required" : "blocked",
        required_level: requiredLevel,
        current_level: currentLevel,
        reason_zh: passed ? "计划前置门通过" : hardFails.map((v) => v.reason_zh).join("; "),
        violations,
        diagnostic_code: hardFails.length > 0 ? hardFails[0].diagnostic_code : undefined,
        evidence_refs: input.evidence_refs ?? [],
        blocked_actions: [...new Set(blockedActions)],
    };
}
/**
 * 在执行动作前检查 plan gate — 返回是否允许执行。
 */
export function requirePlanBeforeAction(gateResult, action) {
    if (!gateResult.passed) {
        return {
            allowed: false,
            reason_zh: `Plan Gate 未通过: ${gateResult.reason_zh}`,
            diagnostic_code: gateResult.diagnostic_code ?? "SF-PLAN-5001",
        };
    }
    if (gateResult.blocked_actions.includes(action)) {
        return {
            allowed: false,
            reason_zh: `动作 ${action} 被 Plan Gate 阻断`,
            diagnostic_code: "SF-PLAN-5004",
        };
    }
    return { allowed: true, reason_zh: "Plan Gate 通过，允许执行" };
}
/**
 * 验证动作是否在已确认计划范围内。
 */
export function validateActionWithinPlan(plannedScope, actionTarget, planLevel) {
    // 简单计划和只读分析不要求 scope 精确匹配
    if (planLevel === "none_with_reason" || planLevel === "brief_plan") {
        return { allowed: true, reason_zh: "低风险任务，不要求 scope 精确匹配" };
    }
    const inScope = plannedScope.some((s) => isPathInScope(actionTarget, s, { caseSensitive: true }));
    if (!inScope) {
        return {
            allowed: false,
            reason_zh: `动作目标 ${actionTarget} 不在已确认计划 scope 内: ${plannedScope.join(", ")}`,
        };
    }
    return { allowed: true, reason_zh: "动作在计划范围内" };
}
/**
 * 创建计划提案证据。
 */
export function createPlanProposalEvidence(input) {
    const evidenceId = `plan-evidence-${input.task_id}-${Date.now()}`;
    return {
        evidence_id: evidenceId,
        task_id: input.task_id,
        plan_id: `plan-${input.task_id}`,
        plan_level: input.plan_level ?? "execution_plan",
        task_type: input.task_type,
        plan_summary_zh: input.plan_summary_zh ?? "",
        proposed_steps: input.proposed_steps ?? [],
        verification_plan: input.verification_plan ?? [],
        risks: input.risks ?? [],
        needs_user_confirmation: input.needs_user_confirmation ?? false,
        user_confirmation_ref: input.user_confirmation_ref,
        evidence_refs: input.evidence_refs ?? [],
        created_at: new Date().toISOString(),
    };
}
/**
 * 推断任务类型 — 从用户意图文本映射到 PlanGateTaskType。
 */
export function inferPlanGateTaskType(intent, route) {
    // 高风险检测优先
    if (/删除|drop\s+table|truncate|rm\s+-rf|覆盖/.test(intent))
        return "delete_or_overwrite";
    if (/迁移|migrate|数据库.*schema|database.*schema/.test(intent))
        return "migration";
    if (/发布|deploy|publish|release|push.*main|push.*master/.test(intent))
        return "high_risk_operation";
    if (/docker|容器|端口.*暴露|port.*expose/.test(intent))
        return "high_risk_operation";
    // 路由推断
    if (route === "code_change")
        return "code_change";
    if (route === "analysis")
        return "read_only_analysis";
    if (route === "operation")
        return "local_acceptance";
    if (route === "review")
        return "test_or_review";
    // 内容推断
    if (/修改.*代码|写.*代码|实现|开发|fix|feat/.test(intent))
        return "code_change";
    if (/修改.*文件|编辑|写.*文件|新增.*文件/.test(intent))
        return "file_edit";
    if (/架构|设计|方案/.test(intent))
        return "architecture_design";
    if (/现有.*系统|已有.*项目/.test(intent))
        return "existing_system_development";
    if (/审查|review|检查/.test(intent))
        return "test_or_review";
    if (/测试|test|验证/.test(intent))
        return "test_or_review";
    if (/文档|doc|batch.*文档/.test(intent))
        return "batch_documentation_update";
    if (/验收|browser|浏览器|docker.*accept/.test(intent))
        return "local_acceptance";
    // 默认
    if (/分析|查看|阅读|read|search|find/.test(intent) || !/修改|写|改|创建|删除|构建|运行/.test(intent)) {
        return "read_only_analysis";
    }
    return "code_change";
}
/**
 * 检查是否为 "只要求 review" 场景 — 如是，不得擅自修复。
 */
export function isReviewOnlyIntent(intent) {
    const lower = intent.toLowerCase();
    const reviewWords = /审查|review|检查|代码审查|code review|只看|只读|不修复|不修改|不修改代码/;
    const fixWords = /修复|fix|修|改|修改.*代码/;
    return reviewWords.test(lower) && !fixWords.test(lower);
}
/**
 * 确认参数 — 计划确认后，旧确认只能覆盖原计划范围。
 */
export function validateConfirmationScope(originalConfirmation, newScope) {
    const newScopeStr = JSON.stringify(newScope.sort());
    const origScopeStr = JSON.stringify(originalConfirmation.scope.sort());
    if (newScopeStr === origScopeStr) {
        return { valid: true, reason_zh: "scope 未变，旧确认有效" };
    }
    const expanded = newScope.filter((s) => !originalConfirmation.scope.includes(s));
    if (expanded.length > 0) {
        return {
            valid: false,
            reason_zh: `scope 扩大: 新增 ${expanded.join(", ")}，需要重新确认`,
        };
    }
    return { valid: true, reason_zh: "scope 未扩大，旧确认有效" };
}
// ── 诊断码注册 ──
export const PLAN_GATE_DIAGNOSTIC_CODES = {
    "SF-PLAN-5001": "执行前缺少计划",
    "SF-PLAN-5002": "计划等级不足",
    "SF-PLAN-5003": "高风险动作缺少用户确认",
    "SF-PLAN-5004": "执行动作超出已确认计划",
    "SF-PLAN-5005": "计划未记录验证方式",
    "SF-PLAN-5006": "计划未进入 evidence refs",
    "SF-PLAN-5007": "计划只存在于最终报告，未在执行前生效",
    "SF-PLAN-5008": "用户项目 adapter 未注入计划前置规则",
    "SF-PLAN-5009": "机制层未接入，只有模板或知识描述",
    "SF-PLAN-5010": "none_with_reason 被用于写入或高风险任务",
};
//# sourceMappingURL=plan_proposal_gate.js.map