from __future__ import annotations from typing import Any from .common import ( EventLoader, event_notices, event_unit, find_branch, find_raw_branch, find_raw_round, find_round, integer, load_events, ) from .schema import field, payload def project_round_summary( detail_ref: str, round_index: int, bundle: dict[str, Any], view: dict[str, Any], load_event: EventLoader, ) -> dict[str, Any]: round_ = find_round(view, round_index) raw_round = find_raw_round(bundle, round_index) if round_ is None or raw_round is None: raise KeyError(detail_ref) raw_branches = [ row for row in bundle.get("branches") or [] if integer(row.get("round_index")) == round_index ] decisions = [ row for row in bundle.get("multipathDecisions") or [] if integer(row.get("round_index")) == round_index ] evaluation = round_.get("overallEvaluation") or {} evaluation_ref = str(evaluation.get("detailRef") or "") evaluation_events = load_events( load_event, [evaluation_ref] if evaluation_ref.startswith("event:") else [], ) goal = field( f"round:{round_index}:summary:goal", "本轮目标", raw_round.get("goal"), source_kind="database", source_label="script_build_round", source_ref=detail_ref, field_path="goal", relation="standing-constraint", ) plan = field( f"round:{round_index}:summary:plan", "当前保存的规划", { "mode": raw_round.get("race_or_divide"), "paths": raw_round.get("multipath_plan"), "note": raw_round.get("plan_note"), }, source_kind="database", source_label="script_build_round", source_ref=detail_ref, field_path="multipath_plan", relation="persisted-output", ) branch_fields = [ field( f"round:{round_index}:summary:branch:{row.get('branch_id')}", f"候选方案 {row.get('branch_id')}", row, source_kind="database", source_label="script_build_branch", source_ref=f"round:{round_index}:branch:{row.get('branch_id')}", relation="persisted-output", ) for row in raw_branches ] decision_fields = [ field( f"round:{round_index}:summary:decision:{row.get('id')}", f"主 Agent 决策 {row.get('id')}", row, source_kind="database", source_label="script_build_multipath_decision", source_ref=f"multipath-decision:{row.get('id')}", relation="persisted-output", ) for row in decisions ] convergence = field( f"round:{round_index}:summary:convergence", "候选评审与主 Agent 决策", round_.get("convergenceBatches") or [], source_kind="calculation", source_label="按当前轮次的候选范围与明确关联记录汇总", source_ref=detail_ref, field_path="convergenceBatches", relation="persisted-output", completeness="complete", ) evaluation_field = field( f"round:{round_index}:summary:evaluation", "主脚本整体评审", evaluation_events[0] if evaluation_events else None, source_kind="runtime-event", source_label="主脚本整体评审运行事件", source_ref=evaluation_ref if evaluation_ref.startswith("event:") else None, relation="persisted-output", completeness="complete" if evaluation_events else "missing", ) result = field( f"round:{round_index}:summary:result", "本轮产出", round_.get("result"), source_kind="calculation", source_label="本轮业务记录确定性聚合", source_ref=detail_ref, field_path="result", relation="persisted-output", completeness="complete" if round_.get("result") else "missing", ) outputs = [ plan, *branch_fields, *decision_fields, convergence, evaluation_field, result, ] notices = event_notices(evaluation_events) if not evaluation_events: notices.append( { "level": "warning", "message": "本轮没有执行或保存主脚本整体评审运行事件。", } ) return payload( "round-summary", "aggregate", inputs=[goal], units=[event_unit(item) for item in evaluation_events], outputs=outputs, runtime_summary="按 round_index 聚合本轮目标、规划、候选分支、决策、整体评审和本轮产出。", calculation="只聚合当前轮次的结构化业务记录;缺失的整体评审保持缺失。", notices=notices, completeness="partial" if not evaluation_events else "complete", business_modules=[ {"id": "goal", "title": "本轮目标", "sourceIds": [goal["id"]]}, {"id": "plan", "title": "当前保存的规划", "sourceIds": [plan["id"]]}, {"id": "branches", "title": "候选方案", "sourceIds": [item["id"] for item in branch_fields]}, { "id": "decisions", "title": "候选评审与主 Agent 决策", "sourceIds": [ *[item["id"] for item in decision_fields], convergence["id"], ], }, {"id": "evaluation", "title": "主脚本整体评审", "sourceIds": [evaluation_field["id"]]}, {"id": "result", "title": "本轮产出", "sourceIds": [result["id"]]}, ], ) def project_branch_summary( detail_ref: str, round_index: int, branch_id: int, bundle: dict[str, Any], view: dict[str, Any], load_event: EventLoader, ) -> dict[str, Any]: branch = find_branch(view, round_index, branch_id) raw_branch = find_raw_branch(bundle, branch_id) if branch is None or raw_branch is None: raise KeyError(detail_ref) decisions = [ row for row in bundle.get("dataDecisions") or [] if integer(row.get("branch_id")) == branch_id and integer(row.get("round_index")) in {None, round_index} ] stage = branch.get("retrievalStage") or {} retrieval_refs: list[Any] = [] for group in stage.get("directToolGroups") or []: retrieval_refs.extend( item.get("eventId") for item in group.get("calls") or [] ) for agent_run in stage.get("agentRuns") or []: retrieval_refs.append(agent_run.get("eventId")) retrieval_refs.extend( item.get("eventId") for item in agent_run.get("attempts") or [] ) retrieval_events = load_events(load_event, retrieval_refs) task = field( f"branch:{branch_id}:summary:task", "实现任务", raw_branch.get("impl_task"), source_kind="database", source_label="script_build_branch", source_ref=detail_ref, field_path="impl_task", relation="direct-input", ) decision_fields = [ field( f"branch:{branch_id}:summary:decision:{row.get('id')}", f"数据取舍 {row.get('id')}", row, source_kind="database", source_label="script_build_data_decision", source_ref=f"data-decision:{row.get('id')}", relation="persisted-output", ) for row in decisions ] retrieval_fields = [ field( f"branch:{branch_id}:summary:retrieval:{event.get('id')}", str(event.get("event_name") or f"取数 Event {event.get('id')}"), event, source_kind="runtime-event", source_label=str(event.get("event_name") or "取数运行事件"), source_ref=f"event:{event.get('id')}", field_path="", relation="available-upstream", ) for event in retrieval_events ] output = field( f"branch:{branch_id}:summary:output", "候选产出", raw_branch, source_kind="database", source_label="script_build_branch", source_ref=detail_ref, relation="persisted-output", ) return payload( "branch-summary", "aggregate", inputs=[task], units=[event_unit(item) for item in retrieval_events], outputs=[*retrieval_fields, *decision_fields, output], runtime_summary="按 branch_id 聚合实现任务、取数、数据取舍和候选产出。", calculation="只使用当前方案的 Branch、明确 scope 取数 Event 与 DataDecision 记录。", completeness="complete", business_modules=[ {"id": "task", "title": "实现任务", "sourceIds": [task["id"]]}, { "id": "data", "title": "取数与数据取舍", "sourceIds": [ *[item["id"] for item in retrieval_fields], *[item["id"] for item in decision_fields], ], }, {"id": "output", "title": "候选产出", "sourceIds": [output["id"]]}, ], ) def project_missing_round_evaluation( detail_ref: str, round_index: int, bundle: dict[str, Any], view: dict[str, Any], ) -> dict[str, Any]: round_ = find_round(view, round_index) raw_round = find_raw_round(bundle, round_index) if round_ is None or raw_round is None: raise KeyError(detail_ref) evaluation = round_.get("overallEvaluation") or {} if str(evaluation.get("detailRef") or "").startswith("event:"): raise KeyError(detail_ref) missing = field( f"round:{round_index}:evaluation:missing", "记录状态", None, source_kind="runtime-event", source_label="script_evaluator Event", source_ref=None, relation="persisted-output", completeness="missing", ) return payload( "evaluation-missing", "missing", outputs=[missing], runtime_summary="本轮没有执行或保存主脚本整体评审运行事件。", notices=[ { "level": "warning", "message": "本轮没有执行或保存主脚本整体评审运行事件。", } ], completeness="missing", business_modules=[ {"id": "primary", "title": "记录状态", "sourceIds": [missing["id"]]} ], ) def project_missing_convergence( detail_ref: str, round_index: int, record_type: str, view: dict[str, Any], ) -> dict[str, Any]: round_ = find_round(view, round_index) if round_ is None: raise KeyError(detail_ref) found_node: dict[str, Any] | None = None found_batch: dict[str, Any] | None = None key = "missingReview" if record_type == "review" else "missingDecision" for batch in round_.get("convergenceBatches") or []: node = batch.get(key) if isinstance(node, dict) and detail_ref in { node.get("id"), node.get("detailRef"), }: found_node, found_batch = node, batch break if found_node is None or found_batch is None: raise KeyError(detail_ref) branch_ids = found_batch.get("branchIds") or [] unscoped_refs = found_node.get("unscopedReviewRefs") or [] status_value = ((found_node.get("card") or {}).get("primary") or {}).get("value") if unscoped_refs: source_kind = "calculation" source_label = "同轮评审未安全关联到具体候选" source_ref = detail_ref value: Any = { "roundIndex": round_index, "branchIds": branch_ids, "unscopedReviewRefs": unscoped_refs, } completeness = "partial" else: source_kind = "database" source_label = ( "script_multipath_evaluator Event 查询结果" if record_type == "review" else "script_build_multipath_decision 查询结果" ) source_ref = ( f"missing-convergence:{record_type}:round:{round_index}:" + ",".join(str(item) for item in branch_ids) ) value = [] completeness = "complete" status = field( f"{detail_ref}:status", "记录状态", status_value, source_kind=source_kind, source_label=source_label, source_ref=source_ref, relation="persisted-output", completeness=completeness, ) scope = field( f"{detail_ref}:scope", "实际查询范围", { "roundIndex": round_index, "branchIds": branch_ids, "resultCount": len(unscoped_refs), }, source_kind="calculation", source_label="可视化按当前轮次和候选范围确定", source_ref=detail_ref, field_path="value", relation="persisted-output", ) return payload( f"multipath-{record_type}-missing", "aggregate", outputs=[status, scope], runtime_summary=str(status_value or "未找到对应记录"), notices=( [{"level": "warning", "message": "存在同轮记录,但无法安全关联到具体候选。"}] if unscoped_refs else [{"level": "info", "message": "按当前轮次与候选范围查询完成,结果为空。"}] ), completeness=completeness, business_modules=[ {"id": "status", "title": "记录状态", "sourceIds": [status["id"], scope["id"]]} ], )