/**
 * Hook Additional Context 类型与辅助函数
 *
 * 从 adapters/claude_code/pre_prompt_contract.ts 提取至 engine 层，
 * 修正 engine→adapter 的依赖方向违规。
 * 被 scenario runner、pre_prompt_contract、negative tests 共用。
 */
/**
 * 从 RouteDecision 构建结构化 additionalContext。
 * skip_chat / direct_answer 返回 null（不触发 SoloForge 工具链）。
 */
export function buildHookAdditionalContext(decision) {
    if (decision.route === "skip_chat" || decision.route === "direct_answer")
        return null;
    return {
        _type: "SoloForgeRouteDecision",
        instruction: "必须先调用 sf_classify 工具进行分类，不要直接处理。",
        route_decision: {
            route: decision.route,
            execution_shape: decision.execution_shape,
            mutation_allowed: decision.mutation_allowed,
            input_materials: decision.input_materials.map(m => ({ kind: m.kind, path: m.path ?? null, required: m.required })),
            output_artifact: decision.output_artifact ?? null,
            missing_required_inputs: decision.missing_required_inputs,
            prompt_template: decision.pipeline_hint ?? null,
            confidence: decision.confidence,
            evidence: decision.evidence,
            rejected_routes: decision.rejected_routes.map(r => ({ route: r.route, reason: r.reason })),
            conflicts: decision.conflicts,
        },
    };
}
const REQUIRED_RD_FIELDS = [
    "route", "execution_shape", "mutation_allowed", "input_materials",
    "output_artifact", "missing_required_inputs", "prompt_template",
    "confidence", "evidence", "rejected_routes", "conflicts",
];
/**
 * 验证 additionalContext 结构是否完整。
 * 用于 negative tests 证明"缺字段时 Gate 会红"。
 */
export function verifyHookAdditionalContextStructure(ctx) {
    const missing = [];
    if (ctx._type !== "SoloForgeRouteDecision") {
        missing.push("_type");
    }
    const rd = ctx.route_decision;
    if (!rd || typeof rd !== "object") {
        missing.push("route_decision");
        return { pass: false, missing_fields: missing };
    }
    for (const field of REQUIRED_RD_FIELDS) {
        if (!(field in rd)) {
            missing.push(field);
        }
    }
    return { pass: missing.length === 0, missing_fields: missing };
}
/**
 * 比较 hook RouteDecision 与 classify RouteDecision，返回冲突证据。
 * 不一致时不允许静默覆盖，必须产生 conflict evidence。
 */
export function compareHookAndClassifyRouteDecision(hookDecision, classifyDecision) {
    const conflicts = [];
    if (hookDecision.route !== classifyDecision.route) {
        conflicts.push({
            field: "route",
            expected: hookDecision.route,
            actual: classifyDecision.route,
            source: "classify",
            severity: "hard_fail",
        });
    }
    if (hookDecision.execution_shape !== classifyDecision.execution_shape) {
        conflicts.push({
            field: "execution_shape",
            expected: hookDecision.execution_shape,
            actual: classifyDecision.execution_shape,
            source: "classify",
            severity: "hard_fail",
        });
    }
    if (hookDecision.mutation_allowed !== classifyDecision.mutation_allowed) {
        conflicts.push({
            field: "mutation_allowed",
            expected: hookDecision.mutation_allowed,
            actual: classifyDecision.mutation_allowed,
            source: "classify",
            severity: "hard_fail",
        });
    }
    // input_materials kind 集合比较
    const hookKinds = new Set(hookDecision.input_materials.map(m => m.kind));
    const classifyKinds = new Set(classifyDecision.input_materials.map(m => m.kind));
    if (hookKinds.size !== classifyKinds.size || [...hookKinds].some(k => !classifyKinds.has(k))) {
        conflicts.push({
            field: "input_materials_kinds",
            expected: [...hookKinds],
            actual: [...classifyKinds],
            source: "classify",
            severity: "degraded",
        });
    }
    // output_artifact kind 比较
    const hookArtifactKind = hookDecision.output_artifact?.kind ?? null;
    const classifyArtifactKind = classifyDecision.output_artifact?.kind ?? null;
    if (hookArtifactKind !== classifyArtifactKind) {
        conflicts.push({
            field: "output_artifact_kind",
            expected: hookArtifactKind,
            actual: classifyArtifactKind,
            source: "classify",
            severity: "degraded",
        });
    }
    return conflicts;
}
//# sourceMappingURL=hook_context_types.js.map