From 7733ff31cf596b628a61efd361b7a6e162ae518a Mon Sep 17 00:00:00 2001 From: yumoqing Date: Fri, 4 Sep 2026 15:14:30 +0800 Subject: [PATCH] =?UTF-8?q?fix(flow):=20=E7=AD=89=E4=B8=8A=E6=B8=B8QC?= =?UTF-8?q?=E6=9C=AA=E8=BF=87=E7=9A=84=E7=BB=B4=E5=BA=A6=E4=B8=8D=E7=AE=97?= =?UTF-8?q?=E7=BC=96=E6=8E=92=E6=8E=89=E9=93=BE=E2=80=94=E2=80=94=E5=90=88?= =?UTF-8?q?=E6=B3=95=E7=AD=89=E5=BE=85=E8=BD=AE=E4=B8=8D=E5=86=8D=E7=A9=BA?= =?UTF-8?q?=E8=BD=AC=E7=83=A7orch=5Fdone(=E4=B8=AD=E7=94=B5=E6=96=B0?= =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E8=AF=AF=E6=8A=9B=E5=BE=85=E5=8A=9E=E6=A0=B9?= =?UTF-8?q?=E5=9B=A0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pipeline_bidding/bid_flow.py | 67 ++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 25 deletions(-) diff --git a/pipeline_bidding/bid_flow.py b/pipeline_bidding/bid_flow.py index fa6de46..80b6331 100644 --- a/pipeline_bidding/bid_flow.py +++ b/pipeline_bidding/bid_flow.py @@ -586,32 +586,49 @@ async def reconcile_project(sor, project_id, project_name=""): if await _open_orch_tasks(sor, project_id) > 0: acts.append("waiting: PM 解析编排任务在办") else: - _ft2 = _ft or await _latest_tender_file_ts(sor, project_id) - orch_done = await _orch_done_count(sor, project_id, since=_ft2 or '') - if orch_done >= MAX_ORCH_ATTEMPT: - ht = await find_human_task(sor, project_id, "general", status="pending") - if not ht: - await create_human_task( - sor, project_id, "general", - "PM 解析编排掉链,需人工介入", - ("解析阶段已完成 %d 次编排任务,仍有维度未启动/未过 QC:%s。\n" - "请人工核对编排任务卡点(任务列表,角色 agent.pm," - "参数 task_kind=analysis_orchestration)," - "或人工派发缺失维度。" - % (orch_done, "、".join(lb for _, lb in first_run_pending))), - assignee_role="owner.superuser") - await sor.sqlExe("COMMIT", {}) - acts.append("escalated: PM 解析编排掉链 → 人工介入") - else: - dims_brief = "、".join("%s(%s)" % (lb, d) for d, lb in first_run_pending) - tid = await create_role_task( - sor, project_id, R_PM, - "%s 解析编排:按任务链派发分析维度" % pname, - {"stage": "analysis_orchestration", - "task_kind": "analysis_orchestration", - "pending_dims": [d for d, _ in first_run_pending]}) - acts.append("created: PM 解析编排任务 %s(待派发维度:%s)" % (tid, dims_brief)) + # 2026-09-04 修复(中电新项目实测):上游 QC 未过的维度是合法等待, + # 不是「掉链」——PM 即使接到编排任务也派发不了(dispatch_analysis_dim + # 依赖门禁拒绝)。把这类维度留在 pending 会让编排任务空转(无可派发维度 + # 即完成),空转轮次计入 orch_done → MAX_ORCH_ATTEMPT 轮后误抛 + # 「PM 解析编排掉链」人工待办。只有真正可派发的维度才驱动编排/掉链计数。 + qc_passed = await _qc_passed_types(sor, project_id) + dispatchable, waiting_up = [], [] + for d, lb in first_run_pending: + up_ok = all(t in qc_passed + for u in DIM_UPSTREAM.get(d, ()) + for t in DIM_QC_TYPES[u]) + (dispatchable if up_ok else waiting_up).append((d, lb)) + if waiting_up: + acts.append("waiting: 维度「%s」等上游 QC 通过(合法等待,不计掉链)" + % "、".join(lb for _, lb in waiting_up)) + first_run_pending = dispatchable + if first_run_pending: + _ft2 = _ft or await _latest_tender_file_ts(sor, project_id) + orch_done = await _orch_done_count(sor, project_id, since=_ft2 or '') + if orch_done >= MAX_ORCH_ATTEMPT: + ht = await find_human_task(sor, project_id, "general", status="pending") + if not ht: + await create_human_task( + sor, project_id, "general", + "PM 解析编排掉链,需人工介入", + ("解析阶段已完成 %d 次编排任务,仍有维度未启动/未过 QC:%s。\n" + "请人工核对编排任务卡点(任务列表,角色 agent.pm," + "参数 task_kind=analysis_orchestration)," + "或人工派发缺失维度。" + % (orch_done, "、".join(lb for _, lb in first_run_pending))), + assignee_role="owner.superuser") await sor.sqlExe("COMMIT", {}) + acts.append("escalated: PM 解析编排掉链 → 人工介入") + else: + dims_brief = "、".join("%s(%s)" % (lb, d) for d, lb in first_run_pending) + tid = await create_role_task( + sor, project_id, R_PM, + "%s 解析编排:按任务链派发分析维度" % pname, + {"stage": "analysis_orchestration", + "task_kind": "analysis_orchestration", + "pending_dims": [d for d, _ in first_run_pending]}) + acts.append("created: PM 解析编排任务 %s(待派发维度:%s)" % (tid, dims_brief)) + await sor.sqlExe("COMMIT", {}) # ── A2. 分析产出 QC 门禁(五个类型逐一审核,每类一个审核任务并行;阈值见 bid_qc_pass_score)── # 2026-09-03 章节级门禁:本段只负责「推进 QC」(重做/审核/冒泡),不再提前 return