from __future__ import annotations import pytest from app.services.analysis_packet_builder import build_analysis_packet from app.services.integrations.feishu_integration_service.mixin_receive_routing import ( FeishuReceiveRoutingMixin, ) def _render_text(packet: dict[str, object]) -> str: return FeishuReceiveRoutingMixin._build_feishu_qa_analysis_packet_reply_text(packet) @pytest.mark.parametrize( ("case_name", "input_payload", "expected_fragments", "forbidden_fragments"), [ ( "project_fit_inventory_responses_api", { "route_decision": {"route_mode": "external", "effective_source_policy": "external"}, "execution_recipe": { "primary_lane": "external", "fit_brief_required": True, "external_evidence_required": True, "plan_handoff_mode": "offer_after_answer", }, "fit_brief": {"project_summary": "采购经理每日实时库存上报服务"}, "external_recommendation": { "retrieval_status": "evidence_found", "impact_status": "indirect_only", }, "recommended_next_step": "先确认它在当前项目里具体承接哪个节点。", "project_snapshot": { "project_name": "采购经理每日实时库存上报服务", "tasks": [ { "id": 1, "title": "每日固定时段生成并推送结构化摘要卡片", "description": "每日凌晨触发全量计算,生成含标题、总水位摘要、TOP10表格的结构化文本卡片,并在上午10点前推送。", }, { "id": 2, "title": "WMS库存快照自动拉取与清洗", "description": "从WMS系统每小时拉取库存快照,按可用/在途/冻结三态聚合,清洗异常值后写入中台临时表。", }, ], "signals": [ { "id": 11, "title": "外部信号源 - WMS实时库存接口", "summary": "提供各仓库每小时更新的库存快照,作为水位与缺货计算的原始数据源。", } ], "analysis_object_refs": { "fit_candidate_task_ref": {"kind": "task", "id": 1, "title": "每日固定时段生成并推送结构化摘要卡片"}, "fit_rejected_task_ref": {"kind": "task", "id": 2, "title": "WMS库存快照自动拉取与清洗"}, "primary_anchor_signal_ref": {"kind": "signal", "id": 11, "title": "外部信号源 - WMS实时库存接口"}, "primary_dependent_task_ref": {"kind": "task", "id": 2, "title": "WMS库存快照自动拉取与清洗"}, }, }, }, [ "每日固定时段生成并推送结构化摘要卡片", "WMS库存快照自动拉取与清洗", "先在这里试更稳", "先定清楚它是给每日固定时段生成并推送结构化摘要卡片补说明", ], ["当前项目:", "先说我的判断", "到底承担什么角色"], ), ( "project_fit_generic_titles_prefers_explicit_refs", { "route_decision": {"route_mode": "external", "effective_source_policy": "external"}, "execution_recipe": { "primary_lane": "external", "fit_brief_required": True, "external_evidence_required": True, "plan_handoff_mode": "offer_after_answer", }, "fit_brief": {"project_summary": "库存异常播报助手"}, "external_recommendation": { "retrieval_status": "evidence_found", "impact_status": "indirect_only", }, "recommended_next_step": "先确认它在项目里具体承接哪个节点。", "project_snapshot": { "project_name": "库存异常播报助手", "tasks": [ { "id": 21, "title": "任务A", "description": "每 15 分钟从仓储中台拉取异常库存快照,清洗后写入临时表供后续核算使用。", }, { "id": 22, "title": "任务B", "description": "根据前序结果生成发给值班同学的异常播报文本,并支持继续追问异常原因。", }, ], "analysis_object_refs": { "fit_candidate_task_ref": {"kind": "task", "id": 22, "title": "任务B"}, "fit_rejected_task_ref": {"kind": "task", "id": 21, "title": "任务A"}, }, }, }, ["任务B", "任务A", "异常播报文本", "先在这里试更稳"], ["status_summary", "外部推荐"], ), ( "project_fit_direct_match_inventory", { "route_decision": {"route_mode": "external", "effective_source_policy": "external"}, "execution_recipe": { "primary_lane": "external", "fit_brief_required": True, "external_evidence_required": True, "plan_handoff_mode": "offer_after_answer", }, "fit_brief": {"project_summary": "采购经理每日实时库存上报服务"}, "external_recommendation": { "retrieval_status": "evidence_found", "impact_status": "direct_match", "affected_signal_sources": ["外部信号源 - WMS实时库存接口"], }, "recommended_next_step": "直接看它会影响哪条下游任务,再决定要不要进 plan。", "project_snapshot": { "project_name": "采购经理每日实时库存上报服务", "tasks": [ { "id": 31, "title": "WMS库存快照自动拉取与清洗", "description": "从WMS系统每小时拉取库存快照,按可用/在途/冻结三态聚合,清洗异常值后写入中台临时表。", } ], "signals": [ { "id": 41, "title": "外部信号源 - WMS实时库存接口", "summary": "提供各仓库每小时更新的库存快照,作为水位与缺货计算的原始数据源。", } ], "analysis_object_refs": { "primary_anchor_signal_ref": {"kind": "signal", "id": 41, "title": "外部信号源 - WMS实时库存接口"}, "primary_dependent_task_ref": {"kind": "task", "id": 31, "title": "WMS库存快照自动拉取与清洗"}, }, }, }, ["WMS库存快照自动拉取与清洗", "外部信号源 - WMS实时库存接口"], ["当前项目:", "外部判断:"], ), ( "external_verifier_blocked_inventory", { "route_decision": {"route_mode": "external", "effective_source_policy": "external"}, "external_recommendation": { "retrieval_status": "verifier_blocked", "impact_status": "no_direct_impact", "external_action": "先修正证据质量,再决定是否继续外部推荐。", }, "recommended_next_step": "先修正证据质量,再决定是否继续外部推荐。", "project_snapshot": { "project_name": "Alpha", "tasks": [ { "id": 51, "title": "每日固定时段生成并推送结构化摘要卡片", "description": "每日凌晨触发全量计算,生成结构化文本卡片,并在上午10点前推送。", } ], "signals": [ { "id": 61, "title": "外部信号源 - WMS实时库存接口", "summary": "提供各仓库每小时更新的库存快照,作为水位与缺货计算的原始数据源。", } ], "analysis_object_refs": { "primary_anchor_signal_ref": {"kind": "signal", "id": 61, "title": "外部信号源 - WMS实时库存接口"}, "primary_dependent_task_ref": {"kind": "task", "id": 51, "title": "每日固定时段生成并推送结构化摘要卡片"}, }, }, }, ["外部信号源 - WMS实时库存接口", "每日固定时段生成并推送结构化摘要卡片", "核实清楚"], ["外部推荐", "证据质量"], ), ( "external_direct_match_inventory", { "route_decision": {"route_mode": "external", "effective_source_policy": "external"}, "external_recommendation": { "retrieval_status": "evidence_found", "impact_status": "direct_match", "affected_signal_sources": ["外部信号源 - WMS实时库存接口"], }, "recommended_next_step": "直接看它会影响哪条下游任务,再决定要不要进 plan。", "project_snapshot": { "project_name": "采购经理每日实时库存上报服务", "tasks": [ { "id": 71, "title": "WMS库存快照自动拉取与清洗", "description": "从WMS系统每小时拉取库存快照,按可用/在途/冻结三态聚合,清洗异常值后写入中台临时表。", } ], "signals": [ { "id": 72, "title": "外部信号源 - WMS实时库存接口", "summary": "提供各仓库每小时更新的库存快照,作为水位与缺货计算的原始数据源。", } ], "analysis_object_refs": { "primary_anchor_signal_ref": {"kind": "signal", "id": 72, "title": "外部信号源 - WMS实时库存接口"}, "primary_dependent_task_ref": {"kind": "task", "id": 71, "title": "WMS库存快照自动拉取与清洗"}, }, }, }, ["WMS库存快照自动拉取与清洗", "能对上的外部来源是外部信号源 - WMS实时库存接口", "不是泛泛相关"], ["status_summary", "当前项目:"], ), ( "external_indirect_only_prefers_explanation_layer", { "route_decision": {"route_mode": "external", "effective_source_policy": "external"}, "external_recommendation": { "retrieval_status": "evidence_found", "impact_status": "indirect_only", }, "recommended_next_step": "先确认它是不是只用在摘要卡片之后。", "project_snapshot": { "project_name": "采购经理每日实时库存上报服务", "tasks": [ { "id": 81, "title": "每日固定时段生成并推送结构化摘要卡片", "description": "每日凌晨触发全量计算,生成结构化文本卡片,并在上午10点前推送。", }, { "id": 82, "title": "WMS库存快照自动拉取与清洗", "description": "从WMS系统每小时拉取库存快照并写入中台临时表。", }, ], "analysis_object_refs": { "fit_candidate_task_ref": {"kind": "task", "id": 81, "title": "每日固定时段生成并推送结构化摘要卡片"}, "fit_rejected_task_ref": {"kind": "task", "id": 82, "title": "WMS库存快照自动拉取与清洗"}, }, }, }, ["背景相关", "每日固定时段生成并推送结构化摘要卡片", "WMS库存快照自动拉取与清洗"], ["先说我的判断", "外部判断:"], ), ( "internal_status_model_router", { "route_decision": {"route_mode": "internal", "effective_source_policy": "internal"}, "answer": "当前活动引擎是 Qwen 低阶引擎。", "query_type": "status", "evidence_pack": {"summary": {"conclusion": "当前活动引擎是 Qwen 低阶引擎。"}}, "internal_context_packet": { "operation_contract": {"query_type": "status", "answer_contract": "status_summary"}, "target_resolution": {"primary_target_label": "模型路由配置"}, "query_plan": {"answer_contract": "status_summary"}, }, }, ["当前活动引擎是 Qwen 低阶引擎", "模型路由配置", "当前情况回答"], ["status_summary", "泛化建议"], ), ( "internal_status_with_uncertainty", { "route_decision": {"route_mode": "internal", "effective_source_policy": "internal"}, "answer": "当前活动引擎是 Qwen 低阶引擎。", "query_type": "status", "evidence_pack": { "summary": { "conclusion": "当前活动引擎是 Qwen 低阶引擎。", "uncertainties": ["尚未确认是否已经切到最新灰度配置。"], } }, "internal_context_packet": { "operation_contract": {"query_type": "status", "answer_contract": "status_summary"}, "target_resolution": {"primary_target_label": "模型路由配置"}, "query_plan": {"answer_contract": "status_summary"}, }, }, ["当前活动引擎是 Qwen 低阶引擎", "模型路由配置", "先不展开方案"], ["status_summary", "contract"], ), ( "followup_route_clarify", { "route_decision": {"route_mode": "uncertain", "effective_source_policy": "uncertain"}, "answer": "你是想问外部公开事实,还是系统内部配置/项目对象?", "clarification_code": "query_route_clarify", "anchor_kind": "reply_thread", "meta_followup_kind": "route_selection", "evidence_pack": { "summary": { "conclusion": "需要先确认查询来源。", "uncertainties": ["内部还是外部"], } }, }, ["需要先确认查询来源"], ["当前项目:", "status_summary"], ), ( "feishu_render_fit_indirect", { "route_decision": {"route_mode": "external", "effective_source_policy": "external"}, "execution_recipe": { "primary_lane": "external", "fit_brief_required": True, "plan_handoff_mode": "offer_after_answer", }, "fit_brief": {"project_summary": "采购经理每日实时库存上报服务"}, "external_recommendation": {"retrieval_status": "evidence_found", "impact_status": "indirect_only"}, "recommended_next_step": "先确认它是不是只用在摘要卡片之后。", "project_snapshot": { "project_name": "采购经理每日实时库存上报服务", "tasks": [ { "id": 91, "title": "每日固定时段生成并推送结构化摘要卡片", "description": "每日凌晨触发全量计算,生成结构化文本卡片,并在上午10点前推送。", }, { "id": 92, "title": "WMS库存快照自动拉取与清洗", "description": "从WMS系统每小时拉取库存快照并写入中台临时表。", }, ], "analysis_object_refs": { "fit_candidate_task_ref": {"kind": "task", "id": 91, "title": "每日固定时段生成并推送结构化摘要卡片"}, "fit_rejected_task_ref": {"kind": "task", "id": 92, "title": "WMS库存快照自动拉取与清洗"}, }, }, }, ["每日固定时段生成并推送结构化摘要卡片", "WMS库存快照自动拉取与清洗"], ["当前项目:", "先说我的判断"], ), ( "feishu_render_verifier_blocked", { "route_decision": {"route_mode": "external", "effective_source_policy": "external"}, "external_recommendation": {"retrieval_status": "verifier_blocked", "impact_status": "no_direct_impact"}, "recommended_next_step": "先修正证据质量,再决定是否继续外部推荐。", "project_snapshot": { "project_name": "Alpha", "tasks": [ { "id": 101, "title": "每日固定时段生成并推送结构化摘要卡片", "description": "每日凌晨触发全量计算,生成结构化文本卡片,并在上午10点前推送。", } ], "signals": [ { "id": 102, "title": "外部信号源 - WMS实时库存接口", "summary": "提供各仓库每小时更新的库存快照,作为水位与缺货计算的原始数据源。", } ], "analysis_object_refs": { "primary_anchor_signal_ref": {"kind": "signal", "id": 102, "title": "外部信号源 - WMS实时库存接口"}, "primary_dependent_task_ref": {"kind": "task", "id": 101, "title": "每日固定时段生成并推送结构化摘要卡片"}, }, }, }, ["核实清楚", "每日固定时段生成并推送结构化摘要卡片"], ["外部推荐", "证据质量"], ), ( "feishu_render_internal_status", { "route_decision": {"route_mode": "internal", "effective_source_policy": "internal"}, "answer": "当前活动引擎是 Qwen 低阶引擎。", "query_type": "status", "evidence_pack": {"summary": {"conclusion": "当前活动引擎是 Qwen 低阶引擎。"}}, "internal_context_packet": { "operation_contract": {"query_type": "status", "answer_contract": "status_summary"}, "target_resolution": {"primary_target_label": "模型路由配置"}, "query_plan": {"answer_contract": "status_summary"}, }, }, ["当前活动引擎是 Qwen 低阶引擎", "模型路由配置"], ["status_summary", "泛化建议"], ), ], ) def test_analysis_packet_golden_v2_cases( case_name: str, input_payload: dict[str, object], expected_fragments: list[str], forbidden_fragments: list[str], ) -> None: _ = case_name packet = build_analysis_packet(**input_payload) assert packet["packet_type"] rendered = _render_text(packet) assert rendered for fragment in expected_fragments: assert fragment in rendered for fragment in forbidden_fragments: assert fragment not in rendered