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,151 @@
1
+ """
2
+ Content assembly for framework CLAUDE.md templates.
3
+
4
+ Assembles sections and applies template variable substitution.
5
+ """
6
+
7
+ import hashlib
8
+ from datetime import datetime
9
+ from typing import Dict, List, Optional, Any
10
+ from collections import OrderedDict
11
+
12
+
13
+ class ContentAssembler:
14
+ """Assembles framework CLAUDE.md content from sections."""
15
+
16
+ def __init__(self):
17
+ """Initialize content assembler."""
18
+ self.template_variables = {}
19
+
20
+ def generate_content_hash(self) -> str:
21
+ """
22
+ Generate a content hash for integrity verification.
23
+
24
+ Returns:
25
+ str: 16-character hash of content
26
+ """
27
+ timestamp = datetime.utcnow().isoformat()
28
+ hash_obj = hashlib.sha256(timestamp.encode())
29
+ return hash_obj.hexdigest()[:16]
30
+
31
+ def assemble_content(self,
32
+ sections: OrderedDict,
33
+ template_variables: Optional[Dict[str, str]] = None) -> str:
34
+ """
35
+ Assemble complete content from sections.
36
+
37
+ Args:
38
+ sections: OrderedDict of section_name -> (generator_func, section_data)
39
+ template_variables: Variables to substitute in the template
40
+
41
+ Returns:
42
+ str: Complete assembled content
43
+ """
44
+ # Store template variables
45
+ if template_variables:
46
+ self.template_variables = template_variables
47
+
48
+ # Generate all sections
49
+ content_parts = []
50
+ for section_name, (generator_func, section_data) in sections.items():
51
+ section_content = generator_func(section_data)
52
+ content_parts.append(section_content)
53
+
54
+ # Join all sections
55
+ full_content = '\n'.join(content_parts)
56
+
57
+ # Apply template variable substitution
58
+ full_content = self.apply_template_variables(full_content)
59
+
60
+ return full_content
61
+
62
+ def apply_template_variables(self, content: str) -> str:
63
+ """
64
+ Apply template variable substitution to content.
65
+
66
+ Args:
67
+ content: Content with template variables
68
+
69
+ Returns:
70
+ str: Content with variables substituted
71
+ """
72
+ for var_name, var_value in self.template_variables.items():
73
+ placeholder = f"{{{{{var_name}}}}}"
74
+ content = content.replace(placeholder, var_value)
75
+
76
+ return content
77
+
78
+ def merge_sections(self,
79
+ base_sections: OrderedDict,
80
+ custom_sections: Dict[str, tuple]) -> OrderedDict:
81
+ """
82
+ Merge custom sections with base sections.
83
+
84
+ Args:
85
+ base_sections: Base section definitions
86
+ custom_sections: Custom sections to merge
87
+
88
+ Returns:
89
+ OrderedDict: Merged sections
90
+ """
91
+ merged = OrderedDict(base_sections)
92
+
93
+ for section_name, section_def in custom_sections.items():
94
+ merged[section_name] = section_def
95
+
96
+ return merged
97
+
98
+ def insert_section_after(self,
99
+ sections: OrderedDict,
100
+ new_section_name: str,
101
+ new_section_def: tuple,
102
+ after_section: str) -> OrderedDict:
103
+ """
104
+ Insert a new section after a specified section.
105
+
106
+ Args:
107
+ sections: Current sections
108
+ new_section_name: Name of new section
109
+ new_section_def: Definition tuple for new section
110
+ after_section: Section to insert after
111
+
112
+ Returns:
113
+ OrderedDict: Updated sections
114
+ """
115
+ if after_section not in sections:
116
+ # If target section doesn't exist, just append
117
+ sections[new_section_name] = new_section_def
118
+ return sections
119
+
120
+ new_sections = OrderedDict()
121
+ for key, value in sections.items():
122
+ new_sections[key] = value
123
+ if key == after_section:
124
+ new_sections[new_section_name] = new_section_def
125
+
126
+ return new_sections
127
+
128
+ def create_metadata_dict(self,
129
+ version: str,
130
+ framework_version: str,
131
+ content_hash: Optional[str] = None) -> Dict[str, Any]:
132
+ """
133
+ Create metadata dictionary for header generation.
134
+
135
+ Args:
136
+ version: CLAUDE_MD_VERSION string
137
+ framework_version: Framework version
138
+ content_hash: Optional content hash
139
+
140
+ Returns:
141
+ Dict: Metadata for header
142
+ """
143
+ timestamp = datetime.utcnow().isoformat()
144
+
145
+ return {
146
+ 'version': version,
147
+ 'framework_version': framework_version,
148
+ 'deployment_date': timestamp,
149
+ 'last_updated': timestamp,
150
+ 'content_hash': content_hash or self.generate_content_hash()
151
+ }
@@ -0,0 +1,126 @@
1
+ """
2
+ Content validation for framework CLAUDE.md templates.
3
+
4
+ Validates generated content structure and completeness.
5
+ """
6
+
7
+ import re
8
+ from typing import Tuple, List, Set
9
+
10
+
11
+ class ContentValidator:
12
+ """Validates framework CLAUDE.md content for completeness and correctness."""
13
+
14
+ # Required sections that must be present
15
+ REQUIRED_SECTIONS = [
16
+ (r'CLAUDE_MD_VERSION:', 'Version metadata'),
17
+ (r'## 🤖 AI ASSISTANT ROLE DESIGNATION', 'Role designation section'),
18
+ (r'## A\) AGENTS', 'Agents section'),
19
+ (r'## B\) TODO AND TASK TOOLS', 'Todo/Task tools section'),
20
+ (r'## C\) CLAUDE-PM INIT', 'Claude-PM init section'),
21
+ (r'## 🚨 CORE ORCHESTRATION PRINCIPLES', 'Orchestration principles'),
22
+ (r'## 🔥🚨 CRITICAL: SUBPROCESS VALIDATION PROTOCOL', 'Subprocess validation'),
23
+ (r'## 🚨 CRITICAL DELEGATION CONSTRAINTS', 'Delegation constraints'),
24
+ (r'## 🚨 TROUBLESHOOTING', 'Troubleshooting section'),
25
+ (r'## Core Responsibilities', 'Core responsibilities'),
26
+ ]
27
+
28
+ # Template variables that are allowed to remain unsubstituted for runtime
29
+ ALLOWED_RUNTIME_VARS = {
30
+ '{{DEPLOYMENT_ID}}',
31
+ '{{PLATFORM}}',
32
+ '{{PYTHON_CMD}}',
33
+ '{{PLATFORM_NOTES}}'
34
+ }
35
+
36
+ def validate_content(self, content: str) -> Tuple[bool, List[str]]:
37
+ """
38
+ Validate that generated content has all required sections.
39
+
40
+ Args:
41
+ content: Content to validate
42
+
43
+ Returns:
44
+ Tuple of (is_valid, list_of_issues)
45
+ """
46
+ issues = []
47
+
48
+ # Check for required sections
49
+ for pattern, section_name in self.REQUIRED_SECTIONS:
50
+ if not re.search(pattern, content):
51
+ issues.append(f"Missing required section: {section_name}")
52
+
53
+ # Check for unsubstituted template variables
54
+ unsubstituted = re.findall(r'\{\{[^}]+\}\}', content)
55
+ unexpected_vars = [var for var in unsubstituted if var not in self.ALLOWED_RUNTIME_VARS]
56
+ if unexpected_vars:
57
+ issues.append(f"Unsubstituted template variables: {', '.join(set(unexpected_vars))}")
58
+
59
+ # Validate version format - now accepts simple serial numbers
60
+ version_match = re.search(r'CLAUDE_MD_VERSION:\s*(\d+)(?:-(\d+))?', content)
61
+ if not version_match:
62
+ issues.append("Invalid or missing CLAUDE_MD_VERSION format")
63
+
64
+ # Check for proper structure
65
+ if not content.strip():
66
+ issues.append("Content is empty")
67
+
68
+ # Validate agent section completeness
69
+ if '## A) AGENTS' in content:
70
+ required_agents = [
71
+ 'Documentation Agent',
72
+ 'Ticketing Agent',
73
+ 'Version Control Agent',
74
+ 'QA Agent',
75
+ 'Research Agent',
76
+ 'Ops Agent',
77
+ 'Security Agent',
78
+ 'Engineer Agent',
79
+ 'Data Engineer Agent'
80
+ ]
81
+ for agent in required_agents:
82
+ if agent not in content:
83
+ issues.append(f"Missing core agent: {agent}")
84
+
85
+ return len(issues) == 0, issues
86
+
87
+ def validate_section_order(self, sections: List[str]) -> Tuple[bool, List[str]]:
88
+ """
89
+ Validate that sections are in the correct order.
90
+
91
+ Args:
92
+ sections: List of section names in order
93
+
94
+ Returns:
95
+ Tuple of (is_valid, list_of_issues)
96
+ """
97
+ expected_order = [
98
+ 'header',
99
+ 'role_designation',
100
+ 'agents',
101
+ 'todo_task_tools',
102
+ 'claude_pm_init',
103
+ 'orchestration_principles',
104
+ 'subprocess_validation',
105
+ 'delegation_constraints',
106
+ 'environment_config',
107
+ 'troubleshooting',
108
+ 'core_responsibilities',
109
+ 'footer'
110
+ ]
111
+
112
+ issues = []
113
+
114
+ # Check that all expected sections are present
115
+ missing = set(expected_order) - set(sections)
116
+ if missing:
117
+ issues.append(f"Missing sections: {', '.join(missing)}")
118
+
119
+ # Check order (only for sections that exist in both lists)
120
+ common_sections = [s for s in sections if s in expected_order]
121
+ expected_common = [s for s in expected_order if s in sections]
122
+
123
+ if common_sections != expected_common:
124
+ issues.append("Sections are not in the expected order")
125
+
126
+ return len(issues) == 0, issues
@@ -0,0 +1,137 @@
1
+ """
2
+ Deployment management for framework CLAUDE.md templates.
3
+
4
+ Handles deployment operations to parent directories.
5
+ """
6
+
7
+ from pathlib import Path
8
+ from typing import Tuple, Optional
9
+ from datetime import datetime
10
+ from .version_manager import VersionManager
11
+ from .content_validator import ContentValidator
12
+
13
+ # Import framework detection utilities
14
+ from ...utils.framework_detection import is_framework_source_directory
15
+
16
+
17
+ class DeploymentManager:
18
+ """Manages deployment of framework CLAUDE.md to parent directories."""
19
+
20
+ def __init__(self, version_manager: VersionManager, validator: ContentValidator):
21
+ """
22
+ Initialize deployment manager.
23
+
24
+ Args:
25
+ version_manager: Version management instance
26
+ validator: Content validator instance
27
+ """
28
+ self.version_manager = version_manager
29
+ self.validator = validator
30
+
31
+ def deploy_to_parent(self,
32
+ content: str,
33
+ parent_path: Path,
34
+ force: bool = False) -> Tuple[bool, str]:
35
+ """
36
+ Deploy generated content to a parent directory.
37
+
38
+ Args:
39
+ content: Content to deploy
40
+ parent_path: Path to parent directory
41
+ force: Force deployment even if versions match
42
+
43
+ Returns:
44
+ Tuple of (success, message)
45
+ """
46
+ # Check if we're in the framework source directory
47
+ is_framework, markers = is_framework_source_directory(parent_path)
48
+ if is_framework:
49
+ return True, f"Skipping deployment - detected framework source directory (markers: {', '.join(markers)})"
50
+
51
+ # Use INSTRUCTIONS.md as primary, with CLAUDE.md as fallback
52
+ target_file = parent_path / "INSTRUCTIONS.md"
53
+ # TODO: Make this configurable via parameter
54
+
55
+ # Validate content before deployment
56
+ is_valid, issues = self.validator.validate_content(content)
57
+ if not is_valid:
58
+ return False, f"Validation failed: {'; '.join(issues)}"
59
+
60
+ # Check if file exists and compare versions
61
+ if target_file.exists() and not force:
62
+ with open(target_file, 'r') as f:
63
+ existing_content = f.read()
64
+ existing_fw_ver, _ = self.version_manager.parse_current_version(existing_content)
65
+
66
+ if existing_fw_ver == self.version_manager.framework_version:
67
+ return True, f"Version {existing_fw_ver} already deployed"
68
+
69
+ # Deploy
70
+ try:
71
+ # Ensure parent directory exists
72
+ parent_path.mkdir(parents=True, exist_ok=True)
73
+
74
+ # Write content
75
+ with open(target_file, 'w') as f:
76
+ f.write(content)
77
+
78
+ # Get version info for success message
79
+ fw_ver, serial = self.version_manager.parse_current_version(content)
80
+ version_str = f"{fw_ver}-{serial:03d}"
81
+
82
+ return True, f"Successfully deployed version {version_str}"
83
+ except Exception as e:
84
+ return False, f"Deployment failed: {str(e)}"
85
+
86
+ def check_deployment_needed(self, parent_path: Path) -> Tuple[bool, str]:
87
+ """
88
+ Check if deployment is needed for a parent directory.
89
+
90
+ Args:
91
+ parent_path: Path to parent directory
92
+
93
+ Returns:
94
+ Tuple of (needed, reason)
95
+ """
96
+ target_file = parent_path / "CLAUDE.md"
97
+
98
+ if not target_file.exists():
99
+ return True, "CLAUDE.md does not exist"
100
+
101
+ try:
102
+ with open(target_file, 'r') as f:
103
+ existing_content = f.read()
104
+ existing_fw_ver, _ = self.version_manager.parse_current_version(existing_content)
105
+
106
+ if existing_fw_ver != self.version_manager.framework_version:
107
+ return True, f"Version mismatch: {existing_fw_ver} vs {self.version_manager.framework_version}"
108
+
109
+ return False, "Already up to date"
110
+ except Exception as e:
111
+ return True, f"Error checking existing file: {str(e)}"
112
+
113
+ def backup_existing(self, parent_path: Path) -> Optional[Path]:
114
+ """
115
+ Create a backup of existing CLAUDE.md before deployment.
116
+
117
+ Args:
118
+ parent_path: Path to parent directory
119
+
120
+ Returns:
121
+ Path to backup file if created, None otherwise
122
+ """
123
+ target_file = parent_path / "CLAUDE.md"
124
+
125
+ if not target_file.exists():
126
+ return None
127
+
128
+ # Create backup filename with timestamp
129
+ timestamp = datetime.utcnow().strftime("%Y%m%d_%H%M%S")
130
+ backup_file = parent_path / f"CLAUDE.md.backup.{timestamp}"
131
+
132
+ try:
133
+ import shutil
134
+ shutil.copy2(target_file, backup_file)
135
+ return backup_file
136
+ except Exception:
137
+ return None
@@ -0,0 +1,106 @@
1
+ """
2
+ Section generators for framework CLAUDE.md template.
3
+
4
+ This module provides base classes and registry for section generators.
5
+ """
6
+
7
+ from typing import Dict, Any, Optional
8
+ from abc import ABC, abstractmethod
9
+ from datetime import datetime
10
+
11
+
12
+ class BaseSectionGenerator(ABC):
13
+ """Base class for all section generators."""
14
+
15
+ def __init__(self, framework_version: str):
16
+ """
17
+ Initialize section generator.
18
+
19
+ Args:
20
+ framework_version: Current framework version
21
+ """
22
+ self.framework_version = framework_version
23
+
24
+ @abstractmethod
25
+ def generate(self, data: Dict[str, Any]) -> str:
26
+ """
27
+ Generate section content.
28
+
29
+ Args:
30
+ data: Section-specific data
31
+
32
+ Returns:
33
+ str: Generated section content
34
+ """
35
+ pass
36
+
37
+ def get_timestamp(self) -> str:
38
+ """Get current UTC timestamp."""
39
+ return datetime.utcnow().isoformat()
40
+
41
+
42
+ class SectionGeneratorRegistry:
43
+ """Registry for section generators."""
44
+
45
+ def __init__(self):
46
+ """Initialize registry."""
47
+ self._generators = {}
48
+
49
+ def register(self, name: str, generator_class: type):
50
+ """
51
+ Register a section generator.
52
+
53
+ Args:
54
+ name: Section name
55
+ generator_class: Generator class
56
+ """
57
+ self._generators[name] = generator_class
58
+
59
+ def get(self, name: str) -> Optional[type]:
60
+ """
61
+ Get a section generator class.
62
+
63
+ Args:
64
+ name: Section name
65
+
66
+ Returns:
67
+ Generator class or None
68
+ """
69
+ return self._generators.get(name)
70
+
71
+ def list_sections(self) -> list:
72
+ """Get list of registered section names."""
73
+ return list(self._generators.keys())
74
+
75
+
76
+ # Global registry instance
77
+ section_registry = SectionGeneratorRegistry()
78
+
79
+
80
+ # Import and register all section generators
81
+ from .header import HeaderGenerator
82
+ from .role_designation import RoleDesignationGenerator
83
+ from .agents import AgentsGenerator
84
+ from .todo_task_tools import TodoTaskToolsGenerator
85
+ from .claude_pm_init import ClaudePmInitGenerator
86
+ from .orchestration_principles import OrchestrationPrinciplesGenerator
87
+ from .subprocess_validation import SubprocessValidationGenerator
88
+ from .delegation_constraints import DelegationConstraintsGenerator
89
+ from .environment_config import EnvironmentConfigGenerator
90
+ from .troubleshooting import TroubleshootingGenerator
91
+ from .core_responsibilities import CoreResponsibilitiesGenerator
92
+ from .footer import FooterGenerator
93
+
94
+ # Register all generators
95
+ section_registry.register('header', HeaderGenerator)
96
+ section_registry.register('role_designation', RoleDesignationGenerator)
97
+ section_registry.register('agents', AgentsGenerator)
98
+ section_registry.register('todo_task_tools', TodoTaskToolsGenerator)
99
+ section_registry.register('claude_pm_init', ClaudePmInitGenerator)
100
+ section_registry.register('orchestration_principles', OrchestrationPrinciplesGenerator)
101
+ section_registry.register('subprocess_validation', SubprocessValidationGenerator)
102
+ section_registry.register('delegation_constraints', DelegationConstraintsGenerator)
103
+ section_registry.register('environment_config', EnvironmentConfigGenerator)
104
+ section_registry.register('troubleshooting', TroubleshootingGenerator)
105
+ section_registry.register('core_responsibilities', CoreResponsibilitiesGenerator)
106
+ section_registry.register('footer', FooterGenerator)