claude-mpm 0.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of claude-mpm might be problematic. Click here for more details.

Files changed (159) hide show
  1. claude_mpm/__init__.py +17 -0
  2. claude_mpm/__main__.py +14 -0
  3. claude_mpm/_version.py +32 -0
  4. claude_mpm/agents/BASE_AGENT_TEMPLATE.md +88 -0
  5. claude_mpm/agents/INSTRUCTIONS.md +375 -0
  6. claude_mpm/agents/__init__.py +118 -0
  7. claude_mpm/agents/agent_loader.py +621 -0
  8. claude_mpm/agents/agent_loader_integration.py +229 -0
  9. claude_mpm/agents/agents_metadata.py +204 -0
  10. claude_mpm/agents/base_agent.json +27 -0
  11. claude_mpm/agents/base_agent_loader.py +519 -0
  12. claude_mpm/agents/schema/agent_schema.json +160 -0
  13. claude_mpm/agents/system_agent_config.py +587 -0
  14. claude_mpm/agents/templates/__init__.py +101 -0
  15. claude_mpm/agents/templates/data_engineer_agent.json +46 -0
  16. claude_mpm/agents/templates/documentation_agent.json +45 -0
  17. claude_mpm/agents/templates/engineer_agent.json +49 -0
  18. claude_mpm/agents/templates/ops_agent.json +46 -0
  19. claude_mpm/agents/templates/qa_agent.json +45 -0
  20. claude_mpm/agents/templates/research_agent.json +49 -0
  21. claude_mpm/agents/templates/security_agent.json +46 -0
  22. claude_mpm/agents/templates/update-optimized-specialized-agents.json +374 -0
  23. claude_mpm/agents/templates/version_control_agent.json +46 -0
  24. claude_mpm/agents/test_fix_deployment/.claude-pm/config/project.json +6 -0
  25. claude_mpm/cli.py +655 -0
  26. claude_mpm/cli_main.py +13 -0
  27. claude_mpm/cli_module/__init__.py +15 -0
  28. claude_mpm/cli_module/args.py +222 -0
  29. claude_mpm/cli_module/commands.py +203 -0
  30. claude_mpm/cli_module/migration_example.py +183 -0
  31. claude_mpm/cli_module/refactoring_guide.md +253 -0
  32. claude_mpm/cli_old/__init__.py +1 -0
  33. claude_mpm/cli_old/ticket_cli.py +102 -0
  34. claude_mpm/config/__init__.py +5 -0
  35. claude_mpm/config/hook_config.py +42 -0
  36. claude_mpm/constants.py +150 -0
  37. claude_mpm/core/__init__.py +45 -0
  38. claude_mpm/core/agent_name_normalizer.py +248 -0
  39. claude_mpm/core/agent_registry.py +627 -0
  40. claude_mpm/core/agent_registry.py.bak +312 -0
  41. claude_mpm/core/agent_session_manager.py +273 -0
  42. claude_mpm/core/base_service.py +747 -0
  43. claude_mpm/core/base_service.py.bak +406 -0
  44. claude_mpm/core/config.py +334 -0
  45. claude_mpm/core/config_aliases.py +292 -0
  46. claude_mpm/core/container.py +347 -0
  47. claude_mpm/core/factories.py +281 -0
  48. claude_mpm/core/framework_loader.py +472 -0
  49. claude_mpm/core/injectable_service.py +206 -0
  50. claude_mpm/core/interfaces.py +539 -0
  51. claude_mpm/core/logger.py +468 -0
  52. claude_mpm/core/minimal_framework_loader.py +107 -0
  53. claude_mpm/core/mixins.py +150 -0
  54. claude_mpm/core/service_registry.py +299 -0
  55. claude_mpm/core/session_manager.py +190 -0
  56. claude_mpm/core/simple_runner.py +511 -0
  57. claude_mpm/core/tool_access_control.py +173 -0
  58. claude_mpm/hooks/README.md +243 -0
  59. claude_mpm/hooks/__init__.py +5 -0
  60. claude_mpm/hooks/base_hook.py +154 -0
  61. claude_mpm/hooks/builtin/__init__.py +1 -0
  62. claude_mpm/hooks/builtin/logging_hook_example.py +165 -0
  63. claude_mpm/hooks/builtin/post_delegation_hook_example.py +124 -0
  64. claude_mpm/hooks/builtin/pre_delegation_hook_example.py +125 -0
  65. claude_mpm/hooks/builtin/submit_hook_example.py +100 -0
  66. claude_mpm/hooks/builtin/ticket_extraction_hook_example.py +237 -0
  67. claude_mpm/hooks/builtin/todo_agent_prefix_hook.py +239 -0
  68. claude_mpm/hooks/builtin/workflow_start_hook.py +181 -0
  69. claude_mpm/hooks/hook_client.py +264 -0
  70. claude_mpm/hooks/hook_runner.py +370 -0
  71. claude_mpm/hooks/json_rpc_executor.py +259 -0
  72. claude_mpm/hooks/json_rpc_hook_client.py +319 -0
  73. claude_mpm/hooks/tool_call_interceptor.py +204 -0
  74. claude_mpm/init.py +246 -0
  75. claude_mpm/orchestration/SUBPROCESS_DESIGN.md +66 -0
  76. claude_mpm/orchestration/__init__.py +6 -0
  77. claude_mpm/orchestration/archive/direct_orchestrator.py +195 -0
  78. claude_mpm/orchestration/archive/factory.py +215 -0
  79. claude_mpm/orchestration/archive/hook_enabled_orchestrator.py +188 -0
  80. claude_mpm/orchestration/archive/hook_integration_example.py +178 -0
  81. claude_mpm/orchestration/archive/interactive_subprocess_orchestrator.py +826 -0
  82. claude_mpm/orchestration/archive/orchestrator.py +501 -0
  83. claude_mpm/orchestration/archive/pexpect_orchestrator.py +252 -0
  84. claude_mpm/orchestration/archive/pty_orchestrator.py +270 -0
  85. claude_mpm/orchestration/archive/simple_orchestrator.py +82 -0
  86. claude_mpm/orchestration/archive/subprocess_orchestrator.py +801 -0
  87. claude_mpm/orchestration/archive/system_prompt_orchestrator.py +278 -0
  88. claude_mpm/orchestration/archive/wrapper_orchestrator.py +187 -0
  89. claude_mpm/scripts/__init__.py +1 -0
  90. claude_mpm/scripts/ticket.py +269 -0
  91. claude_mpm/services/__init__.py +10 -0
  92. claude_mpm/services/agent_deployment.py +955 -0
  93. claude_mpm/services/agent_lifecycle_manager.py +948 -0
  94. claude_mpm/services/agent_management_service.py +596 -0
  95. claude_mpm/services/agent_modification_tracker.py +841 -0
  96. claude_mpm/services/agent_profile_loader.py +606 -0
  97. claude_mpm/services/agent_registry.py +677 -0
  98. claude_mpm/services/base_agent_manager.py +380 -0
  99. claude_mpm/services/framework_agent_loader.py +337 -0
  100. claude_mpm/services/framework_claude_md_generator/README.md +92 -0
  101. claude_mpm/services/framework_claude_md_generator/__init__.py +206 -0
  102. claude_mpm/services/framework_claude_md_generator/content_assembler.py +151 -0
  103. claude_mpm/services/framework_claude_md_generator/content_validator.py +126 -0
  104. claude_mpm/services/framework_claude_md_generator/deployment_manager.py +137 -0
  105. claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +106 -0
  106. claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +582 -0
  107. claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +97 -0
  108. claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +27 -0
  109. claude_mpm/services/framework_claude_md_generator/section_generators/delegation_constraints.py +23 -0
  110. claude_mpm/services/framework_claude_md_generator/section_generators/environment_config.py +23 -0
  111. claude_mpm/services/framework_claude_md_generator/section_generators/footer.py +20 -0
  112. claude_mpm/services/framework_claude_md_generator/section_generators/header.py +26 -0
  113. claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py +30 -0
  114. claude_mpm/services/framework_claude_md_generator/section_generators/role_designation.py +37 -0
  115. claude_mpm/services/framework_claude_md_generator/section_generators/subprocess_validation.py +111 -0
  116. claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +89 -0
  117. claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +39 -0
  118. claude_mpm/services/framework_claude_md_generator/section_manager.py +106 -0
  119. claude_mpm/services/framework_claude_md_generator/version_manager.py +121 -0
  120. claude_mpm/services/framework_claude_md_generator.py +621 -0
  121. claude_mpm/services/hook_service.py +388 -0
  122. claude_mpm/services/hook_service_manager.py +223 -0
  123. claude_mpm/services/json_rpc_hook_manager.py +92 -0
  124. claude_mpm/services/parent_directory_manager/README.md +83 -0
  125. claude_mpm/services/parent_directory_manager/__init__.py +577 -0
  126. claude_mpm/services/parent_directory_manager/backup_manager.py +258 -0
  127. claude_mpm/services/parent_directory_manager/config_manager.py +210 -0
  128. claude_mpm/services/parent_directory_manager/deduplication_manager.py +279 -0
  129. claude_mpm/services/parent_directory_manager/framework_protector.py +143 -0
  130. claude_mpm/services/parent_directory_manager/operations.py +186 -0
  131. claude_mpm/services/parent_directory_manager/state_manager.py +624 -0
  132. claude_mpm/services/parent_directory_manager/template_deployer.py +579 -0
  133. claude_mpm/services/parent_directory_manager/validation_manager.py +378 -0
  134. claude_mpm/services/parent_directory_manager/version_control_helper.py +339 -0
  135. claude_mpm/services/parent_directory_manager/version_manager.py +222 -0
  136. claude_mpm/services/shared_prompt_cache.py +819 -0
  137. claude_mpm/services/ticket_manager.py +213 -0
  138. claude_mpm/services/ticket_manager_di.py +318 -0
  139. claude_mpm/services/ticketing_service_original.py +508 -0
  140. claude_mpm/services/version_control/VERSION +1 -0
  141. claude_mpm/services/version_control/__init__.py +70 -0
  142. claude_mpm/services/version_control/branch_strategy.py +670 -0
  143. claude_mpm/services/version_control/conflict_resolution.py +744 -0
  144. claude_mpm/services/version_control/git_operations.py +784 -0
  145. claude_mpm/services/version_control/semantic_versioning.py +703 -0
  146. claude_mpm/ui/__init__.py +1 -0
  147. claude_mpm/ui/rich_terminal_ui.py +295 -0
  148. claude_mpm/ui/terminal_ui.py +328 -0
  149. claude_mpm/utils/__init__.py +16 -0
  150. claude_mpm/utils/config_manager.py +468 -0
  151. claude_mpm/utils/import_migration_example.py +80 -0
  152. claude_mpm/utils/imports.py +182 -0
  153. claude_mpm/utils/path_operations.py +357 -0
  154. claude_mpm/utils/paths.py +289 -0
  155. claude_mpm-0.3.0.dist-info/METADATA +290 -0
  156. claude_mpm-0.3.0.dist-info/RECORD +159 -0
  157. claude_mpm-0.3.0.dist-info/WHEEL +5 -0
  158. claude_mpm-0.3.0.dist-info/entry_points.txt +4 -0
  159. claude_mpm-0.3.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,670 @@
1
+ """
2
+ Branch Strategy Manager - Branch strategy implementations for Version Control Agent.
3
+
4
+ This module provides comprehensive branch strategy management including:
5
+ 1. Issue-driven development workflow
6
+ 2. GitFlow implementation
7
+ 3. GitHub Flow implementation
8
+ 4. Custom branch strategies
9
+ 5. Branch lifecycle management
10
+ """
11
+
12
+ from enum import Enum
13
+ from datetime import datetime
14
+ from pathlib import Path
15
+ from typing import Dict, List, Optional, Any, Tuple
16
+ from dataclasses import dataclass, field
17
+ import logging
18
+ import re
19
+
20
+
21
+ class BranchStrategyType(Enum):
22
+ """Types of branch strategies."""
23
+
24
+ ISSUE_DRIVEN = "issue_driven"
25
+ GITFLOW = "gitflow"
26
+ GITHUB_FLOW = "github_flow"
27
+ CUSTOM = "custom"
28
+
29
+
30
+ class BranchType(Enum):
31
+ """Types of branches in different strategies."""
32
+
33
+ MAIN = "main"
34
+ DEVELOP = "develop"
35
+ FEATURE = "feature"
36
+ ISSUE = "issue"
37
+ ENHANCEMENT = "enhancement"
38
+ HOTFIX = "hotfix"
39
+ RELEASE = "release"
40
+ EPIC = "epic"
41
+
42
+
43
+ @dataclass
44
+ class BranchNamingRule:
45
+ """Rules for branch naming."""
46
+
47
+ branch_type: BranchType
48
+ prefix: str
49
+ pattern: str
50
+ required_fields: List[str] = field(default_factory=list)
51
+ max_length: Optional[int] = None
52
+ description: str = ""
53
+
54
+
55
+ @dataclass
56
+ class BranchLifecycleRule:
57
+ """Rules for branch lifecycle management."""
58
+
59
+ branch_type: BranchType
60
+ auto_create: bool = False
61
+ auto_merge_target: Optional[str] = None
62
+ auto_merge_strategy: str = "merge"
63
+ auto_delete_after_merge: bool = False
64
+ requires_qa_approval: bool = False
65
+ requires_review: bool = False
66
+ merge_message_template: Optional[str] = None
67
+
68
+
69
+ @dataclass
70
+ class BranchWorkflow:
71
+ """Workflow definition for a branch strategy."""
72
+
73
+ strategy_type: BranchStrategyType
74
+ main_branch: str
75
+ development_branch: Optional[str] = None
76
+ naming_rules: List[BranchNamingRule] = field(default_factory=list)
77
+ lifecycle_rules: List[BranchLifecycleRule] = field(default_factory=list)
78
+ merge_targets: Dict[str, str] = field(default_factory=dict)
79
+ quality_gates: List[str] = field(default_factory=list)
80
+
81
+
82
+ class BranchStrategyManager:
83
+ """
84
+ Manages branch strategies for the Version Control Agent.
85
+
86
+ Provides implementation of different branching strategies including
87
+ issue-driven development, GitFlow, and GitHub Flow.
88
+ """
89
+
90
+ def __init__(self, project_root: str, logger: logging.Logger):
91
+ """
92
+ Initialize Branch Strategy Manager.
93
+
94
+ Args:
95
+ project_root: Root directory of the project
96
+ logger: Logger instance
97
+ """
98
+ self.project_root = Path(project_root)
99
+ self.logger = logger
100
+
101
+ # Initialize predefined strategies
102
+ self.strategies = {
103
+ BranchStrategyType.ISSUE_DRIVEN: self._create_issue_driven_strategy(),
104
+ BranchStrategyType.GITFLOW: self._create_gitflow_strategy(),
105
+ BranchStrategyType.GITHUB_FLOW: self._create_github_flow_strategy(),
106
+ }
107
+
108
+ # Current strategy
109
+ self.current_strategy: Optional[BranchWorkflow] = None
110
+
111
+ # Load strategy from configuration
112
+ self._load_strategy_configuration()
113
+
114
+ def _create_issue_driven_strategy(self) -> BranchWorkflow:
115
+ """Create issue-driven development strategy."""
116
+ naming_rules = [
117
+ BranchNamingRule(
118
+ branch_type=BranchType.ISSUE,
119
+ prefix="issue/",
120
+ pattern=r"^issue/[A-Z]+-\d+(-.*)?$",
121
+ required_fields=["ticket_id"],
122
+ description="Issue branches for bug fixes and standard issues",
123
+ ),
124
+ BranchNamingRule(
125
+ branch_type=BranchType.FEATURE,
126
+ prefix="feature/",
127
+ pattern=r"^feature/[A-Z]+-\d+(-.*)?$",
128
+ required_fields=["ticket_id"],
129
+ description="Feature branches for new functionality",
130
+ ),
131
+ BranchNamingRule(
132
+ branch_type=BranchType.ENHANCEMENT,
133
+ prefix="enhancement/",
134
+ pattern=r"^enhancement/[A-Z]+-\d+(-.*)?$",
135
+ required_fields=["ticket_id"],
136
+ description="Enhancement branches for improvements",
137
+ ),
138
+ BranchNamingRule(
139
+ branch_type=BranchType.HOTFIX,
140
+ prefix="hotfix/",
141
+ pattern=r"^hotfix/[A-Z]+-\d+(-.*)?$",
142
+ required_fields=["ticket_id"],
143
+ description="Hotfix branches for critical fixes",
144
+ ),
145
+ BranchNamingRule(
146
+ branch_type=BranchType.EPIC,
147
+ prefix="epic/",
148
+ pattern=r"^epic/[A-Z]+-\d+(-.*)?$",
149
+ required_fields=["epic_id"],
150
+ description="Epic branches for large features",
151
+ ),
152
+ ]
153
+
154
+ lifecycle_rules = [
155
+ BranchLifecycleRule(
156
+ branch_type=BranchType.ISSUE,
157
+ auto_merge_target="main",
158
+ auto_merge_strategy="merge",
159
+ auto_delete_after_merge=True,
160
+ requires_qa_approval=True,
161
+ merge_message_template="Merge {branch_name}: {ticket_title}",
162
+ ),
163
+ BranchLifecycleRule(
164
+ branch_type=BranchType.FEATURE,
165
+ auto_merge_target="main",
166
+ auto_merge_strategy="merge",
167
+ auto_delete_after_merge=True,
168
+ requires_qa_approval=True,
169
+ requires_review=True,
170
+ merge_message_template="Merge {branch_name}: {ticket_title}",
171
+ ),
172
+ BranchLifecycleRule(
173
+ branch_type=BranchType.ENHANCEMENT,
174
+ auto_merge_target="main",
175
+ auto_merge_strategy="merge",
176
+ auto_delete_after_merge=True,
177
+ requires_qa_approval=True,
178
+ merge_message_template="Merge {branch_name}: {ticket_title}",
179
+ ),
180
+ BranchLifecycleRule(
181
+ branch_type=BranchType.HOTFIX,
182
+ auto_merge_target="main",
183
+ auto_merge_strategy="merge",
184
+ auto_delete_after_merge=True,
185
+ requires_qa_approval=False, # Hotfixes can be fast-tracked
186
+ merge_message_template="Hotfix {branch_name}: {ticket_title}",
187
+ ),
188
+ BranchLifecycleRule(
189
+ branch_type=BranchType.EPIC,
190
+ auto_merge_target="main",
191
+ auto_merge_strategy="squash",
192
+ auto_delete_after_merge=True,
193
+ requires_qa_approval=True,
194
+ requires_review=True,
195
+ merge_message_template="Complete epic {branch_name}: {epic_title}",
196
+ ),
197
+ ]
198
+
199
+ return BranchWorkflow(
200
+ strategy_type=BranchStrategyType.ISSUE_DRIVEN,
201
+ main_branch="main",
202
+ naming_rules=naming_rules,
203
+ lifecycle_rules=lifecycle_rules,
204
+ merge_targets={
205
+ "issue/*": "main",
206
+ "feature/*": "main",
207
+ "enhancement/*": "main",
208
+ "hotfix/*": "main",
209
+ "epic/*": "main",
210
+ },
211
+ quality_gates=["documentation_validation", "qa_testing", "code_quality"],
212
+ )
213
+
214
+ def _create_gitflow_strategy(self) -> BranchWorkflow:
215
+ """Create GitFlow strategy."""
216
+ naming_rules = [
217
+ BranchNamingRule(
218
+ branch_type=BranchType.FEATURE,
219
+ prefix="feature/",
220
+ pattern=r"^feature/.*$",
221
+ description="Feature branches for new functionality",
222
+ ),
223
+ BranchNamingRule(
224
+ branch_type=BranchType.RELEASE,
225
+ prefix="release/",
226
+ pattern=r"^release/\d+\.\d+(\.\d+)?$",
227
+ required_fields=["version"],
228
+ description="Release branches for version preparation",
229
+ ),
230
+ BranchNamingRule(
231
+ branch_type=BranchType.HOTFIX,
232
+ prefix="hotfix/",
233
+ pattern=r"^hotfix/.*$",
234
+ description="Hotfix branches for critical fixes",
235
+ ),
236
+ ]
237
+
238
+ lifecycle_rules = [
239
+ BranchLifecycleRule(
240
+ branch_type=BranchType.FEATURE,
241
+ auto_merge_target="develop",
242
+ auto_merge_strategy="merge",
243
+ auto_delete_after_merge=True,
244
+ requires_review=True,
245
+ ),
246
+ BranchLifecycleRule(
247
+ branch_type=BranchType.RELEASE,
248
+ auto_merge_target="main",
249
+ auto_merge_strategy="merge",
250
+ auto_delete_after_merge=True,
251
+ requires_qa_approval=True,
252
+ ),
253
+ BranchLifecycleRule(
254
+ branch_type=BranchType.HOTFIX,
255
+ auto_merge_target="main",
256
+ auto_merge_strategy="merge",
257
+ auto_delete_after_merge=True,
258
+ ),
259
+ ]
260
+
261
+ return BranchWorkflow(
262
+ strategy_type=BranchStrategyType.GITFLOW,
263
+ main_branch="main",
264
+ development_branch="develop",
265
+ naming_rules=naming_rules,
266
+ lifecycle_rules=lifecycle_rules,
267
+ merge_targets={"feature/*": "develop", "release/*": "main", "hotfix/*": "main"},
268
+ quality_gates=["testing", "code_review"],
269
+ )
270
+
271
+ def _create_github_flow_strategy(self) -> BranchWorkflow:
272
+ """Create GitHub Flow strategy."""
273
+ naming_rules = [
274
+ BranchNamingRule(
275
+ branch_type=BranchType.FEATURE,
276
+ prefix="",
277
+ pattern=r"^[a-z0-9\-/]+$",
278
+ description="Feature branches with descriptive names",
279
+ )
280
+ ]
281
+
282
+ lifecycle_rules = [
283
+ BranchLifecycleRule(
284
+ branch_type=BranchType.FEATURE,
285
+ auto_merge_target="main",
286
+ auto_merge_strategy="squash",
287
+ auto_delete_after_merge=True,
288
+ requires_review=True,
289
+ requires_qa_approval=True,
290
+ )
291
+ ]
292
+
293
+ return BranchWorkflow(
294
+ strategy_type=BranchStrategyType.GITHUB_FLOW,
295
+ main_branch="main",
296
+ naming_rules=naming_rules,
297
+ lifecycle_rules=lifecycle_rules,
298
+ merge_targets={"*": "main"},
299
+ quality_gates=["ci_tests", "code_review", "deployment_test"],
300
+ )
301
+
302
+ def _load_strategy_configuration(self) -> None:
303
+ """Load strategy configuration from project files."""
304
+ # Try to load from configuration files
305
+ config_files = [
306
+ ".claude-pm/config.json",
307
+ "workflow.md",
308
+ ".github/workflows/branch-strategy.yml",
309
+ "branch-strategy.json",
310
+ ]
311
+
312
+ for config_file in config_files:
313
+ config_path = self.project_root / config_file
314
+ if config_path.exists():
315
+ try:
316
+ strategy = self._parse_strategy_config(config_path)
317
+ if strategy:
318
+ self.current_strategy = strategy
319
+ self.logger.info(f"Loaded branch strategy from {config_file}")
320
+ return
321
+ except Exception as e:
322
+ self.logger.error(f"Error loading strategy from {config_file}: {e}")
323
+
324
+ # Default to issue-driven strategy
325
+ self.current_strategy = self.strategies[BranchStrategyType.ISSUE_DRIVEN]
326
+ self.logger.info("Using default issue-driven branch strategy")
327
+
328
+ def _parse_strategy_config(self, config_path: Path) -> Optional[BranchWorkflow]:
329
+ """Parse strategy configuration from file."""
330
+ # This would implement parsing logic for different config file formats
331
+ # For now, return None to use defaults
332
+ return None
333
+
334
+ def get_current_strategy(self) -> BranchWorkflow:
335
+ """Get the current branch strategy."""
336
+ if not self.current_strategy:
337
+ self.current_strategy = self.strategies[BranchStrategyType.ISSUE_DRIVEN]
338
+ return self.current_strategy
339
+
340
+ def set_strategy(self, strategy_type: BranchStrategyType) -> bool:
341
+ """
342
+ Set the current branch strategy.
343
+
344
+ Args:
345
+ strategy_type: Type of strategy to use
346
+
347
+ Returns:
348
+ True if strategy was set successfully
349
+ """
350
+ if strategy_type in self.strategies:
351
+ self.current_strategy = self.strategies[strategy_type]
352
+ self.logger.info(f"Set branch strategy to {strategy_type.value}")
353
+ return True
354
+ else:
355
+ self.logger.error(f"Unknown strategy type: {strategy_type}")
356
+ return False
357
+
358
+ def generate_branch_name(
359
+ self,
360
+ branch_type: BranchType,
361
+ ticket_id: Optional[str] = None,
362
+ description: Optional[str] = None,
363
+ **kwargs,
364
+ ) -> str:
365
+ """
366
+ Generate a branch name following the current strategy.
367
+
368
+ Args:
369
+ branch_type: Type of branch to create
370
+ ticket_id: Ticket/issue ID
371
+ description: Optional description
372
+ **kwargs: Additional parameters
373
+
374
+ Returns:
375
+ Generated branch name
376
+ """
377
+ strategy = self.get_current_strategy()
378
+
379
+ # Find naming rule for this branch type
380
+ naming_rule = None
381
+ for rule in strategy.naming_rules:
382
+ if rule.branch_type == branch_type:
383
+ naming_rule = rule
384
+ break
385
+
386
+ if not naming_rule:
387
+ # Fallback to simple naming
388
+ prefix = branch_type.value + "/"
389
+ if ticket_id:
390
+ return f"{prefix}{ticket_id}"
391
+ elif description:
392
+ return f"{prefix}{self._sanitize_branch_name(description)}"
393
+ else:
394
+ return f"{prefix}{datetime.now().strftime('%Y%m%d')}"
395
+
396
+ # Generate name based on rule
397
+ if strategy.strategy_type == BranchStrategyType.ISSUE_DRIVEN:
398
+ if ticket_id:
399
+ branch_name = f"{naming_rule.prefix}{ticket_id}"
400
+ if description:
401
+ sanitized_desc = self._sanitize_branch_name(description)
402
+ branch_name += f"-{sanitized_desc}"
403
+ return branch_name
404
+
405
+ # Default generation
406
+ return f"{naming_rule.prefix}{ticket_id or 'branch'}"
407
+
408
+ def _sanitize_branch_name(self, name: str) -> str:
409
+ """Sanitize a string for use in branch names."""
410
+ # Convert to lowercase and replace spaces/special chars with hyphens
411
+ sanitized = re.sub(r"[^a-zA-Z0-9\-_]", "-", name.lower())
412
+ # Remove multiple consecutive hyphens
413
+ sanitized = re.sub(r"-+", "-", sanitized)
414
+ # Remove leading/trailing hyphens
415
+ sanitized = sanitized.strip("-")
416
+ # Limit length
417
+ return sanitized[:50]
418
+
419
+ def validate_branch_name(self, branch_name: str) -> Tuple[bool, str]:
420
+ """
421
+ Validate a branch name against current strategy rules.
422
+
423
+ Args:
424
+ branch_name: Branch name to validate
425
+
426
+ Returns:
427
+ Tuple of (is_valid, error_message)
428
+ """
429
+ strategy = self.get_current_strategy()
430
+
431
+ # Check against naming rules
432
+ for rule in strategy.naming_rules:
433
+ if branch_name.startswith(rule.prefix):
434
+ # Check pattern
435
+ if not re.match(rule.pattern, branch_name):
436
+ return False, f"Branch name doesn't match pattern: {rule.pattern}"
437
+
438
+ # Check length
439
+ if rule.max_length and len(branch_name) > rule.max_length:
440
+ return False, f"Branch name exceeds maximum length: {rule.max_length}"
441
+
442
+ return True, "Valid branch name"
443
+
444
+ # Check if it's a protected branch
445
+ protected_branches = [strategy.main_branch]
446
+ if strategy.development_branch:
447
+ protected_branches.append(strategy.development_branch)
448
+
449
+ if branch_name in protected_branches:
450
+ return False, f"Cannot use protected branch name: {branch_name}"
451
+
452
+ return True, "Valid branch name"
453
+
454
+ def get_merge_target(self, branch_name: str) -> Optional[str]:
455
+ """
456
+ Get the merge target for a branch based on current strategy.
457
+
458
+ Args:
459
+ branch_name: Source branch name
460
+
461
+ Returns:
462
+ Target branch name or None
463
+ """
464
+ strategy = self.get_current_strategy()
465
+
466
+ # Check specific merge targets
467
+ for pattern, target in strategy.merge_targets.items():
468
+ if pattern == "*" or branch_name.startswith(pattern.rstrip("*")):
469
+ return target
470
+
471
+ # Default to main branch
472
+ return strategy.main_branch
473
+
474
+ def get_lifecycle_rule(self, branch_name: str) -> Optional[BranchLifecycleRule]:
475
+ """
476
+ Get the lifecycle rule for a branch.
477
+
478
+ Args:
479
+ branch_name: Branch name
480
+
481
+ Returns:
482
+ BranchLifecycleRule or None
483
+ """
484
+ strategy = self.get_current_strategy()
485
+
486
+ # Determine branch type from name
487
+ branch_type = self._get_branch_type(branch_name)
488
+
489
+ # Find matching lifecycle rule
490
+ for rule in strategy.lifecycle_rules:
491
+ if rule.branch_type == branch_type:
492
+ return rule
493
+
494
+ return None
495
+
496
+ def _get_branch_type(self, branch_name: str) -> BranchType:
497
+ """Determine branch type from branch name."""
498
+ strategy = self.get_current_strategy()
499
+
500
+ # Check against naming rules
501
+ for rule in strategy.naming_rules:
502
+ if branch_name.startswith(rule.prefix):
503
+ return rule.branch_type
504
+
505
+ # Default to feature
506
+ return BranchType.FEATURE
507
+
508
+ def should_auto_merge(self, branch_name: str) -> bool:
509
+ """
510
+ Check if a branch should be automatically merged.
511
+
512
+ Args:
513
+ branch_name: Branch name
514
+
515
+ Returns:
516
+ True if branch should be auto-merged
517
+ """
518
+ rule = self.get_lifecycle_rule(branch_name)
519
+ return rule and rule.auto_merge_target is not None
520
+
521
+ def should_delete_after_merge(self, branch_name: str) -> bool:
522
+ """
523
+ Check if a branch should be deleted after merge.
524
+
525
+ Args:
526
+ branch_name: Branch name
527
+
528
+ Returns:
529
+ True if branch should be deleted after merge
530
+ """
531
+ rule = self.get_lifecycle_rule(branch_name)
532
+ return rule and rule.auto_delete_after_merge
533
+
534
+ def requires_qa_approval(self, branch_name: str) -> bool:
535
+ """
536
+ Check if a branch requires QA approval before merge.
537
+
538
+ Args:
539
+ branch_name: Branch name
540
+
541
+ Returns:
542
+ True if QA approval is required
543
+ """
544
+ rule = self.get_lifecycle_rule(branch_name)
545
+ return rule and rule.requires_qa_approval
546
+
547
+ def requires_code_review(self, branch_name: str) -> bool:
548
+ """
549
+ Check if a branch requires code review before merge.
550
+
551
+ Args:
552
+ branch_name: Branch name
553
+
554
+ Returns:
555
+ True if code review is required
556
+ """
557
+ rule = self.get_lifecycle_rule(branch_name)
558
+ return rule and rule.requires_review
559
+
560
+ def get_merge_strategy(self, branch_name: str) -> str:
561
+ """
562
+ Get the merge strategy for a branch.
563
+
564
+ Args:
565
+ branch_name: Branch name
566
+
567
+ Returns:
568
+ Merge strategy (merge, squash, rebase)
569
+ """
570
+ rule = self.get_lifecycle_rule(branch_name)
571
+ return rule.auto_merge_strategy if rule else "merge"
572
+
573
+ def generate_merge_message(
574
+ self, branch_name: str, ticket_title: Optional[str] = None, **kwargs
575
+ ) -> str:
576
+ """
577
+ Generate merge commit message based on strategy.
578
+
579
+ Args:
580
+ branch_name: Source branch name
581
+ ticket_title: Optional ticket title
582
+ **kwargs: Additional template variables
583
+
584
+ Returns:
585
+ Generated merge message
586
+ """
587
+ rule = self.get_lifecycle_rule(branch_name)
588
+
589
+ if rule and rule.merge_message_template:
590
+ template = rule.merge_message_template
591
+
592
+ # Replace template variables
593
+ variables = {
594
+ "branch_name": branch_name,
595
+ "ticket_title": ticket_title or "Updates",
596
+ **kwargs,
597
+ }
598
+
599
+ for key, value in variables.items():
600
+ template = template.replace(f"{{{key}}}", str(value))
601
+
602
+ return template
603
+
604
+ # Default merge message
605
+ if ticket_title:
606
+ return f"Merge {branch_name}: {ticket_title}"
607
+ else:
608
+ return f"Merge {branch_name}"
609
+
610
+ def get_quality_gates(self) -> List[str]:
611
+ """Get quality gates for the current strategy."""
612
+ strategy = self.get_current_strategy()
613
+ return strategy.quality_gates
614
+
615
+ def create_custom_strategy(self, name: str, config: Dict[str, Any]) -> BranchWorkflow:
616
+ """
617
+ Create a custom branch strategy.
618
+
619
+ Args:
620
+ name: Strategy name
621
+ config: Strategy configuration
622
+
623
+ Returns:
624
+ Custom BranchWorkflow
625
+ """
626
+ # This would implement custom strategy creation
627
+ # For now, return a basic custom strategy
628
+ return BranchWorkflow(
629
+ strategy_type=BranchStrategyType.CUSTOM,
630
+ main_branch=config.get("main_branch", "main"),
631
+ naming_rules=[],
632
+ lifecycle_rules=[],
633
+ merge_targets={},
634
+ quality_gates=[],
635
+ )
636
+
637
+ def export_strategy_config(self) -> Dict[str, Any]:
638
+ """Export current strategy as configuration."""
639
+ strategy = self.get_current_strategy()
640
+
641
+ return {
642
+ "strategy_type": strategy.strategy_type.value,
643
+ "main_branch": strategy.main_branch,
644
+ "development_branch": strategy.development_branch,
645
+ "naming_rules": [
646
+ {
647
+ "branch_type": rule.branch_type.value,
648
+ "prefix": rule.prefix,
649
+ "pattern": rule.pattern,
650
+ "required_fields": rule.required_fields,
651
+ "max_length": rule.max_length,
652
+ "description": rule.description,
653
+ }
654
+ for rule in strategy.naming_rules
655
+ ],
656
+ "lifecycle_rules": [
657
+ {
658
+ "branch_type": rule.branch_type.value,
659
+ "auto_merge_target": rule.auto_merge_target,
660
+ "auto_merge_strategy": rule.auto_merge_strategy,
661
+ "auto_delete_after_merge": rule.auto_delete_after_merge,
662
+ "requires_qa_approval": rule.requires_qa_approval,
663
+ "requires_review": rule.requires_review,
664
+ "merge_message_template": rule.merge_message_template,
665
+ }
666
+ for rule in strategy.lifecycle_rules
667
+ ],
668
+ "merge_targets": strategy.merge_targets,
669
+ "quality_gates": strategy.quality_gates,
670
+ }