from app.schemas.project_operating_context import ExecutionRecipe, ProjectFitBrief, ProjectOperatingContext from app.services.ai_pmo.project_operating_context_builder import ProjectOperatingContextBuilder def test_project_operating_context_schema_contract() -> None: context = ProjectOperatingContext( current_project_id=17, current_repo_scope="pmflow-main", page_anchor={"project_id": 17, "origin": "pathname"}, thread_anchor={"reply_to_message_id": "om_xxx"}, ) assert context.context_version == "v1" assert context.current_project_id == 17 assert context.current_repo_scope == "pmflow-main" assert context.page_anchor["project_id"] == 17 assert context.thread_anchor["reply_to_message_id"] == "om_xxx" assert context.fit_scope == "current_project_and_repo" assert context.decision_strategy == "answer_then_offer_plan" def test_project_operating_context_builder_collects_project_repo_and_anchors() -> None: builder = ProjectOperatingContextBuilder(repo_scope="pmflow-main") context = builder.build( current_project_id=17, page_anchor={"project_id": 17, "origin": "rag_request_context"}, thread_anchor={"reply_to_message_id": "om_xxx", "root_message_id": "om_root"}, ) assert context.current_project_id == 17 assert context.current_repo_scope == "pmflow-main" assert context.page_anchor == {"project_id": 17, "origin": "rag_request_context"} assert context.thread_anchor == {"reply_to_message_id": "om_xxx", "root_message_id": "om_root"} assert context.fit_scope == "current_project_and_repo" assert context.decision_strategy == "answer_then_offer_plan" def test_execution_recipe_schema_contract() -> None: recipe = ExecutionRecipe( primary_lane="external", fit_brief_required=True, external_evidence_required=True, plan_handoff_mode="offer_after_answer", ) assert recipe.primary_lane == "external" assert recipe.fit_brief_required is True assert recipe.external_evidence_required is True assert recipe.plan_handoff_mode == "offer_after_answer" def test_project_fit_brief_schema_tracks_signal_source_objectives() -> None: fit_brief = ProjectFitBrief( project_summary="当前项目:#81 测试产能警告 (status=active)", signal_source_anchors=[], signal_source_objectives=[ "设计产能监控逻辑与数据采集:编写脚本收集测试队列与资源使用数据", "实现产能警告触发服务:实时比对数据与阈值", ], ) assert fit_brief.project_summary == "当前项目:#81 测试产能警告 (status=active)" assert fit_brief.signal_source_objectives == [ "设计产能监控逻辑与数据采集:编写脚本收集测试队列与资源使用数据", "实现产能警告触发服务:实时比对数据与阈值", ] def test_project_operating_context_builder_recovers_project_from_route_plan() -> None: builder = ProjectOperatingContextBuilder(repo_scope="pmflow-main") context = builder.build_from_ingress( project_hint_id=None, rag_request_context={ "pmflow_ai_route_plan": { "internal_plan": { "objects": ["project:141"], } } }, ) assert context.current_project_id == 141 assert context.page_anchor["project_id"] == 141 def test_project_operating_context_builder_prefers_active_workspace_primary_project() -> None: builder = ProjectOperatingContextBuilder(repo_scope="pmflow-main") context = builder.build_from_ingress( project_hint_id=None, rag_request_context={ "active_workspace": { "primary_object_ref": "project:141", "primary_object_id": 141, "primary_object_title": "童析—学龄前儿童行为特质AI评估助手", } }, ) assert context.current_project_id == 141 assert context.page_anchor["project_id"] == 141