Source code for core.workflow_generator

"""
工作流生成器核心引擎

基于PRD和需求描述生成完整的实施工作流。
"""

import logging
import re
from datetime import datetime, timedelta
from pathlib import Path
from typing import Dict, List, Optional

from .workflow_effort_calculator import EffortCalculator, PhaseEffortDistributor
from .workflow_models import (
    AcceptanceCriteria,
    ComplexityAnalysis,
    ComplexityLevel,
    CriticalPath,
    Dependency,
    EffortEstimation,
    MCPResults,
    ParallelStream,
    PersonaType,
    PRDStructure,
    Priority,
    Requirement,
    RequirementCategories,
    Risk,
    RiskLevel,
    Workflow,
    WorkflowMilestone,
    WorkflowOptions,
    WorkflowPhase,
    WorkflowStrategy,
)


[docs] class PRDParser: """PRD文档解析器"""
[docs] def __init__(self) -> None: self.logger = logging.getLogger("PRDParser")
[docs] async def parse_document(self, file_path: str) -> PRDStructure: """解析PRD文档文件""" try: source_path = Path(file_path) if not source_path.exists(): raise FileNotFoundError(f"PRD文档不存在: {file_path}") content = source_path.read_text(encoding="utf-8") return self.parse_content(content, source_path.name) except Exception as e: self.logger.error(f"解析PRD文档失败: {str(e)}") raise
[docs] def parse_content(self, content: str, source_name: str = "text_input") -> PRDStructure: """解析PRD文档内容""" try: prd = PRDStructure() # 提取标题 title_match = re.search(r"^#\s+(.+)$", content, re.MULTILINE) if title_match: prd.title = title_match.group(1).strip() else: prd.title = source_name # 提取概述 overview_match = re.search( r"(?:## 概述|## Overview|## 简介)(.*?)(?=##|$)", content, re.DOTALL | re.IGNORECASE ) if overview_match: prd.overview = overview_match.group(1).strip() # 提取目标 objectives = self._extract_list_items(content, ["目标", "objectives", "项目目标"]) prd.objectives = objectives # 提取需求 requirements = self._extract_requirements(content) prd.requirements = requirements # 提取验收标准 acceptance_criteria = self._extract_acceptance_criteria(content, requirements) prd.acceptance_criteria = acceptance_criteria # 提取约束 constraints = self._extract_list_items(content, ["约束", "constraints", "限制"]) prd.constraints = constraints # 提取假设 assumptions = self._extract_list_items(content, ["假设", "assumptions"]) prd.assumptions = assumptions # 提取成功指标 success_metrics = self._extract_list_items(content, ["成功指标", "success metrics", "kpi"]) prd.success_metrics = success_metrics prd.date_created = datetime.now() prd.metadata = {"source": source_name, "parsing_method": "regex"} self.logger.info(f"成功解析PRD: {len(requirements)}个需求, {len(acceptance_criteria)}个验收标准") return prd except Exception as e: self.logger.error(f"解析PRD内容失败: {str(e)}") raise
[docs] def parse_text_description(self, description: str) -> PRDStructure: """解析简单文本描述为PRD结构""" try: prd = PRDStructure() prd.title = "文本描述需求" prd.overview = description prd.date_created = datetime.now() # 从描述中提取需求 sentences = [s.strip() for s in description.split(".") if s.strip()] requirements = [] for i, sentence in enumerate(sentences[:5]): # 最多5个需求 if len(sentence) > 10: # 过滤太短的句子 req = Requirement( title=f"需求 {i+1}", description=sentence, priority=Priority.MEDIUM, complexity=self._estimate_sentence_complexity(sentence), ) requirements.append(req) prd.requirements = requirements prd.metadata = {"source": "text_description", "auto_generated": True} self.logger.info(f"从文本描述生成 {len(requirements)} 个需求") return prd except Exception as e: self.logger.error(f"解析文本描述失败: {str(e)}") raise
def _extract_requirements(self, content: str) -> List[Requirement]: """提取功能需求""" requirements = [] # 查找需求章节 sections = ["需求", "requirements", "功能需求", "functional requirements"] for section in sections: pattern = rf"(?:## {section}|### {section})(.*?)(?=##|$)" match = re.search(pattern, content, re.DOTALL | re.IGNORECASE) if match: section_content = match.group(1) break else: # 如果没找到专门的需求章节,从整个文档提取 section_content = content # 提取编号列表项 list_items = re.findall( r"(?:^|\n)(?:\d+\.|\-|\*)\s+(.+?)(?=\n(?:\d+\.|\-|\*)|$)", section_content, re.MULTILINE | re.DOTALL ) for i, item in enumerate(list_items): if len(item.strip()) > 5: # 过滤太短的项目 req = Requirement( title=f"需求 {i+1}", description=item.strip(), priority=self._extract_priority(item), complexity=self._estimate_requirement_complexity(item), ) requirements.append(req) # 如果没有找到列表项,尝试提取段落作为需求 if not requirements: paragraphs = [p.strip() for p in section_content.split("\n\n") if p.strip()] for i, para in enumerate(paragraphs[:3]): # 最多3个段落 if len(para) > 20: req = Requirement(title=f"需求 {i+1}", description=para, priority=Priority.MEDIUM) requirements.append(req) return requirements def _extract_acceptance_criteria(self, content: str, requirements: List[Requirement]) -> List[AcceptanceCriteria]: """提取验收标准""" criteria = [] # 查找验收标准章节 sections = ["验收标准", "acceptance criteria", "验收条件"] for section in sections: pattern = rf"(?:## {section}|### {section})(.*?)(?=##|$)" match = re.search(pattern, content, re.DOTALL | re.IGNORECASE) if match: section_content = match.group(1) # 提取列表项作为验收标准 list_items = re.findall( r"(?:^|\n)(?:\-|\*)\s+(.+?)(?=\n(?:\-|\*)|$)", section_content, re.MULTILINE | re.DOTALL ) for item in list_items: if len(item.strip()) > 5: ac = AcceptanceCriteria( description=item.strip(), is_testable=self._is_testable(item), test_method=self._determine_test_method(item), ) # 尝试关联到相关需求 if requirements: ac.requirement_id = requirements[0].id # 简化关联逻辑 criteria.append(ac) break return criteria def _extract_list_items(self, content: str, keywords: List[str]) -> List[str]: """提取指定关键词的列表项""" items = [] for keyword in keywords: pattern = rf"(?:## {keyword}|### {keyword})(.*?)(?=##|$)" match = re.search(pattern, content, re.DOTALL | re.IGNORECASE) if match: section_content = match.group(1) list_items = re.findall( r"(?:^|\n)(?:\d+\.|\-|\*)\s+(.+?)(?=\n(?:\d+\.|\-|\*)|$)", section_content, re.MULTILINE | re.DOTALL ) items.extend([item.strip() for item in list_items if len(item.strip()) > 3]) break return items def _extract_priority(self, text: str) -> Priority: """从文本中提取优先级""" text_lower = text.lower() if any(word in text_lower for word in ["高优先级", "high", "critical", "紧急", "关键"]): return Priority.HIGH elif any(word in text_lower for word in ["低优先级", "low", "可选", "optional"]): return Priority.LOW else: return Priority.MEDIUM def _estimate_requirement_complexity(self, text: str) -> ComplexityLevel: """估算需求复杂度""" text_lower = text.lower() complexity_indicators = { "simple": ["简单", "基础", "simple", "basic", "显示", "展示"], "complex": [ "复杂", "集成", "算法", "安全", "性能", "complex", "integration", "algorithm", "security", "performance", ], "enterprise": ["企业级", "分布式", "高可用", "大规模", "enterprise", "distributed", "scalable"], } if any(word in text_lower for word in complexity_indicators["enterprise"]): return ComplexityLevel.ENTERPRISE elif any(word in text_lower for word in complexity_indicators["complex"]): return ComplexityLevel.COMPLEX elif any(word in text_lower for word in complexity_indicators["simple"]): return ComplexityLevel.SIMPLE else: return ComplexityLevel.MEDIUM def _estimate_sentence_complexity(self, sentence: str) -> ComplexityLevel: """基于句子长度和内容估算复杂度""" if len(sentence) < 20: return ComplexityLevel.SIMPLE elif len(sentence) > 100: return ComplexityLevel.COMPLEX else: return ComplexityLevel.MEDIUM def _is_testable(self, criteria: str) -> bool: """判断验收标准是否可测试""" testable_indicators = ["能够", "可以", "应该", "验证", "测试", "should", "can", "able to", "verify"] return any(indicator in criteria.lower() for indicator in testable_indicators) def _determine_test_method(self, criteria: str) -> str: """确定测试方法""" if any(word in criteria.lower() for word in ["自动", "automatic", "api", "接口"]): return "automated" elif any(word in criteria.lower() for word in ["集成", "integration", "端到端"]): return "integration" else: return "manual"
[docs] class RequirementAnalyzer: """需求分析器"""
[docs] def __init__(self) -> None: self.logger = logging.getLogger("RequirementAnalyzer")
[docs] def analyze_complexity(self, requirements: List[Requirement]) -> ComplexityAnalysis: """分析需求复杂度""" try: if not requirements: return ComplexityAnalysis() # 统计各复杂度级别的需求数量 complexity_counts = {level: 0 for level in ComplexityLevel} for req in requirements: complexity_counts[req.complexity] += 1 total_reqs = len(requirements) # 计算加权平均复杂度 complexity_weights = { ComplexityLevel.SIMPLE: 0.2, ComplexityLevel.MEDIUM: 0.5, ComplexityLevel.COMPLEX: 0.8, ComplexityLevel.ENTERPRISE: 1.0, } weighted_sum = sum(complexity_counts[level] * complexity_weights[level] for level in ComplexityLevel) average_complexity = weighted_sum / total_reqs if total_reqs > 0 else 0.5 # 确定整体复杂度级别 if average_complexity < 0.3: overall_complexity = ComplexityLevel.SIMPLE elif average_complexity < 0.6: overall_complexity = ComplexityLevel.MEDIUM elif average_complexity < 0.9: overall_complexity = ComplexityLevel.COMPLEX else: overall_complexity = ComplexityLevel.ENTERPRISE complexity_factors = self._complexity_factors(complexity_counts, total_reqs) # 识别简化机会 simplification_opportunities = [] if complexity_counts[ComplexityLevel.COMPLEX] > 0: simplification_opportunities.append("考虑将复杂需求分解为更小的需求") if total_reqs > 15: simplification_opportunities.append("考虑采用MVP策略,分阶段实施") analysis = ComplexityAnalysis( overall_complexity=overall_complexity, technical_complexity=average_complexity, integration_complexity=self._analyze_integration_complexity(requirements), ui_complexity=self._analyze_ui_complexity(requirements), business_logic_complexity=self._analyze_business_logic_complexity(requirements), data_complexity=self._analyze_data_complexity(requirements), complexity_factors=complexity_factors, simplification_opportunities=simplification_opportunities, ) self.logger.info(f"复杂度分析完成: {overall_complexity.value}, 技术复杂度: {average_complexity:.2f}") return analysis except Exception as e: self.logger.error(f"复杂度分析失败: {str(e)}") return ComplexityAnalysis()
def _complexity_factors(self, counts: Dict[ComplexityLevel, int], total: int) -> List[str]: factors = [] if counts[ComplexityLevel.ENTERPRISE] > 0: factors.append("包含企业级需求") if counts[ComplexityLevel.COMPLEX] > total * 0.5: factors.append("复杂需求占比过半") if total > 20: factors.append("需求数量较多") return factors
[docs] def categorize_requirements(self, requirements: List[Requirement]) -> RequirementCategories: """需求分类""" try: categories = RequirementCategories() for req in requirements: desc_lower = req.description.lower() # 基于描述内容进行分类 if req.type == "functional" or self._is_functional_requirement(desc_lower): categories.functional_requirements.append(req) elif req.type == "non-functional" or self._is_non_functional_requirement(desc_lower): categories.non_functional_requirements.append(req) elif req.type == "constraint": categories.constraint_requirements.append(req) self._categorize_details(req, desc_lower, categories) self.logger.info( f"需求分类完成: 功能性({len(categories.functional_requirements)})," f"非功能性({len(categories.non_functional_requirements)})," f"约束性({len(categories.constraint_requirements)})" ) return categories except Exception as e: self.logger.error(f"需求分类失败: {str(e)}") return RequirementCategories()
def _categorize_details(self, req: Requirement, description: str, categories: RequirementCategories) -> None: if self._is_ui_requirement(description): categories.ui_requirements.append(req) if self._is_api_requirement(description): categories.api_requirements.append(req) if self._is_data_requirement(description): categories.data_requirements.append(req) if self._is_security_requirement(description): categories.security_requirements.append(req) if self._is_performance_requirement(description): categories.performance_requirements.append(req)
[docs] def estimate_effort(self, requirements: List[Requirement]) -> EffortEstimation: """工作量评估""" try: if not requirements: return EffortEstimation() # 基于复杂度的基础工作量估算 complexity_hours = { ComplexityLevel.SIMPLE: 4, # 4小时 ComplexityLevel.MEDIUM: 12, # 1.5天 ComplexityLevel.COMPLEX: 32, # 4天 ComplexityLevel.ENTERPRISE: 80, # 10天 } total_hours = 0.0 breakdown_by_persona: Dict[PersonaType, float] = {} for req in requirements: base_hours = complexity_hours.get(req.complexity, 12) # 根据需求类型调整估算 if self._is_ui_requirement(req.description.lower()): hours = base_hours * 1.2 # UI需求增加20% persona = PersonaType.FRONTEND elif self._is_api_requirement(req.description.lower()): hours = base_hours * 1.1 # API需求增加10% persona = PersonaType.BACKEND elif self._is_security_requirement(req.description.lower()): hours = base_hours * 1.5 # 安全需求增加50% persona = PersonaType.SECURITY else: hours = float(base_hours) persona = PersonaType.BACKEND # 默认后端 total_hours += hours if persona not in breakdown_by_persona: breakdown_by_persona[persona] = 0 breakdown_by_persona[persona] += hours # 添加20%的缓冲 buffered_hours = int(total_hours * 1.2) estimation = EffortEstimation( total_hours=buffered_hours, breakdown_by_persona=breakdown_by_persona, confidence_level=0.7, # 中等置信度 estimation_method="complexity_based", buffer_percentage=0.2, ) self.logger.info(f"工作量评估完成: {buffered_hours}小时 (包含20%缓冲)") return estimation except Exception as e: self.logger.error(f"工作量评估失败: {str(e)}") return EffortEstimation()
def _analyze_integration_complexity(self, requirements: List[Requirement]) -> float: """分析集成复杂度""" integration_keywords = ["集成", "对接", "同步", "integration", "api", "第三方"] integration_reqs = [ req for req in requirements if any(keyword in req.description.lower() for keyword in integration_keywords) ] return min(len(integration_reqs) / len(requirements) * 2, 1.0) if requirements else 0.0 def _analyze_ui_complexity(self, requirements: List[Requirement]) -> float: """分析UI复杂度""" ui_keywords = ["界面", "页面", "组件", "ui", "前端", "交互", "用户体验"] ui_reqs = [req for req in requirements if any(keyword in req.description.lower() for keyword in ui_keywords)] return min(len(ui_reqs) / len(requirements) * 1.5, 1.0) if requirements else 0.0 def _analyze_business_logic_complexity(self, requirements: List[Requirement]) -> float: """分析业务逻辑复杂度""" logic_keywords = ["业务逻辑", "规则", "流程", "算法", "logic", "rule", "process"] logic_reqs = [ req for req in requirements if any(keyword in req.description.lower() for keyword in logic_keywords) ] return min(len(logic_reqs) / len(requirements) * 1.8, 1.0) if requirements else 0.0 def _analyze_data_complexity(self, requirements: List[Requirement]) -> float: """分析数据复杂度""" data_keywords = ["数据", "存储", "数据库", "data", "database", "模型"] data_reqs = [ req for req in requirements if any(keyword in req.description.lower() for keyword in data_keywords) ] return min(len(data_reqs) / len(requirements) * 1.3, 1.0) if requirements else 0.0 def _is_functional_requirement(self, desc: str) -> bool: """判断是否为功能性需求""" functional_keywords = ["实现", "功能", "能够", "可以", "支持", "feature", "function"] return any(keyword in desc for keyword in functional_keywords) def _is_non_functional_requirement(self, desc: str) -> bool: """判断是否为非功能性需求""" non_functional_keywords = ["性能", "安全", "可用性", "扩展性", "performance", "security", "scalability"] return any(keyword in desc for keyword in non_functional_keywords) def _is_ui_requirement(self, desc: str) -> bool: """判断是否为UI需求""" ui_keywords = ["界面", "页面", "组件", "ui", "前端", "用户界面", "交互"] return any(keyword in desc for keyword in ui_keywords) def _is_api_requirement(self, desc: str) -> bool: """判断是否为API需求""" api_keywords = ["api", "接口", "服务", "端点", "endpoint", "service"] return any(keyword in desc for keyword in api_keywords) def _is_data_requirement(self, desc: str) -> bool: """判断是否为数据需求""" data_keywords = ["数据", "存储", "数据库", "模型", "data", "database", "model"] return any(keyword in desc for keyword in data_keywords) def _is_security_requirement(self, desc: str) -> bool: """判断是否为安全需求""" security_keywords = ["安全", "认证", "授权", "加密", "security", "auth", "encryption"] return any(keyword in desc for keyword in security_keywords) def _is_performance_requirement(self, desc: str) -> bool: """判断是否为性能需求""" performance_keywords = ["性能", "速度", "响应时间", "吞吐量", "performance", "speed", "latency"] return any(keyword in desc for keyword in performance_keywords)
[docs] class WorkflowGenerator: """工作流生成器核心引擎"""
[docs] def __init__(self) -> None: self.logger = logging.getLogger("WorkflowGenerator") self.prd_parser = PRDParser() self.requirement_analyzer = RequirementAnalyzer() self.effort_calculator = EffortCalculator() self.phase_distributor = PhaseEffortDistributor()
[docs] async def generate_workflow(self, input_source: str, options: Optional[WorkflowOptions] = None) -> Workflow: """生成完整工作流""" try: if options is None: options = WorkflowOptions() self.logger.info(f"开始生成工作流: {options.strategy.value} 策略") # 1. 解析输入源 prd_structure = await self._parse_input_source(input_source) # 2. 分析需求 complexity_analysis = self.requirement_analyzer.analyze_complexity(prd_structure.requirements) requirement_categories = self.requirement_analyzer.categorize_requirements(prd_structure.requirements) effort_estimation = self.requirement_analyzer.estimate_effort(prd_structure.requirements) # 3. 创建基础工作流对象 workflow = Workflow( name=prd_structure.title or "工作流", description=prd_structure.overview or "自动生成的工作流", strategy=options.strategy, prd_structure=prd_structure, requirements=prd_structure.requirements, complexity_analysis=complexity_analysis, requirement_categories=requirement_categories, effort_estimation=effort_estimation, ) # 4. 根据策略生成工作流阶段 phases = await self._generate_phases(workflow, options) workflow.phases = phases # 5. 分析依赖关系 if options.include_dependencies: dependencies = await self._analyze_dependencies(workflow) workflow.dependencies = dependencies # 6. 评估风险 if options.include_risks: risks = await self._assess_risks(workflow) workflow.risks = risks # 7. 识别并行流 if options.enable_parallel_analysis: parallel_streams = await self._identify_parallel_streams(workflow) workflow.parallel_streams = parallel_streams critical_path = await self._calculate_critical_path(workflow) workflow.critical_path = critical_path # 8. 激活专家人格 activated_personas = await self._activate_personas(workflow, options) workflow.activated_personas = activated_personas # 9. MCP集成(如果启用) if options.enable_mcp_integration: mcp_results = await self._integrate_mcp_services(workflow, options) workflow.mcp_results = mcp_results workflow.updated_at = datetime.now() self.logger.info( f"工作流生成完成: {len(phases)}个阶段, " f"{workflow.get_total_effort()}小时, " f"复杂度: {complexity_analysis.overall_complexity.value}" ) return workflow except Exception as e: self.logger.error(f"生成工作流失败: {str(e)}") raise
async def _parse_input_source(self, input_source: str) -> PRDStructure: """解析输入源""" try: # 检查是否是文件路径 if Path(input_source).exists(): return await self.prd_parser.parse_document(input_source) else: # 作为文本描述处理 return self.prd_parser.parse_text_description(input_source) except Exception as e: self.logger.error(f"解析输入源失败: {str(e)}") raise async def _generate_phases(self, workflow: Workflow, options: WorkflowOptions) -> List[WorkflowPhase]: """根据策略生成工作流阶段""" try: if options.strategy == WorkflowStrategy.SYSTEMATIC: return await self._generate_systematic_phases(workflow, options) elif options.strategy == WorkflowStrategy.AGILE: return await self._generate_agile_phases(workflow, options) elif options.strategy == WorkflowStrategy.MVP: return await self._generate_mvp_phases(workflow, options) else: raise ValueError(f"不支持的工作流策略: {options.strategy}") except Exception as e: self.logger.error(f"生成工作流阶段失败: {str(e)}") raise async def _generate_systematic_phases(self, workflow: Workflow, options: WorkflowOptions) -> List[WorkflowPhase]: """生成系统化策略的阶段 - 修复循环依赖问题""" try: # 1. 使用独立的工作量计算器获取基础工作量 base_effort = self.effort_calculator.calculate_base_effort( workflow.requirements, WorkflowStrategy.SYSTEMATIC ) # 2. 使用阶段分配器获取各阶段工作量 phase_efforts = self.phase_distributor.distribute_effort_to_phases(base_effort, WorkflowStrategy.SYSTEMATIC) # 3. 生成阶段 phases = [] phase1 = WorkflowPhase( name="需求分析", description="深入分析PRD结构和验收标准", order=1, estimated_effort=phase_efforts.get("需求分析", int(base_effort * 0.15)), ) phases.append(phase1) phase2 = WorkflowPhase( name="架构设计", description="系统设计和组件架构规划", order=2, estimated_effort=phase_efforts.get("架构设计", int(base_effort * 0.20)), ) phases.append(phase2) phase3 = WorkflowPhase( name="依赖映射", description="识别所有内部和外部依赖关系", order=3, estimated_effort=phase_efforts.get("依赖映射", int(base_effort * 0.10)), ) phases.append(phase3) phase4 = WorkflowPhase( name="核心开发", description="按序实施各功能模块", order=4, estimated_effort=phase_efforts.get("核心开发", int(base_effort * 0.35)), ) phases.append(phase4) phase5 = WorkflowPhase( name="测试验证", description="全面测试和质量保证", order=5, estimated_effort=phase_efforts.get("测试验证", int(base_effort * 0.15)), ) phases.append(phase5) phase6 = WorkflowPhase( name="部署上线", description="生产部署和监控策略", order=6, estimated_effort=phase_efforts.get("部署上线", int(base_effort * 0.05)), ) phases.append(phase6) # 为每个阶段生成里程碑 if options.enable_milestones: for phase in phases: phase.milestones = await self._generate_phase_milestones(phase, workflow, options) self.logger.info(f"系统化策略生成 {len(phases)} 个阶段,总工作量 {base_effort}h") return phases except Exception as e: self.logger.error(f"生成系统化阶段失败: {str(e)}") raise async def _generate_agile_phases(self, workflow: Workflow, options: WorkflowOptions) -> List[WorkflowPhase]: """生成敏捷策略的阶段 - 修复循环依赖问题""" try: # 1. 使用独立工作量计算 base_effort = self.effort_calculator.calculate_base_effort(workflow.requirements, WorkflowStrategy.AGILE) # 2. 获取阶段分配 phase_efforts = self.phase_distributor.distribute_effort_to_phases(base_effort, WorkflowStrategy.AGILE) phases = [] # 阶段1: Epic分解 phase1 = WorkflowPhase( name="Epic分解", description="将PRD转换为用户故事和Epic", order=1, estimated_effort=phase_efforts.get("Epic分解", int(base_effort * 0.10)), ) phases.append(phase1) # 阶段2: Sprint规划 phase2 = WorkflowPhase( name="Sprint规划", description="组织工作为迭代Sprint", order=2, estimated_effort=phase_efforts.get("Sprint规划", int(base_effort * 0.05)), ) phases.append(phase2) # 阶段3: MVP定义 phase3 = WorkflowPhase( name="MVP定义", description="识别最小可行产品范围", order=3, estimated_effort=phase_efforts.get("MVP定义", int(base_effort * 0.15)), ) phases.append(phase3) # 阶段4: 迭代开发 phase4 = WorkflowPhase( name="迭代开发", description="敏捷迭代开发和交付", order=4, estimated_effort=phase_efforts.get("迭代开发", int(base_effort * 0.50)), ) phases.append(phase4) # 阶段5: 持续集成 phase5 = WorkflowPhase( name="持续集成", description="CI/CD流程和自动化测试", order=5, estimated_effort=phase_efforts.get("持续集成", int(base_effort * 0.15)), ) phases.append(phase5) # 阶段6: 回顾优化 phase6 = WorkflowPhase( name="回顾优化", description="项目回顾和持续改进", order=6, estimated_effort=phase_efforts.get("回顾优化", int(base_effort * 0.05)), ) phases.append(phase6) # 为每个阶段生成里程碑 if options.enable_milestones: for phase in phases: phase.milestones = await self._generate_phase_milestones(phase, workflow, options) self.logger.info(f"敏捷策略生成 {len(phases)} 个阶段,总工作量 {base_effort}h") return phases except Exception as e: self.logger.error(f"生成敏捷阶段失败: {str(e)}") raise async def _generate_mvp_phases(self, workflow: Workflow, options: WorkflowOptions) -> List[WorkflowPhase]: """生成MVP策略的阶段 - 修复循环依赖问题""" try: # 1. 使用独立工作量计算 base_effort = self.effort_calculator.calculate_base_effort(workflow.requirements, WorkflowStrategy.MVP) # 2. 获取阶段分配 phase_efforts = self.phase_distributor.distribute_effort_to_phases(base_effort, WorkflowStrategy.MVP) phases = [] # 阶段1: 核心功能识别 phase1 = WorkflowPhase( name="核心功能识别", description="精简到基本功能", order=1, estimated_effort=phase_efforts.get("核心功能识别", int(base_effort * 0.20)), ) phases.append(phase1) # 阶段2: 快速原型 phase2 = WorkflowPhase( name="快速原型", description="快速验证和反馈", order=2, estimated_effort=phase_efforts.get("快速原型", int(base_effort * 0.35)), ) phases.append(phase2) # 阶段3: 技术债务规划 phase3 = WorkflowPhase( name="技术债务规划", description="识别和规划技术债务", order=3, estimated_effort=phase_efforts.get("技术债务规划", int(base_effort * 0.10)), ) phases.append(phase3) # 阶段4: 验证指标 phase4 = WorkflowPhase( name="验证指标", description="设定和测量成功指标", order=4, estimated_effort=phase_efforts.get("验证指标", int(base_effort * 0.15)), ) phases.append(phase4) # 阶段5: 扩展路线图 phase5 = WorkflowPhase( name="扩展路线图", description="为下一阶段制定计划", order=5, estimated_effort=phase_efforts.get("扩展路线图", int(base_effort * 0.15)), ) phases.append(phase5) # 阶段6: 反馈集成 phase6 = WorkflowPhase( name="反馈集成", description="整合用户反馈到产品中", order=6, estimated_effort=phase_efforts.get("反馈集成", int(base_effort * 0.05)), ) phases.append(phase6) # 为每个阶段生成里程碑 if options.enable_milestones: for phase in phases: phase.milestones = await self._generate_phase_milestones(phase, workflow, options) self.logger.info(f"MVP策略生成 {len(phases)} 个阶段,总工作量 {base_effort}h") return phases except Exception as e: self.logger.error(f"生成MVP阶段失败: {str(e)}") raise async def _generate_phase_milestones( self, phase: WorkflowPhase, workflow: Workflow, options: WorkflowOptions ) -> List[WorkflowMilestone]: """为阶段生成里程碑""" # 这里简化实现,实际应该根据具体阶段内容生成详细的里程碑 milestones = [] if phase.estimated_effort is None: raise ValueError("Phase effort is required to generate milestone estimates") milestone_count = max(2, min(5, phase.estimated_effort // 8)) # 每8小时一个里程碑 effort_per_milestone = phase.estimated_effort // milestone_count for i in range(milestone_count): milestone = WorkflowMilestone( name=f"{phase.name} - 里程碑 {i+1}", description=f"{phase.name}阶段的第{i+1}个关键节点", estimated_effort=effort_per_milestone, priority=Priority.MEDIUM, order=i + 1, ) milestones.append(milestone) return milestones async def _analyze_dependencies(self, workflow: Workflow) -> List[Dependency]: """分析依赖关系""" # 简化实现 - 实际应该分析需求间的依赖关系 dependencies = [] # 基于需求描述识别外部依赖 for req in workflow.requirements: desc = req.description.lower() if any(keyword in desc for keyword in ["第三方", "api", "集成", "外部"]): dep = Dependency( name=f"外部依赖 - {req.title}", type="external", description=f"需求 {req.title} 涉及的外部依赖", criticality=req.priority, ) dependencies.append(dep) return dependencies async def _assess_risks(self, workflow: Workflow) -> List[Risk]: """评估风险""" risks = [] # 基于复杂度评估技术风险 if workflow.complexity_analysis: if workflow.complexity_analysis.overall_complexity == ComplexityLevel.ENTERPRISE: risk = Risk( name="技术复杂度风险", description="项目技术复杂度较高,可能遇到技术挑战", category="technical", likelihood=RiskLevel.HIGH, impact=RiskLevel.HIGH, mitigation_strategies=["增加技术调研时间", "引入专家顾问", "制定技术方案备选"], ) risks.append(risk) # 基于工作量评估时间风险 if workflow.effort_estimation and workflow.effort_estimation.total_hours > 200: risk = Risk( name="项目时间风险", description="项目工作量较大,存在延期风险", category="timeline", likelihood=RiskLevel.MEDIUM, impact=RiskLevel.HIGH, mitigation_strategies=["分阶段交付", "增加人员", "并行开发"], ) risks.append(risk) return risks async def _identify_parallel_streams(self, workflow: Workflow) -> List[ParallelStream]: """识别并行工作流""" # 简化实现 - 基于人格类型识别可并行的工作 streams = [] if len(workflow.phases) > 2: # 前端和后端可以并行开发 frontend_stream = ParallelStream( name="前端开发流", description="UI相关的并行开发流", phases=[phase.id for phase in workflow.phases[1:3]], # 架构设计后可以开始 ) streams.append(frontend_stream) backend_stream = ParallelStream( name="后端开发流", description="API和服务相关的并行开发流", phases=[phase.id for phase in workflow.phases[1:3]], ) streams.append(backend_stream) return streams async def _calculate_critical_path(self, workflow: Workflow) -> CriticalPath: """计算关键路径""" # 简化实现 - 实际应该基于依赖关系计算 total_effort = workflow.get_total_effort() estimated_duration = timedelta(days=total_effort // 8) # 假设每天8小时 critical_path = CriticalPath( phases=[phase.id for phase in workflow.phases], total_duration=estimated_duration, total_effort=total_effort, bottlenecks=[ phase.id for phase in workflow.phases if phase.estimated_effort and phase.estimated_effort > total_effort * 0.3 ], optimization_opportunities=["考虑并行开发", "优化资源分配", "简化复杂需求"], ) return critical_path async def _activate_personas(self, workflow: Workflow, options: WorkflowOptions) -> List[PersonaType]: """激活专家人格""" activated_personas = [] if options.forced_persona: activated_personas.append(options.forced_persona) return activated_personas # 基于需求类别激活相应人格 if workflow.requirement_categories: if workflow.requirement_categories.ui_requirements: activated_personas.append(PersonaType.FRONTEND) if workflow.requirement_categories.api_requirements: activated_personas.append(PersonaType.BACKEND) if workflow.requirement_categories.security_requirements: activated_personas.append(PersonaType.SECURITY) if workflow.requirement_categories.performance_requirements: activated_personas.append(PersonaType.PERFORMANCE) # 基于复杂度激活架构师 if workflow.complexity_analysis and workflow.complexity_analysis.overall_complexity in [ ComplexityLevel.COMPLEX, ComplexityLevel.ENTERPRISE, ]: activated_personas.append(PersonaType.ARCHITECT) # 如果没有激活任何人格,默认激活后端 if not activated_personas: activated_personas.append(PersonaType.BACKEND) return activated_personas async def _integrate_mcp_services(self, workflow: Workflow, options: WorkflowOptions) -> MCPResults: """集成MCP服务""" if any( ( options.enable_context7, options.enable_sequential, options.enable_magic, options.enable_playwright, options.enable_all_mcp, ) ): raise NotImplementedError("External workflow MCP integrations are not implemented") return MCPResults()