/**
 * 意图扩展器 — 隐私门禁、输入材料处理和输出产物创建。
 *
 * 实现在知识解析和提示渲染之前运行的早期返回门禁检查。
 */
import { createInputMaterial, createIngestionEvidence, buildPromptInjectionPlan, classifyIngestionStatus, } from "../input_material_contract_registry.js";
import { normalizePathCandidate } from "../input_material_extractor.js";
import { createOutputArtifact, getDefaultArtifactPath } from "../../contracts/artifact_contract_registry.js";
import { evaluatePrivacyGate, redactSensitiveText, } from "../../audit/privacy_secret_contract.js";
import { FORBIDDEN_READ_PATTERNS } from "../../audit/privacy_patterns.js";
import { resolveCurrentProjectConfigReports } from "../../config/config_precedence_contract.js";
import { resolveWorkflow } from "../../workflow/workflow_contract_registry.js";
import { evaluateCoreExperiencePrinciple, recordCepIntegration } from "../../audit/core_experience_principle.js";
import { debugLog } from "../../core/logger.js";
import { mapToArtifactKind, buildBlockedResult } from "./helpers.js";
// ── 门控阶段函数 ──
/**
 * 解析配置优先级并收集警告。
 * 读取项目配置文件，返回配置报告和潜在警告。
 * @param projectPath - 项目根路径
 * @returns 配置警告列表和完整解析结果
 */
export async function resolveConfigWarnings(projectPath) {
    let configResolution;
    try {
        configResolution = await resolveCurrentProjectConfigReports(projectPath);
    }
    catch (e) {
        debugLog("意图扩展: 配置优先级解析失败 —", e);
        configResolution = { reports: [], resolutions: [], warnings: [], entries: [] };
    }
    return { warnings: configResolution.warnings, configResolution };
}
/**
 * 执行隐私门禁检查 — 对意图文本进行脱敏和敏感信息评估。
 * 轻量路径仅做禁止读取模式检查；全量路径执行完整隐私评估。
 * @param intent - 原始意图文本
 * @param phasePolicy - 策略配置，lightweight=true 时跳过全量评估
 * @param input - 扩展输入参数
 * @returns 脱敏后的意图和隐私门禁结果
 */
export function runPrivacyGate(intent, phasePolicy, input) {
    let safeIntent;
    let safeGoal;
    let privacyGate;
    if (phasePolicy.lightweight) {
        safeIntent = redactSensitiveText(intent, "intent").redacted;
        safeGoal = redactSensitiveText(intent.slice(0, 200), "intent_goal").redacted;
        // 轻量路径仍需检查禁止读取模式 — 即使不做全量隐私评估，也要拦截凭据/密钥泄露
        const forbiddenHits = FORBIDDEN_READ_PATTERNS.filter((p) => p.pattern.test(safeIntent));
        if (forbiddenHits.length > 0) {
            const blockedSources = forbiddenHits.map((p) => p.reason);
            privacyGate = {
                allowed: false,
                labels: [],
                redaction_records: [],
                findings: forbiddenHits.map((p) => ({ severity: "hard_fail", rule: "forbidden-read-pattern", message: p.reason })),
                blocked_sources: blockedSources,
                hard_fail: true,
            };
        }
        else {
            privacyGate = { allowed: true, labels: [], redaction_records: [], findings: [], blocked_sources: [], hard_fail: false };
        }
    }
    else {
        privacyGate = evaluatePrivacyGate({
            intent,
            input_materials: input.route_decision?.input_materials?.map((m) => ({ path_or_ref: m.path ?? "" })) ?? [],
        });
        safeIntent = privacyGate.redacted_text ?? redactSensitiveText(intent, "intent").redacted;
        safeGoal = redactSensitiveText(intent.slice(0, 200), "intent_goal").redacted;
    }
    return { safeIntent, safeGoal, privacyGate };
}
/**
 * 创建输出产物记录 — 根据路由决策生成产物契约。
 * 校验 task_id 一致性和产物路径合法性。
 * @param input - 扩展输入参数
 * @param routeDecision - 意图路由决策
 * @param safeIntent - 脱敏后的意图文本
 * @param safeGoal - 脱敏后的目标文本
 * @returns 产物记录或阻塞原因
 */
export function createOutputArtifactRecord(input, routeDecision, safeIntent, safeGoal) {
    let outputArtifactRecord;
    if (routeDecision?.output_artifact && routeDecision.execution_shape !== "none" && routeDecision.execution_shape !== "code_execution") {
        const artifactKind = mapToArtifactKind(routeDecision.output_artifact.kind);
        if (!input.task_id) {
            return {
                outputArtifactRecord: undefined,
                blockedResult: buildBlockedResult(`## 阻塞：产物缺少 task_id\n\n任务: ${safeIntent}\n\nexpand() 收到 task_id 为空，无法创建产物记录。`, safeGoal, { constraints: ["task_id 缺失"], stopConditions: ["task_id 缺失"] }),
            };
        }
        const sourceMaterialRefs = routeDecision.input_materials
            .filter((m) => m.path)
            .map((m) => m.path);
        if (routeDecision.output_artifact.taskId && routeDecision.output_artifact.taskId !== input.task_id) {
            return {
                outputArtifactRecord: undefined,
                blockedResult: buildBlockedResult(`## Contract Error: task_id 不一致\n\nrouteDecision.taskId=${routeDecision.output_artifact.taskId} !== input.task_id=${input.task_id}`, safeGoal, { constraints: ["task_id 不一致"], stopConditions: ["task_id 不一致"] }),
            };
        }
        outputArtifactRecord = createOutputArtifact({
            kind: artifactKind,
            task_id: input.task_id,
            workflow_id: "pending",
            created_by: "intent_expander",
            path: getDefaultArtifactPath(artifactKind, input.task_id),
            source_material_refs: sourceMaterialRefs,
        });
    }
    return { outputArtifactRecord, blockedResult: undefined };
}
/**
 * 解析工作流契约 — 将路由决策映射到具体工作流实例。
 * 校验 mutation_allowed 一致性，评估核心体验原则。
 * @param routeDecision - 意图路由决策
 * @param input - 扩展输入参数
 * @param safeIntent - 脱敏后的意图文本
 * @param safeGoal - 脱敏后的目标文本
 * @param skipWorkflowContractStrict - 是否跳过严格一致性检查
 * @param outputArtifactRecord - 已创建的输出产物记录
 * @returns 工作流契约和治理发现
 */
export function resolveWorkflowContract(routeDecision, input, safeIntent, safeGoal, skipWorkflowContractStrict, outputArtifactRecord) {
    let workflowContract = undefined;
    const workflowGovernanceFindings = [];
    if (!routeDecision) {
        return { workflowContract, workflowGovernanceFindings, blockedResult: undefined };
    }
    workflowContract = resolveWorkflow(routeDecision);
    if (workflowContract && outputArtifactRecord) {
        outputArtifactRecord.workflow_id = workflowContract.id;
    }
    debugLog("意图膨胀: 工作流契约已解析，workflow=%s", workflowContract?.id ?? "none");
    const cepWfResult = evaluateCoreExperiencePrinciple({
        task_id: input.task_id ?? "", workflow_id: "workflow_resolve",
        has_mainline_hooks: !!workflowContract, has_owner_contracts: !!workflowContract,
        natural_language_entry: true, requires_internal_contract_knowledge: false,
        user_path_steps: 3, has_failures: !workflowContract, hard_fail_downgraded: false,
        forced_heavy_process: false, has_sufficient_evidence: !!workflowContract,
        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("workflow_resolve", cepWfResult);
    if (!workflowContract) {
        return {
            workflowContract, workflowGovernanceFindings,
            blockedResult: buildBlockedResult(`## 阻塞：无工作流契约\n\n任务: ${safeIntent}\n\nroute="${routeDecision.route}" + execution_shape="${routeDecision.execution_shape}" 没有匹配的工作流契约。\n\n请检查意图路由配置。`, safeGoal, {
                constraints: ["无匹配工作流契约"], stopConditions: ["修复意图路由配置"],
                outputArtifactRecord: outputArtifactRecord,
                workflowTrace: {
                    workflow_id: "none", route: routeDecision.route,
                    execution_shape: routeDecision.execution_shape, mutation_allowed: routeDecision.mutation_allowed,
                    required_mechanisms: [],
                    governance_findings: [{ severity: "hard_fail", rule: "gc-no-workflow", message: `no workflow contract for ${routeDecision.route}+${routeDecision.execution_shape}` }],
                    degraded: true, state_transition_target: "none",
                },
            }),
        };
    }
    if (!skipWorkflowContractStrict && workflowContract.mutation_allowed !== routeDecision.mutation_allowed) {
        return {
            workflowContract, workflowGovernanceFindings,
            blockedResult: buildBlockedResult(`## 阻塞：mutation_allowed 不一致\n\n任务: ${safeIntent}\n\n工作流 "${workflowContract.id}" 的 mutation_allowed=${workflowContract.mutation_allowed} 与 route_decision 的 mutation_allowed=${routeDecision.mutation_allowed} 不一致。`, safeGoal, {
                constraints: ["mutation_allowed 不一致"], stopConditions: ["mutation_allowed 不一致"],
                outputArtifactRecord: outputArtifactRecord,
                workflowTrace: {
                    workflow_id: workflowContract.id, route: routeDecision.route,
                    execution_shape: routeDecision.execution_shape, mutation_allowed: workflowContract.mutation_allowed,
                    required_mechanisms: workflowContract.required_mechanisms,
                    governance_findings: [{ severity: "hard_fail", rule: "gc-mutation-mismatch", message: `mutation_allowed mismatch: workflow=${workflowContract.mutation_allowed} route=${routeDecision.mutation_allowed}` }],
                    degraded: true, state_transition_target: "none",
                },
            }),
        };
    }
    if (!skipWorkflowContractStrict && workflowContract.prompt_template !== input.route_decision?.route) {
        // prompt_template 一致性在 expand() 中通过 templateName 检查
        // 此路径保留用于结构一致性
    }
    return { workflowContract, workflowGovernanceFindings, blockedResult: undefined };
}
/**
 * 解析输入材料 — 将路由决策中的材料路径转换为输入材料实例。
 * 检查禁止读取路径、需要确认的材料，并生成摄取证据。
 * @param routeDecision - 意图路由决策
 * @param input - 扩展输入参数
 * @param safeIntent - 脱敏后的意图文本
 * @param safeGoal - 脱敏后的目标文本
 * @param skipInputMaterialHardBlock - 是否跳过禁止材料硬阻断
 * @param workflowContract - 已解析的工作流契约
 * @returns 输入材料列表、摄取证据或阻塞原因
 */
export function resolveInputMaterials(routeDecision, input, safeIntent, safeGoal, skipInputMaterialHardBlock, workflowContract, projectPath) {
    let inputMaterials;
    let ingestionEvidences;
    let promptInjectionPlan;
    const contractNotes = [];
    if (routeDecision && routeDecision.input_materials.length > 0) {
        const pathMaterials = routeDecision.input_materials.filter((m) => m.path);
        if (pathMaterials.length > 0) {
            const materials = pathMaterials.map((m) => createInputMaterial({ path_or_ref: normalizePathCandidate(m.path) }));
            inputMaterials = materials;
            ingestionEvidences = materials.map((m) => createIngestionEvidence(m, projectPath));
            for (const m of materials) {
                if (m.access_mode === "forbidden") {
                    contractNotes.push(`[FORBIDDEN] ${m.path_or_ref}: 禁止读取`);
                }
                else if (m.trust_level === "external_unverified" || m.trust_level === "derived" || m.trust_level === "ai_generated") {
                    contractNotes.push(`[Manual Confirm] ${m.path_or_ref}: 信任等级=${m.trust_level}`);
                }
            }
            promptInjectionPlan = buildPromptInjectionPlan(materials, ingestionEvidences);
        }
    }
    // ── 输入材料硬阻断 ──
    if (inputMaterials) {
        const forbiddenMaterials = inputMaterials.filter((m) => m.access_mode === "forbidden");
        if (!skipInputMaterialHardBlock && forbiddenMaterials.length > 0) {
            const forbiddenPaths = forbiddenMaterials.map((m) => m.path_or_ref).join(", ");
            debugLog("意图膨胀: 输入材料禁止读取: %s", forbiddenPaths);
            return {
                inputMaterials, ingestionEvidences, promptInjectionPlan, contractNotes,
                blockedResult: buildBlockedResult(`## 阻塞：输入材料禁止读取\n\n任务: ${safeIntent}\n\n以下材料路径触发禁止规则，不得读取:\n${forbiddenMaterials.map((m) => "  - " + m.path_or_ref).join("\n")}\n\n请移除这些材料后重新调用。`, safeGoal, {
                    constraints: ["输入材料包含禁止路径"], stopConditions: [],
                    inputMaterials, ingestionEvidences,
                    promptInjectionPlan,
                    workflowTrace: workflowContract ? {
                        workflow_id: workflowContract.id, route: routeDecision?.route ?? "",
                        execution_shape: routeDecision?.execution_shape ?? "", mutation_allowed: workflowContract.mutation_allowed,
                        required_mechanisms: workflowContract.required_mechanisms,
                        governance_findings: [{ severity: "hard_fail", rule: "gc-forbidden-material", message: `材料禁止读取: ${forbiddenPaths}` }],
                        degraded: true, state_transition_target: "none",
                    } : undefined,
                }),
            };
        }
        const confirmations = input.input_material_confirmations ?? [];
        const requiresConfirmationMaterials = inputMaterials.filter((m) => m.access_mode !== "forbidden"
            && classifyIngestionStatus(m.path_or_ref) === "requires_confirmation"
            && !confirmations.includes(m.path_or_ref));
        if (requiresConfirmationMaterials.length > 0) {
            const confirmPaths = requiresConfirmationMaterials.map((m) => m.path_or_ref);
            return {
                inputMaterials, ingestionEvidences, promptInjectionPlan, contractNotes,
                blockedResult: buildBlockedResult(`## 澄清请求\n\n任务: ${safeIntent}\n\n以下输入材料需要人工确认后才能使用:\n${confirmPaths.map((p) => "  - " + p).join("\n")}\n\n请确认以上材料安全性后，通过 input_material_confirmations 参数重新调用。`, safeGoal, {
                    constraints: ["输入材料需要确认"], stopConditions: [],
                    inputMaterials, ingestionEvidences,
                    promptInjectionPlan,
                    workflowTrace: workflowContract ? {
                        workflow_id: workflowContract.id, route: routeDecision?.route ?? "",
                        execution_shape: routeDecision?.execution_shape ?? "", mutation_allowed: workflowContract.mutation_allowed,
                        required_mechanisms: workflowContract.required_mechanisms,
                        governance_findings: [], degraded: true, state_transition_target: "clarifying",
                    } : undefined,
                }),
            };
        }
    }
    return { inputMaterials, ingestionEvidences, promptInjectionPlan, contractNotes, blockedResult: undefined };
}
/**
 * 隐私硬门禁检查 — 评估隐私门禁结果中的 hard_fail 标志。
 * 触发 hard_fail 时返回包含详细治理发现的阻塞结果。
 * @param privacyGate - 隐私门禁评估结果
 * @param safeIntent - 脱敏后的意图文本
 * @param safeGoal - 脱敏后的目标文本
 * @param inputMaterials - 输入材料列表
 * @param ingestionEvidences - 摄取证据列表
 * @param promptInjectionPlan - 提示注入计划
 * @param outputArtifactRecord - 输出产物记录
 * @param workflowContract - 工作流契约
 * @param routeDecision - 意图路由决策
 * @returns 敏感标签、脱敏记录和可能的阻塞结果
 */
export function checkPrivacyHardGate(privacyGate, safeGoal, inputMaterials, ingestionEvidences, promptInjectionPlan, outputArtifactRecord, workflowContract, routeDecision) {
    const labels = privacyGate.labels;
    const redactions = privacyGate.redaction_records;
    const findings = privacyGate.findings;
    if (privacyGate.hard_fail) {
        debugLog("意图膨胀: 隐私策略阻断，包含 %d 个禁止来源", privacyGate.blocked_sources.length);
        return {
            labels, redactions, findings,
            blockedResult: buildBlockedResult([
                "## 阻塞：隐私/敏感信息策略",
                "",
                "任务内容已因隐私策略脱敏",
                "",
                "隐私门禁触发 hard_fail，以下来源包含禁止级别的敏感信息:",
                ...privacyGate.blocked_sources.map((s) => "  - " + s),
                "",
                "治理发现:",
                ...privacyGate.findings.map((f) => `  [${f.severity}] ${f.rule}: ${f.message}`),
                "",
                "请移除敏感信息后重新调用。",
            ].join("\n"), safeGoal, {
                constraints: ["隐私/敏感信息策略阻断"], stopConditions: ["隐私/敏感信息策略阻断"],
                sensitivityLabels: labels, redactionRecords: redactions, privacyFindings: findings,
                inputMaterials, ingestionEvidences,
                promptInjectionPlan, outputArtifactRecord,
                workflowTrace: workflowContract ? {
                    workflow_id: workflowContract.id, route: routeDecision?.route ?? "",
                    execution_shape: routeDecision?.execution_shape ?? "", mutation_allowed: workflowContract.mutation_allowed,
                    required_mechanisms: workflowContract.required_mechanisms,
                    governance_findings: findings.map((f) => ({ severity: f.severity, rule: f.rule, message: f.message })),
                    degraded: true, state_transition_target: "none",
                } : undefined,
            }),
        };
    }
    return { labels, redactions, findings, blockedResult: undefined };
}
//# sourceMappingURL=privacy_gates.js.map