claude-mpm 4.4.3__py3-none-any.whl → 4.4.5__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.
Files changed (118) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/agent_loader.py +3 -2
  3. claude_mpm/agents/agent_loader_integration.py +2 -1
  4. claude_mpm/agents/async_agent_loader.py +2 -2
  5. claude_mpm/agents/base_agent_loader.py +2 -2
  6. claude_mpm/agents/frontmatter_validator.py +1 -0
  7. claude_mpm/agents/system_agent_config.py +2 -1
  8. claude_mpm/cli/commands/doctor.py +44 -5
  9. claude_mpm/cli/commands/mpm_init.py +116 -62
  10. claude_mpm/cli/parsers/configure_parser.py +3 -1
  11. claude_mpm/cli/startup_logging.py +1 -3
  12. claude_mpm/config/agent_config.py +1 -1
  13. claude_mpm/config/paths.py +2 -1
  14. claude_mpm/core/agent_name_normalizer.py +1 -0
  15. claude_mpm/core/config.py +2 -1
  16. claude_mpm/core/config_aliases.py +2 -1
  17. claude_mpm/core/file_utils.py +0 -1
  18. claude_mpm/core/framework/__init__.py +6 -6
  19. claude_mpm/core/framework/formatters/__init__.py +2 -2
  20. claude_mpm/core/framework/formatters/capability_generator.py +19 -8
  21. claude_mpm/core/framework/formatters/content_formatter.py +8 -3
  22. claude_mpm/core/framework/formatters/context_generator.py +7 -3
  23. claude_mpm/core/framework/loaders/__init__.py +3 -3
  24. claude_mpm/core/framework/loaders/agent_loader.py +7 -3
  25. claude_mpm/core/framework/loaders/file_loader.py +16 -6
  26. claude_mpm/core/framework/loaders/instruction_loader.py +16 -6
  27. claude_mpm/core/framework/loaders/packaged_loader.py +36 -12
  28. claude_mpm/core/framework/processors/__init__.py +2 -2
  29. claude_mpm/core/framework/processors/memory_processor.py +14 -6
  30. claude_mpm/core/framework/processors/metadata_processor.py +5 -5
  31. claude_mpm/core/framework/processors/template_processor.py +12 -6
  32. claude_mpm/core/framework_loader.py +44 -20
  33. claude_mpm/core/log_manager.py +2 -1
  34. claude_mpm/core/tool_access_control.py +1 -0
  35. claude_mpm/core/unified_agent_registry.py +2 -1
  36. claude_mpm/core/unified_paths.py +1 -0
  37. claude_mpm/experimental/cli_enhancements.py +1 -0
  38. claude_mpm/hooks/base_hook.py +1 -0
  39. claude_mpm/hooks/instruction_reinforcement.py +1 -0
  40. claude_mpm/hooks/kuzu_memory_hook.py +20 -13
  41. claude_mpm/hooks/validation_hooks.py +1 -1
  42. claude_mpm/scripts/mpm_doctor.py +1 -0
  43. claude_mpm/services/agents/loading/agent_profile_loader.py +1 -1
  44. claude_mpm/services/agents/loading/base_agent_manager.py +1 -1
  45. claude_mpm/services/agents/loading/framework_agent_loader.py +1 -1
  46. claude_mpm/services/agents/management/agent_capabilities_generator.py +1 -0
  47. claude_mpm/services/agents/management/agent_management_service.py +1 -1
  48. claude_mpm/services/agents/memory/memory_categorization_service.py +0 -1
  49. claude_mpm/services/agents/memory/memory_file_service.py +6 -2
  50. claude_mpm/services/agents/memory/memory_format_service.py +0 -1
  51. claude_mpm/services/agents/registry/deployed_agent_discovery.py +1 -1
  52. claude_mpm/services/async_session_logger.py +1 -1
  53. claude_mpm/services/claude_session_logger.py +1 -0
  54. claude_mpm/services/core/path_resolver.py +1 -0
  55. claude_mpm/services/diagnostics/checks/__init__.py +2 -0
  56. claude_mpm/services/diagnostics/checks/installation_check.py +126 -25
  57. claude_mpm/services/diagnostics/checks/mcp_services_check.py +451 -0
  58. claude_mpm/services/diagnostics/diagnostic_runner.py +3 -0
  59. claude_mpm/services/diagnostics/doctor_reporter.py +259 -32
  60. claude_mpm/services/event_bus/direct_relay.py +2 -1
  61. claude_mpm/services/event_bus/event_bus.py +1 -0
  62. claude_mpm/services/event_bus/relay.py +3 -2
  63. claude_mpm/services/framework_claude_md_generator/content_assembler.py +1 -1
  64. claude_mpm/services/infrastructure/daemon_manager.py +1 -1
  65. claude_mpm/services/mcp_config_manager.py +301 -54
  66. claude_mpm/services/mcp_gateway/core/process_pool.py +62 -23
  67. claude_mpm/services/mcp_gateway/tools/__init__.py +6 -5
  68. claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +3 -1
  69. claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +16 -31
  70. claude_mpm/services/memory/cache/simple_cache.py +1 -1
  71. claude_mpm/services/project/archive_manager.py +159 -96
  72. claude_mpm/services/project/documentation_manager.py +64 -45
  73. claude_mpm/services/project/enhanced_analyzer.py +132 -89
  74. claude_mpm/services/project/project_organizer.py +225 -131
  75. claude_mpm/services/response_tracker.py +1 -1
  76. claude_mpm/services/socketio/server/eventbus_integration.py +1 -1
  77. claude_mpm/services/unified/__init__.py +1 -1
  78. claude_mpm/services/unified/analyzer_strategies/__init__.py +3 -3
  79. claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +97 -53
  80. claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +81 -40
  81. claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +277 -178
  82. claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +196 -112
  83. claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +83 -49
  84. claude_mpm/services/unified/config_strategies/__init__.py +111 -126
  85. claude_mpm/services/unified/config_strategies/config_schema.py +157 -111
  86. claude_mpm/services/unified/config_strategies/context_strategy.py +91 -89
  87. claude_mpm/services/unified/config_strategies/error_handling_strategy.py +183 -173
  88. claude_mpm/services/unified/config_strategies/file_loader_strategy.py +160 -152
  89. claude_mpm/services/unified/config_strategies/unified_config_service.py +124 -112
  90. claude_mpm/services/unified/config_strategies/validation_strategy.py +298 -259
  91. claude_mpm/services/unified/deployment_strategies/__init__.py +7 -7
  92. claude_mpm/services/unified/deployment_strategies/base.py +24 -28
  93. claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +168 -88
  94. claude_mpm/services/unified/deployment_strategies/local.py +49 -34
  95. claude_mpm/services/unified/deployment_strategies/utils.py +39 -43
  96. claude_mpm/services/unified/deployment_strategies/vercel.py +30 -24
  97. claude_mpm/services/unified/interfaces.py +0 -26
  98. claude_mpm/services/unified/migration.py +17 -40
  99. claude_mpm/services/unified/strategies.py +9 -26
  100. claude_mpm/services/unified/unified_analyzer.py +48 -44
  101. claude_mpm/services/unified/unified_config.py +21 -19
  102. claude_mpm/services/unified/unified_deployment.py +21 -26
  103. claude_mpm/storage/state_storage.py +1 -0
  104. claude_mpm/utils/agent_dependency_loader.py +18 -6
  105. claude_mpm/utils/common.py +14 -12
  106. claude_mpm/utils/database_connector.py +15 -12
  107. claude_mpm/utils/error_handler.py +1 -0
  108. claude_mpm/utils/log_cleanup.py +1 -0
  109. claude_mpm/utils/path_operations.py +1 -0
  110. claude_mpm/utils/session_logging.py +1 -1
  111. claude_mpm/utils/subprocess_utils.py +1 -0
  112. claude_mpm/validation/agent_validator.py +1 -1
  113. {claude_mpm-4.4.3.dist-info → claude_mpm-4.4.5.dist-info}/METADATA +35 -15
  114. {claude_mpm-4.4.3.dist-info → claude_mpm-4.4.5.dist-info}/RECORD +118 -117
  115. {claude_mpm-4.4.3.dist-info → claude_mpm-4.4.5.dist-info}/WHEEL +0 -0
  116. {claude_mpm-4.4.3.dist-info → claude_mpm-4.4.5.dist-info}/entry_points.txt +0 -0
  117. {claude_mpm-4.4.3.dist-info → claude_mpm-4.4.5.dist-info}/licenses/LICENSE +0 -0
  118. {claude_mpm-4.4.3.dist-info → claude_mpm-4.4.5.dist-info}/top_level.txt +0 -0
@@ -22,7 +22,6 @@ from claude_mpm.core.logging_utils import get_logger
22
22
  logger = get_logger(__name__)
23
23
 
24
24
 
25
-
26
25
  # ==============================================================================
27
26
  # PATH UTILITIES
28
27
  # ==============================================================================
@@ -4,17 +4,17 @@ This module provides the modular framework loading system with specialized compo
4
4
  for handling different aspects of framework initialization and management.
5
5
  """
6
6
 
7
+ from .formatters import (
8
+ CapabilityGenerator,
9
+ ContentFormatter,
10
+ ContextGenerator,
11
+ )
7
12
  from .loaders import (
8
13
  AgentLoader,
9
14
  FileLoader,
10
15
  InstructionLoader,
11
16
  PackagedLoader,
12
17
  )
13
- from .formatters import (
14
- CapabilityGenerator,
15
- ContentFormatter,
16
- ContextGenerator,
17
- )
18
18
  from .processors import (
19
19
  MemoryProcessor,
20
20
  MetadataProcessor,
@@ -35,4 +35,4 @@ __all__ = [
35
35
  "MetadataProcessor",
36
36
  "TemplateProcessor",
37
37
  "MemoryProcessor",
38
- ]
38
+ ]
@@ -5,7 +5,7 @@ from .content_formatter import ContentFormatter
5
5
  from .context_generator import ContextGenerator
6
6
 
7
7
  __all__ = [
8
- "ContentFormatter",
9
8
  "CapabilityGenerator",
9
+ "ContentFormatter",
10
10
  "ContextGenerator",
11
- ]
11
+ ]
@@ -1,7 +1,6 @@
1
1
  """Agent capability generator for dynamic agent discovery."""
2
2
 
3
3
  import json
4
- import time
5
4
  from pathlib import Path
6
5
  from typing import Any, Dict, List, Optional
7
6
 
@@ -128,7 +127,9 @@ class CapabilityGenerator:
128
127
  if agent.get("memory_routing"):
129
128
  memory_routing = agent["memory_routing"]
130
129
  if memory_routing.get("description"):
131
- section += f"- **Memory Routing**: {memory_routing['description']}\n"
130
+ section += (
131
+ f"- **Memory Routing**: {memory_routing['description']}\n"
132
+ )
132
133
 
133
134
  # Add simple Context-Aware Agent Selection
134
135
  section += "\n## Context-Aware Agent Selection\n\n"
@@ -159,7 +160,9 @@ class CapabilityGenerator:
159
160
  # Default values
160
161
  agent_data = {
161
162
  "id": agent_file.stem,
162
- "display_name": agent_file.stem.replace("_", " ").replace("-", " ").title(),
163
+ "display_name": agent_file.stem.replace("_", " ")
164
+ .replace("-", " ")
165
+ .title(),
163
166
  "description": "Specialized agent",
164
167
  }
165
168
 
@@ -191,7 +194,9 @@ class CapabilityGenerator:
191
194
 
192
195
  # Try to load memory routing metadata from JSON template
193
196
  if "memory_routing" not in agent_data:
194
- memory_routing_data = self.load_memory_routing_from_template(agent_file.stem)
197
+ memory_routing_data = self.load_memory_routing_from_template(
198
+ agent_file.stem
199
+ )
195
200
  if memory_routing_data:
196
201
  agent_data["memory_routing"] = memory_routing_data
197
202
 
@@ -233,7 +238,9 @@ class CapabilityGenerator:
233
238
  return None
234
239
 
235
240
  # For development mode, load from filesystem
236
- templates_dir = framework_path / "src" / "claude_mpm" / "agents" / "templates"
241
+ templates_dir = (
242
+ framework_path / "src" / "claude_mpm" / "agents" / "templates"
243
+ )
237
244
  template_file = templates_dir / f"{agent_name}.json"
238
245
 
239
246
  if template_file.exists():
@@ -297,7 +304,9 @@ class CapabilityGenerator:
297
304
  return None
298
305
 
299
306
  # For development mode, load from filesystem
300
- templates_dir = framework_path / "src" / "claude_mpm" / "agents" / "templates"
307
+ templates_dir = (
308
+ framework_path / "src" / "claude_mpm" / "agents" / "templates"
309
+ )
301
310
  template_file = templates_dir / f"{agent_name}.json"
302
311
 
303
312
  if template_file.exists():
@@ -328,7 +337,9 @@ class CapabilityGenerator:
328
337
  return None
329
338
 
330
339
  except Exception as e:
331
- self.logger.debug(f"Could not load memory routing from template for {agent_name}: {e}")
340
+ self.logger.debug(
341
+ f"Could not load memory routing from template for {agent_name}: {e}"
342
+ )
332
343
  return None
333
344
 
334
345
  def get_fallback_capabilities(self) -> str:
@@ -353,4 +364,4 @@ You have the following specialized agents available for delegation:
353
364
  - **Version Control** (`version-control`): Git operations and version management
354
365
 
355
366
  **IMPORTANT**: Use the exact agent ID in parentheses when delegating tasks.
356
- """
367
+ """
@@ -174,7 +174,10 @@ You are a multi-agent orchestrator. Your primary responsibilities are:
174
174
  # Use the actual agent_name as the ID (it's the filename stem)
175
175
  agent_id = agent_name
176
176
  clean_name = agent_name.replace("-", " ").replace("_", " ").title()
177
- if "engineer" in agent_name.lower() and "data" not in agent_name.lower():
177
+ if (
178
+ "engineer" in agent_name.lower()
179
+ and "data" not in agent_name.lower()
180
+ ):
178
181
  agent_list.append(
179
182
  f"- **Engineer Agent** (`{agent_id}`): Code implementation and development"
180
183
  )
@@ -215,7 +218,9 @@ You are a multi-agent orchestrator. Your primary responsibilities are:
215
218
 
216
219
  # Add full agent details
217
220
  instructions += "### Agent Details\n\n"
218
- for agent_name, agent_content in sorted(framework_content["agents"].items()):
221
+ for agent_name, agent_content in sorted(
222
+ framework_content["agents"].items()
223
+ ):
219
224
  instructions += f"#### {agent_name.replace('-', ' ').title()}\n"
220
225
  instructions += agent_content + "\n\n"
221
226
 
@@ -280,4 +285,4 @@ You have the following specialized agents available for delegation:
280
285
  - **Version Control** (`version-control`): Git operations and version management
281
286
 
282
287
  **IMPORTANT**: Use the exact agent ID in parentheses when delegating tasks.
283
- """
288
+ """
@@ -54,7 +54,9 @@ class ContextGenerator:
54
54
  time_str = now.strftime("%H:%M:%S")
55
55
  day_name = now.strftime("%A")
56
56
 
57
- context_lines.append(f"**Current DateTime**: {date_str} {time_str} {tz_info}\n")
57
+ context_lines.append(
58
+ f"**Current DateTime**: {date_str} {time_str} {tz_info}\n"
59
+ )
58
60
  context_lines.append(f"**Day**: {day_name}\n")
59
61
 
60
62
  except Exception as e:
@@ -148,7 +150,9 @@ class ContextGenerator:
148
150
  try:
149
151
  platform_version = platform.release()
150
152
  if platform_version:
151
- context_lines.append(f"**System Version**: {platform_version}\n")
153
+ context_lines.append(
154
+ f"**System Version**: {platform_version}\n"
155
+ )
152
156
  except Exception:
153
157
  pass
154
158
 
@@ -177,4 +181,4 @@ class ContextGenerator:
177
181
  context_lines.append(f"**Locale**: {current_locale[0]}\n")
178
182
  except Exception:
179
183
  # Locale is optional
180
- pass
184
+ pass
@@ -6,8 +6,8 @@ from .instruction_loader import InstructionLoader
6
6
  from .packaged_loader import PackagedLoader
7
7
 
8
8
  __all__ = [
9
+ "AgentLoader",
9
10
  "FileLoader",
10
- "PackagedLoader",
11
11
  "InstructionLoader",
12
- "AgentLoader",
13
- ]
12
+ "PackagedLoader",
13
+ ]
@@ -47,7 +47,9 @@ class AgentLoader:
47
47
  self.logger.debug(f"Total deployed agents found: {len(deployed)}")
48
48
  return deployed
49
49
 
50
- def load_single_agent(self, agent_file: Path) -> Tuple[Optional[str], Optional[str]]:
50
+ def load_single_agent(
51
+ self, agent_file: Path
52
+ ) -> Tuple[Optional[str], Optional[str]]:
51
53
  """
52
54
  Load a single agent file.
53
55
 
@@ -120,7 +122,9 @@ class AgentLoader:
120
122
 
121
123
  # Check for local JSON templates in priority order
122
124
  template_dirs = [
123
- Path.cwd() / ".claude-mpm" / "agents", # Project local agents (highest priority)
125
+ Path.cwd()
126
+ / ".claude-mpm"
127
+ / "agents", # Project local agents (highest priority)
124
128
  Path.home() / ".claude-mpm" / "agents", # User local agents
125
129
  ]
126
130
 
@@ -199,4 +203,4 @@ class AgentLoader:
199
203
  if "," in tools:
200
204
  return tools
201
205
  return tools
202
- return "Standard Tools"
206
+ return "Standard Tools"
@@ -66,7 +66,9 @@ class FileLoader:
66
66
  if "INSTRUCTIONS.md" in str(file_path):
67
67
  self.framework_last_modified = timestamp
68
68
 
69
- def load_instructions_file(self, current_dir: Path) -> tuple[Optional[str], Optional[str]]:
69
+ def load_instructions_file(
70
+ self, current_dir: Path
71
+ ) -> tuple[Optional[str], Optional[str]]:
70
72
  """
71
73
  Load custom INSTRUCTIONS.md from .claude-mpm directories.
72
74
 
@@ -106,7 +108,9 @@ class FileLoader:
106
108
 
107
109
  return None, None
108
110
 
109
- def load_workflow_file(self, current_dir: Path, framework_path: Path) -> tuple[Optional[str], Optional[str]]:
111
+ def load_workflow_file(
112
+ self, current_dir: Path, framework_path: Path
113
+ ) -> tuple[Optional[str], Optional[str]]:
110
114
  """
111
115
  Load WORKFLOW.md from various locations.
112
116
 
@@ -148,7 +152,9 @@ class FileLoader:
148
152
 
149
153
  # Fall back to system workflow (lowest priority)
150
154
  if framework_path and framework_path != Path("__PACKAGED__"):
151
- system_workflow_path = framework_path / "src" / "claude_mpm" / "agents" / "WORKFLOW.md"
155
+ system_workflow_path = (
156
+ framework_path / "src" / "claude_mpm" / "agents" / "WORKFLOW.md"
157
+ )
152
158
  if system_workflow_path.exists():
153
159
  loaded_content = self.try_load_file(
154
160
  system_workflow_path, "system WORKFLOW.md"
@@ -159,7 +165,9 @@ class FileLoader:
159
165
 
160
166
  return None, None
161
167
 
162
- def load_memory_file(self, current_dir: Path, framework_path: Path) -> tuple[Optional[str], Optional[str]]:
168
+ def load_memory_file(
169
+ self, current_dir: Path, framework_path: Path
170
+ ) -> tuple[Optional[str], Optional[str]]:
163
171
  """
164
172
  Load MEMORY.md from various locations.
165
173
 
@@ -201,7 +209,9 @@ class FileLoader:
201
209
 
202
210
  # Fall back to system memory instructions (lowest priority)
203
211
  if framework_path and framework_path != Path("__PACKAGED__"):
204
- system_memory_path = framework_path / "src" / "claude_mpm" / "agents" / "MEMORY.md"
212
+ system_memory_path = (
213
+ framework_path / "src" / "claude_mpm" / "agents" / "MEMORY.md"
214
+ )
205
215
  if system_memory_path.exists():
206
216
  loaded_content = self.try_load_file(
207
217
  system_memory_path, "system MEMORY.md"
@@ -210,4 +220,4 @@ class FileLoader:
210
220
  self.logger.info("Using system memory instructions")
211
221
  return loaded_content, "system"
212
222
 
213
- return None, None
223
+ return None, None
@@ -75,14 +75,18 @@ class InstructionLoader:
75
75
  content["instructions_version"] = self.file_loader.framework_version
76
76
  content["version"] = self.file_loader.framework_version
77
77
  if self.file_loader.framework_last_modified:
78
- content["instructions_last_modified"] = self.file_loader.framework_last_modified
78
+ content["instructions_last_modified"] = (
79
+ self.file_loader.framework_last_modified
80
+ )
79
81
 
80
82
  # Transfer metadata from packaged loader if available
81
83
  if self.packaged_loader.framework_version:
82
84
  content["instructions_version"] = self.packaged_loader.framework_version
83
85
  content["version"] = self.packaged_loader.framework_version
84
86
  if self.packaged_loader.framework_last_modified:
85
- content["instructions_last_modified"] = self.packaged_loader.framework_last_modified
87
+ content["instructions_last_modified"] = (
88
+ self.packaged_loader.framework_last_modified
89
+ )
86
90
 
87
91
  def _load_filesystem_framework_instructions(self, content: Dict[str, Any]) -> None:
88
92
  """Load framework instructions from filesystem.
@@ -120,7 +124,9 @@ class InstructionLoader:
120
124
  )
121
125
 
122
126
  # Load BASE_PM.md for core framework requirements
123
- base_pm_path = self.framework_path / "src" / "claude_mpm" / "agents" / "BASE_PM.md"
127
+ base_pm_path = (
128
+ self.framework_path / "src" / "claude_mpm" / "agents" / "BASE_PM.md"
129
+ )
124
130
  if base_pm_path.exists():
125
131
  base_pm_content = self.file_loader.try_load_file(
126
132
  base_pm_path, "BASE_PM framework requirements"
@@ -134,7 +140,9 @@ class InstructionLoader:
134
140
  Args:
135
141
  content: Dictionary to update with workflow instructions
136
142
  """
137
- workflow, level = self.file_loader.load_workflow_file(self.current_dir, self.framework_path)
143
+ workflow, level = self.file_loader.load_workflow_file(
144
+ self.current_dir, self.framework_path
145
+ )
138
146
  if workflow:
139
147
  content["workflow_instructions"] = workflow
140
148
  content["workflow_instructions_level"] = level
@@ -145,7 +153,9 @@ class InstructionLoader:
145
153
  Args:
146
154
  content: Dictionary to update with memory instructions
147
155
  """
148
- memory, level = self.file_loader.load_memory_file(self.current_dir, self.framework_path)
156
+ memory, level = self.file_loader.load_memory_file(
157
+ self.current_dir, self.framework_path
158
+ )
149
159
  if memory:
150
160
  content["memory_instructions"] = memory
151
- content["memory_instructions_level"] = level
161
+ content["memory_instructions_level"] = level
@@ -68,7 +68,9 @@ class PackagedLoader:
68
68
  self.logger.warning(f"File {filename} not found in package")
69
69
  return None
70
70
  except Exception as e:
71
- self.logger.error(f"Failed to load {filename} from package with fallback: {e}")
71
+ self.logger.error(
72
+ f"Failed to load {filename} from package with fallback: {e}"
73
+ )
72
74
  return None
73
75
 
74
76
  def extract_metadata_from_content(self, content: str, filename: str) -> None:
@@ -97,7 +99,9 @@ class PackagedLoader:
97
99
  content: Dictionary to update with loaded content
98
100
  """
99
101
  if not files:
100
- self.logger.warning("importlib.resources not available, cannot load packaged framework")
102
+ self.logger.warning(
103
+ "importlib.resources not available, cannot load packaged framework"
104
+ )
101
105
  self.logger.debug(f"files variable is: {files}")
102
106
  # Try alternative import methods
103
107
  try:
@@ -107,7 +111,9 @@ class PackagedLoader:
107
111
  self.load_framework_content_fallback(content, resources)
108
112
  return
109
113
  except ImportError:
110
- self.logger.error("No importlib.resources available, using minimal framework")
114
+ self.logger.error(
115
+ "No importlib.resources available, using minimal framework"
116
+ )
111
117
  return
112
118
 
113
119
  try:
@@ -118,7 +124,9 @@ class PackagedLoader:
118
124
  content["loaded"] = True
119
125
  self.logger.info("Loaded consolidated PM_INSTRUCTIONS.md from package")
120
126
  # Extract and store version/timestamp metadata
121
- self.extract_metadata_from_content(pm_instructions_content, "PM_INSTRUCTIONS.md")
127
+ self.extract_metadata_from_content(
128
+ pm_instructions_content, "PM_INSTRUCTIONS.md"
129
+ )
122
130
  else:
123
131
  # Fall back to legacy INSTRUCTIONS.md
124
132
  instructions_content = self.load_packaged_file("INSTRUCTIONS.md")
@@ -127,7 +135,9 @@ class PackagedLoader:
127
135
  content["loaded"] = True
128
136
  self.logger.warning("Using legacy INSTRUCTIONS.md from package")
129
137
  # Extract and store version/timestamp metadata
130
- self.extract_metadata_from_content(instructions_content, "INSTRUCTIONS.md")
138
+ self.extract_metadata_from_content(
139
+ instructions_content, "INSTRUCTIONS.md"
140
+ )
131
141
 
132
142
  if self.framework_version:
133
143
  content["instructions_version"] = self.framework_version
@@ -155,7 +165,9 @@ class PackagedLoader:
155
165
  except Exception as e:
156
166
  self.logger.error(f"Failed to load packaged framework content: {e}")
157
167
 
158
- def load_framework_content_fallback(self, content: Dict[str, Any], resources) -> None:
168
+ def load_framework_content_fallback(
169
+ self, content: Dict[str, Any], resources
170
+ ) -> None:
159
171
  """Load framework content using importlib.resources fallback.
160
172
 
161
173
  Args:
@@ -164,22 +176,30 @@ class PackagedLoader:
164
176
  """
165
177
  try:
166
178
  # Try new consolidated PM_INSTRUCTIONS.md first
167
- pm_instructions_content = self.load_packaged_file_fallback("PM_INSTRUCTIONS.md", resources)
179
+ pm_instructions_content = self.load_packaged_file_fallback(
180
+ "PM_INSTRUCTIONS.md", resources
181
+ )
168
182
  if pm_instructions_content:
169
183
  content["framework_instructions"] = pm_instructions_content
170
184
  content["loaded"] = True
171
185
  self.logger.info("Loaded consolidated PM_INSTRUCTIONS.md via fallback")
172
186
  # Extract and store version/timestamp metadata
173
- self.extract_metadata_from_content(pm_instructions_content, "PM_INSTRUCTIONS.md")
187
+ self.extract_metadata_from_content(
188
+ pm_instructions_content, "PM_INSTRUCTIONS.md"
189
+ )
174
190
  else:
175
191
  # Fall back to legacy INSTRUCTIONS.md
176
- instructions_content = self.load_packaged_file_fallback("INSTRUCTIONS.md", resources)
192
+ instructions_content = self.load_packaged_file_fallback(
193
+ "INSTRUCTIONS.md", resources
194
+ )
177
195
  if instructions_content:
178
196
  content["framework_instructions"] = instructions_content
179
197
  content["loaded"] = True
180
198
  self.logger.warning("Using legacy INSTRUCTIONS.md via fallback")
181
199
  # Extract and store version/timestamp metadata
182
- self.extract_metadata_from_content(instructions_content, "INSTRUCTIONS.md")
200
+ self.extract_metadata_from_content(
201
+ instructions_content, "INSTRUCTIONS.md"
202
+ )
183
203
 
184
204
  if self.framework_version:
185
205
  content["instructions_version"] = self.framework_version
@@ -193,7 +213,9 @@ class PackagedLoader:
193
213
  content["base_pm_instructions"] = base_pm_content
194
214
 
195
215
  # Load WORKFLOW.md
196
- workflow_content = self.load_packaged_file_fallback("WORKFLOW.md", resources)
216
+ workflow_content = self.load_packaged_file_fallback(
217
+ "WORKFLOW.md", resources
218
+ )
197
219
  if workflow_content:
198
220
  content["workflow_instructions"] = workflow_content
199
221
  content["workflow_instructions_level"] = "system"
@@ -205,4 +227,6 @@ class PackagedLoader:
205
227
  content["memory_instructions_level"] = "system"
206
228
 
207
229
  except Exception as e:
208
- self.logger.error(f"Failed to load packaged framework content with fallback: {e}")
230
+ self.logger.error(
231
+ f"Failed to load packaged framework content with fallback: {e}"
232
+ )
@@ -5,7 +5,7 @@ from .metadata_processor import MetadataProcessor
5
5
  from .template_processor import TemplateProcessor
6
6
 
7
7
  __all__ = [
8
+ "MemoryProcessor",
8
9
  "MetadataProcessor",
9
10
  "TemplateProcessor",
10
- "MemoryProcessor",
11
- ]
11
+ ]
@@ -1,7 +1,7 @@
1
1
  """Memory content processor for framework memory management."""
2
2
 
3
3
  from pathlib import Path
4
- from typing import Any, Dict, Optional, Set
4
+ from typing import Any, Dict, Set
5
5
 
6
6
  from claude_mpm.core.logging_utils import get_logger
7
7
 
@@ -28,7 +28,9 @@ class MemoryProcessor:
28
28
  content = project_memory_file.read_text()
29
29
  memories["actual_memories"] = content
30
30
  memories["memory_source"] = "project"
31
- self.logger.info(f"Loaded PM memories from project: {project_memory_file}")
31
+ self.logger.info(
32
+ f"Loaded PM memories from project: {project_memory_file}"
33
+ )
32
34
  return memories
33
35
  except Exception as e:
34
36
  self.logger.error(f"Failed to load project PM memories: {e}")
@@ -74,10 +76,14 @@ class MemoryProcessor:
74
76
  try:
75
77
  content = memory_file.read_text()
76
78
  agent_memories[agent_name] = content
77
- self.logger.debug(f"Loaded memories for {agent_name} from {memory_file}")
79
+ self.logger.debug(
80
+ f"Loaded memories for {agent_name} from {memory_file}"
81
+ )
78
82
  break # Use first found (project > user)
79
83
  except Exception as e:
80
- self.logger.error(f"Failed to load memories for {agent_name}: {e}")
84
+ self.logger.error(
85
+ f"Failed to load memories for {agent_name}: {e}"
86
+ )
81
87
 
82
88
  return agent_memories
83
89
 
@@ -217,6 +223,8 @@ class MemoryProcessor:
217
223
  self.logger.info(f"Migrated memories from {old_path} to {new_path}")
218
224
  migrated = True
219
225
  except Exception as e:
220
- self.logger.error(f"Failed to migrate memories from {old_path}: {e}")
226
+ self.logger.error(
227
+ f"Failed to migrate memories from {old_path}: {e}"
228
+ )
221
229
 
222
- return migrated
230
+ return migrated
@@ -61,7 +61,9 @@ class MetadataProcessor:
61
61
  # Default values
62
62
  agent_data = {
63
63
  "id": agent_file.stem,
64
- "display_name": agent_file.stem.replace("_", " ").replace("-", " ").title(),
64
+ "display_name": agent_file.stem.replace("_", " ")
65
+ .replace("-", " ")
66
+ .title(),
65
67
  "description": "Specialized agent",
66
68
  "file_path": str(agent_file),
67
69
  "file_mtime": agent_file.stat().st_mtime,
@@ -96,9 +98,7 @@ class MetadataProcessor:
96
98
  self.logger.debug(f"Could not parse metadata from {agent_file}: {e}")
97
99
  return None
98
100
 
99
- def extract_cache_metadata(
100
- self, data: Any, cache_key: str
101
- ) -> Tuple[Any, float]:
101
+ def extract_cache_metadata(self, data: Any, cache_key: str) -> Tuple[Any, float]:
102
102
  """Extract cache metadata for storage.
103
103
 
104
104
  Args:
@@ -143,4 +143,4 @@ class MetadataProcessor:
143
143
  return True
144
144
  except Exception as e:
145
145
  self.logger.debug(f"Cache validation failed: {e}")
146
- return False
146
+ return False
@@ -82,7 +82,9 @@ class TemplateProcessor:
82
82
  Returns:
83
83
  Template data or None if not found
84
84
  """
85
- templates_dir = self.framework_path / "src" / "claude_mpm" / "agents" / "templates"
85
+ templates_dir = (
86
+ self.framework_path / "src" / "claude_mpm" / "agents" / "templates"
87
+ )
86
88
 
87
89
  # Try exact match first
88
90
  template_file = templates_dir / f"{agent_name}.json"
@@ -114,8 +116,8 @@ class TemplateProcessor:
114
116
  {
115
117
  agent_name.replace("-", "_"), # api-qa -> api_qa
116
118
  agent_name.replace("_", "-"), # api_qa -> api-qa
117
- agent_name.replace("-", ""), # api-qa -> apiqa
118
- agent_name.replace("_", ""), # api_qa -> apiqa
119
+ agent_name.replace("-", ""), # api-qa -> apiqa
120
+ agent_name.replace("_", ""), # api_qa -> apiqa
119
121
  agent_name.replace("-agent", ""), # research-agent -> research
120
122
  agent_name.replace("_agent", ""), # research_agent -> research
121
123
  agent_name + "_agent", # research -> research_agent
@@ -123,7 +125,9 @@ class TemplateProcessor:
123
125
  }
124
126
  )
125
127
 
126
- def extract_routing(self, template_data: Dict[str, Any]) -> Optional[Dict[str, Any]]:
128
+ def extract_routing(
129
+ self, template_data: Dict[str, Any]
130
+ ) -> Optional[Dict[str, Any]]:
127
131
  """Extract routing information from template.
128
132
 
129
133
  Args:
@@ -134,7 +138,9 @@ class TemplateProcessor:
134
138
  """
135
139
  return template_data.get("routing")
136
140
 
137
- def extract_memory_routing(self, template_data: Dict[str, Any]) -> Optional[Dict[str, Any]]:
141
+ def extract_memory_routing(
142
+ self, template_data: Dict[str, Any]
143
+ ) -> Optional[Dict[str, Any]]:
138
144
  """Extract memory routing information from template.
139
145
 
140
146
  Args:
@@ -235,4 +241,4 @@ class TemplateProcessor:
235
241
  except Exception as e:
236
242
  self.logger.warning(f"Failed to process template {json_file}: {e}")
237
243
 
238
- return local_agents
244
+ return local_agents