/**
 * 强制护栏注册表 — 问题十一 (Enforcement Guard)。
 *
 * 覆盖七类护栏: write、state、knowledge_injection、execution、
 * external_side_effect、prompt、delivery。
 * 护栏 finding 必须绑定 contract_id + diagnostic_code。
 * 只有 contract state=enforced 且 hard_fail_allowed=true 时才能 hard fail。
 */
import { getDiagnosticByCode, createDiagnosticEvent } from "../audit/diagnostic_registry.js";
import { canContractHardFail } from "./contract_registry.js";
import { evaluateCoreExperiencePrinciple, recordCepIntegration } from "../audit/core_experience_principle.js";
import { isPathInScope } from "../core/path_scope_utils.js";
const BUILTIN_GUARDS = [
    {
        guard_id: "guard-write-readonly",
        guard_type: "write",
        enforced: true,
        trigger_description: "只读工作流写入业务源码",
        block_condition: "route=skip_chat/direct_answer/read_only_analysis 且写入目标为业务源码",
        allow_condition: "route 允许写入",
        failure_behavior: "block",
        contract_id: "command_execution_contract",
        diagnostic_code: "SF-GUARD-0001",
        required_context: ["route", "target_path"],
    },
    {
        guard_id: "guard-write-scope",
        guard_type: "write",
        enforced: true,
        trigger_description: "超出 output artifact 范围写入",
        block_condition: "source_extraction 写入非 output artifact 路径",
        allow_condition: "写入路径在 output artifact 范围内",
        failure_behavior: "block",
        contract_id: "artifact_contract",
        diagnostic_code: "SF-GUARD-0002",
        required_context: ["route", "target_path", "output_artifact_paths"],
    },
    {
        guard_id: "guard-state-pseudo-promotion",
        guard_type: "state",
        enforced: true,
        trigger_description: "非法状态转移: 终态/阻断态 → completed",
        block_condition: "failed/blocked/requires_human → completed",
        allow_condition: "合法状态转移路径",
        failure_behavior: "block",
        contract_id: "task_context_contract",
        diagnostic_code: "SF-STATE-0001",
        required_context: ["current_status", "target_status"],
    },
    {
        guard_id: "guard-delivery-explicit",
        guard_type: "delivery",
        enforced: true,
        trigger_description: "交付未显式触发",
        block_condition: "delivery_readiness 自动触发 commit/push/PR/deploy",
        allow_condition: "交付动作由 sf_deliver 显式触发",
        failure_behavior: "block",
        contract_id: "artifact_contract",
        diagnostic_code: "SF-VERIFY-0002",
        required_context: ["delivery_trigger"],
    },
    {
        guard_id: "guard-knowledge-injectable",
        guard_type: "knowledge_injection",
        enforced: true,
        trigger_description: "非 injectable 知识进入 prompt",
        block_condition: "draft/quarantine/deprecated 知识被注入",
        allow_condition: "知识状态为 active 且 injectable",
        failure_behavior: "block",
        contract_id: "knowledge_injection_contract",
        diagnostic_code: "SF-GUARD-0004",
        required_context: ["knowledge_state", "knowledge_lifecycle"],
    },
    {
        guard_id: "guard-execution-destructive",
        guard_type: "execution",
        enforced: true,
        trigger_description: "破坏性命令未确认",
        block_condition: "destructive 命令无人工确认",
        allow_condition: "命令经人工确认或有明确策略",
        failure_behavior: "require_human",
        contract_id: "command_execution_contract",
        diagnostic_code: "SF-GUARD-0003",
        required_context: ["command", "risk_level"],
    },
    {
        guard_id: "guard-external-side-effect",
        guard_type: "external_side_effect",
        enforced: true,
        trigger_description: "外部副作用未记录",
        block_condition: "git push/PR/deploy/数据库迁移 无 evidence",
        allow_condition: "副作用有完整 evidence 记录",
        failure_behavior: "block",
        contract_id: "delivery_readiness_contract",
        diagnostic_code: "SF-GUARD-0006",
        required_context: ["action_type", "evidence"],
    },
    {
        guard_id: "guard-prompt-auth",
        guard_type: "prompt",
        enforced: true,
        trigger_description: "Prompt 授权超过 workflow contract",
        block_condition: "prompt 包含超出 workflow 的权限",
        allow_condition: "prompt 权限在 workflow 范围内",
        failure_behavior: "block",
        contract_id: "workflow_contract",
        diagnostic_code: "SF-GUARD-0005",
        required_context: ["workflow_id", "prompt_permissions"],
    },
];
let runtimeGuards = null;
function getRegistry() {
    if (!runtimeGuards) {
        runtimeGuards = new Map();
        for (const entry of BUILTIN_GUARDS) {
            runtimeGuards.set(entry.guard_id, { ...entry });
        }
    }
    return runtimeGuards;
}
/** 列出所有护栏 */
export function listAllGuards() {
    return [...getRegistry().values()];
}
/** 按类型列出护栏 */
export function listGuardsByType(type) {
    return [...getRegistry().values()].filter((g) => g.guard_type === type);
}
/** 注册新护栏（运行时） */
export function registerGuard(entry) {
    const registry = getRegistry();
    if (registry.has(entry.guard_id)) {
        return { success: false, error: `护栏 ${entry.guard_id} 已存在` };
    }
    if (!getDiagnosticByCode(entry.diagnostic_code)) {
        return { success: false, error: `诊断码 ${entry.diagnostic_code} 不存在` };
    }
    registry.set(entry.guard_id, { ...entry });
    return { success: true };
}
/**
 * 评估写入护栏。
 * 检查 route 和 target_path 是否违反写入规则。
 */
export function evaluateWriteGuard(route, targetPath, outputArtifactPaths, contractId) {
    const findings = [];
    const read_only_routes = ["skip_chat", "direct_answer", "read_only_analysis"];
    // 只读工作流写入检查
    if (read_only_routes.some((r) => route.includes(r))) {
        const guard = getRegistry().get("guard-write-readonly");
        if (guard && guard.enforced) {
            const canHardFail = canContractHardFail(guard.contract_id);
            findings.push({
                guard_id: guard.guard_id,
                contract_id: guard.contract_id,
                diagnostic_code: guard.diagnostic_code,
                severity: canHardFail ? "hard_fail" : "warning",
                action: guard.failure_behavior,
                reason_zh: `只读路由 ${route} 不允许写入 ${targetPath}`,
                blocked: canHardFail,
                diagnostic_event: createDiagnosticEvent(guard.diagnostic_code, { route, targetPath }, contractId),
            });
        }
    }
    // scope 检查（source_extraction 超范围）
    if (route.includes("source_extraction") && outputArtifactPaths.length > 0) {
        if (!outputArtifactPaths.some((p) => isPathInScope(targetPath, p, { caseSensitive: true }))) {
            const guard = getRegistry().get("guard-write-scope");
            if (guard && guard.enforced) {
                const canHardFail = canContractHardFail(guard.contract_id);
                findings.push({
                    guard_id: guard.guard_id,
                    contract_id: guard.contract_id,
                    diagnostic_code: guard.diagnostic_code,
                    severity: canHardFail ? "hard_fail" : "warning",
                    action: guard.failure_behavior,
                    reason_zh: `source_extraction 只能写入 output artifact 路径，不能写入 ${targetPath}`,
                    blocked: canHardFail,
                    diagnostic_event: createDiagnosticEvent(guard.diagnostic_code, { route, targetPath }, contractId),
                });
            }
        }
    }
    // CEP: 护栏评估后核心体验检查
    const guardBlocked = findings.some(f => f.blocked);
    const cepGuardResult = evaluateCoreExperiencePrinciple({
        task_id: "", workflow_id: "guard_evaluation",
        has_mainline_hooks: true, has_owner_contracts: true,
        natural_language_entry: true, requires_internal_contract_knowledge: false,
        user_path_steps: 3, has_failures: guardBlocked, hard_fail_downgraded: false,
        forced_heavy_process: false, has_sufficient_evidence: !guardBlocked,
        output_too_long_no_summary: false, report_only_no_repair: false,
        failed_but_marked_done: false, auto_repair_overreach: false,
        repair_reverified: false, outputs_raw_noise: false,
    });
    recordCepIntegration("guard_evaluation", cepGuardResult);
    return findings;
}
/**
 * 评估状态护栏。
 * 检查状态转移是否合法。
 */
export function evaluateStateGuard(currentStatus, targetStatus, contractId) {
    const findings = [];
    const BLOCKED_FROM = ["failed", "blocked", "requires_human"];
    const BLOCKED_TO = "completed";
    if (BLOCKED_FROM.includes(currentStatus) && targetStatus === BLOCKED_TO) {
        const guard = getRegistry().get("guard-state-pseudo-promotion");
        if (guard && guard.enforced) {
            const canHardFail = canContractHardFail(guard.contract_id);
            findings.push({
                guard_id: guard.guard_id,
                contract_id: guard.contract_id,
                diagnostic_code: guard.diagnostic_code,
                severity: canHardFail ? "hard_fail" : "warning",
                action: guard.failure_behavior,
                reason_zh: `非法状态转移: ${currentStatus} → completed`,
                blocked: canHardFail,
                diagnostic_event: createDiagnosticEvent(guard.diagnostic_code, { currentStatus, targetStatus }, contractId),
            });
        }
    }
    return findings;
}
/**
 * 生成完整护栏评估报告。
 */
export function generateGuardEvaluationReport(workflowId, route, mutationAllowed, guardIds) {
    const allowed = [];
    const blocked = [];
    const warnings = [];
    const humanRequired = [];
    for (const guardId of guardIds) {
        const guard = getRegistry().get(guardId);
        if (!guard)
            continue;
        if (!guard.enforced) {
            allowed.push(guardId);
            continue;
        }
        // 简化评估: 如果 mutation 不允许且 guard 是写入类型，则阻断
        if (!mutationAllowed && guard.guard_type === "write") {
            const canHardFail = canContractHardFail(guard.contract_id);
            const finding = {
                guard_id: guard.guard_id,
                contract_id: guard.contract_id,
                diagnostic_code: guard.diagnostic_code,
                severity: canHardFail ? "hard_fail" : "warning",
                action: guard.failure_behavior,
                reason_zh: guard.trigger_description,
                blocked: canHardFail,
                diagnostic_event: createDiagnosticEvent(guard.diagnostic_code, { workflowId, route }),
            };
            blocked.push(finding);
        }
        else {
            allowed.push(guardId);
        }
    }
    return {
        evaluated_at: new Date().toISOString(),
        workflow_id: workflowId,
        route,
        mutation_allowed: mutationAllowed,
        evaluated_guards: guardIds,
        allowed,
        blocked,
        warnings,
        human_required: humanRequired,
    };
}
/**
 * 校验所有 guard 的 contract_id 是否存在于 Contract Registry。
 */
export function validateGuardContractIds(contractExistsFn) {
    const findings = [];
    for (const guard of getRegistry().values()) {
        if (!contractExistsFn(guard.contract_id)) {
            findings.push({
                guard_id: guard.guard_id,
                contract_id: guard.contract_id,
                severity: "hard_fail",
            });
        }
    }
    return findings;
}
/**
 * 评估交付就绪护栏。
 * 检查交付是否由 sf_deliver 显式触发，验证结果是否满足交付条件。
 */
export function evaluateDeliveryReadinessGuard(verificationResult, _verificationPlan) {
    const findings = [];
    // guard-delivery-explicit: 交付必须由 sf_deliver 显式触发
    const guard = getRegistry().get("guard-delivery-explicit");
    if (guard && guard.enforced) {
        // 如果验证结果不存在或是 plan_only，给出警告
        if (!verificationResult || verificationResult.status === "not_executed") {
            const canHardFail = canContractHardFail(guard.contract_id);
            findings.push({
                guard_id: guard.guard_id,
                contract_id: guard.contract_id,
                diagnostic_code: guard.diagnostic_code,
                severity: canHardFail ? "hard_fail" : "warning",
                action: guard.failure_behavior,
                reason_zh: verificationResult
                    ? `验证结果状态为 ${verificationResult.status}，未通过真实执行验证`
                    : "无验证结果，不得交付",
                blocked: canHardFail,
                diagnostic_event: createDiagnosticEvent(guard.diagnostic_code, { verification_status: verificationResult?.status ?? "missing" }, guard.contract_id),
            });
        }
    }
    return findings;
}
/**
 * 破坏性命令模式库 — 匹配已知的高风险命令模式。
 * 每个条目包含正则和中文描述，用于生成诊断信息。
 */
const DESTRUCTIVE_COMMAND_PATTERNS = [
    { pattern: /\brm\s+(-[a-zA-Z]*r[a-zA-Z]*f[a-zA-Z]*|-rf)\b/, label_zh: "递归强制删除" },
    { pattern: /\brm\s+-[a-zA-Z]*r/, label_zh: "递归删除" },
    { pattern: /\bgit\s+push\s+.*--force(?:-with-lease)?\b/, label_zh: "强制推送" },
    { pattern: /\bgit\s+push\s+(\S+\s+)*-f\b/, label_zh: "强制推送" },
    { pattern: /\bDROP\s+(TABLE|DATABASE|SCHEMA)\b/i, label_zh: "SQL 删除表/数据库" },
    { pattern: /\bTRUNCATE\s+(TABLE\s+)?[\w.]+/i, label_zh: "SQL 清空表" },
    { pattern: /\bDELETE\s+FROM\b(?![^;]*\bWHERE\b)/i, label_zh: "SQL 无 WHERE 删除" },
    { pattern: /\bchmod\s+(-R\s+)?777\b/, label_zh: "全权限修改" },
    { pattern: /\bdocker\s+system\s+prune\b/, label_zh: "Docker 系统清理" },
    { pattern: /\bdocker\s+rm\s+(-f|--force)\b/, label_zh: "Docker 强制删除容器" },
    { pattern: /\bnpm\s+publish\b/, label_zh: "npm 发布（不可撤回）" },
];
/**
 * 评估破坏性命令护栏。
 * 结合 riskLevel 和命令模式双重判定，人工确认后可放行。
 *
 * 判定逻辑:
 * - riskLevel === "destructive" 且匹配破坏性模式 → hard_fail（不可确认放行）
 * - riskLevel === "destructive" 或匹配破坏性模式 → 需确认
 *   - humanConfirmed=true → 放行（清空 findings）
 *   - humanConfirmed=false → 阻断
 * - 仅模式匹配（riskLevel !== "destructive"） → warning
 * - 均不匹配 → 放行（空 findings）
 */
export function evaluateExecutionDestructiveGuard(command, riskLevel, humanConfirmed) {
    const findings = [];
    const guard = getRegistry().get("guard-execution-destructive");
    if (!guard || !guard.enforced) {
        return findings;
    }
    const canHardFail = canContractHardFail(guard.contract_id);
    // 匹配破坏性命令模式
    const matchedPatterns = DESTRUCTIVE_COMMAND_PATTERNS.filter((p) => p.pattern.test(command));
    const matchesDestructivePattern = matchedPatterns.length > 0;
    const isDestructiveRisk = riskLevel === "destructive";
    // 双重确认: riskLevel=destructive 且匹配模式 → 不可确认放行的硬阻断
    if (isDestructiveRisk && matchesDestructivePattern) {
        findings.push({
            guard_id: guard.guard_id,
            contract_id: guard.contract_id,
            diagnostic_code: guard.diagnostic_code,
            severity: "hard_fail",
            action: "block",
            reason_zh: `高风险破坏性命令 "${command.slice(0, 80)}" 匹配破坏性模式（${matchedPatterns.map((p) => p.label_zh).join("、")}），即使人工确认也不允许执行`,
            blocked: true,
            diagnostic_event: createDiagnosticEvent(guard.diagnostic_code, { command, riskLevel, matched_patterns: matchedPatterns.map((p) => p.label_zh), dual_block: true }, guard.contract_id),
        });
        return findings;
    }
    // 单一条件触发: riskLevel=destructive 或匹配模式 → 需人工确认
    if (isDestructiveRisk || matchesDestructivePattern) {
        if (humanConfirmed) {
            // 人工已确认 → 放行
            return findings;
        }
        // 未确认 → 阻断/警告
        const patternLabel = matchesDestructivePattern
            ? matchedPatterns.map((p) => p.label_zh).join("、")
            : "";
        findings.push({
            guard_id: guard.guard_id,
            contract_id: guard.contract_id,
            diagnostic_code: guard.diagnostic_code,
            severity: canHardFail ? "hard_fail" : "warning",
            action: guard.failure_behavior,
            reason_zh: matchesDestructivePattern
                ? `命令 "${command.slice(0, 80)}" 匹配破坏性模式（${patternLabel}），需要人工确认`
                : `破坏性命令 "${command.slice(0, 80)}" 需要人工确认`,
            blocked: canHardFail,
            diagnostic_event: createDiagnosticEvent(guard.diagnostic_code, { command, riskLevel, matched_patterns: matchedPatterns.map((p) => p.label_zh) }, guard.contract_id),
        });
        return findings;
    }
    // 均不匹配 → 放行
    return findings;
}
const EXTERNAL_SIDE_EFFECT_TYPES = {
    deploy: "critical",
    migration: "critical",
    database_change: "critical",
    git_push: "standard",
    pr_create: "standard",
    release: "standard",
};
/**
 * 评估外部副作用护栏。
 * 检查外部副作用操作是否有 evidence 记录，根据操作类型区分严重度。
 *
 * 判定逻辑:
 * - hasEvidence=true → 放行（空 findings）
 * - hasEvidence=false:
 *   - critical 类型（deploy/migration/database_change）→ hard_fail
 *   - standard 类型（git_push/pr_create/release）→ warning
 *   - 未知类型 → warning（保守降级）
 */
export function evaluateExternalSideEffectGuard(actionType, hasEvidence) {
    const findings = [];
    const guard = getRegistry().get("guard-external-side-effect");
    if (!guard || !guard.enforced) {
        return findings;
    }
    // 有 evidence → 放行
    if (hasEvidence) {
        return findings;
    }
    const canHardFail = canContractHardFail(guard.contract_id);
    const criticality = EXTERNAL_SIDE_EFFECT_TYPES[actionType];
    if (criticality === "critical") {
        // 关键操作无 evidence → 硬阻断
        findings.push({
            guard_id: guard.guard_id,
            contract_id: guard.contract_id,
            diagnostic_code: guard.diagnostic_code,
            severity: canHardFail ? "hard_fail" : "warning",
            action: guard.failure_behavior,
            reason_zh: `关键外部副作用操作 "${actionType}" 缺少 evidence 记录，操作已阻断`,
            blocked: canHardFail,
            diagnostic_event: createDiagnosticEvent(guard.diagnostic_code, { actionType, criticality: "critical" }, guard.contract_id),
        });
    }
    else if (criticality === "standard") {
        // 标准操作无 evidence → 警告
        findings.push({
            guard_id: guard.guard_id,
            contract_id: guard.contract_id,
            diagnostic_code: guard.diagnostic_code,
            severity: "warning",
            action: "warn",
            reason_zh: `外部副作用操作 "${actionType}" 缺少 evidence 记录，建议补充`,
            blocked: false,
            diagnostic_event: createDiagnosticEvent(guard.diagnostic_code, { actionType, criticality: "standard" }, guard.contract_id),
        });
    }
    else {
        // 未知类型 → 保守降级为警告
        findings.push({
            guard_id: guard.guard_id,
            contract_id: guard.contract_id,
            diagnostic_code: guard.diagnostic_code,
            severity: "warning",
            action: "warn",
            reason_zh: `未知外部副作用操作 "${actionType}" 缺少 evidence 记录，建议补充`,
            blocked: false,
            diagnostic_event: createDiagnosticEvent(guard.diagnostic_code, { actionType, criticality: "unknown" }, guard.contract_id),
        });
    }
    return findings;
}
/** 重置注册表（测试用） */
export function resetGuardRegistry() {
    runtimeGuards = null;
}
//# sourceMappingURL=enforcement_guard.js.map