fix: make multica workflow path deterministic

This commit is contained in:
2026-06-13 14:25:05 +08:00
parent b3ce64881d
commit 1bc89446bc
2 changed files with 30 additions and 26 deletions
@@ -80,7 +80,7 @@
"initialized": false,
"position": {
"x": 160,
"y": -150
"y": 0
},
"data": {
"label": "需求分析",
@@ -95,8 +95,8 @@
"type": "template",
"initialized": false,
"position": {
"x": 160,
"y": 70
"x": 500,
"y": 0
},
"data": {
"label": "架构方案",
@@ -111,8 +111,8 @@
"type": "parallel",
"initialized": false,
"position": {
"x": 520,
"y": -40
"x": 840,
"y": 0
},
"data": {
"label": "并行实现分派",
@@ -299,31 +299,14 @@
"deletable": true
},
{
"id": "pm_triage-architecture_plan",
"type": "addButton",
"source": "pm_triage",
"target": "architecture_plan",
"data": {
"label": "澄清后设计方案"
},
"label": "澄清后设计方案",
"animated": false,
"style": {
"strokeWidth": 2,
"stroke": "#94a3b8"
},
"markerEnd": "arrowclosed",
"deletable": true
},
{
"id": "requirements_analysis-parallel_delivery",
"id": "requirements_analysis-architecture_plan",
"type": "addButton",
"source": "requirements_analysis",
"target": "parallel_delivery",
"target": "architecture_plan",
"data": {
"label": "需求输入"
"label": "需求输入架构"
},
"label": "需求输入",
"label": "需求输入架构",
"animated": false,
"style": {
"strokeWidth": 2,
@@ -353,6 +336,7 @@
"id": "parallel_delivery-frontend_delivery",
"type": "addButton",
"source": "parallel_delivery",
"sourceHandle": "frontend",
"target": "frontend_delivery",
"data": {
"label": "前端分支"
@@ -370,6 +354,7 @@
"id": "parallel_delivery-backend_delivery",
"type": "addButton",
"source": "parallel_delivery",
"sourceHandle": "backend",
"target": "backend_delivery",
"data": {
"label": "后端分支"
@@ -387,6 +372,7 @@
"id": "parallel_delivery-ops_prepare",
"type": "addButton",
"source": "parallel_delivery",
"sourceHandle": "ops",
"target": "ops_prepare",
"data": {
"label": "发布分支"
@@ -57,7 +57,16 @@ def validate_fixture(fixture: Dict[str, Any]) -> Dict[str, int]:
for node in nodes
if isinstance(node, dict) and (node.get("data") or {}).get("agent_code")
}
node_by_id = {node.get("id"): node for node in nodes if isinstance(node, dict)}
node_types = {node.get("type") for node in nodes}
outgoing_edges: Dict[str, list[str]] = {}
for edge in edges:
if not isinstance(edge, dict):
continue
source = edge.get("source")
target = edge.get("target")
if source and target:
outgoing_edges.setdefault(source, []).append(target)
required_persona_fields = {
"role",
@@ -67,6 +76,7 @@ def validate_fixture(fixture: Dict[str, Any]) -> Dict[str, int]:
"examples",
}
required_node_types = {"start", "end", "template", "parallel", "merge"}
multi_outgoing_node_types = {"parallel", "condition", "intent", "choice"}
missing_workflow_agents = sorted(workflow_agent_codes - agent_codes)
missing_persona_fields = {
@@ -75,6 +85,12 @@ def validate_fixture(fixture: Dict[str, Any]) -> Dict[str, int]:
if required_persona_fields - set((agent.get("persona") or {}).keys())
}
missing_node_types = sorted(required_node_types - node_types)
invalid_multi_outgoing = {
source: targets
for source, targets in outgoing_edges.items()
if len(targets) > 1
and (node_by_id.get(source) or {}).get("type") not in multi_outgoing_node_types
}
project_manager = next(
(agent for agent in agents if agent.get("code") == "project_manager"),
None,
@@ -84,12 +100,14 @@ def validate_fixture(fixture: Dict[str, Any]) -> Dict[str, int]:
missing_workflow_agents
or missing_persona_fields
or missing_node_types
or invalid_multi_outgoing
or project_manager_workflow != "multica_org_collaboration_flow"
):
raise ValueError(
f"Fixture validation failed: missing_workflow_agents={missing_workflow_agents}, "
f"missing_persona_fields={missing_persona_fields}, "
f"missing_node_types={missing_node_types}, "
f"invalid_multi_outgoing={invalid_multi_outgoing}, "
f"project_manager_workflow={project_manager_workflow}"
)