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,337 @@
1
+ """
2
+ Framework Agent Loader Service
3
+
4
+ Implements agent profile loading logic based on directory hierarchy:
5
+ 1. Framework .claude-pm (next to agents/INSTRUCTIONS.md or CLAUDE.md): system, trained, user agents
6
+ 2. Project .claude-pm (in project root): project agents
7
+
8
+ Loading precedence: Project → Framework (user → trained → system)
9
+ """
10
+
11
+ import os
12
+ import json
13
+ from pathlib import Path
14
+ from typing import Dict, Optional, Any
15
+ import logging
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+ class FrameworkAgentLoader:
20
+ """Loads agent profiles from framework and project .claude-pm directories"""
21
+
22
+ def __init__(self):
23
+ self.framework_agents_dir = None
24
+ self.project_agents_dir = None
25
+ self._profile_cache = {}
26
+
27
+ def initialize(self, framework_claude_md_path: Optional[str] = None):
28
+ """
29
+ Initialize loader with framework and project directory detection
30
+
31
+ Args:
32
+ framework_claude_md_path: Optional explicit path to agents/INSTRUCTIONS.md or CLAUDE.md
33
+ """
34
+ # Find framework .claude-pm directory (next to framework/CLAUDE.md)
35
+ if framework_claude_md_path:
36
+ framework_dir = Path(framework_claude_md_path).parent.parent
37
+ else:
38
+ framework_dir = self._find_framework_directory()
39
+
40
+ if framework_dir:
41
+ self.framework_agents_dir = framework_dir / ".claude-pm" / "agents"
42
+ logger.info(f"Framework agents directory: {self.framework_agents_dir}")
43
+
44
+ # Find project .claude-pm directory
45
+ project_dir = self._find_project_directory()
46
+ if project_dir:
47
+ self.project_agents_dir = project_dir / ".claude-pm" / "agents"
48
+ logger.info(f"Project agents directory: {self.project_agents_dir}")
49
+
50
+ def _find_framework_directory(self) -> Optional[Path]:
51
+ """Find directory containing agents/INSTRUCTIONS.md (or legacy CLAUDE.md)"""
52
+ # Check if we're running from a wheel installation
53
+ try:
54
+ import claude_pm
55
+ package_path = Path(claude_pm.__file__).parent
56
+ path_str = str(package_path.resolve())
57
+ if 'site-packages' in path_str or 'dist-packages' in path_str:
58
+ # For wheel installations, check data directory
59
+ data_instructions = package_path / "data" / "agents" / "INSTRUCTIONS.md"
60
+ data_claude = package_path / "data" / "agents" / "CLAUDE.md"
61
+ if data_instructions.exists() or data_claude.exists():
62
+ return package_path / "data"
63
+ except Exception:
64
+ pass
65
+
66
+ current = Path.cwd()
67
+
68
+ # Check current directory and parents
69
+ for path in [current] + list(current.parents):
70
+ framework_instructions = path / "agents" / "INSTRUCTIONS.md"
71
+ framework_claude = path / "agents" / "CLAUDE.md" # Legacy
72
+ if framework_instructions.exists() or framework_claude.exists():
73
+ return path
74
+
75
+ return None
76
+
77
+ def _find_project_directory(self) -> Optional[Path]:
78
+ """Find project directory containing .claude-pm"""
79
+ current = Path.cwd()
80
+
81
+ # Check current directory and parents for .claude-pm
82
+ for path in [current] + list(current.parents):
83
+ claude_pm_dir = path / ".claude-pm"
84
+ if claude_pm_dir.exists():
85
+ return path
86
+
87
+ return None
88
+
89
+ def load_agent_profile(self, agent_type: str) -> Optional[Dict[str, Any]]:
90
+ """
91
+ Load agent profile with precedence: Project → Framework (user → trained → system)
92
+
93
+ Args:
94
+ agent_type: Agent type (Engineer, Documenter, QA, etc.)
95
+
96
+ Returns:
97
+ Agent profile dictionary or None if not found
98
+ """
99
+ # Check cache first
100
+ cache_key = agent_type.lower()
101
+ if cache_key in self._profile_cache:
102
+ return self._profile_cache[cache_key]
103
+
104
+ profile = None
105
+
106
+ # 1. Try project agents first (highest precedence)
107
+ if self.project_agents_dir:
108
+ profile = self._load_profile_from_directory(
109
+ self.project_agents_dir / "project", agent_type
110
+ )
111
+
112
+ # 2. Try framework agents (user → trained → system)
113
+ if not profile and self.framework_agents_dir:
114
+ # Framework user agents
115
+ profile = self._load_profile_from_directory(
116
+ self.framework_agents_dir / "user", agent_type
117
+ )
118
+
119
+ # Framework trained agents
120
+ if not profile:
121
+ profile = self._load_profile_from_directory(
122
+ self.framework_agents_dir / "trained", agent_type
123
+ )
124
+
125
+ # Framework system agents (fallback)
126
+ if not profile:
127
+ profile = self._load_profile_from_directory(
128
+ self.framework_agents_dir / "system", agent_type
129
+ )
130
+
131
+ # Cache result
132
+ if profile:
133
+ self._profile_cache[cache_key] = profile
134
+
135
+ return profile
136
+
137
+ def _load_profile_from_directory(self, directory: Path, agent_type: str) -> Optional[Dict[str, Any]]:
138
+ """Load agent profile from specific directory"""
139
+ if not directory.exists():
140
+ return None
141
+
142
+ profile_file = directory / f"{agent_type}.md"
143
+ if not profile_file.exists():
144
+ return None
145
+
146
+ try:
147
+ content = profile_file.read_text(encoding='utf-8')
148
+ return self._parse_agent_profile(content, str(profile_file))
149
+ except Exception as e:
150
+ logger.error(f"Error loading profile {profile_file}: {e}")
151
+ return None
152
+
153
+ def _parse_agent_profile(self, content: str, source_path: str) -> Dict[str, Any]:
154
+ """Parse agent profile markdown into structured data"""
155
+ profile = {
156
+ 'source_path': source_path,
157
+ 'raw_content': content,
158
+ 'role': '',
159
+ 'capabilities': [],
160
+ 'context_preferences': {},
161
+ 'authority_scope': [],
162
+ 'quality_standards': [],
163
+ 'escalation_criteria': [],
164
+ 'integration_patterns': {}
165
+ }
166
+
167
+ lines = content.split('\n')
168
+ current_section = None
169
+ current_content = []
170
+
171
+ for line in lines:
172
+ line = line.strip()
173
+
174
+ # Detect sections
175
+ if line.startswith('## Role'):
176
+ # Process previous section
177
+ if current_section and current_content:
178
+ self._process_section(profile, current_section, current_content)
179
+ current_section = 'role'
180
+ current_content = []
181
+ elif line.startswith('## Capabilities'):
182
+ if current_section and current_content:
183
+ self._process_section(profile, current_section, current_content)
184
+ current_section = 'capabilities'
185
+ current_content = []
186
+ elif line.startswith('## Context Preferences'):
187
+ if current_section and current_content:
188
+ self._process_section(profile, current_section, current_content)
189
+ current_section = 'context_preferences'
190
+ current_content = []
191
+ elif line.startswith('## Authority Scope'):
192
+ if current_section and current_content:
193
+ self._process_section(profile, current_section, current_content)
194
+ current_section = 'authority_scope'
195
+ current_content = []
196
+ elif line.startswith('## Quality Standards'):
197
+ if current_section and current_content:
198
+ self._process_section(profile, current_section, current_content)
199
+ current_section = 'quality_standards'
200
+ current_content = []
201
+ elif line.startswith('## Escalation Criteria'):
202
+ if current_section and current_content:
203
+ self._process_section(profile, current_section, current_content)
204
+ current_section = 'escalation_criteria'
205
+ current_content = []
206
+ elif line.startswith('## Integration Patterns'):
207
+ if current_section and current_content:
208
+ self._process_section(profile, current_section, current_content)
209
+ current_section = 'integration_patterns'
210
+ current_content = []
211
+ elif line.startswith('#'):
212
+ # Process previous section before starting new one
213
+ if current_section and current_content:
214
+ self._process_section(profile, current_section, current_content)
215
+ current_section = None
216
+ current_content = []
217
+ elif current_section and line:
218
+ current_content.append(line)
219
+
220
+ # Process final section
221
+ if current_section and current_content:
222
+ self._process_section(profile, current_section, current_content)
223
+
224
+ return profile
225
+
226
+ def _process_section(self, profile: Dict[str, Any], section: str, content: list):
227
+ """Process section content into profile structure"""
228
+ text = '\n'.join(content).strip()
229
+
230
+ if section == 'role':
231
+ profile['role'] = text
232
+ elif section == 'capabilities':
233
+ # Extract bullet points
234
+ capabilities = []
235
+ for line in content:
236
+ if line.startswith('- **') and '**:' in line:
237
+ cap = line.split('**:')[0].replace('- **', '').strip()
238
+ capabilities.append(cap)
239
+ profile['capabilities'] = capabilities
240
+ elif section == 'context_preferences':
241
+ # Extract Include/Exclude/Focus
242
+ prefs = {}
243
+ for line in content:
244
+ if line.startswith('- **Include**:'):
245
+ prefs['include'] = line.replace('- **Include**:', '').strip()
246
+ elif line.startswith('- **Exclude**:'):
247
+ prefs['exclude'] = line.replace('- **Exclude**:', '').strip()
248
+ elif line.startswith('- **Focus**:'):
249
+ prefs['focus'] = line.replace('- **Focus**:', '').strip()
250
+ profile['context_preferences'] = prefs
251
+ elif section in ['authority_scope', 'quality_standards', 'escalation_criteria']:
252
+ # Extract bullet points
253
+ items = []
254
+ for line in content:
255
+ if line.startswith('- **') and '**:' in line:
256
+ item = line.split('**:')[0].replace('- **', '').strip()
257
+ items.append(item)
258
+ profile[section] = items
259
+ elif section == 'integration_patterns':
260
+ # Extract With X: patterns
261
+ patterns = {}
262
+ for line in content:
263
+ if line.startswith('- **With ') and '**:' in line:
264
+ agent = line.split('**:')[0].replace('- **With ', '').replace('**', '').strip()
265
+ desc = line.split('**:')[1].strip()
266
+ patterns[agent] = desc
267
+ profile['integration_patterns'] = patterns
268
+
269
+ def get_available_agents(self) -> Dict[str, list]:
270
+ """Get list of available agents by tier"""
271
+ agents = {
272
+ 'project': [],
273
+ 'framework_user': [],
274
+ 'framework_trained': [],
275
+ 'framework_system': []
276
+ }
277
+
278
+ # Project agents
279
+ if self.project_agents_dir:
280
+ project_dir = self.project_agents_dir / "project"
281
+ if project_dir.exists():
282
+ agents['project'] = [f.stem for f in project_dir.glob("*.md")]
283
+
284
+ # Framework agents
285
+ if self.framework_agents_dir:
286
+ for tier in ['user', 'trained', 'system']:
287
+ tier_dir = self.framework_agents_dir / tier
288
+ if tier_dir.exists():
289
+ agents[f'framework_{tier}'] = [f.stem for f in tier_dir.glob("*.md")]
290
+
291
+ return agents
292
+
293
+ def generate_profile_loading_instruction(self, agent_type: str) -> str:
294
+ """Generate instruction for subprocess to load its own profile"""
295
+ profile = self.load_agent_profile(agent_type)
296
+
297
+ if not profile:
298
+ return f"""
299
+ **{agent_type} Agent**: No profile found. Operating with basic capabilities.
300
+
301
+ **Task Context**: Please proceed with the assigned task using standard practices.
302
+ """
303
+
304
+ instruction = f"""
305
+ **{agent_type} Agent Profile Loaded**
306
+
307
+ **Agent Identity**: {agent_type} Agent
308
+ **Profile Source**: {profile.get('source_path', 'Unknown')}
309
+ **Primary Role**: {profile.get('role', 'Not specified')}
310
+
311
+ **Core Capabilities**:
312
+ """
313
+
314
+ for capability in profile.get('capabilities', [])[:5]: # Top 5 capabilities
315
+ instruction += f"- **{capability}**: Primary capability area\n"
316
+
317
+ instruction += f"""
318
+ **Context Preferences**:
319
+ - **Include**: {profile.get('context_preferences', {}).get('include', 'Not specified')}
320
+ - **Exclude**: {profile.get('context_preferences', {}).get('exclude', 'Not specified')}
321
+ - **Focus**: {profile.get('context_preferences', {}).get('focus', 'Not specified')}
322
+
323
+ **Authority Scope**:
324
+ """
325
+
326
+ for authority in profile.get('authority_scope', [])[:3]: # Top 3 authorities
327
+ instruction += f"- **{authority}**: Authorized operation area\n"
328
+
329
+ instruction += f"""
330
+ **Quality Standards**: {len(profile.get('quality_standards', []))} standards defined
331
+ **Escalation Triggers**: {len(profile.get('escalation_criteria', []))} criteria defined
332
+ **Integration Partners**: {len(profile.get('integration_patterns', {}))} agent coordination patterns
333
+
334
+ Please operate according to your profile specifications and maintain quality standards.
335
+ """
336
+
337
+ return instruction.strip()
@@ -0,0 +1,92 @@
1
+ # Framework CLAUDE.md Generator
2
+
3
+ This directory contains the refactored framework CLAUDE.md generator service, originally a single 1,267-line file.
4
+
5
+ ## Structure
6
+
7
+ ### Core Modules
8
+
9
+ - **`__init__.py`** (~250 lines) - Main facade class that coordinates all functionality
10
+ - **`version_manager.py`** (~100 lines) - Handles version parsing, incrementing, and comparison
11
+ - **`content_assembler.py`** (~120 lines) - Assembles sections and applies template variables
12
+ - **`content_validator.py`** (~80 lines) - Validates generated content structure and completeness
13
+ - **`deployment_manager.py`** (~80 lines) - Handles deployment to parent directories
14
+ - **`section_manager.py`** (~60 lines) - Manages section registration, ordering, and updates
15
+
16
+ ### Section Generators
17
+
18
+ The `section_generators/` subdirectory contains individual generators for each section:
19
+
20
+ - **`__init__.py`** - Base classes and registry
21
+ - **`header.py`** - Header with version metadata
22
+ - **`role_designation.py`** - AI Assistant role designation
23
+ - **`agents.py`** (~570 lines) - Comprehensive agents documentation (largest section)
24
+ - **`todo_task_tools.py`** - Todo and Task Tools integration
25
+ - **`claude_pm_init.py`** - Claude-PM initialization procedures
26
+ - **`orchestration_principles.py`** - Core orchestration principles
27
+ - **`subprocess_validation.py`** - Subprocess validation protocol
28
+ - **`delegation_constraints.py`** - Critical delegation constraints
29
+ - **`environment_config.py`** - Environment configuration
30
+ - **`troubleshooting.py`** - Troubleshooting guide
31
+ - **`core_responsibilities.py`** - Core responsibilities list
32
+ - **`footer.py`** - Footer with metadata
33
+
34
+ ## Usage
35
+
36
+ The API remains unchanged from the original implementation:
37
+
38
+ ```python
39
+ from claude_pm.services.framework_claude_md_generator import FrameworkClaudeMdGenerator
40
+
41
+ # Create generator instance
42
+ generator = FrameworkClaudeMdGenerator()
43
+
44
+ # Generate content
45
+ content = generator.generate(
46
+ current_content=existing_content, # Optional: for version auto-increment
47
+ template_variables={'PLATFORM': 'darwin', 'PYTHON_CMD': 'python3'}
48
+ )
49
+
50
+ # Deploy to parent directory
51
+ success, message = generator.deploy_to_parent(Path('/parent/dir'))
52
+
53
+ # Update a section
54
+ generator.update_section('agents', 'Custom agents content')
55
+
56
+ # Add custom section
57
+ generator.add_custom_section('custom', 'Custom content', after='agents')
58
+ ```
59
+
60
+ ## Design Benefits
61
+
62
+ 1. **Modularity**: Each concern is separated into its own module
63
+ 2. **Maintainability**: Smaller, focused modules are easier to understand and modify
64
+ 3. **Testability**: Individual components can be tested in isolation
65
+ 4. **Extensibility**: New section generators can be added easily
66
+ 5. **Performance**: Section generators are loaded on demand
67
+ 6. **Backward Compatibility**: Original API preserved through facade pattern
68
+
69
+ ## Section Generator Pattern
70
+
71
+ To add a new section generator:
72
+
73
+ 1. Create a new file in `section_generators/`
74
+ 2. Inherit from `BaseSectionGenerator`
75
+ 3. Implement the `generate()` method
76
+ 4. Register in `section_generators/__init__.py`
77
+
78
+ Example:
79
+ ```python
80
+ from . import BaseSectionGenerator
81
+
82
+ class CustomSectionGenerator(BaseSectionGenerator):
83
+ def generate(self, data: Dict[str, Any]) -> str:
84
+ return "## Custom Section\n\nContent here..."
85
+ ```
86
+
87
+ ## Refactoring Summary
88
+
89
+ - **Original**: 1,267 lines in a single file
90
+ - **Refactored**: ~250 lines in main module + well-organized submodules
91
+ - **Total line reduction**: Main module reduced by 80%
92
+ - **Improved organization**: 13 focused modules instead of 1 large file
@@ -0,0 +1,206 @@
1
+ """
2
+ Framework INSTRUCTIONS.md Generator Service
3
+
4
+ This service provides structured generation of the framework INSTRUCTIONS.md template
5
+ (legacy: CLAUDE.md) with auto-versioning, section management, and deployment capabilities.
6
+ """
7
+
8
+ from typing import Dict, Optional, Any, List, Tuple
9
+ from pathlib import Path
10
+
11
+ from .version_manager import VersionManager
12
+ from .content_validator import ContentValidator
13
+ from .content_assembler import ContentAssembler
14
+ from .deployment_manager import DeploymentManager
15
+ from .section_manager import SectionManager
16
+ from .section_generators import section_registry
17
+
18
+
19
+ class FrameworkClaudeMdGenerator:
20
+ """
21
+ Generates and manages the framework INSTRUCTIONS.md template (legacy: CLAUDE.md)
22
+ with structured sections, auto-versioning, and deployment capabilities.
23
+
24
+ This is the main facade class that coordinates all the submodules.
25
+ """
26
+
27
+ def __init__(self):
28
+ """Initialize the generator with current framework version."""
29
+ # Initialize managers
30
+ self.version_manager = VersionManager()
31
+ self.validator = ContentValidator()
32
+ self.assembler = ContentAssembler()
33
+ self.section_manager = SectionManager()
34
+
35
+ # Initialize deployment manager with dependencies
36
+ self.deployment_manager = DeploymentManager(
37
+ self.version_manager,
38
+ self.validator
39
+ )
40
+
41
+ # Get framework version
42
+ self.framework_version = self.version_manager.framework_version
43
+
44
+ # Initialize sections
45
+ self._initialize_sections()
46
+
47
+ def _initialize_sections(self):
48
+ """Initialize all sections in the required order."""
49
+ # Register all default sections with their generators
50
+ section_order = [
51
+ 'header',
52
+ 'role_designation',
53
+ 'agents',
54
+ 'todo_task_tools',
55
+ 'claude_pm_init',
56
+ 'orchestration_principles',
57
+ 'subprocess_validation',
58
+ 'delegation_constraints',
59
+ 'environment_config',
60
+ 'troubleshooting',
61
+ 'core_responsibilities',
62
+ 'footer'
63
+ ]
64
+
65
+ for section_name in section_order:
66
+ generator_class = section_registry.get(section_name)
67
+ if generator_class:
68
+ generator_instance = generator_class(self.framework_version)
69
+ self.section_manager.register_section(
70
+ section_name,
71
+ generator_instance.generate
72
+ )
73
+
74
+ def generate(self,
75
+ current_content: Optional[str] = None,
76
+ template_variables: Optional[Dict[str, str]] = None) -> str:
77
+ """
78
+ Generate the complete INSTRUCTIONS.md/CLAUDE.md content.
79
+
80
+ Args:
81
+ current_content: Current INSTRUCTIONS.md/CLAUDE.md content for version parsing
82
+ template_variables: Variables to substitute in the template
83
+
84
+ Returns:
85
+ str: Complete INSTRUCTIONS.md/CLAUDE.md content
86
+ """
87
+ # Auto-increment version if current content provided
88
+ version = self.version_manager.auto_increment_version(current_content)
89
+
90
+ # Create metadata for header
91
+ metadata = self.assembler.create_metadata_dict(
92
+ version=version,
93
+ framework_version=self.framework_version
94
+ )
95
+
96
+ # Update header section with metadata
97
+ sections = self.section_manager.get_sections()
98
+ if 'header' in sections:
99
+ generator_func, _ = sections['header']
100
+ sections['header'] = (generator_func, metadata)
101
+
102
+ # Assemble content
103
+ content = self.assembler.assemble_content(
104
+ sections,
105
+ template_variables
106
+ )
107
+
108
+ return content
109
+
110
+ def validate_content(self, content: str) -> Tuple[bool, List[str]]:
111
+ """
112
+ Validate that generated content has all required sections.
113
+
114
+ Args:
115
+ content: Content to validate
116
+
117
+ Returns:
118
+ Tuple of (is_valid, list_of_issues)
119
+ """
120
+ return self.validator.validate_content(content)
121
+
122
+ def deploy_to_parent(self, parent_path: Path, force: bool = False) -> Tuple[bool, str]:
123
+ """
124
+ Deploy generated content to a parent directory.
125
+
126
+ Args:
127
+ parent_path: Path to parent directory
128
+ force: Force deployment even if versions match
129
+
130
+ Returns:
131
+ Tuple of (success, message)
132
+ """
133
+ # Check if we need to read existing content
134
+ # Try INSTRUCTIONS.md first, fallback to CLAUDE.md for compatibility
135
+ target_file = parent_path / "INSTRUCTIONS.md"
136
+ if not target_file.exists() and (parent_path / "CLAUDE.md").exists():
137
+ target_file = parent_path / "CLAUDE.md"
138
+ current_content = None
139
+
140
+ if target_file.exists():
141
+ with open(target_file, 'r') as f:
142
+ current_content = f.read()
143
+
144
+ # Generate new content
145
+ new_content = self.generate(current_content=current_content)
146
+
147
+ # Deploy using deployment manager
148
+ return self.deployment_manager.deploy_to_parent(
149
+ new_content,
150
+ parent_path,
151
+ force
152
+ )
153
+
154
+ def get_section_list(self) -> List[str]:
155
+ """
156
+ Get list of all section names in order.
157
+
158
+ Returns:
159
+ List of section names
160
+ """
161
+ return self.section_manager.get_section_list()
162
+
163
+ def update_section(self, section_name: str, content: str) -> bool:
164
+ """
165
+ Update a specific section's generator to return custom content.
166
+
167
+ Args:
168
+ section_name: Name of section to update
169
+ content: New content for the section
170
+
171
+ Returns:
172
+ bool: Success status
173
+ """
174
+ return self.section_manager.update_section(section_name, content)
175
+
176
+ def add_custom_section(self, section_name: str, content: str, after: Optional[str] = None):
177
+ """
178
+ Add a custom section to the generator.
179
+
180
+ Args:
181
+ section_name: Name for the new section
182
+ content: Content for the section
183
+ after: Section name to insert after (None = append at end)
184
+ """
185
+ self.section_manager.add_custom_section(section_name, content, after)
186
+
187
+ # Compatibility methods to match original API
188
+ def _get_framework_version(self) -> str:
189
+ """Get framework version (compatibility method)."""
190
+ return self.version_manager._get_framework_version()
191
+
192
+ def _parse_current_version(self, content: str) -> Tuple[str, int]:
193
+ """Parse current version (compatibility method)."""
194
+ return self.version_manager.parse_current_version(content)
195
+
196
+ def _auto_increment_version(self, current_content: Optional[str] = None) -> str:
197
+ """Auto-increment version (compatibility method)."""
198
+ return self.version_manager.auto_increment_version(current_content)
199
+
200
+ def _generate_content_hash(self) -> str:
201
+ """Generate content hash (compatibility method)."""
202
+ return self.assembler.generate_content_hash()
203
+
204
+
205
+ # Export the main class
206
+ __all__ = ['FrameworkClaudeMdGenerator']